示例#1
0
char *
db_fetch(DB *db, const char *key)
{
    char    *ptr;

    if (_db_find(db, key, 0) < 0) {
        ptr = NULL;                /* error, record not found */
        db->cnt_fetcherr++;
    } else {
        ptr = _db_readdat(db);    /* return pointer to data */
        db->cnt_fetchok++;
    }
            /* Unlock the hash chain that _db_find() locked */
    if (un_lock(db->idxfd, db->chainoff, SEEK_SET, 1) < 0)
        err_dump("un_lock error");
    return(ptr);
}
/* Deleting the specified record */
int db_delete(DB *db, const char *key)
{
	int rc;
	if(_db_find(db, key, 1) == 0)
	{
		rc = _db_dodelete(db); /* record found */
		db->cnt_delok++;
	}
	else
	{
		rc = -1; /* not found */
		db->cnt_delerr++;
	}
	if(un_lock(db->idxfd, db->chainoff, SEEK_SET, 1) < 0)
		err_dump("error");
	return(rc);
}
/* Storing a record in a database.
Return 0 if okay, Return 1 if record exists and DB_INSERT specified.
Return -1 if record doesn't exist and DB_REPLACE specified.
*/
int db_store(DB *db, const char *key, const char *data, int flag)
{
	int rc, keylen, datlen;
	off_t ptrval;
	keylen = strlen(key);
	datlen = strlen(data) + 1; /* +1 is for newline at the end */
	if(datlen < DATLEN_MIN || datalen > DATLEN_MAX)
		err_dump("invalid data length");
	/* db_find() calculates which hash table this new record goes into(db->chainoff) whether it already exists or not.
	The calls to _db_writeptr() below change the hash table entry for this chain to point to new record.
	This means that the new record is added to the front of the hash chain */
	if(_db_find(db, key, 1) < 0)
	{
		/* record not found*/
		if(flag & DB_REPLACE)
		{
			rc = -1;
			db->cnt_storerr++;
			goto doreturn; /* error --- record doesn't exist */
		}
		/* do_find() locked the hash chain.
			Reading the chain ptr to the first index record on hash chain */
		ptrval = _db_readptr(db, db->chainoff);
		if(_db_findfree(db, keylen, datlen) < 0)
		{
			/* an empty record of the correct record wasn't found.
				we gotta append the new record to the ends of the index and data files */
			_db_writedat(db, data, 0, SEEK_END);
			_db_writeidx(db, key, 0, SEEK_END, ptrval);
			/* db->idxoff was set by _db_writeidx()
			The record goes to the front of the bash chain */
			_db_writeptr(db, db->chainoff, db->idxoff);
			db->cnt_stor1++;
		}
		else
		{
			/* Re-using an empty record
			_db_findtree() removed the record from the free list and set both db->datoff and db->idxoff */
			_db_writedat(db, data, 0, SEEK_END);
			_db_writeidx(db, key, 0, SEEK_END, ptrval);
			/* re-used record goes to the front of the hash chain */
			_db_writeptr(db, db->chainoff, db->idxoff);
			db->cnt_stor2++;
		}
	}
	else
	{
		/* record found */
		if(flag & DB_INSERT)
		{
			rc = 1;
			db->cnt_storerr++;
			goto doreturn; /* error --- record is already in the database */
		}
		/* We are replacing the existing record.
			We know the new key equals the existing key, but also we gotta check if the data records are the same size. */
		if(datlen != db->datlen)
		{
			_db_dodelete(db); /* delete the existing record */
			/* Re-read the chain ptr in the hash table (It may change with the deletion) */
			ptrval = _db_readptr(db, db->chainoff);
			/* Appending new index and data records to end of files */
			_db_writedat(db, data, 0, SEEK_END);
			_db_writeidx(db, key, 0, SEEK_END, ptrval);
			/* new record going to the front of the hash chain */
			_db_writeptr(db, db->chainoff, db->idxoff);
			db->cnt_stor3++;
		}
		else
		{
			/* Same sized data, just replaces data record */
			_db_writedat(db, data, db->datoff, SEEK_SET);
			db->cnt_stor4++;
		}
	}
	rc = 0; /* woo hoo */
doreturn: /* unlock the hash chain that _db_find() locked */
	if(un_lock(db->idxfd, db->chainoff, SEEK_SET, 1) < 0)
		return(rc);
}