1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-25 23:21:54 +03:00

Change some internal interfaces to cause the hash (which is *expensive*)

to be calculated less often. No change to external interface.
Jeremy.
(This used to be commit 155c9ce666)
This commit is contained in:
Jeremy Allison 2003-09-06 19:59:12 +00:00
parent 5bd4af1302
commit 6007eae339

View File

@ -1015,12 +1015,11 @@ static int tdb_keylocked(TDB_CONTEXT *tdb, u32 hash)
} }
/* As tdb_find, but if you succeed, keep the lock */ /* As tdb_find, but if you succeed, keep the lock */
static tdb_off tdb_find_lock(TDB_CONTEXT *tdb, TDB_DATA key, int locktype, static tdb_off tdb_find_lock_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, int locktype,
struct list_struct *rec) struct list_struct *rec)
{ {
u32 hash, rec_ptr; u32 rec_ptr;
hash = tdb_hash(&key);
if (!tdb_keylocked(tdb, hash)) if (!tdb_keylocked(tdb, hash))
return 0; return 0;
if (tdb_lock(tdb, BUCKET(hash), locktype) == -1) if (tdb_lock(tdb, BUCKET(hash), locktype) == -1)
@ -1061,13 +1060,13 @@ const char *tdb_errorstr(TDB_CONTEXT *tdb)
on failure return -1. on failure return -1.
*/ */
static int tdb_update(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf) static int tdb_update_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf)
{ {
struct list_struct rec; struct list_struct rec;
tdb_off rec_ptr; tdb_off rec_ptr;
/* find entry */ /* find entry */
if (!(rec_ptr = tdb_find(tdb, key, tdb_hash(&key), &rec))) if (!(rec_ptr = tdb_find(tdb, key, hash, &rec)))
return -1; return -1;
/* must be long enough key, data and tailer */ /* must be long enough key, data and tailer */
@ -1101,9 +1100,11 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key)
tdb_off rec_ptr; tdb_off rec_ptr;
struct list_struct rec; struct list_struct rec;
TDB_DATA ret; TDB_DATA ret;
u32 hash;
/* find which hash bucket it is in */ /* find which hash bucket it is in */
if (!(rec_ptr = tdb_find_lock(tdb,key,F_RDLCK,&rec))) hash = tdb_hash(&key);
if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec)))
return tdb_null; return tdb_null;
if (rec.data_len) if (rec.data_len)
@ -1122,16 +1123,22 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key)
this doesn't match the conventions in the rest of this module, but is this doesn't match the conventions in the rest of this module, but is
compatible with gdbm compatible with gdbm
*/ */
int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key) static int tdb_exists_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash)
{ {
struct list_struct rec; struct list_struct rec;
if (tdb_find_lock(tdb, key, F_RDLCK, &rec) == 0) if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0)
return 0; return 0;
tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
return 1; return 1;
} }
int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key)
{
u32 hash = tdb_hash(&key);
return tdb_exists_hash(tdb, key, hash);
}
/* record lock stops delete underneath */ /* record lock stops delete underneath */
static int lock_record(TDB_CONTEXT *tdb, tdb_off off) static int lock_record(TDB_CONTEXT *tdb, tdb_off off)
{ {
@ -1388,7 +1395,7 @@ TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey)
if (!tdb->travlocks.off) { if (!tdb->travlocks.off) {
/* No previous element: do normal find, and lock record */ /* No previous element: do normal find, and lock record */
tdb->travlocks.off = tdb_find_lock(tdb, oldkey, F_WRLCK, &rec); tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb_hash(&oldkey), F_WRLCK, &rec);
if (!tdb->travlocks.off) if (!tdb->travlocks.off)
return tdb_null; return tdb_null;
tdb->travlocks.hash = BUCKET(rec.full_hash); tdb->travlocks.hash = BUCKET(rec.full_hash);
@ -1416,13 +1423,13 @@ TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey)
} }
/* delete an entry in the database given a key */ /* delete an entry in the database given a key */
int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key) static int tdb_delete_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash)
{ {
tdb_off rec_ptr; tdb_off rec_ptr;
struct list_struct rec; struct list_struct rec;
int ret; int ret;
if (!(rec_ptr = tdb_find_lock(tdb, key, F_WRLCK, &rec))) if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, &rec)))
return -1; return -1;
ret = do_delete(tdb, rec_ptr, &rec); ret = do_delete(tdb, rec_ptr, &rec);
if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0) if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0)
@ -1430,6 +1437,12 @@ int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key)
return ret; return ret;
} }
int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key)
{
u32 hash = tdb_hash(&key);
return tdb_delete_hash(tdb, key, hash);
}
/* store an element in the database, replacing any existing element /* store an element in the database, replacing any existing element
with the same key with the same key
@ -1452,13 +1465,13 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
/* check for it existing, on insert. */ /* check for it existing, on insert. */
if (flag == TDB_INSERT) { if (flag == TDB_INSERT) {
if (tdb_exists(tdb, key)) { if (tdb_exists_hash(tdb, key, hash)) {
tdb->ecode = TDB_ERR_EXISTS; tdb->ecode = TDB_ERR_EXISTS;
goto fail; goto fail;
} }
} else { } else {
/* first try in-place update, on modify or replace. */ /* first try in-place update, on modify or replace. */
if (tdb_update(tdb, key, dbuf) == 0) if (tdb_update_hash(tdb, key, hash, dbuf) == 0)
goto out; goto out;
if (flag == TDB_MODIFY && tdb->ecode == TDB_ERR_NOEXIST) if (flag == TDB_MODIFY && tdb->ecode == TDB_ERR_NOEXIST)
goto fail; goto fail;
@ -1470,7 +1483,7 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
care. Doing this first reduces fragmentation, and avoids care. Doing this first reduces fragmentation, and avoids
coalescing with `allocated' block before it's updated. */ coalescing with `allocated' block before it's updated. */
if (flag != TDB_INSERT) if (flag != TDB_INSERT)
tdb_delete(tdb, key); tdb_delete_hash(tdb, key, hash);
/* Copy key+value *before* allocating free space in case malloc /* Copy key+value *before* allocating free space in case malloc
fails and we are left with a dead spot in the tdb. */ fails and we are left with a dead spot in the tdb. */
@ -1519,13 +1532,13 @@ fail:
is <= the old data size and the key exists. is <= the old data size and the key exists.
on failure return -1. Record must be locked before calling. on failure return -1. Record must be locked before calling.
*/ */
static int tdb_append_inplace(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf) static int tdb_append_inplace(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA new_dbuf)
{ {
struct list_struct rec; struct list_struct rec;
tdb_off rec_ptr; tdb_off rec_ptr;
/* find entry */ /* find entry */
if (!(rec_ptr = tdb_find(tdb, key, tdb_hash(&key), &rec))) if (!(rec_ptr = tdb_find(tdb, key, hash, &rec)))
return -1; return -1;
/* Append of 0 is always ok. */ /* Append of 0 is always ok. */
@ -1567,7 +1580,7 @@ int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf)
return -1; return -1;
/* first try in-place. */ /* first try in-place. */
if (tdb_append_inplace(tdb, key, new_dbuf) == 0) if (tdb_append_inplace(tdb, key, hash, new_dbuf) == 0)
goto out; goto out;
/* reset the error code potentially set by the tdb_append_inplace() */ /* reset the error code potentially set by the tdb_append_inplace() */
@ -1610,7 +1623,7 @@ int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf)
care. Doing this first reduces fragmentation, and avoids care. Doing this first reduces fragmentation, and avoids
coalescing with `allocated' block before it's updated. */ coalescing with `allocated' block before it's updated. */
tdb_delete(tdb, key); tdb_delete_hash(tdb, key, hash);
if (!(rec_ptr = tdb_allocate(tdb, key.dsize + new_data_size, &rec))) if (!(rec_ptr = tdb_allocate(tdb, key.dsize + new_data_size, &rec)))
goto fail; goto fail;