Last active
August 29, 2015 13:57
-
-
Save tecbot/9833739 to your computer and use it in GitHub Desktop.
failing prefix test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Copyright (c) 2011 The LevelDB Authors. All rights reserved. | |
Use of this source code is governed by a BSD-style license that can be | |
found in the LICENSE file. See the AUTHORS file for names of contributors. */ | |
#include "rocksdb/c.h" | |
#include <stddef.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <sys/types.h> | |
#include <unistd.h> | |
const char* phase = ""; | |
static char dbname[200]; | |
static void StartPhase(const char* name) { | |
fprintf(stderr, "=== Test %s\n", name); | |
phase = name; | |
} | |
static const char* GetTempDir(void) { | |
const char* ret = getenv("TEST_TMPDIR"); | |
if (ret == NULL || ret[0] == '\0') | |
ret = "/tmp"; | |
return ret; | |
} | |
#define CheckNoError(err) \ | |
if ((err) != NULL) { \ | |
fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, (err)); \ | |
abort(); \ | |
} | |
#define CheckCondition(cond) \ | |
if (!(cond)) { \ | |
fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, #cond); \ | |
abort(); \ | |
} | |
static void CheckEqual(const char* expected, const char* v, size_t n) { | |
if (expected == NULL && v == NULL) { | |
// ok | |
} else if (expected != NULL && v != NULL && n == strlen(expected) && | |
memcmp(expected, v, n) == 0) { | |
// ok | |
return; | |
} else { | |
fprintf(stderr, "%s: expected '%s', got '%s'\n", | |
phase, | |
(expected ? expected : "(null)"), | |
(v ? v : "(null")); | |
abort(); | |
} | |
} | |
static void Free(char** ptr) { | |
if (*ptr) { | |
free(*ptr); | |
*ptr = NULL; | |
} | |
} | |
static void CheckGet( | |
rocksdb_t* db, | |
const rocksdb_readoptions_t* options, | |
const char* key, | |
const char* expected) { | |
char* err = NULL; | |
size_t val_len; | |
char* val; | |
val = rocksdb_get(db, options, key, strlen(key), &val_len, &err); | |
CheckNoError(err); | |
CheckEqual(expected, val, val_len); | |
Free(&val); | |
} | |
static void CheckIter(rocksdb_iterator_t* iter, | |
const char* key, const char* val) { | |
size_t len; | |
const char* str; | |
str = rocksdb_iter_key(iter, &len); | |
CheckEqual(key, str, len); | |
str = rocksdb_iter_value(iter, &len); | |
CheckEqual(val, str, len); | |
} | |
// Callback from rocksdb_writebatch_iterate() | |
static void CheckPut(void* ptr, | |
const char* k, size_t klen, | |
const char* v, size_t vlen) { | |
int* state = (int*) ptr; | |
CheckCondition(*state < 2); | |
switch (*state) { | |
case 0: | |
CheckEqual("bar", k, klen); | |
CheckEqual("b", v, vlen); | |
break; | |
case 1: | |
CheckEqual("box", k, klen); | |
CheckEqual("c", v, vlen); | |
break; | |
} | |
(*state)++; | |
} | |
// Callback from rocksdb_writebatch_iterate() | |
static void CheckDel(void* ptr, const char* k, size_t klen) { | |
int* state = (int*) ptr; | |
CheckCondition(*state == 2); | |
CheckEqual("bar", k, klen); | |
(*state)++; | |
} | |
static void CmpDestroy(void* arg) { } | |
static int CmpCompare(void* arg, const char* a, size_t alen, | |
const char* b, size_t blen) { | |
int n = (alen < blen) ? alen : blen; | |
int r = memcmp(a, b, n); | |
if (r == 0) { | |
if (alen < blen) r = -1; | |
else if (alen > blen) r = +1; | |
} | |
return r; | |
} | |
static const char* CmpName(void* arg) { | |
return "foo"; | |
} | |
// Custom filter policy | |
static unsigned char fake_filter_result = 1; | |
static void FilterDestroy(void* arg) { } | |
static const char* FilterName(void* arg) { | |
return "TestFilter"; | |
} | |
static char* FilterCreate( | |
void* arg, | |
const char* const* key_array, const size_t* key_length_array, | |
int num_keys, | |
size_t* filter_length) { | |
*filter_length = 4; | |
char* result = malloc(4); | |
memcpy(result, "fake", 4); | |
return result; | |
} | |
unsigned char FilterKeyMatch( | |
void* arg, | |
const char* key, size_t length, | |
const char* filter, size_t filter_length) { | |
CheckCondition(filter_length == 4); | |
CheckCondition(memcmp(filter, "fake", 4) == 0); | |
return fake_filter_result; | |
} | |
// Custom merge operator | |
static void MergeOperatorDestroy(void* arg) { } | |
static const char* MergeOperatorName(void* arg) { | |
return "TestMergeOperator"; | |
} | |
static char* MergeOperatorFullMerge( | |
void* arg, | |
const char* key, size_t key_length, | |
const char* existing_value, size_t existing_value_length, | |
const char* const* operands_list, const size_t* operands_list_length, | |
int num_operands, | |
unsigned char* success, size_t* new_value_length) { | |
*new_value_length = 4; | |
*success = 1; | |
char* result = malloc(4); | |
memcpy(result, "fake", 4); | |
return result; | |
} | |
static char* MergeOperatorPartialMerge( | |
void* arg, | |
const char* key, size_t key_length, | |
const char* const* operands_list, const size_t* operands_list_length, | |
int num_operands, | |
unsigned char* success, size_t* new_value_length) { | |
*new_value_length = 4; | |
*success = 1; | |
char* result = malloc(4); | |
memcpy(result, "fake", 4); | |
return result; | |
} | |
int main(int argc, char** argv) { | |
rocksdb_t* db; | |
rocksdb_comparator_t* cmp; | |
rocksdb_cache_t* cache; | |
rocksdb_env_t* env; | |
rocksdb_options_t* options; | |
rocksdb_readoptions_t* roptions; | |
rocksdb_writeoptions_t* woptions; | |
char* err = NULL; | |
int run = -1; | |
snprintf(dbname, sizeof(dbname), | |
"%s/rocksdb_c_test-%d", | |
GetTempDir(), | |
((int) geteuid())); | |
StartPhase("create_objects"); | |
cmp = rocksdb_comparator_create(NULL, CmpDestroy, CmpCompare, CmpName); | |
env = rocksdb_create_default_env(); | |
cache = rocksdb_cache_create_lru(100000); | |
options = rocksdb_options_create(); | |
rocksdb_options_set_comparator(options, cmp); | |
rocksdb_options_set_error_if_exists(options, 1); | |
rocksdb_options_set_cache(options, cache); | |
rocksdb_options_set_env(options, env); | |
rocksdb_options_set_info_log(options, NULL); | |
rocksdb_options_set_write_buffer_size(options, 100000); | |
rocksdb_options_set_paranoid_checks(options, 1); | |
rocksdb_options_set_max_open_files(options, 10); | |
rocksdb_options_set_block_size(options, 1024); | |
rocksdb_options_set_block_restart_interval(options, 8); | |
rocksdb_options_set_compression(options, rocksdb_no_compression); | |
rocksdb_options_set_compression_options(options, -14, -1, 0); | |
int compression_levels[] = {rocksdb_no_compression, rocksdb_no_compression, | |
rocksdb_no_compression, rocksdb_no_compression}; | |
rocksdb_options_set_compression_per_level(options, compression_levels, 4); | |
roptions = rocksdb_readoptions_create(); | |
rocksdb_readoptions_set_verify_checksums(roptions, 1); | |
rocksdb_readoptions_set_fill_cache(roptions, 0); | |
woptions = rocksdb_writeoptions_create(); | |
rocksdb_writeoptions_set_sync(woptions, 1); | |
StartPhase("destroy"); | |
rocksdb_destroy_db(options, dbname, &err); | |
Free(&err); | |
StartPhase("open_error"); | |
db = rocksdb_open(options, dbname, &err); | |
CheckCondition(err != NULL); | |
Free(&err); | |
StartPhase("open"); | |
rocksdb_options_set_create_if_missing(options, 1); | |
db = rocksdb_open(options, dbname, &err); | |
CheckNoError(err); | |
CheckGet(db, roptions, "foo", NULL); | |
StartPhase("put"); | |
rocksdb_put(db, woptions, "foo", 3, "hello", 5, &err); | |
CheckNoError(err); | |
CheckGet(db, roptions, "foo", "hello"); | |
StartPhase("compactall"); | |
rocksdb_compact_range(db, NULL, 0, NULL, 0); | |
CheckGet(db, roptions, "foo", "hello"); | |
StartPhase("compactrange"); | |
rocksdb_compact_range(db, "a", 1, "z", 1); | |
CheckGet(db, roptions, "foo", "hello"); | |
StartPhase("writebatch"); | |
{ | |
rocksdb_writebatch_t* wb = rocksdb_writebatch_create(); | |
rocksdb_writebatch_put(wb, "foo", 3, "a", 1); | |
rocksdb_writebatch_clear(wb); | |
rocksdb_writebatch_put(wb, "bar", 3, "b", 1); | |
rocksdb_writebatch_put(wb, "box", 3, "c", 1); | |
rocksdb_writebatch_delete(wb, "bar", 3); | |
rocksdb_write(db, woptions, wb, &err); | |
CheckNoError(err); | |
CheckGet(db, roptions, "foo", "hello"); | |
CheckGet(db, roptions, "bar", NULL); | |
CheckGet(db, roptions, "box", "c"); | |
int pos = 0; | |
rocksdb_writebatch_iterate(wb, &pos, CheckPut, CheckDel); | |
CheckCondition(pos == 3); | |
rocksdb_writebatch_destroy(wb); | |
} | |
StartPhase("iter"); | |
{ | |
rocksdb_iterator_t* iter = rocksdb_create_iterator(db, roptions); | |
CheckCondition(!rocksdb_iter_valid(iter)); | |
rocksdb_iter_seek_to_first(iter); | |
CheckCondition(rocksdb_iter_valid(iter)); | |
CheckIter(iter, "box", "c"); | |
rocksdb_iter_next(iter); | |
CheckIter(iter, "foo", "hello"); | |
rocksdb_iter_prev(iter); | |
CheckIter(iter, "box", "c"); | |
rocksdb_iter_prev(iter); | |
CheckCondition(!rocksdb_iter_valid(iter)); | |
rocksdb_iter_seek_to_last(iter); | |
CheckIter(iter, "foo", "hello"); | |
rocksdb_iter_seek(iter, "b", 1); | |
CheckIter(iter, "box", "c"); | |
rocksdb_iter_get_error(iter, &err); | |
CheckNoError(err); | |
rocksdb_iter_destroy(iter); | |
} | |
StartPhase("approximate_sizes"); | |
{ | |
int i; | |
int n = 20000; | |
char keybuf[100]; | |
char valbuf[100]; | |
uint64_t sizes[2]; | |
const char* start[2] = { "a", "k00000000000000010000" }; | |
size_t start_len[2] = { 1, 21 }; | |
const char* limit[2] = { "k00000000000000010000", "z" }; | |
size_t limit_len[2] = { 21, 1 }; | |
rocksdb_writeoptions_set_sync(woptions, 0); | |
for (i = 0; i < n; i++) { | |
snprintf(keybuf, sizeof(keybuf), "k%020d", i); | |
snprintf(valbuf, sizeof(valbuf), "v%020d", i); | |
rocksdb_put(db, woptions, keybuf, strlen(keybuf), valbuf, strlen(valbuf), | |
&err); | |
CheckNoError(err); | |
} | |
rocksdb_approximate_sizes(db, 2, start, start_len, limit, limit_len, sizes); | |
CheckCondition(sizes[0] > 0); | |
CheckCondition(sizes[1] > 0); | |
} | |
StartPhase("property"); | |
{ | |
char* prop = rocksdb_property_value(db, "nosuchprop"); | |
CheckCondition(prop == NULL); | |
prop = rocksdb_property_value(db, "rocksdb.stats"); | |
CheckCondition(prop != NULL); | |
Free(&prop); | |
} | |
StartPhase("snapshot"); | |
{ | |
const rocksdb_snapshot_t* snap; | |
snap = rocksdb_create_snapshot(db); | |
rocksdb_delete(db, woptions, "foo", 3, &err); | |
CheckNoError(err); | |
rocksdb_readoptions_set_snapshot(roptions, snap); | |
CheckGet(db, roptions, "foo", "hello"); | |
rocksdb_readoptions_set_snapshot(roptions, NULL); | |
CheckGet(db, roptions, "foo", NULL); | |
rocksdb_release_snapshot(db, snap); | |
} | |
StartPhase("repair"); | |
{ | |
// If we do not compact here, then the lazy deletion of | |
// files (https://reviews.facebook.net/D6123) would leave | |
// around deleted files and the repair process will find | |
// those files and put them back into the database. | |
rocksdb_compact_range(db, NULL, 0, NULL, 0); | |
rocksdb_close(db); | |
rocksdb_options_set_create_if_missing(options, 0); | |
rocksdb_options_set_error_if_exists(options, 0); | |
rocksdb_repair_db(options, dbname, &err); | |
CheckNoError(err); | |
db = rocksdb_open(options, dbname, &err); | |
CheckNoError(err); | |
CheckGet(db, roptions, "foo", NULL); | |
CheckGet(db, roptions, "bar", NULL); | |
CheckGet(db, roptions, "box", "c"); | |
rocksdb_options_set_create_if_missing(options, 1); | |
rocksdb_options_set_error_if_exists(options, 1); | |
} | |
StartPhase("filter"); | |
for (run = 0; run < 2; run++) { | |
// First run uses custom filter, second run uses bloom filter | |
CheckNoError(err); | |
rocksdb_filterpolicy_t* policy; | |
if (run == 0) { | |
policy = rocksdb_filterpolicy_create( | |
NULL, FilterDestroy, FilterCreate, FilterKeyMatch, NULL, FilterName); | |
} else { | |
policy = rocksdb_filterpolicy_create_bloom(10); | |
} | |
// Create new database | |
rocksdb_close(db); | |
rocksdb_destroy_db(options, dbname, &err); | |
rocksdb_options_set_filter_policy(options, policy); | |
db = rocksdb_open(options, dbname, &err); | |
CheckNoError(err); | |
rocksdb_put(db, woptions, "foo", 3, "foovalue", 8, &err); | |
CheckNoError(err); | |
rocksdb_put(db, woptions, "bar", 3, "barvalue", 8, &err); | |
CheckNoError(err); | |
rocksdb_compact_range(db, NULL, 0, NULL, 0); | |
fake_filter_result = 1; | |
CheckGet(db, roptions, "foo", "foovalue"); | |
CheckGet(db, roptions, "bar", "barvalue"); | |
if (phase == 0) { | |
// Must not find value when custom filter returns false | |
fake_filter_result = 0; | |
CheckGet(db, roptions, "foo", NULL); | |
CheckGet(db, roptions, "bar", NULL); | |
fake_filter_result = 1; | |
CheckGet(db, roptions, "foo", "foovalue"); | |
CheckGet(db, roptions, "bar", "barvalue"); | |
} | |
rocksdb_options_set_filter_policy(options, NULL); | |
rocksdb_filterpolicy_destroy(policy); | |
} | |
StartPhase("merge_operator"); | |
{ | |
rocksdb_mergeoperator_t* merge_operator; | |
merge_operator = rocksdb_mergeoperator_create( | |
NULL, MergeOperatorDestroy, MergeOperatorFullMerge, | |
MergeOperatorPartialMerge, NULL, MergeOperatorName); | |
// Create new database | |
rocksdb_close(db); | |
rocksdb_destroy_db(options, dbname, &err); | |
rocksdb_options_set_merge_operator(options, merge_operator); | |
db = rocksdb_open(options, dbname, &err); | |
CheckNoError(err); | |
rocksdb_put(db, woptions, "foo", 3, "foovalue", 8, &err); | |
CheckNoError(err); | |
CheckGet(db, roptions, "foo", "foovalue"); | |
rocksdb_merge(db, woptions, "foo", 3, "barvalue", 8, &err); | |
CheckNoError(err); | |
CheckGet(db, roptions, "foo", "fake"); | |
// Merge of a non-existing value | |
rocksdb_merge(db, woptions, "bar", 3, "barvalue", 8, &err); | |
CheckNoError(err); | |
CheckGet(db, roptions, "bar", "fake"); | |
} | |
StartPhase("prefix"); | |
{ | |
// Create new database | |
rocksdb_close(db); | |
rocksdb_destroy_db(options, dbname, &err); | |
rocksdb_options_set_filter_policy(options, rocksdb_filterpolicy_create_bloom(10)); | |
rocksdb_options_set_prefix_extractor(options, rocksdb_slicetransform_create_fixed_prefix(8)); | |
rocksdb_options_set_memtable_vector_rep(options); | |
db = rocksdb_open(options, dbname, &err); | |
CheckNoError(err); | |
rocksdb_put(db, woptions, "foo1", 4, "foo", 3, &err); | |
CheckNoError(err); | |
rocksdb_put(db, woptions, "foo2", 4, "foo", 3, &err); | |
CheckNoError(err); | |
rocksdb_put(db, woptions, "foo3", 4, "foo", 3, &err); | |
CheckNoError(err); | |
rocksdb_put(db, woptions, "bar1", 4, "bar", 3, &err); | |
CheckNoError(err); | |
rocksdb_put(db, woptions, "bar2", 4, "bar", 3, &err); | |
CheckNoError(err); | |
rocksdb_put(db, woptions, "bar3", 4, "bar", 3, &err); | |
CheckNoError(err); | |
rocksdb_readoptions_set_prefix_seek(roptions, 1); | |
rocksdb_readoptions_set_prefix(roptions, "bar", 3); | |
rocksdb_iterator_t* iter = rocksdb_create_iterator(db, roptions); | |
CheckCondition(!rocksdb_iter_valid(iter)); | |
rocksdb_iter_seek_to_first(iter); | |
rocksdb_iter_get_error(iter, &err); | |
CheckNoError(err); | |
CheckCondition(rocksdb_iter_valid(iter)); | |
CheckIter(iter, "bar1", "bar"); | |
rocksdb_iter_next(iter); | |
CheckIter(iter, "bar2", "bar"); | |
rocksdb_iter_prev(iter); | |
CheckIter(iter, "bar3", "bar"); | |
rocksdb_iter_get_error(iter, &err); | |
CheckNoError(err); | |
rocksdb_iter_destroy(iter); | |
} | |
StartPhase("cleanup"); | |
rocksdb_close(db); | |
rocksdb_options_destroy(options); | |
rocksdb_readoptions_destroy(roptions); | |
rocksdb_writeoptions_destroy(woptions); | |
rocksdb_cache_destroy(cache); | |
rocksdb_comparator_destroy(cmp); | |
rocksdb_env_destroy(env); | |
fprintf(stderr, "PASS\n"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment