Research V7 development
authorAlfred V. Aho <aho@research.uucp>
Sat, 5 May 1979 07:44:02 +0000 (02:44 -0500)
committerAlfred V. Aho <aho@research.uucp>
Sat, 5 May 1979 07:44:02 +0000 (02:44 -0500)
Work on file usr/src/libdbm/dbm.c
Work on file usr/src/libdbm/dbm.h

Synthesized-from: v7

usr/src/libdbm/dbm.c [new file with mode: 0644]
usr/src/libdbm/dbm.h [new file with mode: 0644]

diff --git a/usr/src/libdbm/dbm.c b/usr/src/libdbm/dbm.c
new file mode 100644 (file)
index 0000000..aaafcc4
--- /dev/null
@@ -0,0 +1,465 @@
+#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);
+}
diff --git a/usr/src/libdbm/dbm.h b/usr/src/libdbm/dbm.h
new file mode 100644 (file)
index 0000000..ea5d5a3
--- /dev/null
@@ -0,0 +1,30 @@
+#define        PBLKSIZ 512
+#define        DBLKSIZ 8192
+#define        BYTESIZ 8
+#define        NULL    ((char *) 0)
+
+long   bitno;
+long   maxbno;
+long   blkno;
+long   hmask;
+
+char   pagbuf[PBLKSIZ];
+char   dirbuf[DBLKSIZ];
+
+int    dirf;
+int    pagf;
+
+typedef        struct
+{
+       char    *dptr;
+       int     dsize;
+} datum;
+
+datum  fetch();
+datum  makdatum();
+datum  firstkey();
+datum  nextkey();
+datum  firsthash();
+long   calchash();
+long   hashinc();
+