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 
6 #include <stdio.h>
7 
8 #ifndef ROCKSDB_LITE  // Lite does not support C API
9 
10 #include "rocksdb/c.h"
11 
12 #include <stddef.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <sys/types.h>
16 #ifndef OS_WIN
17 #include <unistd.h>
18 #endif
19 #include <inttypes.h>
20 
21 // Can not use port/port.h macros as this is a c file
22 #ifdef OS_WIN
23 #include <windows.h>
24 
25 // Ok for uniqueness
geteuid()26 int geteuid() {
27   int result = 0;
28 
29   result = ((int)GetCurrentProcessId() << 16);
30   result |= (int)GetCurrentThreadId();
31 
32   return result;
33 }
34 
35 // VS < 2015
36 #if defined(_MSC_VER) && (_MSC_VER < 1900)
37 #define snprintf _snprintf
38 #endif
39 
40 #endif
41 
42 const char* phase = "";
43 static char dbname[200];
44 static char sstfilename[200];
45 static char dbbackupname[200];
46 static char dbcheckpointname[200];
47 static char dbpathname[200];
48 static char secondary_path[200];
49 
StartPhase(const char * name)50 static void StartPhase(const char* name) {
51   fprintf(stderr, "=== Test %s\n", name);
52   phase = name;
53 }
54 #ifdef _MSC_VER
55 #pragma warning(push)
56 #pragma warning (disable: 4996) // getenv security warning
57 #endif
GetTempDir(void)58 static const char* GetTempDir(void) {
59     const char* ret = getenv("TEST_TMPDIR");
60     if (ret == NULL || ret[0] == '\0')
61 #ifdef OS_WIN
62       ret = getenv("TEMP");
63 #else
64       ret = "/tmp";
65 #endif
66     return ret;
67 }
68 #ifdef _MSC_VER
69 #pragma warning(pop)
70 #endif
71 
72 #define CheckNoError(err)                                               \
73   if ((err) != NULL) {                                                  \
74     fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, (err)); \
75     abort();                                                            \
76   }
77 
78 #define CheckCondition(cond)                                            \
79   if (!(cond)) {                                                        \
80     fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, #cond); \
81     abort();                                                            \
82   }
83 
CheckEqual(const char * expected,const char * v,size_t n)84 static void CheckEqual(const char* expected, const char* v, size_t n) {
85   if (expected == NULL && v == NULL) {
86     // ok
87   } else if (expected != NULL && v != NULL && n == strlen(expected) &&
88              memcmp(expected, v, n) == 0) {
89     // ok
90     return;
91   } else {
92     fprintf(stderr, "%s: expected '%s', got '%s'\n",
93             phase,
94             (expected ? expected : "(null)"),
95             (v ? v : "(null"));
96     abort();
97   }
98 }
99 
Free(char ** ptr)100 static void Free(char** ptr) {
101   if (*ptr) {
102     free(*ptr);
103     *ptr = NULL;
104   }
105 }
106 
CheckValue(char * err,const char * expected,char ** actual,size_t actual_length)107 static void CheckValue(
108     char* err,
109     const char* expected,
110     char** actual,
111     size_t actual_length) {
112   CheckNoError(err);
113   CheckEqual(expected, *actual, actual_length);
114   Free(actual);
115 }
116 
CheckGet(rocksdb_t * db,const rocksdb_readoptions_t * options,const char * key,const char * expected)117 static void CheckGet(
118     rocksdb_t* db,
119     const rocksdb_readoptions_t* options,
120     const char* key,
121     const char* expected) {
122   char* err = NULL;
123   size_t val_len;
124   char* val;
125   val = rocksdb_get(db, options, key, strlen(key), &val_len, &err);
126   CheckNoError(err);
127   CheckEqual(expected, val, val_len);
128   Free(&val);
129 }
130 
CheckGetCF(rocksdb_t * db,const rocksdb_readoptions_t * options,rocksdb_column_family_handle_t * handle,const char * key,const char * expected)131 static void CheckGetCF(
132     rocksdb_t* db,
133     const rocksdb_readoptions_t* options,
134     rocksdb_column_family_handle_t* handle,
135     const char* key,
136     const char* expected) {
137   char* err = NULL;
138   size_t val_len;
139   char* val;
140   val = rocksdb_get_cf(db, options, handle, key, strlen(key), &val_len, &err);
141   CheckNoError(err);
142   CheckEqual(expected, val, val_len);
143   Free(&val);
144 }
145 
CheckPinGet(rocksdb_t * db,const rocksdb_readoptions_t * options,const char * key,const char * expected)146 static void CheckPinGet(rocksdb_t* db, const rocksdb_readoptions_t* options,
147                         const char* key, const char* expected) {
148   char* err = NULL;
149   size_t val_len;
150   const char* val;
151   rocksdb_pinnableslice_t* p;
152   p = rocksdb_get_pinned(db, options, key, strlen(key), &err);
153   CheckNoError(err);
154   val = rocksdb_pinnableslice_value(p, &val_len);
155   CheckEqual(expected, val, val_len);
156   rocksdb_pinnableslice_destroy(p);
157 }
158 
CheckPinGetCF(rocksdb_t * db,const rocksdb_readoptions_t * options,rocksdb_column_family_handle_t * handle,const char * key,const char * expected)159 static void CheckPinGetCF(rocksdb_t* db, const rocksdb_readoptions_t* options,
160                           rocksdb_column_family_handle_t* handle,
161                           const char* key, const char* expected) {
162   char* err = NULL;
163   size_t val_len;
164   const char* val;
165   rocksdb_pinnableslice_t* p;
166   p = rocksdb_get_pinned_cf(db, options, handle, key, strlen(key), &err);
167   CheckNoError(err);
168   val = rocksdb_pinnableslice_value(p, &val_len);
169   CheckEqual(expected, val, val_len);
170   rocksdb_pinnableslice_destroy(p);
171 }
172 
CheckIter(rocksdb_iterator_t * iter,const char * key,const char * val)173 static void CheckIter(rocksdb_iterator_t* iter,
174                       const char* key, const char* val) {
175   size_t len;
176   const char* str;
177   str = rocksdb_iter_key(iter, &len);
178   CheckEqual(key, str, len);
179   str = rocksdb_iter_value(iter, &len);
180   CheckEqual(val, str, len);
181 }
182 
183 // Callback from rocksdb_writebatch_iterate()
CheckPut(void * ptr,const char * k,size_t klen,const char * v,size_t vlen)184 static void CheckPut(void* ptr,
185                      const char* k, size_t klen,
186                      const char* v, size_t vlen) {
187   int* state = (int*) ptr;
188   CheckCondition(*state < 2);
189   switch (*state) {
190     case 0:
191       CheckEqual("bar", k, klen);
192       CheckEqual("b", v, vlen);
193       break;
194     case 1:
195       CheckEqual("box", k, klen);
196       CheckEqual("c", v, vlen);
197       break;
198   }
199   (*state)++;
200 }
201 
202 // Callback from rocksdb_writebatch_iterate()
CheckDel(void * ptr,const char * k,size_t klen)203 static void CheckDel(void* ptr, const char* k, size_t klen) {
204   int* state = (int*) ptr;
205   CheckCondition(*state == 2);
206   CheckEqual("bar", k, klen);
207   (*state)++;
208 }
209 
CmpDestroy(void * arg)210 static void CmpDestroy(void* arg) { (void)arg; }
211 
CmpCompare(void * arg,const char * a,size_t alen,const char * b,size_t blen)212 static int CmpCompare(void* arg, const char* a, size_t alen,
213                       const char* b, size_t blen) {
214   (void)arg;
215   size_t n = (alen < blen) ? alen : blen;
216   int r = memcmp(a, b, n);
217   if (r == 0) {
218     if (alen < blen) r = -1;
219     else if (alen > blen) r = +1;
220   }
221   return r;
222 }
223 
CmpName(void * arg)224 static const char* CmpName(void* arg) {
225   (void)arg;
226   return "foo";
227 }
228 
229 // Custom filter policy
230 static unsigned char fake_filter_result = 1;
FilterDestroy(void * arg)231 static void FilterDestroy(void* arg) { (void)arg; }
FilterName(void * arg)232 static const char* FilterName(void* arg) {
233   (void)arg;
234   return "TestFilter";
235 }
FilterCreate(void * arg,const char * const * key_array,const size_t * key_length_array,int num_keys,size_t * filter_length)236 static char* FilterCreate(
237     void* arg,
238     const char* const* key_array, const size_t* key_length_array,
239     int num_keys,
240     size_t* filter_length) {
241   (void)arg;
242   (void)key_array;
243   (void)key_length_array;
244   (void)num_keys;
245   *filter_length = 4;
246   char* result = malloc(4);
247   memcpy(result, "fake", 4);
248   return result;
249 }
FilterKeyMatch(void * arg,const char * key,size_t length,const char * filter,size_t filter_length)250 static unsigned char FilterKeyMatch(
251     void* arg,
252     const char* key, size_t length,
253     const char* filter, size_t filter_length) {
254   (void)arg;
255   (void)key;
256   (void)length;
257   CheckCondition(filter_length == 4);
258   CheckCondition(memcmp(filter, "fake", 4) == 0);
259   return fake_filter_result;
260 }
261 
262 // Custom compaction filter
CFilterDestroy(void * arg)263 static void CFilterDestroy(void* arg) { (void)arg; }
CFilterName(void * arg)264 static const char* CFilterName(void* arg) {
265   (void)arg;
266   return "foo";
267 }
CFilterFilter(void * arg,int level,const char * key,size_t key_length,const char * existing_value,size_t value_length,char ** new_value,size_t * new_value_length,unsigned char * value_changed)268 static unsigned char CFilterFilter(void* arg, int level, const char* key,
269                                    size_t key_length,
270                                    const char* existing_value,
271                                    size_t value_length, char** new_value,
272                                    size_t* new_value_length,
273                                    unsigned char* value_changed) {
274   (void)arg;
275   (void)level;
276   (void)existing_value;
277   (void)value_length;
278   if (key_length == 3) {
279     if (memcmp(key, "bar", key_length) == 0) {
280       return 1;
281     } else if (memcmp(key, "baz", key_length) == 0) {
282       *value_changed = 1;
283       *new_value = "newbazvalue";
284       *new_value_length = 11;
285       return 0;
286     }
287   }
288   return 0;
289 }
290 
CFilterFactoryDestroy(void * arg)291 static void CFilterFactoryDestroy(void* arg) { (void)arg; }
CFilterFactoryName(void * arg)292 static const char* CFilterFactoryName(void* arg) {
293   (void)arg;
294   return "foo";
295 }
CFilterCreate(void * arg,rocksdb_compactionfiltercontext_t * context)296 static rocksdb_compactionfilter_t* CFilterCreate(
297     void* arg, rocksdb_compactionfiltercontext_t* context) {
298   (void)arg;
299   (void)context;
300   return rocksdb_compactionfilter_create(NULL, CFilterDestroy, CFilterFilter,
301                                          CFilterName);
302 }
303 
CheckCompaction(rocksdb_t * db,rocksdb_options_t * options,rocksdb_readoptions_t * roptions,rocksdb_writeoptions_t * woptions)304 static rocksdb_t* CheckCompaction(rocksdb_t* db, rocksdb_options_t* options,
305                                   rocksdb_readoptions_t* roptions,
306                                   rocksdb_writeoptions_t* woptions) {
307   char* err = NULL;
308   db = rocksdb_open(options, dbname, &err);
309   CheckNoError(err);
310   rocksdb_put(db, woptions, "foo", 3, "foovalue", 8, &err);
311   CheckNoError(err);
312   CheckGet(db, roptions, "foo", "foovalue");
313   rocksdb_put(db, woptions, "bar", 3, "barvalue", 8, &err);
314   CheckNoError(err);
315   CheckGet(db, roptions, "bar", "barvalue");
316   rocksdb_put(db, woptions, "baz", 3, "bazvalue", 8, &err);
317   CheckNoError(err);
318   CheckGet(db, roptions, "baz", "bazvalue");
319 
320   // Force compaction
321   rocksdb_compact_range(db, NULL, 0, NULL, 0);
322   // should have filtered bar, but not foo
323   CheckGet(db, roptions, "foo", "foovalue");
324   CheckGet(db, roptions, "bar", NULL);
325   CheckGet(db, roptions, "baz", "newbazvalue");
326   return db;
327 }
328 
329 // Custom merge operator
MergeOperatorDestroy(void * arg)330 static void MergeOperatorDestroy(void* arg) { (void)arg; }
MergeOperatorName(void * arg)331 static const char* MergeOperatorName(void* arg) {
332   (void)arg;
333   return "TestMergeOperator";
334 }
MergeOperatorFullMerge(void * arg,const char * key,size_t key_length,const char * existing_value,size_t existing_value_length,const char * const * operands_list,const size_t * operands_list_length,int num_operands,unsigned char * success,size_t * new_value_length)335 static char* MergeOperatorFullMerge(
336     void* arg,
337     const char* key, size_t key_length,
338     const char* existing_value, size_t existing_value_length,
339     const char* const* operands_list, const size_t* operands_list_length,
340     int num_operands,
341     unsigned char* success, size_t* new_value_length) {
342   (void)arg;
343   (void)key;
344   (void)key_length;
345   (void)existing_value;
346   (void)existing_value_length;
347   (void)operands_list;
348   (void)operands_list_length;
349   (void)num_operands;
350   *new_value_length = 4;
351   *success = 1;
352   char* result = malloc(4);
353   memcpy(result, "fake", 4);
354   return result;
355 }
MergeOperatorPartialMerge(void * arg,const char * key,size_t key_length,const char * const * operands_list,const size_t * operands_list_length,int num_operands,unsigned char * success,size_t * new_value_length)356 static char* MergeOperatorPartialMerge(
357     void* arg,
358     const char* key, size_t key_length,
359     const char* const* operands_list, const size_t* operands_list_length,
360     int num_operands,
361     unsigned char* success, size_t* new_value_length) {
362   (void)arg;
363   (void)key;
364   (void)key_length;
365   (void)operands_list;
366   (void)operands_list_length;
367   (void)num_operands;
368   *new_value_length = 4;
369   *success = 1;
370   char* result = malloc(4);
371   memcpy(result, "fake", 4);
372   return result;
373 }
374 
CheckTxnGet(rocksdb_transaction_t * txn,const rocksdb_readoptions_t * options,const char * key,const char * expected)375 static void CheckTxnGet(
376         rocksdb_transaction_t* txn,
377         const rocksdb_readoptions_t* options,
378         const char* key,
379         const char* expected) {
380         char* err = NULL;
381         size_t val_len;
382         char* val;
383         val = rocksdb_transaction_get(txn, options, key, strlen(key), &val_len, &err);
384         CheckNoError(err);
385         CheckEqual(expected, val, val_len);
386         Free(&val);
387 }
388 
CheckTxnGetCF(rocksdb_transaction_t * txn,const rocksdb_readoptions_t * options,rocksdb_column_family_handle_t * column_family,const char * key,const char * expected)389 static void CheckTxnGetCF(rocksdb_transaction_t* txn,
390                           const rocksdb_readoptions_t* options,
391                           rocksdb_column_family_handle_t* column_family,
392                           const char* key, const char* expected) {
393   char* err = NULL;
394   size_t val_len;
395   char* val;
396   val = rocksdb_transaction_get_cf(txn, options, column_family, key,
397                                    strlen(key), &val_len, &err);
398   CheckNoError(err);
399   CheckEqual(expected, val, val_len);
400   Free(&val);
401 }
402 
CheckTxnDBGet(rocksdb_transactiondb_t * txn_db,const rocksdb_readoptions_t * options,const char * key,const char * expected)403 static void CheckTxnDBGet(
404         rocksdb_transactiondb_t* txn_db,
405         const rocksdb_readoptions_t* options,
406         const char* key,
407         const char* expected) {
408         char* err = NULL;
409         size_t val_len;
410         char* val;
411         val = rocksdb_transactiondb_get(txn_db, options, key, strlen(key), &val_len, &err);
412         CheckNoError(err);
413         CheckEqual(expected, val, val_len);
414         Free(&val);
415 }
416 
CheckTxnDBGetCF(rocksdb_transactiondb_t * txn_db,const rocksdb_readoptions_t * options,rocksdb_column_family_handle_t * column_family,const char * key,const char * expected)417 static void CheckTxnDBGetCF(rocksdb_transactiondb_t* txn_db,
418                             const rocksdb_readoptions_t* options,
419                             rocksdb_column_family_handle_t* column_family,
420                             const char* key, const char* expected) {
421   char* err = NULL;
422   size_t val_len;
423   char* val;
424   val = rocksdb_transactiondb_get_cf(txn_db, options, column_family, key,
425                                      strlen(key), &val_len, &err);
426   CheckNoError(err);
427   CheckEqual(expected, val, val_len);
428   Free(&val);
429 }
430 
main(int argc,char ** argv)431 int main(int argc, char** argv) {
432   (void)argc;
433   (void)argv;
434   rocksdb_t* db;
435   rocksdb_comparator_t* cmp;
436   rocksdb_cache_t* cache;
437   rocksdb_dbpath_t *dbpath;
438   rocksdb_env_t* env;
439   rocksdb_options_t* options;
440   rocksdb_compactoptions_t* coptions;
441   rocksdb_block_based_table_options_t* table_options;
442   rocksdb_readoptions_t* roptions;
443   rocksdb_writeoptions_t* woptions;
444   rocksdb_ratelimiter_t* rate_limiter;
445   rocksdb_transactiondb_t* txn_db;
446   rocksdb_transactiondb_options_t* txn_db_options;
447   rocksdb_transaction_t* txn;
448   rocksdb_transaction_options_t* txn_options;
449   rocksdb_optimistictransactiondb_t* otxn_db;
450   rocksdb_optimistictransaction_options_t* otxn_options;
451   char* err = NULL;
452   int run = -1;
453 
454   snprintf(dbname, sizeof(dbname),
455            "%s/rocksdb_c_test-%d",
456            GetTempDir(),
457            ((int) geteuid()));
458 
459   snprintf(dbbackupname, sizeof(dbbackupname),
460            "%s/rocksdb_c_test-%d-backup",
461            GetTempDir(),
462            ((int) geteuid()));
463 
464   snprintf(dbcheckpointname, sizeof(dbcheckpointname),
465            "%s/rocksdb_c_test-%d-checkpoint",
466            GetTempDir(),
467            ((int) geteuid()));
468 
469   snprintf(sstfilename, sizeof(sstfilename),
470            "%s/rocksdb_c_test-%d-sst",
471            GetTempDir(),
472            ((int)geteuid()));
473 
474   snprintf(dbpathname, sizeof(dbpathname),
475            "%s/rocksdb_c_test-%d-dbpath",
476            GetTempDir(),
477            ((int) geteuid()));
478 
479   StartPhase("create_objects");
480   cmp = rocksdb_comparator_create(NULL, CmpDestroy, CmpCompare, CmpName);
481   dbpath = rocksdb_dbpath_create(dbpathname, 1024 * 1024);
482   env = rocksdb_create_default_env();
483   cache = rocksdb_cache_create_lru(100000);
484 
485   options = rocksdb_options_create();
486   rocksdb_options_set_comparator(options, cmp);
487   rocksdb_options_set_error_if_exists(options, 1);
488   rocksdb_options_set_env(options, env);
489   rocksdb_options_set_info_log(options, NULL);
490   rocksdb_options_set_write_buffer_size(options, 100000);
491   rocksdb_options_set_paranoid_checks(options, 1);
492   rocksdb_options_set_max_open_files(options, 10);
493   rocksdb_options_set_base_background_compactions(options, 1);
494 
495   table_options = rocksdb_block_based_options_create();
496   rocksdb_block_based_options_set_block_cache(table_options, cache);
497   rocksdb_block_based_options_set_data_block_index_type(table_options, 1);
498   rocksdb_block_based_options_set_data_block_hash_ratio(table_options, 0.75);
499   rocksdb_options_set_block_based_table_factory(options, table_options);
500 
501   rocksdb_options_set_compression(options, rocksdb_no_compression);
502   rocksdb_options_set_compression_options(options, -14, -1, 0, 0);
503   int compression_levels[] = {rocksdb_no_compression, rocksdb_no_compression,
504                               rocksdb_no_compression, rocksdb_no_compression};
505   rocksdb_options_set_compression_per_level(options, compression_levels, 4);
506   rate_limiter = rocksdb_ratelimiter_create(1000 * 1024 * 1024, 100 * 1000, 10);
507   rocksdb_options_set_ratelimiter(options, rate_limiter);
508   rocksdb_ratelimiter_destroy(rate_limiter);
509 
510   roptions = rocksdb_readoptions_create();
511   rocksdb_readoptions_set_verify_checksums(roptions, 1);
512   rocksdb_readoptions_set_fill_cache(roptions, 1);
513 
514   woptions = rocksdb_writeoptions_create();
515   rocksdb_writeoptions_set_sync(woptions, 1);
516 
517   coptions = rocksdb_compactoptions_create();
518   rocksdb_compactoptions_set_exclusive_manual_compaction(coptions, 1);
519 
520   rocksdb_options_add_compact_on_deletion_collector_factory(options, 10000,
521                                                             10001);
522 
523   StartPhase("destroy");
524   rocksdb_destroy_db(options, dbname, &err);
525   Free(&err);
526 
527   StartPhase("open_error");
528   rocksdb_open(options, dbname, &err);
529   CheckCondition(err != NULL);
530   Free(&err);
531 
532   StartPhase("open");
533   rocksdb_options_set_create_if_missing(options, 1);
534   db = rocksdb_open(options, dbname, &err);
535   CheckNoError(err);
536   CheckGet(db, roptions, "foo", NULL);
537 
538   StartPhase("put");
539   rocksdb_put(db, woptions, "foo", 3, "hello", 5, &err);
540   CheckNoError(err);
541   CheckGet(db, roptions, "foo", "hello");
542 
543   StartPhase("backup_and_restore");
544   {
545     rocksdb_destroy_db(options, dbbackupname, &err);
546     CheckNoError(err);
547 
548     rocksdb_backup_engine_t *be = rocksdb_backup_engine_open(options, dbbackupname, &err);
549     CheckNoError(err);
550 
551     rocksdb_backup_engine_create_new_backup(be, db, &err);
552     CheckNoError(err);
553 
554     // need a change to trigger a new backup
555     rocksdb_delete(db, woptions, "does-not-exist", 14, &err);
556     CheckNoError(err);
557 
558     rocksdb_backup_engine_create_new_backup(be, db, &err);
559     CheckNoError(err);
560 
561     const rocksdb_backup_engine_info_t* bei = rocksdb_backup_engine_get_backup_info(be);
562     CheckCondition(rocksdb_backup_engine_info_count(bei) > 1);
563     rocksdb_backup_engine_info_destroy(bei);
564 
565     rocksdb_backup_engine_purge_old_backups(be, 1, &err);
566     CheckNoError(err);
567 
568     bei = rocksdb_backup_engine_get_backup_info(be);
569     CheckCondition(rocksdb_backup_engine_info_count(bei) == 1);
570     rocksdb_backup_engine_info_destroy(bei);
571 
572     rocksdb_delete(db, woptions, "foo", 3, &err);
573     CheckNoError(err);
574 
575     rocksdb_close(db);
576 
577     rocksdb_destroy_db(options, dbname, &err);
578     CheckNoError(err);
579 
580     rocksdb_restore_options_t *restore_options = rocksdb_restore_options_create();
581     rocksdb_restore_options_set_keep_log_files(restore_options, 0);
582     rocksdb_backup_engine_restore_db_from_latest_backup(be, dbname, dbname, restore_options, &err);
583     CheckNoError(err);
584     rocksdb_restore_options_destroy(restore_options);
585 
586     rocksdb_options_set_error_if_exists(options, 0);
587     db = rocksdb_open(options, dbname, &err);
588     CheckNoError(err);
589     rocksdb_options_set_error_if_exists(options, 1);
590 
591     CheckGet(db, roptions, "foo", "hello");
592 
593     rocksdb_backup_engine_close(be);
594   }
595 
596   StartPhase("checkpoint");
597   {
598     rocksdb_destroy_db(options, dbcheckpointname, &err);
599     CheckNoError(err);
600 
601     rocksdb_checkpoint_t* checkpoint = rocksdb_checkpoint_object_create(db, &err);
602     CheckNoError(err);
603 
604     rocksdb_checkpoint_create(checkpoint, dbcheckpointname, 0, &err);
605     CheckNoError(err);
606 
607     // start a new database from the checkpoint
608     rocksdb_close(db);
609     rocksdb_options_set_error_if_exists(options, 0);
610     db = rocksdb_open(options, dbcheckpointname, &err);
611     CheckNoError(err);
612 
613     CheckGet(db, roptions, "foo", "hello");
614 
615     rocksdb_checkpoint_object_destroy(checkpoint);
616 
617     rocksdb_close(db);
618     rocksdb_destroy_db(options, dbcheckpointname, &err);
619     CheckNoError(err);
620 
621     db = rocksdb_open(options, dbname, &err);
622     CheckNoError(err);
623     rocksdb_options_set_error_if_exists(options, 1);
624   }
625 
626   StartPhase("compactall");
627   rocksdb_compact_range(db, NULL, 0, NULL, 0);
628   CheckGet(db, roptions, "foo", "hello");
629 
630   StartPhase("compactrange");
631   rocksdb_compact_range(db, "a", 1, "z", 1);
632   CheckGet(db, roptions, "foo", "hello");
633 
634   StartPhase("compactallopt");
635   rocksdb_compact_range_opt(db, coptions, NULL, 0, NULL, 0);
636   CheckGet(db, roptions, "foo", "hello");
637 
638   StartPhase("compactrangeopt");
639   rocksdb_compact_range_opt(db, coptions, "a", 1, "z", 1);
640   CheckGet(db, roptions, "foo", "hello");
641 
642   // Simple check cache usage
643   StartPhase("cache_usage");
644   {
645     rocksdb_readoptions_set_pin_data(roptions, 1);
646     rocksdb_iterator_t* iter = rocksdb_create_iterator(db, roptions);
647     rocksdb_iter_seek(iter, "foo", 3);
648 
649     size_t usage = rocksdb_cache_get_usage(cache);
650     CheckCondition(usage > 0);
651 
652     size_t pin_usage = rocksdb_cache_get_pinned_usage(cache);
653     CheckCondition(pin_usage > 0);
654 
655     rocksdb_iter_next(iter);
656     rocksdb_iter_destroy(iter);
657     rocksdb_readoptions_set_pin_data(roptions, 0);
658   }
659 
660   StartPhase("addfile");
661   {
662     rocksdb_envoptions_t* env_opt = rocksdb_envoptions_create();
663     rocksdb_options_t* io_options = rocksdb_options_create();
664     rocksdb_sstfilewriter_t* writer =
665         rocksdb_sstfilewriter_create(env_opt, io_options);
666 
667     remove(sstfilename);
668     rocksdb_sstfilewriter_open(writer, sstfilename, &err);
669     CheckNoError(err);
670     rocksdb_sstfilewriter_put(writer, "sstk1", 5, "v1", 2, &err);
671     CheckNoError(err);
672     rocksdb_sstfilewriter_put(writer, "sstk2", 5, "v2", 2, &err);
673     CheckNoError(err);
674     rocksdb_sstfilewriter_put(writer, "sstk3", 5, "v3", 2, &err);
675     CheckNoError(err);
676     rocksdb_sstfilewriter_finish(writer, &err);
677     CheckNoError(err);
678 
679     rocksdb_ingestexternalfileoptions_t* ing_opt =
680         rocksdb_ingestexternalfileoptions_create();
681     const char* file_list[1] = {sstfilename};
682     rocksdb_ingest_external_file(db, file_list, 1, ing_opt, &err);
683     CheckNoError(err);
684     CheckGet(db, roptions, "sstk1", "v1");
685     CheckGet(db, roptions, "sstk2", "v2");
686     CheckGet(db, roptions, "sstk3", "v3");
687 
688     remove(sstfilename);
689     rocksdb_sstfilewriter_open(writer, sstfilename, &err);
690     CheckNoError(err);
691     rocksdb_sstfilewriter_put(writer, "sstk2", 5, "v4", 2, &err);
692     CheckNoError(err);
693     rocksdb_sstfilewriter_put(writer, "sstk22", 6, "v5", 2, &err);
694     CheckNoError(err);
695     rocksdb_sstfilewriter_put(writer, "sstk3", 5, "v6", 2, &err);
696     CheckNoError(err);
697     rocksdb_sstfilewriter_finish(writer, &err);
698     CheckNoError(err);
699 
700     rocksdb_ingest_external_file(db, file_list, 1, ing_opt, &err);
701     CheckNoError(err);
702     CheckGet(db, roptions, "sstk1", "v1");
703     CheckGet(db, roptions, "sstk2", "v4");
704     CheckGet(db, roptions, "sstk22", "v5");
705     CheckGet(db, roptions, "sstk3", "v6");
706 
707     rocksdb_ingestexternalfileoptions_destroy(ing_opt);
708     rocksdb_sstfilewriter_destroy(writer);
709     rocksdb_options_destroy(io_options);
710     rocksdb_envoptions_destroy(env_opt);
711 
712     // Delete all keys we just ingested
713     rocksdb_delete(db, woptions, "sstk1", 5, &err);
714     CheckNoError(err);
715     rocksdb_delete(db, woptions, "sstk2", 5, &err);
716     CheckNoError(err);
717     rocksdb_delete(db, woptions, "sstk22", 6, &err);
718     CheckNoError(err);
719     rocksdb_delete(db, woptions, "sstk3", 5, &err);
720     CheckNoError(err);
721   }
722 
723   StartPhase("writebatch");
724   {
725     rocksdb_writebatch_t* wb = rocksdb_writebatch_create();
726     rocksdb_writebatch_put(wb, "foo", 3, "a", 1);
727     rocksdb_writebatch_clear(wb);
728     rocksdb_writebatch_put(wb, "bar", 3, "b", 1);
729     rocksdb_writebatch_put(wb, "box", 3, "c", 1);
730     rocksdb_writebatch_delete(wb, "bar", 3);
731     rocksdb_write(db, woptions, wb, &err);
732     CheckNoError(err);
733     CheckGet(db, roptions, "foo", "hello");
734     CheckGet(db, roptions, "bar", NULL);
735     CheckGet(db, roptions, "box", "c");
736     int pos = 0;
737     rocksdb_writebatch_iterate(wb, &pos, CheckPut, CheckDel);
738     CheckCondition(pos == 3);
739     rocksdb_writebatch_clear(wb);
740     rocksdb_writebatch_put(wb, "bar", 3, "b", 1);
741     rocksdb_writebatch_put(wb, "bay", 3, "d", 1);
742     rocksdb_writebatch_delete_range(wb, "bar", 3, "bay", 3);
743     rocksdb_write(db, woptions, wb, &err);
744     CheckNoError(err);
745     CheckGet(db, roptions, "bar", NULL);
746     CheckGet(db, roptions, "bay", "d");
747     rocksdb_writebatch_clear(wb);
748     const char* start_list[1] = {"bay"};
749     const size_t start_sizes[1] = {3};
750     const char* end_list[1] = {"baz"};
751     const size_t end_sizes[1] = {3};
752     rocksdb_writebatch_delete_rangev(wb, 1, start_list, start_sizes, end_list,
753                                      end_sizes);
754     rocksdb_write(db, woptions, wb, &err);
755     CheckNoError(err);
756     CheckGet(db, roptions, "bay", NULL);
757     rocksdb_writebatch_destroy(wb);
758   }
759 
760   StartPhase("writebatch_vectors");
761   {
762     rocksdb_writebatch_t* wb = rocksdb_writebatch_create();
763     const char* k_list[2] = { "z", "ap" };
764     const size_t k_sizes[2] = { 1, 2 };
765     const char* v_list[3] = { "x", "y", "z" };
766     const size_t v_sizes[3] = { 1, 1, 1 };
767     rocksdb_writebatch_putv(wb, 2, k_list, k_sizes, 3, v_list, v_sizes);
768     rocksdb_write(db, woptions, wb, &err);
769     CheckNoError(err);
770     CheckGet(db, roptions, "zap", "xyz");
771     rocksdb_writebatch_delete(wb, "zap", 3);
772     rocksdb_write(db, woptions, wb, &err);
773     CheckNoError(err);
774     CheckGet(db, roptions, "zap", NULL);
775     rocksdb_writebatch_destroy(wb);
776   }
777 
778   StartPhase("writebatch_savepoint");
779   {
780     rocksdb_writebatch_t* wb = rocksdb_writebatch_create();
781     rocksdb_writebatch_set_save_point(wb);
782     rocksdb_writebatch_set_save_point(wb);
783     const char* k_list[2] = {"z", "ap"};
784     const size_t k_sizes[2] = {1, 2};
785     const char* v_list[3] = {"x", "y", "z"};
786     const size_t v_sizes[3] = {1, 1, 1};
787     rocksdb_writebatch_pop_save_point(wb, &err);
788     CheckNoError(err);
789     rocksdb_writebatch_putv(wb, 2, k_list, k_sizes, 3, v_list, v_sizes);
790     rocksdb_writebatch_rollback_to_save_point(wb, &err);
791     CheckNoError(err);
792     rocksdb_write(db, woptions, wb, &err);
793     CheckNoError(err);
794     CheckGet(db, roptions, "zap", NULL);
795     rocksdb_writebatch_destroy(wb);
796   }
797 
798   StartPhase("writebatch_rep");
799   {
800     rocksdb_writebatch_t* wb1 = rocksdb_writebatch_create();
801     rocksdb_writebatch_put(wb1, "baz", 3, "d", 1);
802     rocksdb_writebatch_put(wb1, "quux", 4, "e", 1);
803     rocksdb_writebatch_delete(wb1, "quux", 4);
804     size_t repsize1 = 0;
805     const char* rep = rocksdb_writebatch_data(wb1, &repsize1);
806     rocksdb_writebatch_t* wb2 = rocksdb_writebatch_create_from(rep, repsize1);
807     CheckCondition(rocksdb_writebatch_count(wb1) ==
808                    rocksdb_writebatch_count(wb2));
809     size_t repsize2 = 0;
810     CheckCondition(
811         memcmp(rep, rocksdb_writebatch_data(wb2, &repsize2), repsize1) == 0);
812     rocksdb_writebatch_destroy(wb1);
813     rocksdb_writebatch_destroy(wb2);
814   }
815 
816   StartPhase("writebatch_wi");
817   {
818     rocksdb_writebatch_wi_t* wbi = rocksdb_writebatch_wi_create(0, 1);
819     rocksdb_writebatch_wi_put(wbi, "foo", 3, "a", 1);
820     rocksdb_writebatch_wi_clear(wbi);
821     rocksdb_writebatch_wi_put(wbi, "bar", 3, "b", 1);
822     rocksdb_writebatch_wi_put(wbi, "box", 3, "c", 1);
823     rocksdb_writebatch_wi_delete(wbi, "bar", 3);
824     int count = rocksdb_writebatch_wi_count(wbi);
825     CheckCondition(count == 3);
826     size_t size;
827     char* value;
828     value = rocksdb_writebatch_wi_get_from_batch(wbi, options, "box", 3, &size, &err);
829     CheckValue(err, "c", &value, size);
830     value = rocksdb_writebatch_wi_get_from_batch(wbi, options, "bar", 3, &size, &err);
831     CheckValue(err, NULL, &value, size);
832     value = rocksdb_writebatch_wi_get_from_batch_and_db(wbi, db, roptions, "foo", 3, &size, &err);
833     CheckValue(err, "hello", &value, size);
834     value = rocksdb_writebatch_wi_get_from_batch_and_db(wbi, db, roptions, "box", 3, &size, &err);
835     CheckValue(err, "c", &value, size);
836     rocksdb_write_writebatch_wi(db, woptions, wbi, &err);
837     CheckNoError(err);
838     CheckGet(db, roptions, "foo", "hello");
839     CheckGet(db, roptions, "bar", NULL);
840     CheckGet(db, roptions, "box", "c");
841     int pos = 0;
842     rocksdb_writebatch_wi_iterate(wbi, &pos, CheckPut, CheckDel);
843     CheckCondition(pos == 3);
844     rocksdb_writebatch_wi_clear(wbi);
845     rocksdb_writebatch_wi_destroy(wbi);
846   }
847 
848   StartPhase("writebatch_wi_vectors");
849   {
850     rocksdb_writebatch_wi_t* wb = rocksdb_writebatch_wi_create(0, 1);
851     const char* k_list[2] = { "z", "ap" };
852     const size_t k_sizes[2] = { 1, 2 };
853     const char* v_list[3] = { "x", "y", "z" };
854     const size_t v_sizes[3] = { 1, 1, 1 };
855     rocksdb_writebatch_wi_putv(wb, 2, k_list, k_sizes, 3, v_list, v_sizes);
856     rocksdb_write_writebatch_wi(db, woptions, wb, &err);
857     CheckNoError(err);
858     CheckGet(db, roptions, "zap", "xyz");
859     rocksdb_writebatch_wi_delete(wb, "zap", 3);
860     rocksdb_write_writebatch_wi(db, woptions, wb, &err);
861     CheckNoError(err);
862     CheckGet(db, roptions, "zap", NULL);
863     rocksdb_writebatch_wi_destroy(wb);
864   }
865 
866   StartPhase("writebatch_wi_savepoint");
867   {
868     rocksdb_writebatch_wi_t* wb = rocksdb_writebatch_wi_create(0, 1);
869     rocksdb_writebatch_wi_set_save_point(wb);
870     const char* k_list[2] = {"z", "ap"};
871     const size_t k_sizes[2] = {1, 2};
872     const char* v_list[3] = {"x", "y", "z"};
873     const size_t v_sizes[3] = {1, 1, 1};
874     rocksdb_writebatch_wi_putv(wb, 2, k_list, k_sizes, 3, v_list, v_sizes);
875     rocksdb_writebatch_wi_rollback_to_save_point(wb, &err);
876     CheckNoError(err);
877     rocksdb_write_writebatch_wi(db, woptions, wb, &err);
878     CheckNoError(err);
879     CheckGet(db, roptions, "zap", NULL);
880     rocksdb_writebatch_wi_destroy(wb);
881   }
882 
883   StartPhase("iter");
884   {
885     rocksdb_iterator_t* iter = rocksdb_create_iterator(db, roptions);
886     CheckCondition(!rocksdb_iter_valid(iter));
887     rocksdb_iter_seek_to_first(iter);
888     CheckCondition(rocksdb_iter_valid(iter));
889     CheckIter(iter, "box", "c");
890     rocksdb_iter_next(iter);
891     CheckIter(iter, "foo", "hello");
892     rocksdb_iter_prev(iter);
893     CheckIter(iter, "box", "c");
894     rocksdb_iter_prev(iter);
895     CheckCondition(!rocksdb_iter_valid(iter));
896     rocksdb_iter_seek_to_last(iter);
897     CheckIter(iter, "foo", "hello");
898     rocksdb_iter_seek(iter, "b", 1);
899     CheckIter(iter, "box", "c");
900     rocksdb_iter_seek_for_prev(iter, "g", 1);
901     CheckIter(iter, "foo", "hello");
902     rocksdb_iter_seek_for_prev(iter, "box", 3);
903     CheckIter(iter, "box", "c");
904     rocksdb_iter_get_error(iter, &err);
905     CheckNoError(err);
906     rocksdb_iter_destroy(iter);
907   }
908 
909   StartPhase("wbwi_iter");
910   {
911     rocksdb_iterator_t* base_iter = rocksdb_create_iterator(db, roptions);
912     rocksdb_writebatch_wi_t* wbi = rocksdb_writebatch_wi_create(0, 1);
913     rocksdb_writebatch_wi_put(wbi, "bar", 3, "b", 1);
914     rocksdb_writebatch_wi_delete(wbi, "foo", 3);
915     rocksdb_iterator_t* iter =
916         rocksdb_writebatch_wi_create_iterator_with_base(wbi, base_iter);
917     CheckCondition(!rocksdb_iter_valid(iter));
918     rocksdb_iter_seek_to_first(iter);
919     CheckCondition(rocksdb_iter_valid(iter));
920     CheckIter(iter, "bar", "b");
921     rocksdb_iter_next(iter);
922     CheckIter(iter, "box", "c");
923     rocksdb_iter_prev(iter);
924     CheckIter(iter, "bar", "b");
925     rocksdb_iter_prev(iter);
926     CheckCondition(!rocksdb_iter_valid(iter));
927     rocksdb_iter_seek_to_last(iter);
928     CheckIter(iter, "box", "c");
929     rocksdb_iter_seek(iter, "b", 1);
930     CheckIter(iter, "bar", "b");
931     rocksdb_iter_seek_for_prev(iter, "c", 1);
932     CheckIter(iter, "box", "c");
933     rocksdb_iter_seek_for_prev(iter, "box", 3);
934     CheckIter(iter, "box", "c");
935     rocksdb_iter_get_error(iter, &err);
936     CheckNoError(err);
937     rocksdb_iter_destroy(iter);
938     rocksdb_writebatch_wi_destroy(wbi);
939   }
940 
941   StartPhase("multiget");
942   {
943     const char* keys[3] = { "box", "foo", "notfound" };
944     const size_t keys_sizes[3] = { 3, 3, 8 };
945     char* vals[3];
946     size_t vals_sizes[3];
947     char* errs[3];
948     rocksdb_multi_get(db, roptions, 3, keys, keys_sizes, vals, vals_sizes, errs);
949 
950     int i;
951     for (i = 0; i < 3; i++) {
952       CheckEqual(NULL, errs[i], 0);
953       switch (i) {
954       case 0:
955         CheckEqual("c", vals[i], vals_sizes[i]);
956         break;
957       case 1:
958         CheckEqual("hello", vals[i], vals_sizes[i]);
959         break;
960       case 2:
961         CheckEqual(NULL, vals[i], vals_sizes[i]);
962         break;
963       }
964       Free(&vals[i]);
965     }
966   }
967 
968   StartPhase("pin_get");
969   {
970     CheckPinGet(db, roptions, "box", "c");
971     CheckPinGet(db, roptions, "foo", "hello");
972     CheckPinGet(db, roptions, "notfound", NULL);
973   }
974 
975   StartPhase("approximate_sizes");
976   {
977     int i;
978     int n = 20000;
979     char keybuf[100];
980     char valbuf[100];
981     uint64_t sizes[2];
982     const char* start[2] = { "a", "k00000000000000010000" };
983     size_t start_len[2] = { 1, 21 };
984     const char* limit[2] = { "k00000000000000010000", "z" };
985     size_t limit_len[2] = { 21, 1 };
986     rocksdb_writeoptions_set_sync(woptions, 0);
987     for (i = 0; i < n; i++) {
988       snprintf(keybuf, sizeof(keybuf), "k%020d", i);
989       snprintf(valbuf, sizeof(valbuf), "v%020d", i);
990       rocksdb_put(db, woptions, keybuf, strlen(keybuf), valbuf, strlen(valbuf),
991                   &err);
992       CheckNoError(err);
993     }
994     rocksdb_approximate_sizes(db, 2, start, start_len, limit, limit_len, sizes,
995                               &err);
996     CheckNoError(err);
997     CheckCondition(sizes[0] > 0);
998     CheckCondition(sizes[1] > 0);
999   }
1000 
1001   StartPhase("property");
1002   {
1003     char* prop = rocksdb_property_value(db, "nosuchprop");
1004     CheckCondition(prop == NULL);
1005     prop = rocksdb_property_value(db, "rocksdb.stats");
1006     CheckCondition(prop != NULL);
1007     Free(&prop);
1008   }
1009 
1010   StartPhase("snapshot");
1011   {
1012     const rocksdb_snapshot_t* snap;
1013     snap = rocksdb_create_snapshot(db);
1014     rocksdb_delete(db, woptions, "foo", 3, &err);
1015     CheckNoError(err);
1016     rocksdb_readoptions_set_snapshot(roptions, snap);
1017     CheckGet(db, roptions, "foo", "hello");
1018     rocksdb_readoptions_set_snapshot(roptions, NULL);
1019     CheckGet(db, roptions, "foo", NULL);
1020     rocksdb_release_snapshot(db, snap);
1021   }
1022 
1023   StartPhase("repair");
1024   {
1025     // If we do not compact here, then the lazy deletion of
1026     // files (https://reviews.facebook.net/D6123) would leave
1027     // around deleted files and the repair process will find
1028     // those files and put them back into the database.
1029     rocksdb_compact_range(db, NULL, 0, NULL, 0);
1030     rocksdb_close(db);
1031     rocksdb_options_set_create_if_missing(options, 0);
1032     rocksdb_options_set_error_if_exists(options, 0);
1033     rocksdb_options_set_wal_recovery_mode(options, 2);
1034     rocksdb_repair_db(options, dbname, &err);
1035     CheckNoError(err);
1036     db = rocksdb_open(options, dbname, &err);
1037     CheckNoError(err);
1038     CheckGet(db, roptions, "foo", NULL);
1039     CheckGet(db, roptions, "bar", NULL);
1040     CheckGet(db, roptions, "box", "c");
1041     rocksdb_options_set_create_if_missing(options, 1);
1042     rocksdb_options_set_error_if_exists(options, 1);
1043   }
1044 
1045   StartPhase("filter");
1046   for (run = 0; run <= 2; run++) {
1047     // First run uses custom filter
1048     // Second run uses old block-based bloom filter
1049     // Third run uses full bloom filter
1050     CheckNoError(err);
1051     rocksdb_filterpolicy_t* policy;
1052     if (run == 0) {
1053       policy = rocksdb_filterpolicy_create(NULL, FilterDestroy, FilterCreate,
1054                                            FilterKeyMatch, NULL, FilterName);
1055     } else if (run == 1) {
1056       policy = rocksdb_filterpolicy_create_bloom(8);
1057     } else {
1058       policy = rocksdb_filterpolicy_create_bloom_full(8);
1059     }
1060     rocksdb_block_based_options_set_filter_policy(table_options, policy);
1061 
1062     // Create new database
1063     rocksdb_close(db);
1064     rocksdb_destroy_db(options, dbname, &err);
1065     rocksdb_options_set_block_based_table_factory(options, table_options);
1066     db = rocksdb_open(options, dbname, &err);
1067     CheckNoError(err);
1068     rocksdb_put(db, woptions, "foo", 3, "foovalue", 8, &err);
1069     CheckNoError(err);
1070     rocksdb_put(db, woptions, "bar", 3, "barvalue", 8, &err);
1071     CheckNoError(err);
1072 
1073     {
1074       // Add enough keys to get just one reasonably populated Bloom filter
1075       const int keys_to_add = 1500;
1076       int i;
1077       char keybuf[100];
1078       for (i = 0; i < keys_to_add; i++) {
1079         snprintf(keybuf, sizeof(keybuf), "yes%020d", i);
1080         rocksdb_put(db, woptions, keybuf, strlen(keybuf), "val", 3, &err);
1081         CheckNoError(err);
1082       }
1083     }
1084     rocksdb_compact_range(db, NULL, 0, NULL, 0);
1085 
1086     fake_filter_result = 1;
1087     CheckGet(db, roptions, "foo", "foovalue");
1088     CheckGet(db, roptions, "bar", "barvalue");
1089     if (run == 0) {
1090       // Must not find value when custom filter returns false
1091       fake_filter_result = 0;
1092       CheckGet(db, roptions, "foo", NULL);
1093       CheckGet(db, roptions, "bar", NULL);
1094       fake_filter_result = 1;
1095 
1096       CheckGet(db, roptions, "foo", "foovalue");
1097       CheckGet(db, roptions, "bar", "barvalue");
1098     }
1099 
1100     {
1101       // Query some keys not added to identify Bloom filter implementation
1102       // from false positive queries, using perfcontext to detect Bloom
1103       // filter behavior
1104       rocksdb_perfcontext_t* perf = rocksdb_perfcontext_create();
1105       rocksdb_perfcontext_reset(perf);
1106 
1107       const int keys_to_query = 10000;
1108       int i;
1109       char keybuf[100];
1110       for (i = 0; i < keys_to_query; i++) {
1111         fake_filter_result = i % 2;
1112         snprintf(keybuf, sizeof(keybuf), "no%020d", i);
1113         CheckGet(db, roptions, keybuf, NULL);
1114       }
1115 
1116       const int hits =
1117           (int)rocksdb_perfcontext_metric(perf, rocksdb_bloom_sst_hit_count);
1118       if (run == 0) {
1119         // Due to half true, half false with fake filter result
1120         CheckCondition(hits == keys_to_query / 2);
1121       } else if (run == 1) {
1122         // Essentially a fingerprint of the block-based Bloom schema
1123         CheckCondition(hits == 241);
1124       } else {
1125         // Essentially a fingerprint of full Bloom schema, format_version=5
1126         CheckCondition(hits == 188);
1127       }
1128       CheckCondition(
1129           (keys_to_query - hits) ==
1130           (int)rocksdb_perfcontext_metric(perf, rocksdb_bloom_sst_miss_count));
1131 
1132       rocksdb_perfcontext_destroy(perf);
1133     }
1134 
1135     // Reset the policy
1136     rocksdb_block_based_options_set_filter_policy(table_options, NULL);
1137     rocksdb_options_set_block_based_table_factory(options, table_options);
1138   }
1139 
1140   StartPhase("compaction_filter");
1141   {
1142     rocksdb_options_t* options_with_filter = rocksdb_options_create();
1143     rocksdb_options_set_create_if_missing(options_with_filter, 1);
1144     rocksdb_compactionfilter_t* cfilter;
1145     cfilter = rocksdb_compactionfilter_create(NULL, CFilterDestroy,
1146                                               CFilterFilter, CFilterName);
1147     // Create new database
1148     rocksdb_close(db);
1149     rocksdb_destroy_db(options_with_filter, dbname, &err);
1150     rocksdb_options_set_compaction_filter(options_with_filter, cfilter);
1151     db = CheckCompaction(db, options_with_filter, roptions, woptions);
1152 
1153     rocksdb_options_set_compaction_filter(options_with_filter, NULL);
1154     rocksdb_compactionfilter_destroy(cfilter);
1155     rocksdb_options_destroy(options_with_filter);
1156   }
1157 
1158   StartPhase("compaction_filter_factory");
1159   {
1160     rocksdb_options_t* options_with_filter_factory = rocksdb_options_create();
1161     rocksdb_options_set_create_if_missing(options_with_filter_factory, 1);
1162     rocksdb_compactionfilterfactory_t* factory;
1163     factory = rocksdb_compactionfilterfactory_create(
1164         NULL, CFilterFactoryDestroy, CFilterCreate, CFilterFactoryName);
1165     // Create new database
1166     rocksdb_close(db);
1167     rocksdb_destroy_db(options_with_filter_factory, dbname, &err);
1168     rocksdb_options_set_compaction_filter_factory(options_with_filter_factory,
1169                                                   factory);
1170     db = CheckCompaction(db, options_with_filter_factory, roptions, woptions);
1171 
1172     rocksdb_options_set_compaction_filter_factory(
1173         options_with_filter_factory, NULL);
1174     rocksdb_options_destroy(options_with_filter_factory);
1175   }
1176 
1177   StartPhase("merge_operator");
1178   {
1179     rocksdb_mergeoperator_t* merge_operator;
1180     merge_operator = rocksdb_mergeoperator_create(
1181         NULL, MergeOperatorDestroy, MergeOperatorFullMerge,
1182         MergeOperatorPartialMerge, NULL, MergeOperatorName);
1183     // Create new database
1184     rocksdb_close(db);
1185     rocksdb_destroy_db(options, dbname, &err);
1186     rocksdb_options_set_merge_operator(options, merge_operator);
1187     db = rocksdb_open(options, dbname, &err);
1188     CheckNoError(err);
1189     rocksdb_put(db, woptions, "foo", 3, "foovalue", 8, &err);
1190     CheckNoError(err);
1191     CheckGet(db, roptions, "foo", "foovalue");
1192     rocksdb_merge(db, woptions, "foo", 3, "barvalue", 8, &err);
1193     CheckNoError(err);
1194     CheckGet(db, roptions, "foo", "fake");
1195 
1196     // Merge of a non-existing value
1197     rocksdb_merge(db, woptions, "bar", 3, "barvalue", 8, &err);
1198     CheckNoError(err);
1199     CheckGet(db, roptions, "bar", "fake");
1200 
1201   }
1202 
1203   StartPhase("columnfamilies");
1204   {
1205     rocksdb_close(db);
1206     rocksdb_destroy_db(options, dbname, &err);
1207     CheckNoError(err);
1208 
1209     rocksdb_options_t* db_options = rocksdb_options_create();
1210     rocksdb_options_set_create_if_missing(db_options, 1);
1211     db = rocksdb_open(db_options, dbname, &err);
1212     CheckNoError(err)
1213     rocksdb_column_family_handle_t* cfh;
1214     cfh = rocksdb_create_column_family(db, db_options, "cf1", &err);
1215     rocksdb_column_family_handle_destroy(cfh);
1216     CheckNoError(err);
1217     rocksdb_close(db);
1218 
1219     size_t cflen;
1220     char** column_fams = rocksdb_list_column_families(db_options, dbname, &cflen, &err);
1221     CheckNoError(err);
1222     CheckEqual("default", column_fams[0], 7);
1223     CheckEqual("cf1", column_fams[1], 3);
1224     CheckCondition(cflen == 2);
1225     rocksdb_list_column_families_destroy(column_fams, cflen);
1226 
1227     rocksdb_options_t* cf_options = rocksdb_options_create();
1228 
1229     const char* cf_names[2] = {"default", "cf1"};
1230     const rocksdb_options_t* cf_opts[2] = {cf_options, cf_options};
1231     rocksdb_column_family_handle_t* handles[2];
1232     db = rocksdb_open_column_families(db_options, dbname, 2, cf_names, cf_opts, handles, &err);
1233     CheckNoError(err);
1234 
1235     rocksdb_put_cf(db, woptions, handles[1], "foo", 3, "hello", 5, &err);
1236     CheckNoError(err);
1237 
1238     rocksdb_put_cf(db, woptions, handles[1], "foobar1", 7, "hello1", 6, &err);
1239     CheckNoError(err);
1240     rocksdb_put_cf(db, woptions, handles[1], "foobar2", 7, "hello2", 6, &err);
1241     CheckNoError(err);
1242     rocksdb_put_cf(db, woptions, handles[1], "foobar3", 7, "hello3", 6, &err);
1243     CheckNoError(err);
1244     rocksdb_put_cf(db, woptions, handles[1], "foobar4", 7, "hello4", 6, &err);
1245     CheckNoError(err);
1246 
1247     rocksdb_flushoptions_t *flush_options = rocksdb_flushoptions_create();
1248     rocksdb_flushoptions_set_wait(flush_options, 1);
1249     rocksdb_flush_cf(db, flush_options, handles[1], &err);
1250     CheckNoError(err)
1251     rocksdb_flushoptions_destroy(flush_options);
1252 
1253     CheckGetCF(db, roptions, handles[1], "foo", "hello");
1254     CheckPinGetCF(db, roptions, handles[1], "foo", "hello");
1255 
1256     rocksdb_delete_cf(db, woptions, handles[1], "foo", 3, &err);
1257     CheckNoError(err);
1258 
1259     rocksdb_delete_range_cf(db, woptions, handles[1], "foobar2", 7, "foobar4",
1260                             7, &err);
1261     CheckNoError(err);
1262 
1263     CheckGetCF(db, roptions, handles[1], "foo", NULL);
1264     CheckPinGetCF(db, roptions, handles[1], "foo", NULL);
1265 
1266     rocksdb_writebatch_t* wb = rocksdb_writebatch_create();
1267     rocksdb_writebatch_put_cf(wb, handles[1], "baz", 3, "a", 1);
1268     rocksdb_writebatch_clear(wb);
1269     rocksdb_writebatch_put_cf(wb, handles[1], "bar", 3, "b", 1);
1270     rocksdb_writebatch_put_cf(wb, handles[1], "box", 3, "c", 1);
1271     rocksdb_writebatch_delete_cf(wb, handles[1], "bar", 3);
1272     rocksdb_write(db, woptions, wb, &err);
1273     CheckNoError(err);
1274     CheckGetCF(db, roptions, handles[1], "baz", NULL);
1275     CheckGetCF(db, roptions, handles[1], "bar", NULL);
1276     CheckGetCF(db, roptions, handles[1], "box", "c");
1277     CheckPinGetCF(db, roptions, handles[1], "baz", NULL);
1278     CheckPinGetCF(db, roptions, handles[1], "bar", NULL);
1279     CheckPinGetCF(db, roptions, handles[1], "box", "c");
1280     rocksdb_writebatch_destroy(wb);
1281 
1282     rocksdb_flush_wal(db, 1, &err);
1283     CheckNoError(err);
1284 
1285     const char* keys[3] = { "box", "box", "barfooxx" };
1286     const rocksdb_column_family_handle_t* get_handles[3] = { handles[0], handles[1], handles[1] };
1287     const size_t keys_sizes[3] = { 3, 3, 8 };
1288     char* vals[3];
1289     size_t vals_sizes[3];
1290     char* errs[3];
1291     rocksdb_multi_get_cf(db, roptions, get_handles, 3, keys, keys_sizes, vals, vals_sizes, errs);
1292 
1293     int i;
1294     for (i = 0; i < 3; i++) {
1295       CheckEqual(NULL, errs[i], 0);
1296       switch (i) {
1297       case 0:
1298         CheckEqual(NULL, vals[i], vals_sizes[i]); // wrong cf
1299         break;
1300       case 1:
1301         CheckEqual("c", vals[i], vals_sizes[i]); // bingo
1302         break;
1303       case 2:
1304         CheckEqual(NULL, vals[i], vals_sizes[i]); // normal not found
1305         break;
1306       }
1307       Free(&vals[i]);
1308     }
1309 
1310     {
1311       unsigned char value_found = 0;
1312 
1313       CheckCondition(!rocksdb_key_may_exist(db, roptions, "invalid_key", 11,
1314                                             NULL, NULL, NULL, 0, NULL));
1315       CheckCondition(!rocksdb_key_may_exist(db, roptions, "invalid_key", 11,
1316                                             &vals[0], &vals_sizes[0], NULL, 0,
1317                                             &value_found));
1318       if (value_found) {
1319         Free(&vals[0]);
1320       }
1321 
1322       CheckCondition(!rocksdb_key_may_exist_cf(db, roptions, handles[1],
1323                                                "invalid_key", 11, NULL, NULL,
1324                                                NULL, 0, NULL));
1325       CheckCondition(!rocksdb_key_may_exist_cf(db, roptions, handles[1],
1326                                                "invalid_key", 11, &vals[0],
1327                                                &vals_sizes[0], NULL, 0, NULL));
1328       if (value_found) {
1329         Free(&vals[0]);
1330       }
1331     }
1332 
1333     rocksdb_iterator_t* iter = rocksdb_create_iterator_cf(db, roptions, handles[1]);
1334     CheckCondition(!rocksdb_iter_valid(iter));
1335     rocksdb_iter_seek_to_first(iter);
1336     CheckCondition(rocksdb_iter_valid(iter));
1337 
1338     for (i = 0; rocksdb_iter_valid(iter) != 0; rocksdb_iter_next(iter)) {
1339       i++;
1340     }
1341     CheckCondition(i == 3);
1342     rocksdb_iter_get_error(iter, &err);
1343     CheckNoError(err);
1344     rocksdb_iter_destroy(iter);
1345 
1346     rocksdb_column_family_handle_t* iters_cf_handles[2] = { handles[0], handles[1] };
1347     rocksdb_iterator_t* iters_handles[2];
1348     rocksdb_create_iterators(db, roptions, iters_cf_handles, iters_handles, 2, &err);
1349     CheckNoError(err);
1350 
1351     iter = iters_handles[0];
1352     CheckCondition(!rocksdb_iter_valid(iter));
1353     rocksdb_iter_seek_to_first(iter);
1354     CheckCondition(!rocksdb_iter_valid(iter));
1355     rocksdb_iter_destroy(iter);
1356 
1357     iter = iters_handles[1];
1358     CheckCondition(!rocksdb_iter_valid(iter));
1359     rocksdb_iter_seek_to_first(iter);
1360     CheckCondition(rocksdb_iter_valid(iter));
1361 
1362     for (i = 0; rocksdb_iter_valid(iter) != 0; rocksdb_iter_next(iter)) {
1363       i++;
1364     }
1365     CheckCondition(i == 3);
1366     rocksdb_iter_get_error(iter, &err);
1367     CheckNoError(err);
1368     rocksdb_iter_destroy(iter);
1369 
1370     rocksdb_drop_column_family(db, handles[1], &err);
1371     CheckNoError(err);
1372     for (i = 0; i < 2; i++) {
1373       rocksdb_column_family_handle_destroy(handles[i]);
1374     }
1375     rocksdb_close(db);
1376     rocksdb_destroy_db(options, dbname, &err);
1377     rocksdb_options_destroy(db_options);
1378     rocksdb_options_destroy(cf_options);
1379   }
1380 
1381   StartPhase("prefix");
1382   {
1383     // Create new database
1384     rocksdb_options_set_allow_mmap_reads(options, 1);
1385     rocksdb_options_set_prefix_extractor(options, rocksdb_slicetransform_create_fixed_prefix(3));
1386     rocksdb_options_set_hash_skip_list_rep(options, 5000, 4, 4);
1387     rocksdb_options_set_plain_table_factory(options, 4, 10, 0.75, 16);
1388     rocksdb_options_set_allow_concurrent_memtable_write(options, 0);
1389 
1390     db = rocksdb_open(options, dbname, &err);
1391     CheckNoError(err);
1392 
1393     rocksdb_put(db, woptions, "foo1", 4, "foo", 3, &err);
1394     CheckNoError(err);
1395     rocksdb_put(db, woptions, "foo2", 4, "foo", 3, &err);
1396     CheckNoError(err);
1397     rocksdb_put(db, woptions, "foo3", 4, "foo", 3, &err);
1398     CheckNoError(err);
1399     rocksdb_put(db, woptions, "bar1", 4, "bar", 3, &err);
1400     CheckNoError(err);
1401     rocksdb_put(db, woptions, "bar2", 4, "bar", 3, &err);
1402     CheckNoError(err);
1403     rocksdb_put(db, woptions, "bar3", 4, "bar", 3, &err);
1404     CheckNoError(err);
1405 
1406     rocksdb_iterator_t* iter = rocksdb_create_iterator(db, roptions);
1407     CheckCondition(!rocksdb_iter_valid(iter));
1408 
1409     rocksdb_iter_seek(iter, "bar", 3);
1410     rocksdb_iter_get_error(iter, &err);
1411     CheckNoError(err);
1412     CheckCondition(rocksdb_iter_valid(iter));
1413 
1414     CheckIter(iter, "bar1", "bar");
1415     rocksdb_iter_next(iter);
1416     CheckIter(iter, "bar2", "bar");
1417     rocksdb_iter_next(iter);
1418     CheckIter(iter, "bar3", "bar");
1419     rocksdb_iter_get_error(iter, &err);
1420     CheckNoError(err);
1421     rocksdb_iter_destroy(iter);
1422 
1423     rocksdb_readoptions_set_total_order_seek(roptions, 1);
1424     iter = rocksdb_create_iterator(db, roptions);
1425     CheckCondition(!rocksdb_iter_valid(iter));
1426 
1427     rocksdb_iter_seek(iter, "ba", 2);
1428     rocksdb_iter_get_error(iter, &err);
1429     CheckNoError(err);
1430     CheckCondition(rocksdb_iter_valid(iter));
1431     CheckIter(iter, "bar1", "bar");
1432 
1433     rocksdb_iter_destroy(iter);
1434     rocksdb_readoptions_set_total_order_seek(roptions, 0);
1435 
1436     rocksdb_close(db);
1437     rocksdb_destroy_db(options, dbname, &err);
1438   }
1439 
1440   // Check memory usage stats
1441   StartPhase("approximate_memory_usage");
1442   {
1443     // Create database
1444     db = rocksdb_open(options, dbname, &err);
1445     CheckNoError(err);
1446 
1447     rocksdb_memory_consumers_t* consumers;
1448     consumers = rocksdb_memory_consumers_create();
1449     rocksdb_memory_consumers_add_db(consumers, db);
1450     rocksdb_memory_consumers_add_cache(consumers, cache);
1451 
1452     // take memory usage report before write-read operation
1453     rocksdb_memory_usage_t* mu1;
1454     mu1 = rocksdb_approximate_memory_usage_create(consumers, &err);
1455     CheckNoError(err);
1456 
1457     // Put data (this should affect memtables)
1458     rocksdb_put(db, woptions, "memory", 6, "test", 4, &err);
1459     CheckNoError(err);
1460     CheckGet(db, roptions, "memory", "test");
1461 
1462     // take memory usage report after write-read operation
1463     rocksdb_memory_usage_t* mu2;
1464     mu2 = rocksdb_approximate_memory_usage_create(consumers, &err);
1465     CheckNoError(err);
1466 
1467     // amount of memory used within memtables should grow
1468     CheckCondition(rocksdb_approximate_memory_usage_get_mem_table_total(mu2) >=
1469                    rocksdb_approximate_memory_usage_get_mem_table_total(mu1));
1470     CheckCondition(rocksdb_approximate_memory_usage_get_mem_table_unflushed(mu2) >=
1471                    rocksdb_approximate_memory_usage_get_mem_table_unflushed(mu1));
1472 
1473     rocksdb_memory_consumers_destroy(consumers);
1474     rocksdb_approximate_memory_usage_destroy(mu1);
1475     rocksdb_approximate_memory_usage_destroy(mu2);
1476     rocksdb_close(db);
1477     rocksdb_destroy_db(options, dbname, &err);
1478     CheckNoError(err);
1479   }
1480 
1481   StartPhase("cuckoo_options");
1482   {
1483     rocksdb_cuckoo_table_options_t* cuckoo_options;
1484     cuckoo_options = rocksdb_cuckoo_options_create();
1485     rocksdb_cuckoo_options_set_hash_ratio(cuckoo_options, 0.5);
1486     rocksdb_cuckoo_options_set_max_search_depth(cuckoo_options, 200);
1487     rocksdb_cuckoo_options_set_cuckoo_block_size(cuckoo_options, 10);
1488     rocksdb_cuckoo_options_set_identity_as_first_hash(cuckoo_options, 1);
1489     rocksdb_cuckoo_options_set_use_module_hash(cuckoo_options, 0);
1490     rocksdb_options_set_cuckoo_table_factory(options, cuckoo_options);
1491 
1492     db = rocksdb_open(options, dbname, &err);
1493     CheckNoError(err);
1494 
1495     rocksdb_cuckoo_options_destroy(cuckoo_options);
1496   }
1497 
1498   StartPhase("options");
1499   {
1500     rocksdb_options_t* o;
1501     o = rocksdb_options_create();
1502 
1503     // Set and check options.
1504     rocksdb_options_set_allow_ingest_behind(o, 1);
1505     CheckCondition(1 == rocksdb_options_get_allow_ingest_behind(o));
1506 
1507     rocksdb_options_compaction_readahead_size(o, 10);
1508     CheckCondition(10 == rocksdb_options_get_compaction_readahead_size(o));
1509 
1510     rocksdb_options_set_create_if_missing(o, 1);
1511     CheckCondition(1 == rocksdb_options_get_create_if_missing(o));
1512 
1513     rocksdb_options_set_create_missing_column_families(o, 1);
1514     CheckCondition(1 == rocksdb_options_get_create_missing_column_families(o));
1515 
1516     rocksdb_options_set_error_if_exists(o, 1);
1517     CheckCondition(1 == rocksdb_options_get_error_if_exists(o));
1518 
1519     rocksdb_options_set_paranoid_checks(o, 1);
1520     CheckCondition(1 == rocksdb_options_get_paranoid_checks(o));
1521 
1522     rocksdb_options_set_info_log_level(o, 3);
1523     CheckCondition(3 == rocksdb_options_get_info_log_level(o));
1524 
1525     rocksdb_options_set_write_buffer_size(o, 100);
1526     CheckCondition(100 == rocksdb_options_get_write_buffer_size(o));
1527 
1528     rocksdb_options_set_db_write_buffer_size(o, 1000);
1529     CheckCondition(1000 == rocksdb_options_get_db_write_buffer_size(o));
1530 
1531     rocksdb_options_set_max_open_files(o, 21);
1532     CheckCondition(21 == rocksdb_options_get_max_open_files(o));
1533 
1534     rocksdb_options_set_max_file_opening_threads(o, 5);
1535     CheckCondition(5 == rocksdb_options_get_max_file_opening_threads(o));
1536 
1537     rocksdb_options_set_max_total_wal_size(o, 400);
1538     CheckCondition(400 == rocksdb_options_get_max_total_wal_size(o));
1539 
1540     rocksdb_options_set_num_levels(o, 7);
1541     CheckCondition(7 == rocksdb_options_get_num_levels(o));
1542 
1543     rocksdb_options_set_level0_file_num_compaction_trigger(o, 4);
1544     CheckCondition(4 ==
1545                    rocksdb_options_get_level0_file_num_compaction_trigger(o));
1546 
1547     rocksdb_options_set_level0_slowdown_writes_trigger(o, 6);
1548     CheckCondition(6 == rocksdb_options_get_level0_slowdown_writes_trigger(o));
1549 
1550     rocksdb_options_set_level0_stop_writes_trigger(o, 8);
1551     CheckCondition(8 == rocksdb_options_get_level0_stop_writes_trigger(o));
1552 
1553     rocksdb_options_set_target_file_size_base(o, 256);
1554     CheckCondition(256 == rocksdb_options_get_target_file_size_base(o));
1555 
1556     rocksdb_options_set_target_file_size_multiplier(o, 3);
1557     CheckCondition(3 == rocksdb_options_get_target_file_size_multiplier(o));
1558 
1559     rocksdb_options_set_max_bytes_for_level_base(o, 1024);
1560     CheckCondition(1024 == rocksdb_options_get_max_bytes_for_level_base(o));
1561 
1562     rocksdb_options_set_level_compaction_dynamic_level_bytes(o, 1);
1563     CheckCondition(1 ==
1564                    rocksdb_options_get_level_compaction_dynamic_level_bytes(o));
1565 
1566     rocksdb_options_set_max_bytes_for_level_multiplier(o, 2.0);
1567     CheckCondition(2.0 ==
1568                    rocksdb_options_get_max_bytes_for_level_multiplier(o));
1569 
1570     rocksdb_options_set_skip_stats_update_on_db_open(o, 1);
1571     CheckCondition(1 == rocksdb_options_get_skip_stats_update_on_db_open(o));
1572 
1573     rocksdb_options_set_skip_checking_sst_file_sizes_on_db_open(o, 1);
1574     CheckCondition(
1575         1 == rocksdb_options_get_skip_checking_sst_file_sizes_on_db_open(o));
1576 
1577     rocksdb_options_set_max_write_buffer_number(o, 97);
1578     CheckCondition(97 == rocksdb_options_get_max_write_buffer_number(o));
1579 
1580     rocksdb_options_set_min_write_buffer_number_to_merge(o, 23);
1581     CheckCondition(23 ==
1582                    rocksdb_options_get_min_write_buffer_number_to_merge(o));
1583 
1584     rocksdb_options_set_max_write_buffer_number_to_maintain(o, 64);
1585     CheckCondition(64 ==
1586                    rocksdb_options_get_max_write_buffer_number_to_maintain(o));
1587 
1588     rocksdb_options_set_max_write_buffer_size_to_maintain(o, 50000);
1589     CheckCondition(50000 ==
1590                    rocksdb_options_get_max_write_buffer_size_to_maintain(o));
1591 
1592     rocksdb_options_set_enable_pipelined_write(o, 1);
1593     CheckCondition(1 == rocksdb_options_get_enable_pipelined_write(o));
1594 
1595     rocksdb_options_set_unordered_write(o, 1);
1596     CheckCondition(1 == rocksdb_options_get_unordered_write(o));
1597 
1598     rocksdb_options_set_max_subcompactions(o, 123456);
1599     CheckCondition(123456 == rocksdb_options_get_max_subcompactions(o));
1600 
1601     rocksdb_options_set_max_background_jobs(o, 2);
1602     CheckCondition(2 == rocksdb_options_get_max_background_jobs(o));
1603 
1604     rocksdb_options_set_max_background_compactions(o, 3);
1605     CheckCondition(3 == rocksdb_options_get_max_background_compactions(o));
1606 
1607     rocksdb_options_set_base_background_compactions(o, 4);
1608     CheckCondition(4 == rocksdb_options_get_base_background_compactions(o));
1609 
1610     rocksdb_options_set_max_background_flushes(o, 5);
1611     CheckCondition(5 == rocksdb_options_get_max_background_flushes(o));
1612 
1613     rocksdb_options_set_max_log_file_size(o, 6);
1614     CheckCondition(6 == rocksdb_options_get_max_log_file_size(o));
1615 
1616     rocksdb_options_set_log_file_time_to_roll(o, 7);
1617     CheckCondition(7 == rocksdb_options_get_log_file_time_to_roll(o));
1618 
1619     rocksdb_options_set_keep_log_file_num(o, 8);
1620     CheckCondition(8 == rocksdb_options_get_keep_log_file_num(o));
1621 
1622     rocksdb_options_set_recycle_log_file_num(o, 9);
1623     CheckCondition(9 == rocksdb_options_get_recycle_log_file_num(o));
1624 
1625     rocksdb_options_set_soft_rate_limit(o, 2.0);
1626     CheckCondition(2.0 == rocksdb_options_get_soft_rate_limit(o));
1627 
1628     rocksdb_options_set_hard_rate_limit(o, 4.0);
1629     CheckCondition(4.0 == rocksdb_options_get_hard_rate_limit(o));
1630 
1631     rocksdb_options_set_soft_pending_compaction_bytes_limit(o, 10);
1632     CheckCondition(10 ==
1633                    rocksdb_options_get_soft_pending_compaction_bytes_limit(o));
1634 
1635     rocksdb_options_set_hard_pending_compaction_bytes_limit(o, 11);
1636     CheckCondition(11 ==
1637                    rocksdb_options_get_hard_pending_compaction_bytes_limit(o));
1638 
1639     rocksdb_options_set_rate_limit_delay_max_milliseconds(o, 1);
1640     CheckCondition(1 ==
1641                    rocksdb_options_get_rate_limit_delay_max_milliseconds(o));
1642 
1643     rocksdb_options_set_max_manifest_file_size(o, 12);
1644     CheckCondition(12 == rocksdb_options_get_max_manifest_file_size(o));
1645 
1646     rocksdb_options_set_table_cache_numshardbits(o, 13);
1647     CheckCondition(13 == rocksdb_options_get_table_cache_numshardbits(o));
1648 
1649     rocksdb_options_set_arena_block_size(o, 14);
1650     CheckCondition(14 == rocksdb_options_get_arena_block_size(o));
1651 
1652     rocksdb_options_set_use_fsync(o, 1);
1653     CheckCondition(1 == rocksdb_options_get_use_fsync(o));
1654 
1655     rocksdb_options_set_WAL_ttl_seconds(o, 15);
1656     CheckCondition(15 == rocksdb_options_get_WAL_ttl_seconds(o));
1657 
1658     rocksdb_options_set_WAL_size_limit_MB(o, 16);
1659     CheckCondition(16 == rocksdb_options_get_WAL_size_limit_MB(o));
1660 
1661     rocksdb_options_set_manifest_preallocation_size(o, 17);
1662     CheckCondition(17 == rocksdb_options_get_manifest_preallocation_size(o));
1663 
1664     rocksdb_options_set_allow_mmap_reads(o, 1);
1665     CheckCondition(1 == rocksdb_options_get_allow_mmap_reads(o));
1666 
1667     rocksdb_options_set_allow_mmap_writes(o, 1);
1668     CheckCondition(1 == rocksdb_options_get_allow_mmap_writes(o));
1669 
1670     rocksdb_options_set_use_direct_reads(o, 1);
1671     CheckCondition(1 == rocksdb_options_get_use_direct_reads(o));
1672 
1673     rocksdb_options_set_use_direct_io_for_flush_and_compaction(o, 1);
1674     CheckCondition(
1675         1 == rocksdb_options_get_use_direct_io_for_flush_and_compaction(o));
1676 
1677     rocksdb_options_set_is_fd_close_on_exec(o, 1);
1678     CheckCondition(1 == rocksdb_options_get_is_fd_close_on_exec(o));
1679 
1680     rocksdb_options_set_skip_log_error_on_recovery(o, 1);
1681     CheckCondition(1 == rocksdb_options_get_skip_log_error_on_recovery(o));
1682 
1683     rocksdb_options_set_stats_dump_period_sec(o, 18);
1684     CheckCondition(18 == rocksdb_options_get_stats_dump_period_sec(o));
1685 
1686     rocksdb_options_set_stats_persist_period_sec(o, 5);
1687     CheckCondition(5 == rocksdb_options_get_stats_persist_period_sec(o));
1688 
1689     rocksdb_options_set_advise_random_on_open(o, 1);
1690     CheckCondition(1 == rocksdb_options_get_advise_random_on_open(o));
1691 
1692     rocksdb_options_set_access_hint_on_compaction_start(o, 3);
1693     CheckCondition(3 == rocksdb_options_get_access_hint_on_compaction_start(o));
1694 
1695     rocksdb_options_set_use_adaptive_mutex(o, 1);
1696     CheckCondition(1 == rocksdb_options_get_use_adaptive_mutex(o));
1697 
1698     rocksdb_options_set_bytes_per_sync(o, 19);
1699     CheckCondition(19 == rocksdb_options_get_bytes_per_sync(o));
1700 
1701     rocksdb_options_set_wal_bytes_per_sync(o, 20);
1702     CheckCondition(20 == rocksdb_options_get_wal_bytes_per_sync(o));
1703 
1704     rocksdb_options_set_writable_file_max_buffer_size(o, 21);
1705     CheckCondition(21 == rocksdb_options_get_writable_file_max_buffer_size(o));
1706 
1707     rocksdb_options_set_allow_concurrent_memtable_write(o, 1);
1708     CheckCondition(1 == rocksdb_options_get_allow_concurrent_memtable_write(o));
1709 
1710     rocksdb_options_set_enable_write_thread_adaptive_yield(o, 1);
1711     CheckCondition(1 ==
1712                    rocksdb_options_get_enable_write_thread_adaptive_yield(o));
1713 
1714     rocksdb_options_set_max_sequential_skip_in_iterations(o, 22);
1715     CheckCondition(22 ==
1716                    rocksdb_options_get_max_sequential_skip_in_iterations(o));
1717 
1718     rocksdb_options_set_disable_auto_compactions(o, 1);
1719     CheckCondition(1 == rocksdb_options_get_disable_auto_compactions(o));
1720 
1721     rocksdb_options_set_optimize_filters_for_hits(o, 1);
1722     CheckCondition(1 == rocksdb_options_get_optimize_filters_for_hits(o));
1723 
1724     rocksdb_options_set_delete_obsolete_files_period_micros(o, 23);
1725     CheckCondition(23 ==
1726                    rocksdb_options_get_delete_obsolete_files_period_micros(o));
1727 
1728     rocksdb_options_set_memtable_prefix_bloom_size_ratio(o, 2.0);
1729     CheckCondition(2.0 ==
1730                    rocksdb_options_get_memtable_prefix_bloom_size_ratio(o));
1731 
1732     rocksdb_options_set_max_compaction_bytes(o, 24);
1733     CheckCondition(24 == rocksdb_options_get_max_compaction_bytes(o));
1734 
1735     rocksdb_options_set_memtable_huge_page_size(o, 25);
1736     CheckCondition(25 == rocksdb_options_get_memtable_huge_page_size(o));
1737 
1738     rocksdb_options_set_max_successive_merges(o, 26);
1739     CheckCondition(26 == rocksdb_options_get_max_successive_merges(o));
1740 
1741     rocksdb_options_set_bloom_locality(o, 27);
1742     CheckCondition(27 == rocksdb_options_get_bloom_locality(o));
1743 
1744     rocksdb_options_set_inplace_update_support(o, 1);
1745     CheckCondition(1 == rocksdb_options_get_inplace_update_support(o));
1746 
1747     rocksdb_options_set_inplace_update_num_locks(o, 28);
1748     CheckCondition(28 == rocksdb_options_get_inplace_update_num_locks(o));
1749 
1750     rocksdb_options_set_report_bg_io_stats(o, 1);
1751     CheckCondition(1 == rocksdb_options_get_report_bg_io_stats(o));
1752 
1753     rocksdb_options_set_wal_recovery_mode(o, 2);
1754     CheckCondition(2 == rocksdb_options_get_wal_recovery_mode(o));
1755 
1756     rocksdb_options_set_compression(o, 5);
1757     CheckCondition(5 == rocksdb_options_get_compression(o));
1758 
1759     rocksdb_options_set_bottommost_compression(o, 4);
1760     CheckCondition(4 == rocksdb_options_get_bottommost_compression(o));
1761 
1762     rocksdb_options_set_compaction_style(o, 2);
1763     CheckCondition(2 == rocksdb_options_get_compaction_style(o));
1764 
1765     rocksdb_options_set_atomic_flush(o, 1);
1766     CheckCondition(1 == rocksdb_options_get_atomic_flush(o));
1767 
1768     rocksdb_options_set_manual_wal_flush(o, 1);
1769     CheckCondition(1 == rocksdb_options_get_manual_wal_flush(o));
1770 
1771     /* Blob Options */
1772     rocksdb_options_set_enable_blob_files(o, 1);
1773     CheckCondition(1 == rocksdb_options_get_enable_blob_files(o));
1774 
1775     rocksdb_options_set_min_blob_size(o, 29);
1776     CheckCondition(29 == rocksdb_options_get_min_blob_size(o));
1777 
1778     rocksdb_options_set_blob_file_size(o, 30);
1779     CheckCondition(30 == rocksdb_options_get_blob_file_size(o));
1780 
1781     rocksdb_options_set_blob_compression_type(o, 4);
1782     CheckCondition(4 == rocksdb_options_get_blob_compression_type(o));
1783 
1784     rocksdb_options_set_enable_blob_gc(o, 1);
1785     CheckCondition(1 == rocksdb_options_get_enable_blob_gc(o));
1786 
1787     rocksdb_options_set_blob_gc_age_cutoff(o, 0.75);
1788     CheckCondition(0.75 == rocksdb_options_get_blob_gc_age_cutoff(o));
1789 
1790     // Create a copy that should be equal to the original.
1791     rocksdb_options_t* copy;
1792     copy = rocksdb_options_create_copy(o);
1793 
1794     CheckCondition(1 == rocksdb_options_get_allow_ingest_behind(copy));
1795     CheckCondition(10 == rocksdb_options_get_compaction_readahead_size(copy));
1796     CheckCondition(1 == rocksdb_options_get_create_if_missing(copy));
1797     CheckCondition(1 ==
1798                    rocksdb_options_get_create_missing_column_families(copy));
1799     CheckCondition(1 == rocksdb_options_get_error_if_exists(copy));
1800     CheckCondition(1 == rocksdb_options_get_paranoid_checks(copy));
1801     CheckCondition(3 == rocksdb_options_get_info_log_level(copy));
1802     CheckCondition(100 == rocksdb_options_get_write_buffer_size(copy));
1803     CheckCondition(1000 == rocksdb_options_get_db_write_buffer_size(copy));
1804     CheckCondition(21 == rocksdb_options_get_max_open_files(copy));
1805     CheckCondition(5 == rocksdb_options_get_max_file_opening_threads(copy));
1806     CheckCondition(400 == rocksdb_options_get_max_total_wal_size(copy));
1807     CheckCondition(7 == rocksdb_options_get_num_levels(copy));
1808     CheckCondition(
1809         4 == rocksdb_options_get_level0_file_num_compaction_trigger(copy));
1810     CheckCondition(6 ==
1811                    rocksdb_options_get_level0_slowdown_writes_trigger(copy));
1812     CheckCondition(8 == rocksdb_options_get_level0_stop_writes_trigger(copy));
1813     CheckCondition(256 == rocksdb_options_get_target_file_size_base(copy));
1814     CheckCondition(3 == rocksdb_options_get_target_file_size_multiplier(copy));
1815     CheckCondition(1024 == rocksdb_options_get_max_bytes_for_level_base(copy));
1816     CheckCondition(
1817         1 == rocksdb_options_get_level_compaction_dynamic_level_bytes(copy));
1818     CheckCondition(2.0 ==
1819                    rocksdb_options_get_max_bytes_for_level_multiplier(copy));
1820     CheckCondition(1 == rocksdb_options_get_skip_stats_update_on_db_open(copy));
1821     CheckCondition(
1822         1 == rocksdb_options_get_skip_checking_sst_file_sizes_on_db_open(copy));
1823     CheckCondition(97 == rocksdb_options_get_max_write_buffer_number(copy));
1824     CheckCondition(23 ==
1825                    rocksdb_options_get_min_write_buffer_number_to_merge(copy));
1826     CheckCondition(
1827         64 == rocksdb_options_get_max_write_buffer_number_to_maintain(copy));
1828     CheckCondition(50000 ==
1829                    rocksdb_options_get_max_write_buffer_size_to_maintain(copy));
1830     CheckCondition(1 == rocksdb_options_get_enable_pipelined_write(copy));
1831     CheckCondition(1 == rocksdb_options_get_unordered_write(copy));
1832     CheckCondition(123456 == rocksdb_options_get_max_subcompactions(copy));
1833     CheckCondition(2 == rocksdb_options_get_max_background_jobs(copy));
1834     CheckCondition(3 == rocksdb_options_get_max_background_compactions(copy));
1835     CheckCondition(4 == rocksdb_options_get_base_background_compactions(copy));
1836     CheckCondition(5 == rocksdb_options_get_max_background_flushes(copy));
1837     CheckCondition(6 == rocksdb_options_get_max_log_file_size(copy));
1838     CheckCondition(7 == rocksdb_options_get_log_file_time_to_roll(copy));
1839     CheckCondition(8 == rocksdb_options_get_keep_log_file_num(copy));
1840     CheckCondition(9 == rocksdb_options_get_recycle_log_file_num(copy));
1841     CheckCondition(2.0 == rocksdb_options_get_soft_rate_limit(copy));
1842     CheckCondition(4.0 == rocksdb_options_get_hard_rate_limit(copy));
1843     CheckCondition(
1844         10 == rocksdb_options_get_soft_pending_compaction_bytes_limit(copy));
1845     CheckCondition(
1846         11 == rocksdb_options_get_hard_pending_compaction_bytes_limit(copy));
1847     CheckCondition(1 ==
1848                    rocksdb_options_get_rate_limit_delay_max_milliseconds(copy));
1849     CheckCondition(12 == rocksdb_options_get_max_manifest_file_size(copy));
1850     CheckCondition(13 == rocksdb_options_get_table_cache_numshardbits(copy));
1851     CheckCondition(14 == rocksdb_options_get_arena_block_size(copy));
1852     CheckCondition(1 == rocksdb_options_get_use_fsync(copy));
1853     CheckCondition(15 == rocksdb_options_get_WAL_ttl_seconds(copy));
1854     CheckCondition(16 == rocksdb_options_get_WAL_size_limit_MB(copy));
1855     CheckCondition(17 == rocksdb_options_get_manifest_preallocation_size(copy));
1856     CheckCondition(1 == rocksdb_options_get_allow_mmap_reads(copy));
1857     CheckCondition(1 == rocksdb_options_get_allow_mmap_writes(copy));
1858     CheckCondition(1 == rocksdb_options_get_use_direct_reads(copy));
1859     CheckCondition(
1860         1 == rocksdb_options_get_use_direct_io_for_flush_and_compaction(copy));
1861     CheckCondition(1 == rocksdb_options_get_is_fd_close_on_exec(copy));
1862     CheckCondition(1 == rocksdb_options_get_skip_log_error_on_recovery(copy));
1863     CheckCondition(18 == rocksdb_options_get_stats_dump_period_sec(copy));
1864     CheckCondition(5 == rocksdb_options_get_stats_persist_period_sec(copy));
1865     CheckCondition(1 == rocksdb_options_get_advise_random_on_open(copy));
1866     CheckCondition(3 ==
1867                    rocksdb_options_get_access_hint_on_compaction_start(copy));
1868     CheckCondition(1 == rocksdb_options_get_use_adaptive_mutex(copy));
1869     CheckCondition(19 == rocksdb_options_get_bytes_per_sync(copy));
1870     CheckCondition(20 == rocksdb_options_get_wal_bytes_per_sync(copy));
1871     CheckCondition(21 ==
1872                    rocksdb_options_get_writable_file_max_buffer_size(copy));
1873     CheckCondition(1 ==
1874                    rocksdb_options_get_allow_concurrent_memtable_write(copy));
1875     CheckCondition(
1876         1 == rocksdb_options_get_enable_write_thread_adaptive_yield(copy));
1877     CheckCondition(22 ==
1878                    rocksdb_options_get_max_sequential_skip_in_iterations(copy));
1879     CheckCondition(1 == rocksdb_options_get_disable_auto_compactions(copy));
1880     CheckCondition(1 == rocksdb_options_get_optimize_filters_for_hits(copy));
1881     CheckCondition(
1882         23 == rocksdb_options_get_delete_obsolete_files_period_micros(copy));
1883     CheckCondition(2.0 ==
1884                    rocksdb_options_get_memtable_prefix_bloom_size_ratio(copy));
1885     CheckCondition(24 == rocksdb_options_get_max_compaction_bytes(copy));
1886     CheckCondition(25 == rocksdb_options_get_memtable_huge_page_size(copy));
1887     CheckCondition(26 == rocksdb_options_get_max_successive_merges(copy));
1888     CheckCondition(27 == rocksdb_options_get_bloom_locality(copy));
1889     CheckCondition(1 == rocksdb_options_get_inplace_update_support(copy));
1890     CheckCondition(28 == rocksdb_options_get_inplace_update_num_locks(copy));
1891     CheckCondition(1 == rocksdb_options_get_report_bg_io_stats(copy));
1892     CheckCondition(2 == rocksdb_options_get_wal_recovery_mode(copy));
1893     CheckCondition(5 == rocksdb_options_get_compression(copy));
1894     CheckCondition(4 == rocksdb_options_get_bottommost_compression(copy));
1895     CheckCondition(2 == rocksdb_options_get_compaction_style(copy));
1896     CheckCondition(1 == rocksdb_options_get_atomic_flush(copy));
1897 
1898     // Copies should be independent.
1899     rocksdb_options_set_allow_ingest_behind(copy, 0);
1900     CheckCondition(0 == rocksdb_options_get_allow_ingest_behind(copy));
1901     CheckCondition(1 == rocksdb_options_get_allow_ingest_behind(o));
1902 
1903     rocksdb_options_compaction_readahead_size(copy, 20);
1904     CheckCondition(20 == rocksdb_options_get_compaction_readahead_size(copy));
1905     CheckCondition(10 == rocksdb_options_get_compaction_readahead_size(o));
1906 
1907     rocksdb_options_set_create_if_missing(copy, 0);
1908     CheckCondition(0 == rocksdb_options_get_create_if_missing(copy));
1909     CheckCondition(1 == rocksdb_options_get_create_if_missing(o));
1910 
1911     rocksdb_options_set_create_missing_column_families(copy, 0);
1912     CheckCondition(0 ==
1913                    rocksdb_options_get_create_missing_column_families(copy));
1914     CheckCondition(1 == rocksdb_options_get_create_missing_column_families(o));
1915 
1916     rocksdb_options_set_error_if_exists(copy, 0);
1917     CheckCondition(0 == rocksdb_options_get_error_if_exists(copy));
1918     CheckCondition(1 == rocksdb_options_get_error_if_exists(o));
1919 
1920     rocksdb_options_set_paranoid_checks(copy, 0);
1921     CheckCondition(0 == rocksdb_options_get_paranoid_checks(copy));
1922     CheckCondition(1 == rocksdb_options_get_paranoid_checks(o));
1923 
1924     rocksdb_options_set_info_log_level(copy, 2);
1925     CheckCondition(2 == rocksdb_options_get_info_log_level(copy));
1926     CheckCondition(3 == rocksdb_options_get_info_log_level(o));
1927 
1928     rocksdb_options_set_write_buffer_size(copy, 200);
1929     CheckCondition(200 == rocksdb_options_get_write_buffer_size(copy));
1930     CheckCondition(100 == rocksdb_options_get_write_buffer_size(o));
1931 
1932     rocksdb_options_set_db_write_buffer_size(copy, 2000);
1933     CheckCondition(2000 == rocksdb_options_get_db_write_buffer_size(copy));
1934     CheckCondition(1000 == rocksdb_options_get_db_write_buffer_size(o));
1935 
1936     rocksdb_options_set_max_open_files(copy, 42);
1937     CheckCondition(42 == rocksdb_options_get_max_open_files(copy));
1938     CheckCondition(21 == rocksdb_options_get_max_open_files(o));
1939 
1940     rocksdb_options_set_max_file_opening_threads(copy, 3);
1941     CheckCondition(3 == rocksdb_options_get_max_file_opening_threads(copy));
1942     CheckCondition(5 == rocksdb_options_get_max_file_opening_threads(o));
1943 
1944     rocksdb_options_set_max_total_wal_size(copy, 4000);
1945     CheckCondition(4000 == rocksdb_options_get_max_total_wal_size(copy));
1946     CheckCondition(400 == rocksdb_options_get_max_total_wal_size(o));
1947 
1948     rocksdb_options_set_num_levels(copy, 6);
1949     CheckCondition(6 == rocksdb_options_get_num_levels(copy));
1950     CheckCondition(7 == rocksdb_options_get_num_levels(o));
1951 
1952     rocksdb_options_set_level0_file_num_compaction_trigger(copy, 14);
1953     CheckCondition(
1954         14 == rocksdb_options_get_level0_file_num_compaction_trigger(copy));
1955     CheckCondition(4 ==
1956                    rocksdb_options_get_level0_file_num_compaction_trigger(o));
1957 
1958     rocksdb_options_set_level0_slowdown_writes_trigger(copy, 61);
1959     CheckCondition(61 ==
1960                    rocksdb_options_get_level0_slowdown_writes_trigger(copy));
1961     CheckCondition(6 == rocksdb_options_get_level0_slowdown_writes_trigger(o));
1962 
1963     rocksdb_options_set_level0_stop_writes_trigger(copy, 17);
1964     CheckCondition(17 == rocksdb_options_get_level0_stop_writes_trigger(copy));
1965     CheckCondition(8 == rocksdb_options_get_level0_stop_writes_trigger(o));
1966 
1967     rocksdb_options_set_target_file_size_base(copy, 128);
1968     CheckCondition(128 == rocksdb_options_get_target_file_size_base(copy));
1969     CheckCondition(256 == rocksdb_options_get_target_file_size_base(o));
1970 
1971     rocksdb_options_set_target_file_size_multiplier(copy, 13);
1972     CheckCondition(13 == rocksdb_options_get_target_file_size_multiplier(copy));
1973     CheckCondition(3 == rocksdb_options_get_target_file_size_multiplier(o));
1974 
1975     rocksdb_options_set_max_bytes_for_level_base(copy, 900);
1976     CheckCondition(900 == rocksdb_options_get_max_bytes_for_level_base(copy));
1977     CheckCondition(1024 == rocksdb_options_get_max_bytes_for_level_base(o));
1978 
1979     rocksdb_options_set_level_compaction_dynamic_level_bytes(copy, 0);
1980     CheckCondition(
1981         0 == rocksdb_options_get_level_compaction_dynamic_level_bytes(copy));
1982     CheckCondition(1 ==
1983                    rocksdb_options_get_level_compaction_dynamic_level_bytes(o));
1984 
1985     rocksdb_options_set_max_bytes_for_level_multiplier(copy, 8.0);
1986     CheckCondition(8.0 ==
1987                    rocksdb_options_get_max_bytes_for_level_multiplier(copy));
1988     CheckCondition(2.0 ==
1989                    rocksdb_options_get_max_bytes_for_level_multiplier(o));
1990 
1991     rocksdb_options_set_skip_stats_update_on_db_open(copy, 0);
1992     CheckCondition(0 == rocksdb_options_get_skip_stats_update_on_db_open(copy));
1993     CheckCondition(1 == rocksdb_options_get_skip_stats_update_on_db_open(o));
1994 
1995     rocksdb_options_set_skip_checking_sst_file_sizes_on_db_open(copy, 0);
1996     CheckCondition(
1997         0 == rocksdb_options_get_skip_checking_sst_file_sizes_on_db_open(copy));
1998     CheckCondition(
1999         1 == rocksdb_options_get_skip_checking_sst_file_sizes_on_db_open(o));
2000 
2001     rocksdb_options_set_max_write_buffer_number(copy, 2000);
2002     CheckCondition(2000 == rocksdb_options_get_max_write_buffer_number(copy));
2003     CheckCondition(97 == rocksdb_options_get_max_write_buffer_number(o));
2004 
2005     rocksdb_options_set_min_write_buffer_number_to_merge(copy, 146);
2006     CheckCondition(146 ==
2007                    rocksdb_options_get_min_write_buffer_number_to_merge(copy));
2008     CheckCondition(23 ==
2009                    rocksdb_options_get_min_write_buffer_number_to_merge(o));
2010 
2011     rocksdb_options_set_max_write_buffer_number_to_maintain(copy, 128);
2012     CheckCondition(
2013         128 == rocksdb_options_get_max_write_buffer_number_to_maintain(copy));
2014     CheckCondition(64 ==
2015                    rocksdb_options_get_max_write_buffer_number_to_maintain(o));
2016 
2017     rocksdb_options_set_max_write_buffer_size_to_maintain(copy, 9000);
2018     CheckCondition(9000 ==
2019                    rocksdb_options_get_max_write_buffer_size_to_maintain(copy));
2020     CheckCondition(50000 ==
2021                    rocksdb_options_get_max_write_buffer_size_to_maintain(o));
2022 
2023     rocksdb_options_set_enable_pipelined_write(copy, 0);
2024     CheckCondition(0 == rocksdb_options_get_enable_pipelined_write(copy));
2025     CheckCondition(1 == rocksdb_options_get_enable_pipelined_write(o));
2026 
2027     rocksdb_options_set_unordered_write(copy, 0);
2028     CheckCondition(0 == rocksdb_options_get_unordered_write(copy));
2029     CheckCondition(1 == rocksdb_options_get_unordered_write(o));
2030 
2031     rocksdb_options_set_max_subcompactions(copy, 90001);
2032     CheckCondition(90001 == rocksdb_options_get_max_subcompactions(copy));
2033     CheckCondition(123456 == rocksdb_options_get_max_subcompactions(o));
2034 
2035     rocksdb_options_set_max_background_jobs(copy, 12);
2036     CheckCondition(12 == rocksdb_options_get_max_background_jobs(copy));
2037     CheckCondition(2 == rocksdb_options_get_max_background_jobs(o));
2038 
2039     rocksdb_options_set_max_background_compactions(copy, 13);
2040     CheckCondition(13 == rocksdb_options_get_max_background_compactions(copy));
2041     CheckCondition(3 == rocksdb_options_get_max_background_compactions(o));
2042 
2043     rocksdb_options_set_base_background_compactions(copy, 14);
2044     CheckCondition(14 == rocksdb_options_get_base_background_compactions(copy));
2045     CheckCondition(4 == rocksdb_options_get_base_background_compactions(o));
2046 
2047     rocksdb_options_set_max_background_flushes(copy, 15);
2048     CheckCondition(15 == rocksdb_options_get_max_background_flushes(copy));
2049     CheckCondition(5 == rocksdb_options_get_max_background_flushes(o));
2050 
2051     rocksdb_options_set_max_log_file_size(copy, 16);
2052     CheckCondition(16 == rocksdb_options_get_max_log_file_size(copy));
2053     CheckCondition(6 == rocksdb_options_get_max_log_file_size(o));
2054 
2055     rocksdb_options_set_log_file_time_to_roll(copy, 17);
2056     CheckCondition(17 == rocksdb_options_get_log_file_time_to_roll(copy));
2057     CheckCondition(7 == rocksdb_options_get_log_file_time_to_roll(o));
2058 
2059     rocksdb_options_set_keep_log_file_num(copy, 18);
2060     CheckCondition(18 == rocksdb_options_get_keep_log_file_num(copy));
2061     CheckCondition(8 == rocksdb_options_get_keep_log_file_num(o));
2062 
2063     rocksdb_options_set_recycle_log_file_num(copy, 19);
2064     CheckCondition(19 == rocksdb_options_get_recycle_log_file_num(copy));
2065     CheckCondition(9 == rocksdb_options_get_recycle_log_file_num(o));
2066 
2067     rocksdb_options_set_soft_rate_limit(copy, 4.0);
2068     CheckCondition(4.0 == rocksdb_options_get_soft_rate_limit(copy));
2069     CheckCondition(2.0 == rocksdb_options_get_soft_rate_limit(o));
2070 
2071     rocksdb_options_set_hard_rate_limit(copy, 2.0);
2072     CheckCondition(2.0 == rocksdb_options_get_hard_rate_limit(copy));
2073     CheckCondition(4.0 == rocksdb_options_get_hard_rate_limit(o));
2074 
2075     rocksdb_options_set_soft_pending_compaction_bytes_limit(copy, 110);
2076     CheckCondition(
2077         110 == rocksdb_options_get_soft_pending_compaction_bytes_limit(copy));
2078     CheckCondition(10 ==
2079                    rocksdb_options_get_soft_pending_compaction_bytes_limit(o));
2080 
2081     rocksdb_options_set_hard_pending_compaction_bytes_limit(copy, 111);
2082     CheckCondition(
2083         111 == rocksdb_options_get_hard_pending_compaction_bytes_limit(copy));
2084     CheckCondition(11 ==
2085                    rocksdb_options_get_hard_pending_compaction_bytes_limit(o));
2086 
2087     rocksdb_options_set_rate_limit_delay_max_milliseconds(copy, 0);
2088     CheckCondition(0 ==
2089                    rocksdb_options_get_rate_limit_delay_max_milliseconds(copy));
2090     CheckCondition(1 ==
2091                    rocksdb_options_get_rate_limit_delay_max_milliseconds(o));
2092 
2093     rocksdb_options_set_max_manifest_file_size(copy, 112);
2094     CheckCondition(112 == rocksdb_options_get_max_manifest_file_size(copy));
2095     CheckCondition(12 == rocksdb_options_get_max_manifest_file_size(o));
2096 
2097     rocksdb_options_set_table_cache_numshardbits(copy, 113);
2098     CheckCondition(113 == rocksdb_options_get_table_cache_numshardbits(copy));
2099     CheckCondition(13 == rocksdb_options_get_table_cache_numshardbits(o));
2100 
2101     rocksdb_options_set_arena_block_size(copy, 114);
2102     CheckCondition(114 == rocksdb_options_get_arena_block_size(copy));
2103     CheckCondition(14 == rocksdb_options_get_arena_block_size(o));
2104 
2105     rocksdb_options_set_use_fsync(copy, 0);
2106     CheckCondition(0 == rocksdb_options_get_use_fsync(copy));
2107     CheckCondition(1 == rocksdb_options_get_use_fsync(o));
2108 
2109     rocksdb_options_set_WAL_ttl_seconds(copy, 115);
2110     CheckCondition(115 == rocksdb_options_get_WAL_ttl_seconds(copy));
2111     CheckCondition(15 == rocksdb_options_get_WAL_ttl_seconds(o));
2112 
2113     rocksdb_options_set_WAL_size_limit_MB(copy, 116);
2114     CheckCondition(116 == rocksdb_options_get_WAL_size_limit_MB(copy));
2115     CheckCondition(16 == rocksdb_options_get_WAL_size_limit_MB(o));
2116 
2117     rocksdb_options_set_manifest_preallocation_size(copy, 117);
2118     CheckCondition(117 ==
2119                    rocksdb_options_get_manifest_preallocation_size(copy));
2120     CheckCondition(17 == rocksdb_options_get_manifest_preallocation_size(o));
2121 
2122     rocksdb_options_set_allow_mmap_reads(copy, 0);
2123     CheckCondition(0 == rocksdb_options_get_allow_mmap_reads(copy));
2124     CheckCondition(1 == rocksdb_options_get_allow_mmap_reads(o));
2125 
2126     rocksdb_options_set_allow_mmap_writes(copy, 0);
2127     CheckCondition(0 == rocksdb_options_get_allow_mmap_writes(copy));
2128     CheckCondition(1 == rocksdb_options_get_allow_mmap_writes(o));
2129 
2130     rocksdb_options_set_use_direct_reads(copy, 0);
2131     CheckCondition(0 == rocksdb_options_get_use_direct_reads(copy));
2132     CheckCondition(1 == rocksdb_options_get_use_direct_reads(o));
2133 
2134     rocksdb_options_set_use_direct_io_for_flush_and_compaction(copy, 0);
2135     CheckCondition(
2136         0 == rocksdb_options_get_use_direct_io_for_flush_and_compaction(copy));
2137     CheckCondition(
2138         1 == rocksdb_options_get_use_direct_io_for_flush_and_compaction(o));
2139 
2140     rocksdb_options_set_is_fd_close_on_exec(copy, 0);
2141     CheckCondition(0 == rocksdb_options_get_is_fd_close_on_exec(copy));
2142     CheckCondition(1 == rocksdb_options_get_is_fd_close_on_exec(o));
2143 
2144     rocksdb_options_set_skip_log_error_on_recovery(copy, 0);
2145     CheckCondition(0 == rocksdb_options_get_skip_log_error_on_recovery(copy));
2146     CheckCondition(1 == rocksdb_options_get_skip_log_error_on_recovery(o));
2147 
2148     rocksdb_options_set_stats_dump_period_sec(copy, 218);
2149     CheckCondition(218 == rocksdb_options_get_stats_dump_period_sec(copy));
2150     CheckCondition(18 == rocksdb_options_get_stats_dump_period_sec(o));
2151 
2152     rocksdb_options_set_stats_persist_period_sec(copy, 600);
2153     CheckCondition(600 == rocksdb_options_get_stats_persist_period_sec(copy));
2154     CheckCondition(5 == rocksdb_options_get_stats_persist_period_sec(o));
2155 
2156     rocksdb_options_set_advise_random_on_open(copy, 0);
2157     CheckCondition(0 == rocksdb_options_get_advise_random_on_open(copy));
2158     CheckCondition(1 == rocksdb_options_get_advise_random_on_open(o));
2159 
2160     rocksdb_options_set_access_hint_on_compaction_start(copy, 2);
2161     CheckCondition(2 ==
2162                    rocksdb_options_get_access_hint_on_compaction_start(copy));
2163     CheckCondition(3 == rocksdb_options_get_access_hint_on_compaction_start(o));
2164 
2165     rocksdb_options_set_use_adaptive_mutex(copy, 0);
2166     CheckCondition(0 == rocksdb_options_get_use_adaptive_mutex(copy));
2167     CheckCondition(1 == rocksdb_options_get_use_adaptive_mutex(o));
2168 
2169     rocksdb_options_set_bytes_per_sync(copy, 219);
2170     CheckCondition(219 == rocksdb_options_get_bytes_per_sync(copy));
2171     CheckCondition(19 == rocksdb_options_get_bytes_per_sync(o));
2172 
2173     rocksdb_options_set_wal_bytes_per_sync(copy, 120);
2174     CheckCondition(120 == rocksdb_options_get_wal_bytes_per_sync(copy));
2175     CheckCondition(20 == rocksdb_options_get_wal_bytes_per_sync(o));
2176 
2177     rocksdb_options_set_writable_file_max_buffer_size(copy, 121);
2178     CheckCondition(121 ==
2179                    rocksdb_options_get_writable_file_max_buffer_size(copy));
2180     CheckCondition(21 == rocksdb_options_get_writable_file_max_buffer_size(o));
2181 
2182     rocksdb_options_set_allow_concurrent_memtable_write(copy, 0);
2183     CheckCondition(0 ==
2184                    rocksdb_options_get_allow_concurrent_memtable_write(copy));
2185     CheckCondition(1 == rocksdb_options_get_allow_concurrent_memtable_write(o));
2186 
2187     rocksdb_options_set_enable_write_thread_adaptive_yield(copy, 0);
2188     CheckCondition(
2189         0 == rocksdb_options_get_enable_write_thread_adaptive_yield(copy));
2190     CheckCondition(1 ==
2191                    rocksdb_options_get_enable_write_thread_adaptive_yield(o));
2192 
2193     rocksdb_options_set_max_sequential_skip_in_iterations(copy, 122);
2194     CheckCondition(122 ==
2195                    rocksdb_options_get_max_sequential_skip_in_iterations(copy));
2196     CheckCondition(22 ==
2197                    rocksdb_options_get_max_sequential_skip_in_iterations(o));
2198 
2199     rocksdb_options_set_disable_auto_compactions(copy, 0);
2200     CheckCondition(0 == rocksdb_options_get_disable_auto_compactions(copy));
2201     CheckCondition(1 == rocksdb_options_get_disable_auto_compactions(o));
2202 
2203     rocksdb_options_set_optimize_filters_for_hits(copy, 0);
2204     CheckCondition(0 == rocksdb_options_get_optimize_filters_for_hits(copy));
2205     CheckCondition(1 == rocksdb_options_get_optimize_filters_for_hits(o));
2206 
2207     rocksdb_options_set_delete_obsolete_files_period_micros(copy, 123);
2208     CheckCondition(
2209         123 == rocksdb_options_get_delete_obsolete_files_period_micros(copy));
2210     CheckCondition(23 ==
2211                    rocksdb_options_get_delete_obsolete_files_period_micros(o));
2212 
2213     rocksdb_options_set_memtable_prefix_bloom_size_ratio(copy, 4.0);
2214     CheckCondition(4.0 ==
2215                    rocksdb_options_get_memtable_prefix_bloom_size_ratio(copy));
2216     CheckCondition(2.0 ==
2217                    rocksdb_options_get_memtable_prefix_bloom_size_ratio(o));
2218 
2219     rocksdb_options_set_max_compaction_bytes(copy, 124);
2220     CheckCondition(124 == rocksdb_options_get_max_compaction_bytes(copy));
2221     CheckCondition(24 == rocksdb_options_get_max_compaction_bytes(o));
2222 
2223     rocksdb_options_set_memtable_huge_page_size(copy, 125);
2224     CheckCondition(125 == rocksdb_options_get_memtable_huge_page_size(copy));
2225     CheckCondition(25 == rocksdb_options_get_memtable_huge_page_size(o));
2226 
2227     rocksdb_options_set_max_successive_merges(copy, 126);
2228     CheckCondition(126 == rocksdb_options_get_max_successive_merges(copy));
2229     CheckCondition(26 == rocksdb_options_get_max_successive_merges(o));
2230 
2231     rocksdb_options_set_bloom_locality(copy, 127);
2232     CheckCondition(127 == rocksdb_options_get_bloom_locality(copy));
2233     CheckCondition(27 == rocksdb_options_get_bloom_locality(o));
2234 
2235     rocksdb_options_set_inplace_update_support(copy, 0);
2236     CheckCondition(0 == rocksdb_options_get_inplace_update_support(copy));
2237     CheckCondition(1 == rocksdb_options_get_inplace_update_support(o));
2238 
2239     rocksdb_options_set_inplace_update_num_locks(copy, 128);
2240     CheckCondition(128 == rocksdb_options_get_inplace_update_num_locks(copy));
2241     CheckCondition(28 == rocksdb_options_get_inplace_update_num_locks(o));
2242 
2243     rocksdb_options_set_report_bg_io_stats(copy, 0);
2244     CheckCondition(0 == rocksdb_options_get_report_bg_io_stats(copy));
2245     CheckCondition(1 == rocksdb_options_get_report_bg_io_stats(o));
2246 
2247     rocksdb_options_set_wal_recovery_mode(copy, 1);
2248     CheckCondition(1 == rocksdb_options_get_wal_recovery_mode(copy));
2249     CheckCondition(2 == rocksdb_options_get_wal_recovery_mode(o));
2250 
2251     rocksdb_options_set_compression(copy, 4);
2252     CheckCondition(4 == rocksdb_options_get_compression(copy));
2253     CheckCondition(5 == rocksdb_options_get_compression(o));
2254 
2255     rocksdb_options_set_bottommost_compression(copy, 3);
2256     CheckCondition(3 == rocksdb_options_get_bottommost_compression(copy));
2257     CheckCondition(4 == rocksdb_options_get_bottommost_compression(o));
2258 
2259     rocksdb_options_set_compaction_style(copy, 1);
2260     CheckCondition(1 == rocksdb_options_get_compaction_style(copy));
2261     CheckCondition(2 == rocksdb_options_get_compaction_style(o));
2262 
2263     rocksdb_options_set_atomic_flush(copy, 0);
2264     CheckCondition(0 == rocksdb_options_get_atomic_flush(copy));
2265     CheckCondition(1 == rocksdb_options_get_atomic_flush(o));
2266 
2267     rocksdb_options_destroy(copy);
2268     rocksdb_options_destroy(o);
2269   }
2270 
2271   StartPhase("read_options");
2272   {
2273     rocksdb_readoptions_t* ro;
2274     ro = rocksdb_readoptions_create();
2275 
2276     rocksdb_readoptions_set_verify_checksums(ro, 1);
2277     CheckCondition(1 == rocksdb_readoptions_get_verify_checksums(ro));
2278 
2279     rocksdb_readoptions_set_fill_cache(ro, 1);
2280     CheckCondition(1 == rocksdb_readoptions_get_fill_cache(ro));
2281 
2282     rocksdb_readoptions_set_read_tier(ro, 2);
2283     CheckCondition(2 == rocksdb_readoptions_get_read_tier(ro));
2284 
2285     rocksdb_readoptions_set_tailing(ro, 1);
2286     CheckCondition(1 == rocksdb_readoptions_get_tailing(ro));
2287 
2288     rocksdb_readoptions_set_readahead_size(ro, 100);
2289     CheckCondition(100 == rocksdb_readoptions_get_readahead_size(ro));
2290 
2291     rocksdb_readoptions_set_prefix_same_as_start(ro, 1);
2292     CheckCondition(1 == rocksdb_readoptions_get_prefix_same_as_start(ro));
2293 
2294     rocksdb_readoptions_set_pin_data(ro, 1);
2295     CheckCondition(1 == rocksdb_readoptions_get_pin_data(ro));
2296 
2297     rocksdb_readoptions_set_total_order_seek(ro, 1);
2298     CheckCondition(1 == rocksdb_readoptions_get_total_order_seek(ro));
2299 
2300     rocksdb_readoptions_set_max_skippable_internal_keys(ro, 200);
2301     CheckCondition(200 ==
2302                    rocksdb_readoptions_get_max_skippable_internal_keys(ro));
2303 
2304     rocksdb_readoptions_set_background_purge_on_iterator_cleanup(ro, 1);
2305     CheckCondition(
2306         1 == rocksdb_readoptions_get_background_purge_on_iterator_cleanup(ro));
2307 
2308     rocksdb_readoptions_set_ignore_range_deletions(ro, 1);
2309     CheckCondition(1 == rocksdb_readoptions_get_ignore_range_deletions(ro));
2310 
2311     rocksdb_readoptions_set_deadline(ro, 300);
2312     CheckCondition(300 == rocksdb_readoptions_get_deadline(ro));
2313 
2314     rocksdb_readoptions_set_io_timeout(ro, 400);
2315     CheckCondition(400 == rocksdb_readoptions_get_io_timeout(ro));
2316 
2317     rocksdb_readoptions_destroy(ro);
2318   }
2319 
2320   StartPhase("write_options");
2321   {
2322     rocksdb_writeoptions_t* wo;
2323     wo = rocksdb_writeoptions_create();
2324 
2325     rocksdb_writeoptions_set_sync(wo, 1);
2326     CheckCondition(1 == rocksdb_writeoptions_get_sync(wo));
2327 
2328     rocksdb_writeoptions_disable_WAL(wo, 1);
2329     CheckCondition(1 == rocksdb_writeoptions_get_disable_WAL(wo));
2330 
2331     rocksdb_writeoptions_set_ignore_missing_column_families(wo, 1);
2332     CheckCondition(1 ==
2333                    rocksdb_writeoptions_get_ignore_missing_column_families(wo));
2334 
2335     rocksdb_writeoptions_set_no_slowdown(wo, 1);
2336     CheckCondition(1 == rocksdb_writeoptions_get_no_slowdown(wo));
2337 
2338     rocksdb_writeoptions_set_low_pri(wo, 1);
2339     CheckCondition(1 == rocksdb_writeoptions_get_low_pri(wo));
2340 
2341     rocksdb_writeoptions_set_memtable_insert_hint_per_batch(wo, 1);
2342     CheckCondition(1 ==
2343                    rocksdb_writeoptions_get_memtable_insert_hint_per_batch(wo));
2344 
2345     rocksdb_writeoptions_destroy(wo);
2346   }
2347 
2348   StartPhase("compact_options");
2349   {
2350     rocksdb_compactoptions_t* co;
2351     co = rocksdb_compactoptions_create();
2352 
2353     rocksdb_compactoptions_set_exclusive_manual_compaction(co, 1);
2354     CheckCondition(1 ==
2355                    rocksdb_compactoptions_get_exclusive_manual_compaction(co));
2356 
2357     rocksdb_compactoptions_set_bottommost_level_compaction(co, 1);
2358     CheckCondition(1 ==
2359                    rocksdb_compactoptions_get_bottommost_level_compaction(co));
2360 
2361     rocksdb_compactoptions_set_change_level(co, 1);
2362     CheckCondition(1 == rocksdb_compactoptions_get_change_level(co));
2363 
2364     rocksdb_compactoptions_set_target_level(co, 1);
2365     CheckCondition(1 == rocksdb_compactoptions_get_target_level(co));
2366 
2367     rocksdb_compactoptions_destroy(co);
2368   }
2369 
2370   StartPhase("flush_options");
2371   {
2372     rocksdb_flushoptions_t* fo;
2373     fo = rocksdb_flushoptions_create();
2374 
2375     rocksdb_flushoptions_set_wait(fo, 1);
2376     CheckCondition(1 == rocksdb_flushoptions_get_wait(fo));
2377 
2378     rocksdb_flushoptions_destroy(fo);
2379   }
2380 
2381   StartPhase("cache_options");
2382   {
2383     rocksdb_cache_t* co;
2384     co = rocksdb_cache_create_lru(100);
2385     CheckCondition(100 == rocksdb_cache_get_capacity(co));
2386 
2387     rocksdb_cache_set_capacity(co, 200);
2388     CheckCondition(200 == rocksdb_cache_get_capacity(co));
2389 
2390     rocksdb_cache_destroy(co);
2391   }
2392 
2393   StartPhase("jemalloc_nodump_allocator");
2394   {
2395     rocksdb_memory_allocator_t* allocator;
2396     allocator = rocksdb_jemalloc_nodump_allocator_create(&err);
2397     if (err != NULL) {
2398       // not supported on all platforms, allow unsupported error
2399       const char* ni = "Not implemented: ";
2400       size_t ni_len = strlen(ni);
2401       size_t err_len = strlen(err);
2402 
2403       CheckCondition(err_len >= ni_len);
2404       CheckCondition(memcmp(ni, err, ni_len) == 0);
2405       Free(&err);
2406     } else {
2407       rocksdb_cache_t* co;
2408       rocksdb_lru_cache_options_t* copts;
2409 
2410       copts = rocksdb_lru_cache_options_create();
2411 
2412       rocksdb_lru_cache_options_set_capacity(copts, 100);
2413       rocksdb_lru_cache_options_set_memory_allocator(copts, allocator);
2414 
2415       co = rocksdb_cache_create_lru_opts(copts);
2416       CheckCondition(100 == rocksdb_cache_get_capacity(co));
2417 
2418       rocksdb_cache_destroy(co);
2419       rocksdb_lru_cache_options_destroy(copts);
2420     }
2421     rocksdb_memory_allocator_destroy(allocator);
2422   }
2423 
2424   StartPhase("env");
2425   {
2426     rocksdb_env_t* e;
2427     e = rocksdb_create_default_env();
2428 
2429     rocksdb_env_set_background_threads(e, 10);
2430     CheckCondition(10 == rocksdb_env_get_background_threads(e));
2431 
2432     rocksdb_env_set_high_priority_background_threads(e, 20);
2433     CheckCondition(20 == rocksdb_env_get_high_priority_background_threads(e));
2434 
2435     rocksdb_env_set_low_priority_background_threads(e, 30);
2436     CheckCondition(30 == rocksdb_env_get_low_priority_background_threads(e));
2437 
2438     rocksdb_env_set_bottom_priority_background_threads(e, 40);
2439     CheckCondition(40 == rocksdb_env_get_bottom_priority_background_threads(e));
2440 
2441     rocksdb_env_destroy(e);
2442   }
2443 
2444   StartPhase("universal_compaction_options");
2445   {
2446     rocksdb_universal_compaction_options_t* uco;
2447     uco = rocksdb_universal_compaction_options_create();
2448 
2449     rocksdb_universal_compaction_options_set_size_ratio(uco, 5);
2450     CheckCondition(5 ==
2451                    rocksdb_universal_compaction_options_get_size_ratio(uco));
2452 
2453     rocksdb_universal_compaction_options_set_min_merge_width(uco, 15);
2454     CheckCondition(
2455         15 == rocksdb_universal_compaction_options_get_min_merge_width(uco));
2456 
2457     rocksdb_universal_compaction_options_set_max_merge_width(uco, 25);
2458     CheckCondition(
2459         25 == rocksdb_universal_compaction_options_get_max_merge_width(uco));
2460 
2461     rocksdb_universal_compaction_options_set_max_size_amplification_percent(uco,
2462                                                                             35);
2463     CheckCondition(
2464         35 ==
2465         rocksdb_universal_compaction_options_get_max_size_amplification_percent(
2466             uco));
2467 
2468     rocksdb_universal_compaction_options_set_compression_size_percent(uco, 45);
2469     CheckCondition(
2470         45 ==
2471         rocksdb_universal_compaction_options_get_compression_size_percent(uco));
2472 
2473     rocksdb_universal_compaction_options_set_stop_style(uco, 1);
2474     CheckCondition(1 ==
2475                    rocksdb_universal_compaction_options_get_stop_style(uco));
2476 
2477     rocksdb_universal_compaction_options_destroy(uco);
2478   }
2479 
2480   StartPhase("fifo_compaction_options");
2481   {
2482     rocksdb_fifo_compaction_options_t* fco;
2483     fco = rocksdb_fifo_compaction_options_create();
2484 
2485     rocksdb_fifo_compaction_options_set_max_table_files_size(fco, 100000);
2486     CheckCondition(
2487         100000 ==
2488         rocksdb_fifo_compaction_options_get_max_table_files_size(fco));
2489 
2490     rocksdb_fifo_compaction_options_destroy(fco);
2491   }
2492 
2493   StartPhase("backupable_db_option");
2494   {
2495     rocksdb_backupable_db_options_t* bdo;
2496     bdo = rocksdb_backupable_db_options_create("path");
2497 
2498     rocksdb_backupable_db_options_set_share_table_files(bdo, 1);
2499     CheckCondition(1 ==
2500                    rocksdb_backupable_db_options_get_share_table_files(bdo));
2501 
2502     rocksdb_backupable_db_options_set_sync(bdo, 1);
2503     CheckCondition(1 == rocksdb_backupable_db_options_get_sync(bdo));
2504 
2505     rocksdb_backupable_db_options_set_destroy_old_data(bdo, 1);
2506     CheckCondition(1 ==
2507                    rocksdb_backupable_db_options_get_destroy_old_data(bdo));
2508 
2509     rocksdb_backupable_db_options_set_backup_log_files(bdo, 1);
2510     CheckCondition(1 ==
2511                    rocksdb_backupable_db_options_get_backup_log_files(bdo));
2512 
2513     rocksdb_backupable_db_options_set_backup_rate_limit(bdo, 123);
2514     CheckCondition(123 ==
2515                    rocksdb_backupable_db_options_get_backup_rate_limit(bdo));
2516 
2517     rocksdb_backupable_db_options_set_restore_rate_limit(bdo, 37);
2518     CheckCondition(37 ==
2519                    rocksdb_backupable_db_options_get_restore_rate_limit(bdo));
2520 
2521     rocksdb_backupable_db_options_set_max_background_operations(bdo, 20);
2522     CheckCondition(
2523         20 == rocksdb_backupable_db_options_get_max_background_operations(bdo));
2524 
2525     rocksdb_backupable_db_options_set_callback_trigger_interval_size(bdo, 9000);
2526     CheckCondition(
2527         9000 ==
2528         rocksdb_backupable_db_options_get_callback_trigger_interval_size(bdo));
2529 
2530     rocksdb_backupable_db_options_set_max_valid_backups_to_open(bdo, 40);
2531     CheckCondition(
2532         40 == rocksdb_backupable_db_options_get_max_valid_backups_to_open(bdo));
2533 
2534     rocksdb_backupable_db_options_set_share_files_with_checksum_naming(bdo, 2);
2535     CheckCondition(
2536         2 == rocksdb_backupable_db_options_get_share_files_with_checksum_naming(
2537                  bdo));
2538 
2539     rocksdb_backupable_db_options_destroy(bdo);
2540   }
2541 
2542   StartPhase("compression_options");
2543   {
2544     rocksdb_options_t* co;
2545     co = rocksdb_options_create();
2546 
2547     rocksdb_options_set_compression_options_zstd_max_train_bytes(co, 100);
2548     CheckCondition(
2549         100 ==
2550         rocksdb_options_get_compression_options_zstd_max_train_bytes(co));
2551 
2552     rocksdb_options_set_compression_options_parallel_threads(co, 2);
2553     CheckCondition(
2554         2 == rocksdb_options_get_compression_options_parallel_threads(co));
2555 
2556     rocksdb_options_set_compression_options_max_dict_buffer_bytes(co, 200);
2557     CheckCondition(
2558         200 ==
2559         rocksdb_options_get_compression_options_max_dict_buffer_bytes(co));
2560 
2561     rocksdb_options_destroy(co);
2562   }
2563 
2564   StartPhase("iterate_upper_bound");
2565   {
2566     // Create new empty database
2567     rocksdb_close(db);
2568     rocksdb_destroy_db(options, dbname, &err);
2569     CheckNoError(err);
2570 
2571     rocksdb_options_set_prefix_extractor(options, NULL);
2572     db = rocksdb_open(options, dbname, &err);
2573     CheckNoError(err);
2574 
2575     rocksdb_put(db, woptions, "a",    1, "0",    1, &err); CheckNoError(err);
2576     rocksdb_put(db, woptions, "foo",  3, "bar",  3, &err); CheckNoError(err);
2577     rocksdb_put(db, woptions, "foo1", 4, "bar1", 4, &err); CheckNoError(err);
2578     rocksdb_put(db, woptions, "g1",   2, "0",    1, &err); CheckNoError(err);
2579 
2580     // testing basic case with no iterate_upper_bound and no prefix_extractor
2581     {
2582        rocksdb_readoptions_set_iterate_upper_bound(roptions, NULL, 0);
2583        rocksdb_iterator_t* iter = rocksdb_create_iterator(db, roptions);
2584 
2585        rocksdb_iter_seek(iter, "foo", 3);
2586        CheckCondition(rocksdb_iter_valid(iter));
2587        CheckIter(iter, "foo", "bar");
2588 
2589        rocksdb_iter_next(iter);
2590        CheckCondition(rocksdb_iter_valid(iter));
2591        CheckIter(iter, "foo1", "bar1");
2592 
2593        rocksdb_iter_next(iter);
2594        CheckCondition(rocksdb_iter_valid(iter));
2595        CheckIter(iter, "g1", "0");
2596 
2597        rocksdb_iter_destroy(iter);
2598     }
2599 
2600     // testing iterate_upper_bound and forward iterator
2601     // to make sure it stops at bound
2602     {
2603        // iterate_upper_bound points beyond the last expected entry
2604        rocksdb_readoptions_set_iterate_upper_bound(roptions, "foo2", 4);
2605 
2606        rocksdb_iterator_t* iter = rocksdb_create_iterator(db, roptions);
2607 
2608        rocksdb_iter_seek(iter, "foo", 3);
2609        CheckCondition(rocksdb_iter_valid(iter));
2610        CheckIter(iter, "foo", "bar");
2611 
2612        rocksdb_iter_next(iter);
2613        CheckCondition(rocksdb_iter_valid(iter));
2614        CheckIter(iter, "foo1", "bar1");
2615 
2616        rocksdb_iter_next(iter);
2617        // should stop here...
2618        CheckCondition(!rocksdb_iter_valid(iter));
2619 
2620        rocksdb_iter_destroy(iter);
2621        rocksdb_readoptions_set_iterate_upper_bound(roptions, NULL, 0);
2622     }
2623   }
2624 
2625   StartPhase("transactions");
2626   {
2627     rocksdb_close(db);
2628     rocksdb_destroy_db(options, dbname, &err);
2629     CheckNoError(err);
2630 
2631     // open a TransactionDB
2632     txn_db_options = rocksdb_transactiondb_options_create();
2633     txn_options = rocksdb_transaction_options_create();
2634     rocksdb_options_set_create_if_missing(options, 1);
2635     txn_db = rocksdb_transactiondb_open(options, txn_db_options, dbname, &err);
2636     CheckNoError(err);
2637 
2638     // put outside a transaction
2639     rocksdb_transactiondb_put(txn_db, woptions, "foo", 3, "hello", 5, &err);
2640     CheckNoError(err);
2641     CheckTxnDBGet(txn_db, roptions, "foo", "hello");
2642 
2643     // delete from outside transaction
2644     rocksdb_transactiondb_delete(txn_db, woptions, "foo", 3, &err);
2645     CheckNoError(err);
2646     CheckTxnDBGet(txn_db, roptions, "foo", NULL);
2647 
2648     // write batch into TransactionDB
2649     rocksdb_writebatch_t* wb = rocksdb_writebatch_create();
2650     rocksdb_writebatch_put(wb, "foo", 3, "a", 1);
2651     rocksdb_writebatch_clear(wb);
2652     rocksdb_writebatch_put(wb, "bar", 3, "b", 1);
2653     rocksdb_writebatch_put(wb, "box", 3, "c", 1);
2654     rocksdb_writebatch_delete(wb, "bar", 3);
2655     rocksdb_transactiondb_write(txn_db, woptions, wb, &err);
2656     rocksdb_writebatch_destroy(wb);
2657     CheckTxnDBGet(txn_db, roptions, "box", "c");
2658     CheckNoError(err);
2659 
2660     // begin a transaction
2661     txn = rocksdb_transaction_begin(txn_db, woptions, txn_options, NULL);
2662     // put
2663     rocksdb_transaction_put(txn, "foo", 3, "hello", 5, &err);
2664     CheckNoError(err);
2665     CheckTxnGet(txn, roptions, "foo", "hello");
2666     // delete
2667     rocksdb_transaction_delete(txn, "foo", 3, &err);
2668     CheckNoError(err);
2669     CheckTxnGet(txn, roptions, "foo", NULL);
2670 
2671     rocksdb_transaction_put(txn, "foo", 3, "hello", 5, &err);
2672     CheckNoError(err);
2673 
2674     // read from outside transaction, before commit
2675     CheckTxnDBGet(txn_db, roptions, "foo", NULL);
2676 
2677     // commit
2678     rocksdb_transaction_commit(txn, &err);
2679     CheckNoError(err);
2680 
2681     // read from outside transaction, after commit
2682     CheckTxnDBGet(txn_db, roptions, "foo", "hello");
2683 
2684     // reuse old transaction
2685     txn = rocksdb_transaction_begin(txn_db, woptions, txn_options, txn);
2686 
2687     // snapshot
2688     const rocksdb_snapshot_t* snapshot;
2689     snapshot = rocksdb_transactiondb_create_snapshot(txn_db);
2690     rocksdb_readoptions_set_snapshot(roptions, snapshot);
2691 
2692     rocksdb_transactiondb_put(txn_db, woptions, "foo", 3, "hey", 3,  &err);
2693     CheckNoError(err);
2694 
2695     CheckTxnDBGet(txn_db, roptions, "foo", "hello");
2696     rocksdb_readoptions_set_snapshot(roptions, NULL);
2697     rocksdb_transactiondb_release_snapshot(txn_db, snapshot);
2698     CheckTxnDBGet(txn_db, roptions, "foo", "hey");
2699 
2700     // iterate
2701     rocksdb_transaction_put(txn, "bar", 3, "hi", 2, &err);
2702     rocksdb_iterator_t* iter = rocksdb_transaction_create_iterator(txn, roptions);
2703     CheckCondition(!rocksdb_iter_valid(iter));
2704     rocksdb_iter_seek_to_first(iter);
2705     CheckCondition(rocksdb_iter_valid(iter));
2706     CheckIter(iter, "bar", "hi");
2707     rocksdb_iter_get_error(iter, &err);
2708     CheckNoError(err);
2709     rocksdb_iter_destroy(iter);
2710 
2711     // rollback
2712     rocksdb_transaction_rollback(txn, &err);
2713     CheckNoError(err);
2714     CheckTxnDBGet(txn_db, roptions, "bar", NULL);
2715 
2716     // save point
2717     rocksdb_transaction_put(txn, "foo1", 4, "hi1", 3, &err);
2718     rocksdb_transaction_set_savepoint(txn);
2719     CheckTxnGet(txn, roptions, "foo1", "hi1");
2720     rocksdb_transaction_put(txn, "foo2", 4, "hi2", 3, &err);
2721     CheckTxnGet(txn, roptions, "foo2", "hi2");
2722 
2723     // rollback to savepoint
2724     rocksdb_transaction_rollback_to_savepoint(txn, &err);
2725     CheckNoError(err);
2726     CheckTxnGet(txn, roptions, "foo2", NULL);
2727     CheckTxnGet(txn, roptions, "foo1", "hi1");
2728     CheckTxnDBGet(txn_db, roptions, "foo1", NULL);
2729     CheckTxnDBGet(txn_db, roptions, "foo2", NULL);
2730     rocksdb_transaction_commit(txn, &err);
2731     CheckNoError(err);
2732     CheckTxnDBGet(txn_db, roptions, "foo1", "hi1");
2733     CheckTxnDBGet(txn_db, roptions, "foo2", NULL);
2734 
2735     // Column families.
2736     rocksdb_column_family_handle_t* cfh;
2737     cfh = rocksdb_transactiondb_create_column_family(txn_db, options,
2738                                                      "txn_db_cf", &err);
2739     CheckNoError(err);
2740 
2741     rocksdb_transactiondb_put_cf(txn_db, woptions, cfh, "cf_foo", 6, "cf_hello",
2742                                  8, &err);
2743     CheckNoError(err);
2744     CheckTxnDBGetCF(txn_db, roptions, cfh, "cf_foo", "cf_hello");
2745 
2746     rocksdb_transactiondb_delete_cf(txn_db, woptions, cfh, "cf_foo", 6, &err);
2747     CheckNoError(err);
2748     CheckTxnDBGetCF(txn_db, roptions, cfh, "cf_foo", NULL);
2749 
2750     rocksdb_column_family_handle_destroy(cfh);
2751 
2752     // close and destroy
2753     rocksdb_transaction_destroy(txn);
2754     rocksdb_transactiondb_close(txn_db);
2755     rocksdb_destroy_db(options, dbname, &err);
2756     CheckNoError(err);
2757     rocksdb_transaction_options_destroy(txn_options);
2758     rocksdb_transactiondb_options_destroy(txn_db_options);
2759   }
2760 
2761   StartPhase("optimistic_transactions");
2762   {
2763     rocksdb_options_t* db_options = rocksdb_options_create();
2764     rocksdb_options_set_create_if_missing(db_options, 1);
2765     rocksdb_options_set_allow_concurrent_memtable_write(db_options, 1);
2766     otxn_db = rocksdb_optimistictransactiondb_open(db_options, dbname, &err);
2767     otxn_options = rocksdb_optimistictransaction_options_create();
2768     rocksdb_transaction_t* txn1 = rocksdb_optimistictransaction_begin(
2769         otxn_db, woptions, otxn_options, NULL);
2770     rocksdb_transaction_t* txn2 = rocksdb_optimistictransaction_begin(
2771         otxn_db, woptions, otxn_options, NULL);
2772     rocksdb_transaction_put(txn1, "key", 3, "value", 5, &err);
2773     CheckNoError(err);
2774     rocksdb_transaction_put(txn2, "key1", 4, "value1", 6, &err);
2775     CheckNoError(err);
2776     CheckTxnGet(txn1, roptions, "key", "value");
2777     rocksdb_transaction_commit(txn1, &err);
2778     CheckNoError(err);
2779     rocksdb_transaction_commit(txn2, &err);
2780     CheckNoError(err);
2781     rocksdb_transaction_destroy(txn1);
2782     rocksdb_transaction_destroy(txn2);
2783 
2784     // Check column family
2785     db = rocksdb_optimistictransactiondb_get_base_db(otxn_db);
2786     rocksdb_put(db, woptions, "key", 3, "value", 5, &err);
2787     CheckNoError(err);
2788     rocksdb_column_family_handle_t *cfh1, *cfh2;
2789     cfh1 = rocksdb_create_column_family(db, db_options, "txn_db_cf1", &err);
2790     cfh2 = rocksdb_create_column_family(db, db_options, "txn_db_cf2", &err);
2791     txn = rocksdb_optimistictransaction_begin(otxn_db, woptions, otxn_options,
2792                                               NULL);
2793     rocksdb_transaction_put_cf(txn, cfh1, "key_cf1", 7, "val_cf1", 7, &err);
2794     CheckNoError(err);
2795     rocksdb_transaction_put_cf(txn, cfh2, "key_cf2", 7, "val_cf2", 7, &err);
2796     CheckNoError(err);
2797     rocksdb_transaction_commit(txn, &err);
2798     CheckNoError(err);
2799     txn = rocksdb_optimistictransaction_begin(otxn_db, woptions, otxn_options,
2800                                               txn);
2801     CheckGetCF(db, roptions, cfh1, "key_cf1", "val_cf1");
2802     CheckTxnGetCF(txn, roptions, cfh1, "key_cf1", "val_cf1");
2803 
2804     // Check iterator with column family
2805     rocksdb_transaction_put_cf(txn, cfh1, "key1_cf", 7, "val1_cf", 7, &err);
2806     CheckNoError(err);
2807     rocksdb_iterator_t* iter =
2808         rocksdb_transaction_create_iterator_cf(txn, roptions, cfh1);
2809     CheckCondition(!rocksdb_iter_valid(iter));
2810     rocksdb_iter_seek_to_first(iter);
2811     CheckCondition(rocksdb_iter_valid(iter));
2812     CheckIter(iter, "key1_cf", "val1_cf");
2813     rocksdb_iter_get_error(iter, &err);
2814     CheckNoError(err);
2815     rocksdb_iter_destroy(iter);
2816 
2817     rocksdb_transaction_destroy(txn);
2818     rocksdb_column_family_handle_destroy(cfh1);
2819     rocksdb_column_family_handle_destroy(cfh2);
2820     rocksdb_optimistictransactiondb_close_base_db(db);
2821     rocksdb_optimistictransactiondb_close(otxn_db);
2822 
2823     // Check open optimistic transaction db with column families
2824     size_t cf_len;
2825     char** column_fams =
2826         rocksdb_list_column_families(db_options, dbname, &cf_len, &err);
2827     CheckNoError(err);
2828     CheckEqual("default", column_fams[0], 7);
2829     CheckEqual("txn_db_cf1", column_fams[1], 10);
2830     CheckEqual("txn_db_cf2", column_fams[2], 10);
2831     CheckCondition(cf_len == 3);
2832     rocksdb_list_column_families_destroy(column_fams, cf_len);
2833 
2834     const char* cf_names[3] = {"default", "txn_db_cf1", "txn_db_cf2"};
2835     rocksdb_options_t* cf_options = rocksdb_options_create();
2836     const rocksdb_options_t* cf_opts[3] = {cf_options, cf_options, cf_options};
2837 
2838     rocksdb_options_set_error_if_exists(cf_options, 0);
2839     rocksdb_column_family_handle_t* cf_handles[3];
2840     otxn_db = rocksdb_optimistictransactiondb_open_column_families(
2841         db_options, dbname, 3, cf_names, cf_opts, cf_handles, &err);
2842     CheckNoError(err);
2843     rocksdb_transaction_t* txn_cf = rocksdb_optimistictransaction_begin(
2844         otxn_db, woptions, otxn_options, NULL);
2845     CheckTxnGetCF(txn_cf, roptions, cf_handles[0], "key", "value");
2846     CheckTxnGetCF(txn_cf, roptions, cf_handles[1], "key_cf1", "val_cf1");
2847     CheckTxnGetCF(txn_cf, roptions, cf_handles[2], "key_cf2", "val_cf2");
2848     rocksdb_transaction_destroy(txn_cf);
2849     rocksdb_options_destroy(cf_options);
2850     rocksdb_column_family_handle_destroy(cf_handles[0]);
2851     rocksdb_column_family_handle_destroy(cf_handles[1]);
2852     rocksdb_column_family_handle_destroy(cf_handles[2]);
2853     rocksdb_optimistictransactiondb_close(otxn_db);
2854     rocksdb_destroy_db(db_options, dbname, &err);
2855     rocksdb_options_destroy(db_options);
2856     rocksdb_optimistictransaction_options_destroy(otxn_options);
2857     CheckNoError(err);
2858   }
2859 
2860   // Simple sanity check that setting memtable rep works.
2861   StartPhase("memtable_reps");
2862   {
2863     // Create database with vector memtable.
2864     rocksdb_options_set_memtable_vector_rep(options);
2865     db = rocksdb_open(options, dbname, &err);
2866     CheckNoError(err);
2867 
2868     // Create database with hash skiplist memtable.
2869     rocksdb_close(db);
2870     rocksdb_destroy_db(options, dbname, &err);
2871     CheckNoError(err);
2872 
2873     rocksdb_options_set_hash_skip_list_rep(options, 5000, 4, 4);
2874     db = rocksdb_open(options, dbname, &err);
2875     CheckNoError(err);
2876   }
2877 
2878   // Check that secondary instance works.
2879   StartPhase("open_as_secondary");
2880   {
2881     rocksdb_close(db);
2882     rocksdb_destroy_db(options, dbname, &err);
2883 
2884     rocksdb_options_t* db_options = rocksdb_options_create();
2885     rocksdb_options_set_create_if_missing(db_options, 1);
2886     db = rocksdb_open(db_options, dbname, &err);
2887     CheckNoError(err);
2888     rocksdb_t* db1;
2889     rocksdb_options_t* opts = rocksdb_options_create();
2890     rocksdb_options_set_max_open_files(opts, -1);
2891     rocksdb_options_set_create_if_missing(opts, 1);
2892     snprintf(secondary_path, sizeof(secondary_path),
2893              "%s/rocksdb_c_test_secondary-%d", GetTempDir(), ((int)geteuid()));
2894     db1 = rocksdb_open_as_secondary(opts, dbname, secondary_path, &err);
2895     CheckNoError(err);
2896 
2897     rocksdb_writeoptions_set_sync(woptions, 0);
2898     rocksdb_writeoptions_disable_WAL(woptions, 1);
2899     rocksdb_put(db, woptions, "key0", 4, "value0", 6, &err);
2900     CheckNoError(err);
2901     rocksdb_flushoptions_t* flush_opts = rocksdb_flushoptions_create();
2902     rocksdb_flushoptions_set_wait(flush_opts, 1);
2903     rocksdb_flush(db, flush_opts, &err);
2904     CheckNoError(err);
2905     rocksdb_try_catch_up_with_primary(db1, &err);
2906     CheckNoError(err);
2907     rocksdb_readoptions_t* ropts = rocksdb_readoptions_create();
2908     rocksdb_readoptions_set_verify_checksums(ropts, 1);
2909     rocksdb_readoptions_set_snapshot(ropts, NULL);
2910     CheckGet(db, ropts, "key0", "value0");
2911     CheckGet(db1, ropts, "key0", "value0");
2912 
2913     rocksdb_writeoptions_disable_WAL(woptions, 0);
2914     rocksdb_put(db, woptions, "key1", 4, "value1", 6, &err);
2915     CheckNoError(err);
2916     rocksdb_try_catch_up_with_primary(db1, &err);
2917     CheckNoError(err);
2918     CheckGet(db1, ropts, "key0", "value0");
2919     CheckGet(db1, ropts, "key1", "value1");
2920 
2921     rocksdb_close(db1);
2922     rocksdb_destroy_db(opts, secondary_path, &err);
2923     CheckNoError(err);
2924 
2925     rocksdb_options_destroy(db_options);
2926     rocksdb_options_destroy(opts);
2927     rocksdb_readoptions_destroy(ropts);
2928     rocksdb_flushoptions_destroy(flush_opts);
2929   }
2930 
2931   // Simple sanity check that options setting db_paths work.
2932   StartPhase("open_db_paths");
2933   {
2934     rocksdb_close(db);
2935     rocksdb_destroy_db(options, dbname, &err);
2936 
2937     const rocksdb_dbpath_t* paths[1] = {dbpath};
2938     rocksdb_options_set_db_paths(options, paths, 1);
2939     db = rocksdb_open(options, dbname, &err);
2940     CheckNoError(err);
2941   }
2942 
2943   StartPhase("cancel_all_background_work");
2944   rocksdb_cancel_all_background_work(db, 1);
2945 
2946   StartPhase("cleanup");
2947   rocksdb_close(db);
2948   rocksdb_options_destroy(options);
2949   rocksdb_block_based_options_destroy(table_options);
2950   rocksdb_readoptions_destroy(roptions);
2951   rocksdb_writeoptions_destroy(woptions);
2952   rocksdb_compactoptions_destroy(coptions);
2953   rocksdb_cache_destroy(cache);
2954   rocksdb_comparator_destroy(cmp);
2955   rocksdb_dbpath_destroy(dbpath);
2956   rocksdb_env_destroy(env);
2957 
2958   fprintf(stderr, "PASS\n");
2959   return 0;
2960 }
2961 
2962 #else
2963 
main(void)2964 int main(void) {
2965   fprintf(stderr, "SKIPPED\n");
2966   return 0;
2967 }
2968 
2969 #endif  // !ROCKSDB_LITE
2970