From: Rusty Russell Date: Wed, 31 Aug 2011 05:57:16 +0000 (+0930) Subject: tdb2: Make TDB1 use the same tdb_hash() wrapper as TDB2 X-Git-Url: https://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=3e46dde21261966941469a6c75e1b45cd2d26324 tdb2: Make TDB1 use the same tdb_hash() wrapper as TDB2 This means converting the tdb1 inbuilt hash functions to the tdb2-style, so they return 64 bit. We truncate to 32 bit everywhere but in tdb_check() which needs to do so explicitly. --- diff --git a/ccan/tdb2/private.h b/ccan/tdb2/private.h index fdd50535..cd52542b 100644 --- a/ccan/tdb2/private.h +++ b/ccan/tdb2/private.h @@ -356,14 +356,14 @@ struct tdb_context { /* Our statistics. */ struct tdb_attribute_stats stats; - /* Are we accessing directly? (debugging check). */ - int direct_access; - /* Hash function. */ uint64_t (*hash_fn)(const void *key, size_t len, uint64_t seed, void *); void *hash_data; uint64_t hash_seed; + /* Are we accessing directly? (debugging check). */ + int direct_access; + /* Set if we are in a transaction. */ struct tdb_transaction *transaction; diff --git a/ccan/tdb2/tdb1.h b/ccan/tdb2/tdb1.h index 67e00c7c..5227bbbb 100644 --- a/ccan/tdb2/tdb1.h +++ b/ccan/tdb2/tdb1.h @@ -42,7 +42,8 @@ typedef struct tdb1_context TDB1_CONTEXT; typedef int (*tdb1_traverse_func)(struct tdb1_context *, TDB_DATA, TDB_DATA, void *); typedef void (*tdb1_log_func)(struct tdb1_context *, enum tdb_log_level, enum TDB_ERROR, const char *, void *); -typedef unsigned int (*tdb1_hash_func)(TDB_DATA *key); +typedef uint64_t (*tdb1_hash_func)(const void *key, size_t len, uint64_t seed, + void *data); struct tdb1_logging_context { tdb1_log_func log_fn; @@ -106,7 +107,7 @@ int tdb1_hash_size(struct tdb1_context *tdb); void tdb1_increment_seqnum_nonblock(struct tdb1_context *tdb); -unsigned int tdb1_incompatible_hash(TDB_DATA *key); +uint64_t tdb1_incompatible_hash(const void *key, size_t len, uint64_t seed, void *); int tdb1_check(struct tdb1_context *tdb, int (*check) (TDB_DATA key, TDB_DATA data, void *private_data), diff --git a/ccan/tdb2/tdb1_check.c b/ccan/tdb2/tdb1_check.c index 51b8b594..edbfd86b 100644 --- a/ccan/tdb2/tdb1_check.c +++ b/ccan/tdb2/tdb1_check.c @@ -255,7 +255,7 @@ static bool tdb1_check_used_record(struct tdb1_context *tdb, if (!key.dptr) return false; - if (tdb->hash_fn(&key) != rec->full_hash) { + if ((uint32_t)tdb_hash(tdb, key.dptr, key.dsize) != rec->full_hash) { tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR, "Record offset %d has incorrect hash\n", off); goto fail_put_key; diff --git a/ccan/tdb2/tdb1_hash.c b/ccan/tdb2/tdb1_hash.c index 886577da..2d5e4961 100644 --- a/ccan/tdb2/tdb1_hash.c +++ b/ccan/tdb2/tdb1_hash.c @@ -25,14 +25,15 @@ #include "tdb1_private.h" /* This is based on the hash algorithm from gdbm */ -unsigned int tdb1_old_hash(TDB_DATA *key) +uint64_t tdb1_old_hash(const void *key, size_t len, uint64_t seed, void *unused) { uint32_t value; /* Used to compute the hash value. */ uint32_t i; /* Used to cycle through random values. */ + const unsigned char *dptr = key; /* Set the initial value from the key size. */ - for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++) - value = (value + (key->dptr[i] << (i*5 % 24))); + for (value = 0x238F13AF * len, i=0; i < len; i++) + value = (value + (dptr[i] << (i*5 % 24))); return (1103515243 * value + 12345); } @@ -339,7 +340,8 @@ static uint32_t hashlittle( const void *key, size_t length ) return c; } -unsigned int tdb1_incompatible_hash(TDB_DATA *key) +uint64_t tdb1_incompatible_hash(const void *key, size_t len, uint64_t seed, + void *unused) { - return hashlittle(key->dptr, key->dsize); + return hashlittle(key, len); } diff --git a/ccan/tdb2/tdb1_lock.c b/ccan/tdb2/tdb1_lock.c index 6498b713..65fa1c12 100644 --- a/ccan/tdb2/tdb1_lock.c +++ b/ccan/tdb2/tdb1_lock.c @@ -392,25 +392,30 @@ int tdb1_unlockall_read(struct tdb1_context *tdb) contention - it cannot guarantee how many records will be locked */ int tdb1_chainlock(struct tdb1_context *tdb, TDB_DATA key) { - int ret = tdb1_lock(tdb, TDB1_BUCKET(tdb->hash_fn(&key)), F_WRLCK); + int ret = tdb1_lock(tdb, + TDB1_BUCKET(tdb_hash(tdb, key.dptr, key.dsize)), + F_WRLCK); return ret; } int tdb1_chainunlock(struct tdb1_context *tdb, TDB_DATA key) { - return tdb1_unlock(tdb, TDB1_BUCKET(tdb->hash_fn(&key)), F_WRLCK); + return tdb1_unlock(tdb, TDB1_BUCKET(tdb_hash(tdb, key.dptr, key.dsize)), + F_WRLCK); } int tdb1_chainlock_read(struct tdb1_context *tdb, TDB_DATA key) { int ret; - ret = tdb1_lock(tdb, TDB1_BUCKET(tdb->hash_fn(&key)), F_RDLCK); + ret = tdb1_lock(tdb, TDB1_BUCKET(tdb_hash(tdb, key.dptr, key.dsize)), + F_RDLCK); return ret; } int tdb1_chainunlock_read(struct tdb1_context *tdb, TDB_DATA key) { - return tdb1_unlock(tdb, TDB1_BUCKET(tdb->hash_fn(&key)), F_RDLCK); + return tdb1_unlock(tdb, TDB1_BUCKET(tdb_hash(tdb, key.dptr, key.dsize)), + F_RDLCK); } /* record lock stops delete underneath */ diff --git a/ccan/tdb2/tdb1_open.c b/ccan/tdb2/tdb1_open.c index 1fe981ac..c01cc6e0 100644 --- a/ccan/tdb2/tdb1_open.c +++ b/ccan/tdb2/tdb1_open.c @@ -34,16 +34,10 @@ static struct tdb1_context *tdb1s = NULL; void tdb1_header_hash(struct tdb1_context *tdb, uint32_t *magic1_hash, uint32_t *magic2_hash) { - TDB_DATA hash_key; uint32_t tdb1_magic = TDB1_MAGIC; - hash_key.dptr = (unsigned char *)TDB_MAGIC_FOOD; - hash_key.dsize = sizeof(TDB_MAGIC_FOOD); - *magic1_hash = tdb->hash_fn(&hash_key); - - hash_key.dptr = (unsigned char *)TDB1_CONV(tdb1_magic); - hash_key.dsize = sizeof(tdb1_magic); - *magic2_hash = tdb->hash_fn(&hash_key); + *magic1_hash = tdb_hash(tdb, TDB_MAGIC_FOOD, sizeof(TDB_MAGIC_FOOD)); + *magic2_hash = tdb_hash(tdb, TDB1_CONV(tdb1_magic), sizeof(tdb1_magic)); /* Make sure at least one hash is non-zero! */ if (*magic1_hash == 0 && *magic2_hash == 0) @@ -223,6 +217,7 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag errno = ENOMEM; goto fail; } + tdb->hash_seed = 0; if (hash_fn) { tdb->hash_fn = hash_fn; diff --git a/ccan/tdb2/tdb1_private.h b/ccan/tdb2/tdb1_private.h index 9350076f..22a6f797 100644 --- a/ccan/tdb2/tdb1_private.h +++ b/ccan/tdb2/tdb1_private.h @@ -58,6 +58,9 @@ #define tdb_allrecord_upgrade(tdb1, start) \ tdb_allrecord_upgrade((struct tdb_context *)(tdb1), (start)) +#define tdb_hash(tdb1, ptr, len) \ + tdb_hash((struct tdb_context *)(tdb1), (ptr), (len)) + #define tdb_lock_gradual(tdb1, ltype, flags, off, len) \ tdb_lock_gradual((struct tdb_context *)(tdb1), \ (ltype), (flags), (off), (len)) @@ -209,12 +212,16 @@ struct tdb1_context { /* Our statistics. */ struct tdb_attribute_stats stats; + /* Hash function. */ + uint64_t (*hash_fn)(const void *key, size_t len, uint64_t seed, void *); + void *hash_data; + uint64_t hash_seed; + bool read_only; /* opened read-only */ int traverse_read; /* read-only traversal */ int traverse_write; /* read-write traversal */ struct tdb1_header header; /* a cached copy of the header */ struct tdb1_traverse_lock travlocks; /* current traversal locks */ - unsigned int (*hash_fn)(TDB_DATA *key); const struct tdb1_methods *methods; struct tdb1_transaction *transaction; int page_size; @@ -280,6 +287,6 @@ bool tdb1_write_all(int fd, const void *buf, size_t count); int tdb1_transaction_recover(struct tdb1_context *tdb); void tdb1_header_hash(struct tdb1_context *tdb, uint32_t *magic1_hash, uint32_t *magic2_hash); -unsigned int tdb1_old_hash(TDB_DATA *key); +uint64_t tdb1_old_hash(const void *key, size_t len, uint64_t seed, void *); size_t tdb1_dead_space(struct tdb1_context *tdb, tdb1_off_t off); #endif /* CCAN_TDB2_TDB1_PRIVATE_H */ diff --git a/ccan/tdb2/tdb1_tdb.c b/ccan/tdb2/tdb1_tdb.c index c69c61d0..8392e712 100644 --- a/ccan/tdb2/tdb1_tdb.c +++ b/ccan/tdb2/tdb1_tdb.c @@ -189,7 +189,7 @@ static TDB_DATA _tdb1_fetch(struct tdb1_context *tdb, TDB_DATA key) uint32_t hash; /* find which hash bucket it is in */ - hash = tdb->hash_fn(&key); + hash = tdb_hash(tdb, key.dptr, key.dsize); if (!(rec_ptr = tdb1_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) return tdb1_null; @@ -236,7 +236,7 @@ int tdb1_parse_record(struct tdb1_context *tdb, TDB_DATA key, uint32_t hash; /* find which hash bucket it is in */ - hash = tdb->hash_fn(&key); + hash = tdb_hash(tdb, key.dptr, key.dsize); if (!(rec_ptr = tdb1_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) { /* record not found */ @@ -270,7 +270,7 @@ static int tdb1_exists_hash(struct tdb1_context *tdb, TDB_DATA key, uint32_t has int tdb1_exists(struct tdb1_context *tdb, TDB_DATA key) { - uint32_t hash = tdb->hash_fn(&key); + uint32_t hash = tdb_hash(tdb, key.dptr, key.dsize); int ret; ret = tdb1_exists_hash(tdb, key, hash); @@ -429,7 +429,7 @@ static int tdb1_delete_hash(struct tdb1_context *tdb, TDB_DATA key, uint32_t has int tdb1_delete(struct tdb1_context *tdb, TDB_DATA key) { - uint32_t hash = tdb->hash_fn(&key); + uint32_t hash = tdb_hash(tdb, key.dptr, key.dsize); int ret; ret = tdb1_delete_hash(tdb, key, hash); @@ -607,7 +607,7 @@ int tdb1_store(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) } /* find which hash bucket it is in */ - hash = tdb->hash_fn(&key); + hash = tdb_hash(tdb, key.dptr, key.dsize); if (tdb1_lock(tdb, TDB1_BUCKET(hash), F_WRLCK) == -1) return -1; @@ -624,7 +624,7 @@ int tdb1_append(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA new_dbuf) int ret = -1; /* find which hash bucket it is in */ - hash = tdb->hash_fn(&key); + hash = tdb_hash(tdb, key.dptr, key.dsize); if (tdb1_lock(tdb, TDB1_BUCKET(hash), F_WRLCK) == -1) return -1; diff --git a/ccan/tdb2/tdb1_traverse.c b/ccan/tdb2/tdb1_traverse.c index 23897c14..8b09e387 100644 --- a/ccan/tdb2/tdb1_traverse.c +++ b/ccan/tdb2/tdb1_traverse.c @@ -331,7 +331,7 @@ TDB_DATA tdb1_nextkey(struct tdb1_context *tdb, TDB_DATA oldkey) if (!tdb->travlocks.off) { /* No previous element: do normal find, and lock record */ - tdb->travlocks.off = tdb1_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), tdb->travlocks.lock_rw, &rec); + tdb->travlocks.off = tdb1_find_lock_hash(tdb, oldkey, tdb_hash(tdb, oldkey.dptr, oldkey.dsize), tdb->travlocks.lock_rw, &rec); if (!tdb->travlocks.off) { return tdb1_null; } diff --git a/ccan/tdb2/test/run-tdb1-3G-file.c b/ccan/tdb2/test/run-tdb1-3G-file.c index 43e9f2ad..cf3db233 100644 --- a/ccan/tdb2/test/run-tdb1-3G-file.c +++ b/ccan/tdb2/test/run-tdb1-3G-file.c @@ -89,7 +89,7 @@ int main(int argc, char *argv[]) free(data.dptr); /* That currently fills at the end, make sure that's true. */ - hash = tdb->hash_fn(&key); + hash = tdb_hash(tdb, key.dptr, key.dsize); rec_ptr = tdb1_find_lock_hash(tdb, key, hash, F_RDLCK, &rec); ok1(rec_ptr); ok1(rec_ptr > 2U*1024*1024*1024); diff --git a/ccan/tdb2/test/run-tdb1-incompatible.c b/ccan/tdb2/test/run-tdb1-incompatible.c index a2754461..58e1fba1 100644 --- a/ccan/tdb2/test/run-tdb1-incompatible.c +++ b/ccan/tdb2/test/run-tdb1-incompatible.c @@ -3,9 +3,10 @@ #include #include -static unsigned int tdb1_dumb_hash(TDB_DATA *key) +static uint64_t tdb1_dumb_hash(const void *key, size_t len, uint64_t seed, + void *unused) { - return key->dsize; + return len; } static void log_fn(struct tdb1_context *tdb, enum tdb_log_level level, @@ -31,14 +32,16 @@ static unsigned int hdr_rwlocks(const char *fname) return hdr.rwlocks; } -static unsigned int jenkins_hashfn(TDB_DATA *key) +static uint64_t jenkins_hashfn(const void *key, size_t len, uint64_t seed, + void *unused) { - return hashlittle(key->dptr, key->dsize); + return hashlittle(key, len); } -static unsigned int old_hash(TDB_DATA *key) +static uint64_t old_hash(const void *key, size_t len, uint64_t seed, + void *unused) { - return tdb1_old_hash(key); + return tdb1_old_hash(key, len, seed, unused); } int main(int argc, char *argv[]) diff --git a/ccan/tdb2/test/run-tdb1-wronghash-fail.c b/ccan/tdb2/test/run-tdb1-wronghash-fail.c index 97a8293e..42bc6c02 100644 --- a/ccan/tdb2/test/run-tdb1-wronghash-fail.c +++ b/ccan/tdb2/test/run-tdb1-wronghash-fail.c @@ -11,16 +11,18 @@ static void log_fn(struct tdb1_context *tdb, enum tdb_log_level level, (*count)++; } -static unsigned int jenkins_hashfn(TDB_DATA *key) +static uint64_t jenkins_hashfn(const void *key, size_t len, uint64_t seed, + void *unused) { - return hashlittle(key->dptr, key->dsize); + return hashlittle(key, len); } /* the tdb1_old_hash function is "magic" as it automatically makes us test the * tdb1_incompatible_hash as well, so use this wrapper. */ -static unsigned int old_hash(TDB_DATA *key) +static uint64_t old_hash(const void *key, size_t len, uint64_t seed, + void *unused) { - return tdb1_old_hash(key); + return tdb1_old_hash(key, len, seed, unused); } int main(int argc, char *argv[])