Add ndblib and iplib
[akaros.git] / user / ndblib / ndbopen.c
1 /* 
2  * This file is part of the UCB release of Plan 9. It is subject to the license
3  * terms in the LICENSE file found in the top-level directory of this
4  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
5  * part of the UCB release of Plan 9, including this file, may be copied,
6  * modified, propagated, or distributed except according to the terms contained
7  * in the LICENSE file.
8  */
9 #include <stdlib.h>
10
11 #include <stdio.h>
12 #include <parlib.h>
13 #include <unistd.h>
14 #include <signal.h>
15 #include <fcntl.h>
16 #include <libip.h>
17 #include <dir.h>
18 #include <ndb.h>
19 #include "ndbhf.h"
20
21 static struct ndb*      doopen(char*);
22 static void     hffree(struct ndb*);
23
24 static char *deffile = "/lib/ndb/local";
25
26 /*
27  *  the database entry in 'file' indicates the list of files
28  *  that makeup the database.  Open each one and search in
29  *  the same order.
30  */
31 struct ndb*
32 ndbopen(char *file)
33 {
34         struct ndb *db, *first, *last;
35         struct ndbs s;
36         struct ndbtuple *t, *nt;
37
38         if(file == 0)
39                 file = deffile;
40         db = doopen(file);
41         if(db == 0)
42                 return 0;
43         first = last = db;
44         t = ndbsearch(db, &s, "database", "");
45         fseek(db->b, 0, 0);
46         if(t == 0)
47                 return db;
48         for(nt = t; nt; nt = nt->entry){
49                 if(strcmp(nt->attr, "file") != 0)
50                         continue;
51                 if(strcmp(nt->val, file) == 0){
52                         /* default file can be reordered in the list */
53                         if(first->next == 0)
54                                 continue;
55                         if(strcmp(first->file, file) == 0){
56                                 db = first;
57                                 first = first->next;
58                                 last->next = db;
59                                 db->next = 0;
60                                 last = db;
61                         }
62                         continue;
63                 }
64                 db = doopen(nt->val);
65                 if(db == 0)
66                         continue;
67                 last->next = db;
68                 last = db;
69         }
70         ndbfree(t);
71         return first;
72 }
73
74 /*
75  *  open a single file
76  */
77 static struct ndb*
78 doopen(char *file)
79 {
80         struct ndb *db;
81
82         db = (struct ndb*)calloc(sizeof(struct ndb), 1);
83         if(db == 0)
84                 return 0;
85         memset(db, 0, sizeof(struct ndb));
86         strncpy(db->file, file, sizeof(db->file)-1);
87
88         if(ndbreopen(db) < 0){
89                 free(db);
90                 return 0;
91         }
92
93         return db;
94 }
95
96 /*
97  *  dump any cached information, forget the hash tables, and reopen a single file
98  */
99 int
100 ndbreopen(struct ndb *db)
101 {
102         int fd;
103         struct dir *d;
104
105         /* forget what we know about the open files */
106         if(db->isopen){
107                 _ndbcacheflush(db);
108                 hffree(db);
109                 fclose(db->b);
110                 db->mtime = 0;
111                 db->isopen = 0;
112         }
113
114         /* try the open again */
115         db->b = fopen(db->file, "r");
116         if(! db->b)
117                 return -1;
118 #if 0
119         d = dirfstat(fd);
120         if(d == NULL){
121                 close(fd);
122                 return -1;
123         }
124
125         db->qid = d->qid;
126         db->mtime = d->mtime;
127         db->length = d->length;
128         free(d);
129 #endif
130         db->isopen = 1;
131         return 0;
132 }
133
134 /*
135  *  close the database files
136  */
137 void
138 ndbclose(struct ndb *db)
139 {
140         struct ndb *nextdb;
141
142         for(; db; db = nextdb){
143                 nextdb = db->next;
144                 _ndbcacheflush(db);
145                 hffree(db);
146                 fclose(db->b);
147                 free(db);
148         }
149 }
150
151 /*
152  *  free the hash files belonging to a db
153  */
154 static void
155 hffree(struct ndb *db)
156 {
157         struct ndbhf *hf, *next;
158
159         for(hf = db->hf; hf; hf = next){
160                 next = hf->next;
161                 close(hf->fd);
162                 free(hf);
163         }
164         db->hf = 0;
165 }
166
167 /*
168  *  return true if any part of the database has changed
169  */
170 int
171 ndbchanged(struct ndb *db)
172 {
173         return 1;
174 #if 0
175         struct ndb *ndb;
176         struct dir *d;
177
178 /* FIX ME */
179         for(ndb = db; ndb != NULL; ndb = ndb->next){
180                 d = dirfstat(Bfildes(&ndb->b));
181                 if(d == NULL)
182                         continue;
183                 if(ndb->qid.path != d->qid.path
184                 || ndb->qid.vers != d->qid.vers){
185                         free(d);
186                         return 1;
187                 }
188                 free(d);
189         }
190         return 0;
191 #endif
192 }