X-Git-Url: http://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Ftdb2%2Fhash.c;h=619d56f8116c49cd954ad0f8864412a5b93ab16e;hp=1359cfecd66dc6280e3314e78fd2e7e5ea91c8bd;hb=5c559e7df1d31b4c0ddf26451fac972dc8a0c2c9;hpb=8cca0397ef6f6017b13ce9ab4999bf3d92a2dee5
diff --git a/ccan/tdb2/hash.c b/ccan/tdb2/hash.c
index 1359cfec..619d56f8 100644
--- a/ccan/tdb2/hash.c
+++ b/ccan/tdb2/hash.c
@@ -16,8 +16,20 @@
License along with this library; if not, see .
*/
#include "private.h"
+#include
#include
+/* Default hash function. */
+uint64_t tdb_jenkins_hash(const void *key, size_t length, uint64_t seed,
+ void *unused)
+{
+ uint64_t ret;
+ /* hash64_stable assumes lower bits are more important; they are a
+ * slightly better hash. We use the upper bits first, so swap them. */
+ ret = hash64_stable((const unsigned char *)key, length, seed);
+ return (ret >> 32) | (ret << 32);
+}
+
uint64_t tdb_hash(struct tdb_context *tdb, const void *ptr, size_t len)
{
return tdb->hash_fn(ptr, len, tdb->hash_seed, tdb->hash_data);
@@ -78,7 +90,7 @@ static tdb_bool_err key_matches(struct tdb_context *tdb,
rkey = tdb_access_read(tdb, off + sizeof(*rec), key->dsize, false);
if (TDB_PTR_IS_ERR(rkey)) {
- return TDB_PTR_ERR(rkey);
+ return (tdb_bool_err)TDB_PTR_ERR(rkey);
}
if (memcmp(rkey, key->dptr, key->dsize) == 0)
ret = true;
@@ -116,7 +128,7 @@ static tdb_bool_err match(struct tdb_context *tdb,
off = val & TDB_OFF_MASK;
ecode = tdb_read_convert(tdb, off, rec, sizeof(*rec));
if (ecode != TDB_SUCCESS) {
- return ecode;
+ return (tdb_bool_err)ecode;
}
if ((h->h & ((1 << 11)-1)) != rec_hash(rec)) {
@@ -164,7 +176,7 @@ static tdb_off_t COLD find_in_chain(struct tdb_context *tdb,
h->group_start = off;
ecode = tdb_read_convert(tdb, off, h->group, sizeof(h->group));
if (ecode != TDB_SUCCESS) {
- return ecode;
+ return TDB_ERR_TO_OFF(ecode);
}
for (i = 0; i < (1 << TDB_HASH_GROUP_BITS); i++) {
@@ -181,14 +193,15 @@ static tdb_off_t COLD find_in_chain(struct tdb_context *tdb,
ecode = tdb_read_convert(tdb, recoff, rec,
sizeof(*rec));
if (ecode != TDB_SUCCESS) {
- return ecode;
+ return TDB_ERR_TO_OFF(ecode);
}
- ecode = key_matches(tdb, rec, recoff, &key);
+ ecode = TDB_OFF_TO_ERR(key_matches(tdb, rec, recoff,
+ &key));
if (ecode < 0) {
- return ecode;
+ return TDB_ERR_TO_OFF(ecode);
}
- if (ecode == 1) {
+ if (ecode == (enum TDB_ERROR)1) {
h->home_bucket = h->found_bucket = i;
if (tinfo) {
@@ -240,7 +253,7 @@ tdb_off_t find_and_lock(struct tdb_context *tdb,
ecode = tdb_lock_hashes(tdb, h->hlock_start, h->hlock_range, ltype,
TDB_LOCK_WAIT);
if (ecode != TDB_SUCCESS) {
- return ecode;
+ return TDB_ERR_TO_OFF(ecode);
}
hashtable = offsetof(struct tdb_header, hashtable);
@@ -303,7 +316,7 @@ tdb_off_t find_and_lock(struct tdb_context *tdb,
berr = match(tdb, h, &key, h->group[h->found_bucket],
rec);
if (berr < 0) {
- ecode = berr;
+ ecode = TDB_OFF_TO_ERR(berr);
goto fail;
}
if (berr) {
@@ -322,7 +335,7 @@ tdb_off_t find_and_lock(struct tdb_context *tdb,
fail:
tdb_unlock_hashes(tdb, h->hlock_start, h->hlock_range, ltype);
- return ecode;
+ return TDB_ERR_TO_OFF(ecode);
}
/* I wrote a simple test, expanding a hash to 2GB, for the following
@@ -414,7 +427,7 @@ static enum TDB_ERROR COLD add_to_chain(struct tdb_context *tdb,
entry = tdb_find_zero_off(tdb, subhash, 1<flags & TDB_VERSION1) {
+ if (tdb1_chainlock(tdb, key) == -1)
+ return tdb->last_error;
+ return TDB_SUCCESS;
+ }
return tdb->last_error = chainlock(tdb, &key, F_WRLCK, TDB_LOCK_WAIT,
"tdb_chainlock");
}
@@ -850,6 +868,11 @@ void tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key)
tdb_off_t lockstart, locksize;
unsigned int group, gbits;
+ if (tdb->flags & TDB_VERSION1) {
+ tdb1_chainunlock(tdb, key);
+ return;
+ }
+
gbits = TDB_TOPLEVEL_HASH_BITS - TDB_HASH_GROUP_BITS;
group = bits_from(h, 64 - gbits, gbits);
@@ -861,6 +884,11 @@ void tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key)
enum TDB_ERROR tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key)
{
+ if (tdb->flags & TDB_VERSION1) {
+ if (tdb1_chainlock_read(tdb, key) == -1)
+ return tdb->last_error;
+ return TDB_SUCCESS;
+ }
return tdb->last_error = chainlock(tdb, &key, F_RDLCK, TDB_LOCK_WAIT,
"tdb_chainlock_read");
}
@@ -871,6 +899,10 @@ void tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key)
tdb_off_t lockstart, locksize;
unsigned int group, gbits;
+ if (tdb->flags & TDB_VERSION1) {
+ tdb1_chainunlock_read(tdb, key);
+ return;
+ }
gbits = TDB_TOPLEVEL_HASH_BITS - TDB_HASH_GROUP_BITS;
group = bits_from(h, 64 - gbits, gbits);