date and time created 83/08/05 13:35:19 by sam
[unix-history] / usr / src / old / libdbm / dbm.c
CommitLineData
f531ad45
SL
1#ifndef lint
2static char sccsid[] = "@(#)dbm.c 4.1 (Berkeley) %G%";
3#endif
4
5#include "dbm.h"
6#include <sys/types.h>
7#include <sys/stat.h>
8
9dbminit(file)
10char *file;
11{
12 struct stat statb;
13
14 dbrdonly = 0;
15 strcpy(pagbuf, file);
16 strcat(pagbuf, ".pag");
17 pagf = open(pagbuf, 2);
18 if (pagf < 0) {
19 pagf = open(pagbuf, 0);
20 dbrdonly = 1;
21 }
22
23 strcpy(pagbuf, file);
24 strcat(pagbuf, ".dir");
25 dirf = open(pagbuf, 2);
26 if (dirf < 0) {
27 dirf = open(pagbuf, 0);
28 dbrdonly = 1;
29 }
30 if(pagf < 0 || dirf < 0) {
31 printf("cannot open database %s\n", file);
32 return(-1);
33 }
34 fstat(dirf, &statb);
35 maxbno = statb.st_size*BYTESIZ-1;
36 return(0);
37}
38
39long
40forder(key)
41datum key;
42{
43 long hash;
44
45 hash = calchash(key);
46 for(hmask=0;; hmask=(hmask<<1)+1) {
47 blkno = hash & hmask;
48 bitno = blkno + hmask;
49 if(getbit() == 0)
50 break;
51 }
52 return(blkno);
53}
54
55datum
56fetch(key)
57datum key;
58{
59 register i;
60 datum item;
61
62 dbm_access(calchash(key));
63 for(i=0;; i+=2) {
64 item = makdatum(pagbuf, i);
65 if(item.dptr == NULL)
66 return(item);
67 if(cmpdatum(key, item) == 0) {
68 item = makdatum(pagbuf, i+1);
69 if(item.dptr == NULL)
70 printf("items not in pairs\n");
71 return(item);
72 }
73 }
74}
75
76delete(key)
77datum key;
78{
79 register i;
80 datum item;
81
82 if (dbrdonly)
83 return -1;
84 dbm_access(calchash(key));
85 for(i=0;; i+=2) {
86 item = makdatum(pagbuf, i);
87 if(item.dptr == NULL)
88 return(-1);
89 if(cmpdatum(key, item) == 0) {
90 delitem(pagbuf, i);
91 delitem(pagbuf, i);
92 break;
93 }
94 }
95 lseek(pagf, blkno*PBLKSIZ, 0);
96 write(pagf, pagbuf, PBLKSIZ);
97 return(0);
98}
99
100store(key, dat)
101datum key, dat;
102{
103 register i;
104 datum item;
105 char ovfbuf[PBLKSIZ];
106
107 if (dbrdonly)
108 return -1;
109loop:
110 dbm_access(calchash(key));
111 for(i=0;; i+=2) {
112 item = makdatum(pagbuf, i);
113 if(item.dptr == NULL)
114 break;
115 if(cmpdatum(key, item) == 0) {
116 delitem(pagbuf, i);
117 delitem(pagbuf, i);
118 break;
119 }
120 }
121 i = additem(pagbuf, key);
122 if(i < 0)
123 goto split;
124 if(additem(pagbuf, dat) < 0) {
125 delitem(pagbuf, i);
126 goto split;
127 }
128 lseek(pagf, blkno*PBLKSIZ, 0);
129 write(pagf, pagbuf, PBLKSIZ);
130 return (0);
131
132split:
133 if(key.dsize+dat.dsize+2*sizeof(short) >= PBLKSIZ) {
134 printf("entry too big\n");
135 return (-1);
136 }
137 clrbuf(ovfbuf, PBLKSIZ);
138 for(i=0;;) {
139 item = makdatum(pagbuf, i);
140 if(item.dptr == NULL)
141 break;
142 if(calchash(item) & (hmask+1)) {
143 additem(ovfbuf, item);
144 delitem(pagbuf, i);
145 item = makdatum(pagbuf, i);
146 if(item.dptr == NULL) {
147 printf("split not paired\n");
148 break;
149 }
150 additem(ovfbuf, item);
151 delitem(pagbuf, i);
152 continue;
153 }
154 i += 2;
155 }
156 lseek(pagf, blkno*PBLKSIZ, 0);
157 write(pagf, pagbuf, PBLKSIZ);
158 lseek(pagf, (blkno+hmask+1)*PBLKSIZ, 0);
159 write(pagf, ovfbuf, PBLKSIZ);
160 setbit();
161 goto loop;
162}
163
164datum
165firstkey()
166{
167 return(firsthash(0L));
168}
169
170datum
171nextkey(key)
172datum key;
173{
174 register i;
175 datum item, bitem;
176 long hash;
177 int f;
178
179 hash = calchash(key);
180 dbm_access(hash);
181 f = 1;
182 for(i=0;; i+=2) {
183 item = makdatum(pagbuf, i);
184 if(item.dptr == NULL)
185 break;
186 if(cmpdatum(key, item) <= 0)
187 continue;
188 if(f || cmpdatum(bitem, item) < 0) {
189 bitem = item;
190 f = 0;
191 }
192 }
193 if(f == 0)
194 return(bitem);
195 hash = hashinc(hash);
196 if(hash == 0)
197 return(item);
198 return(firsthash(hash));
199}
200
201datum
202firsthash(hash)
203long hash;
204{
205 register i;
206 datum item, bitem;
207
208loop:
209 dbm_access(hash);
210 bitem = makdatum(pagbuf, 0);
211 for(i=2;; i+=2) {
212 item = makdatum(pagbuf, i);
213 if(item.dptr == NULL)
214 break;
215 if(cmpdatum(bitem, item) < 0)
216 bitem = item;
217 }
218 if(bitem.dptr != NULL)
219 return(bitem);
220 hash = hashinc(hash);
221 if(hash == 0)
222 return(item);
223 goto loop;
224}
225
226dbm_access(hash)
227long hash;
228{
229 static long oldb = -1;
230
231 for(hmask=0;; hmask=(hmask<<1)+1) {
232 blkno = hash & hmask;
233 bitno = blkno + hmask;
234 if(getbit() == 0)
235 break;
236 }
237 if(blkno != oldb) {
238 clrbuf(pagbuf, PBLKSIZ);
239 lseek(pagf, blkno*PBLKSIZ, 0);
240 read(pagf, pagbuf, PBLKSIZ);
241 chkblk(pagbuf);
242 oldb = blkno;
243 }
244}
245
246getbit()
247{
248 long bn;
249 register b, i, n;
250 static oldb = -1;
251
252 if(bitno > maxbno)
253 return(0);
254 n = bitno % BYTESIZ;
255 bn = bitno / BYTESIZ;
256 i = bn % DBLKSIZ;
257 b = bn / DBLKSIZ;
258 if(b != oldb) {
259 clrbuf(dirbuf, DBLKSIZ);
260 lseek(dirf, (long)b*DBLKSIZ, 0);
261 read(dirf, dirbuf, DBLKSIZ);
262 oldb = b;
263 }
264 if(dirbuf[i] & (1<<n))
265 return(1);
266 return(0);
267}
268
269setbit()
270{
271 long bn;
272 register i, n, b;
273
274 if (dbrdonly)
275 return -1;
276 if(bitno > maxbno) {
277 maxbno = bitno;
278 getbit();
279 }
280 n = bitno % BYTESIZ;
281 bn = bitno / BYTESIZ;
282 i = bn % DBLKSIZ;
283 b = bn / DBLKSIZ;
284 dirbuf[i] |= 1<<n;
285 lseek(dirf, (long)b*DBLKSIZ, 0);
286 write(dirf, dirbuf, DBLKSIZ);
287}
288
289clrbuf(cp, n)
290register char *cp;
291register n;
292{
293
294 do
295 *cp++ = 0;
296 while(--n);
297}
298
299datum
300makdatum(buf, n)
301char buf[PBLKSIZ];
302{
303 register short *sp;
304 register t;
305 datum item;
306
307 sp = (short *)buf;
308 if(n < 0 || n >= sp[0])
309 goto null;
310 t = PBLKSIZ;
311 if(n > 0)
312 t = sp[n+1-1];
313 item.dptr = buf+sp[n+1];
314 item.dsize = t - sp[n+1];
315 return(item);
316
317null:
318 item.dptr = NULL;
319 item.dsize = 0;
320 return(item);
321}
322
323cmpdatum(d1, d2)
324datum d1, d2;
325{
326 register n;
327 register char *p1, *p2;
328
329 n = d1.dsize;
330 if(n != d2.dsize)
331 return(n - d2.dsize);
332 if(n == 0)
333 return(0);
334 p1 = d1.dptr;
335 p2 = d2.dptr;
336 do
337 if(*p1++ != *p2++)
338 return(*--p1 - *--p2);
339 while(--n);
340 return(0);
341}
342
343int hitab[16]
344/* ken's
345{
346 055,043,036,054,063,014,004,005,
347 010,064,077,000,035,027,025,071,
348};
349*/
350 = { 61, 57, 53, 49, 45, 41, 37, 33,
351 29, 25, 21, 17, 13, 9, 5, 1,
352};
353long hltab[64]
354 = {
355 06100151277L,06106161736L,06452611562L,05001724107L,
356 02614772546L,04120731531L,04665262210L,07347467531L,
357 06735253126L,06042345173L,03072226605L,01464164730L,
358 03247435524L,07652510057L,01546775256L,05714532133L,
359 06173260402L,07517101630L,02431460343L,01743245566L,
360 00261675137L,02433103631L,03421772437L,04447707466L,
361 04435620103L,03757017115L,03641531772L,06767633246L,
362 02673230344L,00260612216L,04133454451L,00615531516L,
363 06137717526L,02574116560L,02304023373L,07061702261L,
364 05153031405L,05322056705L,07401116734L,06552375715L,
365 06165233473L,05311063631L,01212221723L,01052267235L,
366 06000615237L,01075222665L,06330216006L,04402355630L,
367 01451177262L,02000133436L,06025467062L,07121076461L,
368 03123433522L,01010635225L,01716177066L,05161746527L,
369 01736635071L,06243505026L,03637211610L,01756474365L,
370 04723077174L,03642763134L,05750130273L,03655541561L,
371};
372
373long
374hashinc(hash)
375long hash;
376{
377 long bit;
378
379 hash &= hmask;
380 bit = hmask+1;
381 for(;;) {
382 bit >>= 1;
383 if(bit == 0)
384 return(0L);
385 if((hash&bit) == 0)
386 return(hash|bit);
387 hash &= ~bit;
388 }
389}
390
391long
392calchash(item)
393datum item;
394{
395 register i, j, f;
396 long hashl;
397 int hashi;
398
399 hashl = 0;
400 hashi = 0;
401 for(i=0; i<item.dsize; i++) {
402 f = item.dptr[i];
403 for(j=0; j<BYTESIZ; j+=4) {
404 hashi += hitab[f&017];
405 hashl += hltab[hashi&63];
406 f >>= 4;
407 }
408 }
409 return(hashl);
410}
411
412delitem(buf, n)
413char buf[PBLKSIZ];
414{
415 register short *sp;
416 register i1, i2, i3;
417
418 sp = (short *)buf;
419 if(n < 0 || n >= sp[0])
420 goto bad;
421 i1 = sp[n+1];
422 i2 = PBLKSIZ;
423 if(n > 0)
424 i2 = sp[n+1-1];
425 i3 = sp[sp[0]+1-1];
426 if(i2 > i1)
427 while(i1 > i3) {
428 i1--;
429 i2--;
430 buf[i2] = buf[i1];
431 buf[i1] = 0;
432 }
433 i2 -= i1;
434 for(i1=n+1; i1<sp[0]; i1++)
435 sp[i1+1-1] = sp[i1+1] + i2;
436 sp[0]--;
437 sp[sp[0]+1] = 0;
438 return;
439
440bad:
441 printf("bad delitem\n");
442 abort();
443}
444
445additem(buf, item)
446char buf[PBLKSIZ];
447datum item;
448{
449 register short *sp;
450 register i1, i2;
451
452 sp = (short *)buf;
453 i1 = PBLKSIZ;
454 if(sp[0] > 0)
455 i1 = sp[sp[0]+1-1];
456 i1 -= item.dsize;
457 i2 = (sp[0]+2) * sizeof(short);
458 if(i1 <= i2)
459 return(-1);
460 sp[sp[0]+1] = i1;
461 for(i2=0; i2<item.dsize; i2++) {
462 buf[i1] = item.dptr[i2];
463 i1++;
464 }
465 sp[0]++;
466 return(sp[0]-1);
467}
468
469chkblk(buf)
470char buf[PBLKSIZ];
471{
472 register short *sp;
473 register t, i;
474
475 sp = (short *)buf;
476 t = PBLKSIZ;
477 for(i=0; i<sp[0]; i++) {
478 if(sp[i+1] > t)
479 goto bad;
480 t = sp[i+1];
481 }
482 if(t < (sp[0]+1)*sizeof(short))
483 goto bad;
484 return;
485
486bad:
487 printf("bad block\n");
488 abort();
489 clrbuf(buf, PBLKSIZ);
490}