int dbm_delete(DBM *db, datum key) { int i; if (dbm_error(db)) return (-1); if (dbm_rdonly(db)) { errno = EPERM; return (-1); } dbm_access(db, dcalchash(key)); if ((i = finddatum(db->dbm_pagbuf, key)) < 0) return (-1); if (!delitem(db->dbm_pagbuf, i)) goto err; db->dbm_pagbno = db->dbm_blkno; if (dbm_defwrite(db)) { dbm_setdirty(db); } else { (void) lseek(db->dbm_pagf, (long)(db->dbm_blkno*PBLKSIZ), L_SET); if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) { err: db->dbm_flags |= _DBM_IOERR; return (-1); } } return (0); }
/* check the block number in pag file */ long dbm_forder(DBM *db, datum key){ long hash; hash = dcalchash(key); for(db->dbm_hmask=0;; db->dbm_hmask=(db->dbm_hmask<<1)+1){ db->dbm_blkno = hash & db->dbm_hmask; db->dbm_bitno = db->dbm_blkno + db->dbm_hmask; if(getbit(db) == 0) break; } return (db->dbm_blkno); }
/* retrieve a record */ datum dbm_fetch(DBM *db, datum key){ int i; datum item; if(dbm_error(db)) goto err; dbm_access(db, dcalchash(key)); if((i = finddatum(db->dbm_pagbuf, key)) >= 0){ item = makdatum(db->dbm_pagbuf, i+1); if(item.dptr != NULL) return (item); } err: item.dptr = NULL; item.dsize = 0; return (item); }
/* store a record */ int dbm_store(DBM *db, datum key, datum dat, int replace){ int i; datum item, item1; char ovfbuf[PBLKSIZ]; if(dbm_error(db)) return (-1); if(dbm_rdonly(db)){ errno = EPERM; return (-1); } loop: dbm_access(db, dcalchash(key)); if((i = finddatum(db->dbm_pagbuf, key)) >= 0){ if(!replace) return (1); if(!delitem(db->dbm_pagbuf, i)){ db->dbm_flags |= _DBM_IOERR; return (-1); } } if(!additem(db->dbm_pagbuf, key, dat)) goto split; db->dbm_pagbno = db->dbm_blkno; (void) lseek(db->dbm_pagf, db->dbm_blkno*PBLKSIZ, SEEK_SET); if(write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ){ db->dbm_flags |= _DBM_IOERR; return (-1); } return (0); split: if(key.dsize+dat.dsize+3*sizeof(short) >= PBLKSIZ){ db->dbm_flags |= _DBM_IOERR; errno = ENOSPC; return (-1); } memset(ovfbuf, 0, PBLKSIZ); for(i=0;;){ item = makdatum(db->dbm_pagbuf, i); if(item.dptr == NULL) break; if(dcalchash(item) & (db->dbm_hmask+1)){ item1 = makdatum(db->dbm_pagbuf, i+1); if(item1.dptr == NULL){ db->dbm_flags |= _DBM_IOERR; break; } if(!additem(ovfbuf, item, item1) || !delitem(db->dbm_pagbuf, i)){ db->dbm_flags |= _DBM_IOERR; return (-1); } continue; } i += 2; } db->dbm_pagbno = db->dbm_blkno; (void) lseek(db->dbm_pagf, db->dbm_blkno*PBLKSIZ, SEEK_SET); if(write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ){ db->dbm_flags |= _DBM_IOERR; return (-1); } (void) lseek(db->dbm_pagf, (db->dbm_blkno+db->dbm_hmask+1)*PBLKSIZ, SEEK_SET); if(write(db->dbm_pagf, ovfbuf, PBLKSIZ) != PBLKSIZ){ db->dbm_flags |= _DBM_IOERR; return (-1); } setbit(db); goto loop; }
datum dbm_do_nextkey(DBM *db, datum inkey) { datum item,bitem; long hash; datum key; int f; int i; int j; short *sp; int n; char *p1, *p2; if ( dbm_error(db) ) { item.dptr = NULL; item.dsize = 0; return (item); } /*user has supplied lastkey*/ if(inkey.dptr != NULL) { dbm_access(db, (hash=dcalchash(inkey))); if ((i = finddatum(db->dbm_pagbuf, inkey)) >= 0) { db->dbm_keyptr = i + 2; db->dbm_blkptr = db->dbm_blkno; } key=inkey; } else { /*is this a manual firstkey request? */ if (db->dbm_blkptr == 0L && db->dbm_keyptr == 0) return (dbm_firsthash(db, 0L)); /*no -- get lastkey this is like dbm_access by blkptr*/ if (db->dbm_blkptr != db->dbm_pagbno) { if (dbm_dirty(db)) dbm_flushpag(db); db->dbm_pagbno = db->dbm_blkptr; (void) lseek(db->dbm_pagf, (long)(db->dbm_blkptr*PBLKSIZ), L_SET); if (read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) bzero(db->dbm_pagbuf, PBLKSIZ); #ifdef DEBUG else if (chkblk(db->dbm_pagbuf) < 0) db->dbm_flags |= _DBM_IOERR; #endif } /*now just make up last key datum*/ if (db->dbm_keyptr >=2) key= makdatum(db->dbm_pagbuf,(db->dbm_keyptr-2)); else key=nullkey; /* the keyptr pagbuf have failed us, the user must be an extra clever moron who depends on these variables and their former meaning. If we set the variables this would have got us the key for sure! So give him the old algorithm.*/ if (key.dptr == NULL) return (dbm_slow_nextkey(db)); } /*at this point the last key is paged in and we can proceed as in old dbm -- like Ken did his. */ f = 1; j=0; sp = (short *)db->dbm_pagbuf; for(i=0;; i+=2) { /*begin put makdatum inline*/ if ((unsigned)i >= sp[0]) { item.dptr = NULL; item.dsize = 0; break; /*from below*/ } else { if (i > 0) item.dsize = sp[i] - sp[i+1]; else item.dsize = PBLKSIZ - sp[i+1]; item.dptr = db->dbm_pagbuf+sp[i+1]; } /* item = makdatum(db->dbm_pagbuf, i);*/ /*end put makdatum inline*/ if(item.dptr == NULL) break; /*inline cmpdatum*/ n = key.dsize; if(n != item.dsize) if( (n - item.dsize) <= 0 ) continue; else { } else { if(n == 0) continue; p1 = key.dptr; p2 = item.dptr; do if(*p1++ != *p2++) if((*--p1 - *--p2) > 0) goto keep_going; else continue; while(--n); continue; } keep_going: /*end inline cmpdatum*/ /*if(cmpdatum(key, item) <= 0) continue;*/ if (f) { bitem = item; j=i; f = 0; } else { /* if(cmpdatum(bitem, item) < 0)*/ n = bitem.dsize; if(n != item.dsize) { if((n - item.dsize) <0) { bitem = item; j=i; } } else if (n != 0) { p1 = bitem.dptr; p2 = item.dptr; do if(*p1++ != *p2++) { if((*--p1 - *--p2) <0) { bitem = item; j=i; } break; } while(--n); } } } if(f == 0) { db->dbm_keyptr = j + 2; db->dbm_blkptr = db->dbm_blkno; return (bitem); } /*really need hash at this point*/ /*if he gave us a key we have already calculated the hash*/ /*if not get it*/ if (inkey.dptr == NULL) hash=dcalchash(key); hash = dbm_hashinc(db,hash); if(hash == 0) return (item); /*null*/ /*get first item on next page in hash table order*/ return (dbm_firsthash(db, hash)); }
int dbm_store(DBM *db, datum key, datum dat, int replace) { int i; datum item, item1; char ovfbuf[PBLKSIZ]; if (dbm_error(db)) return (-1); if (dbm_rdonly(db)) { errno = EPERM; return (-1); } loop: dbm_access(db, dcalchash(key)); if ((i = finddatum(db->dbm_pagbuf, key)) >= 0) { if (!replace) return (1); if (!delitem(db->dbm_pagbuf, i)) { db->dbm_flags |= _DBM_IOERR; return (-1); } } if (!additem(db->dbm_pagbuf, key, dat)) goto split; db->dbm_pagbno = db->dbm_blkno; if (dbm_defwrite(db)) { dbm_setdirty(db); } else { (void) lseek(db->dbm_pagf, (long)(db->dbm_blkno*PBLKSIZ), L_SET); if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) { db->dbm_flags |= _DBM_IOERR; return (-1); } } return (0); split: if (key.dsize+dat.dsize+3*sizeof(short) >= PBLKSIZ) { db->dbm_flags |= _DBM_IOERR; errno = ENOSPC; return (-1); } bzero(ovfbuf, PBLKSIZ); for (i=0;;) { item = makdatum(db->dbm_pagbuf, i); if (item.dptr == NULL) break; if (dcalchash(item) & (db->dbm_hmask+1)) { item1 = makdatum(db->dbm_pagbuf, i+1); if (item1.dptr == NULL) { /*(void) fprintf(stderr, "ndbm: split not paired\n");*/ db->dbm_flags |= _DBM_IOERR; break; } if (!additem(ovfbuf, item, item1) || !delitem(db->dbm_pagbuf, i)) { db->dbm_flags |= _DBM_IOERR; return (-1); } continue; } i += 2; } db->dbm_pagbno = db->dbm_blkno; (void) lseek(db->dbm_pagf, (long)(db->dbm_blkno*PBLKSIZ), L_SET); if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) { db->dbm_flags |= _DBM_IOERR; return (-1); } dbm_clrdirty(db); /*clear dirty*/ (void) lseek(db->dbm_pagf, (long)((db->dbm_blkno+db->dbm_hmask+1)*PBLKSIZ), L_SET); if (write(db->dbm_pagf, ovfbuf, PBLKSIZ) != PBLKSIZ) { db->dbm_flags |= _DBM_IOERR; return (-1); } if (setbit(db) < 0) { db->dbm_flags |= _DBM_IOERR; return (-1); } goto loop; }