Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
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();
}
Ejemplo n.º 3
0
/*
 * 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;
}
Ejemplo n.º 4
0
/*
 * 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;
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
0
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();
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
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();
}
Ejemplo n.º 10
0
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();
}
Ejemplo n.º 11
0
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;
}
Ejemplo n.º 12
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);
}
Ejemplo n.º 13
0
/*
 * 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;
}
Ejemplo n.º 14
0
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;
}
Ejemplo n.º 15
0
/**
 * 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;
}
Ejemplo n.º 16
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();
}
Ejemplo n.º 17
0
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();
}
Ejemplo n.º 18
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;
}
Ejemplo n.º 19
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);
}
Ejemplo n.º 20
0
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;
}
Ejemplo n.º 21
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;
}
Ejemplo n.º 22
0
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);
}
Ejemplo n.º 23
0
/*
  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;
}
Ejemplo n.º 24
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;
}
Ejemplo n.º 25
0
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;
}
Ejemplo n.º 26
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();
}
Ejemplo n.º 27
0
/* 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();
}
Ejemplo n.º 28
0
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();
}
Ejemplo n.º 29
0
int main(int argc, char *argv[])
{
	unsigned int i;
	struct tdb_context *tdb;
	unsigned char *buffer;
	int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
			TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT };
	struct tdb_data key = tdb_mkdata("key", 3);
	struct tdb_data data;

	buffer = malloc(1000);
	for (i = 0; i < 1000; i++)
		buffer[i] = i;

	plan_tests(sizeof(flags) / sizeof(flags[0]) * 20 + 1);

	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		tdb = tdb_open("run-55-transaction.tdb", flags[i],
			       O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(tdb);
		if (!tdb)
			continue;

		ok1(tdb_transaction_start(tdb) == 0);
		data.dptr = buffer;
		data.dsize = 1000;
		ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
		ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS);
		ok1(data.dsize == 1000);
		ok1(memcmp(data.dptr, buffer, data.dsize) == 0);
		free(data.dptr);

		/* Cancelling a transaction means no store */
		tdb_transaction_cancel(tdb);
		ok1(tdb->file->allrecord_lock.count == 0
		    && tdb->file->num_lockrecs == 0);
		ok1(tdb_check(tdb, NULL, NULL) == 0);
		ok1(tdb_fetch(tdb, key, &data) == TDB_ERR_NOEXIST);

		/* Commit the transaction. */
		ok1(tdb_transaction_start(tdb) == 0);
		data.dptr = buffer;
		data.dsize = 1000;
		ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
		ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS);
		ok1(data.dsize == 1000);
		ok1(memcmp(data.dptr, buffer, data.dsize) == 0);
		free(data.dptr);
		ok1(tdb_transaction_commit(tdb) == 0);
		ok1(tdb->file->allrecord_lock.count == 0
		    && tdb->file->num_lockrecs == 0);
		ok1(tdb_check(tdb, NULL, NULL) == 0);
		ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS);
		ok1(data.dsize == 1000);
		ok1(memcmp(data.dptr, buffer, data.dsize) == 0);
		free(data.dptr);

		tdb_close(tdb);
	}

	ok1(tap_log_messages == 0);
	free(buffer);
	return exit_status();
}
Ejemplo n.º 30
0
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;
}