作者: 韩晨旭 10225101440 李畅 10225102463
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

391 rivejä
11 KiB

  1. /* Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  2. Use of this source code is governed by a BSD-style license that can be
  3. found in the LICENSE file. See the AUTHORS file for names of contributors. */
  4. #include "leveldb/c.h"
  5. #include <stddef.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <sys/types.h>
  10. #include <unistd.h>
  11. const char* phase = "";
  12. static char dbname[200];
  13. static void StartPhase(const char* name) {
  14. fprintf(stderr, "=== Test %s\n", name);
  15. phase = name;
  16. }
  17. static const char* GetTempDir(void) {
  18. const char* ret = getenv("TEST_TMPDIR");
  19. if (ret == NULL || ret[0] == '\0')
  20. ret = "/tmp";
  21. return ret;
  22. }
  23. #define CheckNoError(err) \
  24. if ((err) != NULL) { \
  25. fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, (err)); \
  26. abort(); \
  27. }
  28. #define CheckCondition(cond) \
  29. if (!(cond)) { \
  30. fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, #cond); \
  31. abort(); \
  32. }
  33. static void CheckEqual(const char* expected, const char* v, size_t n) {
  34. if (expected == NULL && v == NULL) {
  35. // ok
  36. } else if (expected != NULL && v != NULL && n == strlen(expected) &&
  37. memcmp(expected, v, n) == 0) {
  38. // ok
  39. return;
  40. } else {
  41. fprintf(stderr, "%s: expected '%s', got '%s'\n",
  42. phase,
  43. (expected ? expected : "(null)"),
  44. (v ? v : "(null"));
  45. abort();
  46. }
  47. }
  48. static void Free(char** ptr) {
  49. if (*ptr) {
  50. free(*ptr);
  51. *ptr = NULL;
  52. }
  53. }
  54. static void CheckGet(
  55. leveldb_t* db,
  56. const leveldb_readoptions_t* options,
  57. const char* key,
  58. const char* expected) {
  59. char* err = NULL;
  60. size_t val_len;
  61. char* val;
  62. val = leveldb_get(db, options, key, strlen(key), &val_len, &err);
  63. CheckNoError(err);
  64. CheckEqual(expected, val, val_len);
  65. Free(&val);
  66. }
  67. static void CheckIter(leveldb_iterator_t* iter,
  68. const char* key, const char* val) {
  69. size_t len;
  70. const char* str;
  71. str = leveldb_iter_key(iter, &len);
  72. CheckEqual(key, str, len);
  73. str = leveldb_iter_value(iter, &len);
  74. CheckEqual(val, str, len);
  75. }
  76. // Callback from leveldb_writebatch_iterate()
  77. static void CheckPut(void* ptr,
  78. const char* k, size_t klen,
  79. const char* v, size_t vlen) {
  80. int* state = (int*) ptr;
  81. CheckCondition(*state < 2);
  82. switch (*state) {
  83. case 0:
  84. CheckEqual("bar", k, klen);
  85. CheckEqual("b", v, vlen);
  86. break;
  87. case 1:
  88. CheckEqual("box", k, klen);
  89. CheckEqual("c", v, vlen);
  90. break;
  91. }
  92. (*state)++;
  93. }
  94. // Callback from leveldb_writebatch_iterate()
  95. static void CheckDel(void* ptr, const char* k, size_t klen) {
  96. int* state = (int*) ptr;
  97. CheckCondition(*state == 2);
  98. CheckEqual("bar", k, klen);
  99. (*state)++;
  100. }
  101. static void CmpDestroy(void* arg) { }
  102. static int CmpCompare(void* arg, const char* a, size_t alen,
  103. const char* b, size_t blen) {
  104. int n = (alen < blen) ? alen : blen;
  105. int r = memcmp(a, b, n);
  106. if (r == 0) {
  107. if (alen < blen) r = -1;
  108. else if (alen > blen) r = +1;
  109. }
  110. return r;
  111. }
  112. static const char* CmpName(void* arg) {
  113. return "foo";
  114. }
  115. // Custom filter policy
  116. static unsigned char fake_filter_result = 1;
  117. static void FilterDestroy(void* arg) { }
  118. static const char* FilterName(void* arg) {
  119. return "TestFilter";
  120. }
  121. static char* FilterCreate(
  122. void* arg,
  123. const char* const* key_array, const size_t* key_length_array,
  124. int num_keys,
  125. size_t* filter_length) {
  126. *filter_length = 4;
  127. char* result = malloc(4);
  128. memcpy(result, "fake", 4);
  129. return result;
  130. }
  131. unsigned char FilterKeyMatch(
  132. void* arg,
  133. const char* key, size_t length,
  134. const char* filter, size_t filter_length) {
  135. CheckCondition(filter_length == 4);
  136. CheckCondition(memcmp(filter, "fake", 4) == 0);
  137. return fake_filter_result;
  138. }
  139. int main(int argc, char** argv) {
  140. leveldb_t* db;
  141. leveldb_comparator_t* cmp;
  142. leveldb_cache_t* cache;
  143. leveldb_env_t* env;
  144. leveldb_options_t* options;
  145. leveldb_readoptions_t* roptions;
  146. leveldb_writeoptions_t* woptions;
  147. char* err = NULL;
  148. int run = -1;
  149. CheckCondition(leveldb_major_version() >= 1);
  150. CheckCondition(leveldb_minor_version() >= 1);
  151. snprintf(dbname, sizeof(dbname),
  152. "%s/leveldb_c_test-%d",
  153. GetTempDir(),
  154. ((int) geteuid()));
  155. StartPhase("create_objects");
  156. cmp = leveldb_comparator_create(NULL, CmpDestroy, CmpCompare, CmpName);
  157. env = leveldb_create_default_env();
  158. cache = leveldb_cache_create_lru(100000);
  159. options = leveldb_options_create();
  160. leveldb_options_set_comparator(options, cmp);
  161. leveldb_options_set_error_if_exists(options, 1);
  162. leveldb_options_set_cache(options, cache);
  163. leveldb_options_set_env(options, env);
  164. leveldb_options_set_info_log(options, NULL);
  165. leveldb_options_set_write_buffer_size(options, 100000);
  166. leveldb_options_set_paranoid_checks(options, 1);
  167. leveldb_options_set_max_open_files(options, 10);
  168. leveldb_options_set_block_size(options, 1024);
  169. leveldb_options_set_block_restart_interval(options, 8);
  170. leveldb_options_set_max_file_size(options, 3 << 20);
  171. leveldb_options_set_compression(options, leveldb_no_compression);
  172. roptions = leveldb_readoptions_create();
  173. leveldb_readoptions_set_verify_checksums(roptions, 1);
  174. leveldb_readoptions_set_fill_cache(roptions, 0);
  175. woptions = leveldb_writeoptions_create();
  176. leveldb_writeoptions_set_sync(woptions, 1);
  177. StartPhase("destroy");
  178. leveldb_destroy_db(options, dbname, &err);
  179. Free(&err);
  180. StartPhase("open_error");
  181. db = leveldb_open(options, dbname, &err);
  182. CheckCondition(err != NULL);
  183. Free(&err);
  184. StartPhase("leveldb_free");
  185. db = leveldb_open(options, dbname, &err);
  186. CheckCondition(err != NULL);
  187. leveldb_free(err);
  188. err = NULL;
  189. StartPhase("open");
  190. leveldb_options_set_create_if_missing(options, 1);
  191. db = leveldb_open(options, dbname, &err);
  192. CheckNoError(err);
  193. CheckGet(db, roptions, "foo", NULL);
  194. StartPhase("put");
  195. leveldb_put(db, woptions, "foo", 3, "hello", 5, &err);
  196. CheckNoError(err);
  197. CheckGet(db, roptions, "foo", "hello");
  198. StartPhase("compactall");
  199. leveldb_compact_range(db, NULL, 0, NULL, 0);
  200. CheckGet(db, roptions, "foo", "hello");
  201. StartPhase("compactrange");
  202. leveldb_compact_range(db, "a", 1, "z", 1);
  203. CheckGet(db, roptions, "foo", "hello");
  204. StartPhase("writebatch");
  205. {
  206. leveldb_writebatch_t* wb = leveldb_writebatch_create();
  207. leveldb_writebatch_put(wb, "foo", 3, "a", 1);
  208. leveldb_writebatch_clear(wb);
  209. leveldb_writebatch_put(wb, "bar", 3, "b", 1);
  210. leveldb_writebatch_put(wb, "box", 3, "c", 1);
  211. leveldb_writebatch_delete(wb, "bar", 3);
  212. leveldb_write(db, woptions, wb, &err);
  213. CheckNoError(err);
  214. CheckGet(db, roptions, "foo", "hello");
  215. CheckGet(db, roptions, "bar", NULL);
  216. CheckGet(db, roptions, "box", "c");
  217. int pos = 0;
  218. leveldb_writebatch_iterate(wb, &pos, CheckPut, CheckDel);
  219. CheckCondition(pos == 3);
  220. leveldb_writebatch_destroy(wb);
  221. }
  222. StartPhase("iter");
  223. {
  224. leveldb_iterator_t* iter = leveldb_create_iterator(db, roptions);
  225. CheckCondition(!leveldb_iter_valid(iter));
  226. leveldb_iter_seek_to_first(iter);
  227. CheckCondition(leveldb_iter_valid(iter));
  228. CheckIter(iter, "box", "c");
  229. leveldb_iter_next(iter);
  230. CheckIter(iter, "foo", "hello");
  231. leveldb_iter_prev(iter);
  232. CheckIter(iter, "box", "c");
  233. leveldb_iter_prev(iter);
  234. CheckCondition(!leveldb_iter_valid(iter));
  235. leveldb_iter_seek_to_last(iter);
  236. CheckIter(iter, "foo", "hello");
  237. leveldb_iter_seek(iter, "b", 1);
  238. CheckIter(iter, "box", "c");
  239. leveldb_iter_get_error(iter, &err);
  240. CheckNoError(err);
  241. leveldb_iter_destroy(iter);
  242. }
  243. StartPhase("approximate_sizes");
  244. {
  245. int i;
  246. int n = 20000;
  247. char keybuf[100];
  248. char valbuf[100];
  249. uint64_t sizes[2];
  250. const char* start[2] = { "a", "k00000000000000010000" };
  251. size_t start_len[2] = { 1, 21 };
  252. const char* limit[2] = { "k00000000000000010000", "z" };
  253. size_t limit_len[2] = { 21, 1 };
  254. leveldb_writeoptions_set_sync(woptions, 0);
  255. for (i = 0; i < n; i++) {
  256. snprintf(keybuf, sizeof(keybuf), "k%020d", i);
  257. snprintf(valbuf, sizeof(valbuf), "v%020d", i);
  258. leveldb_put(db, woptions, keybuf, strlen(keybuf), valbuf, strlen(valbuf),
  259. &err);
  260. CheckNoError(err);
  261. }
  262. leveldb_approximate_sizes(db, 2, start, start_len, limit, limit_len, sizes);
  263. CheckCondition(sizes[0] > 0);
  264. CheckCondition(sizes[1] > 0);
  265. }
  266. StartPhase("property");
  267. {
  268. char* prop = leveldb_property_value(db, "nosuchprop");
  269. CheckCondition(prop == NULL);
  270. prop = leveldb_property_value(db, "leveldb.stats");
  271. CheckCondition(prop != NULL);
  272. Free(&prop);
  273. }
  274. StartPhase("snapshot");
  275. {
  276. const leveldb_snapshot_t* snap;
  277. snap = leveldb_create_snapshot(db);
  278. leveldb_delete(db, woptions, "foo", 3, &err);
  279. CheckNoError(err);
  280. leveldb_readoptions_set_snapshot(roptions, snap);
  281. CheckGet(db, roptions, "foo", "hello");
  282. leveldb_readoptions_set_snapshot(roptions, NULL);
  283. CheckGet(db, roptions, "foo", NULL);
  284. leveldb_release_snapshot(db, snap);
  285. }
  286. StartPhase("repair");
  287. {
  288. leveldb_close(db);
  289. leveldb_options_set_create_if_missing(options, 0);
  290. leveldb_options_set_error_if_exists(options, 0);
  291. leveldb_repair_db(options, dbname, &err);
  292. CheckNoError(err);
  293. db = leveldb_open(options, dbname, &err);
  294. CheckNoError(err);
  295. CheckGet(db, roptions, "foo", NULL);
  296. CheckGet(db, roptions, "bar", NULL);
  297. CheckGet(db, roptions, "box", "c");
  298. leveldb_options_set_create_if_missing(options, 1);
  299. leveldb_options_set_error_if_exists(options, 1);
  300. }
  301. StartPhase("filter");
  302. for (run = 0; run < 2; run++) {
  303. // First run uses custom filter, second run uses bloom filter
  304. CheckNoError(err);
  305. leveldb_filterpolicy_t* policy;
  306. if (run == 0) {
  307. policy = leveldb_filterpolicy_create(
  308. NULL, FilterDestroy, FilterCreate, FilterKeyMatch, FilterName);
  309. } else {
  310. policy = leveldb_filterpolicy_create_bloom(10);
  311. }
  312. // Create new database
  313. leveldb_close(db);
  314. leveldb_destroy_db(options, dbname, &err);
  315. leveldb_options_set_filter_policy(options, policy);
  316. db = leveldb_open(options, dbname, &err);
  317. CheckNoError(err);
  318. leveldb_put(db, woptions, "foo", 3, "foovalue", 8, &err);
  319. CheckNoError(err);
  320. leveldb_put(db, woptions, "bar", 3, "barvalue", 8, &err);
  321. CheckNoError(err);
  322. leveldb_compact_range(db, NULL, 0, NULL, 0);
  323. fake_filter_result = 1;
  324. CheckGet(db, roptions, "foo", "foovalue");
  325. CheckGet(db, roptions, "bar", "barvalue");
  326. if (phase == 0) {
  327. // Must not find value when custom filter returns false
  328. fake_filter_result = 0;
  329. CheckGet(db, roptions, "foo", NULL);
  330. CheckGet(db, roptions, "bar", NULL);
  331. fake_filter_result = 1;
  332. CheckGet(db, roptions, "foo", "foovalue");
  333. CheckGet(db, roptions, "bar", "barvalue");
  334. }
  335. leveldb_options_set_filter_policy(options, NULL);
  336. leveldb_filterpolicy_destroy(policy);
  337. }
  338. StartPhase("cleanup");
  339. leveldb_close(db);
  340. leveldb_options_destroy(options);
  341. leveldb_readoptions_destroy(roptions);
  342. leveldb_writeoptions_destroy(woptions);
  343. leveldb_cache_destroy(cache);
  344. leveldb_comparator_destroy(cmp);
  345. leveldb_env_destroy(env);
  346. fprintf(stderr, "PASS\n");
  347. return 0;
  348. }