c_test.c 63 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866
  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. // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
  5. #include <stdio.h>
  6. #ifndef ROCKSDB_LITE // Lite does not support C API
  7. #include "rocksdb/c.h"
  8. #include <stddef.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <sys/types.h>
  12. #ifndef OS_WIN
  13. #include <unistd.h>
  14. #endif
  15. #include <inttypes.h>
  16. // Can not use port/port.h macros as this is a c file
  17. #ifdef OS_WIN
  18. #include <windows.h>
  19. // Ok for uniqueness
  20. int geteuid() {
  21. int result = 0;
  22. result = ((int)GetCurrentProcessId() << 16);
  23. result |= (int)GetCurrentThreadId();
  24. return result;
  25. }
  26. // VS < 2015
  27. #if defined(_MSC_VER) && (_MSC_VER < 1900)
  28. #define snprintf _snprintf
  29. #endif
  30. #endif
  31. const char* phase = "";
  32. static char dbname[200];
  33. static char sstfilename[200];
  34. static char dbbackupname[200];
  35. static char dbcheckpointname[200];
  36. static char dbpathname[200];
  37. static char secondary_path[200];
  38. static void StartPhase(const char* name) {
  39. fprintf(stderr, "=== Test %s\n", name);
  40. phase = name;
  41. }
  42. #ifdef _MSC_VER
  43. #pragma warning(push)
  44. #pragma warning (disable: 4996) // getenv security warning
  45. #endif
  46. static const char* GetTempDir(void) {
  47. const char* ret = getenv("TEST_TMPDIR");
  48. if (ret == NULL || ret[0] == '\0')
  49. ret = "/tmp";
  50. return ret;
  51. }
  52. #ifdef _MSC_VER
  53. #pragma warning(pop)
  54. #endif
  55. #define CheckNoError(err) \
  56. if ((err) != NULL) { \
  57. fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, (err)); \
  58. abort(); \
  59. }
  60. #define CheckCondition(cond) \
  61. if (!(cond)) { \
  62. fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, #cond); \
  63. abort(); \
  64. }
  65. static void CheckEqual(const char* expected, const char* v, size_t n) {
  66. if (expected == NULL && v == NULL) {
  67. // ok
  68. } else if (expected != NULL && v != NULL && n == strlen(expected) &&
  69. memcmp(expected, v, n) == 0) {
  70. // ok
  71. return;
  72. } else {
  73. fprintf(stderr, "%s: expected '%s', got '%s'\n",
  74. phase,
  75. (expected ? expected : "(null)"),
  76. (v ? v : "(null"));
  77. abort();
  78. }
  79. }
  80. static void Free(char** ptr) {
  81. if (*ptr) {
  82. free(*ptr);
  83. *ptr = NULL;
  84. }
  85. }
  86. static void CheckValue(
  87. char* err,
  88. const char* expected,
  89. char** actual,
  90. size_t actual_length) {
  91. CheckNoError(err);
  92. CheckEqual(expected, *actual, actual_length);
  93. Free(actual);
  94. }
  95. static void CheckGet(
  96. rocksdb_t* db,
  97. const rocksdb_readoptions_t* options,
  98. const char* key,
  99. const char* expected) {
  100. char* err = NULL;
  101. size_t val_len;
  102. char* val;
  103. val = rocksdb_get(db, options, key, strlen(key), &val_len, &err);
  104. CheckNoError(err);
  105. CheckEqual(expected, val, val_len);
  106. Free(&val);
  107. }
  108. static void CheckGetCF(
  109. rocksdb_t* db,
  110. const rocksdb_readoptions_t* options,
  111. rocksdb_column_family_handle_t* handle,
  112. const char* key,
  113. const char* expected) {
  114. char* err = NULL;
  115. size_t val_len;
  116. char* val;
  117. val = rocksdb_get_cf(db, options, handle, key, strlen(key), &val_len, &err);
  118. CheckNoError(err);
  119. CheckEqual(expected, val, val_len);
  120. Free(&val);
  121. }
  122. static void CheckPinGet(rocksdb_t* db, const rocksdb_readoptions_t* options,
  123. const char* key, const char* expected) {
  124. char* err = NULL;
  125. size_t val_len;
  126. const char* val;
  127. rocksdb_pinnableslice_t* p;
  128. p = rocksdb_get_pinned(db, options, key, strlen(key), &err);
  129. CheckNoError(err);
  130. val = rocksdb_pinnableslice_value(p, &val_len);
  131. CheckEqual(expected, val, val_len);
  132. rocksdb_pinnableslice_destroy(p);
  133. }
  134. static void CheckPinGetCF(rocksdb_t* db, const rocksdb_readoptions_t* options,
  135. rocksdb_column_family_handle_t* handle,
  136. const char* key, const char* expected) {
  137. char* err = NULL;
  138. size_t val_len;
  139. const char* val;
  140. rocksdb_pinnableslice_t* p;
  141. p = rocksdb_get_pinned_cf(db, options, handle, key, strlen(key), &err);
  142. CheckNoError(err);
  143. val = rocksdb_pinnableslice_value(p, &val_len);
  144. CheckEqual(expected, val, val_len);
  145. rocksdb_pinnableslice_destroy(p);
  146. }
  147. static void CheckIter(rocksdb_iterator_t* iter,
  148. const char* key, const char* val) {
  149. size_t len;
  150. const char* str;
  151. str = rocksdb_iter_key(iter, &len);
  152. CheckEqual(key, str, len);
  153. str = rocksdb_iter_value(iter, &len);
  154. CheckEqual(val, str, len);
  155. }
  156. // Callback from rocksdb_writebatch_iterate()
  157. static void CheckPut(void* ptr,
  158. const char* k, size_t klen,
  159. const char* v, size_t vlen) {
  160. int* state = (int*) ptr;
  161. CheckCondition(*state < 2);
  162. switch (*state) {
  163. case 0:
  164. CheckEqual("bar", k, klen);
  165. CheckEqual("b", v, vlen);
  166. break;
  167. case 1:
  168. CheckEqual("box", k, klen);
  169. CheckEqual("c", v, vlen);
  170. break;
  171. }
  172. (*state)++;
  173. }
  174. // Callback from rocksdb_writebatch_iterate()
  175. static void CheckDel(void* ptr, const char* k, size_t klen) {
  176. int* state = (int*) ptr;
  177. CheckCondition(*state == 2);
  178. CheckEqual("bar", k, klen);
  179. (*state)++;
  180. }
  181. static void CmpDestroy(void* arg) { (void)arg; }
  182. static int CmpCompare(void* arg, const char* a, size_t alen,
  183. const char* b, size_t blen) {
  184. (void)arg;
  185. size_t n = (alen < blen) ? alen : blen;
  186. int r = memcmp(a, b, n);
  187. if (r == 0) {
  188. if (alen < blen) r = -1;
  189. else if (alen > blen) r = +1;
  190. }
  191. return r;
  192. }
  193. static const char* CmpName(void* arg) {
  194. (void)arg;
  195. return "foo";
  196. }
  197. // Custom filter policy
  198. static unsigned char fake_filter_result = 1;
  199. static void FilterDestroy(void* arg) { (void)arg; }
  200. static const char* FilterName(void* arg) {
  201. (void)arg;
  202. return "TestFilter";
  203. }
  204. static char* FilterCreate(
  205. void* arg,
  206. const char* const* key_array, const size_t* key_length_array,
  207. int num_keys,
  208. size_t* filter_length) {
  209. (void)arg;
  210. (void)key_array;
  211. (void)key_length_array;
  212. (void)num_keys;
  213. *filter_length = 4;
  214. char* result = malloc(4);
  215. memcpy(result, "fake", 4);
  216. return result;
  217. }
  218. static unsigned char FilterKeyMatch(
  219. void* arg,
  220. const char* key, size_t length,
  221. const char* filter, size_t filter_length) {
  222. (void)arg;
  223. (void)key;
  224. (void)length;
  225. CheckCondition(filter_length == 4);
  226. CheckCondition(memcmp(filter, "fake", 4) == 0);
  227. return fake_filter_result;
  228. }
  229. // Custom compaction filter
  230. static void CFilterDestroy(void* arg) { (void)arg; }
  231. static const char* CFilterName(void* arg) {
  232. (void)arg;
  233. return "foo";
  234. }
  235. static unsigned char CFilterFilter(void* arg, int level, const char* key,
  236. size_t key_length,
  237. const char* existing_value,
  238. size_t value_length, char** new_value,
  239. size_t* new_value_length,
  240. unsigned char* value_changed) {
  241. (void)arg;
  242. (void)level;
  243. (void)existing_value;
  244. (void)value_length;
  245. if (key_length == 3) {
  246. if (memcmp(key, "bar", key_length) == 0) {
  247. return 1;
  248. } else if (memcmp(key, "baz", key_length) == 0) {
  249. *value_changed = 1;
  250. *new_value = "newbazvalue";
  251. *new_value_length = 11;
  252. return 0;
  253. }
  254. }
  255. return 0;
  256. }
  257. static void CFilterFactoryDestroy(void* arg) { (void)arg; }
  258. static const char* CFilterFactoryName(void* arg) {
  259. (void)arg;
  260. return "foo";
  261. }
  262. static rocksdb_compactionfilter_t* CFilterCreate(
  263. void* arg, rocksdb_compactionfiltercontext_t* context) {
  264. (void)arg;
  265. (void)context;
  266. return rocksdb_compactionfilter_create(NULL, CFilterDestroy, CFilterFilter,
  267. CFilterName);
  268. }
  269. static rocksdb_t* CheckCompaction(rocksdb_t* db, rocksdb_options_t* options,
  270. rocksdb_readoptions_t* roptions,
  271. rocksdb_writeoptions_t* woptions) {
  272. char* err = NULL;
  273. db = rocksdb_open(options, dbname, &err);
  274. CheckNoError(err);
  275. rocksdb_put(db, woptions, "foo", 3, "foovalue", 8, &err);
  276. CheckNoError(err);
  277. CheckGet(db, roptions, "foo", "foovalue");
  278. rocksdb_put(db, woptions, "bar", 3, "barvalue", 8, &err);
  279. CheckNoError(err);
  280. CheckGet(db, roptions, "bar", "barvalue");
  281. rocksdb_put(db, woptions, "baz", 3, "bazvalue", 8, &err);
  282. CheckNoError(err);
  283. CheckGet(db, roptions, "baz", "bazvalue");
  284. // Force compaction
  285. rocksdb_compact_range(db, NULL, 0, NULL, 0);
  286. // should have filtered bar, but not foo
  287. CheckGet(db, roptions, "foo", "foovalue");
  288. CheckGet(db, roptions, "bar", NULL);
  289. CheckGet(db, roptions, "baz", "newbazvalue");
  290. return db;
  291. }
  292. // Custom merge operator
  293. static void MergeOperatorDestroy(void* arg) { (void)arg; }
  294. static const char* MergeOperatorName(void* arg) {
  295. (void)arg;
  296. return "TestMergeOperator";
  297. }
  298. static char* MergeOperatorFullMerge(
  299. void* arg,
  300. const char* key, size_t key_length,
  301. const char* existing_value, size_t existing_value_length,
  302. const char* const* operands_list, const size_t* operands_list_length,
  303. int num_operands,
  304. unsigned char* success, size_t* new_value_length) {
  305. (void)arg;
  306. (void)key;
  307. (void)key_length;
  308. (void)existing_value;
  309. (void)existing_value_length;
  310. (void)operands_list;
  311. (void)operands_list_length;
  312. (void)num_operands;
  313. *new_value_length = 4;
  314. *success = 1;
  315. char* result = malloc(4);
  316. memcpy(result, "fake", 4);
  317. return result;
  318. }
  319. static char* MergeOperatorPartialMerge(
  320. void* arg,
  321. const char* key, size_t key_length,
  322. const char* const* operands_list, const size_t* operands_list_length,
  323. int num_operands,
  324. unsigned char* success, size_t* new_value_length) {
  325. (void)arg;
  326. (void)key;
  327. (void)key_length;
  328. (void)operands_list;
  329. (void)operands_list_length;
  330. (void)num_operands;
  331. *new_value_length = 4;
  332. *success = 1;
  333. char* result = malloc(4);
  334. memcpy(result, "fake", 4);
  335. return result;
  336. }
  337. static void CheckTxnGet(
  338. rocksdb_transaction_t* txn,
  339. const rocksdb_readoptions_t* options,
  340. const char* key,
  341. const char* expected) {
  342. char* err = NULL;
  343. size_t val_len;
  344. char* val;
  345. val = rocksdb_transaction_get(txn, options, key, strlen(key), &val_len, &err);
  346. CheckNoError(err);
  347. CheckEqual(expected, val, val_len);
  348. Free(&val);
  349. }
  350. static void CheckTxnGetCF(rocksdb_transaction_t* txn,
  351. const rocksdb_readoptions_t* options,
  352. rocksdb_column_family_handle_t* column_family,
  353. const char* key, const char* expected) {
  354. char* err = NULL;
  355. size_t val_len;
  356. char* val;
  357. val = rocksdb_transaction_get_cf(txn, options, column_family, key,
  358. strlen(key), &val_len, &err);
  359. CheckNoError(err);
  360. CheckEqual(expected, val, val_len);
  361. Free(&val);
  362. }
  363. static void CheckTxnDBGet(
  364. rocksdb_transactiondb_t* txn_db,
  365. const rocksdb_readoptions_t* options,
  366. const char* key,
  367. const char* expected) {
  368. char* err = NULL;
  369. size_t val_len;
  370. char* val;
  371. val = rocksdb_transactiondb_get(txn_db, options, key, strlen(key), &val_len, &err);
  372. CheckNoError(err);
  373. CheckEqual(expected, val, val_len);
  374. Free(&val);
  375. }
  376. static void CheckTxnDBGetCF(rocksdb_transactiondb_t* txn_db,
  377. const rocksdb_readoptions_t* options,
  378. rocksdb_column_family_handle_t* column_family,
  379. const char* key, const char* expected) {
  380. char* err = NULL;
  381. size_t val_len;
  382. char* val;
  383. val = rocksdb_transactiondb_get_cf(txn_db, options, column_family, key,
  384. strlen(key), &val_len, &err);
  385. CheckNoError(err);
  386. CheckEqual(expected, val, val_len);
  387. Free(&val);
  388. }
  389. int main(int argc, char** argv) {
  390. (void)argc;
  391. (void)argv;
  392. rocksdb_t* db;
  393. rocksdb_comparator_t* cmp;
  394. rocksdb_cache_t* cache;
  395. rocksdb_dbpath_t *dbpath;
  396. rocksdb_env_t* env;
  397. rocksdb_options_t* options;
  398. rocksdb_compactoptions_t* coptions;
  399. rocksdb_block_based_table_options_t* table_options;
  400. rocksdb_readoptions_t* roptions;
  401. rocksdb_writeoptions_t* woptions;
  402. rocksdb_ratelimiter_t* rate_limiter;
  403. rocksdb_transactiondb_t* txn_db;
  404. rocksdb_transactiondb_options_t* txn_db_options;
  405. rocksdb_transaction_t* txn;
  406. rocksdb_transaction_options_t* txn_options;
  407. rocksdb_optimistictransactiondb_t* otxn_db;
  408. rocksdb_optimistictransaction_options_t* otxn_options;
  409. char* err = NULL;
  410. int run = -1;
  411. snprintf(dbname, sizeof(dbname),
  412. "%s/rocksdb_c_test-%d",
  413. GetTempDir(),
  414. ((int) geteuid()));
  415. snprintf(dbbackupname, sizeof(dbbackupname),
  416. "%s/rocksdb_c_test-%d-backup",
  417. GetTempDir(),
  418. ((int) geteuid()));
  419. snprintf(dbcheckpointname, sizeof(dbcheckpointname),
  420. "%s/rocksdb_c_test-%d-checkpoint",
  421. GetTempDir(),
  422. ((int) geteuid()));
  423. snprintf(sstfilename, sizeof(sstfilename),
  424. "%s/rocksdb_c_test-%d-sst",
  425. GetTempDir(),
  426. ((int)geteuid()));
  427. snprintf(dbpathname, sizeof(dbpathname),
  428. "%s/rocksdb_c_test-%d-dbpath",
  429. GetTempDir(),
  430. ((int) geteuid()));
  431. StartPhase("create_objects");
  432. cmp = rocksdb_comparator_create(NULL, CmpDestroy, CmpCompare, CmpName);
  433. dbpath = rocksdb_dbpath_create(dbpathname, 1024 * 1024);
  434. env = rocksdb_create_default_env();
  435. cache = rocksdb_cache_create_lru(100000);
  436. options = rocksdb_options_create();
  437. rocksdb_options_set_comparator(options, cmp);
  438. rocksdb_options_set_error_if_exists(options, 1);
  439. rocksdb_options_set_env(options, env);
  440. rocksdb_options_set_info_log(options, NULL);
  441. rocksdb_options_set_write_buffer_size(options, 100000);
  442. rocksdb_options_set_paranoid_checks(options, 1);
  443. rocksdb_options_set_max_open_files(options, 10);
  444. rocksdb_options_set_base_background_compactions(options, 1);
  445. table_options = rocksdb_block_based_options_create();
  446. rocksdb_block_based_options_set_block_cache(table_options, cache);
  447. rocksdb_block_based_options_set_data_block_index_type(table_options, 1);
  448. rocksdb_block_based_options_set_data_block_hash_ratio(table_options, 0.75);
  449. rocksdb_options_set_block_based_table_factory(options, table_options);
  450. rocksdb_options_set_compression(options, rocksdb_no_compression);
  451. rocksdb_options_set_compression_options(options, -14, -1, 0, 0);
  452. int compression_levels[] = {rocksdb_no_compression, rocksdb_no_compression,
  453. rocksdb_no_compression, rocksdb_no_compression};
  454. rocksdb_options_set_compression_per_level(options, compression_levels, 4);
  455. rate_limiter = rocksdb_ratelimiter_create(1000 * 1024 * 1024, 100 * 1000, 10);
  456. rocksdb_options_set_ratelimiter(options, rate_limiter);
  457. rocksdb_ratelimiter_destroy(rate_limiter);
  458. roptions = rocksdb_readoptions_create();
  459. rocksdb_readoptions_set_verify_checksums(roptions, 1);
  460. rocksdb_readoptions_set_fill_cache(roptions, 1);
  461. woptions = rocksdb_writeoptions_create();
  462. rocksdb_writeoptions_set_sync(woptions, 1);
  463. coptions = rocksdb_compactoptions_create();
  464. rocksdb_compactoptions_set_exclusive_manual_compaction(coptions, 1);
  465. StartPhase("destroy");
  466. rocksdb_destroy_db(options, dbname, &err);
  467. Free(&err);
  468. StartPhase("open_error");
  469. rocksdb_open(options, dbname, &err);
  470. CheckCondition(err != NULL);
  471. Free(&err);
  472. StartPhase("open");
  473. rocksdb_options_set_create_if_missing(options, 1);
  474. db = rocksdb_open(options, dbname, &err);
  475. CheckNoError(err);
  476. CheckGet(db, roptions, "foo", NULL);
  477. StartPhase("put");
  478. rocksdb_put(db, woptions, "foo", 3, "hello", 5, &err);
  479. CheckNoError(err);
  480. CheckGet(db, roptions, "foo", "hello");
  481. StartPhase("backup_and_restore");
  482. {
  483. rocksdb_destroy_db(options, dbbackupname, &err);
  484. CheckNoError(err);
  485. rocksdb_backup_engine_t *be = rocksdb_backup_engine_open(options, dbbackupname, &err);
  486. CheckNoError(err);
  487. rocksdb_backup_engine_create_new_backup(be, db, &err);
  488. CheckNoError(err);
  489. // need a change to trigger a new backup
  490. rocksdb_delete(db, woptions, "does-not-exist", 14, &err);
  491. CheckNoError(err);
  492. rocksdb_backup_engine_create_new_backup(be, db, &err);
  493. CheckNoError(err);
  494. const rocksdb_backup_engine_info_t* bei = rocksdb_backup_engine_get_backup_info(be);
  495. CheckCondition(rocksdb_backup_engine_info_count(bei) > 1);
  496. rocksdb_backup_engine_info_destroy(bei);
  497. rocksdb_backup_engine_purge_old_backups(be, 1, &err);
  498. CheckNoError(err);
  499. bei = rocksdb_backup_engine_get_backup_info(be);
  500. CheckCondition(rocksdb_backup_engine_info_count(bei) == 1);
  501. rocksdb_backup_engine_info_destroy(bei);
  502. rocksdb_delete(db, woptions, "foo", 3, &err);
  503. CheckNoError(err);
  504. rocksdb_close(db);
  505. rocksdb_destroy_db(options, dbname, &err);
  506. CheckNoError(err);
  507. rocksdb_restore_options_t *restore_options = rocksdb_restore_options_create();
  508. rocksdb_restore_options_set_keep_log_files(restore_options, 0);
  509. rocksdb_backup_engine_restore_db_from_latest_backup(be, dbname, dbname, restore_options, &err);
  510. CheckNoError(err);
  511. rocksdb_restore_options_destroy(restore_options);
  512. rocksdb_options_set_error_if_exists(options, 0);
  513. db = rocksdb_open(options, dbname, &err);
  514. CheckNoError(err);
  515. rocksdb_options_set_error_if_exists(options, 1);
  516. CheckGet(db, roptions, "foo", "hello");
  517. rocksdb_backup_engine_close(be);
  518. }
  519. StartPhase("checkpoint");
  520. {
  521. rocksdb_destroy_db(options, dbcheckpointname, &err);
  522. CheckNoError(err);
  523. rocksdb_checkpoint_t* checkpoint = rocksdb_checkpoint_object_create(db, &err);
  524. CheckNoError(err);
  525. rocksdb_checkpoint_create(checkpoint, dbcheckpointname, 0, &err);
  526. CheckNoError(err);
  527. // start a new database from the checkpoint
  528. rocksdb_close(db);
  529. rocksdb_options_set_error_if_exists(options, 0);
  530. db = rocksdb_open(options, dbcheckpointname, &err);
  531. CheckNoError(err);
  532. CheckGet(db, roptions, "foo", "hello");
  533. rocksdb_checkpoint_object_destroy(checkpoint);
  534. rocksdb_close(db);
  535. rocksdb_destroy_db(options, dbcheckpointname, &err);
  536. CheckNoError(err);
  537. db = rocksdb_open(options, dbname, &err);
  538. CheckNoError(err);
  539. rocksdb_options_set_error_if_exists(options, 1);
  540. }
  541. StartPhase("compactall");
  542. rocksdb_compact_range(db, NULL, 0, NULL, 0);
  543. CheckGet(db, roptions, "foo", "hello");
  544. StartPhase("compactrange");
  545. rocksdb_compact_range(db, "a", 1, "z", 1);
  546. CheckGet(db, roptions, "foo", "hello");
  547. StartPhase("compactallopt");
  548. rocksdb_compact_range_opt(db, coptions, NULL, 0, NULL, 0);
  549. CheckGet(db, roptions, "foo", "hello");
  550. StartPhase("compactrangeopt");
  551. rocksdb_compact_range_opt(db, coptions, "a", 1, "z", 1);
  552. CheckGet(db, roptions, "foo", "hello");
  553. // Simple check cache usage
  554. StartPhase("cache_usage");
  555. {
  556. rocksdb_readoptions_set_pin_data(roptions, 1);
  557. rocksdb_iterator_t* iter = rocksdb_create_iterator(db, roptions);
  558. rocksdb_iter_seek(iter, "foo", 3);
  559. size_t usage = rocksdb_cache_get_usage(cache);
  560. CheckCondition(usage > 0);
  561. size_t pin_usage = rocksdb_cache_get_pinned_usage(cache);
  562. CheckCondition(pin_usage > 0);
  563. rocksdb_iter_next(iter);
  564. rocksdb_iter_destroy(iter);
  565. rocksdb_readoptions_set_pin_data(roptions, 0);
  566. }
  567. StartPhase("addfile");
  568. {
  569. rocksdb_envoptions_t* env_opt = rocksdb_envoptions_create();
  570. rocksdb_options_t* io_options = rocksdb_options_create();
  571. rocksdb_sstfilewriter_t* writer =
  572. rocksdb_sstfilewriter_create(env_opt, io_options);
  573. remove(sstfilename);
  574. rocksdb_sstfilewriter_open(writer, sstfilename, &err);
  575. CheckNoError(err);
  576. rocksdb_sstfilewriter_put(writer, "sstk1", 5, "v1", 2, &err);
  577. CheckNoError(err);
  578. rocksdb_sstfilewriter_put(writer, "sstk2", 5, "v2", 2, &err);
  579. CheckNoError(err);
  580. rocksdb_sstfilewriter_put(writer, "sstk3", 5, "v3", 2, &err);
  581. CheckNoError(err);
  582. rocksdb_sstfilewriter_finish(writer, &err);
  583. CheckNoError(err);
  584. rocksdb_ingestexternalfileoptions_t* ing_opt =
  585. rocksdb_ingestexternalfileoptions_create();
  586. const char* file_list[1] = {sstfilename};
  587. rocksdb_ingest_external_file(db, file_list, 1, ing_opt, &err);
  588. CheckNoError(err);
  589. CheckGet(db, roptions, "sstk1", "v1");
  590. CheckGet(db, roptions, "sstk2", "v2");
  591. CheckGet(db, roptions, "sstk3", "v3");
  592. remove(sstfilename);
  593. rocksdb_sstfilewriter_open(writer, sstfilename, &err);
  594. CheckNoError(err);
  595. rocksdb_sstfilewriter_put(writer, "sstk2", 5, "v4", 2, &err);
  596. CheckNoError(err);
  597. rocksdb_sstfilewriter_put(writer, "sstk22", 6, "v5", 2, &err);
  598. CheckNoError(err);
  599. rocksdb_sstfilewriter_put(writer, "sstk3", 5, "v6", 2, &err);
  600. CheckNoError(err);
  601. rocksdb_sstfilewriter_finish(writer, &err);
  602. CheckNoError(err);
  603. rocksdb_ingest_external_file(db, file_list, 1, ing_opt, &err);
  604. CheckNoError(err);
  605. CheckGet(db, roptions, "sstk1", "v1");
  606. CheckGet(db, roptions, "sstk2", "v4");
  607. CheckGet(db, roptions, "sstk22", "v5");
  608. CheckGet(db, roptions, "sstk3", "v6");
  609. rocksdb_ingestexternalfileoptions_destroy(ing_opt);
  610. rocksdb_sstfilewriter_destroy(writer);
  611. rocksdb_options_destroy(io_options);
  612. rocksdb_envoptions_destroy(env_opt);
  613. // Delete all keys we just ingested
  614. rocksdb_delete(db, woptions, "sstk1", 5, &err);
  615. CheckNoError(err);
  616. rocksdb_delete(db, woptions, "sstk2", 5, &err);
  617. CheckNoError(err);
  618. rocksdb_delete(db, woptions, "sstk22", 6, &err);
  619. CheckNoError(err);
  620. rocksdb_delete(db, woptions, "sstk3", 5, &err);
  621. CheckNoError(err);
  622. }
  623. StartPhase("writebatch");
  624. {
  625. rocksdb_writebatch_t* wb = rocksdb_writebatch_create();
  626. rocksdb_writebatch_put(wb, "foo", 3, "a", 1);
  627. rocksdb_writebatch_clear(wb);
  628. rocksdb_writebatch_put(wb, "bar", 3, "b", 1);
  629. rocksdb_writebatch_put(wb, "box", 3, "c", 1);
  630. rocksdb_writebatch_delete(wb, "bar", 3);
  631. rocksdb_write(db, woptions, wb, &err);
  632. CheckNoError(err);
  633. CheckGet(db, roptions, "foo", "hello");
  634. CheckGet(db, roptions, "bar", NULL);
  635. CheckGet(db, roptions, "box", "c");
  636. int pos = 0;
  637. rocksdb_writebatch_iterate(wb, &pos, CheckPut, CheckDel);
  638. CheckCondition(pos == 3);
  639. rocksdb_writebatch_clear(wb);
  640. rocksdb_writebatch_put(wb, "bar", 3, "b", 1);
  641. rocksdb_writebatch_put(wb, "bay", 3, "d", 1);
  642. rocksdb_writebatch_delete_range(wb, "bar", 3, "bay", 3);
  643. rocksdb_write(db, woptions, wb, &err);
  644. CheckNoError(err);
  645. CheckGet(db, roptions, "bar", NULL);
  646. CheckGet(db, roptions, "bay", "d");
  647. rocksdb_writebatch_clear(wb);
  648. const char* start_list[1] = {"bay"};
  649. const size_t start_sizes[1] = {3};
  650. const char* end_list[1] = {"baz"};
  651. const size_t end_sizes[1] = {3};
  652. rocksdb_writebatch_delete_rangev(wb, 1, start_list, start_sizes, end_list,
  653. end_sizes);
  654. rocksdb_write(db, woptions, wb, &err);
  655. CheckNoError(err);
  656. CheckGet(db, roptions, "bay", NULL);
  657. rocksdb_writebatch_destroy(wb);
  658. }
  659. StartPhase("writebatch_vectors");
  660. {
  661. rocksdb_writebatch_t* wb = rocksdb_writebatch_create();
  662. const char* k_list[2] = { "z", "ap" };
  663. const size_t k_sizes[2] = { 1, 2 };
  664. const char* v_list[3] = { "x", "y", "z" };
  665. const size_t v_sizes[3] = { 1, 1, 1 };
  666. rocksdb_writebatch_putv(wb, 2, k_list, k_sizes, 3, v_list, v_sizes);
  667. rocksdb_write(db, woptions, wb, &err);
  668. CheckNoError(err);
  669. CheckGet(db, roptions, "zap", "xyz");
  670. rocksdb_writebatch_delete(wb, "zap", 3);
  671. rocksdb_write(db, woptions, wb, &err);
  672. CheckNoError(err);
  673. CheckGet(db, roptions, "zap", NULL);
  674. rocksdb_writebatch_destroy(wb);
  675. }
  676. StartPhase("writebatch_savepoint");
  677. {
  678. rocksdb_writebatch_t* wb = rocksdb_writebatch_create();
  679. rocksdb_writebatch_set_save_point(wb);
  680. rocksdb_writebatch_set_save_point(wb);
  681. const char* k_list[2] = {"z", "ap"};
  682. const size_t k_sizes[2] = {1, 2};
  683. const char* v_list[3] = {"x", "y", "z"};
  684. const size_t v_sizes[3] = {1, 1, 1};
  685. rocksdb_writebatch_pop_save_point(wb, &err);
  686. CheckNoError(err);
  687. rocksdb_writebatch_putv(wb, 2, k_list, k_sizes, 3, v_list, v_sizes);
  688. rocksdb_writebatch_rollback_to_save_point(wb, &err);
  689. CheckNoError(err);
  690. rocksdb_write(db, woptions, wb, &err);
  691. CheckNoError(err);
  692. CheckGet(db, roptions, "zap", NULL);
  693. rocksdb_writebatch_destroy(wb);
  694. }
  695. StartPhase("writebatch_rep");
  696. {
  697. rocksdb_writebatch_t* wb1 = rocksdb_writebatch_create();
  698. rocksdb_writebatch_put(wb1, "baz", 3, "d", 1);
  699. rocksdb_writebatch_put(wb1, "quux", 4, "e", 1);
  700. rocksdb_writebatch_delete(wb1, "quux", 4);
  701. size_t repsize1 = 0;
  702. const char* rep = rocksdb_writebatch_data(wb1, &repsize1);
  703. rocksdb_writebatch_t* wb2 = rocksdb_writebatch_create_from(rep, repsize1);
  704. CheckCondition(rocksdb_writebatch_count(wb1) ==
  705. rocksdb_writebatch_count(wb2));
  706. size_t repsize2 = 0;
  707. CheckCondition(
  708. memcmp(rep, rocksdb_writebatch_data(wb2, &repsize2), repsize1) == 0);
  709. rocksdb_writebatch_destroy(wb1);
  710. rocksdb_writebatch_destroy(wb2);
  711. }
  712. StartPhase("writebatch_wi");
  713. {
  714. rocksdb_writebatch_wi_t* wbi = rocksdb_writebatch_wi_create(0, 1);
  715. rocksdb_writebatch_wi_put(wbi, "foo", 3, "a", 1);
  716. rocksdb_writebatch_wi_clear(wbi);
  717. rocksdb_writebatch_wi_put(wbi, "bar", 3, "b", 1);
  718. rocksdb_writebatch_wi_put(wbi, "box", 3, "c", 1);
  719. rocksdb_writebatch_wi_delete(wbi, "bar", 3);
  720. int count = rocksdb_writebatch_wi_count(wbi);
  721. CheckCondition(count == 3);
  722. size_t size;
  723. char* value;
  724. value = rocksdb_writebatch_wi_get_from_batch(wbi, options, "box", 3, &size, &err);
  725. CheckValue(err, "c", &value, size);
  726. value = rocksdb_writebatch_wi_get_from_batch(wbi, options, "bar", 3, &size, &err);
  727. CheckValue(err, NULL, &value, size);
  728. value = rocksdb_writebatch_wi_get_from_batch_and_db(wbi, db, roptions, "foo", 3, &size, &err);
  729. CheckValue(err, "hello", &value, size);
  730. value = rocksdb_writebatch_wi_get_from_batch_and_db(wbi, db, roptions, "box", 3, &size, &err);
  731. CheckValue(err, "c", &value, size);
  732. rocksdb_write_writebatch_wi(db, woptions, wbi, &err);
  733. CheckNoError(err);
  734. CheckGet(db, roptions, "foo", "hello");
  735. CheckGet(db, roptions, "bar", NULL);
  736. CheckGet(db, roptions, "box", "c");
  737. int pos = 0;
  738. rocksdb_writebatch_wi_iterate(wbi, &pos, CheckPut, CheckDel);
  739. CheckCondition(pos == 3);
  740. rocksdb_writebatch_wi_clear(wbi);
  741. rocksdb_writebatch_wi_destroy(wbi);
  742. }
  743. StartPhase("writebatch_wi_vectors");
  744. {
  745. rocksdb_writebatch_wi_t* wb = rocksdb_writebatch_wi_create(0, 1);
  746. const char* k_list[2] = { "z", "ap" };
  747. const size_t k_sizes[2] = { 1, 2 };
  748. const char* v_list[3] = { "x", "y", "z" };
  749. const size_t v_sizes[3] = { 1, 1, 1 };
  750. rocksdb_writebatch_wi_putv(wb, 2, k_list, k_sizes, 3, v_list, v_sizes);
  751. rocksdb_write_writebatch_wi(db, woptions, wb, &err);
  752. CheckNoError(err);
  753. CheckGet(db, roptions, "zap", "xyz");
  754. rocksdb_writebatch_wi_delete(wb, "zap", 3);
  755. rocksdb_write_writebatch_wi(db, woptions, wb, &err);
  756. CheckNoError(err);
  757. CheckGet(db, roptions, "zap", NULL);
  758. rocksdb_writebatch_wi_destroy(wb);
  759. }
  760. StartPhase("writebatch_wi_savepoint");
  761. {
  762. rocksdb_writebatch_wi_t* wb = rocksdb_writebatch_wi_create(0, 1);
  763. rocksdb_writebatch_wi_set_save_point(wb);
  764. const char* k_list[2] = {"z", "ap"};
  765. const size_t k_sizes[2] = {1, 2};
  766. const char* v_list[3] = {"x", "y", "z"};
  767. const size_t v_sizes[3] = {1, 1, 1};
  768. rocksdb_writebatch_wi_putv(wb, 2, k_list, k_sizes, 3, v_list, v_sizes);
  769. rocksdb_writebatch_wi_rollback_to_save_point(wb, &err);
  770. CheckNoError(err);
  771. rocksdb_write_writebatch_wi(db, woptions, wb, &err);
  772. CheckNoError(err);
  773. CheckGet(db, roptions, "zap", NULL);
  774. rocksdb_writebatch_wi_destroy(wb);
  775. }
  776. StartPhase("iter");
  777. {
  778. rocksdb_iterator_t* iter = rocksdb_create_iterator(db, roptions);
  779. CheckCondition(!rocksdb_iter_valid(iter));
  780. rocksdb_iter_seek_to_first(iter);
  781. CheckCondition(rocksdb_iter_valid(iter));
  782. CheckIter(iter, "box", "c");
  783. rocksdb_iter_next(iter);
  784. CheckIter(iter, "foo", "hello");
  785. rocksdb_iter_prev(iter);
  786. CheckIter(iter, "box", "c");
  787. rocksdb_iter_prev(iter);
  788. CheckCondition(!rocksdb_iter_valid(iter));
  789. rocksdb_iter_seek_to_last(iter);
  790. CheckIter(iter, "foo", "hello");
  791. rocksdb_iter_seek(iter, "b", 1);
  792. CheckIter(iter, "box", "c");
  793. rocksdb_iter_seek_for_prev(iter, "g", 1);
  794. CheckIter(iter, "foo", "hello");
  795. rocksdb_iter_seek_for_prev(iter, "box", 3);
  796. CheckIter(iter, "box", "c");
  797. rocksdb_iter_get_error(iter, &err);
  798. CheckNoError(err);
  799. rocksdb_iter_destroy(iter);
  800. }
  801. StartPhase("wbwi_iter");
  802. {
  803. rocksdb_iterator_t* base_iter = rocksdb_create_iterator(db, roptions);
  804. rocksdb_writebatch_wi_t* wbi = rocksdb_writebatch_wi_create(0, 1);
  805. rocksdb_writebatch_wi_put(wbi, "bar", 3, "b", 1);
  806. rocksdb_writebatch_wi_delete(wbi, "foo", 3);
  807. rocksdb_iterator_t* iter =
  808. rocksdb_writebatch_wi_create_iterator_with_base(wbi, base_iter);
  809. CheckCondition(!rocksdb_iter_valid(iter));
  810. rocksdb_iter_seek_to_first(iter);
  811. CheckCondition(rocksdb_iter_valid(iter));
  812. CheckIter(iter, "bar", "b");
  813. rocksdb_iter_next(iter);
  814. CheckIter(iter, "box", "c");
  815. rocksdb_iter_prev(iter);
  816. CheckIter(iter, "bar", "b");
  817. rocksdb_iter_prev(iter);
  818. CheckCondition(!rocksdb_iter_valid(iter));
  819. rocksdb_iter_seek_to_last(iter);
  820. CheckIter(iter, "box", "c");
  821. rocksdb_iter_seek(iter, "b", 1);
  822. CheckIter(iter, "bar", "b");
  823. rocksdb_iter_seek_for_prev(iter, "c", 1);
  824. CheckIter(iter, "box", "c");
  825. rocksdb_iter_seek_for_prev(iter, "box", 3);
  826. CheckIter(iter, "box", "c");
  827. rocksdb_iter_get_error(iter, &err);
  828. CheckNoError(err);
  829. rocksdb_iter_destroy(iter);
  830. rocksdb_writebatch_wi_destroy(wbi);
  831. }
  832. StartPhase("multiget");
  833. {
  834. const char* keys[3] = { "box", "foo", "notfound" };
  835. const size_t keys_sizes[3] = { 3, 3, 8 };
  836. char* vals[3];
  837. size_t vals_sizes[3];
  838. char* errs[3];
  839. rocksdb_multi_get(db, roptions, 3, keys, keys_sizes, vals, vals_sizes, errs);
  840. int i;
  841. for (i = 0; i < 3; i++) {
  842. CheckEqual(NULL, errs[i], 0);
  843. switch (i) {
  844. case 0:
  845. CheckEqual("c", vals[i], vals_sizes[i]);
  846. break;
  847. case 1:
  848. CheckEqual("hello", vals[i], vals_sizes[i]);
  849. break;
  850. case 2:
  851. CheckEqual(NULL, vals[i], vals_sizes[i]);
  852. break;
  853. }
  854. Free(&vals[i]);
  855. }
  856. }
  857. StartPhase("pin_get");
  858. {
  859. CheckPinGet(db, roptions, "box", "c");
  860. CheckPinGet(db, roptions, "foo", "hello");
  861. CheckPinGet(db, roptions, "notfound", NULL);
  862. }
  863. StartPhase("approximate_sizes");
  864. {
  865. int i;
  866. int n = 20000;
  867. char keybuf[100];
  868. char valbuf[100];
  869. uint64_t sizes[2];
  870. const char* start[2] = { "a", "k00000000000000010000" };
  871. size_t start_len[2] = { 1, 21 };
  872. const char* limit[2] = { "k00000000000000010000", "z" };
  873. size_t limit_len[2] = { 21, 1 };
  874. rocksdb_writeoptions_set_sync(woptions, 0);
  875. for (i = 0; i < n; i++) {
  876. snprintf(keybuf, sizeof(keybuf), "k%020d", i);
  877. snprintf(valbuf, sizeof(valbuf), "v%020d", i);
  878. rocksdb_put(db, woptions, keybuf, strlen(keybuf), valbuf, strlen(valbuf),
  879. &err);
  880. CheckNoError(err);
  881. }
  882. rocksdb_approximate_sizes(db, 2, start, start_len, limit, limit_len, sizes);
  883. CheckCondition(sizes[0] > 0);
  884. CheckCondition(sizes[1] > 0);
  885. }
  886. StartPhase("property");
  887. {
  888. char* prop = rocksdb_property_value(db, "nosuchprop");
  889. CheckCondition(prop == NULL);
  890. prop = rocksdb_property_value(db, "rocksdb.stats");
  891. CheckCondition(prop != NULL);
  892. Free(&prop);
  893. }
  894. StartPhase("snapshot");
  895. {
  896. const rocksdb_snapshot_t* snap;
  897. snap = rocksdb_create_snapshot(db);
  898. rocksdb_delete(db, woptions, "foo", 3, &err);
  899. CheckNoError(err);
  900. rocksdb_readoptions_set_snapshot(roptions, snap);
  901. CheckGet(db, roptions, "foo", "hello");
  902. rocksdb_readoptions_set_snapshot(roptions, NULL);
  903. CheckGet(db, roptions, "foo", NULL);
  904. rocksdb_release_snapshot(db, snap);
  905. }
  906. StartPhase("repair");
  907. {
  908. // If we do not compact here, then the lazy deletion of
  909. // files (https://reviews.facebook.net/D6123) would leave
  910. // around deleted files and the repair process will find
  911. // those files and put them back into the database.
  912. rocksdb_compact_range(db, NULL, 0, NULL, 0);
  913. rocksdb_close(db);
  914. rocksdb_options_set_create_if_missing(options, 0);
  915. rocksdb_options_set_error_if_exists(options, 0);
  916. rocksdb_options_set_wal_recovery_mode(options, 2);
  917. rocksdb_repair_db(options, dbname, &err);
  918. CheckNoError(err);
  919. db = rocksdb_open(options, dbname, &err);
  920. CheckNoError(err);
  921. CheckGet(db, roptions, "foo", NULL);
  922. CheckGet(db, roptions, "bar", NULL);
  923. CheckGet(db, roptions, "box", "c");
  924. rocksdb_options_set_create_if_missing(options, 1);
  925. rocksdb_options_set_error_if_exists(options, 1);
  926. }
  927. StartPhase("filter");
  928. for (run = 0; run <= 2; run++) {
  929. // First run uses custom filter
  930. // Second run uses old block-based bloom filter
  931. // Third run uses full bloom filter
  932. CheckNoError(err);
  933. rocksdb_filterpolicy_t* policy;
  934. if (run == 0) {
  935. policy = rocksdb_filterpolicy_create(NULL, FilterDestroy, FilterCreate,
  936. FilterKeyMatch, NULL, FilterName);
  937. } else if (run == 1) {
  938. policy = rocksdb_filterpolicy_create_bloom(8);
  939. } else {
  940. policy = rocksdb_filterpolicy_create_bloom_full(8);
  941. }
  942. rocksdb_block_based_options_set_filter_policy(table_options, policy);
  943. // Create new database
  944. rocksdb_close(db);
  945. rocksdb_destroy_db(options, dbname, &err);
  946. rocksdb_options_set_block_based_table_factory(options, table_options);
  947. db = rocksdb_open(options, dbname, &err);
  948. CheckNoError(err);
  949. rocksdb_put(db, woptions, "foo", 3, "foovalue", 8, &err);
  950. CheckNoError(err);
  951. rocksdb_put(db, woptions, "bar", 3, "barvalue", 8, &err);
  952. CheckNoError(err);
  953. {
  954. // Add enough keys to get just one reasonably populated Bloom filter
  955. const int keys_to_add = 1500;
  956. int i;
  957. char keybuf[100];
  958. for (i = 0; i < keys_to_add; i++) {
  959. snprintf(keybuf, sizeof(keybuf), "yes%020d", i);
  960. rocksdb_put(db, woptions, keybuf, strlen(keybuf), "val", 3, &err);
  961. CheckNoError(err);
  962. }
  963. }
  964. rocksdb_compact_range(db, NULL, 0, NULL, 0);
  965. fake_filter_result = 1;
  966. CheckGet(db, roptions, "foo", "foovalue");
  967. CheckGet(db, roptions, "bar", "barvalue");
  968. if (run == 0) {
  969. // Must not find value when custom filter returns false
  970. fake_filter_result = 0;
  971. CheckGet(db, roptions, "foo", NULL);
  972. CheckGet(db, roptions, "bar", NULL);
  973. fake_filter_result = 1;
  974. CheckGet(db, roptions, "foo", "foovalue");
  975. CheckGet(db, roptions, "bar", "barvalue");
  976. }
  977. {
  978. // Query some keys not added to identify Bloom filter implementation
  979. // from false positive queries, using perfcontext to detect Bloom
  980. // filter behavior
  981. rocksdb_perfcontext_t* perf = rocksdb_perfcontext_create();
  982. rocksdb_perfcontext_reset(perf);
  983. const int keys_to_query = 10000;
  984. int i;
  985. char keybuf[100];
  986. for (i = 0; i < keys_to_query; i++) {
  987. fake_filter_result = i % 2;
  988. snprintf(keybuf, sizeof(keybuf), "no%020d", i);
  989. CheckGet(db, roptions, keybuf, NULL);
  990. }
  991. const int hits =
  992. (int)rocksdb_perfcontext_metric(perf, rocksdb_bloom_sst_hit_count);
  993. if (run == 0) {
  994. // Due to half true, half false with fake filter result
  995. CheckCondition(hits == keys_to_query / 2);
  996. } else if (run == 1) {
  997. // Essentially a fingerprint of the block-based Bloom schema
  998. CheckCondition(hits == 241);
  999. } else {
  1000. // Essentially a fingerprint of the full Bloom schema(s),
  1001. // format_version < 5, which vary for three different CACHE_LINE_SIZEs
  1002. CheckCondition(hits == 224 || hits == 180 || hits == 125);
  1003. }
  1004. CheckCondition(
  1005. (keys_to_query - hits) ==
  1006. (int)rocksdb_perfcontext_metric(perf, rocksdb_bloom_sst_miss_count));
  1007. rocksdb_perfcontext_destroy(perf);
  1008. }
  1009. // Reset the policy
  1010. rocksdb_block_based_options_set_filter_policy(table_options, NULL);
  1011. rocksdb_options_set_block_based_table_factory(options, table_options);
  1012. }
  1013. StartPhase("compaction_filter");
  1014. {
  1015. rocksdb_options_t* options_with_filter = rocksdb_options_create();
  1016. rocksdb_options_set_create_if_missing(options_with_filter, 1);
  1017. rocksdb_compactionfilter_t* cfilter;
  1018. cfilter = rocksdb_compactionfilter_create(NULL, CFilterDestroy,
  1019. CFilterFilter, CFilterName);
  1020. // Create new database
  1021. rocksdb_close(db);
  1022. rocksdb_destroy_db(options_with_filter, dbname, &err);
  1023. rocksdb_options_set_compaction_filter(options_with_filter, cfilter);
  1024. db = CheckCompaction(db, options_with_filter, roptions, woptions);
  1025. rocksdb_options_set_compaction_filter(options_with_filter, NULL);
  1026. rocksdb_compactionfilter_destroy(cfilter);
  1027. rocksdb_options_destroy(options_with_filter);
  1028. }
  1029. StartPhase("compaction_filter_factory");
  1030. {
  1031. rocksdb_options_t* options_with_filter_factory = rocksdb_options_create();
  1032. rocksdb_options_set_create_if_missing(options_with_filter_factory, 1);
  1033. rocksdb_compactionfilterfactory_t* factory;
  1034. factory = rocksdb_compactionfilterfactory_create(
  1035. NULL, CFilterFactoryDestroy, CFilterCreate, CFilterFactoryName);
  1036. // Create new database
  1037. rocksdb_close(db);
  1038. rocksdb_destroy_db(options_with_filter_factory, dbname, &err);
  1039. rocksdb_options_set_compaction_filter_factory(options_with_filter_factory,
  1040. factory);
  1041. db = CheckCompaction(db, options_with_filter_factory, roptions, woptions);
  1042. rocksdb_options_set_compaction_filter_factory(
  1043. options_with_filter_factory, NULL);
  1044. rocksdb_options_destroy(options_with_filter_factory);
  1045. }
  1046. StartPhase("merge_operator");
  1047. {
  1048. rocksdb_mergeoperator_t* merge_operator;
  1049. merge_operator = rocksdb_mergeoperator_create(
  1050. NULL, MergeOperatorDestroy, MergeOperatorFullMerge,
  1051. MergeOperatorPartialMerge, NULL, MergeOperatorName);
  1052. // Create new database
  1053. rocksdb_close(db);
  1054. rocksdb_destroy_db(options, dbname, &err);
  1055. rocksdb_options_set_merge_operator(options, merge_operator);
  1056. db = rocksdb_open(options, dbname, &err);
  1057. CheckNoError(err);
  1058. rocksdb_put(db, woptions, "foo", 3, "foovalue", 8, &err);
  1059. CheckNoError(err);
  1060. CheckGet(db, roptions, "foo", "foovalue");
  1061. rocksdb_merge(db, woptions, "foo", 3, "barvalue", 8, &err);
  1062. CheckNoError(err);
  1063. CheckGet(db, roptions, "foo", "fake");
  1064. // Merge of a non-existing value
  1065. rocksdb_merge(db, woptions, "bar", 3, "barvalue", 8, &err);
  1066. CheckNoError(err);
  1067. CheckGet(db, roptions, "bar", "fake");
  1068. }
  1069. StartPhase("columnfamilies");
  1070. {
  1071. rocksdb_close(db);
  1072. rocksdb_destroy_db(options, dbname, &err);
  1073. CheckNoError(err);
  1074. rocksdb_options_t* db_options = rocksdb_options_create();
  1075. rocksdb_options_set_create_if_missing(db_options, 1);
  1076. db = rocksdb_open(db_options, dbname, &err);
  1077. CheckNoError(err)
  1078. rocksdb_column_family_handle_t* cfh;
  1079. cfh = rocksdb_create_column_family(db, db_options, "cf1", &err);
  1080. rocksdb_column_family_handle_destroy(cfh);
  1081. CheckNoError(err);
  1082. rocksdb_close(db);
  1083. size_t cflen;
  1084. char** column_fams = rocksdb_list_column_families(db_options, dbname, &cflen, &err);
  1085. CheckNoError(err);
  1086. CheckEqual("default", column_fams[0], 7);
  1087. CheckEqual("cf1", column_fams[1], 3);
  1088. CheckCondition(cflen == 2);
  1089. rocksdb_list_column_families_destroy(column_fams, cflen);
  1090. rocksdb_options_t* cf_options = rocksdb_options_create();
  1091. const char* cf_names[2] = {"default", "cf1"};
  1092. const rocksdb_options_t* cf_opts[2] = {cf_options, cf_options};
  1093. rocksdb_column_family_handle_t* handles[2];
  1094. db = rocksdb_open_column_families(db_options, dbname, 2, cf_names, cf_opts, handles, &err);
  1095. CheckNoError(err);
  1096. rocksdb_put_cf(db, woptions, handles[1], "foo", 3, "hello", 5, &err);
  1097. CheckNoError(err);
  1098. rocksdb_put_cf(db, woptions, handles[1], "foobar1", 7, "hello1", 6, &err);
  1099. CheckNoError(err);
  1100. rocksdb_put_cf(db, woptions, handles[1], "foobar2", 7, "hello2", 6, &err);
  1101. CheckNoError(err);
  1102. rocksdb_put_cf(db, woptions, handles[1], "foobar3", 7, "hello3", 6, &err);
  1103. CheckNoError(err);
  1104. rocksdb_put_cf(db, woptions, handles[1], "foobar4", 7, "hello4", 6, &err);
  1105. CheckNoError(err);
  1106. rocksdb_flushoptions_t *flush_options = rocksdb_flushoptions_create();
  1107. rocksdb_flushoptions_set_wait(flush_options, 1);
  1108. rocksdb_flush_cf(db, flush_options, handles[1], &err);
  1109. CheckNoError(err)
  1110. rocksdb_flushoptions_destroy(flush_options);
  1111. CheckGetCF(db, roptions, handles[1], "foo", "hello");
  1112. CheckPinGetCF(db, roptions, handles[1], "foo", "hello");
  1113. rocksdb_delete_cf(db, woptions, handles[1], "foo", 3, &err);
  1114. CheckNoError(err);
  1115. rocksdb_delete_range_cf(db, woptions, handles[1], "foobar2", 7, "foobar4",
  1116. 7, &err);
  1117. CheckNoError(err);
  1118. CheckGetCF(db, roptions, handles[1], "foo", NULL);
  1119. CheckPinGetCF(db, roptions, handles[1], "foo", NULL);
  1120. rocksdb_writebatch_t* wb = rocksdb_writebatch_create();
  1121. rocksdb_writebatch_put_cf(wb, handles[1], "baz", 3, "a", 1);
  1122. rocksdb_writebatch_clear(wb);
  1123. rocksdb_writebatch_put_cf(wb, handles[1], "bar", 3, "b", 1);
  1124. rocksdb_writebatch_put_cf(wb, handles[1], "box", 3, "c", 1);
  1125. rocksdb_writebatch_delete_cf(wb, handles[1], "bar", 3);
  1126. rocksdb_write(db, woptions, wb, &err);
  1127. CheckNoError(err);
  1128. CheckGetCF(db, roptions, handles[1], "baz", NULL);
  1129. CheckGetCF(db, roptions, handles[1], "bar", NULL);
  1130. CheckGetCF(db, roptions, handles[1], "box", "c");
  1131. CheckPinGetCF(db, roptions, handles[1], "baz", NULL);
  1132. CheckPinGetCF(db, roptions, handles[1], "bar", NULL);
  1133. CheckPinGetCF(db, roptions, handles[1], "box", "c");
  1134. rocksdb_writebatch_destroy(wb);
  1135. const char* keys[3] = { "box", "box", "barfooxx" };
  1136. const rocksdb_column_family_handle_t* get_handles[3] = { handles[0], handles[1], handles[1] };
  1137. const size_t keys_sizes[3] = { 3, 3, 8 };
  1138. char* vals[3];
  1139. size_t vals_sizes[3];
  1140. char* errs[3];
  1141. rocksdb_multi_get_cf(db, roptions, get_handles, 3, keys, keys_sizes, vals, vals_sizes, errs);
  1142. int i;
  1143. for (i = 0; i < 3; i++) {
  1144. CheckEqual(NULL, errs[i], 0);
  1145. switch (i) {
  1146. case 0:
  1147. CheckEqual(NULL, vals[i], vals_sizes[i]); // wrong cf
  1148. break;
  1149. case 1:
  1150. CheckEqual("c", vals[i], vals_sizes[i]); // bingo
  1151. break;
  1152. case 2:
  1153. CheckEqual(NULL, vals[i], vals_sizes[i]); // normal not found
  1154. break;
  1155. }
  1156. Free(&vals[i]);
  1157. }
  1158. rocksdb_iterator_t* iter = rocksdb_create_iterator_cf(db, roptions, handles[1]);
  1159. CheckCondition(!rocksdb_iter_valid(iter));
  1160. rocksdb_iter_seek_to_first(iter);
  1161. CheckCondition(rocksdb_iter_valid(iter));
  1162. for (i = 0; rocksdb_iter_valid(iter) != 0; rocksdb_iter_next(iter)) {
  1163. i++;
  1164. }
  1165. CheckCondition(i == 3);
  1166. rocksdb_iter_get_error(iter, &err);
  1167. CheckNoError(err);
  1168. rocksdb_iter_destroy(iter);
  1169. rocksdb_column_family_handle_t* iters_cf_handles[2] = { handles[0], handles[1] };
  1170. rocksdb_iterator_t* iters_handles[2];
  1171. rocksdb_create_iterators(db, roptions, iters_cf_handles, iters_handles, 2, &err);
  1172. CheckNoError(err);
  1173. iter = iters_handles[0];
  1174. CheckCondition(!rocksdb_iter_valid(iter));
  1175. rocksdb_iter_seek_to_first(iter);
  1176. CheckCondition(!rocksdb_iter_valid(iter));
  1177. rocksdb_iter_destroy(iter);
  1178. iter = iters_handles[1];
  1179. CheckCondition(!rocksdb_iter_valid(iter));
  1180. rocksdb_iter_seek_to_first(iter);
  1181. CheckCondition(rocksdb_iter_valid(iter));
  1182. for (i = 0; rocksdb_iter_valid(iter) != 0; rocksdb_iter_next(iter)) {
  1183. i++;
  1184. }
  1185. CheckCondition(i == 3);
  1186. rocksdb_iter_get_error(iter, &err);
  1187. CheckNoError(err);
  1188. rocksdb_iter_destroy(iter);
  1189. rocksdb_drop_column_family(db, handles[1], &err);
  1190. CheckNoError(err);
  1191. for (i = 0; i < 2; i++) {
  1192. rocksdb_column_family_handle_destroy(handles[i]);
  1193. }
  1194. rocksdb_close(db);
  1195. rocksdb_destroy_db(options, dbname, &err);
  1196. rocksdb_options_destroy(db_options);
  1197. rocksdb_options_destroy(cf_options);
  1198. }
  1199. StartPhase("prefix");
  1200. {
  1201. // Create new database
  1202. rocksdb_options_set_allow_mmap_reads(options, 1);
  1203. rocksdb_options_set_prefix_extractor(options, rocksdb_slicetransform_create_fixed_prefix(3));
  1204. rocksdb_options_set_hash_skip_list_rep(options, 5000, 4, 4);
  1205. rocksdb_options_set_plain_table_factory(options, 4, 10, 0.75, 16);
  1206. rocksdb_options_set_allow_concurrent_memtable_write(options, 0);
  1207. db = rocksdb_open(options, dbname, &err);
  1208. CheckNoError(err);
  1209. rocksdb_put(db, woptions, "foo1", 4, "foo", 3, &err);
  1210. CheckNoError(err);
  1211. rocksdb_put(db, woptions, "foo2", 4, "foo", 3, &err);
  1212. CheckNoError(err);
  1213. rocksdb_put(db, woptions, "foo3", 4, "foo", 3, &err);
  1214. CheckNoError(err);
  1215. rocksdb_put(db, woptions, "bar1", 4, "bar", 3, &err);
  1216. CheckNoError(err);
  1217. rocksdb_put(db, woptions, "bar2", 4, "bar", 3, &err);
  1218. CheckNoError(err);
  1219. rocksdb_put(db, woptions, "bar3", 4, "bar", 3, &err);
  1220. CheckNoError(err);
  1221. rocksdb_iterator_t* iter = rocksdb_create_iterator(db, roptions);
  1222. CheckCondition(!rocksdb_iter_valid(iter));
  1223. rocksdb_iter_seek(iter, "bar", 3);
  1224. rocksdb_iter_get_error(iter, &err);
  1225. CheckNoError(err);
  1226. CheckCondition(rocksdb_iter_valid(iter));
  1227. CheckIter(iter, "bar1", "bar");
  1228. rocksdb_iter_next(iter);
  1229. CheckIter(iter, "bar2", "bar");
  1230. rocksdb_iter_next(iter);
  1231. CheckIter(iter, "bar3", "bar");
  1232. rocksdb_iter_get_error(iter, &err);
  1233. CheckNoError(err);
  1234. rocksdb_iter_destroy(iter);
  1235. rocksdb_readoptions_set_total_order_seek(roptions, 1);
  1236. iter = rocksdb_create_iterator(db, roptions);
  1237. CheckCondition(!rocksdb_iter_valid(iter));
  1238. rocksdb_iter_seek(iter, "ba", 2);
  1239. rocksdb_iter_get_error(iter, &err);
  1240. CheckNoError(err);
  1241. CheckCondition(rocksdb_iter_valid(iter));
  1242. CheckIter(iter, "bar1", "bar");
  1243. rocksdb_iter_destroy(iter);
  1244. rocksdb_readoptions_set_total_order_seek(roptions, 0);
  1245. rocksdb_close(db);
  1246. rocksdb_destroy_db(options, dbname, &err);
  1247. }
  1248. // Check memory usage stats
  1249. StartPhase("approximate_memory_usage");
  1250. {
  1251. // Create database
  1252. db = rocksdb_open(options, dbname, &err);
  1253. CheckNoError(err);
  1254. rocksdb_memory_consumers_t* consumers;
  1255. consumers = rocksdb_memory_consumers_create();
  1256. rocksdb_memory_consumers_add_db(consumers, db);
  1257. rocksdb_memory_consumers_add_cache(consumers, cache);
  1258. // take memory usage report before write-read operation
  1259. rocksdb_memory_usage_t* mu1;
  1260. mu1 = rocksdb_approximate_memory_usage_create(consumers, &err);
  1261. CheckNoError(err);
  1262. // Put data (this should affect memtables)
  1263. rocksdb_put(db, woptions, "memory", 6, "test", 4, &err);
  1264. CheckNoError(err);
  1265. CheckGet(db, roptions, "memory", "test");
  1266. // take memory usage report after write-read operation
  1267. rocksdb_memory_usage_t* mu2;
  1268. mu2 = rocksdb_approximate_memory_usage_create(consumers, &err);
  1269. CheckNoError(err);
  1270. // amount of memory used within memtables should grow
  1271. CheckCondition(rocksdb_approximate_memory_usage_get_mem_table_total(mu2) >=
  1272. rocksdb_approximate_memory_usage_get_mem_table_total(mu1));
  1273. CheckCondition(rocksdb_approximate_memory_usage_get_mem_table_unflushed(mu2) >=
  1274. rocksdb_approximate_memory_usage_get_mem_table_unflushed(mu1));
  1275. rocksdb_memory_consumers_destroy(consumers);
  1276. rocksdb_approximate_memory_usage_destroy(mu1);
  1277. rocksdb_approximate_memory_usage_destroy(mu2);
  1278. rocksdb_close(db);
  1279. rocksdb_destroy_db(options, dbname, &err);
  1280. CheckNoError(err);
  1281. }
  1282. StartPhase("cuckoo_options");
  1283. {
  1284. rocksdb_cuckoo_table_options_t* cuckoo_options;
  1285. cuckoo_options = rocksdb_cuckoo_options_create();
  1286. rocksdb_cuckoo_options_set_hash_ratio(cuckoo_options, 0.5);
  1287. rocksdb_cuckoo_options_set_max_search_depth(cuckoo_options, 200);
  1288. rocksdb_cuckoo_options_set_cuckoo_block_size(cuckoo_options, 10);
  1289. rocksdb_cuckoo_options_set_identity_as_first_hash(cuckoo_options, 1);
  1290. rocksdb_cuckoo_options_set_use_module_hash(cuckoo_options, 0);
  1291. rocksdb_options_set_cuckoo_table_factory(options, cuckoo_options);
  1292. db = rocksdb_open(options, dbname, &err);
  1293. CheckNoError(err);
  1294. rocksdb_cuckoo_options_destroy(cuckoo_options);
  1295. }
  1296. StartPhase("iterate_upper_bound");
  1297. {
  1298. // Create new empty database
  1299. rocksdb_close(db);
  1300. rocksdb_destroy_db(options, dbname, &err);
  1301. CheckNoError(err);
  1302. rocksdb_options_set_prefix_extractor(options, NULL);
  1303. db = rocksdb_open(options, dbname, &err);
  1304. CheckNoError(err);
  1305. rocksdb_put(db, woptions, "a", 1, "0", 1, &err); CheckNoError(err);
  1306. rocksdb_put(db, woptions, "foo", 3, "bar", 3, &err); CheckNoError(err);
  1307. rocksdb_put(db, woptions, "foo1", 4, "bar1", 4, &err); CheckNoError(err);
  1308. rocksdb_put(db, woptions, "g1", 2, "0", 1, &err); CheckNoError(err);
  1309. // testing basic case with no iterate_upper_bound and no prefix_extractor
  1310. {
  1311. rocksdb_readoptions_set_iterate_upper_bound(roptions, NULL, 0);
  1312. rocksdb_iterator_t* iter = rocksdb_create_iterator(db, roptions);
  1313. rocksdb_iter_seek(iter, "foo", 3);
  1314. CheckCondition(rocksdb_iter_valid(iter));
  1315. CheckIter(iter, "foo", "bar");
  1316. rocksdb_iter_next(iter);
  1317. CheckCondition(rocksdb_iter_valid(iter));
  1318. CheckIter(iter, "foo1", "bar1");
  1319. rocksdb_iter_next(iter);
  1320. CheckCondition(rocksdb_iter_valid(iter));
  1321. CheckIter(iter, "g1", "0");
  1322. rocksdb_iter_destroy(iter);
  1323. }
  1324. // testing iterate_upper_bound and forward iterator
  1325. // to make sure it stops at bound
  1326. {
  1327. // iterate_upper_bound points beyond the last expected entry
  1328. rocksdb_readoptions_set_iterate_upper_bound(roptions, "foo2", 4);
  1329. rocksdb_iterator_t* iter = rocksdb_create_iterator(db, roptions);
  1330. rocksdb_iter_seek(iter, "foo", 3);
  1331. CheckCondition(rocksdb_iter_valid(iter));
  1332. CheckIter(iter, "foo", "bar");
  1333. rocksdb_iter_next(iter);
  1334. CheckCondition(rocksdb_iter_valid(iter));
  1335. CheckIter(iter, "foo1", "bar1");
  1336. rocksdb_iter_next(iter);
  1337. // should stop here...
  1338. CheckCondition(!rocksdb_iter_valid(iter));
  1339. rocksdb_iter_destroy(iter);
  1340. rocksdb_readoptions_set_iterate_upper_bound(roptions, NULL, 0);
  1341. }
  1342. }
  1343. StartPhase("transactions");
  1344. {
  1345. rocksdb_close(db);
  1346. rocksdb_destroy_db(options, dbname, &err);
  1347. CheckNoError(err);
  1348. // open a TransactionDB
  1349. txn_db_options = rocksdb_transactiondb_options_create();
  1350. txn_options = rocksdb_transaction_options_create();
  1351. rocksdb_options_set_create_if_missing(options, 1);
  1352. txn_db = rocksdb_transactiondb_open(options, txn_db_options, dbname, &err);
  1353. CheckNoError(err);
  1354. // put outside a transaction
  1355. rocksdb_transactiondb_put(txn_db, woptions, "foo", 3, "hello", 5, &err);
  1356. CheckNoError(err);
  1357. CheckTxnDBGet(txn_db, roptions, "foo", "hello");
  1358. // delete from outside transaction
  1359. rocksdb_transactiondb_delete(txn_db, woptions, "foo", 3, &err);
  1360. CheckNoError(err);
  1361. CheckTxnDBGet(txn_db, roptions, "foo", NULL);
  1362. // write batch into TransactionDB
  1363. rocksdb_writebatch_t* wb = rocksdb_writebatch_create();
  1364. rocksdb_writebatch_put(wb, "foo", 3, "a", 1);
  1365. rocksdb_writebatch_clear(wb);
  1366. rocksdb_writebatch_put(wb, "bar", 3, "b", 1);
  1367. rocksdb_writebatch_put(wb, "box", 3, "c", 1);
  1368. rocksdb_writebatch_delete(wb, "bar", 3);
  1369. rocksdb_transactiondb_write(txn_db, woptions, wb, &err);
  1370. rocksdb_writebatch_destroy(wb);
  1371. CheckTxnDBGet(txn_db, roptions, "box", "c");
  1372. CheckNoError(err);
  1373. // begin a transaction
  1374. txn = rocksdb_transaction_begin(txn_db, woptions, txn_options, NULL);
  1375. // put
  1376. rocksdb_transaction_put(txn, "foo", 3, "hello", 5, &err);
  1377. CheckNoError(err);
  1378. CheckTxnGet(txn, roptions, "foo", "hello");
  1379. // delete
  1380. rocksdb_transaction_delete(txn, "foo", 3, &err);
  1381. CheckNoError(err);
  1382. CheckTxnGet(txn, roptions, "foo", NULL);
  1383. rocksdb_transaction_put(txn, "foo", 3, "hello", 5, &err);
  1384. CheckNoError(err);
  1385. // read from outside transaction, before commit
  1386. CheckTxnDBGet(txn_db, roptions, "foo", NULL);
  1387. // commit
  1388. rocksdb_transaction_commit(txn, &err);
  1389. CheckNoError(err);
  1390. // read from outside transaction, after commit
  1391. CheckTxnDBGet(txn_db, roptions, "foo", "hello");
  1392. // reuse old transaction
  1393. txn = rocksdb_transaction_begin(txn_db, woptions, txn_options, txn);
  1394. // snapshot
  1395. const rocksdb_snapshot_t* snapshot;
  1396. snapshot = rocksdb_transactiondb_create_snapshot(txn_db);
  1397. rocksdb_readoptions_set_snapshot(roptions, snapshot);
  1398. rocksdb_transactiondb_put(txn_db, woptions, "foo", 3, "hey", 3, &err);
  1399. CheckNoError(err);
  1400. CheckTxnDBGet(txn_db, roptions, "foo", "hello");
  1401. rocksdb_readoptions_set_snapshot(roptions, NULL);
  1402. rocksdb_transactiondb_release_snapshot(txn_db, snapshot);
  1403. CheckTxnDBGet(txn_db, roptions, "foo", "hey");
  1404. // iterate
  1405. rocksdb_transaction_put(txn, "bar", 3, "hi", 2, &err);
  1406. rocksdb_iterator_t* iter = rocksdb_transaction_create_iterator(txn, roptions);
  1407. CheckCondition(!rocksdb_iter_valid(iter));
  1408. rocksdb_iter_seek_to_first(iter);
  1409. CheckCondition(rocksdb_iter_valid(iter));
  1410. CheckIter(iter, "bar", "hi");
  1411. rocksdb_iter_get_error(iter, &err);
  1412. CheckNoError(err);
  1413. rocksdb_iter_destroy(iter);
  1414. // rollback
  1415. rocksdb_transaction_rollback(txn, &err);
  1416. CheckNoError(err);
  1417. CheckTxnDBGet(txn_db, roptions, "bar", NULL);
  1418. // save point
  1419. rocksdb_transaction_put(txn, "foo1", 4, "hi1", 3, &err);
  1420. rocksdb_transaction_set_savepoint(txn);
  1421. CheckTxnGet(txn, roptions, "foo1", "hi1");
  1422. rocksdb_transaction_put(txn, "foo2", 4, "hi2", 3, &err);
  1423. CheckTxnGet(txn, roptions, "foo2", "hi2");
  1424. // rollback to savepoint
  1425. rocksdb_transaction_rollback_to_savepoint(txn, &err);
  1426. CheckNoError(err);
  1427. CheckTxnGet(txn, roptions, "foo2", NULL);
  1428. CheckTxnGet(txn, roptions, "foo1", "hi1");
  1429. CheckTxnDBGet(txn_db, roptions, "foo1", NULL);
  1430. CheckTxnDBGet(txn_db, roptions, "foo2", NULL);
  1431. rocksdb_transaction_commit(txn, &err);
  1432. CheckNoError(err);
  1433. CheckTxnDBGet(txn_db, roptions, "foo1", "hi1");
  1434. CheckTxnDBGet(txn_db, roptions, "foo2", NULL);
  1435. // Column families.
  1436. rocksdb_column_family_handle_t* cfh;
  1437. cfh = rocksdb_transactiondb_create_column_family(txn_db, options,
  1438. "txn_db_cf", &err);
  1439. CheckNoError(err);
  1440. rocksdb_transactiondb_put_cf(txn_db, woptions, cfh, "cf_foo", 6, "cf_hello",
  1441. 8, &err);
  1442. CheckNoError(err);
  1443. CheckTxnDBGetCF(txn_db, roptions, cfh, "cf_foo", "cf_hello");
  1444. rocksdb_transactiondb_delete_cf(txn_db, woptions, cfh, "cf_foo", 6, &err);
  1445. CheckNoError(err);
  1446. CheckTxnDBGetCF(txn_db, roptions, cfh, "cf_foo", NULL);
  1447. rocksdb_column_family_handle_destroy(cfh);
  1448. // close and destroy
  1449. rocksdb_transaction_destroy(txn);
  1450. rocksdb_transactiondb_close(txn_db);
  1451. rocksdb_destroy_db(options, dbname, &err);
  1452. CheckNoError(err);
  1453. rocksdb_transaction_options_destroy(txn_options);
  1454. rocksdb_transactiondb_options_destroy(txn_db_options);
  1455. }
  1456. StartPhase("optimistic_transactions");
  1457. {
  1458. rocksdb_options_t* db_options = rocksdb_options_create();
  1459. rocksdb_options_set_create_if_missing(db_options, 1);
  1460. rocksdb_options_set_allow_concurrent_memtable_write(db_options, 1);
  1461. otxn_db = rocksdb_optimistictransactiondb_open(db_options, dbname, &err);
  1462. otxn_options = rocksdb_optimistictransaction_options_create();
  1463. rocksdb_transaction_t* txn1 = rocksdb_optimistictransaction_begin(
  1464. otxn_db, woptions, otxn_options, NULL);
  1465. rocksdb_transaction_t* txn2 = rocksdb_optimistictransaction_begin(
  1466. otxn_db, woptions, otxn_options, NULL);
  1467. rocksdb_transaction_put(txn1, "key", 3, "value", 5, &err);
  1468. CheckNoError(err);
  1469. rocksdb_transaction_put(txn2, "key1", 4, "value1", 6, &err);
  1470. CheckNoError(err);
  1471. CheckTxnGet(txn1, roptions, "key", "value");
  1472. rocksdb_transaction_commit(txn1, &err);
  1473. CheckNoError(err);
  1474. rocksdb_transaction_commit(txn2, &err);
  1475. CheckNoError(err);
  1476. rocksdb_transaction_destroy(txn1);
  1477. rocksdb_transaction_destroy(txn2);
  1478. // Check column family
  1479. db = rocksdb_optimistictransactiondb_get_base_db(otxn_db);
  1480. rocksdb_put(db, woptions, "key", 3, "value", 5, &err);
  1481. CheckNoError(err);
  1482. rocksdb_column_family_handle_t *cfh1, *cfh2;
  1483. cfh1 = rocksdb_create_column_family(db, db_options, "txn_db_cf1", &err);
  1484. cfh2 = rocksdb_create_column_family(db, db_options, "txn_db_cf2", &err);
  1485. txn = rocksdb_optimistictransaction_begin(otxn_db, woptions, otxn_options,
  1486. NULL);
  1487. rocksdb_transaction_put_cf(txn, cfh1, "key_cf1", 7, "val_cf1", 7, &err);
  1488. CheckNoError(err);
  1489. rocksdb_transaction_put_cf(txn, cfh2, "key_cf2", 7, "val_cf2", 7, &err);
  1490. CheckNoError(err);
  1491. rocksdb_transaction_commit(txn, &err);
  1492. CheckNoError(err);
  1493. txn = rocksdb_optimistictransaction_begin(otxn_db, woptions, otxn_options,
  1494. txn);
  1495. CheckGetCF(db, roptions, cfh1, "key_cf1", "val_cf1");
  1496. CheckTxnGetCF(txn, roptions, cfh1, "key_cf1", "val_cf1");
  1497. // Check iterator with column family
  1498. rocksdb_transaction_put_cf(txn, cfh1, "key1_cf", 7, "val1_cf", 7, &err);
  1499. CheckNoError(err);
  1500. rocksdb_iterator_t* iter =
  1501. rocksdb_transaction_create_iterator_cf(txn, roptions, cfh1);
  1502. CheckCondition(!rocksdb_iter_valid(iter));
  1503. rocksdb_iter_seek_to_first(iter);
  1504. CheckCondition(rocksdb_iter_valid(iter));
  1505. CheckIter(iter, "key1_cf", "val1_cf");
  1506. rocksdb_iter_get_error(iter, &err);
  1507. CheckNoError(err);
  1508. rocksdb_iter_destroy(iter);
  1509. rocksdb_transaction_destroy(txn);
  1510. rocksdb_column_family_handle_destroy(cfh1);
  1511. rocksdb_column_family_handle_destroy(cfh2);
  1512. rocksdb_optimistictransactiondb_close_base_db(db);
  1513. rocksdb_optimistictransactiondb_close(otxn_db);
  1514. // Check open optimistic transaction db with column families
  1515. size_t cf_len;
  1516. char** column_fams =
  1517. rocksdb_list_column_families(db_options, dbname, &cf_len, &err);
  1518. CheckNoError(err);
  1519. CheckEqual("default", column_fams[0], 7);
  1520. CheckEqual("txn_db_cf1", column_fams[1], 10);
  1521. CheckEqual("txn_db_cf2", column_fams[2], 10);
  1522. CheckCondition(cf_len == 3);
  1523. rocksdb_list_column_families_destroy(column_fams, cf_len);
  1524. const char* cf_names[3] = {"default", "txn_db_cf1", "txn_db_cf2"};
  1525. rocksdb_options_t* cf_options = rocksdb_options_create();
  1526. const rocksdb_options_t* cf_opts[3] = {cf_options, cf_options, cf_options};
  1527. rocksdb_options_set_error_if_exists(cf_options, 0);
  1528. rocksdb_column_family_handle_t* cf_handles[3];
  1529. otxn_db = rocksdb_optimistictransactiondb_open_column_families(
  1530. db_options, dbname, 3, cf_names, cf_opts, cf_handles, &err);
  1531. CheckNoError(err);
  1532. rocksdb_transaction_t* txn_cf = rocksdb_optimistictransaction_begin(
  1533. otxn_db, woptions, otxn_options, NULL);
  1534. CheckTxnGetCF(txn_cf, roptions, cf_handles[0], "key", "value");
  1535. CheckTxnGetCF(txn_cf, roptions, cf_handles[1], "key_cf1", "val_cf1");
  1536. CheckTxnGetCF(txn_cf, roptions, cf_handles[2], "key_cf2", "val_cf2");
  1537. rocksdb_transaction_destroy(txn_cf);
  1538. rocksdb_options_destroy(cf_options);
  1539. rocksdb_column_family_handle_destroy(cf_handles[0]);
  1540. rocksdb_column_family_handle_destroy(cf_handles[1]);
  1541. rocksdb_column_family_handle_destroy(cf_handles[2]);
  1542. rocksdb_optimistictransactiondb_close(otxn_db);
  1543. rocksdb_destroy_db(db_options, dbname, &err);
  1544. rocksdb_options_destroy(db_options);
  1545. rocksdb_optimistictransaction_options_destroy(otxn_options);
  1546. CheckNoError(err);
  1547. }
  1548. // Simple sanity check that setting memtable rep works.
  1549. StartPhase("memtable_reps");
  1550. {
  1551. // Create database with vector memtable.
  1552. rocksdb_options_set_memtable_vector_rep(options);
  1553. db = rocksdb_open(options, dbname, &err);
  1554. CheckNoError(err);
  1555. // Create database with hash skiplist memtable.
  1556. rocksdb_close(db);
  1557. rocksdb_destroy_db(options, dbname, &err);
  1558. CheckNoError(err);
  1559. rocksdb_options_set_hash_skip_list_rep(options, 5000, 4, 4);
  1560. db = rocksdb_open(options, dbname, &err);
  1561. CheckNoError(err);
  1562. }
  1563. // Check that secondary instance works.
  1564. StartPhase("open_as_secondary");
  1565. {
  1566. rocksdb_close(db);
  1567. rocksdb_destroy_db(options, dbname, &err);
  1568. rocksdb_options_t* db_options = rocksdb_options_create();
  1569. rocksdb_options_set_create_if_missing(db_options, 1);
  1570. db = rocksdb_open(db_options, dbname, &err);
  1571. CheckNoError(err);
  1572. rocksdb_t* db1;
  1573. rocksdb_options_t* opts = rocksdb_options_create();
  1574. rocksdb_options_set_max_open_files(opts, -1);
  1575. rocksdb_options_set_create_if_missing(opts, 1);
  1576. snprintf(secondary_path, sizeof(secondary_path),
  1577. "%s/rocksdb_c_test_secondary-%d", GetTempDir(), ((int)geteuid()));
  1578. db1 = rocksdb_open_as_secondary(opts, dbname, secondary_path, &err);
  1579. CheckNoError(err);
  1580. rocksdb_writeoptions_set_sync(woptions, 0);
  1581. rocksdb_writeoptions_disable_WAL(woptions, 1);
  1582. rocksdb_put(db, woptions, "key0", 4, "value0", 6, &err);
  1583. CheckNoError(err);
  1584. rocksdb_flushoptions_t* flush_opts = rocksdb_flushoptions_create();
  1585. rocksdb_flushoptions_set_wait(flush_opts, 1);
  1586. rocksdb_flush(db, flush_opts, &err);
  1587. CheckNoError(err);
  1588. rocksdb_try_catch_up_with_primary(db1, &err);
  1589. CheckNoError(err);
  1590. rocksdb_readoptions_t* ropts = rocksdb_readoptions_create();
  1591. rocksdb_readoptions_set_verify_checksums(ropts, 1);
  1592. rocksdb_readoptions_set_snapshot(ropts, NULL);
  1593. CheckGet(db, ropts, "key0", "value0");
  1594. CheckGet(db1, ropts, "key0", "value0");
  1595. rocksdb_writeoptions_disable_WAL(woptions, 0);
  1596. rocksdb_put(db, woptions, "key1", 4, "value1", 6, &err);
  1597. CheckNoError(err);
  1598. rocksdb_try_catch_up_with_primary(db1, &err);
  1599. CheckNoError(err);
  1600. CheckGet(db1, ropts, "key0", "value0");
  1601. CheckGet(db1, ropts, "key1", "value1");
  1602. rocksdb_close(db1);
  1603. rocksdb_destroy_db(opts, secondary_path, &err);
  1604. CheckNoError(err);
  1605. rocksdb_options_destroy(db_options);
  1606. rocksdb_options_destroy(opts);
  1607. rocksdb_readoptions_destroy(ropts);
  1608. rocksdb_flushoptions_destroy(flush_opts);
  1609. }
  1610. // Simple sanity check that options setting db_paths work.
  1611. StartPhase("open_db_paths");
  1612. {
  1613. rocksdb_close(db);
  1614. rocksdb_destroy_db(options, dbname, &err);
  1615. const rocksdb_dbpath_t* paths[1] = {dbpath};
  1616. rocksdb_options_set_db_paths(options, paths, 1);
  1617. db = rocksdb_open(options, dbname, &err);
  1618. CheckNoError(err);
  1619. }
  1620. StartPhase("cleanup");
  1621. rocksdb_close(db);
  1622. rocksdb_options_destroy(options);
  1623. rocksdb_block_based_options_destroy(table_options);
  1624. rocksdb_readoptions_destroy(roptions);
  1625. rocksdb_writeoptions_destroy(woptions);
  1626. rocksdb_compactoptions_destroy(coptions);
  1627. rocksdb_cache_destroy(cache);
  1628. rocksdb_comparator_destroy(cmp);
  1629. rocksdb_dbpath_destroy(dbpath);
  1630. rocksdb_env_destroy(env);
  1631. fprintf(stderr, "PASS\n");
  1632. return 0;
  1633. }
  1634. #else
  1635. int main() {
  1636. fprintf(stderr, "SKIPPED\n");
  1637. return 0;
  1638. }
  1639. #endif // !ROCKSDB_LITE