From 8cca0397ef6f6017b13ce9ab4999bf3d92a2dee5 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 27 Apr 2011 23:21:32 +0930 Subject: [PATCH] tdb2: TDB_ATTRIBUTE_STATS access via tdb_get_attribute. Now we have tdb_get_attribute, it makes sense to make that the method of accessing statistics. That way they are always available, and it's probably cheaper doing the direct increment than even the unlikely() branch. --- ccan/tdb2/free.c | 22 +++---- ccan/tdb2/hash.c | 16 ++--- ccan/tdb2/io.c | 6 -- ccan/tdb2/lock.c | 8 +-- ccan/tdb2/open.c | 48 +++++++-------- ccan/tdb2/private.h | 14 +---- ccan/tdb2/tdb.c | 4 +- ccan/tdb2/tdb2.h | 10 ++-- ccan/tdb2/test/failtest_helper.h | 2 +- ccan/tdb2/test/run-91-get-stats.c | 59 +++++++++++++++++++ ccan/tdb2/tools/speed.c | 98 +++++++++++++++++-------------- ccan/tdb2/transaction.c | 2 +- 12 files changed, 166 insertions(+), 123 deletions(-) create mode 100644 ccan/tdb2/test/run-91-get-stats.c diff --git a/ccan/tdb2/free.c b/ccan/tdb2/free.c index c78d1389..e2b9cb18 100644 --- a/ccan/tdb2/free.c +++ b/ccan/tdb2/free.c @@ -342,7 +342,7 @@ static tdb_bool_err coalesce(struct tdb_context *tdb, struct tdb_free_record rec; enum TDB_ERROR ecode; - add_stat(tdb, alloc_coalesce_tried, 1); + tdb->stats.alloc_coalesce_tried++; end = off + sizeof(struct tdb_used_record) + data_len; while (end < tdb->file->map_size) { @@ -376,7 +376,7 @@ static tdb_bool_err coalesce(struct tdb_context *tdb, /* We may be violating lock order here, so best effort. */ if (tdb_lock_free_bucket(tdb, nb_off, TDB_LOCK_NOWAIT) != TDB_SUCCESS) { - add_stat(tdb, alloc_coalesce_lockfail, 1); + tdb->stats.alloc_coalesce_lockfail++; break; } @@ -388,14 +388,14 @@ static tdb_bool_err coalesce(struct tdb_context *tdb, } if (unlikely(frec_magic(&rec) != TDB_FREE_MAGIC)) { - add_stat(tdb, alloc_coalesce_race, 1); + tdb->stats.alloc_coalesce_race++; tdb_unlock_free_bucket(tdb, nb_off); break; } if (unlikely(frec_ftable(&rec) != ftable) || unlikely(size_to_bucket(frec_len(&rec)) != bucket)) { - add_stat(tdb, alloc_coalesce_race, 1); + tdb->stats.alloc_coalesce_race++; tdb_unlock_free_bucket(tdb, nb_off); break; } @@ -409,7 +409,7 @@ static tdb_bool_err coalesce(struct tdb_context *tdb, end += sizeof(struct tdb_used_record) + frec_len(&rec); tdb_unlock_free_bucket(tdb, nb_off); - add_stat(tdb, alloc_coalesce_num_merged, 1); + tdb->stats.alloc_coalesce_num_merged++; } /* Didn't find any adjacent free? */ @@ -446,7 +446,7 @@ static tdb_bool_err coalesce(struct tdb_context *tdb, goto err; } - add_stat(tdb, alloc_coalesce_succeeded, 1); + tdb->stats.alloc_coalesce_succeeded++; tdb_unlock_free_bucket(tdb, b_off); ecode = add_free_record(tdb, off, end - off); @@ -476,7 +476,7 @@ static tdb_off_t lock_and_alloc(struct tdb_context *tdb, size_t size = adjust_size(keylen, datalen); enum TDB_ERROR ecode; - add_stat(tdb, allocs, 1); + tdb->stats.allocs++; again: b_off = bucket_off(ftable_off, bucket); @@ -596,7 +596,7 @@ again: /* Bucket of leftover will be <= current bucket, so nested * locking is allowed. */ if (leftover) { - add_stat(tdb, alloc_leftover, 1); + tdb->stats.alloc_leftover++; ecode = add_free_record(tdb, best_off + sizeof(rec) + frec_len(&best) - leftover, @@ -649,9 +649,9 @@ static tdb_off_t get_free(struct tdb_context *tdb, return off; if (off != 0) { if (b == start_b) - add_stat(tdb, alloc_bucket_exact, 1); + tdb->stats.alloc_bucket_exact++; if (b == TDB_FREE_BUCKETS - 1) - add_stat(tdb, alloc_bucket_max, 1); + tdb->stats.alloc_bucket_max++; /* Worked? Stay using this list. */ tdb->ftable_off = ftable_off; tdb->ftable = ftable; @@ -758,7 +758,7 @@ static enum TDB_ERROR tdb_expand(struct tdb_context *tdb, tdb_len_t size) /* We need to drop this lock before adding free record. */ tdb_unlock_expand(tdb, F_WRLCK); - add_stat(tdb, expands, 1); + tdb->stats.expands++; return add_free_record(tdb, old_size, wanted); } diff --git a/ccan/tdb2/hash.c b/ccan/tdb2/hash.c index 745f04c8..1359cfec 100644 --- a/ccan/tdb2/hash.c +++ b/ccan/tdb2/hash.c @@ -72,7 +72,7 @@ static tdb_bool_err key_matches(struct tdb_context *tdb, const char *rkey; if (rec_key_length(rec) != key->dsize) { - add_stat(tdb, compare_wrong_keylen, 1); + tdb->stats.compare_wrong_keylen++; return ret; } @@ -83,7 +83,7 @@ static tdb_bool_err key_matches(struct tdb_context *tdb, if (memcmp(rkey, key->dptr, key->dsize) == 0) ret = true; else - add_stat(tdb, compare_wrong_keycmp, 1); + tdb->stats.compare_wrong_keycmp++; tdb_access_release(tdb, rkey); return ret; } @@ -98,10 +98,10 @@ static tdb_bool_err match(struct tdb_context *tdb, tdb_off_t off; enum TDB_ERROR ecode; - add_stat(tdb, compares, 1); + tdb->stats.compares++; /* Desired bucket must match. */ if (h->home_bucket != (val & TDB_OFF_HASH_GROUP_MASK)) { - add_stat(tdb, compare_wrong_bucket, 1); + tdb->stats.compare_wrong_bucket++; return false; } @@ -109,7 +109,7 @@ static tdb_bool_err match(struct tdb_context *tdb, if (bits_from(val, TDB_OFF_HASH_EXTRA_BIT, TDB_OFF_UPPER_STEAL_EXTRA) != bits_from(h->h, 64 - h->hash_used - TDB_OFF_UPPER_STEAL_EXTRA, TDB_OFF_UPPER_STEAL_EXTRA)) { - add_stat(tdb, compare_wrong_offsetbits, 1); + tdb->stats.compare_wrong_offsetbits++; return false; } @@ -120,7 +120,7 @@ static tdb_bool_err match(struct tdb_context *tdb, } if ((h->h & ((1 << 11)-1)) != rec_hash(rec)) { - add_stat(tdb, compare_wrong_rechash, 1); + tdb->stats.compare_wrong_rechash++; return false; } @@ -492,11 +492,11 @@ static enum TDB_ERROR expand_group(struct tdb_context *tdb, struct hash_info *h) bucket = fullest_bucket(tdb, h->group, h->home_bucket); if (h->hash_used == 64) { - add_stat(tdb, alloc_chain, 1); + tdb->stats.alloc_chain++; subsize = sizeof(struct tdb_chain); magic = TDB_CHAIN_MAGIC; } else { - add_stat(tdb, alloc_subhash, 1); + tdb->stats.alloc_subhash++; subsize = (sizeof(tdb_off_t) << TDB_SUBLEVEL_HASH_BITS); magic = TDB_HTABLE_MAGIC; } diff --git a/ccan/tdb2/io.c b/ccan/tdb2/io.c index bb3d2192..240a1c03 100644 --- a/ccan/tdb2/io.c +++ b/ccan/tdb2/io.c @@ -592,12 +592,6 @@ void tdb_inc_seqnum(struct tdb_context *tdb) } } -void add_stat_(struct tdb_context *tdb, uint64_t *s, size_t val) -{ - if ((uintptr_t)s < (uintptr_t)tdb->stats + tdb->stats->size) - *s += val; -} - static const struct tdb_methods io_methods = { tdb_read, tdb_write, diff --git a/ccan/tdb2/lock.c b/ccan/tdb2/lock.c index 2878eaee..8a338cbe 100644 --- a/ccan/tdb2/lock.c +++ b/ccan/tdb2/lock.c @@ -104,9 +104,9 @@ static int lock(struct tdb_context *tdb, tdb->file->locker = getpid(); } - add_stat(tdb, lock_lowlevel, 1); + tdb->stats.lock_lowlevel++; if (!waitflag) - add_stat(tdb, lock_nonblock, 1); + tdb->stats.lock_nonblock++; return tdb->lock_fn(tdb->file->fd, rw, off, len, waitflag, tdb->lock_data); } @@ -359,7 +359,7 @@ static enum TDB_ERROR tdb_nest_lock(struct tdb_context *tdb, return TDB_ERR_LOCK; } - add_stat(tdb, locks, 1); + tdb->stats.locks++; new_lck = find_nestlock(tdb, offset, NULL); if (new_lck) { @@ -567,7 +567,7 @@ enum TDB_ERROR tdb_allrecord_lock(struct tdb_context *tdb, int ltype, " can't upgrade a write lock"); } - add_stat(tdb, locks, 1); + tdb->stats.locks++; again: /* Lock hashes, gradually. */ ecode = tdb_lock_gradual(tdb, ltype, flags, TDB_HASH_LOCK_START, diff --git a/ccan/tdb2/open.c b/ccan/tdb2/open.c index 37e20907..1292fcc1 100644 --- a/ccan/tdb2/open.c +++ b/ccan/tdb2/open.c @@ -203,6 +203,12 @@ enum TDB_ERROR tdb_set_attribute(struct tdb_context *tdb, : attr->base.attr == TDB_ATTRIBUTE_SEED ? "TDB_ATTRIBUTE_SEED" : "TDB_ATTRIBUTE_OPENHOOK"); + case TDB_ATTRIBUTE_STATS: + return tdb->last_error + = tdb_logerr(tdb, TDB_ERR_EINVAL, + TDB_LOG_USE_ERROR, + "tdb_set_attribute:" + " cannot set TDB_ATTRIBUTE_STATS"); case TDB_ATTRIBUTE_FLOCK: tdb->lock_fn = attr->flock.lock; tdb->unlock_fn = attr->flock.unlock; @@ -252,9 +258,13 @@ enum TDB_ERROR tdb_get_attribute(struct tdb_context *tdb, TDB_LOG_USE_ERROR, "tdb_get_attribute:" " cannot get TDB_ATTRIBUTE_OPENHOOK"); - case TDB_ATTRIBUTE_STATS: - /* FIXME */ - return TDB_ERR_EINVAL; + case TDB_ATTRIBUTE_STATS: { + size_t size = attr->stats.size; + if (size > tdb->stats.size) + size = tdb->stats.size; + memcpy(&attr->stats, &tdb->stats, size); + break; + } case TDB_ATTRIBUTE_FLOCK: attr->flock.lock = tdb->lock_fn; attr->flock.unlock = tdb->unlock_fn; @@ -291,7 +301,10 @@ void tdb_unset_attribute(struct tdb_context *tdb, : "TDB_ATTRIBUTE_OPENHOOK"); break; case TDB_ATTRIBUTE_STATS: - /* FIXME */ + tdb_logerr(tdb, TDB_ERR_EINVAL, + TDB_LOG_USE_ERROR, + "tdb_unset_attribute:" + "cannot unset TDB_ATTRIBUTE_STATS"); break; case TDB_ATTRIBUTE_FLOCK: tdb->lock_fn = tdb_fcntl_lock; @@ -337,13 +350,15 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags, tdb->flags = tdb_flags; tdb->log_fn = NULL; tdb->transaction = NULL; - tdb->stats = NULL; tdb->access = NULL; tdb->last_error = TDB_SUCCESS; tdb->file = NULL; tdb->lock_fn = tdb_fcntl_lock; tdb->unlock_fn = tdb_fcntl_unlock; tdb->hash_fn = jenkins_hash; + memset(&tdb->stats, 0, sizeof(tdb->stats)); + tdb->stats.base.attr = TDB_ATTRIBUTE_STATS; + tdb->stats.size = sizeof(tdb->stats); tdb_io_init(tdb); while (attr) { @@ -355,12 +370,6 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags, case TDB_ATTRIBUTE_SEED: seed = &attr->seed; break; - case TDB_ATTRIBUTE_STATS: - tdb->stats = &attr->stats; - /* They have stats we don't know about? Tell them. */ - if (tdb->stats->size > sizeof(attr->stats)) - tdb->stats->size = sizeof(attr->stats); - break; case TDB_ATTRIBUTE_OPENHOOK: openhook = &attr->openhook; break; @@ -407,16 +416,6 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags, if (ecode != TDB_SUCCESS) { goto fail; } - if (name) { - tdb->name = strdup(name); - if (!tdb->name) { - ecode = tdb_logerr(tdb, TDB_ERR_OOM, - TDB_LOG_ERROR, - "tdb_open: failed to" - " allocate name"); - goto fail; - } - } tdb_convert(tdb, &hdr.hash_seed, sizeof(hdr.hash_seed)); tdb->hash_seed = hdr.hash_seed; tdb_ftable_init(tdb); @@ -525,13 +524,6 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags, goto fail; } - tdb->name = strdup(name); - if (!tdb->name) { - ecode = tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR, - "tdb_open: failed to allocate name"); - goto fail; - } - /* Clear any features we don't understand. */ if ((open_flags & O_ACCMODE) != O_RDONLY) { hdr.features_used &= TDB_FEATURE_MASK; diff --git a/ccan/tdb2/private.h b/ccan/tdb2/private.h index 306cb3ff..cc791b0b 100644 --- a/ccan/tdb2/private.h +++ b/ccan/tdb2/private.h @@ -358,9 +358,6 @@ struct tdb_context { /* mmap read only? */ int mmap_flags; - /* Error code for last tdb error. */ - enum TDB_ERROR ecode; - /* the flags passed to tdb_open, for tdb_reopen. */ uint32_t flags; @@ -391,7 +388,8 @@ struct tdb_context { /* IO methods: changes for transactions. */ const struct tdb_methods *methods; - struct tdb_attribute_stats *stats; + /* Our statistics. */ + struct tdb_attribute_stats stats; /* Direct access information */ struct tdb_access_hdr *access; @@ -535,14 +533,6 @@ enum TDB_ERROR tdb_read_convert(struct tdb_context *tdb, tdb_off_t off, /* Bump the seqnum (caller checks for tdb->flags & TDB_SEQNUM) */ void tdb_inc_seqnum(struct tdb_context *tdb); -/* Adds a stat, if it's in range. */ -void add_stat_(struct tdb_context *tdb, uint64_t *stat, size_t val); -#define add_stat(tdb, statname, val) \ - do { \ - if (unlikely((tdb)->stats)) \ - add_stat_((tdb), &(tdb)->stats->statname, (val)); \ - } while (0) - /* lock.c: */ /* Lock/unlock a range of hashes. */ enum TDB_ERROR tdb_lock_hashes(struct tdb_context *tdb, diff --git a/ccan/tdb2/tdb.c b/ccan/tdb2/tdb.c index 2a37f130..18cf2e93 100644 --- a/ccan/tdb2/tdb.c +++ b/ccan/tdb2/tdb.c @@ -38,7 +38,7 @@ static enum TDB_ERROR replace_data(struct tdb_context *tdb, /* We didn't like the existing one: remove it. */ if (old_off) { - add_stat(tdb, frees, 1); + tdb->stats.frees++; ecode = add_free_record(tdb, old_off, sizeof(struct tdb_used_record) + key.dsize + old_room); @@ -285,7 +285,7 @@ enum TDB_ERROR tdb_delete(struct tdb_context *tdb, struct tdb_data key) } /* Free the deleted entry. */ - add_stat(tdb, frees, 1); + tdb->stats.frees++; ecode = add_free_record(tdb, off, sizeof(struct tdb_used_record) + rec_key_length(&rec) diff --git a/ccan/tdb2/tdb2.h b/ccan/tdb2/tdb2.h index 296410e7..d9194a5e 100644 --- a/ccan/tdb2/tdb2.h +++ b/ccan/tdb2/tdb2.h @@ -729,13 +729,13 @@ struct tdb_attribute_seed { * struct tdb_attribute_stats - tdb operational statistics * * This attribute records statistics of various low-level TDB operations. - * This can be used to assist performance evaluation. + * This can be used to assist performance evaluation. This is only + * useful for tdb_get_attribute(). * * New fields will be added at the end, hence the "size" argument which - * indicates how large your structure is. If your size is larger than - * that known about by this version of tdb, the size will be reduced to - * the known structure size. Thus you can detect older versions, and - * thus know that newer stats will not be updated. + * indicates how large your structure is: it must be filled in before + * calling tdb_get_attribute(), which will overwrite it with the size + * tdb knows about. */ struct tdb_attribute_stats { struct tdb_attribute_base base; /* .attr = TDB_ATTRIBUTE_STATS */ diff --git a/ccan/tdb2/test/failtest_helper.h b/ccan/tdb2/test/failtest_helper.h index 214fcfa1..af0ee9b7 100644 --- a/ccan/tdb2/test/failtest_helper.h +++ b/ccan/tdb2/test/failtest_helper.h @@ -4,7 +4,7 @@ #include /* FIXME: Check these! */ -#define INITIAL_TDB_MALLOC "open.c", 324, FAILTEST_MALLOC +#define INITIAL_TDB_MALLOC "open.c", 337, FAILTEST_MALLOC #define URANDOM_OPEN "open.c", 45, FAILTEST_OPEN #define URANDOM_READ "open.c", 25, FAILTEST_READ diff --git a/ccan/tdb2/test/run-91-get-stats.c b/ccan/tdb2/test/run-91-get-stats.c new file mode 100644 index 00000000..795dfd66 --- /dev/null +++ b/ccan/tdb2/test/run-91-get-stats.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#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_DEFAULT, TDB_NOMMAP, + TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT }; + + plan_tests(sizeof(flags) / sizeof(flags[0]) * 11); + + for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) { + union tdb_attribute *attr; + struct tdb_data key = tdb_mkdata("key", 3); + + tdb = tdb_open("run-91-get-stats.tdb", flags[i], + O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr); + ok1(tdb); + ok1(tdb_store(tdb, key, key, TDB_REPLACE) == 0); + + /* Use malloc so valgrind will catch overruns. */ + attr = malloc(sizeof *attr); + attr->stats.base.attr = TDB_ATTRIBUTE_STATS; + attr->stats.size = sizeof(*attr); + + ok1(tdb_get_attribute(tdb, attr) == 0); + ok1(attr->stats.size == sizeof(*attr)); + ok1(attr->stats.allocs > 0); + ok1(attr->stats.expands > 0); + ok1(attr->stats.locks > 0); + free(attr); + + /* Try short one. */ + attr = malloc(offsetof(struct tdb_attribute_stats, allocs) + + sizeof(attr->stats.allocs)); + attr->stats.base.attr = TDB_ATTRIBUTE_STATS; + attr->stats.size = offsetof(struct tdb_attribute_stats, allocs) + + sizeof(attr->stats.allocs); + ok1(tdb_get_attribute(tdb, attr) == 0); + ok1(attr->stats.size == sizeof(*attr)); + ok1(attr->stats.allocs > 0); + free(attr); + ok1(tap_log_messages == 0); + + tdb_close(tdb); + + } + return exit_status(); +} diff --git a/ccan/tdb2/tools/speed.c b/ccan/tdb2/tools/speed.c index 487c056a..86c36ed8 100644 --- a/ccan/tdb2/tools/speed.c +++ b/ccan/tdb2/tools/speed.c @@ -43,55 +43,67 @@ static int count_record(struct tdb_context *tdb, return 0; } -static void dump_and_clear_stats(struct tdb_attribute_stats *stats) +static void dump_and_clear_stats(struct tdb_context **tdb, + int flags, + union tdb_attribute *attr) { + union tdb_attribute stats; + enum TDB_ERROR ecode; + + stats.base.attr = TDB_ATTRIBUTE_STATS; + stats.stats.size = sizeof(stats.stats); + ecode = tdb_get_attribute(*tdb, &stats); + if (ecode != TDB_SUCCESS) + errx(1, "Getting stats: %s", tdb_errorstr(ecode)); + printf("allocs = %llu\n", - (unsigned long long)stats->allocs); + (unsigned long long)stats.stats.allocs); printf(" alloc_subhash = %llu\n", - (unsigned long long)stats->alloc_subhash); + (unsigned long long)stats.stats.alloc_subhash); printf(" alloc_chain = %llu\n", - (unsigned long long)stats->alloc_chain); + (unsigned long long)stats.stats.alloc_chain); printf(" alloc_bucket_exact = %llu\n", - (unsigned long long)stats->alloc_bucket_exact); + (unsigned long long)stats.stats.alloc_bucket_exact); printf(" alloc_bucket_max = %llu\n", - (unsigned long long)stats->alloc_bucket_max); + (unsigned long long)stats.stats.alloc_bucket_max); printf(" alloc_leftover = %llu\n", - (unsigned long long)stats->alloc_leftover); + (unsigned long long)stats.stats.alloc_leftover); printf(" alloc_coalesce_tried = %llu\n", - (unsigned long long)stats->alloc_coalesce_tried); + (unsigned long long)stats.stats.alloc_coalesce_tried); printf(" alloc_coalesce_lockfail = %llu\n", - (unsigned long long)stats->alloc_coalesce_lockfail); + (unsigned long long)stats.stats.alloc_coalesce_lockfail); printf(" alloc_coalesce_race = %llu\n", - (unsigned long long)stats->alloc_coalesce_race); + (unsigned long long)stats.stats.alloc_coalesce_race); printf(" alloc_coalesce_succeeded = %llu\n", - (unsigned long long)stats->alloc_coalesce_succeeded); + (unsigned long long)stats.stats.alloc_coalesce_succeeded); printf(" alloc_coalesce_num_merged = %llu\n", - (unsigned long long)stats->alloc_coalesce_num_merged); + (unsigned long long)stats.stats.alloc_coalesce_num_merged); printf("compares = %llu\n", - (unsigned long long)stats->compares); + (unsigned long long)stats.stats.compares); printf(" compare_wrong_bucket = %llu\n", - (unsigned long long)stats->compare_wrong_bucket); + (unsigned long long)stats.stats.compare_wrong_bucket); printf(" compare_wrong_offsetbits = %llu\n", - (unsigned long long)stats->compare_wrong_offsetbits); + (unsigned long long)stats.stats.compare_wrong_offsetbits); printf(" compare_wrong_keylen = %llu\n", - (unsigned long long)stats->compare_wrong_keylen); + (unsigned long long)stats.stats.compare_wrong_keylen); printf(" compare_wrong_rechash = %llu\n", - (unsigned long long)stats->compare_wrong_rechash); + (unsigned long long)stats.stats.compare_wrong_rechash); printf(" compare_wrong_keycmp = %llu\n", - (unsigned long long)stats->compare_wrong_keycmp); + (unsigned long long)stats.stats.compare_wrong_keycmp); printf("expands = %llu\n", - (unsigned long long)stats->expands); + (unsigned long long)stats.stats.expands); printf("frees = %llu\n", - (unsigned long long)stats->frees); + (unsigned long long)stats.stats.frees); printf("locks = %llu\n", - (unsigned long long)stats->locks); + (unsigned long long)stats.stats.locks); printf(" lock_lowlevel = %llu\n", - (unsigned long long)stats->lock_lowlevel); + (unsigned long long)stats.stats.lock_lowlevel); printf(" lock_nonblock = %llu\n", - (unsigned long long)stats->lock_nonblock); + (unsigned long long)stats.stats.lock_nonblock); /* Now clear. */ - memset(&stats->allocs, 0, (char *)(stats+1) - (char *)&stats->allocs); + tdb_close(*tdb); + *tdb = tdb_open("/tmp/speed.tdb", flags, O_RDWR, 0, attr); } static void tdb_log(struct tdb_context *tdb, enum tdb_log_level level, @@ -109,7 +121,8 @@ int main(int argc, char *argv[]) TDB_DATA key, data; struct tdb_context *tdb; struct timeval start, stop; - union tdb_attribute seed, stats, log; + union tdb_attribute seed, log; + bool do_stats = false; enum TDB_ERROR ecode; /* Try to keep benchmarks even. */ @@ -121,11 +134,6 @@ int main(int argc, char *argv[]) log.base.next = &seed; log.log.fn = tdb_log; - memset(&stats, 0, sizeof(stats)); - stats.base.attr = TDB_ATTRIBUTE_STATS; - stats.base.next = NULL; - stats.stats.size = sizeof(stats); - if (argv[1] && strcmp(argv[1], "--internal") == 0) { flags = TDB_INTERNAL; argc--; @@ -147,7 +155,7 @@ int main(int argc, char *argv[]) argv++; } if (argv[1] && strcmp(argv[1], "--stats") == 0) { - seed.base.next = &stats; + do_stats = true; argc--; argv++; } @@ -196,8 +204,8 @@ int main(int argc, char *argv[]) printf("%s\n", sumstr); free(sumstr); } - if (seed.base.next) - dump_and_clear_stats(&stats.stats); + if (do_stats) + dump_and_clear_stats(&tdb, flags, &log); if (++stage == stopat) exit(0); @@ -228,8 +236,8 @@ int main(int argc, char *argv[]) printf("%s\n", sumstr); free(sumstr); } - if (seed.base.next) - dump_and_clear_stats(&stats.stats); + if (do_stats) + dump_and_clear_stats(&tdb, flags, &log); if (++stage == stopat) exit(0); @@ -258,8 +266,8 @@ int main(int argc, char *argv[]) printf("%s\n", sumstr); free(sumstr); } - if (seed.base.next) - dump_and_clear_stats(&stats.stats); + if (do_stats) + dump_and_clear_stats(&tdb, flags, &log); if (++stage == stopat) exit(0); @@ -286,8 +294,8 @@ int main(int argc, char *argv[]) printf("%s\n", sumstr); free(sumstr); } - if (seed.base.next) - dump_and_clear_stats(&stats.stats); + if (do_stats) + dump_and_clear_stats(&tdb, flags, &log); if (++stage == stopat) exit(0); @@ -315,8 +323,8 @@ int main(int argc, char *argv[]) printf("%s\n", sumstr); free(sumstr); } - if (seed.base.next) - dump_and_clear_stats(&stats.stats); + if (do_stats) + dump_and_clear_stats(&tdb, flags, &log); if (++stage == stopat) exit(0); @@ -344,8 +352,8 @@ int main(int argc, char *argv[]) printf("%s\n", sumstr); free(sumstr); } - if (seed.base.next) - dump_and_clear_stats(&stats.stats); + if (do_stats) + dump_and_clear_stats(&tdb, flags, &log); if (++stage == stopat) exit(0); @@ -403,8 +411,8 @@ int main(int argc, char *argv[]) printf("%s\n", sumstr); free(sumstr); } - if (seed.base.next) - dump_and_clear_stats(&stats.stats); + if (do_stats) + dump_and_clear_stats(&tdb, flags, &log); if (++stage == stopat) exit(0); diff --git a/ccan/tdb2/transaction.c b/ccan/tdb2/transaction.c index d15db106..68ae234d 100644 --- a/ccan/tdb2/transaction.c +++ b/ccan/tdb2/transaction.c @@ -682,7 +682,7 @@ static enum TDB_ERROR tdb_recovery_allocate(struct tdb_context *tdb, us an area that is being currently used (as of the start of the transaction) */ if (recovery_head != 0) { - add_stat(tdb, frees, 1); + tdb->stats.frees++; ecode = add_free_record(tdb, recovery_head, sizeof(rec) + rec.max_len); if (ecode != TDB_SUCCESS) { -- 2.39.2