Blob
1 #include <u.h>2 #include <libc.h>3 #include <bio.h>4 #include <ctype.h>5 #include <ndb.h>6 #include "ndbhf.h"8 static Ndb* doopen(char*);9 static void hffree(Ndb*);11 static char *deffile = "/lib/ndb/local";13 /*14 * the database entry in 'file' indicates the list of files15 * that makeup the database. Open each one and search in16 * the same order.17 */18 Ndb*19 ndbopen(char *file)20 {21 Ndb *db, *first, *last;22 Ndbs s;23 Ndbtuple *t, *nt;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 }61 /*62 * open a single file63 */64 static Ndb*65 doopen(char *file)66 {67 Ndb *db;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);75 if(ndbreopen(db) < 0){76 free(db);77 return 0;78 }80 return db;81 }83 /*84 * dump any cached information, forget the hash tables, and reopen a single file85 */86 int87 ndbreopen(Ndb *db)88 {89 int fd;90 Dir *d;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 }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 }111 db->qid = d->qid;112 db->mtime = d->mtime;113 db->length = d->length;114 Binit(&db->b, fd, OREAD);115 free(d);116 return 0;117 }119 /*120 * close the database files121 */122 void123 ndbclose(Ndb *db)124 {125 Ndb *nextdb;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 }137 /*138 * free the hash files belonging to a db139 */140 static void141 hffree(Ndb *db)142 {143 Ndbhf *hf, *next;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 }153 /*154 * return true if any part of the database has changed155 */156 int157 ndbchanged(Ndb *db)158 {159 Ndb *ndb;160 Dir *d;162 for(ndb = db; ndb != nil; ndb = ndb->next){163 d = dirfstat(Bfildes(&db->b));164 if(d == nil)165 continue;166 if(ndb->qid.path != d->qid.path167 || ndb->qid.vers != d->qid.vers){168 free(d);169 return 1;170 }171 free(d);172 }173 return 0;174 }