ndbopen.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include <ctype.h>
  5. #include <ndb.h>
  6. #include "ndbhf.h"
  7. static Ndb* doopen(char*);
  8. static void hffree(Ndb*);
  9. static char *deffile = "/lib/ndb/local";
  10. /*
  11. * the database entry in 'file' indicates the list of files
  12. * that makeup the database. Open each one and search in
  13. * the same order.
  14. */
  15. Ndb*
  16. ndbopen(char *file)
  17. {
  18. Ndb *db, *first, *last;
  19. Ndbs s;
  20. Ndbtuple *t, *nt;
  21. if(file == 0)
  22. file = deffile;
  23. db = doopen(file);
  24. if(db == 0)
  25. return 0;
  26. first = last = db;
  27. t = ndbsearch(db, &s, "database", "");
  28. Bseek(&db->b, 0, 0);
  29. if(t == 0)
  30. return db;
  31. for(nt = t; nt; nt = nt->entry){
  32. if(strcmp(nt->attr, "file") != 0)
  33. continue;
  34. if(strcmp(nt->val, file) == 0){
  35. /* default file can be reordered in the list */
  36. if(first->next == 0)
  37. continue;
  38. if(strcmp(first->file, file) == 0){
  39. db = first;
  40. first = first->next;
  41. last->next = db;
  42. db->next = 0;
  43. last = db;
  44. }
  45. continue;
  46. }
  47. db = doopen(nt->val);
  48. if(db == 0)
  49. continue;
  50. last->next = db;
  51. last = db;
  52. }
  53. ndbfree(t);
  54. return first;
  55. }
  56. /*
  57. * open a single file
  58. */
  59. static Ndb*
  60. doopen(char *file)
  61. {
  62. Ndb *db;
  63. db = (Ndb*)malloc(sizeof(Ndb));
  64. if(db == 0)
  65. return 0;
  66. memset(db, 0, sizeof(Ndb));
  67. strncpy(db->file, file, sizeof(db->file)-1);
  68. if(ndbreopen(db) < 0){
  69. free(db);
  70. return 0;
  71. }
  72. return db;
  73. }
  74. /*
  75. * dump any cached information, forget the hash tables, and reopen a single file
  76. */
  77. int
  78. ndbreopen(Ndb *db)
  79. {
  80. int fd;
  81. Dir *d;
  82. /* forget what we know about the open files */
  83. if(db->mtime){
  84. _ndbcacheflush(db);
  85. hffree(db);
  86. close(Bfildes(&db->b));
  87. Bterm(&db->b);
  88. db->mtime = 0;
  89. }
  90. /* try the open again */
  91. fd = open(db->file, OREAD);
  92. if(fd < 0)
  93. return -1;
  94. d = dirfstat(fd);
  95. if(d == nil){
  96. close(fd);
  97. return -1;
  98. }
  99. db->qid = d->qid;
  100. db->mtime = d->mtime;
  101. db->length = d->length;
  102. Binits(&db->b, fd, OREAD, db->buf, sizeof(db->buf));
  103. free(d);
  104. return 0;
  105. }
  106. /*
  107. * close the database files
  108. */
  109. void
  110. ndbclose(Ndb *db)
  111. {
  112. Ndb *nextdb;
  113. for(; db; db = nextdb){
  114. nextdb = db->next;
  115. _ndbcacheflush(db);
  116. hffree(db);
  117. close(Bfildes(&db->b));
  118. Bterm(&db->b);
  119. free(db);
  120. }
  121. }
  122. /*
  123. * free the hash files belonging to a db
  124. */
  125. static void
  126. hffree(Ndb *db)
  127. {
  128. Ndbhf *hf, *next;
  129. for(hf = db->hf; hf; hf = next){
  130. next = hf->next;
  131. close(hf->fd);
  132. free(hf);
  133. }
  134. db->hf = 0;
  135. }
  136. /*
  137. * return true if any part of the database has changed
  138. */
  139. int
  140. ndbchanged(Ndb *db)
  141. {
  142. Ndb *ndb;
  143. Dir *d;
  144. for(ndb = db; ndb != nil; ndb = ndb->next){
  145. d = dirfstat(Bfildes(&db->b));
  146. if(d == nil)
  147. continue;
  148. if(ndb->qid.path != d->qid.path
  149. || ndb->qid.vers != d->qid.vers){
  150. free(d);
  151. return 1;
  152. }
  153. free(d);
  154. }
  155. return 0;
  156. }