tdb2: Make TDB1 use the same tdb_hash() wrapper as TDB2
authorRusty Russell <rusty@rustcorp.com.au>
Wed, 31 Aug 2011 05:57:16 +0000 (15:27 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Wed, 31 Aug 2011 05:57:16 +0000 (15:27 +0930)
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.

12 files changed:
ccan/tdb2/private.h
ccan/tdb2/tdb1.h
ccan/tdb2/tdb1_check.c
ccan/tdb2/tdb1_hash.c
ccan/tdb2/tdb1_lock.c
ccan/tdb2/tdb1_open.c
ccan/tdb2/tdb1_private.h
ccan/tdb2/tdb1_tdb.c
ccan/tdb2/tdb1_traverse.c
ccan/tdb2/test/run-tdb1-3G-file.c
ccan/tdb2/test/run-tdb1-incompatible.c
ccan/tdb2/test/run-tdb1-wronghash-fail.c

index fdd505357433fadf607c98d96f385530b509ba6f..cd52542bed1199ee86aa876fca8e0d8984d57966 100644 (file)
@@ -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;
        
index 67e00c7c86a9737bad073769ba0f4d5f3f21c2fc..5227bbbbc8edf16ab99ba271ba0c52f169cba253 100644 (file)
@@ -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),
index 51b8b594f414bb5539ddaa09dacbccee2ab9b220..edbfd86bcfe1041168931f6102e014d3e6c58bbf 100644 (file)
@@ -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;
index 886577da7020eefc355c87278c72845892523e9c..2d5e4961a30b78ecca2da21fb006a1c71a85c253 100644 (file)
 #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);
 }
index 6498b7136726bf6083e774315bd4455caf9dde9a..65fa1c123c5086b208448ee0dcb8487f1073d965 100644 (file)
@@ -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 */
index 1fe981ac76b2a7f688ad6c4c70f534235f4e3001..c01cc6e0614ecf2604020c4a55fcb6ed40935661 100644 (file)
@@ -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;
index 9350076f27d08a76e45be3de46a117c90af678cd..22a6f7972f2c89219f4a7eb99af00087f0634d98 100644 (file)
@@ -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 */
index c69c61d0c0663f85e9eac8522a0d51c6080c0db5..8392e71240f33c70e1747d62b06ad9ba71df4c52 100644 (file)
@@ -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;
 
index 23897c14419e6ec55212c1810944489f52265945..8b09e3874a966d54bd266d92d5894e8fea6cc63a 100644 (file)
@@ -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;
                }
index 43e9f2ad9bd831f847acfe954ab3e6305315b207..cf3db233218d8e034559ac0d374f67295d3fdf94 100644 (file)
@@ -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);
index a2754461e26c515df9807f95947a7ff1233a13b2..58e1fba1fa5dc35447bbe01aa7ad97faac5c8bf6 100644 (file)
@@ -3,9 +3,10 @@
 #include <stdlib.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,
@@ -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[])
index 97a8293e7d255e5ea1bd1877e6608769e714d07b..42bc6c02f4dcb36cd456b17491fb9ce932b52a16 100644 (file)
@@ -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[])