示例#1
0
int main(int argc, char *argv[])
{
	unsigned int i, count;
	bool found[3];
	struct ntdb_context *ntdb0, *ntdb1, *ntdb;
	int flags[] = { NTDB_DEFAULT, NTDB_NOMMAP,
			NTDB_CONVERT, NTDB_NOMMAP|NTDB_CONVERT };

	plan_tests(sizeof(flags) / sizeof(flags[0]) * 8);
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		ntdb0 = ntdb_open("run-ntdb_foreach0.ntdb",
				  flags[i]|MAYBE_NOSYNC,
				  O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ntdb1 = ntdb_open("run-ntdb_foreach1.ntdb",
				  flags[i]|MAYBE_NOSYNC,
				  O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ntdb = ntdb_open("run-ntdb_foreach2.ntdb",
				 flags[i]|MAYBE_NOSYNC,
				 O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);

		memset(found, 0, sizeof(found));
		ntdb_foreach(set_found, found);
		ok1(found[0] && found[1] && found[2]);

		/* Test premature iteration termination */
		count = 1;
		ntdb_foreach(drop_count, &count);
		ok1(count == 0);

		ntdb_close(ntdb1);
		memset(found, 0, sizeof(found));
		ntdb_foreach(set_found, found);
		ok1(found[0] && !found[1] && found[2]);

		ntdb_close(ntdb);
		memset(found, 0, sizeof(found));
		ntdb_foreach(set_found, found);
		ok1(found[0] && !found[1] && !found[2]);

		ntdb1 = ntdb_open("run-ntdb_foreach1.ntdb",
				  flags[i]|MAYBE_NOSYNC,
				  O_RDWR, 0600, &tap_log_attr);
		memset(found, 0, sizeof(found));
		ntdb_foreach(set_found, found);
		ok1(found[0] && found[1] && !found[2]);

		ntdb_close(ntdb0);
		memset(found, 0, sizeof(found));
		ntdb_foreach(set_found, found);
		ok1(!found[0] && found[1] && !found[2]);

		ntdb_close(ntdb1);
		memset(found, 0, sizeof(found));
		ntdb_foreach(set_found, found);
		ok1(!found[0] && !found[1] && !found[2]);
		ok1(tap_log_messages == 0);
	}

	return exit_status();
}
示例#2
0
int main(int argc, char *argv[])
{
	unsigned int i, j;
	struct ntdb_context *ntdb;
	int flags[] = { NTDB_DEFAULT, NTDB_NOMMAP,
			NTDB_CONVERT, NTDB_NOMMAP|NTDB_CONVERT };
	NTDB_DATA key = { (unsigned char *)&j, sizeof(j) };
	NTDB_DATA data = { (unsigned char *)&j, sizeof(j) };

	plan_tests(sizeof(flags) / sizeof(flags[0]) * 8 + 1);
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		uint64_t features;
		ntdb = ntdb_open("run-features.ntdb", flags[i]|MAYBE_NOSYNC,
				 O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(ntdb);
		if (!ntdb)
			continue;

		/* Put some stuff in there. */
		for (j = 0; j < 100; j++) {
			if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != 0)
				fail("Storing in ntdb");
		}

		/* Mess with features fields in hdr. */
		features = (~NTDB_FEATURE_MASK ^ 1);
		ok1(ntdb_write_convert(ntdb, offsetof(struct ntdb_header,
						    features_used),
				      &features, sizeof(features)) == 0);
		ok1(ntdb_write_convert(ntdb, offsetof(struct ntdb_header,
						    features_offered),
				      &features, sizeof(features)) == 0);
		ntdb_close(ntdb);

		ntdb = ntdb_open("run-features.ntdb", flags[i]|MAYBE_NOSYNC,
				 O_RDWR, 0, &tap_log_attr);
		ok1(ntdb);
		if (!ntdb)
			continue;

		/* Should not have changed features offered. */
		ok1(ntdb_read_convert(ntdb, offsetof(struct ntdb_header,
						   features_offered),
				     &features, sizeof(features)) == 0);
		ok1(features == (~NTDB_FEATURE_MASK ^ 1));

		/* Should have cleared unknown bits in features_used. */
		ok1(ntdb_read_convert(ntdb, offsetof(struct ntdb_header,
						   features_used),
				     &features, sizeof(features)) == 0);
		ok1(features == (1 & NTDB_FEATURE_MASK));

		ntdb_close(ntdb);
	}

	ok1(tap_log_messages == 0);
	return exit_status();
}
示例#3
0
int main(int argc, char *argv[])
{
	unsigned int i;
	struct ntdb_context *ntdb;
	struct agent *agent;
	union ntdb_attribute cif;
	NTDB_DATA key = ntdb_mkdata(KEY_STR, strlen(KEY_STR));
	int flags[] = { NTDB_DEFAULT, NTDB_NOMMAP,
			NTDB_CONVERT, NTDB_NOMMAP|NTDB_CONVERT };

	cif.openhook.base.attr = NTDB_ATTRIBUTE_OPENHOOK;
	cif.openhook.base.next = &tap_log_attr;
	cif.openhook.fn = clear_if_first;
	cif.openhook.data = clear_if_first;

	agent = prepare_external_agent();
	plan_tests(sizeof(flags) / sizeof(flags[0]) * 13);
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		/* Create it */
		ntdb = ntdb_open("run-83-openhook.ntdb", flags[i]|MAYBE_NOSYNC,
				 O_RDWR|O_CREAT|O_TRUNC, 0600, NULL);
		ok1(ntdb);
		ok1(ntdb_store(ntdb, key, key, NTDB_REPLACE) == 0);
		ntdb_close(ntdb);

		/* Now, open with CIF, should clear it. */
		ntdb = ntdb_open("run-83-openhook.ntdb", flags[i]|MAYBE_NOSYNC,
				 O_RDWR, 0, &cif);
		ok1(ntdb);
		ok1(!ntdb_exists(ntdb, key));
		ok1(ntdb_store(ntdb, key, key, NTDB_REPLACE) == 0);

		/* Agent should not clear it, since it's still open. */
		ok1(external_agent_operation(agent, OPEN_WITH_HOOK,
					     "run-83-openhook.ntdb") == SUCCESS);
		ok1(external_agent_operation(agent, FETCH, KEY_STR "=" KEY_STR)
		    == SUCCESS);
		ok1(external_agent_operation(agent, CLOSE, "") == SUCCESS);

		/* Still exists for us too. */
		ok1(ntdb_exists(ntdb, key));

		/* Close it, now agent should clear it. */
		ntdb_close(ntdb);

		ok1(external_agent_operation(agent, OPEN_WITH_HOOK,
					     "run-83-openhook.ntdb") == SUCCESS);
		ok1(external_agent_operation(agent, FETCH, KEY_STR "=" KEY_STR)
		    == FAILED);
		ok1(external_agent_operation(agent, CLOSE, "") == SUCCESS);

		ok1(tap_log_messages == 0);
	}

	free_external_agent(agent);
	return exit_status();
}
示例#4
0
int main(int argc, char *argv[])
{
	unsigned int i, messages = 0;
	struct ntdb_context *ntdb;
	int flags[] = { NTDB_DEFAULT, NTDB_NOMMAP,
			NTDB_CONVERT, NTDB_NOMMAP|NTDB_CONVERT };

	failtest_init(argc, argv);
	failtest_hook = block_repeat_failures;
	failtest_exit_check = exit_check_log;
	plan_tests(sizeof(flags) / sizeof(flags[0]) * 4);
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		ntdb = ntdb_open("run-35-convert.ntdb", flags[i]|MAYBE_NOSYNC,
				 O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		if (!ok1(ntdb))
			failtest_exit(exit_status());

		ntdb_close(ntdb);
		/* We can fail in log message formatting or open.  That's OK */
		if (failtest_has_failed()) {
			failtest_exit(exit_status());
		}
		/* If we say NTDB_CONVERT, it must be converted */
		ntdb = ntdb_open("run-35-convert.ntdb",
				 flags[i]|NTDB_CONVERT|MAYBE_NOSYNC,
				 O_RDWR, 0600, &tap_log_attr);
		if (flags[i] & NTDB_CONVERT) {
			if (!ntdb)
				failtest_exit(exit_status());
			ok1(ntdb_get_flags(ntdb) & NTDB_CONVERT);
			ntdb_close(ntdb);
		} else {
			if (!ok1(!ntdb && errno == EIO))
				failtest_exit(exit_status());
			ok1(tap_log_messages == ++messages);
			if (!ok1(log_last && strstr(log_last, "NTDB_CONVERT")))
				failtest_exit(exit_status());
		}

		/* If don't say NTDB_CONVERT, it *may* be converted */
		ntdb = ntdb_open("run-35-convert.ntdb",
				 (flags[i] & ~NTDB_CONVERT)|MAYBE_NOSYNC,
				 O_RDWR, 0600, &tap_log_attr);
		if (!ntdb)
			failtest_exit(exit_status());
		ok1(ntdb_get_flags(ntdb) == (flags[i]|MAYBE_NOSYNC));
		ntdb_close(ntdb);
	}
	failtest_exit(exit_status());
}
示例#5
0
static int dump_ntdb(const char *fname, const char *keyname)
{
	struct ntdb_context *ntdb;
	NTDB_DATA key, value;

	ntdb = ntdb_open(fname, 0, O_RDONLY, 0, NULL);
	if (!ntdb) {
		printf("Failed to open %s\n", fname);
		return 1;
	}

	if (!keyname) {
		ntdb_traverse(ntdb, traverse_fn, NULL);
	} else {
		key = ntdb_mkdata(keyname, strlen(keyname));
		if (ntdb_fetch(ntdb, key, &value) != 0) {
			return 1;
		} else {
			print_data(value);
			free(value.dptr);
		}
	}

	return 0;
}
示例#6
0
int main(int argc, char *argv[])
{
	unsigned int i;
	struct ntdb_context *ntdb;
	int flags[] = { NTDB_INTERNAL, NTDB_DEFAULT, NTDB_NOMMAP,
			NTDB_INTERNAL|NTDB_CONVERT, NTDB_CONVERT,
			NTDB_NOMMAP|NTDB_CONVERT };
	NTDB_DATA key = ntdb_mkdata("key", 3);
	NTDB_DATA data = ntdb_mkdata("data", 4);

	plan_tests(sizeof(flags) / sizeof(flags[0]) * 7 + 1);
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		ntdb = ntdb_open("run-simple-delete.ntdb",
				 flags[i]|MAYBE_NOSYNC,
				 O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(ntdb);
		if (ntdb) {
			/* Delete should fail. */
			ok1(ntdb_delete(ntdb, key) == NTDB_ERR_NOEXIST);
			ok1(ntdb_check(ntdb, NULL, NULL) == 0);
			/* Insert should succeed. */
			ok1(ntdb_store(ntdb, key, data, NTDB_INSERT) == 0);
			ok1(ntdb_check(ntdb, NULL, NULL) == 0);
			/* Delete should now work. */
			ok1(ntdb_delete(ntdb, key) == 0);
			ok1(ntdb_check(ntdb, NULL, NULL) == 0);
			ntdb_close(ntdb);
		}
	}
	ok1(tap_log_messages == 0);
	return exit_status();
}
示例#7
0
int main(int argc, char *argv[])
{
	unsigned int i;
	struct ntdb_context *ntdb;
	int flags[] = { NTDB_INTERNAL, NTDB_DEFAULT, NTDB_NOMMAP,
			NTDB_INTERNAL|NTDB_CONVERT, NTDB_CONVERT,
			NTDB_NOMMAP|NTDB_CONVERT };

	failtest_init(argc, argv);
	failtest_hook = block_repeat_failures;
	failtest_exit_check = exit_check_log;
	plan_tests(sizeof(flags) / sizeof(flags[0]) * 3);
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		ntdb = ntdb_open("run-new_database.ntdb", flags[i]|MAYBE_NOSYNC,
				 O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		if (!ok1(ntdb))
			failtest_exit(exit_status());

		failtest_suppress = true;
		ok1(ntdb_check(ntdb, NULL, NULL) == 0);
		failtest_suppress = false;
		ntdb_close(ntdb);
		if (!ok1(tap_log_messages == 0))
			break;
	}
	failtest_exit(exit_status());

	/*
	 * We will never reach this but the compiler complains if we do not
	 * return in this function.
	 */
	return EFAULT;
}
示例#8
0
int main(int argc, char *argv[])
{
	unsigned int i;
	bool found[NUM_TESTS];
	struct ntdb_context *ntdb;
	int flags[] = { NTDB_DEFAULT, NTDB_NOMMAP,
			NTDB_CONVERT, NTDB_NOMMAP|NTDB_CONVERT
	};

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

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

		ok1(store_all(ntdb));

		ok1(ntdb_repack(ntdb) == NTDB_SUCCESS);
		memset(found, 0, sizeof(found));
		ok1(ntdb_check(ntdb, NULL, NULL) == NTDB_SUCCESS);
		ok1(ntdb_traverse(ntdb, mark_entry, found) == NUM_TESTS);
		ok1(is_all_set(found, NUM_TESTS));
		ntdb_close(ntdb);
	}

	ok1(tap_log_messages == 0);
	return exit_status();
}
int main(int argc, char *argv[])
{
	unsigned int i;
	struct agent *agent;
	struct ntdb_context *ntdb;
	NTDB_DATA d = ntdb_mkdata("hello", 5);
	const char filename[] = "run-remap-in-read_traverse.ntdb";

	plan_tests(4);

	agent = prepare_external_agent();

	ntdb = ntdb_open(filename, MAYBE_NOSYNC,
		       O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);

	ok1(external_agent_operation(agent, OPEN, filename) == SUCCESS);
	i = add_records_to_grow(agent, ntdb->file->fd, ntdb->file->map_size);

	/* Do a traverse. */
	ok1(ntdb_traverse(ntdb, NULL, NULL) == i);

	/* Now store something! */
	ok1(ntdb_store(ntdb, d, d, NTDB_INSERT) == 0);
	ok1(tap_log_messages == 0);
	ntdb_close(ntdb);
	free_external_agent(agent);
	return exit_status();
}
示例#10
0
int main(int argc, char *argv[])
{
	unsigned int i;
	uint64_t val;
	struct ntdb_context *ntdb;
	int flags[] = { NTDB_INTERNAL, NTDB_DEFAULT, NTDB_NOMMAP,
			NTDB_INTERNAL|NTDB_CONVERT, NTDB_CONVERT,
			NTDB_NOMMAP|NTDB_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;
		ntdb = ntdb_open("run-expand.ntdb", flags[i]|MAYBE_NOSYNC,
				 O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		if (!ok1(ntdb))
			break;

		val = ntdb->file->map_size;
		/* Need some hash lock for expand. */
		ok1(ntdb_lock_hash(ntdb, 0, F_WRLCK) == 0);
		failtest_suppress = false;
		if (!ok1(ntdb_expand(ntdb, 1) == 0)) {
			failtest_suppress = true;
			ntdb_close(ntdb);
			break;
		}
		failtest_suppress = true;

		ok1(ntdb->file->map_size >= val + 1 * NTDB_EXTENSION_FACTOR);
		ok1(ntdb_unlock_hash(ntdb, 0, F_WRLCK) == 0);
		ok1(ntdb_check(ntdb, NULL, NULL) == 0);

		val = ntdb->file->map_size;
		ok1(ntdb_lock_hash(ntdb, 0, F_WRLCK) == 0);
		failtest_suppress = false;
		if (!ok1(ntdb_expand(ntdb, 1024) == 0)) {
			failtest_suppress = true;
			ntdb_close(ntdb);
			break;
		}
		failtest_suppress = true;
		ok1(ntdb_unlock_hash(ntdb, 0, F_WRLCK) == 0);
		ok1(ntdb->file->map_size >= val + 1024 * NTDB_EXTENSION_FACTOR);
		ok1(ntdb_check(ntdb, NULL, NULL) == 0);
		ntdb_close(ntdb);
	}

	ok1(tap_log_messages == 0);
	failtest_exit(exit_status());
}
示例#11
0
int main(int argc, char *argv[])
{
	unsigned int i;
	struct ntdb_context *ntdb;
	int flags[] = { NTDB_DEFAULT, NTDB_NOMMAP,
			NTDB_CONVERT, NTDB_NOMMAP|NTDB_CONVERT };

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

	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		union ntdb_attribute *attr;
		NTDB_DATA key = ntdb_mkdata("key", 3), data;

		ntdb = ntdb_open("run-91-get-stats.ntdb", flags[i]|MAYBE_NOSYNC,
				 O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(ntdb);
		/* Force an expansion */
		data.dsize = 65536;
		data.dptr = calloc(data.dsize, 1);
		ok1(ntdb_store(ntdb, key, data, NTDB_REPLACE) == 0);
		free(data.dptr);

		/* Use malloc so valgrind will catch overruns. */
		attr = malloc(sizeof *attr);
		attr->stats.base.attr = NTDB_ATTRIBUTE_STATS;
		attr->stats.size = sizeof(*attr);

		ok1(ntdb_get_attribute(ntdb, attr) == 0);
		ok1(attr->stats.size == sizeof(*attr));
		ok1(attr->stats.allocs > 0);
		ok1(attr->stats.expands > 0);
		ok1(attr->stats.locks > 0);
		free(attr);

		/* Try short one. */
		attr = malloc(offsetof(struct ntdb_attribute_stats, allocs)
			      + sizeof(attr->stats.allocs));
		attr->stats.base.attr = NTDB_ATTRIBUTE_STATS;
		attr->stats.size = offsetof(struct ntdb_attribute_stats, allocs)
			+ sizeof(attr->stats.allocs);
		ok1(ntdb_get_attribute(ntdb, attr) == 0);
		ok1(attr->stats.size == sizeof(*attr));
		ok1(attr->stats.allocs > 0);
		free(attr);
		ok1(tap_log_messages == 0);

		ntdb_close(ntdb);

	}
	return exit_status();
}
示例#12
0
static void open_ntdb(const char *tdbname)
{
	union ntdb_attribute log_attr;
	log_attr.base.attr = NTDB_ATTRIBUTE_LOG;
	log_attr.base.next = NULL;
	log_attr.log.fn = ntdb_log;

	if (ntdb) ntdb_close(ntdb);
	ntdb = ntdb_open(tdbname, disable_mmap?NTDB_NOMMAP:0, O_RDWR, 0600,
		       &log_attr);
	if (!ntdb) {
		printf("Could not open %s: %s\n", tdbname, strerror(errno));
	}
}
示例#13
0
int main(int argc, char *argv[])
{
	unsigned int i, j;
	struct ntdb_context *ntdb;
	int flags[] = { NTDB_INTERNAL, NTDB_DEFAULT, NTDB_NOMMAP,
			NTDB_INTERNAL|NTDB_CONVERT, NTDB_CONVERT,
			NTDB_NOMMAP|NTDB_CONVERT };
	NTDB_DATA key = { (unsigned char *)&j, sizeof(j) };
	NTDB_DATA data = { (unsigned char *)&j, sizeof(j) };
	char *summary;

	plan_tests(sizeof(flags) / sizeof(flags[0]) * (1 + 2 * 5) + 1);
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		ntdb = ntdb_open("run-summary.ntdb", flags[i]|MAYBE_NOSYNC,
				 O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(ntdb);
		if (!ntdb)
			continue;

		/* Put some stuff in there. */
		for (j = 0; j < 500; j++) {
			/* Make sure padding varies to we get some graphs! */
			data.dsize = j % (sizeof(j) + 1);
			if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != 0)
				fail("Storing in ntdb");
		}

		for (j = 0;
		     j <= NTDB_SUMMARY_HISTOGRAMS;
		     j += NTDB_SUMMARY_HISTOGRAMS) {
			ok1(ntdb_summary(ntdb, j, &summary) == NTDB_SUCCESS);
			ok1(strstr(summary, "Number of records: 500\n"));
			ok1(strstr(summary, "Smallest/average/largest keys: 4/4/4\n"));
			ok1(strstr(summary, "Smallest/average/largest data: 0/2/4\n"));
			if (j == NTDB_SUMMARY_HISTOGRAMS) {
				ok1(strstr(summary, "|")
				    && strstr(summary, "*"));
			} else {
				ok1(!strstr(summary, "|")
				    && !strstr(summary, "*"));
			}
			free(summary);
		}
		ntdb_close(ntdb);
	}

	ok1(tap_log_messages == 0);
	return exit_status();
}
示例#14
0
int main(int argc, char *argv[])
{
	unsigned int i, j;
	union ntdb_attribute alloc_attr;
	struct ntdb_context *ntdb;
	int flags[] = { NTDB_INTERNAL, NTDB_DEFAULT, NTDB_NOMMAP,
			NTDB_INTERNAL|NTDB_CONVERT, NTDB_CONVERT,
			NTDB_NOMMAP|NTDB_CONVERT };
	NTDB_DATA key = { (unsigned char *)&j, sizeof(j) };
	NTDB_DATA data = { (unsigned char *)&j, sizeof(j) };

	alloc_attr.base.next = &tap_log_attr;
	alloc_attr.base.attr = NTDB_ATTRIBUTE_ALLOCATOR;

	alloc_attr.alloc.alloc = test_alloc;
	alloc_attr.alloc.expand = test_expand;
	alloc_attr.alloc.free = test_free;
	alloc_attr.alloc.priv_data = &owner_weird_count;

	plan_tests(sizeof(flags) / sizeof(flags[0]) * (1 + 700 * 3 + 4) + 1);

	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		curr_ntdb = NULL;
		curr_file = NULL;
		ntdb = ntdb_open("run-12-store.ntdb", flags[i]|MAYBE_NOSYNC,
			       O_RDWR|O_CREAT|O_TRUNC, 0600, &alloc_attr);
		ok1(ntdb);
		if (!ntdb)
			continue;

		for (j = 0; j < 700; j++) {
			NTDB_DATA d = { NULL, 0 }; /* Bogus GCC warning */
			ok1(ntdb_store(ntdb, key, data, NTDB_REPLACE) == 0);
			ok1(ntdb_fetch(ntdb, key, &d) == NTDB_SUCCESS);
			ok1(ntdb_deq(d, data));
			test_free(d.dptr, &owner_weird_count);
		}
		ntdb_close(ntdb);

		ok1(owner_null_count == 2+i*2);
		ok1(owner_weird_count == 0);
		ok1(alloc_count == free_count);
		ok1(expand_count != 0);
	}

	ok1(tap_log_messages == 0);
	return exit_status();
}
int main(int argc, char *argv[])
{
	unsigned int i;
	int flags[] = { NTDB_DEFAULT, NTDB_NOMMAP, NTDB_CONVERT };
	NTDB_DATA key = ntdb_mkdata("hello", 5), data = ntdb_mkdata("world", 5);

	plan_tests(sizeof(flags) / sizeof(flags[0]) * 2 + 1);
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		ntdb = ntdb_open("api-95-read-only-during-parse.ntdb",
				 flags[i]|MAYBE_NOSYNC,
				 O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(ntdb_store(ntdb, key, data, NTDB_INSERT) == NTDB_SUCCESS);
		ok1(ntdb_parse_record(ntdb, key, parse, &data) == NTDB_SUCCESS);
		ntdb_close(ntdb);
	}

	ok1(tap_log_messages == 0);
	return exit_status();
}
示例#16
0
文件: ntdb.c 项目: AIdrifter/samba
_PUBLIC_ enum NTDB_ERROR ntdb_repack(struct ntdb_context *ntdb)
{
	struct ntdb_context *tmp_db;
	struct traverse_state state;

	state.error = ntdb_transaction_start(ntdb);
	if (state.error != NTDB_SUCCESS) {
		return state.error;
	}

	tmp_db = ntdb_open("tmpdb", NTDB_INTERNAL, O_RDWR|O_CREAT, 0, NULL);
	if (tmp_db == NULL) {
		state.error = ntdb_logerr(ntdb, NTDB_ERR_OOM, NTDB_LOG_ERROR,
					 __location__
					 " Failed to create tmp_db");
		ntdb_transaction_cancel(ntdb);
		return state.error;
	}

	state.dest_db = tmp_db;
	if (ntdb_traverse(ntdb, repack_traverse, &state) < 0) {
		goto fail;
	}

	state.error = ntdb_wipe_all(ntdb);
	if (state.error != NTDB_SUCCESS) {
		goto fail;
	}

	state.dest_db = ntdb;
	if (ntdb_traverse(tmp_db, repack_traverse, &state) < 0) {
		goto fail;
	}

	ntdb_close(tmp_db);
	return ntdb_transaction_commit(ntdb);

fail:
	ntdb_transaction_cancel(ntdb);
	ntdb_close(tmp_db);
	return state.error;
}
示例#17
0
static void move_rec(char *keyname, size_t keylen, char* tdbname)
{
	NTDB_DATA key, dbuf;
	struct ntdb_context *dst_ntdb;
	enum NTDB_ERROR ecode;

	if ((keyname == NULL) || (keylen == 0)) {
		terror(NTDB_SUCCESS, "need key");
		return;
	}

	if ( !tdbname ) {
		terror(NTDB_SUCCESS, "need destination ntdb name");
		return;
	}

	key.dptr = (unsigned char *)keyname;
	key.dsize = keylen;

	ecode = ntdb_fetch(ntdb, key, &dbuf);
	if (ecode) {
		terror(ecode, "fetch failed");
		return;
	}

	print_rec(ntdb, key, dbuf, NULL);

	dst_ntdb = ntdb_open(tdbname, 0, O_RDWR, 0600, NULL);
	if ( !dst_ntdb ) {
		terror(NTDB_SUCCESS, "unable to open destination ntdb");
		return;
	}

	ecode = ntdb_store( dst_ntdb, key, dbuf, NTDB_REPLACE);
	if (ecode)
		terror(ecode, "failed to move record");
	else
		printf("record moved\n");

	ntdb_close( dst_ntdb );
}
int main(int argc, char *argv[])
{
	unsigned int i;
	struct ntdb_context *ntdb;
	int flags[] = { NTDB_INTERNAL, NTDB_DEFAULT, NTDB_NOMMAP,
			NTDB_INTERNAL|NTDB_CONVERT, NTDB_CONVERT,
			NTDB_NOMMAP|NTDB_CONVERT };
	NTDB_DATA key = ntdb_mkdata("key", 3);
	NTDB_DATA data;

	data.dptr = malloc(MAX_SIZE);
	memset(data.dptr, 0x24, MAX_SIZE);

	plan_tests(sizeof(flags) / sizeof(flags[0])
		   * (3 + (1 + (MAX_SIZE/SIZE_STEP)) * 2) + 1);
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		ntdb = ntdb_open("run-record-expand.ntdb",
				 flags[i]|MAYBE_NOSYNC,
				 O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(ntdb);
		if (!ntdb)
			continue;

		data.dsize = 0;
		ok1(ntdb_store(ntdb, key, data, NTDB_INSERT) == 0);
		ok1(ntdb_check(ntdb, NULL, NULL) == 0);
		for (data.dsize = 0;
		     data.dsize < MAX_SIZE;
		     data.dsize += SIZE_STEP) {
			memset(data.dptr, data.dsize, data.dsize);
			ok1(ntdb_store(ntdb, key, data, NTDB_MODIFY) == 0);
			ok1(ntdb_check(ntdb, NULL, NULL) == 0);
		}
		ntdb_close(ntdb);
	}
	ok1(tap_log_messages == 0);
	free(data.dptr);

	return exit_status();
}
int main(int argc, char *argv[])
{
	const int flags[] = { NTDB_DEFAULT, NTDB_NOMMAP,
			NTDB_CONVERT, NTDB_NOMMAP|NTDB_CONVERT };
	int i;
	struct ntdb_context *ntdb;
	NTDB_DATA key, data;

	plan_tests(sizeof(flags)/sizeof(flags[0]) * 5);
	agent = prepare_external_agent();
	if (!agent)
		err(1, "preparing agent");

	unlock_callback = after_unlock;
	for (i = 0; i < sizeof(flags)/sizeof(flags[0]); i++) {
		diag("Test with %s and %s\n",
		     (flags[i] & NTDB_CONVERT) ? "CONVERT" : "DEFAULT",
		     (flags[i] & NTDB_NOMMAP) ? "no mmap" : "mmap");
		unlink(TEST_DBNAME);
		ntdb = ntdb_open(TEST_DBNAME, flags[i]|MAYBE_NOSYNC,
				 O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(ntdb);

		opened = true;
		ok1(ntdb_transaction_start(ntdb) == 0);
		key = ntdb_mkdata("hi", strlen("hi"));
		data = ntdb_mkdata("world", strlen("world"));

		ok1(ntdb_store(ntdb, key, data, NTDB_INSERT) == 0);
		ok1(ntdb_transaction_commit(ntdb) == 0);
		ok(!errors, "We had %u open errors", errors);

		opened = false;
		ntdb_close(ntdb);
	}

	return exit_status();
}
示例#20
0
int main(int argc, char *argv[])
{
	unsigned int i;
	struct ntdb_context *ntdb;
	int flags[] = { NTDB_INTERNAL,
			NTDB_INTERNAL|NTDB_CONVERT,
			NTDB_CONVERT };
	NTDB_DATA key = ntdb_mkdata("key", 3);
	NTDB_DATA data = ntdb_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++) {
		ntdb = ntdb_open("run-12-check.ntdb", flags[i]|MAYBE_NOSYNC,
				 O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(ntdb);
		ok1(ntdb_store(ntdb, key, data, NTDB_INSERT) == 0);

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

		ntdb_close(ntdb);
	}
	ok1(tap_log_messages == 0);
	failtest_exit(exit_status());

fail:
	failtest_suppress = true;
	ntdb_close(ntdb);
	failtest_exit(exit_status());
}
int main(int argc, char *argv[])
{
	unsigned int i;
	struct ntdb_context *ntdb;
	int flags[] = { NTDB_INTERNAL, NTDB_DEFAULT, NTDB_NOMMAP,
			NTDB_INTERNAL|NTDB_CONVERT, NTDB_CONVERT,
			NTDB_NOMMAP|NTDB_CONVERT };

	plan_tests(sizeof(flags) / sizeof(flags[0]) * 3);
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		ntdb = ntdb_open("api-80-ntdb_fd.ntdb", flags[i]|MAYBE_NOSYNC,
			       O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		if (!ok1(ntdb))
			continue;

		if (flags[i] & NTDB_INTERNAL)
			ok1(ntdb_fd(ntdb) == -1);
		else
			ok1(ntdb_fd(ntdb) > 2);
		ntdb_close(ntdb);
		ok1(tap_log_messages == 0);
	}
	return exit_status();
}
示例#22
0
int main(int argc, char *argv[])
{
	unsigned int i, seq;
	struct ntdb_context *ntdb;
	NTDB_DATA d = { NULL, 0 }; /* Bogus GCC warning */
	NTDB_DATA key = ntdb_mkdata("key", 3);
	NTDB_DATA data = ntdb_mkdata("data", 4);
	int flags[] = { NTDB_INTERNAL, NTDB_DEFAULT, NTDB_NOMMAP,
			NTDB_INTERNAL|NTDB_CONVERT, NTDB_CONVERT,
			NTDB_NOMMAP|NTDB_CONVERT };

	plan_tests(sizeof(flags) / sizeof(flags[0]) * 15 + 4 * 13);
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		ntdb = ntdb_open("api-81-seqnum.ntdb",
				 flags[i]|NTDB_SEQNUM|MAYBE_NOSYNC,
				 O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		if (!ok1(ntdb))
			continue;

		seq = 0;
		ok1(ntdb_get_seqnum(ntdb) == seq);
		ok1(ntdb_store(ntdb, key, data, NTDB_INSERT) == 0);
		ok1(ntdb_get_seqnum(ntdb) == ++seq);
		/* Fetch doesn't change seqnum */
		if (ok1(ntdb_fetch(ntdb, key, &d) == NTDB_SUCCESS))
			free(d.dptr);
		ok1(ntdb_get_seqnum(ntdb) == seq);
		ok1(ntdb_append(ntdb, key, data) == NTDB_SUCCESS);
		ok1(ntdb_get_seqnum(ntdb) == ++seq);

		ok1(ntdb_delete(ntdb, key) == NTDB_SUCCESS);
		ok1(ntdb_get_seqnum(ntdb) == ++seq);
		/* Empty append works */
		ok1(ntdb_append(ntdb, key, data) == NTDB_SUCCESS);
		ok1(ntdb_get_seqnum(ntdb) == ++seq);

		ok1(ntdb_wipe_all(ntdb) == NTDB_SUCCESS);
		ok1(ntdb_get_seqnum(ntdb) == ++seq);

		if (!(flags[i] & NTDB_INTERNAL)) {
			ok1(ntdb_transaction_start(ntdb) == NTDB_SUCCESS);
			ok1(ntdb_store(ntdb, key, data, NTDB_INSERT) == 0);
			ok1(ntdb_get_seqnum(ntdb) == ++seq);
			ok1(ntdb_append(ntdb, key, data) == NTDB_SUCCESS);
			ok1(ntdb_get_seqnum(ntdb) == ++seq);
			ok1(ntdb_delete(ntdb, key) == NTDB_SUCCESS);
			ok1(ntdb_get_seqnum(ntdb) == ++seq);
			ok1(ntdb_transaction_commit(ntdb) == NTDB_SUCCESS);
			ok1(ntdb_get_seqnum(ntdb) == seq);

			ok1(ntdb_transaction_start(ntdb) == NTDB_SUCCESS);
			ok1(ntdb_store(ntdb, key, data, NTDB_INSERT) == 0);
			ok1(ntdb_get_seqnum(ntdb) == seq + 1);
			ntdb_transaction_cancel(ntdb);
			ok1(ntdb_get_seqnum(ntdb) == seq);
		}
		ntdb_close(ntdb);
		ok1(tap_log_messages == 0);
	}
	return exit_status();
}
示例#23
0
int main(int argc, char *argv[])
{
	unsigned int i;
	struct ntdb_context *ntdb;
	int flags[] = { NTDB_DEFAULT, NTDB_NOMMAP,
			NTDB_CONVERT, NTDB_NOMMAP|NTDB_CONVERT };
	NTDB_DATA key = ntdb_mkdata("key", 3);
	NTDB_DATA data = ntdb_mkdata("data", 4), d;
	union ntdb_attribute seed_attr;
	unsigned int msgs = 0;

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

	seed_attr.base.attr = NTDB_ATTRIBUTE_SEED;
	seed_attr.base.next = &tap_log_attr;
	seed_attr.seed.seed = 0;

	failtest_suppress = true;
	plan_tests(sizeof(flags) / sizeof(flags[0]) * 11);
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		ntdb = ntdb_open("run-05-readonly-open.ntdb",
				 flags[i]|MAYBE_NOSYNC,
				 O_RDWR|O_CREAT|O_TRUNC, 0600,
				 &seed_attr);
		ok1(ntdb_store(ntdb, key, data, NTDB_INSERT) == 0);
		ntdb_close(ntdb);

		failtest_suppress = false;
		ntdb = ntdb_open("run-05-readonly-open.ntdb",
				 flags[i]|MAYBE_NOSYNC,
				 O_RDONLY, 0600, &tap_log_attr);
		if (!ok1(ntdb))
			break;
		ok1(tap_log_messages == msgs);
		/* Fetch should succeed, stores should fail. */
		if (!ok1(ntdb_fetch(ntdb, key, &d) == 0))
			goto fail;
		ok1(ntdb_deq(d, data));
		free(d.dptr);
		if (!ok1(ntdb_store(ntdb, key, data, NTDB_MODIFY)
			 == NTDB_ERR_RDONLY))
			goto fail;
		ok1(tap_log_messages == ++msgs);
		if (!ok1(ntdb_store(ntdb, key, data, NTDB_INSERT)
			 == NTDB_ERR_RDONLY))
			goto fail;
		ok1(tap_log_messages == ++msgs);
		failtest_suppress = true;
		ok1(ntdb_check(ntdb, NULL, NULL) == 0);
		ntdb_close(ntdb);
		ok1(tap_log_messages == msgs);
		/* SIGH: failtest bug, it doesn't save the ntdb file because
		 * we have it read-only.  If we go around again, it gets
		 * changed underneath us and things get screwy. */
		if (failtest_has_failed())
			break;
	}
	failtest_exit(exit_status());

fail:
	failtest_suppress = true;
	ntdb_close(ntdb);
	failtest_exit(exit_status());
}
int main(int argc, char *argv[])
{
	unsigned int i;
	struct ntdb_context *ntdb;
	int flags[] = { NTDB_DEFAULT, NTDB_NOMMAP,
			NTDB_CONVERT, NTDB_NOMMAP|NTDB_CONVERT };
	NTDB_DATA key = ntdb_mkdata("key", 3);
	NTDB_DATA data = ntdb_mkdata("data", 4);

	plan_tests(sizeof(flags) / sizeof(flags[0]) * 14);
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		int status;

		tap_log_messages = 0;

		ntdb = ntdb_open("run-fork-test.ntdb",
				 flags[i]|MAYBE_NOSYNC,
				 O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		if (!ok1(ntdb))
			continue;

		/* Put a record in here. */
		ok1(ntdb_store(ntdb, key, data, NTDB_REPLACE) == NTDB_SUCCESS);

		ok1(ntdb_chainlock(ntdb, key) == NTDB_SUCCESS);
		if (fork() == 0) {
			/* We expect this to fail. */
			if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != NTDB_ERR_LOCK)
				return 1;

			if (ntdb_fetch(ntdb, key, &data) != NTDB_ERR_LOCK)
				return 1;

			if (tap_log_messages != 2)
				return 2;

			/* Child can do this without any complaints. */
			ntdb_chainunlock(ntdb, key);
			if (tap_log_messages != 2)
				return 3;
			ntdb_close(ntdb);
			if (tap_log_messages != 2)
				return 4;
			return 0;
		}
		wait(&status);
		ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
		ntdb_chainunlock(ntdb, key);

		ok1(ntdb_lockall(ntdb) == NTDB_SUCCESS);
		if (fork() == 0) {
			/* We expect this to fail. */
			if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != NTDB_ERR_LOCK)
				return 1;

			if (ntdb_fetch(ntdb, key, &data) != NTDB_ERR_LOCK)
				return 1;

			if (tap_log_messages != 2)
				return 2;

			/* Child can do this without any complaints. */
			ntdb_unlockall(ntdb);
			if (tap_log_messages != 2)
				return 3;
			ntdb_close(ntdb);
			if (tap_log_messages != 2)
				return 4;
			return 0;
		}
		wait(&status);
		ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
		ntdb_unlockall(ntdb);

		ok1(ntdb_lockall_read(ntdb) == NTDB_SUCCESS);
		if (fork() == 0) {
			/* We expect this to fail. */
			/* This would always fail anyway... */
			if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != NTDB_ERR_LOCK)
				return 1;

			if (ntdb_fetch(ntdb, key, &data) != NTDB_ERR_LOCK)
				return 1;

			if (tap_log_messages != 2)
				return 2;

			/* Child can do this without any complaints. */
			ntdb_unlockall_read(ntdb);
			if (tap_log_messages != 2)
				return 3;
			ntdb_close(ntdb);
			if (tap_log_messages != 2)
				return 4;
			return 0;
		}
		wait(&status);
		ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
		ntdb_unlockall_read(ntdb);

		ok1(ntdb_transaction_start(ntdb) == NTDB_SUCCESS);
		/* If transactions is empty, noop "commit" succeeds. */
		ok1(ntdb_delete(ntdb, key) == NTDB_SUCCESS);
		if (fork() == 0) {
			int last_log_messages;

			/* We expect this to fail. */
			if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != NTDB_ERR_LOCK)
				return 1;

			if (ntdb_fetch(ntdb, key, &data) != NTDB_ERR_LOCK)
				return 1;

			if (tap_log_messages != 2)
				return 2;

			if (ntdb_transaction_prepare_commit(ntdb)
			    != NTDB_ERR_LOCK)
				return 3;
			if (tap_log_messages == 2)
				return 4;

			last_log_messages = tap_log_messages;
			/* Child can do this without any complaints. */
			ntdb_transaction_cancel(ntdb);
			if (tap_log_messages != last_log_messages)
				return 4;
			ntdb_close(ntdb);
			if (tap_log_messages != last_log_messages)
				return 4;
			return 0;
		}
		wait(&status);
		ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
		ntdb_transaction_cancel(ntdb);

		ok1(ntdb_parse_record(ntdb, key, fork_in_parse, ntdb)
		    == NTDB_SUCCESS);
		ntdb_close(ntdb);
		if (am_child) {
			/* Child can return from parse without complaints. */
			if (tap_log_messages != 2)
				exit(3);
			exit(0);
		}
		ok1(tap_log_messages == 0);
	}
	return exit_status();
}
int main(int argc, char *argv[])
{
	unsigned int i;
	struct ntdb_context *ntdb;
	NTDB_DATA key = ntdb_mkdata("key", 3);
	NTDB_DATA data = ntdb_mkdata("data", 4);
	int flags[] = { NTDB_DEFAULT, NTDB_NOMMAP,
			NTDB_CONVERT, NTDB_NOMMAP|NTDB_CONVERT };

	plan_tests(sizeof(flags) / sizeof(flags[0]) * 48);

	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		/* RW -> R0 */
		ntdb = ntdb_open("run-92-get-set-readonly.ntdb",
				 flags[i]|MAYBE_NOSYNC,
				 O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(ntdb);
		ok1(!(ntdb_get_flags(ntdb) & NTDB_RDONLY));

		ok1(ntdb_store(ntdb, key, data, NTDB_INSERT) == NTDB_SUCCESS);

		ntdb_add_flag(ntdb, NTDB_RDONLY);
		ok1(ntdb_get_flags(ntdb) & NTDB_RDONLY);

		/* Can't store, append, delete. */
		ok1(ntdb_store(ntdb, key, data, NTDB_MODIFY) == NTDB_ERR_RDONLY);
		ok1(tap_log_messages == 1);
		ok1(ntdb_append(ntdb, key, data) == NTDB_ERR_RDONLY);
		ok1(tap_log_messages == 2);
		ok1(ntdb_delete(ntdb, key) == NTDB_ERR_RDONLY);
		ok1(tap_log_messages == 3);

		/* Can't start a transaction, or any write lock. */
		ok1(ntdb_transaction_start(ntdb) == NTDB_ERR_RDONLY);
		ok1(tap_log_messages == 4);
		ok1(ntdb_chainlock(ntdb, key) == NTDB_ERR_RDONLY);
		ok1(tap_log_messages == 5);
		ok1(ntdb_lockall(ntdb) == NTDB_ERR_RDONLY);
		ok1(tap_log_messages == 6);
		ok1(ntdb_wipe_all(ntdb) == NTDB_ERR_RDONLY);
		ok1(tap_log_messages == 7);

		/* Back to RW. */
		ntdb_remove_flag(ntdb, NTDB_RDONLY);
		ok1(!(ntdb_get_flags(ntdb) & NTDB_RDONLY));

		ok1(ntdb_store(ntdb, key, data, NTDB_MODIFY) == NTDB_SUCCESS);
		ok1(ntdb_append(ntdb, key, data) == NTDB_SUCCESS);
		ok1(ntdb_delete(ntdb, key) == NTDB_SUCCESS);

		ok1(ntdb_transaction_start(ntdb) == NTDB_SUCCESS);
		ok1(ntdb_store(ntdb, key, data, NTDB_INSERT) == NTDB_SUCCESS);
		ok1(ntdb_transaction_commit(ntdb) == NTDB_SUCCESS);

		ok1(ntdb_chainlock(ntdb, key) == NTDB_SUCCESS);
		ntdb_chainunlock(ntdb, key);
		ok1(ntdb_lockall(ntdb) == NTDB_SUCCESS);
		ntdb_unlockall(ntdb);
		ok1(ntdb_wipe_all(ntdb) == NTDB_SUCCESS);
		ok1(tap_log_messages == 7);

		ntdb_close(ntdb);

		/* R0 -> RW */
		ntdb = ntdb_open("run-92-get-set-readonly.ntdb",
				 flags[i]|MAYBE_NOSYNC,
				 O_RDONLY, 0600, &tap_log_attr);
		ok1(ntdb);
		ok1(ntdb_get_flags(ntdb) & NTDB_RDONLY);

		/* Can't store, append, delete. */
		ok1(ntdb_store(ntdb, key, data, NTDB_INSERT) == NTDB_ERR_RDONLY);
		ok1(tap_log_messages == 8);
		ok1(ntdb_append(ntdb, key, data) == NTDB_ERR_RDONLY);
		ok1(tap_log_messages == 9);
		ok1(ntdb_delete(ntdb, key) == NTDB_ERR_RDONLY);
		ok1(tap_log_messages == 10);

		/* Can't start a transaction, or any write lock. */
		ok1(ntdb_transaction_start(ntdb) == NTDB_ERR_RDONLY);
		ok1(tap_log_messages == 11);
		ok1(ntdb_chainlock(ntdb, key) == NTDB_ERR_RDONLY);
		ok1(tap_log_messages == 12);
		ok1(ntdb_lockall(ntdb) == NTDB_ERR_RDONLY);
		ok1(tap_log_messages == 13);
		ok1(ntdb_wipe_all(ntdb) == NTDB_ERR_RDONLY);
		ok1(tap_log_messages == 14);

		/* Can't remove NTDB_RDONLY since we opened with O_RDONLY */
		ntdb_remove_flag(ntdb, NTDB_RDONLY);
		ok1(tap_log_messages == 15);
		ok1(ntdb_get_flags(ntdb) & NTDB_RDONLY);
		ntdb_close(ntdb);

		ok1(tap_log_messages == 15);
		tap_log_messages = 0;
	}
	return exit_status();
}
示例#26
0
int main(int argc, char *argv[])
{
	unsigned int i;
	struct ntdb_context *ntdb;
	unsigned char *buffer;
	int flags[] = { NTDB_DEFAULT, NTDB_NOMMAP,
			NTDB_CONVERT, NTDB_NOMMAP|NTDB_CONVERT };
	NTDB_DATA key = ntdb_mkdata("key", 3);
	NTDB_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++) {
		ntdb = ntdb_open("run-55-transaction.ntdb",
				 flags[i]|MAYBE_NOSYNC,
				 O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(ntdb);
		if (!ntdb)
			continue;

		ok1(ntdb_transaction_start(ntdb) == 0);
		data.dptr = buffer;
		data.dsize = 1000;
		ok1(ntdb_store(ntdb, key, data, NTDB_INSERT) == 0);
		ok1(ntdb_fetch(ntdb, key, &data) == NTDB_SUCCESS);
		ok1(data.dsize == 1000);
		ok1(memcmp(data.dptr, buffer, data.dsize) == 0);
		free(data.dptr);

		/* Cancelling a transaction means no store */
		ntdb_transaction_cancel(ntdb);
		ok1(ntdb->file->allrecord_lock.count == 0
		    && ntdb->file->num_lockrecs == 0);
		ok1(ntdb_check(ntdb, NULL, NULL) == 0);
		ok1(ntdb_fetch(ntdb, key, &data) == NTDB_ERR_NOEXIST);

		/* Commit the transaction. */
		ok1(ntdb_transaction_start(ntdb) == 0);
		data.dptr = buffer;
		data.dsize = 1000;
		ok1(ntdb_store(ntdb, key, data, NTDB_INSERT) == 0);
		ok1(ntdb_fetch(ntdb, key, &data) == NTDB_SUCCESS);
		ok1(data.dsize == 1000);
		ok1(memcmp(data.dptr, buffer, data.dsize) == 0);
		free(data.dptr);
		ok1(ntdb_transaction_commit(ntdb) == 0);
		ok1(ntdb->file->allrecord_lock.count == 0
		    && ntdb->file->num_lockrecs == 0);
		ok1(ntdb_check(ntdb, NULL, NULL) == 0);
		ok1(ntdb_fetch(ntdb, key, &data) == NTDB_SUCCESS);
		ok1(data.dsize == 1000);
		ok1(memcmp(data.dptr, buffer, data.dsize) == 0);
		free(data.dptr);

		ntdb_close(ntdb);
	}

	ok1(tap_log_messages == 0);
	free(buffer);
	return exit_status();
}
示例#27
0
static enum agent_return do_operation(enum operation op, const char *name)
{
	NTDB_DATA k, d;
	enum agent_return ret;
	NTDB_DATA data;
	enum NTDB_ERROR ecode;
	union ntdb_attribute cif;
	const char *eq;

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

	diag("external: %s", operation_name(op));

	eq = strchr(name, '=');
	if (eq) {
		k = ntdb_mkdata(name, eq - name);
		d = ntdb_mkdata(eq + 1, strlen(eq+1));
	} else {
		k = ntdb_mkdata(name, strlen(name));
		d.dsize = 0;
		d.dptr = NULL;
	}

	locking_would_block = 0;
	switch (op) {
	case OPEN:
		if (ntdb) {
			diag("Already have ntdb %s open", ntdb_name(ntdb));
			return OTHER_FAILURE;
		}
		ntdb = ntdb_open(name, MAYBE_NOSYNC, O_RDWR, 0, &tap_log_attr);
		if (!ntdb) {
			if (!locking_would_block)
				diag("Opening ntdb gave %s", strerror(errno));
			forget_locking();
			ret = OTHER_FAILURE;
		} else
			ret = SUCCESS;
		break;
	case OPEN_WITH_HOOK:
		if (ntdb) {
			diag("Already have ntdb %s open", ntdb_name(ntdb));
			return OTHER_FAILURE;
		}
		cif.openhook.base.attr = NTDB_ATTRIBUTE_OPENHOOK;
		cif.openhook.base.next = &tap_log_attr;
		cif.openhook.fn = clear_if_first;
		ntdb = ntdb_open(name, MAYBE_NOSYNC, O_RDWR, 0, &cif);
		if (!ntdb) {
			if (!locking_would_block)
				diag("Opening ntdb gave %s", strerror(errno));
			forget_locking();
			ret = OTHER_FAILURE;
		} else
			ret = SUCCESS;
		break;
	case FETCH:
		ecode = ntdb_fetch(ntdb, k, &data);
		if (ecode == NTDB_ERR_NOEXIST) {
			ret = FAILED;
		} else if (ecode < 0) {
			ret = OTHER_FAILURE;
		} else if (!ntdb_deq(data, d)) {
			ret = OTHER_FAILURE;
			external_agent_free(data.dptr);
		} else {
			ret = SUCCESS;
			external_agent_free(data.dptr);
		}
		break;
	case STORE:
		ret = ntdb_store(ntdb, k, d, 0) == 0 ? SUCCESS : OTHER_FAILURE;
		break;
	case TRANSACTION_START:
		ret = ntdb_transaction_start(ntdb) == 0 ? SUCCESS : OTHER_FAILURE;
		break;
	case TRANSACTION_COMMIT:
		ret = ntdb_transaction_commit(ntdb)==0 ? SUCCESS : OTHER_FAILURE;
		break;
	case NEEDS_RECOVERY:
		ret = external_agent_needs_rec(ntdb);
		break;
	case CHECK:
		ret = ntdb_check(ntdb, NULL, NULL) == 0 ? SUCCESS : OTHER_FAILURE;
		break;
	case CLOSE:
		ret = ntdb_close(ntdb) == 0 ? SUCCESS : OTHER_FAILURE;
		ntdb = 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;
}
示例#28
0
文件: speed.c 项目: AIdrifter/samba
static void dump_and_clear_stats(struct ntdb_context **ntdb,
				 int flags,
				 union ntdb_attribute *attr)
{
	union ntdb_attribute stats;
	enum NTDB_ERROR ecode;

	stats.base.attr = NTDB_ATTRIBUTE_STATS;
	stats.stats.size = sizeof(stats.stats);
	ecode = ntdb_get_attribute(*ntdb, &stats);
	if (ecode != NTDB_SUCCESS)
		errx(1, "Getting stats: %s", ntdb_errorstr(ecode));

	printf("allocs = %llu\n",
	       (unsigned long long)stats.stats.allocs);
	printf("  alloc_subhash = %llu\n",
	       (unsigned long long)stats.stats.alloc_subhash);
	printf("  alloc_chain = %llu\n",
	       (unsigned long long)stats.stats.alloc_chain);
	printf("  alloc_bucket_exact = %llu\n",
	       (unsigned long long)stats.stats.alloc_bucket_exact);
	printf("  alloc_bucket_max = %llu\n",
	       (unsigned long long)stats.stats.alloc_bucket_max);
	printf("  alloc_leftover = %llu\n",
	       (unsigned long long)stats.stats.alloc_leftover);
	printf("  alloc_coalesce_tried = %llu\n",
	       (unsigned long long)stats.stats.alloc_coalesce_tried);
	printf("    alloc_coalesce_iterate_clash = %llu\n",
	       (unsigned long long)stats.stats.alloc_coalesce_iterate_clash);
	printf("    alloc_coalesce_lockfail = %llu\n",
	       (unsigned long long)stats.stats.alloc_coalesce_lockfail);
	printf("    alloc_coalesce_race = %llu\n",
	       (unsigned long long)stats.stats.alloc_coalesce_race);
	printf("    alloc_coalesce_succeeded = %llu\n",
	       (unsigned long long)stats.stats.alloc_coalesce_succeeded);
	printf("      alloc_coalesce_num_merged = %llu\n",
	       (unsigned long long)stats.stats.alloc_coalesce_num_merged);
	printf("compares = %llu\n",
	       (unsigned long long)stats.stats.compares);
	printf("  compare_wrong_offsetbits = %llu\n",
	       (unsigned long long)stats.stats.compare_wrong_offsetbits);
	printf("  compare_wrong_keylen = %llu\n",
	       (unsigned long long)stats.stats.compare_wrong_keylen);
	printf("  compare_wrong_rechash = %llu\n",
	       (unsigned long long)stats.stats.compare_wrong_rechash);
	printf("  compare_wrong_keycmp = %llu\n",
	       (unsigned long long)stats.stats.compare_wrong_keycmp);
	printf("transactions = %llu\n",
	       (unsigned long long)stats.stats.transactions);
	printf("  transaction_cancel = %llu\n",
	       (unsigned long long)stats.stats.transaction_cancel);
	printf("  transaction_nest = %llu\n",
	       (unsigned long long)stats.stats.transaction_nest);
	printf("  transaction_expand_file = %llu\n",
	       (unsigned long long)stats.stats.transaction_expand_file);
	printf("  transaction_read_direct = %llu\n",
	       (unsigned long long)stats.stats.transaction_read_direct);
	printf("    transaction_read_direct_fail = %llu\n",
	       (unsigned long long)stats.stats.transaction_read_direct_fail);
	printf("  transaction_write_direct = %llu\n",
	       (unsigned long long)stats.stats.transaction_write_direct);
	printf("    transaction_write_direct_fail = %llu\n",
	       (unsigned long long)stats.stats.transaction_write_direct_fail);
	printf("expands = %llu\n",
	       (unsigned long long)stats.stats.expands);
	printf("frees = %llu\n",
	       (unsigned long long)stats.stats.frees);
	printf("locks = %llu\n",
	       (unsigned long long)stats.stats.locks);
	printf("  lock_lowlevel = %llu\n",
	       (unsigned long long)stats.stats.lock_lowlevel);
	printf("  lock_nonblock = %llu\n",
	       (unsigned long long)stats.stats.lock_nonblock);
	printf("    lock_nonblock_fail = %llu\n",
	       (unsigned long long)stats.stats.lock_nonblock_fail);

	/* Now clear. */
	ntdb_close(*ntdb);
	*ntdb = ntdb_open("/tmp/speed.ntdb", flags, O_RDWR, 0, attr);
}
示例#29
0
文件: speed.c 项目: AIdrifter/samba
int main(int argc, char *argv[])
{
	unsigned int i, j, num = 1000, stage = 0, stopat = -1;
	int flags = NTDB_DEFAULT;
	bool transaction = false, summary = false;
	NTDB_DATA key, data;
	struct ntdb_context *ntdb;
	struct timeval start, stop;
	union ntdb_attribute seed, log;
	bool do_stats = false;
	enum NTDB_ERROR ecode;

	/* Try to keep benchmarks even. */
	seed.base.attr = NTDB_ATTRIBUTE_SEED;
	seed.base.next = NULL;
	seed.seed.seed = 0;

	log.base.attr = NTDB_ATTRIBUTE_LOG;
	log.base.next = &seed;
	log.log.fn = ntdb_log;

	if (argv[1] && strcmp(argv[1], "--internal") == 0) {
		flags = NTDB_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 |= NTDB_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++;
	}

	ntdb = ntdb_open("/tmp/speed.ntdb", flags, O_RDWR|O_CREAT|O_TRUNC,
		       0600, &log);
	if (!ntdb)
		err(1, "Opening /tmp/speed.ntdb");

	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 = ntdb_transaction_start(ntdb)))
		errx(1, "starting transaction: %s", ntdb_errorstr(ecode));
	gettimeofday(&start, NULL);
	for (i = 0; i < num; i++)
		if ((ecode = ntdb_store(ntdb, key, data, NTDB_INSERT)) != 0)
			errx(1, "Inserting key %u in ntdb: %s",
			     i, ntdb_errorstr(ecode));
	gettimeofday(&stop, NULL);
	if (transaction && (ecode = ntdb_transaction_commit(ntdb)))
		errx(1, "committing transaction: %s", ntdb_errorstr(ecode));
	printf(" %zu ns (%zu bytes)\n",
	       normalize(&start, &stop, num), file_size());

	if (ntdb_check(ntdb, NULL, NULL))
		errx(1, "ntdb_check failed!");
	if (summary) {
		char *sumstr = NULL;
		ntdb_summary(ntdb, NTDB_SUMMARY_HISTOGRAMS, &sumstr);
		printf("%s\n", sumstr);
		free(sumstr);
	}
	if (do_stats)
		dump_and_clear_stats(&ntdb, flags, &log);

	if (++stage == stopat)
		exit(0);

	/* Finding 1000 records. */
	printf("Finding %u records: ", num); fflush(stdout);
	if (transaction && (ecode = ntdb_transaction_start(ntdb)))
		errx(1, "starting transaction: %s", ntdb_errorstr(ecode));
	gettimeofday(&start, NULL);
	for (i = 0; i < num; i++) {
		NTDB_DATA dbuf;
		if ((ecode = ntdb_fetch(ntdb, key, &dbuf)) != NTDB_SUCCESS
		    || *(int *)dbuf.dptr != i) {
			errx(1, "Fetching key %u in ntdb gave %u",
			     i, ecode ? ecode : *(int *)dbuf.dptr);
		}
	}
	gettimeofday(&stop, NULL);
	if (transaction && (ecode = ntdb_transaction_commit(ntdb)))
		errx(1, "committing transaction: %s", ntdb_errorstr(ecode));
	printf(" %zu ns (%zu bytes)\n",
	       normalize(&start, &stop, num), file_size());
	if (ntdb_check(ntdb, NULL, NULL))
		errx(1, "ntdb_check failed!");
	if (summary) {
		char *sumstr = NULL;
		ntdb_summary(ntdb, NTDB_SUMMARY_HISTOGRAMS, &sumstr);
		printf("%s\n", sumstr);
		free(sumstr);
	}
	if (do_stats)
		dump_and_clear_stats(&ntdb, flags, &log);
	if (++stage == stopat)
		exit(0);

	/* Missing 1000 records. */
	printf("Missing %u records: ", num); fflush(stdout);
	if (transaction && (ecode = ntdb_transaction_start(ntdb)))
		errx(1, "starting transaction: %s", ntdb_errorstr(ecode));
	gettimeofday(&start, NULL);
	for (i = num; i < num*2; i++) {
		NTDB_DATA dbuf;
		ecode = ntdb_fetch(ntdb, key, &dbuf);
		if (ecode != NTDB_ERR_NOEXIST)
			errx(1, "Fetching key %u in ntdb gave %s",
			     i, ntdb_errorstr(ecode));
	}
	gettimeofday(&stop, NULL);
	if (transaction && (ecode = ntdb_transaction_commit(ntdb)))
		errx(1, "committing transaction: %s", ntdb_errorstr(ecode));
	printf(" %zu ns (%zu bytes)\n",
	       normalize(&start, &stop, num), file_size());
	if (ntdb_check(ntdb, NULL, NULL))
		errx(1, "ntdb_check failed!");
	if (summary) {
		char *sumstr = NULL;
		ntdb_summary(ntdb, NTDB_SUMMARY_HISTOGRAMS, &sumstr);
		printf("%s\n", sumstr);
		free(sumstr);
	}
	if (do_stats)
		dump_and_clear_stats(&ntdb, flags, &log);
	if (++stage == stopat)
		exit(0);

	/* Traverse 1000 records. */
	printf("Traversing %u records: ", num); fflush(stdout);
	if (transaction && (ecode = ntdb_transaction_start(ntdb)))
		errx(1, "starting transaction: %s", ntdb_errorstr(ecode));
	i = 0;
	gettimeofday(&start, NULL);
	if (ntdb_traverse(ntdb, 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 = ntdb_transaction_commit(ntdb)))
		errx(1, "committing transaction: %s", ntdb_errorstr(ecode));
	printf(" %zu ns (%zu bytes)\n",
	       normalize(&start, &stop, num), file_size());
	if (ntdb_check(ntdb, NULL, NULL))
		errx(1, "ntdb_check failed!");
	if (summary) {
		char *sumstr = NULL;
		ntdb_summary(ntdb, NTDB_SUMMARY_HISTOGRAMS, &sumstr);
		printf("%s\n", sumstr);
		free(sumstr);
	}
	if (do_stats)
		dump_and_clear_stats(&ntdb, flags, &log);
	if (++stage == stopat)
		exit(0);

	/* Delete 1000 records (not in order). */
	printf("Deleting %u records: ", num); fflush(stdout);
	if (transaction && (ecode = ntdb_transaction_start(ntdb)))
		errx(1, "starting transaction: %s", ntdb_errorstr(ecode));
	gettimeofday(&start, NULL);
	for (j = 0; j < num; j++) {
		i = (j + 100003) % num;
		if ((ecode = ntdb_delete(ntdb, key)) != NTDB_SUCCESS)
			errx(1, "Deleting key %u in ntdb: %s",
			     i, ntdb_errorstr(ecode));
	}
	gettimeofday(&stop, NULL);
	if (transaction && (ecode = ntdb_transaction_commit(ntdb)))
		errx(1, "committing transaction: %s", ntdb_errorstr(ecode));
	printf(" %zu ns (%zu bytes)\n",
	       normalize(&start, &stop, num), file_size());
	if (ntdb_check(ntdb, NULL, NULL))
		errx(1, "ntdb_check failed!");
	if (summary) {
		char *sumstr = NULL;
		ntdb_summary(ntdb, NTDB_SUMMARY_HISTOGRAMS, &sumstr);
		printf("%s\n", sumstr);
		free(sumstr);
	}
	if (do_stats)
		dump_and_clear_stats(&ntdb, 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 = ntdb_transaction_start(ntdb)))
		errx(1, "starting transaction: %s", ntdb_errorstr(ecode));
	gettimeofday(&start, NULL);
	for (j = 0; j < num; j++) {
		i = (j + 100003) % num;
		if ((ecode = ntdb_store(ntdb, key, data, NTDB_INSERT)) != 0)
			errx(1, "Inserting key %u in ntdb: %s",
			     i, ntdb_errorstr(ecode));
	}
	gettimeofday(&stop, NULL);
	if (transaction && (ecode = ntdb_transaction_commit(ntdb)))
		errx(1, "committing transaction: %s", ntdb_errorstr(ecode));
	printf(" %zu ns (%zu bytes)\n",
	       normalize(&start, &stop, num), file_size());
	if (ntdb_check(ntdb, NULL, NULL))
		errx(1, "ntdb_check failed!");
	if (summary) {
		char *sumstr = NULL;
		ntdb_summary(ntdb, NTDB_SUMMARY_HISTOGRAMS, &sumstr);
		printf("%s\n", sumstr);
		free(sumstr);
	}
	if (do_stats)
		dump_and_clear_stats(&ntdb, flags, &log);
	if (++stage == stopat)
		exit(0);

	/* Append 1000 records. */
	if (transaction && (ecode = ntdb_transaction_start(ntdb)))
		errx(1, "starting transaction: %s", ntdb_errorstr(ecode));
	printf("Appending %u records: ", num); fflush(stdout);
	gettimeofday(&start, NULL);
	for (i = 0; i < num; i++)
		if ((ecode = ntdb_append(ntdb, key, data)) != NTDB_SUCCESS)
			errx(1, "Appending key %u in ntdb: %s",
			     i, ntdb_errorstr(ecode));
	gettimeofday(&stop, NULL);
	if (transaction && (ecode = ntdb_transaction_commit(ntdb)))
		errx(1, "committing transaction: %s", ntdb_errorstr(ecode));
	printf(" %zu ns (%zu bytes)\n",
	       normalize(&start, &stop, num), file_size());
	if (ntdb_check(ntdb, NULL, NULL))
		errx(1, "ntdb_check failed!");
	if (summary) {
		char *sumstr = NULL;
		ntdb_summary(ntdb, NTDB_SUMMARY_HISTOGRAMS, &sumstr);
		printf("%s\n", sumstr);
		free(sumstr);
	}
	if (++stage == stopat)
		exit(0);

	/* Churn 1000 records: not in order! */
	if (transaction && (ecode = ntdb_transaction_start(ntdb)))
		errx(1, "starting transaction: %s", ntdb_errorstr(ecode));
	printf("Churning %u records: ", num); fflush(stdout);
	gettimeofday(&start, NULL);
	for (j = 0; j < num; j++) {
		i = (j + 1000019) % num;
		if ((ecode = ntdb_delete(ntdb, key)) != NTDB_SUCCESS)
			errx(1, "Deleting key %u in ntdb: %s",
			     i, ntdb_errorstr(ecode));
		i += num;
		if ((ecode = ntdb_store(ntdb, key, data, NTDB_INSERT)) != 0)
			errx(1, "Inserting key %u in ntdb: %s",
			     i, ntdb_errorstr(ecode));
	}
	gettimeofday(&stop, NULL);
	if (transaction && (ecode = ntdb_transaction_commit(ntdb)))
		errx(1, "committing transaction: %s", ntdb_errorstr(ecode));
	printf(" %zu ns (%zu bytes)\n",
	       normalize(&start, &stop, num), file_size());

	if (ntdb_check(ntdb, NULL, NULL))
		errx(1, "ntdb_check failed!");
	if (summary) {
		char *sumstr = NULL;
		ntdb_summary(ntdb, NTDB_SUMMARY_HISTOGRAMS, &sumstr);
		printf("%s\n", sumstr);
		free(sumstr);
	}
	if (do_stats)
		dump_and_clear_stats(&ntdb, flags, &log);
	if (++stage == stopat)
		exit(0);

	return 0;
}
int main(int argc, char *argv[])
{
	unsigned int i;
	struct ntdb_context *ntdb;
	int flags[] = { NTDB_INTERNAL, NTDB_DEFAULT, NTDB_NOMMAP,
			NTDB_INTERNAL|NTDB_CONVERT, NTDB_CONVERT,
			NTDB_NOMMAP|NTDB_CONVERT };

	plan_tests(87);
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		ntdb = ntdb_open("run-add-remove-flags.ntdb",
				 flags[i]|MAYBE_NOSYNC,
				 O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(ntdb);
		if (!ntdb)
			continue;

		ok1(ntdb_get_flags(ntdb) == ntdb->flags);
		tap_log_messages = 0;
		ntdb_add_flag(ntdb, NTDB_NOLOCK);
		if (flags[i] & NTDB_INTERNAL)
			ok1(tap_log_messages == 1);
		else {
			ok1(tap_log_messages == 0);
			ok1(ntdb_get_flags(ntdb) & NTDB_NOLOCK);
		}

		tap_log_messages = 0;
		ntdb_add_flag(ntdb, NTDB_NOMMAP);
		if (flags[i] & NTDB_INTERNAL)
			ok1(tap_log_messages == 1);
		else {
			ok1(tap_log_messages == 0);
			ok1(ntdb_get_flags(ntdb) & NTDB_NOMMAP);
			ok1(ntdb->file->map_ptr == NULL);
		}

		tap_log_messages = 0;
		ntdb_add_flag(ntdb, NTDB_NOSYNC);
		if (flags[i] & NTDB_INTERNAL)
			ok1(tap_log_messages == 1);
		else {
			ok1(tap_log_messages == 0);
			ok1(ntdb_get_flags(ntdb) & NTDB_NOSYNC);
		}

		ok1(ntdb_get_flags(ntdb) == ntdb->flags);

		tap_log_messages = 0;
		ntdb_remove_flag(ntdb, NTDB_NOLOCK);
		if (flags[i] & NTDB_INTERNAL)
			ok1(tap_log_messages == 1);
		else {
			ok1(tap_log_messages == 0);
			ok1(!(ntdb_get_flags(ntdb) & NTDB_NOLOCK));
		}

		tap_log_messages = 0;
		ntdb_remove_flag(ntdb, NTDB_NOMMAP);
		if (flags[i] & NTDB_INTERNAL)
			ok1(tap_log_messages == 1);
		else {
			ok1(tap_log_messages == 0);
			ok1(!(ntdb_get_flags(ntdb) & NTDB_NOMMAP));
			ok1(ntdb->file->map_ptr != NULL);
		}

		tap_log_messages = 0;
		ntdb_remove_flag(ntdb, NTDB_NOSYNC);
		if (flags[i] & NTDB_INTERNAL)
			ok1(tap_log_messages == 1);
		else {
			ok1(tap_log_messages == 0);
			ok1(!(ntdb_get_flags(ntdb) & NTDB_NOSYNC));
		}

		ntdb_close(ntdb);
	}

	ok1(tap_log_messages == 0);
	return exit_status();
}