10225501448 李度 10225101546 陈胤遒 10215501422 高宇菲
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

390 lignes
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_compression(options, leveldb_no_compression);
  171. roptions = leveldb_readoptions_create();
  172. leveldb_readoptions_set_verify_checksums(roptions, 1);
  173. leveldb_readoptions_set_fill_cache(roptions, 0);
  174. woptions = leveldb_writeoptions_create();
  175. leveldb_writeoptions_set_sync(woptions, 1);
  176. StartPhase("destroy");
  177. leveldb_destroy_db(options, dbname, &err);
  178. Free(&err);
  179. StartPhase("open_error");
  180. db = leveldb_open(options, dbname, &err);
  181. CheckCondition(err != NULL);
  182. Free(&err);
  183. StartPhase("leveldb_free");
  184. db = leveldb_open(options, dbname, &err);
  185. CheckCondition(err != NULL);
  186. leveldb_free(err);
  187. err = NULL;
  188. StartPhase("open");
  189. leveldb_options_set_create_if_missing(options, 1);
  190. db = leveldb_open(options, dbname, &err);
  191. CheckNoError(err);
  192. CheckGet(db, roptions, "foo", NULL);
  193. StartPhase("put");
  194. leveldb_put(db, woptions, "foo", 3, "hello", 5, &err);
  195. CheckNoError(err);
  196. CheckGet(db, roptions, "foo", "hello");
  197. StartPhase("compactall");
  198. leveldb_compact_range(db, NULL, 0, NULL, 0);
  199. CheckGet(db, roptions, "foo", "hello");
  200. StartPhase("compactrange");
  201. leveldb_compact_range(db, "a", 1, "z", 1);
  202. CheckGet(db, roptions, "foo", "hello");
  203. StartPhase("writebatch");
  204. {
  205. leveldb_writebatch_t* wb = leveldb_writebatch_create();
  206. leveldb_writebatch_put(wb, "foo", 3, "a", 1);
  207. leveldb_writebatch_clear(wb);
  208. leveldb_writebatch_put(wb, "bar", 3, "b", 1);
  209. leveldb_writebatch_put(wb, "box", 3, "c", 1);
  210. leveldb_writebatch_delete(wb, "bar", 3);
  211. leveldb_write(db, woptions, wb, &err);
  212. CheckNoError(err);
  213. CheckGet(db, roptions, "foo", "hello");
  214. CheckGet(db, roptions, "bar", NULL);
  215. CheckGet(db, roptions, "box", "c");
  216. int pos = 0;
  217. leveldb_writebatch_iterate(wb, &pos, CheckPut, CheckDel);
  218. CheckCondition(pos == 3);
  219. leveldb_writebatch_destroy(wb);
  220. }
  221. StartPhase("iter");
  222. {
  223. leveldb_iterator_t* iter = leveldb_create_iterator(db, roptions);
  224. CheckCondition(!leveldb_iter_valid(iter));
  225. leveldb_iter_seek_to_first(iter);
  226. CheckCondition(leveldb_iter_valid(iter));
  227. CheckIter(iter, "box", "c");
  228. leveldb_iter_next(iter);
  229. CheckIter(iter, "foo", "hello");
  230. leveldb_iter_prev(iter);
  231. CheckIter(iter, "box", "c");
  232. leveldb_iter_prev(iter);
  233. CheckCondition(!leveldb_iter_valid(iter));
  234. leveldb_iter_seek_to_last(iter);
  235. CheckIter(iter, "foo", "hello");
  236. leveldb_iter_seek(iter, "b", 1);
  237. CheckIter(iter, "box", "c");
  238. leveldb_iter_get_error(iter, &err);
  239. CheckNoError(err);
  240. leveldb_iter_destroy(iter);
  241. }
  242. StartPhase("approximate_sizes");
  243. {
  244. int i;
  245. int n = 20000;
  246. char keybuf[100];
  247. char valbuf[100];
  248. uint64_t sizes[2];
  249. const char* start[2] = { "a", "k00000000000000010000" };
  250. size_t start_len[2] = { 1, 21 };
  251. const char* limit[2] = { "k00000000000000010000", "z" };
  252. size_t limit_len[2] = { 21, 1 };
  253. leveldb_writeoptions_set_sync(woptions, 0);
  254. for (i = 0; i < n; i++) {
  255. snprintf(keybuf, sizeof(keybuf), "k%020d", i);
  256. snprintf(valbuf, sizeof(valbuf), "v%020d", i);
  257. leveldb_put(db, woptions, keybuf, strlen(keybuf), valbuf, strlen(valbuf),
  258. &err);
  259. CheckNoError(err);
  260. }
  261. leveldb_approximate_sizes(db, 2, start, start_len, limit, limit_len, sizes);
  262. CheckCondition(sizes[0] > 0);
  263. CheckCondition(sizes[1] > 0);
  264. }
  265. StartPhase("property");
  266. {
  267. char* prop = leveldb_property_value(db, "nosuchprop");
  268. CheckCondition(prop == NULL);
  269. prop = leveldb_property_value(db, "leveldb.stats");
  270. CheckCondition(prop != NULL);
  271. Free(&prop);
  272. }
  273. StartPhase("snapshot");
  274. {
  275. const leveldb_snapshot_t* snap;
  276. snap = leveldb_create_snapshot(db);
  277. leveldb_delete(db, woptions, "foo", 3, &err);
  278. CheckNoError(err);
  279. leveldb_readoptions_set_snapshot(roptions, snap);
  280. CheckGet(db, roptions, "foo", "hello");
  281. leveldb_readoptions_set_snapshot(roptions, NULL);
  282. CheckGet(db, roptions, "foo", NULL);
  283. leveldb_release_snapshot(db, snap);
  284. }
  285. StartPhase("repair");
  286. {
  287. leveldb_close(db);
  288. leveldb_options_set_create_if_missing(options, 0);
  289. leveldb_options_set_error_if_exists(options, 0);
  290. leveldb_repair_db(options, dbname, &err);
  291. CheckNoError(err);
  292. db = leveldb_open(options, dbname, &err);
  293. CheckNoError(err);
  294. CheckGet(db, roptions, "foo", NULL);
  295. CheckGet(db, roptions, "bar", NULL);
  296. CheckGet(db, roptions, "box", "c");
  297. leveldb_options_set_create_if_missing(options, 1);
  298. leveldb_options_set_error_if_exists(options, 1);
  299. }
  300. StartPhase("filter");
  301. for (run = 0; run < 2; run++) {
  302. // First run uses custom filter, second run uses bloom filter
  303. CheckNoError(err);
  304. leveldb_filterpolicy_t* policy;
  305. if (run == 0) {
  306. policy = leveldb_filterpolicy_create(
  307. NULL, FilterDestroy, FilterCreate, FilterKeyMatch, FilterName);
  308. } else {
  309. policy = leveldb_filterpolicy_create_bloom(10);
  310. }
  311. // Create new database
  312. leveldb_close(db);
  313. leveldb_destroy_db(options, dbname, &err);
  314. leveldb_options_set_filter_policy(options, policy);
  315. db = leveldb_open(options, dbname, &err);
  316. CheckNoError(err);
  317. leveldb_put(db, woptions, "foo", 3, "foovalue", 8, &err);
  318. CheckNoError(err);
  319. leveldb_put(db, woptions, "bar", 3, "barvalue", 8, &err);
  320. CheckNoError(err);
  321. leveldb_compact_range(db, NULL, 0, NULL, 0);
  322. fake_filter_result = 1;
  323. CheckGet(db, roptions, "foo", "foovalue");
  324. CheckGet(db, roptions, "bar", "barvalue");
  325. if (phase == 0) {
  326. // Must not find value when custom filter returns false
  327. fake_filter_result = 0;
  328. CheckGet(db, roptions, "foo", NULL);
  329. CheckGet(db, roptions, "bar", NULL);
  330. fake_filter_result = 1;
  331. CheckGet(db, roptions, "foo", "foovalue");
  332. CheckGet(db, roptions, "bar", "barvalue");
  333. }
  334. leveldb_options_set_filter_policy(options, NULL);
  335. leveldb_filterpolicy_destroy(policy);
  336. }
  337. StartPhase("cleanup");
  338. leveldb_close(db);
  339. leveldb_options_destroy(options);
  340. leveldb_readoptions_destroy(roptions);
  341. leveldb_writeoptions_destroy(woptions);
  342. leveldb_cache_destroy(cache);
  343. leveldb_comparator_destroy(cmp);
  344. leveldb_env_destroy(env);
  345. fprintf(stderr, "PASS\n");
  346. return 0;
  347. }