static int do_child(int tdb_flags, int to, int from) { struct tdb_context *tdb; unsigned int log_count; struct tdb_logging_context log_ctx = { log_fn, &log_count }; int ret; char c = 0; tdb = tdb_open_ex("mutex-transaction1.tdb", 3, tdb_flags, O_RDWR|O_CREAT, 0755, &log_ctx, NULL); ok(tdb, "tdb_open_ex should succeed"); ret = tdb_transaction_start(tdb); ok(ret == 0, "tdb_transaction_start should succeed"); ret = tdb_store(tdb, key, data, TDB_INSERT); ok(ret == 0, "tdb_store(tdb, key, data, TDB_INSERT) should succeed"); write(to, &c, sizeof(c)); read(from, &c, sizeof(c)); ret = tdb_transaction_cancel(tdb); ok(ret == 0, "tdb_transaction_cancel should succeed"); write(to, &c, sizeof(c)); read(from, &c, sizeof(c)); ret = tdb_transaction_start(tdb); ok(ret == 0, "tdb_transaction_start should succeed"); ret = tdb_store(tdb, key, data, TDB_INSERT); ok(ret == 0, "tdb_store(tdb, key, data, TDB_INSERT) should succeed"); write(to, &c, sizeof(c)); read(from, &c, sizeof(c)); ret = tdb_transaction_commit(tdb); ok(ret == 0, "tdb_transaction_commit should succeed"); write(to, &c, sizeof(c)); read(from, &c, sizeof(c)); ret = tdb_transaction_start(tdb); ok(ret == 0, "tdb_transaction_start should succeed"); ret = tdb_store(tdb, key, key, TDB_REPLACE); ok(ret == 0, "tdb_store(tdb, key, data, TDB_REPLACE) should succeed"); write(to, &c, sizeof(c)); read(from, &c, sizeof(c)); ret = tdb_transaction_commit(tdb); ok(ret == 0, "tdb_transaction_commit should succeed"); write(to, &c, sizeof(c)); read(from, &c, sizeof(c)); return 0; }
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(); }
/* * On rmdir we need to delete the tdb record */ static int posix_eadb_rmdir(vfs_handle_struct *handle, const char *path) { NTSTATUS status; struct tdb_wrap *ea_tdb; int ret; SMB_VFS_HANDLE_GET_DATA(handle, ea_tdb, struct tdb_wrap, return -1); if (tdb_transaction_start(ea_tdb->tdb) != 0) { return -1; } status = unlink_posix_eadb_raw(ea_tdb, path, -1); if (!NT_STATUS_IS_OK(status)) { tdb_transaction_cancel(ea_tdb->tdb); } ret = SMB_VFS_NEXT_RMDIR(handle, path); if (ret == -1) { tdb_transaction_cancel(ea_tdb->tdb); } else { if (tdb_transaction_commit(ea_tdb->tdb) != 0) { return -1; } } return ret; }
/* * On unlink we need to delete the tdb record */ static int posix_eadb_unlink(vfs_handle_struct *handle, const struct smb_filename *smb_fname) { struct smb_filename *smb_fname_tmp = NULL; int ret = -1; struct tdb_wrap *ea_tdb; SMB_VFS_HANDLE_GET_DATA(handle, ea_tdb, struct tdb_wrap, return -1); smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname); if (smb_fname_tmp == NULL) { errno = ENOMEM; return -1; } if (lp_posix_pathnames()) { ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_tmp); } else { ret = SMB_VFS_NEXT_STAT(handle, smb_fname_tmp); } if (ret == -1) { goto out; } if (smb_fname_tmp->st.st_ex_nlink == 1) { NTSTATUS status; /* Only remove record on last link to file. */ if (tdb_transaction_start(ea_tdb->tdb) != 0) { ret = -1; goto out; } status = unlink_posix_eadb_raw(ea_tdb, smb_fname->base_name, -1); if (!NT_STATUS_IS_OK(status)) { tdb_transaction_cancel(ea_tdb->tdb); ret = -1; goto out; } } ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_tmp); if (ret == -1) { tdb_transaction_cancel(ea_tdb->tdb); goto out; } else { if (tdb_transaction_commit(ea_tdb->tdb) != 0) { ret = -1; goto out; } } out: TALLOC_FREE(smb_fname_tmp); return ret; }
static int run_child(int i, int seed, unsigned num_loops, unsigned start, int tdb_flags) { struct sigaction act = { .sa_sigaction = segv_handler, .sa_flags = SA_SIGINFO }; sigaction(11, &act, NULL); db = tdb_open("torture.tdb", tdb_flags, O_RDWR | O_CREAT, 0600, &log_attr); if (!db) { fatal(NULL, "db open failed"); } #if 0 if (i == 0) { printf("pid %i\n", getpid()); sleep(9); } else sleep(10); #endif srand(seed + i); srandom(seed + i); /* Set global, then we're ready to handle being killed. */ loopnum = start; signal(SIGUSR1, send_count_and_suicide); for (;loopnum<num_loops && error_count == 0;loopnum++) { addrec_db(); } if (error_count == 0) { tdb_traverse(db, NULL, NULL); #if TRANSACTION_PROB if (always_transaction) { while (in_transaction) { tdb_transaction_cancel(db); in_transaction--; } if (tdb_transaction_start(db) != 0) fatal(db, "tdb_transaction_start failed"); } #endif tdb_traverse(db, traverse_fn, NULL); tdb_traverse(db, traverse_fn, NULL); #if TRANSACTION_PROB if (always_transaction) { if (tdb_transaction_commit(db) != 0) fatal(db, "tdb_transaction_commit failed"); } #endif } tdb_close(db); return (error_count < 100 ? error_count : 100); }
static PyObject *obj_transaction_start(PyTdbObject *self) { int ret; PyErr_TDB_RAISE_IF_CLOSED(self); ret = tdb_transaction_start(self->ctx); PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); Py_RETURN_NONE; }
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.dsize = strlen("hi"); key.dptr = (void *)"hi"; data.dptr = (void *)"world"; data.dsize = 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(); }
static int ltdb_start_trans(struct ldb_module *module) { void *data = ldb_module_get_private(module); struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); if (tdb_transaction_start(ltdb->tdb) != 0) { return ltdb_err_map(tdb_error(ltdb->tdb)); } ltdb->in_transaction++; ltdb_index_transaction_start(module); return LDB_SUCCESS; }
int main(int argc, char *argv[]) { struct tdb_context *tdb; TDB_DATA key, data; plan_tests(13); agent = prepare_external_agent(); if (!agent) err(1, "preparing agent"); tdb = tdb_open_ex("run-traverse-in-transaction.tdb", 1024, TDB_CLEAR_IF_FIRST, O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); ok1(tdb); key.dsize = strlen("hi"); key.dptr = (void *)"hi"; data.dptr = (void *)"world"; data.dsize = strlen("world"); ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); ok1(external_agent_operation(agent, OPEN, tdb_name(tdb)) == SUCCESS); ok1(tdb_transaction_start(tdb) == 0); ok1(external_agent_operation(agent, TRANSACTION_START, tdb_name(tdb)) == WOULD_HAVE_BLOCKED); tdb_traverse(tdb, traverse, NULL); /* That should *not* release the transaction lock! */ ok1(external_agent_operation(agent, TRANSACTION_START, tdb_name(tdb)) == WOULD_HAVE_BLOCKED); tdb_traverse_read(tdb, traverse, NULL); /* That should *not* release the transaction lock! */ ok1(external_agent_operation(agent, TRANSACTION_START, tdb_name(tdb)) == WOULD_HAVE_BLOCKED); ok1(tdb_transaction_commit(tdb) == 0); /* Now we should be fine. */ ok1(external_agent_operation(agent, TRANSACTION_START, tdb_name(tdb)) == SUCCESS); tdb_close(tdb); return exit_status(); }
int main(int argc, char *argv[]) { const int flags[] = { TDB_DEFAULT, TDB_CLEAR_IF_FIRST, TDB_NOMMAP, TDB_CLEAR_IF_FIRST | TDB_NOMMAP }; int i; struct tdb_context *tdb; TDB_DATA key, data; plan_tests(20); agent = prepare_external_agent(); if (!agent) err(1, "preparing agent"); unlock_callback = after_unlock; for (i = 0; i < sizeof(flags)/sizeof(flags[0]); i++) { clear_if_first = (flags[i] & TDB_CLEAR_IF_FIRST); diag("Test with %s and %s\n", clear_if_first ? "CLEAR" : "DEFAULT", (flags[i] & TDB_NOMMAP) ? "no mmap" : "mmap"); unlink(TEST_DBNAME); tdb = tdb_open_ex(TEST_DBNAME, 1024, flags[i], O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); ok1(tdb); opened = true; ok1(tdb_transaction_start(tdb) == 0); key.dsize = strlen("hi"); key.dptr = (void *)"hi"; data.dptr = (void *)"world"; data.dsize = strlen("world"); ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); ok1(tdb_transaction_commit(tdb) == 0); ok(!errors, "We had %u open errors", errors); opened = false; tdb_close(tdb); } return exit_status(); }
enum TDB_ERROR tdb_repack(struct tdb_context *tdb) { struct tdb_context *tmp_db; struct traverse_state state; state.error = tdb_transaction_start(tdb); if (state.error != TDB_SUCCESS) { return state.error; } tmp_db = tdb_open("tmpdb", TDB_INTERNAL, O_RDWR|O_CREAT, 0, NULL); if (tmp_db == NULL) { state.error = tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR, __location__ " Failed to create tmp_db"); tdb_transaction_cancel(tdb); return tdb->last_error = state.error; } state.dest_db = tmp_db; if (tdb_traverse(tdb, repack_traverse, &state) < 0) { goto fail; } state.error = tdb_wipe_all(tdb); if (state.error != TDB_SUCCESS) { goto fail; } state.dest_db = tdb; if (tdb_traverse(tmp_db, repack_traverse, &state) < 0) { goto fail; } tdb_close(tmp_db); return tdb_transaction_commit(tdb); fail: tdb_transaction_cancel(tdb); tdb_close(tmp_db); return state.error; }
static int run_child(const char *filename, int i, int seed, unsigned num_loops, unsigned start) { db = tdb_open_ex(filename, hash_size, TDB_DEFAULT, O_RDWR | O_CREAT, 0600, &log_ctx, NULL); if (!db) { fatal("db open failed"); } srand(seed + i); srandom(seed + i); /* Set global, then we're ready to handle being killed. */ loopnum = start; signal(SIGUSR1, send_count_and_suicide); for (;loopnum<num_loops && error_count == 0;loopnum++) { addrec_db(); } if (error_count == 0) { tdb_traverse_read(db, NULL, NULL); if (always_transaction) { while (in_transaction) { tdb_transaction_cancel(db); in_transaction--; } if (tdb_transaction_start(db) != 0) fatal("tdb_transaction_start failed"); } tdb_traverse(db, traverse_fn, NULL); tdb_traverse(db, traverse_fn, NULL); if (always_transaction) { if (tdb_transaction_commit(db) != 0) fatal("tdb_transaction_commit failed"); } } tdb_close(db); return (error_count < 100 ? error_count : 100); }
/* * Transaction start */ int partition_metadata_start_trans(struct ldb_module *module) { struct partition_private_data *data; struct tdb_context *tdb; data = talloc_get_type_abort(ldb_module_get_private(module), struct partition_private_data); if (!data || !data->metadata || !data->metadata->db) { return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR, "partition_metadata: metadata not initialized"); } tdb = data->metadata->db->tdb; if (tdb_transaction_start(tdb) != 0) { return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR, tdb_errorstr(tdb)); } data->metadata->in_transaction++; return LDB_SUCCESS; }
enum TDB_ERROR tdb_transaction_start_nonblock(struct tdb_context *tdb) { union tdb_attribute locking, orig; enum TDB_ERROR ecode; orig.base.attr = TDB_ATTRIBUTE_FLOCK; ecode = tdb_get_attribute(tdb, &orig); if (ecode != TDB_SUCCESS) return ecode; /* Replace locking function with our own. */ locking = orig; locking.flock.data = &orig; locking.flock.lock = lock_nonblock; ecode = tdb_set_attribute(tdb, &locking); if (ecode != TDB_SUCCESS) return ecode; ecode = tdb_transaction_start(tdb); tdb_unset_attribute(tdb, TDB_ATTRIBUTE_FLOCK); return ecode; }
/** * Start a transaction on database */ static int db_transaction_start_handler(struct ctdb_db_context *ctdb_db, void *private_data) { bool freeze_transaction_started = *(bool *)private_data; int ret; tdb_add_flags(ctdb_db->ltdb->tdb, TDB_NOLOCK); if (freeze_transaction_started) { ret = tdb_transaction_cancel(ctdb_db->ltdb->tdb); if (ret != 0) { DEBUG(DEBUG_ERR, ("Failed to cancel transaction for db %s\n", ctdb_db->db_name)); } } ret = tdb_transaction_start(ctdb_db->ltdb->tdb); tdb_remove_flags(ctdb_db->ltdb->tdb, TDB_NOLOCK); if (ret != 0) { DEBUG(DEBUG_ERR, ("Failed to start transaction for db %s\n", ctdb_db->db_name)); return -1; } return 0; }
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, 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 int do_command(void) { COMMAND_TABLE *ctp = cmd_table; enum commands mycmd = CMD_HELP; int cmd_len; if (cmdname && strlen(cmdname) == 0) { mycmd = CMD_NEXT; } else { while (ctp->name) { cmd_len = strlen(ctp->name); if (strncmp(ctp->name,cmdname,cmd_len) == 0) { mycmd = ctp->cmd; break; } ctp++; } } switch (mycmd) { case CMD_CREATE_TDB: bIterate = 0; create_tdb(arg1); return 0; case CMD_OPEN_TDB: bIterate = 0; open_tdb(arg1); return 0; case CMD_SYSTEM: /* Shell command */ if (system(arg1) == -1) { terror("system() call failed\n"); } return 0; case CMD_QUIT: return 1; default: /* all the rest require a open database */ if (!tdb) { bIterate = 0; terror("database not open"); help(); return 0; } switch (mycmd) { case CMD_TRANSACTION_START: bIterate = 0; tdb_transaction_start(tdb); return 0; case CMD_TRANSACTION_COMMIT: bIterate = 0; tdb_transaction_commit(tdb); return 0; case CMD_REPACK: bIterate = 0; tdb_repack(tdb); return 0; case CMD_TRANSACTION_CANCEL: bIterate = 0; tdb_transaction_cancel(tdb); return 0; case CMD_ERASE: bIterate = 0; tdb_traverse(tdb, do_delete_fn, NULL); return 0; case CMD_DUMP: bIterate = 0; tdb_traverse(tdb, print_rec, NULL); return 0; case CMD_INSERT: bIterate = 0; insert_tdb(arg1, arg1len,arg2,arg2len); return 0; case CMD_MOVE: bIterate = 0; move_rec(arg1,arg1len,arg2); return 0; case CMD_STORE: bIterate = 0; store_tdb(arg1,arg1len,arg2,arg2len); return 0; case CMD_SHOW: bIterate = 0; show_tdb(arg1, arg1len); return 0; case CMD_KEYS: tdb_traverse(tdb, print_key, NULL); return 0; case CMD_HEXKEYS: tdb_traverse(tdb, print_hexkey, NULL); return 0; case CMD_DELETE: bIterate = 0; delete_tdb(arg1,arg1len); return 0; case CMD_LIST_HASH_FREE: tdb_dump_all(tdb); return 0; case CMD_LIST_FREE: tdb_printfreelist(tdb); return 0; case CMD_FREELIST_SIZE: { int size; size = tdb_freelist_size(tdb); if (size < 0) { printf("Error getting freelist size.\n"); } else { printf("freelist size: %d\n", size); } return 0; } case CMD_INFO: info_tdb(); return 0; case CMD_SPEED: speed_tdb(arg1); return 0; case CMD_MMAP: toggle_mmap(); return 0; case CMD_FIRST: bIterate = 1; first_record(tdb, &iterate_kbuf); return 0; case CMD_NEXT: if (bIterate) next_record(tdb, &iterate_kbuf); return 0; case CMD_CHECK: check_db(tdb); return 0; case CMD_HELP: help(); return 0; case CMD_CREATE_TDB: case CMD_OPEN_TDB: case CMD_SYSTEM: case CMD_QUIT: /* * unhandled commands. cases included here to avoid compiler * warnings. */ return 0; } } return 0; }
static void speed_tdb(const char *tlimit) { const char *str = "store test", *str2 = "transaction test"; 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.dptr = discard_const_p(uint8_t, str); key.dsize = strlen((char *)key.dptr); dbuf.dptr = (uint8_t *) &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 { TDB_DATA key; key.dptr = discard_const_p(uint8_t, str); key.dsize = strlen((char *)key.dptr); tdb_fetch(tdb, key); 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.dptr = discard_const_p(uint8_t, str2); key.dsize = strlen((char *)key.dptr); dbuf.dptr = (uint8_t *) &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); }
static int db_tdb_transaction_start(struct db_context *db) { struct db_tdb_ctx *db_ctx = talloc_get_type_abort(db->private_data, struct db_tdb_ctx); return tdb_transaction_start(db_ctx->wtdb->tdb) ? -1 : 0; }
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; }
static void addrec_db(void) { int klen, dlen; char *k, *d; TDB_DATA key, data; klen = 1 + (rand() % KEYLEN); dlen = 1 + (rand() % DATALEN); k = randbuf(klen); d = randbuf(dlen); key.dptr = (unsigned char *)k; key.dsize = klen+1; data.dptr = (unsigned char *)d; data.dsize = dlen+1; #if REOPEN_PROB if (in_transaction == 0 && random() % REOPEN_PROB == 0) { tdb_reopen_all(0); goto next; } #endif #if TRANSACTION_PROB if (in_transaction == 0 && (always_transaction || random() % TRANSACTION_PROB == 0)) { if (tdb_transaction_start(db) != 0) { fatal("tdb_transaction_start failed"); } in_transaction++; goto next; } if (in_transaction && random() % TRANSACTION_PROB == 0) { if (random() % TRANSACTION_PREPARE_PROB == 0) { if (tdb_transaction_prepare_commit(db) != 0) { fatal("tdb_transaction_prepare_commit failed"); } } if (tdb_transaction_commit(db) != 0) { fatal("tdb_transaction_commit failed"); } in_transaction--; goto next; } if (in_transaction && random() % TRANSACTION_PROB == 0) { if (tdb_transaction_cancel(db) != 0) { fatal("tdb_transaction_cancel failed"); } in_transaction--; goto next; } #endif #if DELETE_PROB if (random() % DELETE_PROB == 0) { tdb_delete(db, key); goto next; } #endif #if STORE_PROB if (random() % STORE_PROB == 0) { if (tdb_store(db, key, data, TDB_REPLACE) != 0) { fatal("tdb_store failed"); } goto next; } #endif #if APPEND_PROB if (random() % APPEND_PROB == 0) { if (tdb_append(db, key, data) != 0) { fatal("tdb_append failed"); } goto next; } #endif #if LOCKSTORE_PROB if (random() % LOCKSTORE_PROB == 0) { tdb_chainlock(db, key); data = tdb_fetch(db, key); if (tdb_store(db, key, data, TDB_REPLACE) != 0) { fatal("tdb_store failed"); } if (data.dptr) free(data.dptr); tdb_chainunlock(db, key); goto next; } #endif #if TRAVERSE_PROB if (random() % TRAVERSE_PROB == 0) { tdb_traverse(db, cull_traverse, NULL); goto next; } #endif #if TRAVERSE_READ_PROB if (random() % TRAVERSE_READ_PROB == 0) { tdb_traverse_read(db, NULL, NULL); goto next; } #endif data = tdb_fetch(db, key); if (data.dptr) free(data.dptr); next: free(k); free(d); }
/* carefully backup a tdb, validating the contents and only doing the backup if its OK this function is also used for restore */ static int backup_tdb(const char *old_name, const char *new_name, int hash_size, int nolock) { TDB_CONTEXT *tdb; TDB_CONTEXT *tdb_new; char *tmp_name; struct stat st; int count1, count2; tmp_name = add_suffix(new_name, ".tmp"); /* stat the old tdb to find its permissions */ if (stat(old_name, &st) != 0) { perror(old_name); free(tmp_name); return 1; } /* open the old tdb */ tdb = tdb_open_ex(old_name, 0, TDB_DEFAULT | (nolock ? TDB_NOLOCK : 0), O_RDWR, 0, &log_ctx, NULL); if (!tdb) { printf("Failed to open %s\n", old_name); free(tmp_name); return 1; } /* create the new tdb */ unlink(tmp_name); tdb_new = tdb_open_ex(tmp_name, hash_size ? hash_size : tdb_hash_size(tdb), TDB_DEFAULT, O_RDWR|O_CREAT|O_EXCL, st.st_mode & 0777, &log_ctx, NULL); if (!tdb_new) { perror(tmp_name); free(tmp_name); return 1; } if (tdb_transaction_start(tdb) != 0) { printf("Failed to start transaction on old tdb\n"); tdb_close(tdb); tdb_close(tdb_new); unlink(tmp_name); free(tmp_name); return 1; } /* lock the backup tdb so that nobody else can change it */ if (tdb_lockall(tdb_new) != 0) { printf("Failed to lock backup tdb\n"); tdb_close(tdb); tdb_close(tdb_new); unlink(tmp_name); free(tmp_name); return 1; } failed = 0; /* traverse and copy */ count1 = tdb_traverse(tdb, copy_fn, (void *)tdb_new); if (count1 < 0 || failed) { fprintf(stderr,"failed to copy %s\n", old_name); tdb_close(tdb); tdb_close(tdb_new); unlink(tmp_name); free(tmp_name); return 1; } /* close the old tdb */ tdb_close(tdb); /* copy done, unlock the backup tdb */ tdb_unlockall(tdb_new); #ifdef HAVE_FDATASYNC if (fdatasync(tdb_fd(tdb_new)) != 0) { #else if (fsync(tdb_fd(tdb_new)) != 0) { #endif /* not fatal */ fprintf(stderr, "failed to fsync backup file\n"); } /* close the new tdb and re-open read-only */ tdb_close(tdb_new); tdb_new = tdb_open_ex(tmp_name, 0, TDB_DEFAULT, O_RDONLY, 0, &log_ctx, NULL); if (!tdb_new) { fprintf(stderr,"failed to reopen %s\n", tmp_name); unlink(tmp_name); perror(tmp_name); free(tmp_name); return 1; } /* traverse the new tdb to confirm */ count2 = tdb_traverse(tdb_new, test_fn, NULL); if (count2 != count1) { fprintf(stderr,"failed to copy %s\n", old_name); tdb_close(tdb_new); unlink(tmp_name); free(tmp_name); return 1; } /* close the new tdb and rename it to .bak */ tdb_close(tdb_new); if (rename(tmp_name, new_name) != 0) { perror(new_name); free(tmp_name); return 1; } free(tmp_name); return 0; } /* verify a tdb and if it is corrupt then restore from *.bak */ static int verify_tdb(const char *fname, const char *bak_name) { TDB_CONTEXT *tdb; int count = -1; /* open the tdb */ tdb = tdb_open_ex(fname, 0, 0, O_RDONLY, 0, &log_ctx, NULL); /* traverse the tdb, then close it */ if (tdb) { count = tdb_traverse(tdb, test_fn, NULL); tdb_close(tdb); } /* count is < 0 means an error */ if (count < 0) { printf("restoring %s\n", fname); return backup_tdb(bak_name, fname, 0, 0); } printf("%s : %d records\n", fname, count); return 0; }
static errcode_t undo_write_tdb(io_channel channel, unsigned long long block, int count) { int size, sz; unsigned long long block_num, backing_blk_num; errcode_t retval = 0; ext2_loff_t offset; struct undo_private_data *data; TDB_DATA tdb_key, tdb_data; unsigned char *read_ptr; unsigned long long end_block; data = (struct undo_private_data *) channel->private_data; if (data->tdb == NULL) { /* * Transaction database not initialized */ return 0; } if (count == 1) size = channel->block_size; else { if (count < 0) size = -count; else size = count * channel->block_size; } /* * Data is stored in tdb database as blocks of tdb_data_size size * This helps in efficient lookup further. * * We divide the disk to blocks of tdb_data_size. */ offset = (block * channel->block_size) + data->offset ; block_num = offset / data->tdb_data_size; end_block = (offset + size) / data->tdb_data_size; tdb_transaction_start(data->tdb); while (block_num <= end_block ) { tdb_key.dptr = (unsigned char *)&block_num; tdb_key.dsize = sizeof(block_num); /* * Check if we have the record already */ if (tdb_exists(data->tdb, tdb_key)) { /* Try the next block */ block_num++; continue; } /* * Read one block using the backing I/O manager * The backing I/O manager block size may be * different from the tdb_data_size. * Also we need to recalcuate the block number with respect * to the backing I/O manager. */ offset = block_num * data->tdb_data_size; backing_blk_num = (offset - data->offset) / channel->block_size; count = data->tdb_data_size + ((offset - data->offset) % channel->block_size); retval = ext2fs_get_mem(count, &read_ptr); if (retval) { tdb_transaction_cancel(data->tdb); return retval; } memset(read_ptr, 0, count); actual_size = 0; if ((count % channel->block_size) == 0) sz = count / channel->block_size; else sz = -count; retval = io_channel_read_blk64(data->real, backing_blk_num, sz, read_ptr); if (retval) { if (retval != EXT2_ET_SHORT_READ) { free(read_ptr); tdb_transaction_cancel(data->tdb); return retval; } /* * short read so update the record size * accordingly */ tdb_data.dsize = actual_size; } else { tdb_data.dsize = data->tdb_data_size; } tdb_data.dptr = read_ptr + ((offset - data->offset) % channel->block_size); #ifdef DEBUG printf("Printing with key %lld data %x and size %d\n", block_num, tdb_data.dptr, tdb_data.dsize); #endif if (!data->tdb_written) { data->tdb_written = 1; /* Write the blocksize to tdb file */ retval = write_block_size(data->tdb, data->tdb_data_size); if (retval) { tdb_transaction_cancel(data->tdb); retval = EXT2_ET_TDB_ERR_IO; free(read_ptr); return retval; } } retval = tdb_store(data->tdb, tdb_key, tdb_data, TDB_INSERT); if (retval == -1) { /* * TDB_ERR_EXISTS cannot happen because we * have already verified it doesn't exist */ tdb_transaction_cancel(data->tdb); retval = EXT2_ET_TDB_ERR_IO; free(read_ptr); return retval; } free(read_ptr); /* Next block */ block_num++; } tdb_transaction_commit(data->tdb); return retval; }
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[]) { struct tdb_context *tdb; TDB_DATA key, orig_data, data; uint32_t hashval; tdb_off_t rec_ptr; struct tdb_record rec; int ret; plan_tests(24); tdb = tdb_open_ex("run-36-file.tdb", 1024, TDB_CLEAR_IF_FIRST, O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); ok1(tdb); tdb->methods = &large_io_methods; key.dsize = strlen("hi"); key.dptr = (void *)"hi"; orig_data.dsize = strlen("world"); orig_data.dptr = (void *)"world"; /* Enlarge the file (internally multiplies by 2). */ ret = tdb_expand(tdb, 1500000000); #ifdef HAVE_INCOHERENT_MMAP /* This can fail due to mmap failure on 32 bit systems. */ if (ret == -1) { /* These should now fail. */ ok1(tdb_store(tdb, key, orig_data, TDB_INSERT) == -1); data = tdb_fetch(tdb, key); ok1(data.dptr == NULL); ok1(tdb_traverse(tdb, test_traverse, &orig_data) == -1); ok1(tdb_delete(tdb, key) == -1); ok1(tdb_traverse(tdb, test_traverse, NULL) == -1); /* Skip the rest... */ for (ret = 0; ret < 24 - 6; ret++) ok1(1); tdb_close(tdb); return exit_status(); } #endif ok1(ret == 0); /* Put an entry in, and check it. */ ok1(tdb_store(tdb, key, orig_data, TDB_INSERT) == 0); data = tdb_fetch(tdb, key); ok1(data.dsize == strlen("world")); ok1(memcmp(data.dptr, "world", strlen("world")) == 0); free(data.dptr); /* That currently fills at the end, make sure that's true. */ hashval = tdb->hash_fn(&key); rec_ptr = tdb_find_lock_hash(tdb, key, hashval, F_RDLCK, &rec); ok1(rec_ptr); ok1(rec_ptr > 2U*1024*1024*1024); tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); /* Traverse must work. */ ok1(tdb_traverse(tdb, test_traverse, &orig_data) == 1); /* Delete should work. */ ok1(tdb_delete(tdb, key) == 0); ok1(tdb_traverse(tdb, test_traverse, NULL) == 0); /* Transactions should work. */ ok1(tdb_transaction_start(tdb) == 0); ok1(tdb_store(tdb, key, orig_data, TDB_INSERT) == 0); data = tdb_fetch(tdb, key); ok1(data.dsize == strlen("world")); ok1(memcmp(data.dptr, "world", strlen("world")) == 0); free(data.dptr); ok1(tdb_transaction_commit(tdb) == 0); ok1(tdb_traverse(tdb, test_traverse, &orig_data) == 1); tdb_close(tdb); return exit_status(); }
/* The code should barf on TDBs created with rwlocks. */ int main(int argc, char *argv[]) { struct tdb_context *tdb; unsigned int log_count; struct tdb_logging_context log_ctx = { log_fn, &log_count }; int ret, status; pid_t child, wait_ret; int fromchild[2]; int tochild[2]; TDB_DATA val; char c; int tdb_flags; bool runtime_support; runtime_support = tdb_runtime_check_for_robust_mutexes(); if (!runtime_support) { skip(1, "No robust mutex support"); return exit_status(); } key.dsize = strlen("hi"); key.dptr = discard_const_p(uint8_t, "hi"); data.dsize = strlen("world"); data.dptr = discard_const_p(uint8_t, "world"); pipe(fromchild); pipe(tochild); tdb_flags = TDB_INCOMPATIBLE_HASH| TDB_MUTEX_LOCKING| TDB_CLEAR_IF_FIRST; child = fork(); if (child == 0) { close(fromchild[0]); close(tochild[1]); return do_child(tdb_flags, fromchild[1], tochild[0]); } close(fromchild[1]); close(tochild[0]); read(fromchild[0], &c, sizeof(c)); tdb = tdb_open_ex("mutex-transaction1.tdb", 0, tdb_flags, O_RDWR|O_CREAT, 0755, &log_ctx, NULL); ok(tdb, "tdb_open_ex should succeed"); /* * The child has the transaction running */ ret = tdb_transaction_start_nonblock(tdb); ok(ret == -1, "tdb_transaction_start_nonblock not succeed"); ret = tdb_chainlock_nonblock(tdb, key); ok(ret == -1, "tdb_chainlock_nonblock should not succeed"); /* * We can still read */ ret = tdb_exists(tdb, key); ok(ret == 0, "tdb_exists(tdb, key) should return 0"); val = tdb_fetch(tdb, key); ok(val.dsize == 0, "tdb_fetch(tdb, key) should return an empty value"); write(tochild[1], &c, sizeof(c)); /* * When the child canceled we can start... */ ret = tdb_transaction_start(tdb); ok(ret == 0, "tdb_transaction_start should succeed"); read(fromchild[0], &c, sizeof(c)); write(tochild[1], &c, sizeof(c)); ret = tdb_transaction_cancel(tdb); ok(ret == 0, "tdb_transaction_cancel should succeed"); /* * When we canceled the child can start and store... */ read(fromchild[0], &c, sizeof(c)); /* * We still see the old values before the child commits... */ ret = tdb_exists(tdb, key); ok(ret == 0, "tdb_exists(tdb, key) should return 0"); val = tdb_fetch(tdb, key); ok(val.dsize == 0, "tdb_fetch(tdb, key) should return an empty value"); write(tochild[1], &c, sizeof(c)); read(fromchild[0], &c, sizeof(c)); /* * We see the new values after the commit... */ ret = tdb_exists(tdb, key); ok(ret == 1, "tdb_exists(tdb, key) should return 1"); val = tdb_fetch(tdb, key); ok(val.dsize != 0, "tdb_fetch(tdb, key) should return a value"); ok(val.dsize == data.dsize, "tdb_fetch(tdb, key) should return a value"); ok(memcmp(val.dptr, data.dptr, data.dsize) == 0, "tdb_fetch(tdb, key) should return a value"); write(tochild[1], &c, sizeof(c)); read(fromchild[0], &c, sizeof(c)); /* * The child started a new transaction and replaces the value, * but we still see the old values before the child commits... */ ret = tdb_exists(tdb, key); ok(ret == 1, "tdb_exists(tdb, key) should return 1"); val = tdb_fetch(tdb, key); ok(val.dsize != 0, "tdb_fetch(tdb, key) should return a value"); ok(val.dsize == data.dsize, "tdb_fetch(tdb, key) should return a value"); ok(memcmp(val.dptr, data.dptr, data.dsize) == 0, "tdb_fetch(tdb, key) should return a value"); write(tochild[1], &c, sizeof(c)); read(fromchild[0], &c, sizeof(c)); /* * We see the new values after the commit... */ ret = tdb_exists(tdb, key); ok(ret == 1, "tdb_exists(tdb, key) should return 1"); val = tdb_fetch(tdb, key); ok(val.dsize != 0, "tdb_fetch(tdb, key) should return a value"); ok(val.dsize == key.dsize, "tdb_fetch(tdb, key) should return a value"); ok(memcmp(val.dptr, key.dptr, key.dsize) == 0, "tdb_fetch(tdb, key) should return a value"); write(tochild[1], &c, sizeof(c)); wait_ret = wait(&status); ok(wait_ret == child, "child should have exited correctly"); diag("done"); return exit_status(); }
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(); }
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(); }
static BOOL init_registry_data( void ) { pstring path, base, remaining; fstring keyname, subkeyname; REGSUBKEY_CTR *subkeys; REGVAL_CTR *values; int i; const char *p, *p2; UNISTR2 data; /* * There are potentially quite a few store operations which are all * indiviually wrapped in tdb transactions. Wrapping them in a single * transaction gives just a single transaction_commit() to actually do * its fsync()s. See tdb/common/transaction.c for info about nested * transaction behaviour. */ if ( tdb_transaction_start( tdb_reg ) == -1 ) { DEBUG(0, ("init_registry_data: tdb_transaction_start " "failed\n")); return False; } /* loop over all of the predefined paths and add each component */ for ( i=0; builtin_registry_paths[i] != NULL; i++ ) { DEBUG(6,("init_registry_data: Adding [%s]\n", builtin_registry_paths[i])); pstrcpy( path, builtin_registry_paths[i] ); pstrcpy( base, "" ); p = path; while ( next_token(&p, keyname, "\\", sizeof(keyname)) ) { /* build up the registry path from the components */ if ( *base ) pstrcat( base, "\\" ); pstrcat( base, keyname ); /* get the immediate subkeyname (if we have one ) */ *subkeyname = '\0'; if ( *p ) { pstrcpy( remaining, p ); p2 = remaining; if ( !next_token(&p2, subkeyname, "\\", sizeof(subkeyname)) ) fstrcpy( subkeyname, p2 ); } DEBUG(10,("init_registry_data: Storing key [%s] with subkey [%s]\n", base, *subkeyname ? subkeyname : "NULL")); /* we don't really care if the lookup succeeds or not since we are about to update the record. We just want any subkeys already present */ if ( !(subkeys = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) ) { DEBUG(0,("talloc() failure!\n")); goto fail; } regdb_fetch_keys( base, subkeys ); if ( *subkeyname ) regsubkey_ctr_addkey( subkeys, subkeyname ); if ( !regdb_store_keys( base, subkeys )) goto fail; TALLOC_FREE( subkeys ); } } /* loop over all of the predefined values and add each component */ for ( i=0; builtin_registry_values[i].path != NULL; i++ ) { if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) ) { DEBUG(0,("talloc() failure!\n")); goto fail; } regdb_fetch_values( builtin_registry_values[i].path, values ); /* preserve existing values across restarts. Only add new ones */ if ( !regval_ctr_key_exists( values, builtin_registry_values[i].valuename ) ) { switch( builtin_registry_values[i].type ) { case REG_DWORD: regval_ctr_addvalue( values, builtin_registry_values[i].valuename, REG_DWORD, (char*)&builtin_registry_values[i].data.dw_value, sizeof(uint32) ); break; case REG_SZ: init_unistr2( &data, builtin_registry_values[i].data.string, UNI_STR_TERMINATE); regval_ctr_addvalue( values, builtin_registry_values[i].valuename, REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); break; default: DEBUG(0,("init_registry_data: invalid value type in builtin_registry_values [%d]\n", builtin_registry_values[i].type)); } regdb_store_values( builtin_registry_values[i].path, values ); } TALLOC_FREE( values ); } if (tdb_transaction_commit( tdb_reg ) == -1) { DEBUG(0, ("init_registry_data: Could not commit " "transaction\n")); return False; } return True; fail: if (tdb_transaction_cancel( tdb_reg ) == -1) { smb_panic("init_registry_data: tdb_transaction_cancel " "failed\n"); } return False; }