home *** CD-ROM | disk | FTP | other *** search
- #include "dbm.h"
- #include <sys/types.h>
- #include <sys/stat.h>
-
- dbminit(file)
- char *file;
- {
- struct stat statb;
-
- strcpy(pagbuf, file);
- strcat(pagbuf, ".pag");
- pagf = open(pagbuf, 2);
-
- strcpy(pagbuf, file);
- strcat(pagbuf, ".dir");
- dirf = open(pagbuf, 2);
- if(pagf < 0 || dirf < 0) {
- printf("cannot open database %s\n", file);
- return(-1);
- }
- fstat(dirf, &statb);
- maxbno = statb.st_size*BYTESIZ-1;
- return(0);
- }
-
- long
- forder(key)
- datum key;
- {
- long hash;
-
- hash = calchash(key);
- for(hmask=0;; hmask=(hmask<<1)+1) {
- blkno = hash & hmask;
- bitno = blkno + hmask;
- if(getbit() == 0)
- break;
- }
- return(blkno);
- }
-
- datum
- fetch(key)
- datum key;
- {
- register i;
- datum item;
-
- dbm_access(calchash(key));
- for(i=0;; i+=2) {
- item = makdatum(pagbuf, i);
- if(item.dptr == NULL)
- return(item);
- if(cmpdatum(key, item) == 0) {
- item = makdatum(pagbuf, i+1);
- if(item.dptr == NULL)
- printf("items not in pairs\n");
- return(item);
- }
- }
- }
-
- delete(key)
- datum key;
- {
- register i;
- datum item;
-
- dbm_access(calchash(key));
- for(i=0;; i+=2) {
- item = makdatum(pagbuf, i);
- if(item.dptr == NULL)
- return(-1);
- if(cmpdatum(key, item) == 0) {
- delitem(pagbuf, i);
- delitem(pagbuf, i);
- break;
- }
- }
- lseek(pagf, blkno*PBLKSIZ, 0);
- write(pagf, pagbuf, PBLKSIZ);
- return(0);
- }
-
- store(key, dat)
- datum key, dat;
- {
- register i;
- datum item;
- char ovfbuf[PBLKSIZ];
-
- loop:
- dbm_access(calchash(key));
- for(i=0;; i+=2) {
- item = makdatum(pagbuf, i);
- if(item.dptr == NULL)
- break;
- if(cmpdatum(key, item) == 0) {
- delitem(pagbuf, i);
- delitem(pagbuf, i);
- break;
- }
- }
- i = additem(pagbuf, key);
- if(i < 0)
- goto split;
- if(additem(pagbuf, dat) < 0) {
- delitem(pagbuf, i);
- goto split;
- }
- lseek(pagf, blkno*PBLKSIZ, 0);
- write(pagf, pagbuf, PBLKSIZ);
- return;
-
- split:
- if(key.dsize+dat.dsize+2*sizeof(short) >= PBLKSIZ) {
- printf("entry too big\n");
- return;
- }
- clrbuf(ovfbuf, PBLKSIZ);
- for(i=0;;) {
- item = makdatum(pagbuf, i);
- if(item.dptr == NULL)
- break;
- if(calchash(item) & (hmask+1)) {
- additem(ovfbuf, item);
- delitem(pagbuf, i);
- item = makdatum(pagbuf, i);
- if(item.dptr == NULL) {
- printf("split not paired\n");
- break;
- }
- additem(ovfbuf, item);
- delitem(pagbuf, i);
- continue;
- }
- i += 2;
- }
- lseek(pagf, blkno*PBLKSIZ, 0);
- write(pagf, pagbuf, PBLKSIZ);
- lseek(pagf, (blkno+hmask+1)*PBLKSIZ, 0);
- write(pagf, ovfbuf, PBLKSIZ);
- setbit();
- goto loop;
- }
-
- datum
- firstkey()
- {
- return(firsthash(0L));
- }
-
- datum
- nextkey(key)
- datum key;
- {
- register i;
- datum item, bitem;
- long hash;
- int f;
-
- hash = calchash(key);
- dbm_access(hash);
- f = 1;
- for(i=0;; i+=2) {
- item = makdatum(pagbuf, i);
- if(item.dptr == NULL)
- break;
- if(cmpdatum(key, item) <= 0)
- continue;
- if(f || cmpdatum(bitem, item) < 0) {
- bitem = item;
- f = 0;
- }
- }
- if(f == 0)
- return(bitem);
- hash = hashinc(hash);
- if(hash == 0)
- return(item);
- return(firsthash(hash));
- }
-
- datum
- firsthash(hash)
- long hash;
- {
- register i;
- datum item, bitem;
-
- loop:
- dbm_access(hash);
- bitem = makdatum(pagbuf, 0);
- for(i=2;; i+=2) {
- item = makdatum(pagbuf, i);
- if(item.dptr == NULL)
- break;
- if(cmpdatum(bitem, item) < 0)
- bitem = item;
- }
- if(bitem.dptr != NULL)
- return(bitem);
- hash = hashinc(hash);
- if(hash == 0)
- return(item);
- goto loop;
- }
-
- dbm_access(hash)
- long hash;
- {
- static long oldb = -1;
-
- for(hmask=0;; hmask=(hmask<<1)+1) {
- blkno = hash & hmask;
- bitno = blkno + hmask;
- if(getbit() == 0)
- break;
- }
- if(blkno != oldb) {
- clrbuf(pagbuf, PBLKSIZ);
- lseek(pagf, blkno*PBLKSIZ, 0);
- read(pagf, pagbuf, PBLKSIZ);
- chkblk(pagbuf);
- oldb = blkno;
- }
- }
-
- getbit()
- {
- long bn;
- register b, i, n;
- static oldb = -1;
-
- if(bitno > maxbno)
- return(0);
- n = bitno % BYTESIZ;
- bn = bitno / BYTESIZ;
- i = bn % DBLKSIZ;
- b = bn / DBLKSIZ;
- if(b != oldb) {
- clrbuf(dirbuf, DBLKSIZ);
- lseek(dirf, (long)b*DBLKSIZ, 0);
- read(dirf, dirbuf, DBLKSIZ);
- oldb = b;
- }
- if(dirbuf[i] & (1<<n))
- return(1);
- return(0);
- }
-
- setbit()
- {
- long bn;
- register i, n, b;
-
- if(bitno > maxbno) {
- maxbno = bitno;
- getbit();
- }
- n = bitno % BYTESIZ;
- bn = bitno / BYTESIZ;
- i = bn % DBLKSIZ;
- b = bn / DBLKSIZ;
- dirbuf[i] |= 1<<n;
- lseek(dirf, (long)b*DBLKSIZ, 0);
- write(dirf, dirbuf, DBLKSIZ);
- }
-
- clrbuf(cp, n)
- register char *cp;
- register n;
- {
-
- do
- *cp++ = 0;
- while(--n);
- }
-
- datum
- makdatum(buf, n)
- char buf[PBLKSIZ];
- {
- register short *sp;
- register t;
- datum item;
-
- sp = (short *)buf;
- if(n < 0 || n >= sp[0])
- goto null;
- t = PBLKSIZ;
- if(n > 0)
- t = sp[n+1-1];
- item.dptr = buf+sp[n+1];
- item.dsize = t - sp[n+1];
- return(item);
-
- null:
- item.dptr = NULL;
- item.dsize = 0;
- return(item);
- }
-
- cmpdatum(d1, d2)
- datum d1, d2;
- {
- register n;
- register char *p1, *p2;
-
- n = d1.dsize;
- if(n != d2.dsize)
- return(n - d2.dsize);
- if(n == 0)
- return(0);
- p1 = d1.dptr;
- p2 = d2.dptr;
- do
- if(*p1++ != *p2++)
- return(*--p1 - *--p2);
- while(--n);
- return(0);
- }
-
- int hitab[16] =
- { 61, 57, 53, 49, 45, 41, 37, 33,
- 29, 25, 21, 17, 13, 9, 5, 1,
- };
- long hltab[64] =
- {
- 06100151277L,06106161736L,06452611562L,05001724107L,
- 02614772546L,04120731531L,04665262210L,07347467531L,
- 06735253126L,06042345173L,03072226605L,01464164730L,
- 03247435524L,07652510057L,01546775256L,05714532133L,
- 06173260402L,07517101630L,02431460343L,01743245566L,
- 00261675137L,02433103631L,03421772437L,04447707466L,
- 04435620103L,03757017115L,03641531772L,06767633246L,
- 02673230344L,00260612216L,04133454451L,00615531516L,
- 06137717526L,02574116560L,02304023373L,07061702261L,
- 05153031405L,05322056705L,07401116734L,06552375715L,
- 06165233473L,05311063631L,01212221723L,01052267235L,
- 06000615237L,01075222665L,06330216006L,04402355630L,
- 01451177262L,02000133436L,06025467062L,07121076461L,
- 03123433522L,01010635225L,01716177066L,05161746527L,
- 01736635071L,06243505026L,03637211610L,01756474365L,
- 04723077174L,03642763134L,05750130273L,03655541561L,
- };
-
- long
- hashinc(hash)
- long hash;
- {
- long bit;
-
- hash &= hmask;
- bit = hmask+1;
- for(;;) {
- bit >>= 1;
- if(bit == 0)
- return(0L);
- if((hash&bit) == 0)
- return(hash|bit);
- hash &= ~bit;
- }
- }
-
- long
- calchash(item)
- datum item;
- {
- register i, j, f;
- long hashl;
- int hashi;
-
- hashl = 0;
- hashi = 0;
- for(i=0; i<item.dsize; i++) {
- f = item.dptr[i];
- for(j=0; j<BYTESIZ; j+=4) {
- hashi += hitab[f&017];
- hashl += hltab[hashi&077];
- f >>= 4;
- }
- }
- return(hashl);
- }
-
- delitem(buf, n)
- char buf[PBLKSIZ];
- {
- register short *sp;
- register i1, i2, i3;
-
- sp = (short *)buf;
- if(n < 0 || n >= sp[0])
- goto bad;
- i1 = sp[n+1];
- i2 = PBLKSIZ;
- if(n > 0)
- i2 = sp[n+1-1];
- i3 = sp[sp[0]+1-1];
- if(i2 > i1)
- while(i1 > i3) {
- i1--;
- i2--;
- buf[i2] = buf[i1];
- buf[i1] = 0;
- }
- i2 -= i1;
- for(i1=n+1; i1<sp[0]; i1++)
- sp[i1+1-1] = sp[i1+1] + i2;
- sp[0]--;
- sp[sp[0]+1] = 0;
- return;
-
- bad:
- printf("bad delitem\n");
- abort();
- }
-
- additem(buf, item)
- char buf[PBLKSIZ];
- datum item;
- {
- register short *sp;
- register i1, i2;
-
- sp = (short *)buf;
- i1 = PBLKSIZ;
- if(sp[0] > 0)
- i1 = sp[sp[0]+1-1];
- i1 -= item.dsize;
- i2 = (sp[0]+2) * sizeof(short);
- if(i1 <= i2)
- return(-1);
- sp[sp[0]+1] = i1;
- for(i2=0; i2<item.dsize; i2++) {
- buf[i1] = item.dptr[i2];
- i1++;
- }
- sp[0]++;
- return(sp[0]-1);
- }
-
- chkblk(buf)
- char buf[PBLKSIZ];
- {
- register short *sp;
- register t, i;
-
- sp = (short *)buf;
- t = PBLKSIZ;
- for(i=0; i<sp[0]; i++) {
- if(sp[i+1] > t)
- goto bad;
- t = sp[i+1];
- }
- if(t < (sp[0]+1)*sizeof(short))
- goto bad;
- return;
-
- bad:
- printf("bad block\n");
- abort();
- clrbuf(buf, PBLKSIZ);
- }
-