/* * 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 ltdb_del_trans(struct ldb_module *module) { void *data = ldb_module_get_private(module); struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); ltdb->in_transaction--; if (ltdb_index_transaction_cancel(module) != 0) { tdb_transaction_cancel(ltdb->tdb); return ltdb_err_map(tdb_error(ltdb->tdb)); } tdb_transaction_cancel(ltdb->tdb); return LDB_SUCCESS; }
static int db_tdb_transaction_cancel(struct db_context *db) { struct db_tdb_ctx *db_ctx = talloc_get_type_abort(db->private_data, struct db_tdb_ctx); tdb_transaction_cancel(db_ctx->wtdb->tdb); return 0; }
/** * Close a database. * * @returns -1 for error; 0 for success. **/ int tdb_close(struct tdb_context *tdb) { struct tdb_context **i; int ret = 0; if (tdb->transaction) { tdb_transaction_cancel(tdb); } if (tdb->map_ptr) { if (tdb->flags & TDB_INTERNAL) SAFE_FREE(tdb->map_ptr); else tdb_munmap(tdb); } SAFE_FREE(tdb->name); if (tdb->fd != -1) ret = close(tdb->fd); SAFE_FREE(tdb->locked); /* Remove from contexts list */ for (i = &tdbs; *i; i = &(*i)->next) { if (*i == tdb) { *i = tdb->next; break; } } memset(tdb, 0, sizeof(*tdb)); SAFE_FREE(tdb); return ret; }
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; }
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_cancel(PyTdbObject *self) { int ret; PyErr_TDB_RAISE_IF_CLOSED(self); ret = tdb_transaction_cancel(self->ctx); PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); Py_RETURN_NONE; }
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; }
/** * Cancel a transaction on database */ static int db_transaction_cancel_handler(struct ctdb_db_context *ctdb_db, void *private_data) { int ret; tdb_add_flags(ctdb_db->ltdb->tdb, TDB_NOLOCK); 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)); } tdb_remove_flags(ctdb_db->ltdb->tdb, TDB_NOLOCK); return 0; }
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 delete */ int partition_metadata_del_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 (data->metadata->in_transaction == 0) { return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR, "partition_metadata: not in transaction"); } data->metadata->in_transaction--; tdb_transaction_cancel(tdb); return LDB_SUCCESS; }
static int ltdb_prepare_commit(struct ldb_module *module) { void *data = ldb_module_get_private(module); struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); if (ltdb->in_transaction != 1) { return LDB_SUCCESS; } if (ltdb_index_transaction_commit(module) != 0) { tdb_transaction_cancel(ltdb->tdb); ltdb->in_transaction--; return ltdb_err_map(tdb_error(ltdb->tdb)); } if (tdb_transaction_prepare_commit(ltdb->tdb) != 0) { ltdb->in_transaction--; return ltdb_err_map(tdb_error(ltdb->tdb)); } ltdb->prepared_commit = true; return LDB_SUCCESS; }
/** * 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; }
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; }
int main(int argc, char *argv[]) { struct tdb_context *tdb; TDB_DATA key, data; plan_tests(27); key.dsize = strlen("hi"); key.dptr = (void *)"hi"; tdb = tdb_open_ex("run-nested-transactions.tdb", 1024, TDB_CLEAR_IF_FIRST|TDB_DISALLOW_NESTING, O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); ok1(tdb); /* Nesting disallowed. */ ok1(tdb_transaction_start(tdb) == 0); data.dptr = (void *)"world"; data.dsize = strlen("world"); ok1(tdb_store(tdb, key, 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_start(tdb) != 0); ok1(tdb_error(tdb) == TDB_ERR_NESTING); 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); data = tdb_fetch(tdb, key); ok1(data.dsize == strlen("world")); ok1(memcmp(data.dptr, "world", strlen("world")) == 0); free(data.dptr); tdb_close(tdb); /* Nesting allowed by default */ tdb = tdb_open_ex("run-nested-transactions.tdb", 1024, TDB_DEFAULT, O_RDWR, 0, &taplogctx, NULL); ok1(tdb); ok1(tdb_transaction_start(tdb) == 0); ok1(tdb_transaction_start(tdb) == 0); ok1(tdb_delete(tdb, key) == 0); ok1(tdb_transaction_commit(tdb) == 0); ok1(!tdb_exists(tdb, key)); ok1(tdb_transaction_cancel(tdb) == 0); /* Surprise! Kills inner "committed" transaction. */ ok1(tdb_exists(tdb, key)); ok1(tdb_transaction_start(tdb) == 0); ok1(tdb_transaction_start(tdb) == 0); ok1(tdb_delete(tdb, key) == 0); ok1(tdb_transaction_commit(tdb) == 0); ok1(!tdb_exists(tdb, key)); ok1(tdb_transaction_commit(tdb) == 0); ok1(!tdb_exists(tdb, key)); 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(); }
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); }
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; }
NTSTATUS schannel_check_creds_state(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, const char *computer_name, struct netr_Authenticator *received_authenticator, struct netr_Authenticator *return_authenticator, struct netlogon_creds_CredentialState **creds_out) { TALLOC_CTX *tmpctx; struct tdb_wrap *tdb_sc; struct netlogon_creds_CredentialState *creds; NTSTATUS status; int ret; tmpctx = talloc_named(mem_ctx, 0, "schannel_check_creds_state"); if (!tmpctx) { return NT_STATUS_NO_MEMORY; } tdb_sc = open_schannel_session_store(tmpctx, lp_ctx); if (!tdb_sc) { status = NT_STATUS_ACCESS_DENIED; goto done; } ret = tdb_transaction_start(tdb_sc->tdb); if (ret != 0) { status = NT_STATUS_INTERNAL_DB_CORRUPTION; goto done; } /* Because this is a shared structure (even across * disconnects) we must update the database every time we * update the structure */ status = schannel_fetch_session_key_tdb(tdb_sc, tmpctx, computer_name, &creds); if (!NT_STATUS_IS_OK(status)) { tdb_transaction_cancel(tdb_sc->tdb); goto done; } status = netlogon_creds_server_step_check(creds, received_authenticator, return_authenticator); if (!NT_STATUS_IS_OK(status)) { tdb_transaction_cancel(tdb_sc->tdb); goto done; } status = schannel_store_session_key_tdb(tdb_sc, tmpctx, creds); if (!NT_STATUS_IS_OK(status)) { tdb_transaction_cancel(tdb_sc->tdb); goto done; } tdb_transaction_commit(tdb_sc->tdb); if (creds_out) { *creds_out = talloc_steal(mem_ctx, creds); if (!*creds_out) { status = NT_STATUS_NO_MEMORY; goto done; } } status = NT_STATUS_OK; done: talloc_free(tmpctx); return 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; }