URI:
       tndbopen.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tndbopen.c (2981B)
       ---
            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*, char*);
            9 static void        hffree(Ndb*);
           10 
           11 static char *deffile = "#9/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 = unsharp(deffile);
           27         db = doopen(file, nil);
           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, file);
           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, char *rel)
           66 {
           67         char *p;
           68         Ndb *db;
           69 
           70         db = (Ndb*)malloc(sizeof(Ndb));
           71         if(db == 0)
           72                 return 0;
           73 
           74         memset(db, 0, sizeof(Ndb));
           75         /*
           76          * Rooted paths are taken as is.
           77          * Unrooted paths are taken relative to db we opened.
           78          */
           79         if(file[0]!='/' && rel && (p=strrchr(rel, '/'))!=nil)
           80                 snprint(db->file, sizeof(db->file), "%.*s/%s",
           81                         utfnlen(rel, p-rel), rel, file);
           82         else
           83                 strncpy(db->file, file, sizeof(db->file)-1);
           84 
           85         if(ndbreopen(db) < 0){
           86                 free(db);
           87                 return 0;
           88         }
           89 
           90         return db;
           91 }
           92 
           93 /*
           94  *  dump any cached information, forget the hash tables, and reopen a single file
           95  */
           96 int
           97 ndbreopen(Ndb *db)
           98 {
           99         int fd;
          100         Dir *d;
          101 
          102         /* forget what we know about the open files */
          103         if(db->mtime){
          104                 _ndbcacheflush(db);
          105                 hffree(db);
          106                 close(Bfildes(&db->b));
          107                 Bterm(&db->b);
          108                 db->mtime = 0;
          109         }
          110 
          111         /* try the open again */
          112         fd = open(db->file, OREAD);
          113         if(fd < 0)
          114                 return -1;
          115         d = dirfstat(fd);
          116         if(d == nil){
          117                 close(fd);
          118                 return -1;
          119         }
          120 
          121         db->qid = d->qid;
          122         db->mtime = d->mtime;
          123         db->length = d->length;
          124         Binit(&db->b, fd, OREAD);
          125         free(d);
          126         return 0;
          127 }
          128 
          129 /*
          130  *  close the database files
          131  */
          132 void
          133 ndbclose(Ndb *db)
          134 {
          135         Ndb *nextdb;
          136 
          137         for(; db; db = nextdb){
          138                 nextdb = db->next;
          139                 _ndbcacheflush(db);
          140                 hffree(db);
          141                 close(Bfildes(&db->b));
          142                 Bterm(&db->b);
          143                 free(db);
          144         }
          145 }
          146 
          147 /*
          148  *  free the hash files belonging to a db
          149  */
          150 static void
          151 hffree(Ndb *db)
          152 {
          153         Ndbhf *hf, *next;
          154 
          155         for(hf = db->hf; hf; hf = next){
          156                 next = hf->next;
          157                 close(hf->fd);
          158                 free(hf);
          159         }
          160         db->hf = 0;
          161 }
          162 
          163 /*
          164  *  return true if any part of the database has changed
          165  */
          166 int
          167 ndbchanged(Ndb *db)
          168 {
          169         Ndb *ndb;
          170         Dir *d;
          171 
          172         for(ndb = db; ndb != nil; ndb = ndb->next){
          173                 d = dirfstat(Bfildes(&db->b));
          174                 if(d == nil)
          175                         continue;
          176                 if(ndb->qid.path != d->qid.path
          177                 || ndb->qid.vers != d->qid.vers){
          178                         free(d);
          179                         return 1;
          180                 }
          181                 free(d);
          182         }
          183         return 0;
          184 }