xref: /plan9-contrib/sys/src/libndb/ndbopen.c (revision d46c239f8612929b7dbade67d0d071633df3a15d)
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