示例#1
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();
}
示例#2
0
int main(int argc, char *argv[])
{
	unsigned int i;
	struct tdb_context *tdb;
	int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
			TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
			TDB_NOMMAP|TDB_CONVERT,
			TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
			TDB_NOMMAP|TDB_VERSION1,
			TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
			TDB_CONVERT|TDB_VERSION1,
			TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
	struct tdb_data key = tdb_mkdata("key", 3);
	struct tdb_data data = tdb_mkdata("data", 4);

	failtest_init(argc, argv);
	failtest_hook = block_repeat_failures;
	failtest_exit_check = exit_check_log;

	failtest_suppress = true;
	plan_tests(sizeof(flags) / sizeof(flags[0]) * 8 + 1);
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		tdb = tdb_open("run-11-simple-fetch.tdb", flags[i],
			       O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(tdb);
		if (tdb) {
			struct tdb_data d = { NULL, 0 }; /* Bogus GCC warning */

			/* fetch should fail. */
			failtest_suppress = false;
			if (!ok1(tdb_fetch(tdb, key, &d) == TDB_ERR_NOEXIST))
				goto fail;
			failtest_suppress = true;
			ok1(tdb_check(tdb, NULL, NULL) == 0);
			/* Insert should succeed. */
			ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
			ok1(tdb_check(tdb, NULL, NULL) == 0);
			/* Fetch should now work. */
			failtest_suppress = false;
			if (!ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS))
				goto fail;
			failtest_suppress = true;
			ok1(tdb_deq(d, data));
			free(d.dptr);
			ok1(tdb_check(tdb, NULL, NULL) == 0);
			tdb_close(tdb);
		}
	}
	ok1(tap_log_messages == 0);
	failtest_exit(exit_status());

fail:
	failtest_suppress = true;
	tdb_close(tdb);
	failtest_exit(exit_status());
}
示例#3
0
int main(int argc, char *argv[])
{
	unsigned int i;
	uint64_t val;
	struct tdb_context *tdb;
	int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
			TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
			TDB_NOMMAP|TDB_CONVERT };

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

	failtest_init(argc, argv);
	failtest_hook = block_repeat_failures;
	failtest_exit_check = exit_check_log;

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

		val = tdb->file->map_size;
		/* Need some hash lock for expand. */
		ok1(tdb_lock_hashes(tdb, 0, 1, F_WRLCK, TDB_LOCK_WAIT) == 0);
		failtest_suppress = false;
		if (!ok1(tdb_expand(tdb, 1) == 0)) {
			failtest_suppress = true;
			tdb_close(tdb);
			break;
		}
		failtest_suppress = true;

		ok1(tdb->file->map_size >= val + 1 * TDB_EXTENSION_FACTOR);
		ok1(tdb_unlock_hashes(tdb, 0, 1, F_WRLCK) == 0);
		ok1(tdb_check(tdb, NULL, NULL) == 0);

		val = tdb->file->map_size;
		ok1(tdb_lock_hashes(tdb, 0, 1, F_WRLCK, TDB_LOCK_WAIT) == 0);
		failtest_suppress = false;
		if (!ok1(tdb_expand(tdb, 1024) == 0)) {
			failtest_suppress = true;
			tdb_close(tdb);
			break;
		}
		failtest_suppress = true;
		ok1(tdb_unlock_hashes(tdb, 0, 1, F_WRLCK) == 0);
		ok1(tdb->file->map_size >= val + 1024 * TDB_EXTENSION_FACTOR);
		ok1(tdb_check(tdb, NULL, NULL) == 0);
		tdb_close(tdb);
	}

	ok1(tap_log_messages == 0);
	failtest_exit(exit_status());
}
示例#4
0
int main(int argc, char *argv[])
{
	unsigned int i, j;
	struct tdb_context *tdb;
	int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
			TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
			TDB_NOMMAP|TDB_CONVERT };

	plan_tests(sizeof(flags) / sizeof(flags[0]) * 4 + 1);
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		bool array[NUM_RECORDS];

		tdb = tdb_open("run-check-callback.tdb", flags[i],
			       O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(tdb);
		if (!tdb)
			continue;

		ok1(store_records(tdb));
		for (j = 0; j < NUM_RECORDS; j++)
			array[j] = false;
		ok1(tdb_check(tdb, check, array) == TDB_SUCCESS);
		for (j = 0; j < NUM_RECORDS; j++)
			if (!array[j])
				break;
		ok1(j == NUM_RECORDS);
		tdb_close(tdb);
	}

	ok1(tap_log_messages == 0);
	return exit_status();
}
示例#5
0
int main(int argc, char *argv[])
{
	unsigned int i;
	bool found[NUM_TESTS];
	struct tdb_context *tdb;
	int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
			TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT,
			TDB_VERSION1, TDB_VERSION1|TDB_NOMMAP,
			TDB_VERSION1|TDB_CONVERT,
			TDB_VERSION1|TDB_NOMMAP|TDB_CONVERT
	};

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

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

		ok1(store_all(tdb));

		ok1(tdb_repack(tdb) == TDB_SUCCESS);
		memset(found, 0, sizeof(found));
		ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);
		ok1(tdb_traverse(tdb, mark_entry, found) == NUM_TESTS);
		ok1(is_all_set(found, NUM_TESTS));
		tdb_close(tdb);
	}

	ok1(tap_log_messages == 0);
	return exit_status();
}
int main(int argc, char *argv[])
{
	tdb_off_t off;
	struct tdb_context *tdb;
	struct tdb_layout *layout;
	TDB_DATA key, data;

	plan_tests(11);
	key.dptr = (unsigned char *)"Hello";
	data.dptr = (unsigned char *)"world";
	data.dsize = 5;
	key.dsize = 5;

	/* Create a TDB with three free tables. */
	layout = new_tdb_layout(NULL);
	tdb_layout_add_freetable(layout);
	tdb_layout_add_freetable(layout);
	tdb_layout_add_freetable(layout);
	tdb_layout_add_free(layout, 80, 0);
	/* Used record prevent coalescing. */
	tdb_layout_add_used(layout, key, data, 6);
	tdb_layout_add_free(layout, 160, 1);
	key.dsize--;
	tdb_layout_add_used(layout, key, data, 7);
	tdb_layout_add_free(layout, 320, 2);
	key.dsize--;
	tdb_layout_add_used(layout, key, data, 8);
	tdb_layout_add_free(layout, 40, 0);
	tdb = tdb_layout_get(layout);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	off = get_free(tdb, 0, 80 - sizeof(struct tdb_used_record), 0,
		       TDB_USED_MAGIC, 0);
	ok1(off == layout->elem[3].base.off);
	ok1(tdb->ftable_off == layout->elem[0].base.off);

	off = get_free(tdb, 0, 160 - sizeof(struct tdb_used_record), 0,
		       TDB_USED_MAGIC, 0);
	ok1(off == layout->elem[5].base.off);
	ok1(tdb->ftable_off == layout->elem[1].base.off);

	off = get_free(tdb, 0, 320 - sizeof(struct tdb_used_record), 0,
		       TDB_USED_MAGIC, 0);
	ok1(off == layout->elem[7].base.off);
	ok1(tdb->ftable_off == layout->elem[2].base.off);

	off = get_free(tdb, 0, 40 - sizeof(struct tdb_used_record), 0,
		       TDB_USED_MAGIC, 0);
	ok1(off == layout->elem[9].base.off);
	ok1(tdb->ftable_off == layout->elem[0].base.off);

	/* Now we fail. */
	off = get_free(tdb, 0, 0, 1, TDB_USED_MAGIC, 0);
	ok1(off == 0);

	tdb_close(tdb);

	ok1(tap_log_messages == 0);
	return exit_status();
}
示例#7
0
文件: tdb2tool.c 项目: burito/ccan
static void check_db(struct tdb_context *the_tdb)
{
	if (!the_tdb) {
		printf("Error: No database opened!\n");
	} else {
		if (tdb_check(the_tdb, NULL, NULL) != 0)
			printf("Integrity check for the opened database failed.\n");
		else
			printf("Database integrity is OK.\n");
	}
}
示例#8
0
文件: tdbtool.c 项目: csesteban/ccan
static void check_db(TDB_CONTEXT *the_tdb)
{
	if (!the_tdb) {
		printf("Error: No database opened!\n");
	} else {
		if (tdb_check(the_tdb, NULL, NULL) == -1)
			printf("Integrity check for the opened database failed.\n");
		else
			printf("Database integrity is OK.\n");
	}
}
示例#9
0
static void check_db(TDB_CONTEXT *the_tdb)
{
	int tdbcount = 0;
	if (!the_tdb)
		printf("Error: No database opened!\n");
	else if (tdb_check(the_tdb, count, &tdbcount) == -1)
		printf("Integrity check for the opened database failed.\n");
	else
		printf("Database integrity is OK and has %d records.\n",
		       tdbcount);
}
示例#10
0
bool netsamlogon_cache_init(void)
{
    bool first_try = true;
    char *path = NULL;
    int ret;
    struct tdb_context *tdb;

    if (netsamlogon_tdb) {
        return true;
    }

    path = cache_path(NETSAMLOGON_TDB);
    if (path == NULL) {
        return false;
    }
again:
    tdb = tdb_open_log(path, 0, TDB_DEFAULT|TDB_INCOMPATIBLE_HASH,
                       O_RDWR | O_CREAT, 0600);
    if (tdb == NULL) {
        DEBUG(0,("tdb_open_log('%s') - failed\n", path));
        goto clear;
    }

    ret = tdb_check(tdb, NULL, NULL);
    if (ret != 0) {
        tdb_close(tdb);
        DEBUG(0,("tdb_check('%s') - failed\n", path));
        goto clear;
    }

    netsamlogon_tdb = tdb;
    talloc_free(path);
    return true;

clear:
    if (!first_try) {
        talloc_free(path);
        return false;
    }
    first_try = false;

    DEBUG(0,("retry after truncate for '%s'\n", path));
    ret = truncate(path, 0);
    if (ret == -1) {
        DBG_ERR("truncate failed: %s\n", strerror(errno));
        talloc_free(path);
        return false;
    }

    goto again;
}
int main(int argc, char *argv[])
{
	unsigned int i, j;
	struct tdb_context *tdb;
	int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
			TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
			TDB_NOMMAP|TDB_CONVERT };

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

	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		TDB_DATA k;
		uint64_t size;
		bool was_empty = false;

		k.dptr = (void *)&j;
		k.dsize = sizeof(j);

		tdb = tdb_open("run-30-exhaust-before-expand.tdb", flags[i],
			       O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(tdb);
		if (!tdb)
			continue;

		ok1(empty_freetable(tdb));
		/* Need some hash lock for expand. */
		ok1(tdb_lock_hashes(tdb, 0, 1, F_WRLCK, TDB_LOCK_WAIT) == 0);
		/* Create some free space. */
		ok1(tdb_expand(tdb, 1) == 0);
		ok1(tdb_unlock_hashes(tdb, 0, 1, F_WRLCK) == 0);
		ok1(tdb_check(tdb, NULL, NULL) == 0);
		ok1(!empty_freetable(tdb));

		size = tdb->map_size;
		/* Insert minimal-length records until we expand. */
		for (j = 0; tdb->map_size == size; j++) {
			was_empty = empty_freetable(tdb);
			if (tdb_store(tdb, k, k, TDB_INSERT) != 0)
				err(1, "Failed to store record %i", j);
		}

		/* Would have been empty before expansion, but no longer. */
		ok1(was_empty);
		ok1(!empty_freetable(tdb));
		tdb_close(tdb);
	}

	ok1(tap_log_messages == 0);
	return exit_status();
}
示例#12
0
int main(int argc, char *argv[])
{
	unsigned int i;
	struct tdb_context *tdb;
	int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
			TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
			TDB_NOMMAP|TDB_CONVERT,
			TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
			TDB_NOMMAP|TDB_VERSION1,
			TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
			TDB_CONVERT|TDB_VERSION1,
			TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
	struct tdb_data key = tdb_mkdata("key", 3);
	struct tdb_data data = tdb_mkdata("data", 4);

	plan_tests(sizeof(flags) / sizeof(flags[0]) * 7 + 1);
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		tdb = tdb_open("run-simple-delete.tdb", flags[i],
			       O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(tdb);
		if (tdb) {
			/* Delete should fail. */
			ok1(tdb_delete(tdb, key) == TDB_ERR_NOEXIST);
			ok1(tdb_check(tdb, NULL, NULL) == 0);
			/* Insert should succeed. */
			ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
			ok1(tdb_check(tdb, NULL, NULL) == 0);
			/* Delete should now work. */
			ok1(tdb_delete(tdb, key) == 0);
			ok1(tdb_check(tdb, NULL, NULL) == 0);
			tdb_close(tdb);
		}
	}
	ok1(tap_log_messages == 0);
	return exit_status();
}
示例#13
0
int main(int argc, char *argv[])
{
	struct tdb_context *tdb;
	TDB_DATA key, data;
	union tdb_attribute hsize;

	hsize.base.attr = TDB_ATTRIBUTE_TDB1_HASHSIZE;
	hsize.base.next = &tap_log_attr;
	hsize.tdb1_hashsize.hsize = 1;

	plan_tests(13);
	tdb = tdb_open("run-check.tdb1", TDB_VERSION1,
		       O_CREAT|O_TRUNC|O_RDWR, 0600, &hsize);

	ok1(tdb);
	ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);

	key = tdb_mkdata("hi", strlen("hi"));
	data = tdb_mkdata("world", strlen("world"));

	ok1(tdb_store(tdb, key, data, TDB_INSERT) == TDB_SUCCESS);
	ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);
	tdb_close(tdb);

	tdb = tdb_open("run-check.tdb1", TDB_VERSION1, O_RDWR, 0, &tap_log_attr);
	ok1(tdb);
	ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);
	tdb_close(tdb);

	tdb = tdb_open("test/tdb1.corrupt", TDB_VERSION1, O_RDWR, 0,
			&tap_log_attr);
	ok1(tdb);
	ok1(tdb_check(tdb, NULL, NULL) == TDB_ERR_CORRUPT);
	ok1(tdb_error(tdb) == TDB_ERR_CORRUPT);
	tdb_close(tdb);

	/* Big and little endian should work! */
	tdb = tdb_open("test/old-nohash-le.tdb1", TDB_VERSION1, O_RDWR, 0,
		       &tap_log_attr);
	ok1(tdb);
	ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);
	tdb_close(tdb);

	tdb = tdb_open("test/old-nohash-be.tdb1", TDB_VERSION1, O_RDWR, 0,
			&tap_log_attr);
	ok1(tdb);
	ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);
	tdb_close(tdb);

	return exit_status();
}
示例#14
0
int main(int argc, char *argv[])
{
	unsigned int i;
	struct tdb_context *tdb;
	int flags[] = { TDB_INTERNAL,
			TDB_INTERNAL|TDB_CONVERT,
			TDB_CONVERT,
			TDB_INTERNAL|TDB_VERSION1,
			TDB_VERSION1,
			TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
			TDB_CONVERT|TDB_VERSION1 };
	struct tdb_data key = tdb_mkdata("key", 3);
	struct tdb_data data = tdb_mkdata("data", 4);

	failtest_init(argc, argv);
	failtest_hook = block_repeat_failures;
	failtest_exit_check = exit_check_log;

	failtest_suppress = true;
	plan_tests(sizeof(flags) / sizeof(flags[0]) * 3 + 1);
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		tdb = tdb_open("run-12-check.tdb", flags[i],
			       O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(tdb);
		ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);

		/* This is what we really want to test: tdb_check(). */
		failtest_suppress = false;
		if (!ok1(tdb_check(tdb, NULL, NULL) == 0))
			goto fail;
		failtest_suppress = true;

		tdb_close(tdb);
	}
	ok1(tap_log_messages == 0);
	failtest_exit(exit_status());

fail:
	failtest_suppress = true;
	tdb_close(tdb);
	failtest_exit(exit_status());
}
示例#15
0
int main(int argc, char *argv[])
{
	struct tdb_context *tdb;
	TDB_DATA key, data;

	plan_tests(13);
	tdb = tdb_open_ex("run-check.tdb", 1, TDB_CLEAR_IF_FIRST,
			  O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL);

	ok1(tdb);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	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);
	tdb_close(tdb);

	tdb = tdb_open_ex("run-check.tdb", 1024, 0, O_RDWR, 0,
			  &taplogctx, NULL);
	ok1(tdb);
	ok1(tdb_check(tdb, NULL, NULL) == 0);
	tdb_close(tdb);

	tdb = tdb_open_ex("test/tdb.corrupt", 1024, 0, O_RDWR, 0,
			  &taplogctx, NULL);
	ok1(tdb);
	ok1(tdb_check(tdb, NULL, NULL) == -1);
	ok1(tdb_error(tdb) == TDB_ERR_CORRUPT);
	tdb_close(tdb);

	/* Big and little endian should work! */
	tdb = tdb_open_ex("test/old-nohash-le.tdb", 1024, 0, O_RDWR, 0,
			  &taplogctx, NULL);
	ok1(tdb);
	ok1(tdb_check(tdb, NULL, NULL) == 0);
	tdb_close(tdb);

	tdb = tdb_open_ex("test/old-nohash-be.tdb", 1024, 0, O_RDWR, 0,
			  &taplogctx, NULL);
	ok1(tdb);
	ok1(tdb_check(tdb, NULL, NULL) == 0);
	tdb_close(tdb);

	return exit_status();
}
示例#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();
}
示例#17
0
int main(int argc, char *argv[])
{
	struct tdb_context *tdb;
	unsigned int log_count;
	TDB_DATA d;
	struct tdb_logging_context log_ctx = { log_fn, &log_count };

	plan_tests(28);

	/* Create with default hash. */
	log_count = 0;
	tdb = tdb_open_ex("run-wronghash-fail.tdb", 0, 0,
			  O_CREAT|O_RDWR|O_TRUNC, 0600, &log_ctx, NULL);
	ok1(tdb);
	ok1(log_count == 0);
	d.dptr = (void *)"Hello";
	d.dsize = 5;
	ok1(tdb_store(tdb, d, d, TDB_INSERT) == 0);
	tdb_close(tdb);

	/* Fail to open with different hash. */
	tdb = tdb_open_ex("run-wronghash-fail.tdb", 0, 0, O_RDWR, 0,
			  &log_ctx, tdb_jenkins_hash);
	ok1(!tdb);
	ok1(log_count == 1);

	/* Create with different hash. */
	log_count = 0;
	tdb = tdb_open_ex("run-wronghash-fail.tdb", 0, 0,
			  O_CREAT|O_RDWR|O_TRUNC,
			  0600, &log_ctx, tdb_jenkins_hash);
	ok1(tdb);
	ok1(log_count == 0);
	tdb_close(tdb);

	/* Endian should be no problem. */
	log_count = 0;
	tdb = tdb_open_ex("test/jenkins-le-hash.tdb", 0, 0, O_RDWR, 0,
			  &log_ctx, tdb_old_hash);
	ok1(!tdb);
	ok1(log_count == 1);

	log_count = 0;
	tdb = tdb_open_ex("test/jenkins-be-hash.tdb", 0, 0, O_RDWR, 0,
			  &log_ctx, tdb_old_hash);
	ok1(!tdb);
	ok1(log_count == 1);

	log_count = 0;
	/* Fail to open with old default hash. */
	tdb = tdb_open_ex("run-wronghash-fail.tdb", 0, 0, O_RDWR, 0,
			  &log_ctx, tdb_old_hash);
	ok1(!tdb);
	ok1(log_count == 1);

	log_count = 0;
	tdb = tdb_open_ex("test/jenkins-le-hash.tdb", 0, 0, O_RDONLY,
			  0, &log_ctx, tdb_jenkins_hash);
	ok1(tdb);
	ok1(log_count == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);
	tdb_close(tdb);

	log_count = 0;
	tdb = tdb_open_ex("test/jenkins-be-hash.tdb", 0, 0, O_RDONLY,
			  0, &log_ctx, tdb_jenkins_hash);
	ok1(tdb);
	ok1(log_count == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);
	tdb_close(tdb);

	/* It should open with jenkins hash if we don't specify. */
	log_count = 0;
	tdb = tdb_open_ex("test/jenkins-le-hash.tdb", 0, 0, O_RDWR, 0,
			  &log_ctx, NULL);
	ok1(tdb);
	ok1(log_count == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);
	tdb_close(tdb);

	log_count = 0;
	tdb = tdb_open_ex("test/jenkins-be-hash.tdb", 0, 0, O_RDWR, 0,
			  &log_ctx, NULL);
	ok1(tdb);
	ok1(log_count == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);
	tdb_close(tdb);

	log_count = 0;
	tdb = tdb_open_ex("run-wronghash-fail.tdb", 0, 0, O_RDONLY,
			  0, &log_ctx, NULL);
	ok1(tdb);
	ok1(log_count == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);
	tdb_close(tdb);


	return exit_status();
}
示例#18
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 };

	if (sizeof(off_t) <= 4) {
		plan_tests(1);
		pass("No 64 bit off_t");
		return exit_status();
	}

	plan_tests(sizeof(flags) / sizeof(flags[0]) * 14);
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		off_t old_size;
		TDB_DATA k, d;
		struct hash_info h;
		struct tdb_used_record rec;
		tdb_off_t off;

		tdb = tdb_open("run-64-bit-tdb.tdb", flags[i],
			       O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(tdb);
		if (!tdb)
			continue;

		old_size = tdb->file->map_size;

		/* This makes a sparse file */
		ok1(ftruncate(tdb->file->fd, 0xFFFFFFF0) == 0);
		ok1(add_free_record(tdb, old_size, 0xFFFFFFF0 - old_size,
				    TDB_LOCK_WAIT, false) == TDB_SUCCESS);

		/* Now add a little record past the 4G barrier. */
		ok1(tdb_expand_file(tdb, 100) == TDB_SUCCESS);
		ok1(add_free_record(tdb, 0xFFFFFFF0, 100, TDB_LOCK_WAIT, false)
		    == TDB_SUCCESS);

		ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);

		/* Test allocation path. */
		k = tdb_mkdata("key", 4);
		d = tdb_mkdata("data", 5);
		ok1(tdb_store(tdb, k, d, TDB_INSERT) == 0);
		ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);

		/* Make sure it put it at end as we expected. */
		off = find_and_lock(tdb, k, F_RDLCK, &h, &rec, NULL);
		ok1(off >= 0xFFFFFFF0);
		tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK);

		ok1(tdb_fetch(tdb, k, &d) == 0);
		ok1(d.dsize == 5);
		ok1(strcmp((char *)d.dptr, "data") == 0);
		free(d.dptr);

		ok1(tdb_delete(tdb, k) == 0);
		ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);

		tdb_close(tdb);
	}

	/* We might get messages about mmap failing, so don't test
	 * tap_log_messages */
	return exit_status();
}
示例#19
0
static enum agent_return do_operation(enum operation op, const char *name)
{
	TDB_DATA k;
	enum agent_return ret;
	TDB_DATA data;

	if (op != OPEN && op != OPEN_WITH_CLEAR_IF_FIRST && !tdb) {
		diag("external: No tdb open!");
		return OTHER_FAILURE;
	}

	k.dptr = (void *)name;
	k.dsize = 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_ex(name, 0, TDB_DEFAULT, O_RDWR, 0,
				  &taplogctx, NULL);
		if (!tdb) {
			if (!locking_would_block)
				diag("Opening tdb gave %s", strerror(errno));
			ret = OTHER_FAILURE;
		} else
			ret = SUCCESS;
		break;
	case OPEN_WITH_CLEAR_IF_FIRST:
		if (tdb)
			return OTHER_FAILURE;
		tdb = tdb_open_ex(name, 0, TDB_CLEAR_IF_FIRST, O_RDWR, 0,
				  &taplogctx, NULL);
		ret = tdb ? SUCCESS : OTHER_FAILURE;
		break;
	case TRANSACTION_START:
		ret = tdb_transaction_start(tdb) == 0 ? SUCCESS : OTHER_FAILURE;
		break;
	case FETCH:
		data = tdb_fetch(tdb, k);
		if (data.dptr == NULL) {
			if (tdb_error(tdb) == TDB_ERR_NOEXIST)
				ret = FAILED;
			else
				ret = OTHER_FAILURE;
		} else if (data.dsize != k.dsize
			   || memcmp(data.dptr, k.dptr, k.dsize) != 0) {
			ret = OTHER_FAILURE;
		} else {
			ret = SUCCESS;
		}
		free(data.dptr);
		break;
	case STORE:
		ret = tdb_store(tdb, k, k, 0) == 0 ? SUCCESS : OTHER_FAILURE;
		break;
	case TRANSACTION_COMMIT:
		ret = tdb_transaction_commit(tdb)==0 ? SUCCESS : OTHER_FAILURE;
		break;
	case CHECK:
		ret = tdb_check(tdb, NULL, NULL) == 0 ? SUCCESS : OTHER_FAILURE;
		break;
	case NEEDS_RECOVERY:
		ret = tdb_needs_recovery(tdb) ? SUCCESS : FAILED;
		break;
	case CLOSE:
		ret = tdb_close(tdb) == 0 ? SUCCESS : OTHER_FAILURE;
		tdb = NULL;
		break;
	default:
		ret = OTHER_FAILURE;
	}

	if (locking_would_block)
		ret = WOULD_HAVE_BLOCKED;

	return ret;
}
示例#20
0
int main(int argc, char *argv[])
{
	tdb_off_t b_off, test;
	struct tdb_context *tdb;
	struct tdb_layout *layout;
	struct tdb_data data, key;
	tdb_len_t len;

	/* FIXME: Test TDB_CONVERT */
	/* FIXME: Test lock order fail. */

	plan_tests(42);
	data = tdb_mkdata("world", 5);
	key = tdb_mkdata("hello", 5);

	/* No coalescing can be done due to EOF */
	layout = new_tdb_layout("run-03-coalesce.tdb");
	tdb_layout_add_freetable(layout);
	len = 1024;
	tdb_layout_add_free(layout, len, 0);
	tdb = tdb_layout_get(layout);
	ok1(tdb_check(tdb, NULL, NULL) == 0);
	ok1(free_record_length(tdb, layout->elem[1].base.off) == len);

	/* Figure out which bucket free entry is. */
	b_off = bucket_off(tdb->ftable_off, size_to_bucket(len));
	/* Lock and fail to coalesce. */
	ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0);
	test = layout->elem[1].base.off;
	ok1(coalesce(tdb, layout->elem[1].base.off, b_off, len, &test)
	    == 0);
	tdb_unlock_free_bucket(tdb, b_off);
	ok1(free_record_length(tdb, layout->elem[1].base.off) == len);
	ok1(test == layout->elem[1].base.off);
	ok1(tdb_check(tdb, NULL, NULL) == 0);
	tdb_close(tdb);
	tdb_layout_free(layout);

	/* No coalescing can be done due to used record */
	layout = new_tdb_layout("run-03-coalesce.tdb");
	tdb_layout_add_freetable(layout);
	tdb_layout_add_free(layout, 1024, 0);
	tdb_layout_add_used(layout, key, data, 6);
	tdb = tdb_layout_get(layout);
	ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	/* Figure out which bucket free entry is. */
	b_off = bucket_off(tdb->ftable_off, size_to_bucket(1024));
	/* Lock and fail to coalesce. */
	ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0);
	test = layout->elem[1].base.off;
	ok1(coalesce(tdb, layout->elem[1].base.off, b_off, 1024, &test)
	    == 0);
	tdb_unlock_free_bucket(tdb, b_off);
	ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024);
	ok1(test == layout->elem[1].base.off);
	ok1(tdb_check(tdb, NULL, NULL) == 0);
	tdb_close(tdb);
	tdb_layout_free(layout);

	/* Coalescing can be done due to two free records, then EOF */
	layout = new_tdb_layout("run-03-coalesce.tdb");
	tdb_layout_add_freetable(layout);
	tdb_layout_add_free(layout, 1024, 0);
	tdb_layout_add_free(layout, 2048, 0);
	tdb = tdb_layout_get(layout);
	ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024);
	ok1(free_record_length(tdb, layout->elem[2].base.off) == 2048);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	/* Figure out which bucket (first) free entry is. */
	b_off = bucket_off(tdb->ftable_off, size_to_bucket(1024));
	/* Lock and coalesce. */
	ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0);
	test = layout->elem[2].base.off;
	ok1(coalesce(tdb, layout->elem[1].base.off, b_off, 1024, &test)
	    == 1024 + sizeof(struct tdb_used_record) + 2048);
	/* Should tell us it's erased this one... */
	ok1(test == TDB_ERR_NOEXIST);
	ok1(tdb->file->allrecord_lock.count == 0 && tdb->file->num_lockrecs == 0);
	ok1(free_record_length(tdb, layout->elem[1].base.off)
	    == 1024 + sizeof(struct tdb_used_record) + 2048);
	ok1(tdb_check(tdb, NULL, NULL) == 0);
	tdb_close(tdb);
	tdb_layout_free(layout);

	/* Coalescing can be done due to two free records, then data */
	layout = new_tdb_layout("run-03-coalesce.tdb");
	tdb_layout_add_freetable(layout);
	tdb_layout_add_free(layout, 1024, 0);
	tdb_layout_add_free(layout, 512, 0);
	tdb_layout_add_used(layout, key, data, 6);
	tdb = tdb_layout_get(layout);
	ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024);
	ok1(free_record_length(tdb, layout->elem[2].base.off) == 512);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	/* Figure out which bucket free entry is. */
	b_off = bucket_off(tdb->ftable_off, size_to_bucket(1024));
	/* Lock and coalesce. */
	ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0);
	test = layout->elem[2].base.off;
	ok1(coalesce(tdb, layout->elem[1].base.off, b_off, 1024, &test)
	    == 1024 + sizeof(struct tdb_used_record) + 512);
	ok1(tdb->file->allrecord_lock.count == 0 && tdb->file->num_lockrecs == 0);
	ok1(free_record_length(tdb, layout->elem[1].base.off)
	    == 1024 + sizeof(struct tdb_used_record) + 512);
	ok1(test == TDB_ERR_NOEXIST);
	ok1(tdb_check(tdb, NULL, NULL) == 0);
	tdb_close(tdb);
	tdb_layout_free(layout);

	/* Coalescing can be done due to three free records, then EOF */
	layout = new_tdb_layout("run-03-coalesce.tdb");
	tdb_layout_add_freetable(layout);
	tdb_layout_add_free(layout, 1024, 0);
	tdb_layout_add_free(layout, 512, 0);
	tdb_layout_add_free(layout, 256, 0);
	tdb = tdb_layout_get(layout);
	ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024);
	ok1(free_record_length(tdb, layout->elem[2].base.off) == 512);
	ok1(free_record_length(tdb, layout->elem[3].base.off) == 256);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	/* Figure out which bucket free entry is. */
	b_off = bucket_off(tdb->ftable_off, size_to_bucket(1024));
	/* Lock and coalesce. */
	ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0);
	test = layout->elem[2].base.off;
	ok1(coalesce(tdb, layout->elem[1].base.off, b_off, 1024, &test)
	    == 1024 + sizeof(struct tdb_used_record) + 512
	    + sizeof(struct tdb_used_record) + 256);
	ok1(tdb->file->allrecord_lock.count == 0
	    && tdb->file->num_lockrecs == 0);
	ok1(free_record_length(tdb, layout->elem[1].base.off)
	    == 1024 + sizeof(struct tdb_used_record) + 512
	    + sizeof(struct tdb_used_record) + 256);
	ok1(tdb_check(tdb, NULL, NULL) == 0);
	tdb_close(tdb);
	tdb_layout_free(layout);

	ok1(tap_log_messages == 0);
	return exit_status();
}
示例#21
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();
}
示例#22
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;
}
示例#23
0
文件: speed.c 项目: atlant2011/samba
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;
}
示例#24
0
int main(int argc, char *argv[])
{
    tdb_off_t off;
    struct tdb_context *tdb;
    struct tdb_layout *layout;
    TDB_DATA key, data;
    union tdb_attribute seed;

    /* This seed value previously tickled a layout.c bug. */
    seed.base.attr = TDB_ATTRIBUTE_SEED;
    seed.seed.seed = 0xb1142bc054d035b4ULL;
    seed.base.next = &tap_log_attr;

    plan_tests(11);
    key = tdb_mkdata("Hello", 5);
    data = tdb_mkdata("world", 5);

    /* Create a TDB with three free tables. */
    layout = new_tdb_layout();
    tdb_layout_add_freetable(layout);
    tdb_layout_add_freetable(layout);
    tdb_layout_add_freetable(layout);
    tdb_layout_add_free(layout, 80, 0);
    /* Used record prevent coalescing. */
    tdb_layout_add_used(layout, key, data, 6);
    tdb_layout_add_free(layout, 160, 1);
    key.dsize--;
    tdb_layout_add_used(layout, key, data, 7);
    tdb_layout_add_free(layout, 320, 2);
    key.dsize--;
    tdb_layout_add_used(layout, key, data, 8);
    tdb_layout_add_free(layout, 40, 0);
    tdb = tdb_layout_get(layout, free, &seed);
    ok1(tdb_check(tdb, NULL, NULL) == 0);

    off = get_free(tdb, 0, 80 - sizeof(struct tdb_used_record), 0,
                   TDB_USED_MAGIC, 0);
    ok1(off == layout->elem[3].base.off);
    ok1(tdb->tdb2.ftable_off == layout->elem[0].base.off);

    off = get_free(tdb, 0, 160 - sizeof(struct tdb_used_record), 0,
                   TDB_USED_MAGIC, 0);
    ok1(off == layout->elem[5].base.off);
    ok1(tdb->tdb2.ftable_off == layout->elem[1].base.off);

    off = get_free(tdb, 0, 320 - sizeof(struct tdb_used_record), 0,
                   TDB_USED_MAGIC, 0);
    ok1(off == layout->elem[7].base.off);
    ok1(tdb->tdb2.ftable_off == layout->elem[2].base.off);

    off = get_free(tdb, 0, 40 - sizeof(struct tdb_used_record), 0,
                   TDB_USED_MAGIC, 0);
    ok1(off == layout->elem[9].base.off);
    ok1(tdb->tdb2.ftable_off == layout->elem[0].base.off);

    /* Now we fail. */
    off = get_free(tdb, 0, 0, 1, TDB_USED_MAGIC, 0);
    ok1(off == 0);

    tdb_close(tdb);
    tdb_layout_free(layout);

    ok1(tap_log_messages == 0);
    return exit_status();
}
示例#25
0
文件: tdb2torture.c 项目: burito/ccan
int main(int argc, char * const *argv)
{
	int i, seed = -1;
	int num_loops = 5000;
	int num_procs = 3;
	int c, pfds[2];
	extern char *optarg;
	pid_t *pids;
	int kill_random = 0;
	int *done;
	int tdb_flags = TDB_DEFAULT;

	log_attr.base.attr = TDB_ATTRIBUTE_LOG;
	log_attr.base.next = &seed_attr;
	log_attr.log.fn = tdb_log;
	seed_attr.base.attr = TDB_ATTRIBUTE_SEED;

	while ((c = getopt(argc, argv, "n:l:s:thkS")) != -1) {
		switch (c) {
		case 'n':
			num_procs = strtol(optarg, NULL, 0);
			break;
		case 'l':
			num_loops = strtol(optarg, NULL, 0);
			break;
		case 's':
			seed = strtol(optarg, NULL, 0);
			break;
		case 'S':
			tdb_flags = TDB_NOSYNC;
			break;
		case 't':
#if TRANSACTION_PROB
			always_transaction = 1;
#else
			fprintf(stderr, "Transactions not supported\n");
			usage();
#endif
			break;
		case 'k':
			kill_random = 1;
			break;
		default:
			usage();
		}
	}

	unlink("torture.tdb");

	if (seed == -1) {
		seed = (getpid() + time(NULL)) & 0x7FFFFFFF;
	}
	seed_attr.seed.seed = (((uint64_t)seed) << 32) | seed; 

	if (num_procs == 1 && !kill_random) {
		/* Don't fork for this case, makes debugging easier. */
		error_count = run_child(0, seed, num_loops, 0, tdb_flags);
		goto done;
	}

	pids = (pid_t *)calloc(sizeof(pid_t), num_procs);
	done = (int *)calloc(sizeof(int), num_procs);

	if (pipe(pfds) != 0) {
		perror("Creating pipe");
		exit(1);
	}
	count_pipe = pfds[1];

	for (i=0;i<num_procs;i++) {
		if ((pids[i]=fork()) == 0) {
			close(pfds[0]);
			if (i == 0) {
				printf("testing with %d processes, %d loops, seed=%d%s\n", 
				       num_procs, num_loops, seed, 
#if TRANSACTION_PROB
				       always_transaction ? " (all within transactions)" : ""
#else
				       ""
#endif
					);
			}
			exit(run_child(i, seed, num_loops, 0, tdb_flags));
		}
	}

	while (num_procs) {
		int status, j;
		pid_t pid;

		if (error_count != 0) {
			/* try and stop the test on any failure */
			for (j=0;j<num_procs;j++) {
				if (pids[j] != 0) {
					kill(pids[j], SIGTERM);
				}
			}
		}

		pid = waitpid(-1, &status, kill_random ? WNOHANG : 0);
		if (pid == 0) {
			struct timespec ts;

			/* Sleep for 1/10 second. */
			ts.tv_sec = 0;
			ts.tv_nsec = 100000000;
			nanosleep(&ts, NULL);

			/* Kill someone. */
			kill(pids[random() % num_procs], SIGUSR1);
			continue;
		}

		if (pid == -1) {
			perror("failed to wait for child\n");
			exit(1);
		}

		for (j=0;j<num_procs;j++) {
			if (pids[j] == pid) break;
		}
		if (j == num_procs) {
			printf("unknown child %d exited!?\n", (int)pid);
			exit(1);
		}
		if (WIFSIGNALED(status)) {
			if (WTERMSIG(status) == SIGUSR2
			    || WTERMSIG(status) == SIGUSR1) {
				/* SIGUSR2 means they wrote to pipe. */
				if (WTERMSIG(status) == SIGUSR2) {
					if (read(pfds[0], &done[j],
						 sizeof(done[j]))
					    != sizeof(done[j]))
						err(1,
						    "Short read from child?");
				}
				pids[j] = fork();
				if (pids[j] == 0)
					exit(run_child(j, seed, num_loops,
						       done[j], tdb_flags));
				printf("Restarting child %i for %u-%u\n",
				       j, done[j], num_loops);
				continue;
			}
			printf("child %d exited with signal %d\n",
			       (int)pid, WTERMSIG(status));
			error_count++;
		} else {
			if (WEXITSTATUS(status) != 0) {
				printf("child %d exited with status %d\n",
				       (int)pid, WEXITSTATUS(status));
				error_count++;
			}
		}
		memmove(&pids[j], &pids[j+1],
			(num_procs - j - 1)*sizeof(pids[0]));
		num_procs--;
	}

	free(pids);

done:
	if (error_count == 0) {
		db = tdb_open("torture.tdb", TDB_DEFAULT, O_RDWR | O_CREAT,
			      0600, &log_attr);
		if (!db) {
			fatal(db, "db open failed");
			exit(1);
		}
		if (tdb_check(db, NULL, NULL) != 0) {
			fatal(db, "db check failed");
			exit(1);
		}
		tdb_close(db);
		printf("OK\n");
	}

	return error_count;
}
示例#26
0
static int db_tdb_check(struct db_context *db)
{
	struct db_tdb_ctx *ctx = talloc_get_type_abort(
		db->private_data, struct db_tdb_ctx);
	return tdb_check(ctx->wtdb->tdb, NULL, NULL);
}
示例#27
0
int main(int argc, char *argv[])
{
    struct tdb_context *tdb;
    unsigned int log_count;
    TDB_DATA d;
    union tdb_attribute log_attr, jhash_attr, ohash_attr,
              incompat_hash_attr;

    log_attr.base.attr = TDB_ATTRIBUTE_LOG;
    log_attr.base.next = NULL;
    log_attr.log.fn = log_fn;
    log_attr.log.data = &log_count;

    jhash_attr.base.attr = TDB_ATTRIBUTE_HASH;
    jhash_attr.base.next = &log_attr;
    jhash_attr.hash.fn = jenkins_hashfn;

    ohash_attr.base.attr = TDB_ATTRIBUTE_HASH;
    ohash_attr.base.next = &log_attr;
    ohash_attr.hash.fn = old_hash;

    incompat_hash_attr.base.attr = TDB_ATTRIBUTE_HASH;
    incompat_hash_attr.base.next = &log_attr;
    incompat_hash_attr.hash.fn = tdb1_incompatible_hash;

    plan_tests(28);

    /* Create with default hash. */
    log_count = 0;
    tdb = tdb_open("run-wronghash-fail.tdb1", TDB_VERSION1,
                   O_CREAT|O_RDWR|O_TRUNC, 0600, &log_attr);
    ok1(tdb);
    ok1(log_count == 0);
    d.dptr = (void *)"Hello";
    d.dsize = 5;
    ok1(tdb_store(tdb, d, d, TDB_INSERT) == TDB_SUCCESS);
    tdb_close(tdb);

    /* Fail to open with different hash. */
    tdb = tdb_open("run-wronghash-fail.tdb1", TDB_VERSION1, O_RDWR, 0,
                   &jhash_attr);
    ok1(!tdb);
    ok1(log_count == 1);

    /* Create with different hash. */
    log_count = 0;
    tdb = tdb_open("run-wronghash-fail.tdb1", TDB_VERSION1,
                   O_CREAT|O_RDWR|O_TRUNC, 0600, &jhash_attr);
    ok1(tdb);
    ok1(log_count == 0);
    tdb_close(tdb);

    /* Endian should be no problem. */
    log_count = 0;
    tdb = tdb_open("test/jenkins-le-hash.tdb1", TDB_VERSION1, O_RDWR, 0,
                   &ohash_attr);
    ok1(!tdb);
    ok1(log_count == 1);

    log_count = 0;
    tdb = tdb_open("test/jenkins-be-hash.tdb1", TDB_VERSION1, O_RDWR, 0,
                   &ohash_attr);
    ok1(!tdb);
    ok1(log_count == 1);

    log_count = 0;
    /* Fail to open with old default hash. */
    tdb = tdb_open("run-wronghash-fail.tdb1", TDB_VERSION1, O_RDWR, 0,
                   &ohash_attr);
    ok1(!tdb);
    ok1(log_count == 1);

    log_count = 0;
    tdb = tdb_open("test/jenkins-le-hash.tdb1", TDB_VERSION1, O_RDONLY,
                   0, &incompat_hash_attr);
    ok1(tdb);
    ok1(log_count == 0);
    ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);
    tdb_close(tdb);

    log_count = 0;
    tdb = tdb_open("test/jenkins-be-hash.tdb1", TDB_VERSION1, O_RDONLY,
                   0, &incompat_hash_attr);
    ok1(tdb);
    ok1(log_count == 0);
    ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);
    tdb_close(tdb);

    /* It should open with jenkins hash if we don't specify. */
    log_count = 0;
    tdb = tdb_open("test/jenkins-le-hash.tdb1", TDB_VERSION1, O_RDWR, 0,
                   &log_attr);
    ok1(tdb);
    ok1(log_count == 0);
    ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);
    tdb_close(tdb);

    log_count = 0;
    tdb = tdb_open("test/jenkins-be-hash.tdb1", TDB_VERSION1, O_RDWR, 0,
                   &log_attr);
    ok1(tdb);
    ok1(log_count == 0);
    ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);
    tdb_close(tdb);

    log_count = 0;
    tdb = tdb_open("run-wronghash-fail.tdb1", TDB_VERSION1, O_RDONLY,
                   0, &log_attr);
    ok1(tdb);
    ok1(log_count == 0);
    ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);
    tdb_close(tdb);


    return exit_status();
}
int main(int argc, char * const *argv)
{
	int i, seed = -1;
	int num_loops = 5000;
	int num_procs = 3;
	int c, pfds[2];
	extern char *optarg;
	pid_t *pids;
	int kill_random = 0;
	int *done;
	char *test_tdb;

	log_ctx.log_fn = tdb_log;

	while ((c = getopt(argc, argv, "n:l:s:H:thk")) != -1) {
		switch (c) {
		case 'n':
			num_procs = strtol(optarg, NULL, 0);
			break;
		case 'l':
			num_loops = strtol(optarg, NULL, 0);
			break;
		case 'H':
			hash_size = strtol(optarg, NULL, 0);
			break;
		case 's':
			seed = strtol(optarg, NULL, 0);
			break;
		case 't':
			always_transaction = 1;
			break;
		case 'k':
			kill_random = 1;
			break;
		default:
			usage();
		}
	}

	test_tdb = test_path("torture.tdb");

	unlink(test_tdb);

	if (seed == -1) {
		seed = (getpid() + time(NULL)) & 0x7FFFFFFF;
	}

	if (num_procs == 1 && !kill_random) {
		/* Don't fork for this case, makes debugging easier. */
		error_count = run_child(test_tdb, 0, seed, num_loops, 0);
		goto done;
	}

	pids = (pid_t *)calloc(sizeof(pid_t), num_procs);
	done = (int *)calloc(sizeof(int), num_procs);

	if (pipe(pfds) != 0) {
		perror("Creating pipe");
		exit(1);
	}
	count_pipe = pfds[1];

	for (i=0;i<num_procs;i++) {
		if ((pids[i]=fork()) == 0) {
			close(pfds[0]);
			if (i == 0) {
				printf("Testing with %d processes, %d loops, %d hash_size, seed=%d%s\n",
				       num_procs, num_loops, hash_size, seed, always_transaction ? " (all within transactions)" : "");
			}
			exit(run_child(test_tdb, i, seed, num_loops, 0));
		}
	}

	while (num_procs) {
		int status, j;
		pid_t pid;

		if (error_count != 0) {
			/* try and stop the test on any failure */
			for (j=0;j<num_procs;j++) {
				if (pids[j] != 0) {
					kill(pids[j], SIGTERM);
				}
			}
		}

		pid = waitpid(-1, &status, kill_random ? WNOHANG : 0);
		if (pid == 0) {
			struct timeval tv;

			/* Sleep for 1/10 second. */
			tv.tv_sec = 0;
			tv.tv_usec = 100000;
			select(0, NULL, NULL, NULL, &tv);

			/* Kill someone. */
			kill(pids[random() % num_procs], SIGUSR1);
			continue;
		}

		if (pid == -1) {
			perror("failed to wait for child\n");
			exit(1);
		}

		for (j=0;j<num_procs;j++) {
			if (pids[j] == pid) break;
		}
		if (j == num_procs) {
			printf("unknown child %d exited!?\n", (int)pid);
			exit(1);
		}
		if (WIFSIGNALED(status)) {
			if (WTERMSIG(status) == SIGUSR2
			    || WTERMSIG(status) == SIGUSR1) {
				/* SIGUSR2 means they wrote to pipe. */
				if (WTERMSIG(status) == SIGUSR2) {
					read(pfds[0], &done[j],
					     sizeof(done[j]));
				}
				pids[j] = fork();
				if (pids[j] == 0)
					exit(run_child(test_tdb, j, seed,
						       num_loops, done[j]));
				printf("Restarting child %i for %u-%u\n",
				       j, done[j], num_loops);
				continue;
			}
			printf("child %d exited with signal %d\n",
			       (int)pid, WTERMSIG(status));
			error_count++;
		} else {
			if (WEXITSTATUS(status) != 0) {
				printf("child %d exited with status %d\n",
				       (int)pid, WEXITSTATUS(status));
				error_count++;
			}
		}
		memmove(&pids[j], &pids[j+1],
			(num_procs - j - 1)*sizeof(pids[0]));
		num_procs--;
	}

	free(pids);

done:
	if (error_count == 0) {
		db = tdb_open_ex(test_tdb, hash_size, TDB_DEFAULT,
				 O_RDWR, 0, &log_ctx, NULL);
		if (!db) {
			fatal("db open failed\n");
			exit(1);
		}
		if (tdb_check(db, NULL, NULL) == -1) {
			printf("db check failed\n");
			exit(1);
		}
		tdb_close(db);
		printf("OK\n");
	}

	free(test_tdb);
	return error_count;
}
示例#29
0
static void test_val(struct tdb_context *tdb, uint64_t val)
{
	uint64_t v;
	struct tdb_data key = { (unsigned char *)&v, sizeof(v) };
	struct tdb_data d, data = { (unsigned char *)&v, sizeof(v) };

	/* Insert an entry, then delete it. */
	v = val;
	/* Delete should fail. */
	ok1(tdb_delete(tdb, key) == TDB_ERR_NOEXIST);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	/* Insert should succeed. */
	ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	/* Delete should succeed. */
	ok1(tdb_delete(tdb, key) == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	/* Re-add it, then add collision. */
	ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
	v = val + 1;
	ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	/* Can find both? */
	ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
	ok1(d.dsize == data.dsize);
	free(d.dptr);
	v = val;
	ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
	ok1(d.dsize == data.dsize);
	free(d.dptr);

	/* Delete second one. */
	v = val + 1;
	ok1(tdb_delete(tdb, key) == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	/* Re-add */
	ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	/* Now, try deleting first one. */
	v = val;
	ok1(tdb_delete(tdb, key) == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	/* Can still find second? */
	v = val + 1;
	ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
	ok1(d.dsize == data.dsize);
	free(d.dptr);

	/* Now, this will be ideally placed. */
	v = val + 2;
	ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	/* This will collide with both. */
	v = val;
	ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);

	/* We can still find them all, right? */
	ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
	ok1(d.dsize == data.dsize);
	free(d.dptr);
	v = val + 1;
	ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
	ok1(d.dsize == data.dsize);
	free(d.dptr);
	v = val + 2;
	ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
	ok1(d.dsize == data.dsize);
	free(d.dptr);

	/* And if we delete val + 1, that val + 2 should not move! */
	v = val + 1;
	ok1(tdb_delete(tdb, key) == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	v = val;
	ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
	ok1(d.dsize == data.dsize);
	free(d.dptr);
	v = val + 2;
	ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
	ok1(d.dsize == data.dsize);
	free(d.dptr);

	/* Delete those two, so we are empty. */
	ok1(tdb_delete(tdb, key) == 0);
	v = val;
	ok1(tdb_delete(tdb, key) == 0);

	ok1(tdb_check(tdb, NULL, NULL) == 0);
}
示例#30
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();
}