#include #include #include #include #include #include "ndbhf.h" static Ndb* doopen(char*); static void hffree(Ndb*); static char *deffile = "/lib/ndb/local"; /* * the database entry in 'file' indicates the list of files * that makeup the database. Open each one and search in * the same order. */ Ndb* ndbopen(char *file) { Ndb *db, *first, *last; Ndbs s; Ndbtuple *t, *nt; if(file == nil && (file = getenv("NDBFILE")) == nil) file = deffile; db = doopen(file); if(db == 0) return 0; first = last = db; t = ndbsearch(db, &s, "database", ""); Bseek(&db->b, 0, 0); if(t == 0) return db; for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, "file") != 0) continue; if(strcmp(nt->val, file) == 0){ /* default file can be reordered in the list */ if(first->next == 0) continue; if(strcmp(first->file, file) == 0){ db = first; first = first->next; last->next = db; db->next = 0; last = db; } continue; } db = doopen(nt->val); if(db == 0) continue; last->next = db; last = db; } ndbfree(t); return first; } /* * open a single file */ static Ndb* doopen(char *file) { Ndb *db; db = (Ndb*)malloc(sizeof(Ndb)); if(db == 0) return 0; memset(db, 0, sizeof(Ndb)); strncpy(db->file, file, sizeof(db->file)-1); if(ndbreopen(db) < 0){ free(db); return 0; } return db; } /* * dump any cached information, forget the hash tables, and reopen a single file */ int ndbreopen(Ndb *db) { int fd; Dir *d; /* forget what we know about the open files */ if(db->mtime){ _ndbcacheflush(db); hffree(db); close(Bfildes(&db->b)); Bterm(&db->b); db->mtime = 0; } /* try the open again */ fd = open(db->file, OREAD); if(fd < 0) return -1; d = dirfstat(fd); if(d == nil){ close(fd); return -1; } db->qid = d->qid; db->mtime = d->mtime; db->length = d->length; Binits(&db->b, fd, OREAD, db->buf, sizeof(db->buf)); free(d); return 0; } /* * close the database files */ void ndbclose(Ndb *db) { Ndb *nextdb; for(; db; db = nextdb){ nextdb = db->next; _ndbcacheflush(db); hffree(db); close(Bfildes(&db->b)); Bterm(&db->b); free(db); } } /* * free the hash files belonging to a db */ static void hffree(Ndb *db) { Ndbhf *hf, *next; for(hf = db->hf; hf; hf = next){ next = hf->next; close(hf->fd); free(hf); } db->hf = 0; } /* * return true if any part of the database has changed */ int ndbchanged(Ndb *db) { Ndb *ndb; Dir *d; for(ndb = db; ndb != nil; ndb = ndb->next){ d = dirfstat(Bfildes(&ndb->b)); if(d == nil) continue; if(ndb->qid.path != d->qid.path || ndb->qid.vers != d->qid.vers){ free(d); return 1; } free(d); } return 0; }