int main(int argc, char *argv[]) { struct tdb_context *tdb; TDB_DATA key, data; plan_tests(11); tdb = tdb_open_ex("run-readonly-check.tdb", 1024, TDB_DEFAULT, O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); ok1(tdb); key.dsize = strlen("hi"); key.dptr = discard_const_p(uint8_t, "hi"); data.dsize = strlen("world"); data.dptr = discard_const_p(uint8_t, "world"); ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); /* We are also allowed to do a check inside a transaction. */ ok1(tdb_transaction_start(tdb) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); ok1(tdb_close(tdb) == 0); tdb = tdb_open_ex("run-readonly-check.tdb", 1024, TDB_DEFAULT, O_RDONLY, 0, &taplogctx, NULL); ok1(tdb); ok1(tdb_store(tdb, key, data, TDB_MODIFY) == -1); ok1(tdb_error(tdb) == TDB_ERR_RDONLY); ok1(tdb_check(tdb, NULL, NULL) == 0); ok1(tdb_close(tdb) == 0); return exit_status(); }
int main(int argc, char *argv[]) { unsigned int i; struct tdb_context *tdb; int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP, TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT, TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1, TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1, TDB_CONVERT|TDB_VERSION1, TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 }; struct tdb_data key = tdb_mkdata("key", 3); struct tdb_data data = tdb_mkdata("data", 4); failtest_init(argc, argv); failtest_hook = block_repeat_failures; failtest_exit_check = exit_check_log; failtest_suppress = true; plan_tests(sizeof(flags) / sizeof(flags[0]) * 8 + 1); for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) { tdb = tdb_open("run-11-simple-fetch.tdb", flags[i], O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr); ok1(tdb); if (tdb) { struct tdb_data d = { NULL, 0 }; /* Bogus GCC warning */ /* fetch should fail. */ failtest_suppress = false; if (!ok1(tdb_fetch(tdb, key, &d) == TDB_ERR_NOEXIST)) goto fail; failtest_suppress = true; 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. */ failtest_suppress = false; if (!ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS)) goto fail; failtest_suppress = true; ok1(tdb_deq(d, data)); free(d.dptr); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); } } ok1(tap_log_messages == 0); failtest_exit(exit_status()); fail: failtest_suppress = true; tdb_close(tdb); failtest_exit(exit_status()); }
int main(int argc, char *argv[]) { unsigned int i; uint64_t val; struct tdb_context *tdb; int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP, TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT }; plan_tests(sizeof(flags) / sizeof(flags[0]) * 11 + 1); failtest_init(argc, argv); failtest_hook = block_repeat_failures; failtest_exit_check = exit_check_log; for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) { failtest_suppress = true; tdb = tdb_open("run-expand.tdb", flags[i], O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr); if (!ok1(tdb)) break; val = tdb->file->map_size; /* Need some hash lock for expand. */ ok1(tdb_lock_hashes(tdb, 0, 1, F_WRLCK, TDB_LOCK_WAIT) == 0); failtest_suppress = false; if (!ok1(tdb_expand(tdb, 1) == 0)) { failtest_suppress = true; tdb_close(tdb); break; } failtest_suppress = true; ok1(tdb->file->map_size >= val + 1 * TDB_EXTENSION_FACTOR); ok1(tdb_unlock_hashes(tdb, 0, 1, F_WRLCK) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); val = tdb->file->map_size; ok1(tdb_lock_hashes(tdb, 0, 1, F_WRLCK, TDB_LOCK_WAIT) == 0); failtest_suppress = false; if (!ok1(tdb_expand(tdb, 1024) == 0)) { failtest_suppress = true; tdb_close(tdb); break; } failtest_suppress = true; ok1(tdb_unlock_hashes(tdb, 0, 1, F_WRLCK) == 0); ok1(tdb->file->map_size >= val + 1024 * TDB_EXTENSION_FACTOR); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); } ok1(tap_log_messages == 0); failtest_exit(exit_status()); }
int main(int argc, char *argv[]) { unsigned int i, j; struct tdb_context *tdb; int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP, TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT }; plan_tests(sizeof(flags) / sizeof(flags[0]) * 4 + 1); for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) { bool array[NUM_RECORDS]; tdb = tdb_open("run-check-callback.tdb", flags[i], O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr); ok1(tdb); if (!tdb) continue; ok1(store_records(tdb)); for (j = 0; j < NUM_RECORDS; j++) array[j] = false; ok1(tdb_check(tdb, check, array) == TDB_SUCCESS); for (j = 0; j < NUM_RECORDS; j++) if (!array[j]) break; ok1(j == NUM_RECORDS); tdb_close(tdb); } ok1(tap_log_messages == 0); return exit_status(); }
int main(int argc, char *argv[]) { unsigned int i; bool found[NUM_TESTS]; struct tdb_context *tdb; int flags[] = { TDB_DEFAULT, TDB_NOMMAP, TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT, TDB_VERSION1, TDB_VERSION1|TDB_NOMMAP, TDB_VERSION1|TDB_CONVERT, TDB_VERSION1|TDB_NOMMAP|TDB_CONVERT }; plan_tests(sizeof(flags) / sizeof(flags[0]) * 6 + 1); for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) { tdb = tdb_open("run-93-repack.tdb", flags[i], O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr); ok1(tdb); if (!tdb) break; ok1(store_all(tdb)); ok1(tdb_repack(tdb) == TDB_SUCCESS); memset(found, 0, sizeof(found)); ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS); ok1(tdb_traverse(tdb, mark_entry, found) == NUM_TESTS); ok1(is_all_set(found, NUM_TESTS)); tdb_close(tdb); } ok1(tap_log_messages == 0); return exit_status(); }
int main(int argc, char *argv[]) { tdb_off_t off; struct tdb_context *tdb; struct tdb_layout *layout; TDB_DATA key, data; plan_tests(11); key.dptr = (unsigned char *)"Hello"; data.dptr = (unsigned char *)"world"; data.dsize = 5; key.dsize = 5; /* Create a TDB with three free tables. */ layout = new_tdb_layout(NULL); tdb_layout_add_freetable(layout); tdb_layout_add_freetable(layout); tdb_layout_add_freetable(layout); tdb_layout_add_free(layout, 80, 0); /* Used record prevent coalescing. */ tdb_layout_add_used(layout, key, data, 6); tdb_layout_add_free(layout, 160, 1); key.dsize--; tdb_layout_add_used(layout, key, data, 7); tdb_layout_add_free(layout, 320, 2); key.dsize--; tdb_layout_add_used(layout, key, data, 8); tdb_layout_add_free(layout, 40, 0); tdb = tdb_layout_get(layout); ok1(tdb_check(tdb, NULL, NULL) == 0); off = get_free(tdb, 0, 80 - sizeof(struct tdb_used_record), 0, TDB_USED_MAGIC, 0); ok1(off == layout->elem[3].base.off); ok1(tdb->ftable_off == layout->elem[0].base.off); off = get_free(tdb, 0, 160 - sizeof(struct tdb_used_record), 0, TDB_USED_MAGIC, 0); ok1(off == layout->elem[5].base.off); ok1(tdb->ftable_off == layout->elem[1].base.off); off = get_free(tdb, 0, 320 - sizeof(struct tdb_used_record), 0, TDB_USED_MAGIC, 0); ok1(off == layout->elem[7].base.off); ok1(tdb->ftable_off == layout->elem[2].base.off); off = get_free(tdb, 0, 40 - sizeof(struct tdb_used_record), 0, TDB_USED_MAGIC, 0); ok1(off == layout->elem[9].base.off); ok1(tdb->ftable_off == layout->elem[0].base.off); /* Now we fail. */ off = get_free(tdb, 0, 0, 1, TDB_USED_MAGIC, 0); ok1(off == 0); tdb_close(tdb); ok1(tap_log_messages == 0); return exit_status(); }
static void check_db(struct tdb_context *the_tdb) { if (!the_tdb) { printf("Error: No database opened!\n"); } else { if (tdb_check(the_tdb, NULL, NULL) != 0) printf("Integrity check for the opened database failed.\n"); else printf("Database integrity is OK.\n"); } }
static void check_db(TDB_CONTEXT *the_tdb) { if (!the_tdb) { printf("Error: No database opened!\n"); } else { if (tdb_check(the_tdb, NULL, NULL) == -1) printf("Integrity check for the opened database failed.\n"); else printf("Database integrity is OK.\n"); } }
static void check_db(TDB_CONTEXT *the_tdb) { int tdbcount = 0; if (!the_tdb) printf("Error: No database opened!\n"); else if (tdb_check(the_tdb, count, &tdbcount) == -1) printf("Integrity check for the opened database failed.\n"); else printf("Database integrity is OK and has %d records.\n", tdbcount); }
bool netsamlogon_cache_init(void) { bool first_try = true; char *path = NULL; int ret; struct tdb_context *tdb; if (netsamlogon_tdb) { return true; } path = cache_path(NETSAMLOGON_TDB); if (path == NULL) { return false; } again: tdb = tdb_open_log(path, 0, TDB_DEFAULT|TDB_INCOMPATIBLE_HASH, O_RDWR | O_CREAT, 0600); if (tdb == NULL) { DEBUG(0,("tdb_open_log('%s') - failed\n", path)); goto clear; } ret = tdb_check(tdb, NULL, NULL); if (ret != 0) { tdb_close(tdb); DEBUG(0,("tdb_check('%s') - failed\n", path)); goto clear; } netsamlogon_tdb = tdb; talloc_free(path); return true; clear: if (!first_try) { talloc_free(path); return false; } first_try = false; DEBUG(0,("retry after truncate for '%s'\n", path)); ret = truncate(path, 0); if (ret == -1) { DBG_ERR("truncate failed: %s\n", strerror(errno)); talloc_free(path); return false; } goto again; }
int main(int argc, char *argv[]) { unsigned int i, j; struct tdb_context *tdb; int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP, TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT }; plan_tests(sizeof(flags) / sizeof(flags[0]) * 9 + 1); for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) { TDB_DATA k; uint64_t size; bool was_empty = false; k.dptr = (void *)&j; k.dsize = sizeof(j); tdb = tdb_open("run-30-exhaust-before-expand.tdb", flags[i], O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr); ok1(tdb); if (!tdb) continue; ok1(empty_freetable(tdb)); /* Need some hash lock for expand. */ ok1(tdb_lock_hashes(tdb, 0, 1, F_WRLCK, TDB_LOCK_WAIT) == 0); /* Create some free space. */ ok1(tdb_expand(tdb, 1) == 0); ok1(tdb_unlock_hashes(tdb, 0, 1, F_WRLCK) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); ok1(!empty_freetable(tdb)); size = tdb->map_size; /* Insert minimal-length records until we expand. */ for (j = 0; tdb->map_size == size; j++) { was_empty = empty_freetable(tdb); if (tdb_store(tdb, k, k, TDB_INSERT) != 0) err(1, "Failed to store record %i", j); } /* Would have been empty before expansion, but no longer. */ ok1(was_empty); ok1(!empty_freetable(tdb)); tdb_close(tdb); } ok1(tap_log_messages == 0); return exit_status(); }
int main(int argc, char *argv[]) { unsigned int i; struct tdb_context *tdb; int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP, TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT, TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1, TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1, TDB_CONVERT|TDB_VERSION1, TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 }; struct tdb_data key = tdb_mkdata("key", 3); struct tdb_data data = tdb_mkdata("data", 4); plan_tests(sizeof(flags) / sizeof(flags[0]) * 7 + 1); for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) { tdb = tdb_open("run-simple-delete.tdb", flags[i], O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr); ok1(tdb); if (tdb) { /* Delete should fail. */ ok1(tdb_delete(tdb, key) == 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(); }
int main(int argc, char *argv[]) { struct tdb_context *tdb; TDB_DATA key, data; union tdb_attribute hsize; hsize.base.attr = TDB_ATTRIBUTE_TDB1_HASHSIZE; hsize.base.next = &tap_log_attr; hsize.tdb1_hashsize.hsize = 1; plan_tests(13); tdb = tdb_open("run-check.tdb1", TDB_VERSION1, O_CREAT|O_TRUNC|O_RDWR, 0600, &hsize); ok1(tdb); ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS); key = tdb_mkdata("hi", strlen("hi")); data = tdb_mkdata("world", strlen("world")); ok1(tdb_store(tdb, key, data, TDB_INSERT) == TDB_SUCCESS); ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS); tdb_close(tdb); tdb = tdb_open("run-check.tdb1", TDB_VERSION1, O_RDWR, 0, &tap_log_attr); ok1(tdb); ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS); tdb_close(tdb); tdb = tdb_open("test/tdb1.corrupt", TDB_VERSION1, O_RDWR, 0, &tap_log_attr); ok1(tdb); ok1(tdb_check(tdb, NULL, NULL) == TDB_ERR_CORRUPT); ok1(tdb_error(tdb) == TDB_ERR_CORRUPT); tdb_close(tdb); /* Big and little endian should work! */ tdb = tdb_open("test/old-nohash-le.tdb1", TDB_VERSION1, O_RDWR, 0, &tap_log_attr); ok1(tdb); ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS); tdb_close(tdb); tdb = tdb_open("test/old-nohash-be.tdb1", TDB_VERSION1, O_RDWR, 0, &tap_log_attr); ok1(tdb); ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS); tdb_close(tdb); return exit_status(); }
int main(int argc, char *argv[]) { unsigned int i; struct tdb_context *tdb; int flags[] = { TDB_INTERNAL, TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT, TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1, TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1, TDB_CONVERT|TDB_VERSION1 }; struct tdb_data key = tdb_mkdata("key", 3); struct tdb_data data = tdb_mkdata("data", 4); failtest_init(argc, argv); failtest_hook = block_repeat_failures; failtest_exit_check = exit_check_log; failtest_suppress = true; plan_tests(sizeof(flags) / sizeof(flags[0]) * 3 + 1); for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) { tdb = tdb_open("run-12-check.tdb", flags[i], O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr); ok1(tdb); ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); /* This is what we really want to test: tdb_check(). */ failtest_suppress = false; if (!ok1(tdb_check(tdb, NULL, NULL) == 0)) goto fail; failtest_suppress = true; tdb_close(tdb); } ok1(tap_log_messages == 0); failtest_exit(exit_status()); fail: failtest_suppress = true; tdb_close(tdb); failtest_exit(exit_status()); }
int main(int argc, char *argv[]) { struct tdb_context *tdb; TDB_DATA key, data; plan_tests(13); tdb = tdb_open_ex("run-check.tdb", 1, TDB_CLEAR_IF_FIRST, O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); ok1(tdb); ok1(tdb_check(tdb, NULL, NULL) == 0); key.dsize = strlen("hi"); key.dptr = discard_const_p(uint8_t, "hi"); data.dsize = strlen("world"); data.dptr = discard_const_p(uint8_t, "world"); ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); tdb = tdb_open_ex("run-check.tdb", 1024, 0, O_RDWR, 0, &taplogctx, NULL); ok1(tdb); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); tdb = tdb_open_ex("test/tdb.corrupt", 1024, 0, O_RDWR, 0, &taplogctx, NULL); ok1(tdb); ok1(tdb_check(tdb, NULL, NULL) == -1); ok1(tdb_error(tdb) == TDB_ERR_CORRUPT); tdb_close(tdb); /* Big and little endian should work! */ tdb = tdb_open_ex("test/old-nohash-le.tdb", 1024, 0, O_RDWR, 0, &taplogctx, NULL); ok1(tdb); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); tdb = tdb_open_ex("test/old-nohash-be.tdb", 1024, 0, O_RDWR, 0, &taplogctx, NULL); ok1(tdb); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); return exit_status(); }
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, TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1, TDB_CONVERT|TDB_VERSION1, TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 }; struct tdb_data key = tdb_mkdata("key", 3); struct tdb_data data = tdb_mkdata("data", 4); plan_tests(sizeof(flags) / sizeof(flags[0]) * 7 + 1); for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) { size_t size; tdb = tdb_open("run-expand-in-transaction.tdb", flags[i], O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr); ok1(tdb); if (!tdb) continue; size = tdb->file->map_size; ok1(tdb_transaction_start(tdb) == 0); ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); ok1(tdb->file->map_size > size); ok1(tdb_transaction_commit(tdb) == 0); ok1(tdb->file->map_size > size); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); } ok1(tap_log_messages == 0); return exit_status(); }
int main(int argc, char *argv[]) { struct tdb_context *tdb; unsigned int log_count; TDB_DATA d; struct tdb_logging_context log_ctx = { log_fn, &log_count }; plan_tests(28); /* Create with default hash. */ log_count = 0; tdb = tdb_open_ex("run-wronghash-fail.tdb", 0, 0, O_CREAT|O_RDWR|O_TRUNC, 0600, &log_ctx, NULL); ok1(tdb); ok1(log_count == 0); d.dptr = (void *)"Hello"; d.dsize = 5; ok1(tdb_store(tdb, d, d, TDB_INSERT) == 0); tdb_close(tdb); /* Fail to open with different hash. */ tdb = tdb_open_ex("run-wronghash-fail.tdb", 0, 0, O_RDWR, 0, &log_ctx, tdb_jenkins_hash); ok1(!tdb); ok1(log_count == 1); /* Create with different hash. */ log_count = 0; tdb = tdb_open_ex("run-wronghash-fail.tdb", 0, 0, O_CREAT|O_RDWR|O_TRUNC, 0600, &log_ctx, tdb_jenkins_hash); ok1(tdb); ok1(log_count == 0); tdb_close(tdb); /* Endian should be no problem. */ log_count = 0; tdb = tdb_open_ex("test/jenkins-le-hash.tdb", 0, 0, O_RDWR, 0, &log_ctx, tdb_old_hash); ok1(!tdb); ok1(log_count == 1); log_count = 0; tdb = tdb_open_ex("test/jenkins-be-hash.tdb", 0, 0, O_RDWR, 0, &log_ctx, tdb_old_hash); ok1(!tdb); ok1(log_count == 1); log_count = 0; /* Fail to open with old default hash. */ tdb = tdb_open_ex("run-wronghash-fail.tdb", 0, 0, O_RDWR, 0, &log_ctx, tdb_old_hash); ok1(!tdb); ok1(log_count == 1); log_count = 0; tdb = tdb_open_ex("test/jenkins-le-hash.tdb", 0, 0, O_RDONLY, 0, &log_ctx, tdb_jenkins_hash); ok1(tdb); ok1(log_count == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); log_count = 0; tdb = tdb_open_ex("test/jenkins-be-hash.tdb", 0, 0, O_RDONLY, 0, &log_ctx, tdb_jenkins_hash); ok1(tdb); ok1(log_count == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); /* It should open with jenkins hash if we don't specify. */ log_count = 0; tdb = tdb_open_ex("test/jenkins-le-hash.tdb", 0, 0, O_RDWR, 0, &log_ctx, NULL); ok1(tdb); ok1(log_count == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); log_count = 0; tdb = tdb_open_ex("test/jenkins-be-hash.tdb", 0, 0, O_RDWR, 0, &log_ctx, NULL); ok1(tdb); ok1(log_count == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); log_count = 0; tdb = tdb_open_ex("run-wronghash-fail.tdb", 0, 0, O_RDONLY, 0, &log_ctx, NULL); ok1(tdb); ok1(log_count == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); return exit_status(); }
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 }; if (sizeof(off_t) <= 4) { plan_tests(1); pass("No 64 bit off_t"); return exit_status(); } plan_tests(sizeof(flags) / sizeof(flags[0]) * 14); for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) { off_t old_size; TDB_DATA k, d; struct hash_info h; struct tdb_used_record rec; tdb_off_t off; tdb = tdb_open("run-64-bit-tdb.tdb", flags[i], O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr); ok1(tdb); if (!tdb) continue; old_size = tdb->file->map_size; /* This makes a sparse file */ ok1(ftruncate(tdb->file->fd, 0xFFFFFFF0) == 0); ok1(add_free_record(tdb, old_size, 0xFFFFFFF0 - old_size, TDB_LOCK_WAIT, false) == TDB_SUCCESS); /* Now add a little record past the 4G barrier. */ ok1(tdb_expand_file(tdb, 100) == TDB_SUCCESS); ok1(add_free_record(tdb, 0xFFFFFFF0, 100, TDB_LOCK_WAIT, false) == TDB_SUCCESS); ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS); /* Test allocation path. */ k = tdb_mkdata("key", 4); d = tdb_mkdata("data", 5); ok1(tdb_store(tdb, k, d, TDB_INSERT) == 0); ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS); /* Make sure it put it at end as we expected. */ off = find_and_lock(tdb, k, F_RDLCK, &h, &rec, NULL); ok1(off >= 0xFFFFFFF0); tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK); ok1(tdb_fetch(tdb, k, &d) == 0); ok1(d.dsize == 5); ok1(strcmp((char *)d.dptr, "data") == 0); free(d.dptr); ok1(tdb_delete(tdb, k) == 0); ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS); tdb_close(tdb); } /* We might get messages about mmap failing, so don't test * tap_log_messages */ return exit_status(); }
static enum agent_return do_operation(enum operation op, const char *name) { TDB_DATA k; enum agent_return ret; TDB_DATA data; if (op != OPEN && op != OPEN_WITH_CLEAR_IF_FIRST && !tdb) { diag("external: No tdb open!"); return OTHER_FAILURE; } k.dptr = (void *)name; k.dsize = strlen(name); locking_would_block = 0; switch (op) { case OPEN: if (tdb) { diag("Already have tdb %s open", tdb_name(tdb)); return OTHER_FAILURE; } tdb = tdb_open_ex(name, 0, TDB_DEFAULT, O_RDWR, 0, &taplogctx, NULL); if (!tdb) { if (!locking_would_block) diag("Opening tdb gave %s", strerror(errno)); ret = OTHER_FAILURE; } else ret = SUCCESS; break; case OPEN_WITH_CLEAR_IF_FIRST: if (tdb) return OTHER_FAILURE; tdb = tdb_open_ex(name, 0, TDB_CLEAR_IF_FIRST, O_RDWR, 0, &taplogctx, NULL); ret = tdb ? SUCCESS : OTHER_FAILURE; break; case TRANSACTION_START: ret = tdb_transaction_start(tdb) == 0 ? SUCCESS : OTHER_FAILURE; break; case FETCH: data = tdb_fetch(tdb, k); if (data.dptr == NULL) { if (tdb_error(tdb) == TDB_ERR_NOEXIST) ret = FAILED; else ret = OTHER_FAILURE; } else if (data.dsize != k.dsize || memcmp(data.dptr, k.dptr, k.dsize) != 0) { ret = OTHER_FAILURE; } else { ret = SUCCESS; } free(data.dptr); break; case STORE: ret = tdb_store(tdb, k, k, 0) == 0 ? SUCCESS : OTHER_FAILURE; break; case TRANSACTION_COMMIT: ret = tdb_transaction_commit(tdb)==0 ? SUCCESS : OTHER_FAILURE; break; case CHECK: ret = tdb_check(tdb, NULL, NULL) == 0 ? SUCCESS : OTHER_FAILURE; break; case NEEDS_RECOVERY: ret = tdb_needs_recovery(tdb) ? SUCCESS : FAILED; break; case CLOSE: ret = tdb_close(tdb) == 0 ? SUCCESS : OTHER_FAILURE; tdb = NULL; break; default: ret = OTHER_FAILURE; } if (locking_would_block) ret = WOULD_HAVE_BLOCKED; return ret; }
int main(int argc, char *argv[]) { tdb_off_t b_off, test; struct tdb_context *tdb; struct tdb_layout *layout; struct tdb_data data, key; tdb_len_t len; /* FIXME: Test TDB_CONVERT */ /* FIXME: Test lock order fail. */ plan_tests(42); data = tdb_mkdata("world", 5); key = tdb_mkdata("hello", 5); /* No coalescing can be done due to EOF */ layout = new_tdb_layout("run-03-coalesce.tdb"); tdb_layout_add_freetable(layout); len = 1024; tdb_layout_add_free(layout, len, 0); tdb = tdb_layout_get(layout); ok1(tdb_check(tdb, NULL, NULL) == 0); ok1(free_record_length(tdb, layout->elem[1].base.off) == len); /* Figure out which bucket free entry is. */ b_off = bucket_off(tdb->ftable_off, size_to_bucket(len)); /* Lock and fail to coalesce. */ ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0); test = layout->elem[1].base.off; ok1(coalesce(tdb, layout->elem[1].base.off, b_off, len, &test) == 0); tdb_unlock_free_bucket(tdb, b_off); ok1(free_record_length(tdb, layout->elem[1].base.off) == len); ok1(test == layout->elem[1].base.off); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); tdb_layout_free(layout); /* No coalescing can be done due to used record */ layout = new_tdb_layout("run-03-coalesce.tdb"); tdb_layout_add_freetable(layout); tdb_layout_add_free(layout, 1024, 0); tdb_layout_add_used(layout, key, data, 6); tdb = tdb_layout_get(layout); ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024); ok1(tdb_check(tdb, NULL, NULL) == 0); /* Figure out which bucket free entry is. */ b_off = bucket_off(tdb->ftable_off, size_to_bucket(1024)); /* Lock and fail to coalesce. */ ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0); test = layout->elem[1].base.off; ok1(coalesce(tdb, layout->elem[1].base.off, b_off, 1024, &test) == 0); tdb_unlock_free_bucket(tdb, b_off); ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024); ok1(test == layout->elem[1].base.off); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); tdb_layout_free(layout); /* Coalescing can be done due to two free records, then EOF */ layout = new_tdb_layout("run-03-coalesce.tdb"); tdb_layout_add_freetable(layout); tdb_layout_add_free(layout, 1024, 0); tdb_layout_add_free(layout, 2048, 0); tdb = tdb_layout_get(layout); ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024); ok1(free_record_length(tdb, layout->elem[2].base.off) == 2048); ok1(tdb_check(tdb, NULL, NULL) == 0); /* Figure out which bucket (first) free entry is. */ b_off = bucket_off(tdb->ftable_off, size_to_bucket(1024)); /* Lock and coalesce. */ ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0); test = layout->elem[2].base.off; ok1(coalesce(tdb, layout->elem[1].base.off, b_off, 1024, &test) == 1024 + sizeof(struct tdb_used_record) + 2048); /* Should tell us it's erased this one... */ ok1(test == TDB_ERR_NOEXIST); ok1(tdb->file->allrecord_lock.count == 0 && tdb->file->num_lockrecs == 0); ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024 + sizeof(struct tdb_used_record) + 2048); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); tdb_layout_free(layout); /* Coalescing can be done due to two free records, then data */ layout = new_tdb_layout("run-03-coalesce.tdb"); tdb_layout_add_freetable(layout); tdb_layout_add_free(layout, 1024, 0); tdb_layout_add_free(layout, 512, 0); tdb_layout_add_used(layout, key, data, 6); tdb = tdb_layout_get(layout); ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024); ok1(free_record_length(tdb, layout->elem[2].base.off) == 512); ok1(tdb_check(tdb, NULL, NULL) == 0); /* Figure out which bucket free entry is. */ b_off = bucket_off(tdb->ftable_off, size_to_bucket(1024)); /* Lock and coalesce. */ ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0); test = layout->elem[2].base.off; ok1(coalesce(tdb, layout->elem[1].base.off, b_off, 1024, &test) == 1024 + sizeof(struct tdb_used_record) + 512); ok1(tdb->file->allrecord_lock.count == 0 && tdb->file->num_lockrecs == 0); ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024 + sizeof(struct tdb_used_record) + 512); ok1(test == TDB_ERR_NOEXIST); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); tdb_layout_free(layout); /* Coalescing can be done due to three free records, then EOF */ layout = new_tdb_layout("run-03-coalesce.tdb"); tdb_layout_add_freetable(layout); tdb_layout_add_free(layout, 1024, 0); tdb_layout_add_free(layout, 512, 0); tdb_layout_add_free(layout, 256, 0); tdb = tdb_layout_get(layout); ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024); ok1(free_record_length(tdb, layout->elem[2].base.off) == 512); ok1(free_record_length(tdb, layout->elem[3].base.off) == 256); ok1(tdb_check(tdb, NULL, NULL) == 0); /* Figure out which bucket free entry is. */ b_off = bucket_off(tdb->ftable_off, size_to_bucket(1024)); /* Lock and coalesce. */ ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0); test = layout->elem[2].base.off; ok1(coalesce(tdb, layout->elem[1].base.off, b_off, 1024, &test) == 1024 + sizeof(struct tdb_used_record) + 512 + sizeof(struct tdb_used_record) + 256); ok1(tdb->file->allrecord_lock.count == 0 && tdb->file->num_lockrecs == 0); ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024 + sizeof(struct tdb_used_record) + 512 + sizeof(struct tdb_used_record) + 256); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); tdb_layout_free(layout); ok1(tap_log_messages == 0); return exit_status(); }
int main(int argc, char *argv[]) { unsigned int i, extra_messages; struct tdb_context *tdb, *tdb2; struct tdb_data key = { (unsigned char *)&i, sizeof(i) }; struct tdb_data data = { (unsigned char *)&i, sizeof(i) }; struct tdb_data d = { NULL, 0 }; /* Bogus GCC warning */ int flags[] = { TDB_DEFAULT, TDB_NOMMAP, TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT, TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1, TDB_CONVERT|TDB_VERSION1, TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 }; plan_tests(sizeof(flags) / sizeof(flags[0]) * 28); for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) { tdb = tdb_open("run-open-multiple-times.tdb", flags[i], O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr); ok1(tdb); if (!tdb) continue; if (flags[i] & TDB_VERSION1) { extra_messages = 1; } else { extra_messages = 0; } tdb2 = tdb_open("run-open-multiple-times.tdb", flags[i], O_RDWR|O_CREAT, 0600, &tap_log_attr); ok1(tdb_check(tdb, NULL, NULL) == 0); ok1(tdb_check(tdb2, NULL, NULL) == 0); /* Store in one, fetch in the other. */ ok1(tdb_store(tdb, key, data, TDB_REPLACE) == 0); ok1(tdb_fetch(tdb2, key, &d) == TDB_SUCCESS); ok1(tdb_deq(d, data)); free(d.dptr); /* Vice versa, with delete. */ ok1(tdb_delete(tdb2, key) == 0); ok1(tdb_fetch(tdb, key, &d) == TDB_ERR_NOEXIST); /* OK, now close first one, check second still good. */ ok1(tdb_close(tdb) == 0); ok1(tdb_store(tdb2, key, data, TDB_REPLACE) == 0); ok1(tdb_fetch(tdb2, key, &d) == TDB_SUCCESS); ok1(tdb_deq(d, data)); free(d.dptr); /* Reopen */ tdb = tdb_open("run-open-multiple-times.tdb", flags[i], O_RDWR|O_CREAT, 0600, &tap_log_attr); ok1(tdb); ok1(tdb_transaction_start(tdb2) == 0); /* Anything in the other one should fail. */ ok1(tdb_fetch(tdb, key, &d) == TDB_ERR_LOCK); tap_log_messages -= extra_messages; ok1(tap_log_messages == 1); ok1(tdb_store(tdb, key, data, TDB_REPLACE) == TDB_ERR_LOCK); tap_log_messages -= extra_messages; ok1(tap_log_messages == 2); ok1(tdb_transaction_start(tdb) == TDB_ERR_LOCK); ok1(tap_log_messages == 3); ok1(tdb_chainlock(tdb, key) == TDB_ERR_LOCK); tap_log_messages -= extra_messages; ok1(tap_log_messages == 4); /* Transaciton should work as normal. */ ok1(tdb_store(tdb2, key, data, TDB_REPLACE) == TDB_SUCCESS); /* Now... try closing with locks held. */ ok1(tdb_close(tdb2) == 0); ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS); ok1(tdb_deq(d, data)); free(d.dptr); ok1(tdb_close(tdb) == 0); ok1(tap_log_messages == 4); tap_log_messages = 0; } return exit_status(); }
static enum agent_return do_operation(enum operation op, const char *name) { TDB_DATA k; enum agent_return ret; TDB_DATA data; enum TDB_ERROR ecode; union tdb_attribute cif; if (op != OPEN && op != OPEN_WITH_HOOK && !tdb) { diag("external: No tdb open!"); return OTHER_FAILURE; } diag("external: %s", operation_name(op)); k = tdb_mkdata(name, strlen(name)); locking_would_block = 0; switch (op) { case OPEN: if (tdb) { diag("Already have tdb %s open", tdb_name(tdb)); return OTHER_FAILURE; } tdb = tdb_open(name, TDB_DEFAULT, O_RDWR, 0, &tap_log_attr); if (!tdb) { if (!locking_would_block) diag("Opening tdb gave %s", strerror(errno)); forget_locking(); ret = OTHER_FAILURE; } else ret = SUCCESS; break; case OPEN_WITH_HOOK: if (tdb) { diag("Already have tdb %s open", tdb_name(tdb)); return OTHER_FAILURE; } cif.openhook.base.attr = TDB_ATTRIBUTE_OPENHOOK; cif.openhook.base.next = &tap_log_attr; cif.openhook.fn = clear_if_first; tdb = tdb_open(name, TDB_DEFAULT, O_RDWR, 0, &cif); if (!tdb) { if (!locking_would_block) diag("Opening tdb gave %s", strerror(errno)); forget_locking(); ret = OTHER_FAILURE; } else ret = SUCCESS; break; case FETCH: ecode = tdb_fetch(tdb, k, &data); if (ecode == TDB_ERR_NOEXIST) { ret = FAILED; } else if (ecode < 0) { ret = OTHER_FAILURE; } else if (!tdb_deq(data, k)) { ret = OTHER_FAILURE; external_agent_free(data.dptr); } else { ret = SUCCESS; external_agent_free(data.dptr); } break; case STORE: ret = tdb_store(tdb, k, k, 0) == 0 ? SUCCESS : OTHER_FAILURE; break; case TRANSACTION_START: ret = tdb_transaction_start(tdb) == 0 ? SUCCESS : OTHER_FAILURE; break; case TRANSACTION_COMMIT: ret = tdb_transaction_commit(tdb)==0 ? SUCCESS : OTHER_FAILURE; break; case NEEDS_RECOVERY: ret = external_agent_needs_rec(tdb); break; case CHECK: ret = tdb_check(tdb, NULL, NULL) == 0 ? SUCCESS : OTHER_FAILURE; break; case CLOSE: ret = tdb_close(tdb) == 0 ? SUCCESS : OTHER_FAILURE; tdb = NULL; break; case SEND_SIGNAL: /* We do this async */ ret = SUCCESS; break; default: ret = OTHER_FAILURE; } if (locking_would_block) ret = WOULD_HAVE_BLOCKED; return ret; }
int main(int argc, char *argv[]) { unsigned int i, j, num = 1000, stage = 0, stopat = -1; int flags = TDB_DEFAULT; bool transaction = false, summary = false; TDB_DATA key, data; struct tdb_context *tdb; struct timeval start, stop; union tdb_attribute seed, log; bool do_stats = false; enum TDB_ERROR ecode; /* Try to keep benchmarks even. */ seed.base.attr = TDB_ATTRIBUTE_SEED; seed.base.next = NULL; seed.seed.seed = 0; log.base.attr = TDB_ATTRIBUTE_LOG; log.base.next = &seed; log.log.fn = tdb_log; if (argv[1] && strcmp(argv[1], "--internal") == 0) { flags = TDB_INTERNAL; argc--; argv++; } if (argv[1] && strcmp(argv[1], "--transaction") == 0) { transaction = true; argc--; argv++; } if (argv[1] && strcmp(argv[1], "--no-sync") == 0) { flags |= TDB_NOSYNC; argc--; argv++; } if (argv[1] && strcmp(argv[1], "--summary") == 0) { summary = true; argc--; argv++; } if (argv[1] && strcmp(argv[1], "--stats") == 0) { do_stats = true; argc--; argv++; } tdb = tdb_open("/tmp/speed.tdb", flags, O_RDWR|O_CREAT|O_TRUNC, 0600, &log); if (!tdb) err(1, "Opening /tmp/speed.tdb"); key.dptr = (void *)&i; key.dsize = sizeof(i); data = key; if (argv[1]) { num = atoi(argv[1]); argv++; argc--; } if (argv[1]) { stopat = atoi(argv[1]); argv++; argc--; } /* Add 1000 records. */ printf("Adding %u records: ", num); fflush(stdout); if (transaction && (ecode = tdb_transaction_start(tdb))) errx(1, "starting transaction: %s", tdb_errorstr(ecode)); gettimeofday(&start, NULL); for (i = 0; i < num; i++) if ((ecode = tdb_store(tdb, key, data, TDB_INSERT)) != 0) errx(1, "Inserting key %u in tdb: %s", i, tdb_errorstr(ecode)); gettimeofday(&stop, NULL); if (transaction && (ecode = tdb_transaction_commit(tdb))) errx(1, "committing transaction: %s", tdb_errorstr(ecode)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (tdb_check(tdb, NULL, NULL)) errx(1, "tdb_check failed!"); if (summary) { char *sumstr = NULL; tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr); printf("%s\n", sumstr); free(sumstr); } if (do_stats) dump_and_clear_stats(&tdb, flags, &log); if (++stage == stopat) exit(0); /* Finding 1000 records. */ printf("Finding %u records: ", num); fflush(stdout); if (transaction && (ecode = tdb_transaction_start(tdb))) errx(1, "starting transaction: %s", tdb_errorstr(ecode)); gettimeofday(&start, NULL); for (i = 0; i < num; i++) { struct tdb_data dbuf; if ((ecode = tdb_fetch(tdb, key, &dbuf)) != TDB_SUCCESS || *(int *)dbuf.dptr != i) { errx(1, "Fetching key %u in tdb gave %u", i, ecode ? ecode : *(int *)dbuf.dptr); } } gettimeofday(&stop, NULL); if (transaction && (ecode = tdb_transaction_commit(tdb))) errx(1, "committing transaction: %s", tdb_errorstr(ecode)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (tdb_check(tdb, NULL, NULL)) errx(1, "tdb_check failed!"); if (summary) { char *sumstr = NULL; tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr); printf("%s\n", sumstr); free(sumstr); } if (do_stats) dump_and_clear_stats(&tdb, flags, &log); if (++stage == stopat) exit(0); /* Missing 1000 records. */ printf("Missing %u records: ", num); fflush(stdout); if (transaction && (ecode = tdb_transaction_start(tdb))) errx(1, "starting transaction: %s", tdb_errorstr(ecode)); gettimeofday(&start, NULL); for (i = num; i < num*2; i++) { struct tdb_data dbuf; ecode = tdb_fetch(tdb, key, &dbuf); if (ecode != TDB_ERR_NOEXIST) errx(1, "Fetching key %u in tdb gave %s", i, tdb_errorstr(ecode)); } gettimeofday(&stop, NULL); if (transaction && (ecode = tdb_transaction_commit(tdb))) errx(1, "committing transaction: %s", tdb_errorstr(ecode)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (tdb_check(tdb, NULL, NULL)) errx(1, "tdb_check failed!"); if (summary) { char *sumstr = NULL; tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr); printf("%s\n", sumstr); free(sumstr); } if (do_stats) dump_and_clear_stats(&tdb, flags, &log); if (++stage == stopat) exit(0); /* Traverse 1000 records. */ printf("Traversing %u records: ", num); fflush(stdout); if (transaction && (ecode = tdb_transaction_start(tdb))) errx(1, "starting transaction: %s", tdb_errorstr(ecode)); i = 0; gettimeofday(&start, NULL); if (tdb_traverse(tdb, count_record, &i) != num) errx(1, "Traverse returned wrong number of records"); if (i != (num - 1) * (num / 2)) errx(1, "Traverse tallied to %u", i); gettimeofday(&stop, NULL); if (transaction && (ecode = tdb_transaction_commit(tdb))) errx(1, "committing transaction: %s", tdb_errorstr(ecode)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (tdb_check(tdb, NULL, NULL)) errx(1, "tdb_check failed!"); if (summary) { char *sumstr = NULL; tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr); printf("%s\n", sumstr); free(sumstr); } if (do_stats) dump_and_clear_stats(&tdb, flags, &log); if (++stage == stopat) exit(0); /* Delete 1000 records (not in order). */ printf("Deleting %u records: ", num); fflush(stdout); if (transaction && (ecode = tdb_transaction_start(tdb))) errx(1, "starting transaction: %s", tdb_errorstr(ecode)); gettimeofday(&start, NULL); for (j = 0; j < num; j++) { i = (j + 100003) % num; if ((ecode = tdb_delete(tdb, key)) != TDB_SUCCESS) errx(1, "Deleting key %u in tdb: %s", i, tdb_errorstr(ecode)); } gettimeofday(&stop, NULL); if (transaction && (ecode = tdb_transaction_commit(tdb))) errx(1, "committing transaction: %s", tdb_errorstr(ecode)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (tdb_check(tdb, NULL, NULL)) errx(1, "tdb_check failed!"); if (summary) { char *sumstr = NULL; tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr); printf("%s\n", sumstr); free(sumstr); } if (do_stats) dump_and_clear_stats(&tdb, flags, &log); if (++stage == stopat) exit(0); /* Re-add 1000 records (not in order). */ printf("Re-adding %u records: ", num); fflush(stdout); if (transaction && (ecode = tdb_transaction_start(tdb))) errx(1, "starting transaction: %s", tdb_errorstr(ecode)); gettimeofday(&start, NULL); for (j = 0; j < num; j++) { i = (j + 100003) % num; if ((ecode = tdb_store(tdb, key, data, TDB_INSERT)) != 0) errx(1, "Inserting key %u in tdb: %s", i, tdb_errorstr(ecode)); } gettimeofday(&stop, NULL); if (transaction && (ecode = tdb_transaction_commit(tdb))) errx(1, "committing transaction: %s", tdb_errorstr(ecode)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (tdb_check(tdb, NULL, NULL)) errx(1, "tdb_check failed!"); if (summary) { char *sumstr = NULL; tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr); printf("%s\n", sumstr); free(sumstr); } if (do_stats) dump_and_clear_stats(&tdb, flags, &log); if (++stage == stopat) exit(0); /* Append 1000 records. */ if (transaction && (ecode = tdb_transaction_start(tdb))) errx(1, "starting transaction: %s", tdb_errorstr(ecode)); printf("Appending %u records: ", num); fflush(stdout); gettimeofday(&start, NULL); for (i = 0; i < num; i++) if ((ecode = tdb_append(tdb, key, data)) != TDB_SUCCESS) errx(1, "Appending key %u in tdb: %s", i, tdb_errorstr(ecode)); gettimeofday(&stop, NULL); if (transaction && (ecode = tdb_transaction_commit(tdb))) errx(1, "committing transaction: %s", tdb_errorstr(ecode)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (tdb_check(tdb, NULL, NULL)) errx(1, "tdb_check failed!"); if (summary) { char *sumstr = NULL; tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr); printf("%s\n", sumstr); free(sumstr); } if (++stage == stopat) exit(0); /* Churn 1000 records: not in order! */ if (transaction && (ecode = tdb_transaction_start(tdb))) errx(1, "starting transaction: %s", tdb_errorstr(ecode)); printf("Churning %u records: ", num); fflush(stdout); gettimeofday(&start, NULL); for (j = 0; j < num; j++) { i = (j + 1000019) % num; if ((ecode = tdb_delete(tdb, key)) != TDB_SUCCESS) errx(1, "Deleting key %u in tdb: %s", i, tdb_errorstr(ecode)); i += num; if ((ecode = tdb_store(tdb, key, data, TDB_INSERT)) != 0) errx(1, "Inserting key %u in tdb: %s", i, tdb_errorstr(ecode)); } gettimeofday(&stop, NULL); if (transaction && (ecode = tdb_transaction_commit(tdb))) errx(1, "committing transaction: %s", tdb_errorstr(ecode)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (tdb_check(tdb, NULL, NULL)) errx(1, "tdb_check failed!"); if (summary) { char *sumstr = NULL; tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr); printf("%s\n", sumstr); free(sumstr); } if (do_stats) dump_and_clear_stats(&tdb, flags, &log); if (++stage == stopat) exit(0); return 0; }
int main(int argc, char *argv[]) { tdb_off_t off; struct tdb_context *tdb; struct tdb_layout *layout; TDB_DATA key, data; union tdb_attribute seed; /* This seed value previously tickled a layout.c bug. */ seed.base.attr = TDB_ATTRIBUTE_SEED; seed.seed.seed = 0xb1142bc054d035b4ULL; seed.base.next = &tap_log_attr; plan_tests(11); key = tdb_mkdata("Hello", 5); data = tdb_mkdata("world", 5); /* Create a TDB with three free tables. */ layout = new_tdb_layout(); tdb_layout_add_freetable(layout); tdb_layout_add_freetable(layout); tdb_layout_add_freetable(layout); tdb_layout_add_free(layout, 80, 0); /* Used record prevent coalescing. */ tdb_layout_add_used(layout, key, data, 6); tdb_layout_add_free(layout, 160, 1); key.dsize--; tdb_layout_add_used(layout, key, data, 7); tdb_layout_add_free(layout, 320, 2); key.dsize--; tdb_layout_add_used(layout, key, data, 8); tdb_layout_add_free(layout, 40, 0); tdb = tdb_layout_get(layout, free, &seed); ok1(tdb_check(tdb, NULL, NULL) == 0); off = get_free(tdb, 0, 80 - sizeof(struct tdb_used_record), 0, TDB_USED_MAGIC, 0); ok1(off == layout->elem[3].base.off); ok1(tdb->tdb2.ftable_off == layout->elem[0].base.off); off = get_free(tdb, 0, 160 - sizeof(struct tdb_used_record), 0, TDB_USED_MAGIC, 0); ok1(off == layout->elem[5].base.off); ok1(tdb->tdb2.ftable_off == layout->elem[1].base.off); off = get_free(tdb, 0, 320 - sizeof(struct tdb_used_record), 0, TDB_USED_MAGIC, 0); ok1(off == layout->elem[7].base.off); ok1(tdb->tdb2.ftable_off == layout->elem[2].base.off); off = get_free(tdb, 0, 40 - sizeof(struct tdb_used_record), 0, TDB_USED_MAGIC, 0); ok1(off == layout->elem[9].base.off); ok1(tdb->tdb2.ftable_off == layout->elem[0].base.off); /* Now we fail. */ off = get_free(tdb, 0, 0, 1, TDB_USED_MAGIC, 0); ok1(off == 0); tdb_close(tdb); tdb_layout_free(layout); ok1(tap_log_messages == 0); return exit_status(); }
int main(int argc, char * const *argv) { int i, seed = -1; int num_loops = 5000; int num_procs = 3; int c, pfds[2]; extern char *optarg; pid_t *pids; int kill_random = 0; int *done; int tdb_flags = TDB_DEFAULT; log_attr.base.attr = TDB_ATTRIBUTE_LOG; log_attr.base.next = &seed_attr; log_attr.log.fn = tdb_log; seed_attr.base.attr = TDB_ATTRIBUTE_SEED; while ((c = getopt(argc, argv, "n:l:s:thkS")) != -1) { switch (c) { case 'n': num_procs = strtol(optarg, NULL, 0); break; case 'l': num_loops = strtol(optarg, NULL, 0); break; case 's': seed = strtol(optarg, NULL, 0); break; case 'S': tdb_flags = TDB_NOSYNC; break; case 't': #if TRANSACTION_PROB always_transaction = 1; #else fprintf(stderr, "Transactions not supported\n"); usage(); #endif break; case 'k': kill_random = 1; break; default: usage(); } } unlink("torture.tdb"); if (seed == -1) { seed = (getpid() + time(NULL)) & 0x7FFFFFFF; } seed_attr.seed.seed = (((uint64_t)seed) << 32) | seed; if (num_procs == 1 && !kill_random) { /* Don't fork for this case, makes debugging easier. */ error_count = run_child(0, seed, num_loops, 0, tdb_flags); goto done; } pids = (pid_t *)calloc(sizeof(pid_t), num_procs); done = (int *)calloc(sizeof(int), num_procs); if (pipe(pfds) != 0) { perror("Creating pipe"); exit(1); } count_pipe = pfds[1]; for (i=0;i<num_procs;i++) { if ((pids[i]=fork()) == 0) { close(pfds[0]); if (i == 0) { printf("testing with %d processes, %d loops, seed=%d%s\n", num_procs, num_loops, seed, #if TRANSACTION_PROB always_transaction ? " (all within transactions)" : "" #else "" #endif ); } exit(run_child(i, seed, num_loops, 0, tdb_flags)); } } while (num_procs) { int status, j; pid_t pid; if (error_count != 0) { /* try and stop the test on any failure */ for (j=0;j<num_procs;j++) { if (pids[j] != 0) { kill(pids[j], SIGTERM); } } } pid = waitpid(-1, &status, kill_random ? WNOHANG : 0); if (pid == 0) { struct timespec ts; /* Sleep for 1/10 second. */ ts.tv_sec = 0; ts.tv_nsec = 100000000; nanosleep(&ts, NULL); /* Kill someone. */ kill(pids[random() % num_procs], SIGUSR1); continue; } if (pid == -1) { perror("failed to wait for child\n"); exit(1); } for (j=0;j<num_procs;j++) { if (pids[j] == pid) break; } if (j == num_procs) { printf("unknown child %d exited!?\n", (int)pid); exit(1); } if (WIFSIGNALED(status)) { if (WTERMSIG(status) == SIGUSR2 || WTERMSIG(status) == SIGUSR1) { /* SIGUSR2 means they wrote to pipe. */ if (WTERMSIG(status) == SIGUSR2) { if (read(pfds[0], &done[j], sizeof(done[j])) != sizeof(done[j])) err(1, "Short read from child?"); } pids[j] = fork(); if (pids[j] == 0) exit(run_child(j, seed, num_loops, done[j], tdb_flags)); printf("Restarting child %i for %u-%u\n", j, done[j], num_loops); continue; } printf("child %d exited with signal %d\n", (int)pid, WTERMSIG(status)); error_count++; } else { if (WEXITSTATUS(status) != 0) { printf("child %d exited with status %d\n", (int)pid, WEXITSTATUS(status)); error_count++; } } memmove(&pids[j], &pids[j+1], (num_procs - j - 1)*sizeof(pids[0])); num_procs--; } free(pids); done: if (error_count == 0) { db = tdb_open("torture.tdb", TDB_DEFAULT, O_RDWR | O_CREAT, 0600, &log_attr); if (!db) { fatal(db, "db open failed"); exit(1); } if (tdb_check(db, NULL, NULL) != 0) { fatal(db, "db check failed"); exit(1); } tdb_close(db); printf("OK\n"); } return error_count; }
static int db_tdb_check(struct db_context *db) { struct db_tdb_ctx *ctx = talloc_get_type_abort( db->private_data, struct db_tdb_ctx); return tdb_check(ctx->wtdb->tdb, NULL, NULL); }
int main(int argc, char *argv[]) { struct tdb_context *tdb; unsigned int log_count; TDB_DATA d; union tdb_attribute log_attr, jhash_attr, ohash_attr, incompat_hash_attr; log_attr.base.attr = TDB_ATTRIBUTE_LOG; log_attr.base.next = NULL; log_attr.log.fn = log_fn; log_attr.log.data = &log_count; jhash_attr.base.attr = TDB_ATTRIBUTE_HASH; jhash_attr.base.next = &log_attr; jhash_attr.hash.fn = jenkins_hashfn; ohash_attr.base.attr = TDB_ATTRIBUTE_HASH; ohash_attr.base.next = &log_attr; ohash_attr.hash.fn = old_hash; incompat_hash_attr.base.attr = TDB_ATTRIBUTE_HASH; incompat_hash_attr.base.next = &log_attr; incompat_hash_attr.hash.fn = tdb1_incompatible_hash; plan_tests(28); /* Create with default hash. */ log_count = 0; tdb = tdb_open("run-wronghash-fail.tdb1", TDB_VERSION1, O_CREAT|O_RDWR|O_TRUNC, 0600, &log_attr); ok1(tdb); ok1(log_count == 0); d.dptr = (void *)"Hello"; d.dsize = 5; ok1(tdb_store(tdb, d, d, TDB_INSERT) == TDB_SUCCESS); tdb_close(tdb); /* Fail to open with different hash. */ tdb = tdb_open("run-wronghash-fail.tdb1", TDB_VERSION1, O_RDWR, 0, &jhash_attr); ok1(!tdb); ok1(log_count == 1); /* Create with different hash. */ log_count = 0; tdb = tdb_open("run-wronghash-fail.tdb1", TDB_VERSION1, O_CREAT|O_RDWR|O_TRUNC, 0600, &jhash_attr); ok1(tdb); ok1(log_count == 0); tdb_close(tdb); /* Endian should be no problem. */ log_count = 0; tdb = tdb_open("test/jenkins-le-hash.tdb1", TDB_VERSION1, O_RDWR, 0, &ohash_attr); ok1(!tdb); ok1(log_count == 1); log_count = 0; tdb = tdb_open("test/jenkins-be-hash.tdb1", TDB_VERSION1, O_RDWR, 0, &ohash_attr); ok1(!tdb); ok1(log_count == 1); log_count = 0; /* Fail to open with old default hash. */ tdb = tdb_open("run-wronghash-fail.tdb1", TDB_VERSION1, O_RDWR, 0, &ohash_attr); ok1(!tdb); ok1(log_count == 1); log_count = 0; tdb = tdb_open("test/jenkins-le-hash.tdb1", TDB_VERSION1, O_RDONLY, 0, &incompat_hash_attr); ok1(tdb); ok1(log_count == 0); ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS); tdb_close(tdb); log_count = 0; tdb = tdb_open("test/jenkins-be-hash.tdb1", TDB_VERSION1, O_RDONLY, 0, &incompat_hash_attr); ok1(tdb); ok1(log_count == 0); ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS); tdb_close(tdb); /* It should open with jenkins hash if we don't specify. */ log_count = 0; tdb = tdb_open("test/jenkins-le-hash.tdb1", TDB_VERSION1, O_RDWR, 0, &log_attr); ok1(tdb); ok1(log_count == 0); ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS); tdb_close(tdb); log_count = 0; tdb = tdb_open("test/jenkins-be-hash.tdb1", TDB_VERSION1, O_RDWR, 0, &log_attr); ok1(tdb); ok1(log_count == 0); ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS); tdb_close(tdb); log_count = 0; tdb = tdb_open("run-wronghash-fail.tdb1", TDB_VERSION1, O_RDONLY, 0, &log_attr); ok1(tdb); ok1(log_count == 0); ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS); tdb_close(tdb); return exit_status(); }
int main(int argc, char * const *argv) { int i, seed = -1; int num_loops = 5000; int num_procs = 3; int c, pfds[2]; extern char *optarg; pid_t *pids; int kill_random = 0; int *done; char *test_tdb; log_ctx.log_fn = tdb_log; while ((c = getopt(argc, argv, "n:l:s:H:thk")) != -1) { switch (c) { case 'n': num_procs = strtol(optarg, NULL, 0); break; case 'l': num_loops = strtol(optarg, NULL, 0); break; case 'H': hash_size = strtol(optarg, NULL, 0); break; case 's': seed = strtol(optarg, NULL, 0); break; case 't': always_transaction = 1; break; case 'k': kill_random = 1; break; default: usage(); } } test_tdb = test_path("torture.tdb"); unlink(test_tdb); if (seed == -1) { seed = (getpid() + time(NULL)) & 0x7FFFFFFF; } if (num_procs == 1 && !kill_random) { /* Don't fork for this case, makes debugging easier. */ error_count = run_child(test_tdb, 0, seed, num_loops, 0); goto done; } pids = (pid_t *)calloc(sizeof(pid_t), num_procs); done = (int *)calloc(sizeof(int), num_procs); if (pipe(pfds) != 0) { perror("Creating pipe"); exit(1); } count_pipe = pfds[1]; for (i=0;i<num_procs;i++) { if ((pids[i]=fork()) == 0) { close(pfds[0]); if (i == 0) { printf("Testing with %d processes, %d loops, %d hash_size, seed=%d%s\n", num_procs, num_loops, hash_size, seed, always_transaction ? " (all within transactions)" : ""); } exit(run_child(test_tdb, i, seed, num_loops, 0)); } } while (num_procs) { int status, j; pid_t pid; if (error_count != 0) { /* try and stop the test on any failure */ for (j=0;j<num_procs;j++) { if (pids[j] != 0) { kill(pids[j], SIGTERM); } } } pid = waitpid(-1, &status, kill_random ? WNOHANG : 0); if (pid == 0) { struct timeval tv; /* Sleep for 1/10 second. */ tv.tv_sec = 0; tv.tv_usec = 100000; select(0, NULL, NULL, NULL, &tv); /* Kill someone. */ kill(pids[random() % num_procs], SIGUSR1); continue; } if (pid == -1) { perror("failed to wait for child\n"); exit(1); } for (j=0;j<num_procs;j++) { if (pids[j] == pid) break; } if (j == num_procs) { printf("unknown child %d exited!?\n", (int)pid); exit(1); } if (WIFSIGNALED(status)) { if (WTERMSIG(status) == SIGUSR2 || WTERMSIG(status) == SIGUSR1) { /* SIGUSR2 means they wrote to pipe. */ if (WTERMSIG(status) == SIGUSR2) { read(pfds[0], &done[j], sizeof(done[j])); } pids[j] = fork(); if (pids[j] == 0) exit(run_child(test_tdb, j, seed, num_loops, done[j])); printf("Restarting child %i for %u-%u\n", j, done[j], num_loops); continue; } printf("child %d exited with signal %d\n", (int)pid, WTERMSIG(status)); error_count++; } else { if (WEXITSTATUS(status) != 0) { printf("child %d exited with status %d\n", (int)pid, WEXITSTATUS(status)); error_count++; } } memmove(&pids[j], &pids[j+1], (num_procs - j - 1)*sizeof(pids[0])); num_procs--; } free(pids); done: if (error_count == 0) { db = tdb_open_ex(test_tdb, hash_size, TDB_DEFAULT, O_RDWR, 0, &log_ctx, NULL); if (!db) { fatal("db open failed\n"); exit(1); } if (tdb_check(db, NULL, NULL) == -1) { printf("db check failed\n"); exit(1); } tdb_close(db); printf("OK\n"); } free(test_tdb); return error_count; }
static void test_val(struct tdb_context *tdb, uint64_t val) { uint64_t v; struct tdb_data key = { (unsigned char *)&v, sizeof(v) }; struct tdb_data d, data = { (unsigned char *)&v, sizeof(v) }; /* Insert an entry, then delete it. */ v = val; /* Delete should fail. */ ok1(tdb_delete(tdb, key) == 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 succeed. */ ok1(tdb_delete(tdb, key) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); /* Re-add it, then add collision. */ ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); v = val + 1; ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); /* Can find both? */ ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS); ok1(d.dsize == data.dsize); free(d.dptr); v = val; ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS); ok1(d.dsize == data.dsize); free(d.dptr); /* Delete second one. */ v = val + 1; ok1(tdb_delete(tdb, key) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); /* Re-add */ ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); /* Now, try deleting first one. */ v = val; ok1(tdb_delete(tdb, key) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); /* Can still find second? */ v = val + 1; ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS); ok1(d.dsize == data.dsize); free(d.dptr); /* Now, this will be ideally placed. */ v = val + 2; ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); /* This will collide with both. */ v = val; ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); /* We can still find them all, right? */ ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS); ok1(d.dsize == data.dsize); free(d.dptr); v = val + 1; ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS); ok1(d.dsize == data.dsize); free(d.dptr); v = val + 2; ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS); ok1(d.dsize == data.dsize); free(d.dptr); /* And if we delete val + 1, that val + 2 should not move! */ v = val + 1; ok1(tdb_delete(tdb, key) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); v = val; ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS); ok1(d.dsize == data.dsize); free(d.dptr); v = val + 2; ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS); ok1(d.dsize == data.dsize); free(d.dptr); /* Delete those two, so we are empty. */ ok1(tdb_delete(tdb, key) == 0); v = val; ok1(tdb_delete(tdb, key) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); }
int main(int argc, char *argv[]) { unsigned int i; struct tdb_context *tdb; unsigned char *buffer; int flags[] = { TDB_DEFAULT, TDB_NOMMAP, TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT }; struct tdb_data key = tdb_mkdata("key", 3); struct tdb_data data; buffer = malloc(1000); for (i = 0; i < 1000; i++) buffer[i] = i; plan_tests(sizeof(flags) / sizeof(flags[0]) * 20 + 1); for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) { tdb = tdb_open("run-55-transaction.tdb", flags[i], O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr); ok1(tdb); if (!tdb) continue; ok1(tdb_transaction_start(tdb) == 0); data.dptr = buffer; data.dsize = 1000; ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS); ok1(data.dsize == 1000); ok1(memcmp(data.dptr, buffer, data.dsize) == 0); free(data.dptr); /* Cancelling a transaction means no store */ tdb_transaction_cancel(tdb); ok1(tdb->file->allrecord_lock.count == 0 && tdb->file->num_lockrecs == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); ok1(tdb_fetch(tdb, key, &data) == TDB_ERR_NOEXIST); /* Commit the transaction. */ ok1(tdb_transaction_start(tdb) == 0); data.dptr = buffer; data.dsize = 1000; ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS); ok1(data.dsize == 1000); ok1(memcmp(data.dptr, buffer, data.dsize) == 0); free(data.dptr); ok1(tdb_transaction_commit(tdb) == 0); ok1(tdb->file->allrecord_lock.count == 0 && tdb->file->num_lockrecs == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS); ok1(data.dsize == 1000); ok1(memcmp(data.dptr, buffer, data.dsize) == 0); free(data.dptr); tdb_close(tdb); } ok1(tap_log_messages == 0); free(buffer); return exit_status(); }