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