Esempio n. 1
0
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);
}