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