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