ndbopen.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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. return first;
  54. }
  55. /*
  56. * open a single file
  57. */
  58. static Ndb*
  59. doopen(char *file)
  60. {
  61. Ndb *db;
  62. db = (Ndb*)malloc(sizeof(Ndb));
  63. if(db == 0)
  64. return 0;
  65. memset(db, 0, sizeof(Ndb));
  66. strncpy(db->file, file, sizeof(db->file)-1);
  67. if(ndbreopen(db) < 0){
  68. free(db);
  69. return 0;
  70. }
  71. return db;
  72. }
  73. /*
  74. * dump any cached information, forget the hash tables, and reopen a single file
  75. */
  76. int
  77. ndbreopen(Ndb *db)
  78. {
  79. int fd;
  80. Dir *d;
  81. /* forget what we know about the open files */
  82. if(db->mtime){
  83. _ndbcacheflush(db);
  84. hffree(db);
  85. close(Bfildes(&db->b));
  86. Bterm(&db->b);
  87. db->mtime = 0;
  88. }
  89. /* try the open again */
  90. fd = open(db->file, OREAD);
  91. if(fd < 0)
  92. return -1;
  93. d = dirfstat(fd);
  94. if(d == nil){
  95. close(fd);
  96. return -1;
  97. }
  98. db->qid = d->qid;
  99. db->mtime = d->mtime;
  100. db->length = d->length;
  101. Binits(&db->b, fd, OREAD, db->buf, sizeof(db->buf));
  102. free(d);
  103. return 0;
  104. }
  105. /*
  106. * close the database files
  107. */
  108. void
  109. ndbclose(Ndb *db)
  110. {
  111. Ndb *nextdb;
  112. for(; db; db = nextdb){
  113. nextdb = db->next;
  114. _ndbcacheflush(db);
  115. hffree(db);
  116. close(Bfildes(&db->b));
  117. Bterm(&db->b);
  118. free(db);
  119. }
  120. }
  121. /*
  122. * free the hash files belonging to a db
  123. */
  124. static void
  125. hffree(Ndb *db)
  126. {
  127. Ndbhf *hf, *next;
  128. for(hf = db->hf; hf; hf = next){
  129. next = hf->next;
  130. close(hf->fd);
  131. free(hf);
  132. }
  133. db->hf = 0;
  134. }
  135. /*
  136. * return true if any part of the database has changed
  137. */
  138. int
  139. ndbchanged(Ndb *db)
  140. {
  141. Ndb *ndb;
  142. Dir *d;
  143. for(ndb = db; ndb != nil; ndb = ndb->next){
  144. d = dirfstat(Bfildes(&db->b));
  145. if(d == nil)
  146. continue;
  147. if(ndb->qid.path != d->qid.path
  148. || ndb->qid.vers != d->qid.vers){
  149. free(d);
  150. return 1;
  151. }
  152. free(d);
  153. }
  154. return 0;
  155. }