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 = 1024; plan_tests(5); tdb = tdb_open(NULL, TDB_INTERNAL|TDB_VERSION1, O_CREAT|O_TRUNC|O_RDWR, 0600, &hsize); ok1(tdb); /* Tickle bug on appending zero length buffer to zero length buffer. */ key = tdb_mkdata("hi", strlen("hi")); data = tdb_mkdata("world", 0); ok1(tdb_append(tdb, key, data) == TDB_SUCCESS); ok1(tdb_append(tdb, key, data) == TDB_SUCCESS); ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS); ok1(data.dsize == 0); free(data.dptr); tdb_close(tdb); 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[]) { 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[]) { 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 = 1024; plan_tests(13); agent = prepare_external_agent1(); if (!agent) err(1, "preparing agent"); tdb = tdb_open("run-traverse-in-transaction.tdb1", TDB_VERSION1, O_CREAT|O_TRUNC|O_RDWR, 0600, &hsize); ok1(tdb); key = tdb_mkdata("hi", strlen("hi")); data = tdb_mkdata("world", strlen("world")); ok1(tdb_store(tdb, key, data, TDB_INSERT) == TDB_SUCCESS); ok1(external_agent_operation1(agent, OPEN, tdb->name) == SUCCESS); ok1(tdb_transaction_start(tdb) == TDB_SUCCESS); ok1(external_agent_operation1(agent, TRANSACTION_START, tdb->name) == WOULD_HAVE_BLOCKED); tdb_traverse(tdb, traverse, NULL); /* That should *not* release the transaction lock! */ ok1(external_agent_operation1(agent, TRANSACTION_START, tdb->name) == WOULD_HAVE_BLOCKED); tdb_traverse(tdb, traverse, NULL); /* That should *not* release the transaction lock! */ ok1(external_agent_operation1(agent, TRANSACTION_START, tdb->name) == WOULD_HAVE_BLOCKED); ok1(tdb_transaction_commit(tdb) == TDB_SUCCESS); /* Now we should be fine. */ ok1(external_agent_operation1(agent, TRANSACTION_START, tdb->name) == 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[]) { 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[]) { 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(); }
enum TDB_ERROR tdb_parse_record_(struct tdb_context *tdb, TDB_DATA key, enum TDB_ERROR (*parse)(TDB_DATA k, TDB_DATA d, void *data), void *data) { tdb_off_t off; struct tdb_used_record rec; struct hash_info h; enum TDB_ERROR ecode; if (tdb->flags & TDB_VERSION1) { return tdb->last_error = tdb1_parse_record(tdb, key, parse, data); } off = find_and_lock(tdb, key, F_RDLCK, &h, &rec, NULL); if (TDB_OFF_IS_ERR(off)) { return tdb->last_error = TDB_OFF_TO_ERR(off); } if (!off) { ecode = TDB_ERR_NOEXIST; } else { const void *dptr; dptr = tdb_access_read(tdb, off + sizeof(rec) + key.dsize, rec_data_length(&rec), false); if (TDB_PTR_IS_ERR(dptr)) { ecode = TDB_PTR_ERR(dptr); } else { TDB_DATA d = tdb_mkdata(dptr, rec_data_length(&rec)); ecode = parse(key, d, data); tdb_access_release(tdb, dptr); } } tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK); return tdb->last_error = ecode; }
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(); }
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; 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(); }
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(); }
static void speed_tdb(const char *tlimit) { unsigned timelimit = tlimit?atoi(tlimit):0; double t; int ops; if (timelimit == 0) timelimit = 5; ops = 0; printf("Testing store speed for %u seconds\n", timelimit); _start_timer(); do { long int r = random(); TDB_DATA key, dbuf; key = tdb_mkdata("store test", strlen("store test")); dbuf.dptr = (unsigned char *)&r; dbuf.dsize = sizeof(r); tdb_store(tdb, key, dbuf, TDB_REPLACE); t = _end_timer(); ops++; } while (t < timelimit); printf("%10.3f ops/sec\n", ops/t); ops = 0; printf("Testing fetch speed for %u seconds\n", timelimit); _start_timer(); do { long int r = random(); TDB_DATA key, dbuf; key = tdb_mkdata("store test", strlen("store test")); dbuf.dptr = (unsigned char *)&r; dbuf.dsize = sizeof(r); tdb_fetch(tdb, key, &dbuf); t = _end_timer(); ops++; } while (t < timelimit); printf("%10.3f ops/sec\n", ops/t); ops = 0; printf("Testing transaction speed for %u seconds\n", timelimit); _start_timer(); do { long int r = random(); TDB_DATA key, dbuf; key = tdb_mkdata("transaction test", strlen("transaction test")); dbuf.dptr = (unsigned char *)&r; dbuf.dsize = sizeof(r); tdb_transaction_start(tdb); tdb_store(tdb, key, dbuf, TDB_REPLACE); tdb_transaction_commit(tdb); t = _end_timer(); ops++; } while (t < timelimit); printf("%10.3f ops/sec\n", ops/t); ops = 0; printf("Testing traverse speed for %u seconds\n", timelimit); _start_timer(); do { tdb_traverse(tdb, traverse_fn, NULL); t = _end_timer(); ops++; } while (t < timelimit); printf("%10.3f ops/sec\n", ops/t); }
int main(int argc, char *argv[]) { unsigned int i, extra_msgs; struct tdb_context *tdb; struct tdb_data key = tdb_mkdata("key", 3); struct tdb_data data = tdb_mkdata("data", 4); 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]) * 48); for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) { /* RW -> R0 */ tdb = tdb_open("run-92-get-set-readonly.tdb", flags[i], O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr); ok1(tdb); ok1(!(tdb_get_flags(tdb) & TDB_RDONLY)); /* TDB1 complains multiple times. */ if (flags[i] & TDB_VERSION1) { extra_msgs = 1; } else { extra_msgs = 0; } ok1(tdb_store(tdb, key, data, TDB_INSERT) == TDB_SUCCESS); tdb_add_flag(tdb, TDB_RDONLY); ok1(tdb_get_flags(tdb) & TDB_RDONLY); /* Can't store, append, delete. */ ok1(tdb_store(tdb, key, data, TDB_MODIFY) == TDB_ERR_RDONLY); ok1(tap_log_messages == 1); ok1(tdb_append(tdb, key, data) == TDB_ERR_RDONLY); tap_log_messages -= extra_msgs; ok1(tap_log_messages == 2); ok1(tdb_delete(tdb, key) == TDB_ERR_RDONLY); tap_log_messages -= extra_msgs; ok1(tap_log_messages == 3); /* Can't start a transaction, or any write lock. */ ok1(tdb_transaction_start(tdb) == TDB_ERR_RDONLY); ok1(tap_log_messages == 4); ok1(tdb_chainlock(tdb, key) == TDB_ERR_RDONLY); tap_log_messages -= extra_msgs; ok1(tap_log_messages == 5); ok1(tdb_lockall(tdb) == TDB_ERR_RDONLY); ok1(tap_log_messages == 6); ok1(tdb_wipe_all(tdb) == TDB_ERR_RDONLY); ok1(tap_log_messages == 7); /* Back to RW. */ tdb_remove_flag(tdb, TDB_RDONLY); ok1(!(tdb_get_flags(tdb) & TDB_RDONLY)); ok1(tdb_store(tdb, key, data, TDB_MODIFY) == TDB_SUCCESS); ok1(tdb_append(tdb, key, data) == TDB_SUCCESS); ok1(tdb_delete(tdb, key) == TDB_SUCCESS); ok1(tdb_transaction_start(tdb) == TDB_SUCCESS); ok1(tdb_store(tdb, key, data, TDB_INSERT) == TDB_SUCCESS); ok1(tdb_transaction_commit(tdb) == TDB_SUCCESS); ok1(tdb_chainlock(tdb, key) == TDB_SUCCESS); tdb_chainunlock(tdb, key); ok1(tdb_lockall(tdb) == TDB_SUCCESS); tdb_unlockall(tdb); ok1(tdb_wipe_all(tdb) == TDB_SUCCESS); ok1(tap_log_messages == 7); tdb_close(tdb); /* R0 -> RW */ tdb = tdb_open("run-92-get-set-readonly.tdb", flags[i], O_RDONLY, 0600, &tap_log_attr); ok1(tdb); ok1(tdb_get_flags(tdb) & TDB_RDONLY); /* Can't store, append, delete. */ ok1(tdb_store(tdb, key, data, TDB_INSERT) == TDB_ERR_RDONLY); ok1(tap_log_messages == 8); ok1(tdb_append(tdb, key, data) == TDB_ERR_RDONLY); tap_log_messages -= extra_msgs; ok1(tap_log_messages == 9); ok1(tdb_delete(tdb, key) == TDB_ERR_RDONLY); tap_log_messages -= extra_msgs; ok1(tap_log_messages == 10); /* Can't start a transaction, or any write lock. */ ok1(tdb_transaction_start(tdb) == TDB_ERR_RDONLY); ok1(tap_log_messages == 11); ok1(tdb_chainlock(tdb, key) == TDB_ERR_RDONLY); tap_log_messages -= extra_msgs; ok1(tap_log_messages == 12); ok1(tdb_lockall(tdb) == TDB_ERR_RDONLY); ok1(tap_log_messages == 13); ok1(tdb_wipe_all(tdb) == TDB_ERR_RDONLY); ok1(tap_log_messages == 14); /* Can't remove TDB_RDONLY since we opened with O_RDONLY */ tdb_remove_flag(tdb, TDB_RDONLY); ok1(tap_log_messages == 15); ok1(tdb_get_flags(tdb) & TDB_RDONLY); tdb_close(tdb); ok1(tap_log_messages == 15); 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; }