char * db_nextrec(DB *db, char *key) { char c, *ptr; /* We read lock the free list so that we don't read a record in the middle of its being deleted. */ if (readw_lock(db->idxfd, FREE_OFF, SEEK_SET, 1) < 0) err_dump("readw_lock error"); do { /* read next sequential index record */ if (_db_readidx(db, 0) < 0) { ptr = NULL; /* end of index file, EOF */ goto doreturn; } /* check if key is all blank (empty record) */ ptr = db->idxbuf; while ( (c = *ptr++) != 0 && c == ' ') ; /* skip until null byte or nonblank */ } while (c == 0); /* loop until a nonblank key is found */ if (key != NULL) strcpy(key, db->idxbuf); /* return key */ ptr = _db_readdat(db); /* return pointer to data buffer */ db->cnt_nextrec++; doreturn: if (un_lock(db->idxfd, FREE_OFF, SEEK_SET, 1) < 0) err_dump("un_lock error"); return(ptr); }
/* Returning the sequential record... Just gotta step ahead through the index file where we gotta ignore deleted records. db_rewind() essential to be called before this function at initial stage itself */ char *db_nextrec(DB *db, char *key) { char c, *ptr; /* Locking the free list where we don't actually read a record in the mid of deletion*/ if(readw_lock(db->idxfd, FREE_OFF, SEEK_SET, 1) < 0) err_dump("error"); do { /* read next sequential index record */ if(_db_readidx(db, 0) < 0) { ptr = NULL; /* end of index file --- EOF */ goto doreturn; } /* Checking if the key is still blank or empty record */ ptr = db->idxbuf; while((c = *ptr++) != 0 && c = ' '); /* skip if it's not blank */ } while(c == 0) /* loop untill a non-empty key is found*/ if(key != NULL) strcpy(key, db->idxbuf); /* return key */ ptr = _db_readdat(db); /* return pointer to data buffer */ db->cnt_nextrec++; doreturn: if(un_lock(db->idxfd, FREE_OFF, SEEK_SET, 1) < 0) err_dump("error"); }
/* Find specified record. Called by db_delete(), db_fetch() and db_store() */ int _db_find(DB *db, const char *key, int writelock) { off_t offset, nextoffset; /* calculate hash value for this key, then calculate byte offset of corresponding chain ptr in hash table. */ /* calculate offset in hash table for this key */ db->chainoff = (_db_hash(db, key) * PTR_SZ) + db->hashoff; db->ptroff = db->chainoff; /* here's where we lock this hash chain. It's the caller responsibility to unlock it when done. Note that we lock and unlock only the first byte. */ if(writelock) { if(writew_lock(db->idxfd, db->chainoff, SEEK_SET, 1) < 0) err_dump("error"); } else { if(readw_lock(db->idxfd, db->chainoff, SEEK_SET, 1) < 0) err_dump("error"); } /* Get the offset in the index file of first record on the bash chain (it can be 0 too) */ offset = _db_readptr(db, db->ptroff); while(offset!=0) { nextoffset = _db_readidx(db, offset); if(strcmp(db->idxbuf, key) == 0) break; /* found a match */ db->ptroff = offset; /* offset of this (unequal) record */ offset = nextoffset; /* next one to compare */ } if(offset == 0) return(-1); /* error -- record not found */ return(0); /* if not error */ }
/* Try to find a free index record and accompany data record of correct sizes. We're only called by db_store() */ int _db_findtree(DB *db, int keylen, int datalen) { int rc; off_t offset, nextoffset, saveoffset; /* locking the free list */ if(writew_lock(db->idxfd, FREE_OFF, SEEK_SET, 1) < 0) err_dump("error"); /* reading the free list pointer */ saveoffset = FREE_OFF; offset = _db_readptr(db, saveoffset); while(offset != 0) { nextoffset = _db_readidx(db, offset); if(strlen(db->idxbuf) == keylen && db->datlen == datlen) break; /* found a match */ saveoffset = offset; offset = nextoffset; } if(offset == 0) rc = -1; /* no match found */ else { /* Found a tree record with matching sizes. The index record was read in by _db_readidx() above which sets db->ptrval. Also, saveoffset points to the chain ptr that pointed to empty record on free list. We'll be setting this chain ptr to db->ptrval, which removes empty record from free list */ _db_writeptr(db, saveoffset, db->ptrval); rc = 0; /* _db_readidx() set both db->idxoff and db->datoff. This is used by the caller, db_store() inorder to write new index record and data record */ } /* Unlocking the free list */ if(un_lock(db->idxfd, FREE_OFF, SEEK_SET, 1) < 0) err_dump("error"); return(rc); }