Commit 3e46dde2 authored by Rusty Russell's avatar Rusty Russell

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.
parent 8458811a
...@@ -356,14 +356,14 @@ struct tdb_context { ...@@ -356,14 +356,14 @@ struct tdb_context {
/* Our statistics. */ /* Our statistics. */
struct tdb_attribute_stats stats; struct tdb_attribute_stats stats;
/* Are we accessing directly? (debugging check). */
int direct_access;
/* Hash function. */ /* Hash function. */
uint64_t (*hash_fn)(const void *key, size_t len, uint64_t seed, void *); uint64_t (*hash_fn)(const void *key, size_t len, uint64_t seed, void *);
void *hash_data; void *hash_data;
uint64_t hash_seed; uint64_t hash_seed;
/* Are we accessing directly? (debugging check). */
int direct_access;
/* Set if we are in a transaction. */ /* Set if we are in a transaction. */
struct tdb_transaction *transaction; struct tdb_transaction *transaction;
......
...@@ -42,7 +42,8 @@ typedef struct tdb1_context TDB1_CONTEXT; ...@@ -42,7 +42,8 @@ typedef struct tdb1_context TDB1_CONTEXT;
typedef int (*tdb1_traverse_func)(struct tdb1_context *, TDB_DATA, TDB_DATA, void *); 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, typedef void (*tdb1_log_func)(struct tdb1_context *, enum tdb_log_level, enum TDB_ERROR,
const char *, void *); 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 { struct tdb1_logging_context {
tdb1_log_func log_fn; tdb1_log_func log_fn;
...@@ -106,7 +107,7 @@ int tdb1_hash_size(struct tdb1_context *tdb); ...@@ -106,7 +107,7 @@ int tdb1_hash_size(struct tdb1_context *tdb);
void tdb1_increment_seqnum_nonblock(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 tdb1_check(struct tdb1_context *tdb,
int (*check) (TDB_DATA key, TDB_DATA data, void *private_data), int (*check) (TDB_DATA key, TDB_DATA data, void *private_data),
......
...@@ -255,7 +255,7 @@ static bool tdb1_check_used_record(struct tdb1_context *tdb, ...@@ -255,7 +255,7 @@ static bool tdb1_check_used_record(struct tdb1_context *tdb,
if (!key.dptr) if (!key.dptr)
return false; 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, tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
"Record offset %d has incorrect hash\n", off); "Record offset %d has incorrect hash\n", off);
goto fail_put_key; goto fail_put_key;
......
...@@ -25,14 +25,15 @@ ...@@ -25,14 +25,15 @@
#include "tdb1_private.h" #include "tdb1_private.h"
/* This is based on the hash algorithm from gdbm */ /* 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 value; /* Used to compute the hash value. */
uint32_t i; /* Used to cycle through random values. */ uint32_t i; /* Used to cycle through random values. */
const unsigned char *dptr = key;
/* Set the initial value from the key size. */ /* Set the initial value from the key size. */
for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++) for (value = 0x238F13AF * len, i=0; i < len; i++)
value = (value + (key->dptr[i] << (i*5 % 24))); value = (value + (dptr[i] << (i*5 % 24)));
return (1103515243 * value + 12345); return (1103515243 * value + 12345);
} }
...@@ -339,7 +340,8 @@ static uint32_t hashlittle( const void *key, size_t length ) ...@@ -339,7 +340,8 @@ static uint32_t hashlittle( const void *key, size_t length )
return c; 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);
} }
...@@ -392,25 +392,30 @@ int tdb1_unlockall_read(struct tdb1_context *tdb) ...@@ -392,25 +392,30 @@ int tdb1_unlockall_read(struct tdb1_context *tdb)
contention - it cannot guarantee how many records will be locked */ contention - it cannot guarantee how many records will be locked */
int tdb1_chainlock(struct tdb1_context *tdb, TDB_DATA key) 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; return ret;
} }
int tdb1_chainunlock(struct tdb1_context *tdb, TDB_DATA key) 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 tdb1_chainlock_read(struct tdb1_context *tdb, TDB_DATA key)
{ {
int ret; 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; return ret;
} }
int tdb1_chainunlock_read(struct tdb1_context *tdb, TDB_DATA key) 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 */ /* record lock stops delete underneath */
......
...@@ -34,16 +34,10 @@ static struct tdb1_context *tdb1s = NULL; ...@@ -34,16 +34,10 @@ static struct tdb1_context *tdb1s = NULL;
void tdb1_header_hash(struct tdb1_context *tdb, void tdb1_header_hash(struct tdb1_context *tdb,
uint32_t *magic1_hash, uint32_t *magic2_hash) uint32_t *magic1_hash, uint32_t *magic2_hash)
{ {
TDB_DATA hash_key;
uint32_t tdb1_magic = TDB1_MAGIC; uint32_t tdb1_magic = TDB1_MAGIC;
hash_key.dptr = (unsigned char *)TDB_MAGIC_FOOD; *magic1_hash = tdb_hash(tdb, TDB_MAGIC_FOOD, sizeof(TDB_MAGIC_FOOD));
hash_key.dsize = sizeof(TDB_MAGIC_FOOD); *magic2_hash = tdb_hash(tdb, TDB1_CONV(tdb1_magic), sizeof(tdb1_magic));
*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);
/* Make sure at least one hash is non-zero! */ /* Make sure at least one hash is non-zero! */
if (*magic1_hash == 0 && *magic2_hash == 0) 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 ...@@ -223,6 +217,7 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
errno = ENOMEM; errno = ENOMEM;
goto fail; goto fail;
} }
tdb->hash_seed = 0;
if (hash_fn) { if (hash_fn) {
tdb->hash_fn = hash_fn; tdb->hash_fn = hash_fn;
......
...@@ -58,6 +58,9 @@ ...@@ -58,6 +58,9 @@
#define tdb_allrecord_upgrade(tdb1, start) \ #define tdb_allrecord_upgrade(tdb1, start) \
tdb_allrecord_upgrade((struct tdb_context *)(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) \ #define tdb_lock_gradual(tdb1, ltype, flags, off, len) \
tdb_lock_gradual((struct tdb_context *)(tdb1), \ tdb_lock_gradual((struct tdb_context *)(tdb1), \
(ltype), (flags), (off), (len)) (ltype), (flags), (off), (len))
...@@ -209,12 +212,16 @@ struct tdb1_context { ...@@ -209,12 +212,16 @@ struct tdb1_context {
/* Our statistics. */ /* Our statistics. */
struct tdb_attribute_stats stats; 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 */ bool read_only; /* opened read-only */
int traverse_read; /* read-only traversal */ int traverse_read; /* read-only traversal */
int traverse_write; /* read-write traversal */ int traverse_write; /* read-write traversal */
struct tdb1_header header; /* a cached copy of the header */ struct tdb1_header header; /* a cached copy of the header */
struct tdb1_traverse_lock travlocks; /* current traversal locks */ struct tdb1_traverse_lock travlocks; /* current traversal locks */
unsigned int (*hash_fn)(TDB_DATA *key);
const struct tdb1_methods *methods; const struct tdb1_methods *methods;
struct tdb1_transaction *transaction; struct tdb1_transaction *transaction;
int page_size; int page_size;
...@@ -280,6 +287,6 @@ bool tdb1_write_all(int fd, const void *buf, size_t count); ...@@ -280,6 +287,6 @@ bool tdb1_write_all(int fd, const void *buf, size_t count);
int tdb1_transaction_recover(struct tdb1_context *tdb); int tdb1_transaction_recover(struct tdb1_context *tdb);
void tdb1_header_hash(struct tdb1_context *tdb, void tdb1_header_hash(struct tdb1_context *tdb,
uint32_t *magic1_hash, uint32_t *magic2_hash); 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); size_t tdb1_dead_space(struct tdb1_context *tdb, tdb1_off_t off);
#endif /* CCAN_TDB2_TDB1_PRIVATE_H */ #endif /* CCAN_TDB2_TDB1_PRIVATE_H */
...@@ -189,7 +189,7 @@ static TDB_DATA _tdb1_fetch(struct tdb1_context *tdb, TDB_DATA key) ...@@ -189,7 +189,7 @@ static TDB_DATA _tdb1_fetch(struct tdb1_context *tdb, TDB_DATA key)
uint32_t hash; uint32_t hash;
/* find which hash bucket it is in */ /* 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))) if (!(rec_ptr = tdb1_find_lock_hash(tdb,key,hash,F_RDLCK,&rec)))
return tdb1_null; return tdb1_null;
...@@ -236,7 +236,7 @@ int tdb1_parse_record(struct tdb1_context *tdb, TDB_DATA key, ...@@ -236,7 +236,7 @@ int tdb1_parse_record(struct tdb1_context *tdb, TDB_DATA key,
uint32_t hash; uint32_t hash;
/* find which hash bucket it is in */ /* 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))) { if (!(rec_ptr = tdb1_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) {
/* record not found */ /* record not found */
...@@ -270,7 +270,7 @@ static int tdb1_exists_hash(struct tdb1_context *tdb, TDB_DATA key, uint32_t has ...@@ -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) 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; int ret;
ret = tdb1_exists_hash(tdb, key, hash); 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 ...@@ -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) 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; int ret;
ret = tdb1_delete_hash(tdb, key, hash); 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) ...@@ -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 */ /* 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) if (tdb1_lock(tdb, TDB1_BUCKET(hash), F_WRLCK) == -1)
return -1; return -1;
...@@ -624,7 +624,7 @@ int tdb1_append(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA new_dbuf) ...@@ -624,7 +624,7 @@ int tdb1_append(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
int ret = -1; int ret = -1;
/* find which hash bucket it is in */ /* 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) if (tdb1_lock(tdb, TDB1_BUCKET(hash), F_WRLCK) == -1)
return -1; return -1;
......
...@@ -331,7 +331,7 @@ TDB_DATA tdb1_nextkey(struct tdb1_context *tdb, TDB_DATA oldkey) ...@@ -331,7 +331,7 @@ TDB_DATA tdb1_nextkey(struct tdb1_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 = 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) { if (!tdb->travlocks.off) {
return tdb1_null; return tdb1_null;
} }
......
...@@ -89,7 +89,7 @@ int main(int argc, char *argv[]) ...@@ -89,7 +89,7 @@ int main(int argc, char *argv[])
free(data.dptr); free(data.dptr);
/* That currently fills at the end, make sure that's true. */ /* 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); rec_ptr = tdb1_find_lock_hash(tdb, key, hash, F_RDLCK, &rec);
ok1(rec_ptr); ok1(rec_ptr);
ok1(rec_ptr > 2U*1024*1024*1024); ok1(rec_ptr > 2U*1024*1024*1024);
......
...@@ -3,9 +3,10 @@ ...@@ -3,9 +3,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <err.h> #include <err.h>
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, 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) ...@@ -31,14 +32,16 @@ static unsigned int hdr_rwlocks(const char *fname)
return hdr.rwlocks; 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[]) int main(int argc, char *argv[])
......
...@@ -11,16 +11,18 @@ static void log_fn(struct tdb1_context *tdb, enum tdb_log_level level, ...@@ -11,16 +11,18 @@ static void log_fn(struct tdb1_context *tdb, enum tdb_log_level level,
(*count)++; (*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 /* the tdb1_old_hash function is "magic" as it automatically makes us test the
* tdb1_incompatible_hash as well, so use this wrapper. */ * 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[]) int main(int argc, char *argv[])
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment