plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

ndbopen.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 }