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