小组成员:10215300402-朱维清 & 10222140408 谷杰
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.

295 lines
8.6 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. #define CheckNoError(err) \
  18. if ((err) != NULL) { \
  19. fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, (err)); \
  20. abort(); \
  21. }
  22. #define CheckCondition(cond) \
  23. if (!(cond)) { \
  24. fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, #cond); \
  25. abort(); \
  26. }
  27. static void CheckEqual(const char* expected, const char* v, size_t n) {
  28. if (expected == NULL && v == NULL) {
  29. // ok
  30. } else if (expected != NULL && v != NULL && n == strlen(expected) &&
  31. memcmp(expected, v, n) == 0) {
  32. // ok
  33. return;
  34. } else {
  35. fprintf(stderr, "%s: expected '%s', got '%s'\n",
  36. phase,
  37. (expected ? expected : "(null)"),
  38. (v ? v : "(null"));
  39. abort();
  40. }
  41. }
  42. static void Free(char** ptr) {
  43. if (*ptr) {
  44. free(*ptr);
  45. *ptr = NULL;
  46. }
  47. }
  48. static void CheckGet(
  49. leveldb_t* db,
  50. const leveldb_readoptions_t* options,
  51. const char* key,
  52. const char* expected) {
  53. char* err = NULL;
  54. size_t val_len;
  55. char* val;
  56. val = leveldb_get(db, options, key, strlen(key), &val_len, &err);
  57. CheckNoError(err);
  58. CheckEqual(expected, val, val_len);
  59. Free(&val);
  60. }
  61. static void CheckIter(leveldb_iterator_t* iter,
  62. const char* key, const char* val) {
  63. size_t len;
  64. const char* str;
  65. str = leveldb_iter_key(iter, &len);
  66. CheckEqual(key, str, len);
  67. str = leveldb_iter_value(iter, &len);
  68. CheckEqual(val, str, len);
  69. }
  70. // Callback from leveldb_writebatch_iterate()
  71. static void CheckPut(void* ptr,
  72. const char* k, size_t klen,
  73. const char* v, size_t vlen) {
  74. int* state = (int*) ptr;
  75. CheckCondition(*state < 2);
  76. switch (*state) {
  77. case 0:
  78. CheckEqual("bar", k, klen);
  79. CheckEqual("b", v, vlen);
  80. break;
  81. case 1:
  82. CheckEqual("box", k, klen);
  83. CheckEqual("c", v, vlen);
  84. break;
  85. }
  86. (*state)++;
  87. }
  88. // Callback from leveldb_writebatch_iterate()
  89. static void CheckDel(void* ptr, const char* k, size_t klen) {
  90. int* state = (int*) ptr;
  91. CheckCondition(*state == 2);
  92. CheckEqual("bar", k, klen);
  93. (*state)++;
  94. }
  95. static void CmpDestroy(void* arg) { }
  96. static int CmpCompare(void* arg, const char* a, size_t alen,
  97. const char* b, size_t blen) {
  98. int n = (alen < blen) ? alen : blen;
  99. int r = memcmp(a, b, n);
  100. if (r == 0) {
  101. if (alen < blen) r = -1;
  102. else if (alen > blen) r = +1;
  103. }
  104. return r;
  105. }
  106. static const char* CmpName(void* arg) {
  107. return "foo";
  108. }
  109. int main(int argc, char** argv) {
  110. leveldb_t* db;
  111. leveldb_comparator_t* cmp;
  112. leveldb_cache_t* cache;
  113. leveldb_env_t* env;
  114. leveldb_options_t* options;
  115. leveldb_readoptions_t* roptions;
  116. leveldb_writeoptions_t* woptions;
  117. char* err = NULL;
  118. snprintf(dbname, sizeof(dbname), "/tmp/leveldb_c_test-%d",
  119. ((int) geteuid()));
  120. StartPhase("create_objects");
  121. cmp = leveldb_comparator_create(NULL, CmpDestroy, CmpCompare, CmpName);
  122. env = leveldb_create_default_env();
  123. cache = leveldb_cache_create_lru(100000);
  124. options = leveldb_options_create();
  125. leveldb_options_set_comparator(options, cmp);
  126. leveldb_options_set_error_if_exists(options, 1);
  127. leveldb_options_set_cache(options, cache);
  128. leveldb_options_set_env(options, env);
  129. leveldb_options_set_info_log(options, NULL);
  130. leveldb_options_set_write_buffer_size(options, 100000);
  131. leveldb_options_set_paranoid_checks(options, 1);
  132. leveldb_options_set_max_open_files(options, 10);
  133. leveldb_options_set_block_size(options, 1024);
  134. leveldb_options_set_block_restart_interval(options, 8);
  135. leveldb_options_set_compression(options, leveldb_no_compression);
  136. roptions = leveldb_readoptions_create();
  137. leveldb_readoptions_set_verify_checksums(roptions, 1);
  138. leveldb_readoptions_set_fill_cache(roptions, 0);
  139. woptions = leveldb_writeoptions_create();
  140. leveldb_writeoptions_set_sync(woptions, 1);
  141. StartPhase("destroy");
  142. leveldb_destroy_db(options, dbname, &err);
  143. Free(&err);
  144. StartPhase("open_error");
  145. db = leveldb_open(options, dbname, &err);
  146. CheckCondition(err != NULL);
  147. Free(&err);
  148. StartPhase("open");
  149. leveldb_options_set_create_if_missing(options, 1);
  150. db = leveldb_open(options, dbname, &err);
  151. CheckNoError(err);
  152. CheckGet(db, roptions, "foo", NULL);
  153. StartPhase("put");
  154. leveldb_put(db, woptions, "foo", 3, "hello", 5, &err);
  155. CheckNoError(err);
  156. CheckGet(db, roptions, "foo", "hello");
  157. StartPhase("writebatch");
  158. {
  159. leveldb_writebatch_t* wb = leveldb_writebatch_create();
  160. leveldb_writebatch_put(wb, "foo", 3, "a", 1);
  161. leveldb_writebatch_clear(wb);
  162. leveldb_writebatch_put(wb, "bar", 3, "b", 1);
  163. leveldb_writebatch_put(wb, "box", 3, "c", 1);
  164. leveldb_writebatch_delete(wb, "bar", 3);
  165. leveldb_write(db, woptions, wb, &err);
  166. CheckNoError(err);
  167. CheckGet(db, roptions, "foo", "hello");
  168. CheckGet(db, roptions, "bar", NULL);
  169. CheckGet(db, roptions, "box", "c");
  170. int pos = 0;
  171. leveldb_writebatch_iterate(wb, &pos, CheckPut, CheckDel);
  172. CheckCondition(pos == 3);
  173. leveldb_writebatch_destroy(wb);
  174. }
  175. StartPhase("iter");
  176. {
  177. leveldb_iterator_t* iter = leveldb_create_iterator(db, roptions);
  178. CheckCondition(!leveldb_iter_valid(iter));
  179. leveldb_iter_seek_to_first(iter);
  180. CheckCondition(leveldb_iter_valid(iter));
  181. CheckIter(iter, "box", "c");
  182. leveldb_iter_next(iter);
  183. CheckIter(iter, "foo", "hello");
  184. leveldb_iter_prev(iter);
  185. CheckIter(iter, "box", "c");
  186. leveldb_iter_prev(iter);
  187. CheckCondition(!leveldb_iter_valid(iter));
  188. leveldb_iter_seek_to_last(iter);
  189. CheckIter(iter, "foo", "hello");
  190. leveldb_iter_seek(iter, "b", 1);
  191. CheckIter(iter, "box", "c");
  192. leveldb_iter_get_error(iter, &err);
  193. CheckNoError(err);
  194. leveldb_iter_destroy(iter);
  195. }
  196. StartPhase("approximate_sizes");
  197. {
  198. int i;
  199. int n = 20000;
  200. char keybuf[100];
  201. char valbuf[100];
  202. uint64_t sizes[2];
  203. const char* start[2] = { "a", "k00000000000000010000" };
  204. size_t start_len[2] = { 1, 21 };
  205. const char* limit[2] = { "k00000000000000010000", "z" };
  206. size_t limit_len[2] = { 21, 1 };
  207. leveldb_writeoptions_set_sync(woptions, 0);
  208. for (i = 0; i < n; i++) {
  209. snprintf(keybuf, sizeof(keybuf), "k%020d", i);
  210. snprintf(valbuf, sizeof(valbuf), "v%020d", i);
  211. leveldb_put(db, woptions, keybuf, strlen(keybuf), valbuf, strlen(valbuf),
  212. &err);
  213. CheckNoError(err);
  214. }
  215. leveldb_approximate_sizes(db, 2, start, start_len, limit, limit_len, sizes);
  216. CheckCondition(sizes[0] > 0);
  217. CheckCondition(sizes[1] > 0);
  218. }
  219. StartPhase("property");
  220. {
  221. char* prop = leveldb_property_value(db, "nosuchprop");
  222. CheckCondition(prop == NULL);
  223. prop = leveldb_property_value(db, "leveldb.stats");
  224. CheckCondition(prop != NULL);
  225. Free(&prop);
  226. }
  227. StartPhase("snapshot");
  228. {
  229. const leveldb_snapshot_t* snap;
  230. snap = leveldb_create_snapshot(db);
  231. leveldb_delete(db, woptions, "foo", 3, &err);
  232. CheckNoError(err);
  233. leveldb_readoptions_set_snapshot(roptions, snap);
  234. CheckGet(db, roptions, "foo", "hello");
  235. leveldb_readoptions_set_snapshot(roptions, NULL);
  236. CheckGet(db, roptions, "foo", NULL);
  237. leveldb_release_snapshot(db, snap);
  238. }
  239. StartPhase("repair");
  240. {
  241. leveldb_close(db);
  242. leveldb_options_set_create_if_missing(options, 0);
  243. leveldb_options_set_error_if_exists(options, 0);
  244. leveldb_repair_db(options, dbname, &err);
  245. CheckNoError(err);
  246. db = leveldb_open(options, dbname, &err);
  247. CheckNoError(err);
  248. CheckGet(db, roptions, "foo", NULL);
  249. CheckGet(db, roptions, "bar", NULL);
  250. CheckGet(db, roptions, "box", "c");
  251. }
  252. StartPhase("cleanup");
  253. leveldb_close(db);
  254. leveldb_options_destroy(options);
  255. leveldb_readoptions_destroy(roptions);
  256. leveldb_writeoptions_destroy(woptions);
  257. leveldb_cache_destroy(cache);
  258. leveldb_comparator_destroy(cmp);
  259. leveldb_env_destroy(env);
  260. fprintf(stderr, "PASS\n");
  261. return 0;
  262. }