Exemplo n.º 1
0
static bool
verify_file(const char *fname)
{
	bool res = true;
	int fd;
	struct mtbl_reader *r;
	const struct mtbl_metadata *m;

	fd = open(fname, O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "%s: open() failed: %s\n", fname, strerror(errno));
		return false;
	}

	r = mtbl_reader_init_fd(fd, NULL);
	if (r == NULL) {
		close(fd);
		fprintf(stderr, "%s: mtbl_reader_init_fd() failed\n", fname);
		return false;
	}

	m = mtbl_reader_metadata(r);

	uint64_t count_data_blocks = mtbl_metadata_count_data_blocks(m);
	uint64_t bytes_data_blocks = mtbl_metadata_bytes_data_blocks(m);
	uint64_t index_offset = mtbl_metadata_index_block_offset(m);

	uint64_t data_offset = index_offset - bytes_data_blocks;

	if (verify_data_blocks(fd, fname, data_offset, bytes_data_blocks, count_data_blocks)) {
		printf("%s: OK\n", fname);
		res = true;
	} else {
		printf("%s: FAILED\n", fname);
		res = false;
	}

	mtbl_reader_destroy(&r);

	return res;
}
Exemplo n.º 2
0
/**
 * Write a test key ('A' * 10000) + test value ('B' * 20000) to an mtbl_writer,
 * using the given compression type. Then re-open the file with an mtbl_reader
 * and verify that we get the exact same key/value entry back.
 *
 * This tests that data block compression/decompression is functioning
 * correctly.
 *
 * We use mkstemp() to create a temporary file, then immediately unlink() and
 * dup() it, which allows us to read from the file after we close it. This
 * avoids leaving the temporary file on the filesystem if the test fails.
 */
static int
test_compression(mtbl_compression_type c_type, const char *dirname)
{
	mtbl_res res;

	/* Initialize test key/value. */
	size_t len_key = 10000;
	size_t len_val = 20000;
	uint8_t *key = my_malloc(len_key);
	uint8_t *val = my_malloc(len_val);
	memset(key, 'A', len_key);
	memset(val, 'B', len_val);

	/* Create and open temporary file. */
	char fname[strlen(dirname) + 100];
	sprintf(fname, "%s/.mtbl." NAME ".%ld.XXXXXX", dirname, (long)getpid());
	int fd = mkstemp(fname);
	if (fd == -1) {
		fprintf(stderr, NAME ": mkstemp() failed: %s\n", strerror(errno));
		return 1;
	}

	/* Unlink the temporary filename. */
	int unlink_ret = unlink(fname);
	if (unlink_ret == -1) {
		fprintf(stderr, NAME ": unlink() on file '%s' failed: %s\n",
			fname, strerror(errno));
		return 1;
	}

	/**
	 * Duplicate the file descriptor.
	 * Used by the reader, since mtbl_writer_destroy() will close the fd,
	 * which will delete the file, since it has no links on the filesystem.
	 */
	int dup_fd = dup(fd);
	if (dup_fd == -1) {
		fprintf(stderr, NAME ": dup() failed: %s\n", strerror(errno));
		return 1;
	}

	/* Open a writer on the temporary file. */
	struct mtbl_writer_options *wopt = mtbl_writer_options_init();
	mtbl_writer_options_set_compression(wopt, c_type);
	struct mtbl_writer *w = mtbl_writer_init_fd(fd, wopt);
	mtbl_writer_options_destroy(&wopt);
	if (w == NULL) {
		fprintf(stderr, NAME ": mtbl_writer_init_fd() failed\n");
		return 1;
	}

	/* Write the test key/value entry. */
	res = mtbl_writer_add(w, key, len_key, val, len_val);
	if (res != mtbl_res_success) {
		fprintf(stderr, NAME ": mtbl_writer_add() failed\n");
		return 1;
	}

	/* Close the writer. */
	mtbl_writer_destroy(&w);
	fd = -1;

	/* Open the reader on the dup()'d file descriptor. */
	struct mtbl_reader *r = mtbl_reader_init_fd(dup_fd, NULL);
	if (r == NULL) {
		fprintf(stderr, NAME ": mtbl_reader_init_fd() failed\n");
		return 1;
	}

	/**
	 * Check that the compresison algorithm on the reader was what we set
	 * on the writer.
	 */
	const struct mtbl_metadata *m = mtbl_reader_metadata(r);
	uint64_t m_c_type = mtbl_metadata_compression_algorithm(m);
	if ((mtbl_compression_type) m_c_type != c_type) {
		fprintf(stderr, NAME ": mtbl_metadata_compression_algorithm() "
			"returned unexpected value %" PRIu64 " (!= %u)\n",
			m_c_type, c_type);
		return 1;
	}

	/* Retrieve the test key/value entry. */
	const struct mtbl_source *s = mtbl_reader_source(r);
	if (s == NULL) {
		fprintf(stderr, NAME ": mtbl_reader_source() failed\n");
		return 1;
	}
	struct mtbl_iter *it = mtbl_source_iter(s);
	const uint8_t *it_key, *it_val;
	size_t len_it_key, len_it_val;
	res = mtbl_iter_next(it, &it_key, &len_it_key, &it_val, &len_it_val);
	if (res != mtbl_res_success) {
		fprintf(stderr, NAME ": mtbl_iter_next() failed\n");
		return 1;
	}

	/* Check the test entry against our original entry. */
	if (len_it_key != len_key) {
		fprintf(stderr, NAME ": len_it_key != len_key\n");
		return 1;
	}
	if (len_it_val != len_val) {
		fprintf(stderr, NAME ": len_it_val != len_val\n");
		return 1;
	}
	if (memcmp(it_key, key, len_key) != 0) {
		fprintf(stderr, NAME ": it_key != key\n");
		return 1;
	}
	if (memcmp(it_val, val, len_val) != 0) {
		fprintf(stderr, NAME ": it_val != val\n");
		return 1;
	}

	/* Test that there are no more entries. */
	res = mtbl_iter_next(it, &it_key, &len_it_key, &it_val, &len_it_val);
	if (res != mtbl_res_failure) {
		fprintf(stderr, NAME ": mtbl_iter_next() returned an "
			"additional unexpected entry\n");
		return 1;
	}

	/* Cleanup. */
	mtbl_iter_destroy(&it);
	mtbl_reader_destroy(&r);
	free(key);
	free(val);

	return 0;
}
Exemplo n.º 3
0
int main(int argc, char ** argv) {
	FILE *tmp = tmpfile();
	assert(tmp != NULL);

	init_mtbl(dup(fileno(tmp)));

	struct mtbl_reader_options *reader_options = mtbl_reader_options_init();
	assert(reader_options != NULL);

	struct mtbl_reader *reader = mtbl_reader_init_fd(dup(fileno(tmp)), reader_options);
	assert(reader != NULL);

	const struct mtbl_source *source = mtbl_reader_source(reader);
	assert(source != NULL);

	struct mtbl_iter *iter = mtbl_source_iter(source);
	assert(iter != NULL);

	test_iter(iter);
	fprintf(stderr, NAME ": PASS: iter run successful\n");

	mtbl_iter_destroy(&iter);

	struct mtbl_merger_options *merger_options = mtbl_merger_options_init();
	assert(merger_options != NULL);

	mtbl_merger_options_set_merge_func(merger_options, my_merge_func, NULL);

	struct mtbl_merger *merger = mtbl_merger_init(merger_options);
	assert(merger != NULL);

	mtbl_merger_add_source(merger, source);

	const struct mtbl_source *merger_source = mtbl_merger_source(merger);
	assert(merger_source != NULL);

	struct mtbl_iter *merger_iter = mtbl_source_iter(merger_source);
	assert(merger_iter != NULL);

	test_iter(merger_iter);
	fprintf(stderr, NAME ": PASS: merger run 1 successful\n");

	mtbl_iter_destroy(&merger_iter);
	
	FILE *tmp2 = tmpfile();
	assert(tmp != NULL);

	init_mtbl(dup(fileno(tmp2)));

	struct mtbl_reader *reader2 = mtbl_reader_init_fd(dup(fileno(tmp2)), reader_options);
	assert(reader2 != NULL);

	mtbl_merger_add_source(merger, mtbl_reader_source(reader2));

	merger_iter = mtbl_source_iter(merger_source);
	assert(merger_iter != NULL);

	test_iter(merger_iter);
	fprintf(stderr, NAME ": PASS: merger run 2 successful\n");

	mtbl_iter_destroy(&merger_iter);

	mtbl_merger_destroy(&merger);
	mtbl_merger_options_destroy(&merger_options);
	mtbl_reader_destroy(&reader);
	mtbl_reader_destroy(&reader2);
	mtbl_reader_options_destroy(&reader_options);

	fclose(tmp);
	fclose(tmp2);
}