📄 store.c
字号:
#include "db.h"
/* Store a record in the database.
* Return 0 if OK, 1 if record exists and DB_INSERT specified,
* -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 for newline at end */
if (datlen < DATLEN_MIN || datlen > DATLEN_MAX)
err_dump("invalid data length");
/* _db_find() calculates which hash table this new record
goes into (db->chainoff), regardless whether it already
exists or not. The calls to _db_writeptr() below
change the hash table entry for this chain to point to
the new record. This means 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 does not exist */
}
/* _db_find() locked the hash chain for us; read 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 size was not found.
We have to 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 new
record goes to the front of the hash chain. */
_db_writeptr(db, db->chainoff, db->idxoff);
db->cnt_stor1++;
} else {
/* We can reuse an empty record.
_db_findfree() removed the record from the free
list and set both db->datoff and db->idxoff. */
_db_writedat(db, data, db->datoff, SEEK_SET);
_db_writeidx(db, key, db->idxoff, SEEK_SET, ptrval);
/* reused 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 already in db */
}
/* We are replacing an existing record. We know the new
key equals the existing key, but we need to check if
the data records are the same size. */
if (datlen != db->datlen) {
_db_dodelete(db); /* delete the existing record */
/* Reread the chain ptr in the hash table
(it may change with the deletion). */
ptrval = _db_readptr(db, db->chainoff);
/* append 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 goes to the front of the hash chain. */
_db_writeptr(db, db->chainoff, db->idxoff);
db->cnt_stor3++;
} else {
/* same size data, just replace data record */
_db_writedat(db, data, db->datoff, SEEK_SET);
db->cnt_stor4++;
}
}
rc = 0; /* OK */
doreturn: /* 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(rc);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -