]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libndb/ndbopen.c
blit: fix mkfile
[plan9front.git] / sys / src / libndb / ndbopen.c
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         ndbfree(t);
58         return first;
59 }
60
61 /*
62  *  open a single file
63  */
64 static Ndb*
65 doopen(char *file)
66 {
67         Ndb *db;
68
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);
74
75         if(ndbreopen(db) < 0){
76                 free(db);
77                 return 0;
78         }
79
80         return db;
81 }
82
83 /*
84  *  dump any cached information, forget the hash tables, and reopen a single file
85  */
86 int
87 ndbreopen(Ndb *db)
88 {
89         int fd;
90         Dir *d;
91
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         }
100
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         }
110
111         /* no hashfile for /net/ndb (avoids deadlock in cs) */
112         if(d->type == 'I')
113                 db->nohash = 1;
114
115         db->qid = d->qid;
116         db->mtime = d->mtime;
117         db->length = d->length;
118         Binits(&db->b, fd, OREAD, db->buf, sizeof(db->buf));
119         free(d);
120         return 0;
121 }
122
123 /*
124  *  close the database files
125  */
126 void
127 ndbclose(Ndb *db)
128 {
129         Ndb *nextdb;
130
131         for(; db; db = nextdb){
132                 nextdb = db->next;
133                 _ndbcacheflush(db);
134                 hffree(db);
135                 close(Bfildes(&db->b));
136                 Bterm(&db->b);
137                 free(db);
138         }
139 }
140
141 /*
142  *  free the hash files belonging to a db
143  */
144 static void
145 hffree(Ndb *db)
146 {
147         Ndbhf *hf, *next;
148
149         for(hf = db->hf; hf; hf = next){
150                 next = hf->next;
151                 close(hf->fd);
152                 free(hf);
153         }
154         db->hf = 0;
155 }
156
157 /*
158  *  return true if any part of the database has changed
159  */
160 int
161 ndbchanged(Ndb *db)
162 {
163         Ndb *ndb;
164         Dir *d;
165
166         for(ndb = db; ndb != nil; ndb = ndb->next){
167                 d = dirfstat(Bfildes(&ndb->b));
168                 if(d == nil)
169                         continue;
170                 if(ndb->qid.path != d->qid.path
171                 || ndb->qid.vers != d->qid.vers){
172                         free(d);
173                         return 1;
174                 }
175                 free(d);
176         }
177         return 0;
178 }