From: Rusty Russell Date: Thu, 26 Aug 2010 12:27:32 +0000 (+0930) Subject: tdb2: delete and fetch now work. X-Git-Url: https://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=dbf1ac48c3a1f5147dfcd457a7847a03de26a6c7 tdb2: delete and fetch now work. --- diff --git a/ccan/tdb2/tdb.c b/ccan/tdb2/tdb.c index 151eebe9..61791c9d 100644 --- a/ccan/tdb2/tdb.c +++ b/ccan/tdb2/tdb.c @@ -842,23 +842,24 @@ delete: goto unlock_err; /* 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; uint64_t h2; - off2 = tdb_read_off(tdb, hash_off(tdb, i)); + off2 = tdb_read_off(tdb, i); if (unlikely(off2 == TDB_OFF_ERR)) goto unlock_err; /* Maybe use a bit to indicate it is in ideal place? */ h2 = hash_record(tdb, off2); /* 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; /* Remove it. */ - if (tdb_write_off(tdb, hash_off(tdb, i), 0) == -1) + if (tdb_write_off(tdb, i, 0) == -1) goto unlock_err; /* Rehash it. */ diff --git a/ccan/tdb2/test/logging.h b/ccan/tdb2/test/logging.h index c7a5f112..b8550df9 100644 --- a/ccan/tdb2/test/logging.h +++ b/ccan/tdb2/test/logging.h @@ -1,10 +1,19 @@ #ifndef TDB2_TEST_LOGGING_H #define TDB2_TEST_LOGGING_H #include +#include +#include + unsigned tap_log_messages; void tap_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, void *priv, 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 */ diff --git a/ccan/tdb2/test/run-simple-delete.c b/ccan/tdb2/test/run-simple-delete.c new file mode 100644 index 00000000..37e9a462 --- /dev/null +++ b/ccan/tdb2/test/run-simple-delete.c @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include +#include +#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(); +} diff --git a/ccan/tdb2/test/run-simple-fetch.c b/ccan/tdb2/test/run-simple-fetch.c new file mode 100644 index 00000000..18028442 --- /dev/null +++ b/ccan/tdb2/test/run-simple-fetch.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include +#include +#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(); +}