Browse Source

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.
Rusty Russell 14 years ago
parent
commit
3e46dde212

+ 3 - 3
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;
 	

+ 3 - 2
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),

+ 1 - 1
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;

+ 7 - 5
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);
 }

+ 9 - 4
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 */

+ 3 - 8
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;

+ 9 - 2
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 */

+ 6 - 6
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;
 

+ 1 - 1
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;
 		}

+ 1 - 1
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);

+ 9 - 6
ccan/tdb2/test/run-tdb1-incompatible.c

@@ -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[])

+ 6 - 4
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[])