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()); }
static bool store_records(struct tdb_context *tdb) { int i; struct tdb_data key = { (unsigned char *)&i, sizeof(i) }; struct tdb_data d, data = { (unsigned char *)&i, sizeof(i) }; for (i = 0; i < 1000; i++) { if (tdb_store(tdb, key, data, TDB_REPLACE) != 0) return false; tdb_fetch(tdb, key, &d); if (!tdb_deq(d, data)) return false; free(d.dptr); } return true; }
static enum TDB_ERROR parse(TDB_DATA key, TDB_DATA data, TDB_DATA *expected) { if (!tdb_deq(data, *expected)) return TDB_ERR_EINVAL; return TDB_SUCCESS; }
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, 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(); }