Browse Source

tdb2: delete and fetch now work.

Rusty Russell 15 years ago
parent
commit
dbf1ac48c3

+ 6 - 5
ccan/tdb2/tdb.c

@@ -842,23 +842,24 @@ delete:
 		goto unlock_err;
 		goto unlock_err;
 
 
 	/* Rehash anything following. */
 	/* Rehash anything following. */
-	for (i = old_bucket+1; i < h + num_locks; i++) {
+	for (i = hash_off(tdb, old_bucket+1);
+	     i != hash_off(tdb, h + num_locks);
+	     i += sizeof(tdb_off_t)) {
 		tdb_off_t off2;
 		tdb_off_t off2;
 		uint64_t h2;
 		uint64_t h2;
 
 
-		off2 = tdb_read_off(tdb, hash_off(tdb, i));
+		off2 = tdb_read_off(tdb, i);
 		if (unlikely(off2 == TDB_OFF_ERR))
 		if (unlikely(off2 == TDB_OFF_ERR))
 			goto unlock_err;
 			goto unlock_err;
 
 
 		/* Maybe use a bit to indicate it is in ideal place? */
 		/* Maybe use a bit to indicate it is in ideal place? */
 		h2 = hash_record(tdb, off2);
 		h2 = hash_record(tdb, off2);
 		/* Is it happy where it is? */
 		/* Is it happy where it is? */
-		if ((h2 & ((1ULL << tdb->header.v.hash_bits)-1))
-		    == (i & ((1ULL << tdb->header.v.hash_bits)-1)))
+		if (hash_off(tdb, h2) == i)
 			continue;
 			continue;
 
 
 		/* Remove it. */
 		/* Remove it. */
-		if (tdb_write_off(tdb, hash_off(tdb, i), 0) == -1)
+		if (tdb_write_off(tdb, i, 0) == -1)
 			goto unlock_err;
 			goto unlock_err;
 
 
 		/* Rehash it. */
 		/* Rehash it. */

+ 9 - 0
ccan/tdb2/test/logging.h

@@ -1,10 +1,19 @@
 #ifndef TDB2_TEST_LOGGING_H
 #ifndef TDB2_TEST_LOGGING_H
 #define TDB2_TEST_LOGGING_H
 #define TDB2_TEST_LOGGING_H
 #include <ccan/tdb2/tdb2.h>
 #include <ccan/tdb2/tdb2.h>
+#include <stdbool.h>
+#include <string.h>
+
 unsigned tap_log_messages;
 unsigned tap_log_messages;
 
 
 void tap_log_fn(struct tdb_context *tdb,
 void tap_log_fn(struct tdb_context *tdb,
 		enum tdb_debug_level level, void *priv,
 		enum tdb_debug_level level, void *priv,
 		const char *fmt, ...);
 		const char *fmt, ...);
 
 
+static inline bool data_equal(struct tdb_data a, struct tdb_data b)
+{
+	if (a.dsize != b.dsize)
+		return false;
+	return memcmp(a.dptr, b.dptr, a.dsize) == 0;
+}
 #endif /* TDB2_TEST_LOGGING_H */
 #endif /* TDB2_TEST_LOGGING_H */

+ 40 - 0
ccan/tdb2/test/run-simple-delete.c

@@ -0,0 +1,40 @@
+#include <ccan/tdb2/tdb.c>
+#include <ccan/tdb2/free.c>
+#include <ccan/tdb2/lock.c>
+#include <ccan/tdb2/io.c>
+#include <ccan/tdb2/check.c>
+#include <ccan/tap/tap.h>
+#include "logging.h"
+
+int main(int argc, char *argv[])
+{
+	unsigned int i;
+	struct tdb_context *tdb;
+	int flags[] = { TDB_INTERNAL, TDB_DEFAULT,
+			TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT };
+	struct tdb_data key = { (unsigned char *)"key", 3 };
+	struct tdb_data data = { (unsigned char *)"data", 4 };
+
+	plan_tests(sizeof(flags) / sizeof(flags[0]) * 8 + 1);
+	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+		tdb = tdb_open("/tmp/run-new_database.tdb", flags[i],
+			       O_RDWR|O_CREAT|O_TRUNC, 0600, NULL);
+		tdb->log = tap_log_fn;
+		ok1(tdb);
+		if (tdb) {
+			/* Delete should fail. */
+			ok1(tdb_delete(tdb, key) == -1);
+			ok1(tdb_error(tdb) == TDB_ERR_NOEXIST);
+			ok1(tdb_check(tdb, NULL, NULL) == 0);
+			/* Insert should succeed. */
+			ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
+			ok1(tdb_check(tdb, NULL, NULL) == 0);
+			/* Delete should now work. */
+			ok1(tdb_delete(tdb, key) == 0);
+			ok1(tdb_check(tdb, NULL, NULL) == 0);
+			tdb_close(tdb);
+		}
+	}
+	ok1(tap_log_messages == 0);
+	return exit_status();
+}

+ 44 - 0
ccan/tdb2/test/run-simple-fetch.c

@@ -0,0 +1,44 @@
+#include <ccan/tdb2/tdb.c>
+#include <ccan/tdb2/free.c>
+#include <ccan/tdb2/lock.c>
+#include <ccan/tdb2/io.c>
+#include <ccan/tdb2/check.c>
+#include <ccan/tap/tap.h>
+#include "logging.h"
+
+int main(int argc, char *argv[])
+{
+	unsigned int i;
+	struct tdb_context *tdb;
+	int flags[] = { TDB_INTERNAL, TDB_DEFAULT,
+			TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT };
+	struct tdb_data key = { (unsigned char *)"key", 3 };
+	struct tdb_data data = { (unsigned char *)"data", 4 };
+
+	plan_tests(sizeof(flags) / sizeof(flags[0]) * 8 + 1);
+	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+		tdb = tdb_open("/tmp/run-new_database.tdb", flags[i],
+			       O_RDWR|O_CREAT|O_TRUNC, 0600, NULL);
+		tdb->log = tap_log_fn;
+		ok1(tdb);
+		if (tdb) {
+			struct tdb_data d;
+
+			/* fetch should fail. */
+			d = tdb_fetch(tdb, key);
+			ok1(d.dptr == NULL);
+			ok1(tdb_error(tdb) == TDB_ERR_NOEXIST);
+			ok1(tdb_check(tdb, NULL, NULL) == 0);
+			/* Insert should succeed. */
+			ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
+			ok1(tdb_check(tdb, NULL, NULL) == 0);
+			/* Fetch should now work. */
+			d = tdb_fetch(tdb, key);
+			ok1(data_equal(d, data));
+			ok1(tdb_check(tdb, NULL, NULL) == 0);
+			tdb_close(tdb);
+		}
+	}
+	ok1(tap_log_messages == 0);
+	return exit_status();
+}