ndbopen.c 3.1 KB

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