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:
parent
5bd4af1302
commit
6007eae339
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user