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. */
7 #ifndef ROCKSDB_LITE // Lite does not support C API
14 #include <sys/types.h>
20 // Can not use port/port.h macros as this is a c file
28 result
= ((int)GetCurrentProcessId() << 16);
29 result
|= (int)GetCurrentThreadId();
35 #if defined(_MSC_VER) && (_MSC_VER < 1900)
36 #define snprintf _snprintf
41 const char* phase
= "";
42 static char dbname
[200];
43 static char sstfilename
[200];
44 static char dbbackupname
[200];
45 static char dbcheckpointname
[200];
46 static char dbpathname
[200];
48 static void StartPhase(const char* name
) {
49 fprintf(stderr
, "=== Test %s\n", name
);
54 #pragma warning (disable: 4996) // getenv security warning
56 static const char* GetTempDir(void) {
57 const char* ret
= getenv("TEST_TMPDIR");
58 if (ret
== NULL
|| ret
[0] == '\0')
66 #define CheckNoError(err) \
67 if ((err) != NULL) { \
68 fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, (err)); \
72 #define CheckCondition(cond) \
74 fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, #cond); \
78 static void CheckEqual(const char* expected
, const char* v
, size_t n
) {
79 if (expected
== NULL
&& v
== NULL
) {
81 } else if (expected
!= NULL
&& v
!= NULL
&& n
== strlen(expected
) &&
82 memcmp(expected
, v
, n
) == 0) {
86 fprintf(stderr
, "%s: expected '%s', got '%s'\n",
88 (expected
? expected
: "(null)"),
94 static void Free(char** ptr
) {
101 static void CheckValue(
103 const char* expected
,
105 size_t actual_length
) {
107 CheckEqual(expected
, *actual
, actual_length
);
111 static void CheckGet(
113 const rocksdb_readoptions_t
* options
,
115 const char* expected
) {
119 val
= rocksdb_get(db
, options
, key
, strlen(key
), &val_len
, &err
);
121 CheckEqual(expected
, val
, val_len
);
125 static void CheckGetCF(
127 const rocksdb_readoptions_t
* options
,
128 rocksdb_column_family_handle_t
* handle
,
130 const char* expected
) {
134 val
= rocksdb_get_cf(db
, options
, handle
, key
, strlen(key
), &val_len
, &err
);
136 CheckEqual(expected
, val
, val_len
);
140 static void CheckPinGet(rocksdb_t
* db
, const rocksdb_readoptions_t
* options
,
141 const char* key
, const char* expected
) {
145 rocksdb_pinnableslice_t
* p
;
146 p
= rocksdb_get_pinned(db
, options
, key
, strlen(key
), &err
);
148 val
= rocksdb_pinnableslice_value(p
, &val_len
);
149 CheckEqual(expected
, val
, val_len
);
150 rocksdb_pinnableslice_destroy(p
);
153 static void CheckPinGetCF(rocksdb_t
* db
, const rocksdb_readoptions_t
* options
,
154 rocksdb_column_family_handle_t
* handle
,
155 const char* key
, const char* expected
) {
159 rocksdb_pinnableslice_t
* p
;
160 p
= rocksdb_get_pinned_cf(db
, options
, handle
, key
, strlen(key
), &err
);
162 val
= rocksdb_pinnableslice_value(p
, &val_len
);
163 CheckEqual(expected
, val
, val_len
);
164 rocksdb_pinnableslice_destroy(p
);
167 static void CheckIter(rocksdb_iterator_t
* iter
,
168 const char* key
, const char* val
) {
171 str
= rocksdb_iter_key(iter
, &len
);
172 CheckEqual(key
, str
, len
);
173 str
= rocksdb_iter_value(iter
, &len
);
174 CheckEqual(val
, str
, len
);
177 // Callback from rocksdb_writebatch_iterate()
178 static void CheckPut(void* ptr
,
179 const char* k
, size_t klen
,
180 const char* v
, size_t vlen
) {
181 int* state
= (int*) ptr
;
182 CheckCondition(*state
< 2);
185 CheckEqual("bar", k
, klen
);
186 CheckEqual("b", v
, vlen
);
189 CheckEqual("box", k
, klen
);
190 CheckEqual("c", v
, vlen
);
196 // Callback from rocksdb_writebatch_iterate()
197 static void CheckDel(void* ptr
, const char* k
, size_t klen
) {
198 int* state
= (int*) ptr
;
199 CheckCondition(*state
== 2);
200 CheckEqual("bar", k
, klen
);
204 static void CmpDestroy(void* arg
) { (void)arg
; }
206 static int CmpCompare(void* arg
, const char* a
, size_t alen
,
207 const char* b
, size_t blen
) {
209 size_t n
= (alen
< blen
) ? alen
: blen
;
210 int r
= memcmp(a
, b
, n
);
212 if (alen
< blen
) r
= -1;
213 else if (alen
> blen
) r
= +1;
218 static const char* CmpName(void* arg
) {
223 // Custom filter policy
224 static unsigned char fake_filter_result
= 1;
225 static void FilterDestroy(void* arg
) { (void)arg
; }
226 static const char* FilterName(void* arg
) {
230 static char* FilterCreate(
232 const char* const* key_array
, const size_t* key_length_array
,
234 size_t* filter_length
) {
237 (void)key_length_array
;
240 char* result
= malloc(4);
241 memcpy(result
, "fake", 4);
244 static unsigned char FilterKeyMatch(
246 const char* key
, size_t length
,
247 const char* filter
, size_t filter_length
) {
251 CheckCondition(filter_length
== 4);
252 CheckCondition(memcmp(filter
, "fake", 4) == 0);
253 return fake_filter_result
;
256 // Custom compaction filter
257 static void CFilterDestroy(void* arg
) { (void)arg
; }
258 static const char* CFilterName(void* arg
) {
262 static unsigned char CFilterFilter(void* arg
, int level
, const char* key
,
264 const char* existing_value
,
265 size_t value_length
, char** new_value
,
266 size_t* new_value_length
,
267 unsigned char* value_changed
) {
270 (void)existing_value
;
272 if (key_length
== 3) {
273 if (memcmp(key
, "bar", key_length
) == 0) {
275 } else if (memcmp(key
, "baz", key_length
) == 0) {
277 *new_value
= "newbazvalue";
278 *new_value_length
= 11;
285 static void CFilterFactoryDestroy(void* arg
) { (void)arg
; }
286 static const char* CFilterFactoryName(void* arg
) {
290 static rocksdb_compactionfilter_t
* CFilterCreate(
291 void* arg
, rocksdb_compactionfiltercontext_t
* context
) {
294 return rocksdb_compactionfilter_create(NULL
, CFilterDestroy
, CFilterFilter
,
298 static rocksdb_t
* CheckCompaction(rocksdb_t
* db
, rocksdb_options_t
* options
,
299 rocksdb_readoptions_t
* roptions
,
300 rocksdb_writeoptions_t
* woptions
) {
302 db
= rocksdb_open(options
, dbname
, &err
);
304 rocksdb_put(db
, woptions
, "foo", 3, "foovalue", 8, &err
);
306 CheckGet(db
, roptions
, "foo", "foovalue");
307 rocksdb_put(db
, woptions
, "bar", 3, "barvalue", 8, &err
);
309 CheckGet(db
, roptions
, "bar", "barvalue");
310 rocksdb_put(db
, woptions
, "baz", 3, "bazvalue", 8, &err
);
312 CheckGet(db
, roptions
, "baz", "bazvalue");
315 rocksdb_compact_range(db
, NULL
, 0, NULL
, 0);
316 // should have filtered bar, but not foo
317 CheckGet(db
, roptions
, "foo", "foovalue");
318 CheckGet(db
, roptions
, "bar", NULL
);
319 CheckGet(db
, roptions
, "baz", "newbazvalue");
323 // Custom merge operator
324 static void MergeOperatorDestroy(void* arg
) { (void)arg
; }
325 static const char* MergeOperatorName(void* arg
) {
327 return "TestMergeOperator";
329 static char* MergeOperatorFullMerge(
331 const char* key
, size_t key_length
,
332 const char* existing_value
, size_t existing_value_length
,
333 const char* const* operands_list
, const size_t* operands_list_length
,
335 unsigned char* success
, size_t* new_value_length
) {
339 (void)existing_value
;
340 (void)existing_value_length
;
342 (void)operands_list_length
;
344 *new_value_length
= 4;
346 char* result
= malloc(4);
347 memcpy(result
, "fake", 4);
350 static char* MergeOperatorPartialMerge(
352 const char* key
, size_t key_length
,
353 const char* const* operands_list
, const size_t* operands_list_length
,
355 unsigned char* success
, size_t* new_value_length
) {
360 (void)operands_list_length
;
362 *new_value_length
= 4;
364 char* result
= malloc(4);
365 memcpy(result
, "fake", 4);
369 static void CheckTxnGet(
370 rocksdb_transaction_t
* txn
,
371 const rocksdb_readoptions_t
* options
,
373 const char* expected
) {
377 val
= rocksdb_transaction_get(txn
, options
, key
, strlen(key
), &val_len
, &err
);
379 CheckEqual(expected
, val
, val_len
);
383 static void CheckTxnGetCF(rocksdb_transaction_t
* txn
,
384 const rocksdb_readoptions_t
* options
,
385 rocksdb_column_family_handle_t
* column_family
,
386 const char* key
, const char* expected
) {
390 val
= rocksdb_transaction_get_cf(txn
, options
, column_family
, key
,
391 strlen(key
), &val_len
, &err
);
393 CheckEqual(expected
, val
, val_len
);
397 static void CheckTxnDBGet(
398 rocksdb_transactiondb_t
* txn_db
,
399 const rocksdb_readoptions_t
* options
,
401 const char* expected
) {
405 val
= rocksdb_transactiondb_get(txn_db
, options
, key
, strlen(key
), &val_len
, &err
);
407 CheckEqual(expected
, val
, val_len
);
411 static void CheckTxnDBGetCF(rocksdb_transactiondb_t
* txn_db
,
412 const rocksdb_readoptions_t
* options
,
413 rocksdb_column_family_handle_t
* column_family
,
414 const char* key
, const char* expected
) {
418 val
= rocksdb_transactiondb_get_cf(txn_db
, options
, column_family
, key
,
419 strlen(key
), &val_len
, &err
);
421 CheckEqual(expected
, val
, val_len
);
425 int main(int argc
, char** argv
) {
429 rocksdb_comparator_t
* cmp
;
430 rocksdb_cache_t
* cache
;
431 rocksdb_dbpath_t
*dbpath
;
433 rocksdb_options_t
* options
;
434 rocksdb_compactoptions_t
* coptions
;
435 rocksdb_block_based_table_options_t
* table_options
;
436 rocksdb_readoptions_t
* roptions
;
437 rocksdb_writeoptions_t
* woptions
;
438 rocksdb_ratelimiter_t
* rate_limiter
;
439 rocksdb_transactiondb_t
* txn_db
;
440 rocksdb_transactiondb_options_t
* txn_db_options
;
441 rocksdb_transaction_t
* txn
;
442 rocksdb_transaction_options_t
* txn_options
;
443 rocksdb_optimistictransactiondb_t
* otxn_db
;
444 rocksdb_optimistictransaction_options_t
* otxn_options
;
448 snprintf(dbname
, sizeof(dbname
),
449 "%s/rocksdb_c_test-%d",
453 snprintf(dbbackupname
, sizeof(dbbackupname
),
454 "%s/rocksdb_c_test-%d-backup",
458 snprintf(dbcheckpointname
, sizeof(dbcheckpointname
),
459 "%s/rocksdb_c_test-%d-checkpoint",
463 snprintf(sstfilename
, sizeof(sstfilename
),
464 "%s/rocksdb_c_test-%d-sst",
468 snprintf(dbpathname
, sizeof(dbpathname
),
469 "%s/rocksdb_c_test-%d-dbpath",
473 StartPhase("create_objects");
474 cmp
= rocksdb_comparator_create(NULL
, CmpDestroy
, CmpCompare
, CmpName
);
475 dbpath
= rocksdb_dbpath_create(dbpathname
, 1024 * 1024);
476 env
= rocksdb_create_default_env();
477 cache
= rocksdb_cache_create_lru(100000);
479 options
= rocksdb_options_create();
480 rocksdb_options_set_comparator(options
, cmp
);
481 rocksdb_options_set_error_if_exists(options
, 1);
482 rocksdb_options_set_env(options
, env
);
483 rocksdb_options_set_info_log(options
, NULL
);
484 rocksdb_options_set_write_buffer_size(options
, 100000);
485 rocksdb_options_set_paranoid_checks(options
, 1);
486 rocksdb_options_set_max_open_files(options
, 10);
487 rocksdb_options_set_base_background_compactions(options
, 1);
488 table_options
= rocksdb_block_based_options_create();
489 rocksdb_block_based_options_set_block_cache(table_options
, cache
);
490 rocksdb_options_set_block_based_table_factory(options
, table_options
);
492 rocksdb_options_set_compression(options
, rocksdb_no_compression
);
493 rocksdb_options_set_compression_options(options
, -14, -1, 0, 0);
494 int compression_levels
[] = {rocksdb_no_compression
, rocksdb_no_compression
,
495 rocksdb_no_compression
, rocksdb_no_compression
};
496 rocksdb_options_set_compression_per_level(options
, compression_levels
, 4);
497 rate_limiter
= rocksdb_ratelimiter_create(1000 * 1024 * 1024, 100 * 1000, 10);
498 rocksdb_options_set_ratelimiter(options
, rate_limiter
);
499 rocksdb_ratelimiter_destroy(rate_limiter
);
501 roptions
= rocksdb_readoptions_create();
502 rocksdb_readoptions_set_verify_checksums(roptions
, 1);
503 rocksdb_readoptions_set_fill_cache(roptions
, 1);
505 woptions
= rocksdb_writeoptions_create();
506 rocksdb_writeoptions_set_sync(woptions
, 1);
508 coptions
= rocksdb_compactoptions_create();
509 rocksdb_compactoptions_set_exclusive_manual_compaction(coptions
, 1);
511 StartPhase("destroy");
512 rocksdb_destroy_db(options
, dbname
, &err
);
515 StartPhase("open_error");
516 rocksdb_open(options
, dbname
, &err
);
517 CheckCondition(err
!= NULL
);
521 rocksdb_options_set_create_if_missing(options
, 1);
522 db
= rocksdb_open(options
, dbname
, &err
);
524 CheckGet(db
, roptions
, "foo", NULL
);
527 rocksdb_put(db
, woptions
, "foo", 3, "hello", 5, &err
);
529 CheckGet(db
, roptions
, "foo", "hello");
531 StartPhase("backup_and_restore");
533 rocksdb_destroy_db(options
, dbbackupname
, &err
);
536 rocksdb_backup_engine_t
*be
= rocksdb_backup_engine_open(options
, dbbackupname
, &err
);
539 rocksdb_backup_engine_create_new_backup(be
, db
, &err
);
542 // need a change to trigger a new backup
543 rocksdb_delete(db
, woptions
, "does-not-exist", 14, &err
);
546 rocksdb_backup_engine_create_new_backup(be
, db
, &err
);
549 const rocksdb_backup_engine_info_t
* bei
= rocksdb_backup_engine_get_backup_info(be
);
550 CheckCondition(rocksdb_backup_engine_info_count(bei
) > 1);
551 rocksdb_backup_engine_info_destroy(bei
);
553 rocksdb_backup_engine_purge_old_backups(be
, 1, &err
);
556 bei
= rocksdb_backup_engine_get_backup_info(be
);
557 CheckCondition(rocksdb_backup_engine_info_count(bei
) == 1);
558 rocksdb_backup_engine_info_destroy(bei
);
560 rocksdb_delete(db
, woptions
, "foo", 3, &err
);
565 rocksdb_destroy_db(options
, dbname
, &err
);
568 rocksdb_restore_options_t
*restore_options
= rocksdb_restore_options_create();
569 rocksdb_restore_options_set_keep_log_files(restore_options
, 0);
570 rocksdb_backup_engine_restore_db_from_latest_backup(be
, dbname
, dbname
, restore_options
, &err
);
572 rocksdb_restore_options_destroy(restore_options
);
574 rocksdb_options_set_error_if_exists(options
, 0);
575 db
= rocksdb_open(options
, dbname
, &err
);
577 rocksdb_options_set_error_if_exists(options
, 1);
579 CheckGet(db
, roptions
, "foo", "hello");
581 rocksdb_backup_engine_close(be
);
584 StartPhase("checkpoint");
586 rocksdb_destroy_db(options
, dbcheckpointname
, &err
);
589 rocksdb_checkpoint_t
* checkpoint
= rocksdb_checkpoint_object_create(db
, &err
);
592 rocksdb_checkpoint_create(checkpoint
, dbcheckpointname
, 0, &err
);
595 // start a new database from the checkpoint
597 rocksdb_options_set_error_if_exists(options
, 0);
598 db
= rocksdb_open(options
, dbcheckpointname
, &err
);
601 CheckGet(db
, roptions
, "foo", "hello");
603 rocksdb_checkpoint_object_destroy(checkpoint
);
606 rocksdb_destroy_db(options
, dbcheckpointname
, &err
);
609 db
= rocksdb_open(options
, dbname
, &err
);
611 rocksdb_options_set_error_if_exists(options
, 1);
614 StartPhase("compactall");
615 rocksdb_compact_range(db
, NULL
, 0, NULL
, 0);
616 CheckGet(db
, roptions
, "foo", "hello");
618 StartPhase("compactrange");
619 rocksdb_compact_range(db
, "a", 1, "z", 1);
620 CheckGet(db
, roptions
, "foo", "hello");
622 StartPhase("compactallopt");
623 rocksdb_compact_range_opt(db
, coptions
, NULL
, 0, NULL
, 0);
624 CheckGet(db
, roptions
, "foo", "hello");
626 StartPhase("compactrangeopt");
627 rocksdb_compact_range_opt(db
, coptions
, "a", 1, "z", 1);
628 CheckGet(db
, roptions
, "foo", "hello");
630 // Simple check cache usage
631 StartPhase("cache_usage");
633 rocksdb_readoptions_set_pin_data(roptions
, 1);
634 rocksdb_iterator_t
* iter
= rocksdb_create_iterator(db
, roptions
);
635 rocksdb_iter_seek(iter
, "foo", 3);
637 size_t usage
= rocksdb_cache_get_usage(cache
);
638 CheckCondition(usage
> 0);
640 size_t pin_usage
= rocksdb_cache_get_pinned_usage(cache
);
641 CheckCondition(pin_usage
> 0);
643 rocksdb_iter_next(iter
);
644 rocksdb_iter_destroy(iter
);
645 rocksdb_readoptions_set_pin_data(roptions
, 0);
648 StartPhase("addfile");
650 rocksdb_envoptions_t
* env_opt
= rocksdb_envoptions_create();
651 rocksdb_options_t
* io_options
= rocksdb_options_create();
652 rocksdb_sstfilewriter_t
* writer
=
653 rocksdb_sstfilewriter_create(env_opt
, io_options
);
656 rocksdb_sstfilewriter_open(writer
, sstfilename
, &err
);
658 rocksdb_sstfilewriter_put(writer
, "sstk1", 5, "v1", 2, &err
);
660 rocksdb_sstfilewriter_put(writer
, "sstk2", 5, "v2", 2, &err
);
662 rocksdb_sstfilewriter_put(writer
, "sstk3", 5, "v3", 2, &err
);
664 rocksdb_sstfilewriter_finish(writer
, &err
);
667 rocksdb_ingestexternalfileoptions_t
* ing_opt
=
668 rocksdb_ingestexternalfileoptions_create();
669 const char* file_list
[1] = {sstfilename
};
670 rocksdb_ingest_external_file(db
, file_list
, 1, ing_opt
, &err
);
672 CheckGet(db
, roptions
, "sstk1", "v1");
673 CheckGet(db
, roptions
, "sstk2", "v2");
674 CheckGet(db
, roptions
, "sstk3", "v3");
677 rocksdb_sstfilewriter_open(writer
, sstfilename
, &err
);
679 rocksdb_sstfilewriter_put(writer
, "sstk2", 5, "v4", 2, &err
);
681 rocksdb_sstfilewriter_put(writer
, "sstk22", 6, "v5", 2, &err
);
683 rocksdb_sstfilewriter_put(writer
, "sstk3", 5, "v6", 2, &err
);
685 rocksdb_sstfilewriter_finish(writer
, &err
);
688 rocksdb_ingest_external_file(db
, file_list
, 1, ing_opt
, &err
);
690 CheckGet(db
, roptions
, "sstk1", "v1");
691 CheckGet(db
, roptions
, "sstk2", "v4");
692 CheckGet(db
, roptions
, "sstk22", "v5");
693 CheckGet(db
, roptions
, "sstk3", "v6");
695 rocksdb_ingestexternalfileoptions_destroy(ing_opt
);
696 rocksdb_sstfilewriter_destroy(writer
);
697 rocksdb_options_destroy(io_options
);
698 rocksdb_envoptions_destroy(env_opt
);
700 // Delete all keys we just ingested
701 rocksdb_delete(db
, woptions
, "sstk1", 5, &err
);
703 rocksdb_delete(db
, woptions
, "sstk2", 5, &err
);
705 rocksdb_delete(db
, woptions
, "sstk22", 6, &err
);
707 rocksdb_delete(db
, woptions
, "sstk3", 5, &err
);
711 StartPhase("writebatch");
713 rocksdb_writebatch_t
* wb
= rocksdb_writebatch_create();
714 rocksdb_writebatch_put(wb
, "foo", 3, "a", 1);
715 rocksdb_writebatch_clear(wb
);
716 rocksdb_writebatch_put(wb
, "bar", 3, "b", 1);
717 rocksdb_writebatch_put(wb
, "box", 3, "c", 1);
718 rocksdb_writebatch_delete(wb
, "bar", 3);
719 rocksdb_write(db
, woptions
, wb
, &err
);
721 CheckGet(db
, roptions
, "foo", "hello");
722 CheckGet(db
, roptions
, "bar", NULL
);
723 CheckGet(db
, roptions
, "box", "c");
725 rocksdb_writebatch_iterate(wb
, &pos
, CheckPut
, CheckDel
);
726 CheckCondition(pos
== 3);
727 rocksdb_writebatch_clear(wb
);
728 rocksdb_writebatch_put(wb
, "bar", 3, "b", 1);
729 rocksdb_writebatch_put(wb
, "bay", 3, "d", 1);
730 rocksdb_writebatch_delete_range(wb
, "bar", 3, "bay", 3);
731 rocksdb_write(db
, woptions
, wb
, &err
);
733 CheckGet(db
, roptions
, "bar", NULL
);
734 CheckGet(db
, roptions
, "bay", "d");
735 rocksdb_writebatch_clear(wb
);
736 const char* start_list
[1] = {"bay"};
737 const size_t start_sizes
[1] = {3};
738 const char* end_list
[1] = {"baz"};
739 const size_t end_sizes
[1] = {3};
740 rocksdb_writebatch_delete_rangev(wb
, 1, start_list
, start_sizes
, end_list
,
742 rocksdb_write(db
, woptions
, wb
, &err
);
744 CheckGet(db
, roptions
, "bay", NULL
);
745 rocksdb_writebatch_destroy(wb
);
748 StartPhase("writebatch_vectors");
750 rocksdb_writebatch_t
* wb
= rocksdb_writebatch_create();
751 const char* k_list
[2] = { "z", "ap" };
752 const size_t k_sizes
[2] = { 1, 2 };
753 const char* v_list
[3] = { "x", "y", "z" };
754 const size_t v_sizes
[3] = { 1, 1, 1 };
755 rocksdb_writebatch_putv(wb
, 2, k_list
, k_sizes
, 3, v_list
, v_sizes
);
756 rocksdb_write(db
, woptions
, wb
, &err
);
758 CheckGet(db
, roptions
, "zap", "xyz");
759 rocksdb_writebatch_delete(wb
, "zap", 3);
760 rocksdb_write(db
, woptions
, wb
, &err
);
762 CheckGet(db
, roptions
, "zap", NULL
);
763 rocksdb_writebatch_destroy(wb
);
766 StartPhase("writebatch_savepoint");
768 rocksdb_writebatch_t
* wb
= rocksdb_writebatch_create();
769 rocksdb_writebatch_set_save_point(wb
);
770 rocksdb_writebatch_set_save_point(wb
);
771 const char* k_list
[2] = {"z", "ap"};
772 const size_t k_sizes
[2] = {1, 2};
773 const char* v_list
[3] = {"x", "y", "z"};
774 const size_t v_sizes
[3] = {1, 1, 1};
775 rocksdb_writebatch_pop_save_point(wb
, &err
);
777 rocksdb_writebatch_putv(wb
, 2, k_list
, k_sizes
, 3, v_list
, v_sizes
);
778 rocksdb_writebatch_rollback_to_save_point(wb
, &err
);
780 rocksdb_write(db
, woptions
, wb
, &err
);
782 CheckGet(db
, roptions
, "zap", NULL
);
783 rocksdb_writebatch_destroy(wb
);
786 StartPhase("writebatch_rep");
788 rocksdb_writebatch_t
* wb1
= rocksdb_writebatch_create();
789 rocksdb_writebatch_put(wb1
, "baz", 3, "d", 1);
790 rocksdb_writebatch_put(wb1
, "quux", 4, "e", 1);
791 rocksdb_writebatch_delete(wb1
, "quux", 4);
793 const char* rep
= rocksdb_writebatch_data(wb1
, &repsize1
);
794 rocksdb_writebatch_t
* wb2
= rocksdb_writebatch_create_from(rep
, repsize1
);
795 CheckCondition(rocksdb_writebatch_count(wb1
) ==
796 rocksdb_writebatch_count(wb2
));
799 memcmp(rep
, rocksdb_writebatch_data(wb2
, &repsize2
), repsize1
) == 0);
800 rocksdb_writebatch_destroy(wb1
);
801 rocksdb_writebatch_destroy(wb2
);
804 StartPhase("writebatch_wi");
806 rocksdb_writebatch_wi_t
* wbi
= rocksdb_writebatch_wi_create(0, 1);
807 rocksdb_writebatch_wi_put(wbi
, "foo", 3, "a", 1);
808 rocksdb_writebatch_wi_clear(wbi
);
809 rocksdb_writebatch_wi_put(wbi
, "bar", 3, "b", 1);
810 rocksdb_writebatch_wi_put(wbi
, "box", 3, "c", 1);
811 rocksdb_writebatch_wi_delete(wbi
, "bar", 3);
812 int count
= rocksdb_writebatch_wi_count(wbi
);
813 CheckCondition(count
== 3);
816 value
= rocksdb_writebatch_wi_get_from_batch(wbi
, options
, "box", 3, &size
, &err
);
817 CheckValue(err
, "c", &value
, size
);
818 value
= rocksdb_writebatch_wi_get_from_batch(wbi
, options
, "bar", 3, &size
, &err
);
819 CheckValue(err
, NULL
, &value
, size
);
820 value
= rocksdb_writebatch_wi_get_from_batch_and_db(wbi
, db
, roptions
, "foo", 3, &size
, &err
);
821 CheckValue(err
, "hello", &value
, size
);
822 value
= rocksdb_writebatch_wi_get_from_batch_and_db(wbi
, db
, roptions
, "box", 3, &size
, &err
);
823 CheckValue(err
, "c", &value
, size
);
824 rocksdb_write_writebatch_wi(db
, woptions
, wbi
, &err
);
826 CheckGet(db
, roptions
, "foo", "hello");
827 CheckGet(db
, roptions
, "bar", NULL
);
828 CheckGet(db
, roptions
, "box", "c");
830 rocksdb_writebatch_wi_iterate(wbi
, &pos
, CheckPut
, CheckDel
);
831 CheckCondition(pos
== 3);
832 rocksdb_writebatch_wi_clear(wbi
);
833 rocksdb_writebatch_wi_put(wbi
, "bar", 3, "b", 1);
834 rocksdb_writebatch_wi_put(wbi
, "bay", 3, "d", 1);
835 rocksdb_writebatch_wi_delete_range(wbi
, "bar", 3, "bay", 3);
836 rocksdb_write_writebatch_wi(db
, woptions
, wbi
, &err
);
838 CheckGet(db
, roptions
, "bar", NULL
);
839 CheckGet(db
, roptions
, "bay", "d");
840 rocksdb_writebatch_wi_clear(wbi
);
841 const char* start_list
[1] = {"bay"};
842 const size_t start_sizes
[1] = {3};
843 const char* end_list
[1] = {"baz"};
844 const size_t end_sizes
[1] = {3};
845 rocksdb_writebatch_wi_delete_rangev(wbi
, 1, start_list
, start_sizes
, end_list
,
847 rocksdb_write_writebatch_wi(db
, woptions
, wbi
, &err
);
849 CheckGet(db
, roptions
, "bay", NULL
);
850 rocksdb_writebatch_wi_destroy(wbi
);
853 StartPhase("writebatch_wi_vectors");
855 rocksdb_writebatch_wi_t
* wb
= rocksdb_writebatch_wi_create(0, 1);
856 const char* k_list
[2] = { "z", "ap" };
857 const size_t k_sizes
[2] = { 1, 2 };
858 const char* v_list
[3] = { "x", "y", "z" };
859 const size_t v_sizes
[3] = { 1, 1, 1 };
860 rocksdb_writebatch_wi_putv(wb
, 2, k_list
, k_sizes
, 3, v_list
, v_sizes
);
861 rocksdb_write_writebatch_wi(db
, woptions
, wb
, &err
);
863 CheckGet(db
, roptions
, "zap", "xyz");
864 rocksdb_writebatch_wi_delete(wb
, "zap", 3);
865 rocksdb_write_writebatch_wi(db
, woptions
, wb
, &err
);
867 CheckGet(db
, roptions
, "zap", NULL
);
868 rocksdb_writebatch_wi_destroy(wb
);
871 StartPhase("writebatch_wi_savepoint");
873 rocksdb_writebatch_wi_t
* wb
= rocksdb_writebatch_wi_create(0, 1);
874 rocksdb_writebatch_wi_set_save_point(wb
);
875 const char* k_list
[2] = {"z", "ap"};
876 const size_t k_sizes
[2] = {1, 2};
877 const char* v_list
[3] = {"x", "y", "z"};
878 const size_t v_sizes
[3] = {1, 1, 1};
879 rocksdb_writebatch_wi_putv(wb
, 2, k_list
, k_sizes
, 3, v_list
, v_sizes
);
880 rocksdb_writebatch_wi_rollback_to_save_point(wb
, &err
);
882 rocksdb_write_writebatch_wi(db
, woptions
, wb
, &err
);
884 CheckGet(db
, roptions
, "zap", NULL
);
885 rocksdb_writebatch_wi_destroy(wb
);
890 rocksdb_iterator_t
* iter
= rocksdb_create_iterator(db
, roptions
);
891 CheckCondition(!rocksdb_iter_valid(iter
));
892 rocksdb_iter_seek_to_first(iter
);
893 CheckCondition(rocksdb_iter_valid(iter
));
894 CheckIter(iter
, "box", "c");
895 rocksdb_iter_next(iter
);
896 CheckIter(iter
, "foo", "hello");
897 rocksdb_iter_prev(iter
);
898 CheckIter(iter
, "box", "c");
899 rocksdb_iter_prev(iter
);
900 CheckCondition(!rocksdb_iter_valid(iter
));
901 rocksdb_iter_seek_to_last(iter
);
902 CheckIter(iter
, "foo", "hello");
903 rocksdb_iter_seek(iter
, "b", 1);
904 CheckIter(iter
, "box", "c");
905 rocksdb_iter_seek_for_prev(iter
, "g", 1);
906 CheckIter(iter
, "foo", "hello");
907 rocksdb_iter_seek_for_prev(iter
, "box", 3);
908 CheckIter(iter
, "box", "c");
909 rocksdb_iter_get_error(iter
, &err
);
911 rocksdb_iter_destroy(iter
);
914 StartPhase("wbwi_iter");
916 rocksdb_iterator_t
* base_iter
= rocksdb_create_iterator(db
, roptions
);
917 rocksdb_writebatch_wi_t
* wbi
= rocksdb_writebatch_wi_create(0, 1);
918 rocksdb_writebatch_wi_put(wbi
, "bar", 3, "b", 1);
919 rocksdb_writebatch_wi_delete(wbi
, "foo", 3);
920 rocksdb_iterator_t
* iter
= rocksdb_writebatch_wi_create_iterator_with_base(wbi
, base_iter
);
921 CheckCondition(!rocksdb_iter_valid(iter
));
922 rocksdb_iter_seek_to_first(iter
);
923 CheckCondition(rocksdb_iter_valid(iter
));
924 CheckIter(iter
, "bar", "b");
925 rocksdb_iter_next(iter
);
926 CheckIter(iter
, "box", "c");
927 rocksdb_iter_prev(iter
);
928 CheckIter(iter
, "bar", "b");
929 rocksdb_iter_prev(iter
);
930 CheckCondition(!rocksdb_iter_valid(iter
));
931 rocksdb_iter_seek_to_last(iter
);
932 CheckIter(iter
, "box", "c");
933 rocksdb_iter_seek(iter
, "b", 1);
934 CheckIter(iter
, "bar", "b");
935 rocksdb_iter_seek_for_prev(iter
, "c", 1);
936 CheckIter(iter
, "box", "c");
937 rocksdb_iter_seek_for_prev(iter
, "box", 3);
938 CheckIter(iter
, "box", "c");
939 rocksdb_iter_get_error(iter
, &err
);
941 rocksdb_iter_destroy(iter
);
942 rocksdb_writebatch_wi_destroy(wbi
);
945 StartPhase("multiget");
947 const char* keys
[3] = { "box", "foo", "notfound" };
948 const size_t keys_sizes
[3] = { 3, 3, 8 };
950 size_t vals_sizes
[3];
952 rocksdb_multi_get(db
, roptions
, 3, keys
, keys_sizes
, vals
, vals_sizes
, errs
);
955 for (i
= 0; i
< 3; i
++) {
956 CheckEqual(NULL
, errs
[i
], 0);
959 CheckEqual("c", vals
[i
], vals_sizes
[i
]);
962 CheckEqual("hello", vals
[i
], vals_sizes
[i
]);
965 CheckEqual(NULL
, vals
[i
], vals_sizes
[i
]);
972 StartPhase("pin_get");
974 CheckPinGet(db
, roptions
, "box", "c");
975 CheckPinGet(db
, roptions
, "foo", "hello");
976 CheckPinGet(db
, roptions
, "notfound", NULL
);
979 StartPhase("approximate_sizes");
986 const char* start
[2] = { "a", "k00000000000000010000" };
987 size_t start_len
[2] = { 1, 21 };
988 const char* limit
[2] = { "k00000000000000010000", "z" };
989 size_t limit_len
[2] = { 21, 1 };
990 rocksdb_writeoptions_set_sync(woptions
, 0);
991 for (i
= 0; i
< n
; i
++) {
992 snprintf(keybuf
, sizeof(keybuf
), "k%020d", i
);
993 snprintf(valbuf
, sizeof(valbuf
), "v%020d", i
);
994 rocksdb_put(db
, woptions
, keybuf
, strlen(keybuf
), valbuf
, strlen(valbuf
),
998 rocksdb_approximate_sizes(db
, 2, start
, start_len
, limit
, limit_len
, sizes
);
999 CheckCondition(sizes
[0] > 0);
1000 CheckCondition(sizes
[1] > 0);
1003 StartPhase("property");
1005 char* prop
= rocksdb_property_value(db
, "nosuchprop");
1006 CheckCondition(prop
== NULL
);
1007 prop
= rocksdb_property_value(db
, "rocksdb.stats");
1008 CheckCondition(prop
!= NULL
);
1012 StartPhase("snapshot");
1014 const rocksdb_snapshot_t
* snap
;
1015 snap
= rocksdb_create_snapshot(db
);
1016 rocksdb_delete(db
, woptions
, "foo", 3, &err
);
1018 rocksdb_readoptions_set_snapshot(roptions
, snap
);
1019 CheckGet(db
, roptions
, "foo", "hello");
1020 rocksdb_readoptions_set_snapshot(roptions
, NULL
);
1021 CheckGet(db
, roptions
, "foo", NULL
);
1022 rocksdb_release_snapshot(db
, snap
);
1025 StartPhase("repair");
1027 // If we do not compact here, then the lazy deletion of
1028 // files (https://reviews.facebook.net/D6123) would leave
1029 // around deleted files and the repair process will find
1030 // those files and put them back into the database.
1031 rocksdb_compact_range(db
, NULL
, 0, NULL
, 0);
1033 rocksdb_options_set_create_if_missing(options
, 0);
1034 rocksdb_options_set_error_if_exists(options
, 0);
1035 rocksdb_options_set_wal_recovery_mode(options
, 2);
1036 rocksdb_repair_db(options
, dbname
, &err
);
1038 db
= rocksdb_open(options
, dbname
, &err
);
1040 CheckGet(db
, roptions
, "foo", NULL
);
1041 CheckGet(db
, roptions
, "bar", NULL
);
1042 CheckGet(db
, roptions
, "box", "c");
1043 rocksdb_options_set_create_if_missing(options
, 1);
1044 rocksdb_options_set_error_if_exists(options
, 1);
1047 StartPhase("filter");
1048 for (run
= 0; run
< 2; run
++) {
1049 // First run uses custom filter, second run uses bloom filter
1051 rocksdb_filterpolicy_t
* policy
;
1053 policy
= rocksdb_filterpolicy_create(
1054 NULL
, FilterDestroy
, FilterCreate
, FilterKeyMatch
, NULL
, FilterName
);
1056 policy
= rocksdb_filterpolicy_create_bloom(10);
1059 rocksdb_block_based_options_set_filter_policy(table_options
, policy
);
1061 // Create new database
1063 rocksdb_destroy_db(options
, dbname
, &err
);
1064 rocksdb_options_set_block_based_table_factory(options
, table_options
);
1065 db
= rocksdb_open(options
, dbname
, &err
);
1067 rocksdb_put(db
, woptions
, "foo", 3, "foovalue", 8, &err
);
1069 rocksdb_put(db
, woptions
, "bar", 3, "barvalue", 8, &err
);
1071 rocksdb_compact_range(db
, NULL
, 0, NULL
, 0);
1073 fake_filter_result
= 1;
1074 CheckGet(db
, roptions
, "foo", "foovalue");
1075 CheckGet(db
, roptions
, "bar", "barvalue");
1077 // Must not find value when custom filter returns false
1078 fake_filter_result
= 0;
1079 CheckGet(db
, roptions
, "foo", NULL
);
1080 CheckGet(db
, roptions
, "bar", NULL
);
1081 fake_filter_result
= 1;
1083 CheckGet(db
, roptions
, "foo", "foovalue");
1084 CheckGet(db
, roptions
, "bar", "barvalue");
1087 rocksdb_block_based_options_set_filter_policy(table_options
, NULL
);
1088 rocksdb_options_set_block_based_table_factory(options
, table_options
);
1091 StartPhase("compaction_filter");
1093 rocksdb_options_t
* options_with_filter
= rocksdb_options_create();
1094 rocksdb_options_set_create_if_missing(options_with_filter
, 1);
1095 rocksdb_compactionfilter_t
* cfilter
;
1096 cfilter
= rocksdb_compactionfilter_create(NULL
, CFilterDestroy
,
1097 CFilterFilter
, CFilterName
);
1098 // Create new database
1100 rocksdb_destroy_db(options_with_filter
, dbname
, &err
);
1101 rocksdb_options_set_compaction_filter(options_with_filter
, cfilter
);
1102 db
= CheckCompaction(db
, options_with_filter
, roptions
, woptions
);
1104 rocksdb_options_set_compaction_filter(options_with_filter
, NULL
);
1105 rocksdb_compactionfilter_destroy(cfilter
);
1106 rocksdb_options_destroy(options_with_filter
);
1109 StartPhase("compaction_filter_factory");
1111 rocksdb_options_t
* options_with_filter_factory
= rocksdb_options_create();
1112 rocksdb_options_set_create_if_missing(options_with_filter_factory
, 1);
1113 rocksdb_compactionfilterfactory_t
* factory
;
1114 factory
= rocksdb_compactionfilterfactory_create(
1115 NULL
, CFilterFactoryDestroy
, CFilterCreate
, CFilterFactoryName
);
1116 // Create new database
1118 rocksdb_destroy_db(options_with_filter_factory
, dbname
, &err
);
1119 rocksdb_options_set_compaction_filter_factory(options_with_filter_factory
,
1121 db
= CheckCompaction(db
, options_with_filter_factory
, roptions
, woptions
);
1123 rocksdb_options_set_compaction_filter_factory(
1124 options_with_filter_factory
, NULL
);
1125 rocksdb_options_destroy(options_with_filter_factory
);
1128 StartPhase("merge_operator");
1130 rocksdb_mergeoperator_t
* merge_operator
;
1131 merge_operator
= rocksdb_mergeoperator_create(
1132 NULL
, MergeOperatorDestroy
, MergeOperatorFullMerge
,
1133 MergeOperatorPartialMerge
, NULL
, MergeOperatorName
);
1134 // Create new database
1136 rocksdb_destroy_db(options
, dbname
, &err
);
1137 rocksdb_options_set_merge_operator(options
, merge_operator
);
1138 db
= rocksdb_open(options
, dbname
, &err
);
1140 rocksdb_put(db
, woptions
, "foo", 3, "foovalue", 8, &err
);
1142 CheckGet(db
, roptions
, "foo", "foovalue");
1143 rocksdb_merge(db
, woptions
, "foo", 3, "barvalue", 8, &err
);
1145 CheckGet(db
, roptions
, "foo", "fake");
1147 // Merge of a non-existing value
1148 rocksdb_merge(db
, woptions
, "bar", 3, "barvalue", 8, &err
);
1150 CheckGet(db
, roptions
, "bar", "fake");
1154 StartPhase("columnfamilies");
1157 rocksdb_destroy_db(options
, dbname
, &err
);
1160 rocksdb_options_t
* db_options
= rocksdb_options_create();
1161 rocksdb_options_set_create_if_missing(db_options
, 1);
1162 db
= rocksdb_open(db_options
, dbname
, &err
);
1164 rocksdb_column_family_handle_t
* cfh
;
1165 cfh
= rocksdb_create_column_family(db
, db_options
, "cf1", &err
);
1166 rocksdb_column_family_handle_destroy(cfh
);
1171 char** column_fams
= rocksdb_list_column_families(db_options
, dbname
, &cflen
, &err
);
1173 CheckEqual("default", column_fams
[0], 7);
1174 CheckEqual("cf1", column_fams
[1], 3);
1175 CheckCondition(cflen
== 2);
1176 rocksdb_list_column_families_destroy(column_fams
, cflen
);
1178 rocksdb_options_t
* cf_options
= rocksdb_options_create();
1180 const char* cf_names
[2] = {"default", "cf1"};
1181 const rocksdb_options_t
* cf_opts
[2] = {cf_options
, cf_options
};
1182 rocksdb_column_family_handle_t
* handles
[2];
1183 db
= rocksdb_open_column_families(db_options
, dbname
, 2, cf_names
, cf_opts
, handles
, &err
);
1186 rocksdb_put_cf(db
, woptions
, handles
[1], "foo", 3, "hello", 5, &err
);
1189 CheckGetCF(db
, roptions
, handles
[1], "foo", "hello");
1190 CheckPinGetCF(db
, roptions
, handles
[1], "foo", "hello");
1192 rocksdb_delete_cf(db
, woptions
, handles
[1], "foo", 3, &err
);
1195 CheckGetCF(db
, roptions
, handles
[1], "foo", NULL
);
1196 CheckPinGetCF(db
, roptions
, handles
[1], "foo", NULL
);
1198 rocksdb_writebatch_t
* wb
= rocksdb_writebatch_create();
1199 rocksdb_writebatch_put_cf(wb
, handles
[1], "baz", 3, "a", 1);
1200 rocksdb_writebatch_clear(wb
);
1201 rocksdb_writebatch_put_cf(wb
, handles
[1], "bar", 3, "b", 1);
1202 rocksdb_writebatch_put_cf(wb
, handles
[1], "box", 3, "c", 1);
1203 rocksdb_writebatch_delete_cf(wb
, handles
[1], "bar", 3);
1204 rocksdb_write(db
, woptions
, wb
, &err
);
1206 CheckGetCF(db
, roptions
, handles
[1], "baz", NULL
);
1207 CheckGetCF(db
, roptions
, handles
[1], "bar", NULL
);
1208 CheckGetCF(db
, roptions
, handles
[1], "box", "c");
1209 CheckPinGetCF(db
, roptions
, handles
[1], "baz", NULL
);
1210 CheckPinGetCF(db
, roptions
, handles
[1], "bar", NULL
);
1211 CheckPinGetCF(db
, roptions
, handles
[1], "box", "c");
1212 rocksdb_writebatch_destroy(wb
);
1214 const char* keys
[3] = { "box", "box", "barfooxx" };
1215 const rocksdb_column_family_handle_t
* get_handles
[3] = { handles
[0], handles
[1], handles
[1] };
1216 const size_t keys_sizes
[3] = { 3, 3, 8 };
1218 size_t vals_sizes
[3];
1220 rocksdb_multi_get_cf(db
, roptions
, get_handles
, 3, keys
, keys_sizes
, vals
, vals_sizes
, errs
);
1223 for (i
= 0; i
< 3; i
++) {
1224 CheckEqual(NULL
, errs
[i
], 0);
1227 CheckEqual(NULL
, vals
[i
], vals_sizes
[i
]); // wrong cf
1230 CheckEqual("c", vals
[i
], vals_sizes
[i
]); // bingo
1233 CheckEqual(NULL
, vals
[i
], vals_sizes
[i
]); // normal not found
1239 rocksdb_iterator_t
* iter
= rocksdb_create_iterator_cf(db
, roptions
, handles
[1]);
1240 CheckCondition(!rocksdb_iter_valid(iter
));
1241 rocksdb_iter_seek_to_first(iter
);
1242 CheckCondition(rocksdb_iter_valid(iter
));
1244 for (i
= 0; rocksdb_iter_valid(iter
) != 0; rocksdb_iter_next(iter
)) {
1247 CheckCondition(i
== 1);
1248 rocksdb_iter_get_error(iter
, &err
);
1250 rocksdb_iter_destroy(iter
);
1252 rocksdb_column_family_handle_t
* iters_cf_handles
[2] = { handles
[0], handles
[1] };
1253 rocksdb_iterator_t
* iters_handles
[2];
1254 rocksdb_create_iterators(db
, roptions
, iters_cf_handles
, iters_handles
, 2, &err
);
1257 iter
= iters_handles
[0];
1258 CheckCondition(!rocksdb_iter_valid(iter
));
1259 rocksdb_iter_seek_to_first(iter
);
1260 CheckCondition(!rocksdb_iter_valid(iter
));
1261 rocksdb_iter_destroy(iter
);
1263 iter
= iters_handles
[1];
1264 CheckCondition(!rocksdb_iter_valid(iter
));
1265 rocksdb_iter_seek_to_first(iter
);
1266 CheckCondition(rocksdb_iter_valid(iter
));
1268 for (i
= 0; rocksdb_iter_valid(iter
) != 0; rocksdb_iter_next(iter
)) {
1271 CheckCondition(i
== 1);
1272 rocksdb_iter_get_error(iter
, &err
);
1274 rocksdb_iter_destroy(iter
);
1276 rocksdb_drop_column_family(db
, handles
[1], &err
);
1278 for (i
= 0; i
< 2; i
++) {
1279 rocksdb_column_family_handle_destroy(handles
[i
]);
1282 rocksdb_destroy_db(options
, dbname
, &err
);
1283 rocksdb_options_destroy(db_options
);
1284 rocksdb_options_destroy(cf_options
);
1287 StartPhase("prefix");
1289 // Create new database
1290 rocksdb_options_set_allow_mmap_reads(options
, 1);
1291 rocksdb_options_set_prefix_extractor(options
, rocksdb_slicetransform_create_fixed_prefix(3));
1292 rocksdb_options_set_hash_skip_list_rep(options
, 5000, 4, 4);
1293 rocksdb_options_set_plain_table_factory(options
, 4, 10, 0.75, 16);
1294 rocksdb_options_set_allow_concurrent_memtable_write(options
, 0);
1296 db
= rocksdb_open(options
, dbname
, &err
);
1299 rocksdb_put(db
, woptions
, "foo1", 4, "foo", 3, &err
);
1301 rocksdb_put(db
, woptions
, "foo2", 4, "foo", 3, &err
);
1303 rocksdb_put(db
, woptions
, "foo3", 4, "foo", 3, &err
);
1305 rocksdb_put(db
, woptions
, "bar1", 4, "bar", 3, &err
);
1307 rocksdb_put(db
, woptions
, "bar2", 4, "bar", 3, &err
);
1309 rocksdb_put(db
, woptions
, "bar3", 4, "bar", 3, &err
);
1312 rocksdb_iterator_t
* iter
= rocksdb_create_iterator(db
, roptions
);
1313 CheckCondition(!rocksdb_iter_valid(iter
));
1315 rocksdb_iter_seek(iter
, "bar", 3);
1316 rocksdb_iter_get_error(iter
, &err
);
1318 CheckCondition(rocksdb_iter_valid(iter
));
1320 CheckIter(iter
, "bar1", "bar");
1321 rocksdb_iter_next(iter
);
1322 CheckIter(iter
, "bar2", "bar");
1323 rocksdb_iter_next(iter
);
1324 CheckIter(iter
, "bar3", "bar");
1325 rocksdb_iter_get_error(iter
, &err
);
1327 rocksdb_iter_destroy(iter
);
1329 rocksdb_readoptions_set_total_order_seek(roptions
, 1);
1330 iter
= rocksdb_create_iterator(db
, roptions
);
1331 CheckCondition(!rocksdb_iter_valid(iter
));
1333 rocksdb_iter_seek(iter
, "ba", 2);
1334 rocksdb_iter_get_error(iter
, &err
);
1336 CheckCondition(rocksdb_iter_valid(iter
));
1337 CheckIter(iter
, "bar1", "bar");
1339 rocksdb_iter_destroy(iter
);
1340 rocksdb_readoptions_set_total_order_seek(roptions
, 0);
1343 rocksdb_destroy_db(options
, dbname
, &err
);
1346 // Check memory usage stats
1347 StartPhase("approximate_memory_usage");
1350 db
= rocksdb_open(options
, dbname
, &err
);
1353 rocksdb_memory_consumers_t
* consumers
;
1354 consumers
= rocksdb_memory_consumers_create();
1355 rocksdb_memory_consumers_add_db(consumers
, db
);
1356 rocksdb_memory_consumers_add_cache(consumers
, cache
);
1358 // take memory usage report before write-read operation
1359 rocksdb_memory_usage_t
* mu1
;
1360 mu1
= rocksdb_approximate_memory_usage_create(consumers
, &err
);
1363 // Put data (this should affect memtables)
1364 rocksdb_put(db
, woptions
, "memory", 6, "test", 4, &err
);
1366 CheckGet(db
, roptions
, "memory", "test");
1368 // take memory usage report after write-read operation
1369 rocksdb_memory_usage_t
* mu2
;
1370 mu2
= rocksdb_approximate_memory_usage_create(consumers
, &err
);
1373 // amount of memory used within memtables should grow
1374 CheckCondition(rocksdb_approximate_memory_usage_get_mem_table_total(mu2
) >=
1375 rocksdb_approximate_memory_usage_get_mem_table_total(mu1
));
1376 CheckCondition(rocksdb_approximate_memory_usage_get_mem_table_unflushed(mu2
) >=
1377 rocksdb_approximate_memory_usage_get_mem_table_unflushed(mu1
));
1379 rocksdb_memory_consumers_destroy(consumers
);
1380 rocksdb_approximate_memory_usage_destroy(mu1
);
1381 rocksdb_approximate_memory_usage_destroy(mu2
);
1383 rocksdb_destroy_db(options
, dbname
, &err
);
1387 StartPhase("cuckoo_options");
1389 rocksdb_cuckoo_table_options_t
* cuckoo_options
;
1390 cuckoo_options
= rocksdb_cuckoo_options_create();
1391 rocksdb_cuckoo_options_set_hash_ratio(cuckoo_options
, 0.5);
1392 rocksdb_cuckoo_options_set_max_search_depth(cuckoo_options
, 200);
1393 rocksdb_cuckoo_options_set_cuckoo_block_size(cuckoo_options
, 10);
1394 rocksdb_cuckoo_options_set_identity_as_first_hash(cuckoo_options
, 1);
1395 rocksdb_cuckoo_options_set_use_module_hash(cuckoo_options
, 0);
1396 rocksdb_options_set_cuckoo_table_factory(options
, cuckoo_options
);
1398 db
= rocksdb_open(options
, dbname
, &err
);
1401 rocksdb_cuckoo_options_destroy(cuckoo_options
);
1404 StartPhase("iterate_upper_bound");
1406 // Create new empty database
1408 rocksdb_destroy_db(options
, dbname
, &err
);
1411 rocksdb_options_set_prefix_extractor(options
, NULL
);
1412 db
= rocksdb_open(options
, dbname
, &err
);
1415 rocksdb_put(db
, woptions
, "a", 1, "0", 1, &err
); CheckNoError(err
);
1416 rocksdb_put(db
, woptions
, "foo", 3, "bar", 3, &err
); CheckNoError(err
);
1417 rocksdb_put(db
, woptions
, "foo1", 4, "bar1", 4, &err
); CheckNoError(err
);
1418 rocksdb_put(db
, woptions
, "g1", 2, "0", 1, &err
); CheckNoError(err
);
1420 // testing basic case with no iterate_upper_bound and no prefix_extractor
1422 rocksdb_readoptions_set_iterate_upper_bound(roptions
, NULL
, 0);
1423 rocksdb_iterator_t
* iter
= rocksdb_create_iterator(db
, roptions
);
1425 rocksdb_iter_seek(iter
, "foo", 3);
1426 CheckCondition(rocksdb_iter_valid(iter
));
1427 CheckIter(iter
, "foo", "bar");
1429 rocksdb_iter_next(iter
);
1430 CheckCondition(rocksdb_iter_valid(iter
));
1431 CheckIter(iter
, "foo1", "bar1");
1433 rocksdb_iter_next(iter
);
1434 CheckCondition(rocksdb_iter_valid(iter
));
1435 CheckIter(iter
, "g1", "0");
1437 rocksdb_iter_destroy(iter
);
1440 // testing iterate_upper_bound and forward iterator
1441 // to make sure it stops at bound
1443 // iterate_upper_bound points beyond the last expected entry
1444 rocksdb_readoptions_set_iterate_upper_bound(roptions
, "foo2", 4);
1446 rocksdb_iterator_t
* iter
= rocksdb_create_iterator(db
, roptions
);
1448 rocksdb_iter_seek(iter
, "foo", 3);
1449 CheckCondition(rocksdb_iter_valid(iter
));
1450 CheckIter(iter
, "foo", "bar");
1452 rocksdb_iter_next(iter
);
1453 CheckCondition(rocksdb_iter_valid(iter
));
1454 CheckIter(iter
, "foo1", "bar1");
1456 rocksdb_iter_next(iter
);
1457 // should stop here...
1458 CheckCondition(!rocksdb_iter_valid(iter
));
1460 rocksdb_iter_destroy(iter
);
1464 StartPhase("transactions");
1467 rocksdb_destroy_db(options
, dbname
, &err
);
1470 // open a TransactionDB
1471 txn_db_options
= rocksdb_transactiondb_options_create();
1472 txn_options
= rocksdb_transaction_options_create();
1473 rocksdb_options_set_create_if_missing(options
, 1);
1474 txn_db
= rocksdb_transactiondb_open(options
, txn_db_options
, dbname
, &err
);
1477 // put outside a transaction
1478 rocksdb_transactiondb_put(txn_db
, woptions
, "foo", 3, "hello", 5, &err
);
1480 CheckTxnDBGet(txn_db
, roptions
, "foo", "hello");
1482 // delete from outside transaction
1483 rocksdb_transactiondb_delete(txn_db
, woptions
, "foo", 3, &err
);
1485 CheckTxnDBGet(txn_db
, roptions
, "foo", NULL
);
1487 // write batch into TransactionDB
1488 rocksdb_writebatch_t
* wb
= rocksdb_writebatch_create();
1489 rocksdb_writebatch_put(wb
, "foo", 3, "a", 1);
1490 rocksdb_writebatch_clear(wb
);
1491 rocksdb_writebatch_put(wb
, "bar", 3, "b", 1);
1492 rocksdb_writebatch_put(wb
, "box", 3, "c", 1);
1493 rocksdb_writebatch_delete(wb
, "bar", 3);
1494 rocksdb_transactiondb_write(txn_db
, woptions
, wb
, &err
);
1495 rocksdb_writebatch_destroy(wb
);
1496 CheckTxnDBGet(txn_db
, roptions
, "box", "c");
1499 // begin a transaction
1500 txn
= rocksdb_transaction_begin(txn_db
, woptions
, txn_options
, NULL
);
1502 rocksdb_transaction_put(txn
, "foo", 3, "hello", 5, &err
);
1504 CheckTxnGet(txn
, roptions
, "foo", "hello");
1506 rocksdb_transaction_delete(txn
, "foo", 3, &err
);
1508 CheckTxnGet(txn
, roptions
, "foo", NULL
);
1510 rocksdb_transaction_put(txn
, "foo", 3, "hello", 5, &err
);
1513 // read from outside transaction, before commit
1514 CheckTxnDBGet(txn_db
, roptions
, "foo", NULL
);
1517 rocksdb_transaction_commit(txn
, &err
);
1520 // read from outside transaction, after commit
1521 CheckTxnDBGet(txn_db
, roptions
, "foo", "hello");
1523 // reuse old transaction
1524 txn
= rocksdb_transaction_begin(txn_db
, woptions
, txn_options
, txn
);
1527 const rocksdb_snapshot_t
* snapshot
;
1528 snapshot
= rocksdb_transactiondb_create_snapshot(txn_db
);
1529 rocksdb_readoptions_set_snapshot(roptions
, snapshot
);
1531 rocksdb_transactiondb_put(txn_db
, woptions
, "foo", 3, "hey", 3, &err
);
1534 CheckTxnDBGet(txn_db
, roptions
, "foo", "hello");
1535 rocksdb_readoptions_set_snapshot(roptions
, NULL
);
1536 rocksdb_transactiondb_release_snapshot(txn_db
, snapshot
);
1537 CheckTxnDBGet(txn_db
, roptions
, "foo", "hey");
1540 rocksdb_transaction_put(txn
, "bar", 3, "hi", 2, &err
);
1541 rocksdb_iterator_t
* iter
= rocksdb_transaction_create_iterator(txn
, roptions
);
1542 CheckCondition(!rocksdb_iter_valid(iter
));
1543 rocksdb_iter_seek_to_first(iter
);
1544 CheckCondition(rocksdb_iter_valid(iter
));
1545 CheckIter(iter
, "bar", "hi");
1546 rocksdb_iter_get_error(iter
, &err
);
1548 rocksdb_iter_destroy(iter
);
1551 rocksdb_transaction_rollback(txn
, &err
);
1553 CheckTxnDBGet(txn_db
, roptions
, "bar", NULL
);
1556 rocksdb_transaction_put(txn
, "foo1", 4, "hi1", 3, &err
);
1557 rocksdb_transaction_set_savepoint(txn
);
1558 CheckTxnGet(txn
, roptions
, "foo1", "hi1");
1559 rocksdb_transaction_put(txn
, "foo2", 4, "hi2", 3, &err
);
1560 CheckTxnGet(txn
, roptions
, "foo2", "hi2");
1562 // rollback to savepoint
1563 rocksdb_transaction_rollback_to_savepoint(txn
, &err
);
1565 CheckTxnGet(txn
, roptions
, "foo2", NULL
);
1566 CheckTxnGet(txn
, roptions
, "foo1", "hi1");
1567 CheckTxnDBGet(txn_db
, roptions
, "foo1", NULL
);
1568 CheckTxnDBGet(txn_db
, roptions
, "foo2", NULL
);
1569 rocksdb_transaction_commit(txn
, &err
);
1571 CheckTxnDBGet(txn_db
, roptions
, "foo1", "hi1");
1572 CheckTxnDBGet(txn_db
, roptions
, "foo2", NULL
);
1575 rocksdb_column_family_handle_t
* cfh
;
1576 cfh
= rocksdb_transactiondb_create_column_family(txn_db
, options
,
1580 rocksdb_transactiondb_put_cf(txn_db
, woptions
, cfh
, "cf_foo", 6, "cf_hello",
1583 CheckTxnDBGetCF(txn_db
, roptions
, cfh
, "cf_foo", "cf_hello");
1585 rocksdb_transactiondb_delete_cf(txn_db
, woptions
, cfh
, "cf_foo", 6, &err
);
1587 CheckTxnDBGetCF(txn_db
, roptions
, cfh
, "cf_foo", NULL
);
1589 rocksdb_column_family_handle_destroy(cfh
);
1591 // close and destroy
1592 rocksdb_transaction_destroy(txn
);
1593 rocksdb_transactiondb_close(txn_db
);
1594 rocksdb_destroy_db(options
, dbname
, &err
);
1596 rocksdb_transaction_options_destroy(txn_options
);
1597 rocksdb_transactiondb_options_destroy(txn_db_options
);
1600 StartPhase("optimistic_transactions");
1602 rocksdb_options_t
* db_options
= rocksdb_options_create();
1603 rocksdb_options_set_create_if_missing(db_options
, 1);
1604 rocksdb_options_set_allow_concurrent_memtable_write(db_options
, 1);
1605 otxn_db
= rocksdb_optimistictransactiondb_open(db_options
, dbname
, &err
);
1606 otxn_options
= rocksdb_optimistictransaction_options_create();
1607 rocksdb_transaction_t
* txn1
= rocksdb_optimistictransaction_begin(
1608 otxn_db
, woptions
, otxn_options
, NULL
);
1609 rocksdb_transaction_t
* txn2
= rocksdb_optimistictransaction_begin(
1610 otxn_db
, woptions
, otxn_options
, NULL
);
1611 rocksdb_transaction_put(txn1
, "key", 3, "value", 5, &err
);
1613 rocksdb_transaction_put(txn2
, "key1", 4, "value1", 6, &err
);
1615 CheckTxnGet(txn1
, roptions
, "key", "value");
1616 rocksdb_transaction_commit(txn1
, &err
);
1618 rocksdb_transaction_commit(txn2
, &err
);
1620 rocksdb_transaction_destroy(txn1
);
1621 rocksdb_transaction_destroy(txn2
);
1623 // Check column family
1624 db
= rocksdb_optimistictransactiondb_get_base_db(otxn_db
);
1625 rocksdb_put(db
, woptions
, "key", 3, "value", 5, &err
);
1627 rocksdb_column_family_handle_t
*cfh1
, *cfh2
;
1628 cfh1
= rocksdb_create_column_family(db
, db_options
, "txn_db_cf1", &err
);
1629 cfh2
= rocksdb_create_column_family(db
, db_options
, "txn_db_cf2", &err
);
1630 txn
= rocksdb_optimistictransaction_begin(otxn_db
, woptions
, otxn_options
,
1632 rocksdb_transaction_put_cf(txn
, cfh1
, "key_cf1", 7, "val_cf1", 7, &err
);
1634 rocksdb_transaction_put_cf(txn
, cfh2
, "key_cf2", 7, "val_cf2", 7, &err
);
1636 rocksdb_transaction_commit(txn
, &err
);
1638 txn
= rocksdb_optimistictransaction_begin(otxn_db
, woptions
, otxn_options
,
1640 CheckGetCF(db
, roptions
, cfh1
, "key_cf1", "val_cf1");
1641 CheckTxnGetCF(txn
, roptions
, cfh1
, "key_cf1", "val_cf1");
1643 // Check iterator with column family
1644 rocksdb_transaction_put_cf(txn
, cfh1
, "key1_cf", 7, "val1_cf", 7, &err
);
1646 rocksdb_iterator_t
* iter
=
1647 rocksdb_transaction_create_iterator_cf(txn
, roptions
, cfh1
);
1648 CheckCondition(!rocksdb_iter_valid(iter
));
1649 rocksdb_iter_seek_to_first(iter
);
1650 CheckCondition(rocksdb_iter_valid(iter
));
1651 CheckIter(iter
, "key1_cf", "val1_cf");
1652 rocksdb_iter_get_error(iter
, &err
);
1654 rocksdb_iter_destroy(iter
);
1656 rocksdb_transaction_destroy(txn
);
1657 rocksdb_column_family_handle_destroy(cfh1
);
1658 rocksdb_column_family_handle_destroy(cfh2
);
1659 rocksdb_optimistictransactiondb_close_base_db(db
);
1660 rocksdb_optimistictransactiondb_close(otxn_db
);
1662 // Check open optimistic transaction db with column families
1664 char** column_fams
=
1665 rocksdb_list_column_families(db_options
, dbname
, &cf_len
, &err
);
1667 CheckEqual("default", column_fams
[0], 7);
1668 CheckEqual("txn_db_cf1", column_fams
[1], 10);
1669 CheckEqual("txn_db_cf2", column_fams
[2], 10);
1670 CheckCondition(cf_len
== 3);
1671 rocksdb_list_column_families_destroy(column_fams
, cf_len
);
1673 const char* cf_names
[3] = {"default", "txn_db_cf1", "txn_db_cf2"};
1674 rocksdb_options_t
* cf_options
= rocksdb_options_create();
1675 const rocksdb_options_t
* cf_opts
[3] = {cf_options
, cf_options
, cf_options
};
1677 rocksdb_options_set_error_if_exists(cf_options
, 0);
1678 rocksdb_column_family_handle_t
* cf_handles
[3];
1679 otxn_db
= rocksdb_optimistictransactiondb_open_column_families(
1680 db_options
, dbname
, 3, cf_names
, cf_opts
, cf_handles
, &err
);
1682 rocksdb_transaction_t
* txn_cf
= rocksdb_optimistictransaction_begin(
1683 otxn_db
, woptions
, otxn_options
, NULL
);
1684 CheckTxnGetCF(txn_cf
, roptions
, cf_handles
[0], "key", "value");
1685 CheckTxnGetCF(txn_cf
, roptions
, cf_handles
[1], "key_cf1", "val_cf1");
1686 CheckTxnGetCF(txn_cf
, roptions
, cf_handles
[2], "key_cf2", "val_cf2");
1687 rocksdb_transaction_destroy(txn_cf
);
1688 rocksdb_options_destroy(cf_options
);
1689 rocksdb_column_family_handle_destroy(cf_handles
[0]);
1690 rocksdb_column_family_handle_destroy(cf_handles
[1]);
1691 rocksdb_column_family_handle_destroy(cf_handles
[2]);
1692 rocksdb_optimistictransactiondb_close(otxn_db
);
1693 rocksdb_destroy_db(db_options
, dbname
, &err
);
1694 rocksdb_options_destroy(db_options
);
1695 rocksdb_optimistictransaction_options_destroy(otxn_options
);
1699 // Simple sanity check that setting memtable rep works.
1700 StartPhase("memtable_reps");
1702 // Create database with vector memtable.
1703 rocksdb_options_set_memtable_vector_rep(options
);
1704 db
= rocksdb_open(options
, dbname
, &err
);
1707 // Create database with hash skiplist memtable.
1709 rocksdb_destroy_db(options
, dbname
, &err
);
1712 rocksdb_options_set_hash_skip_list_rep(options
, 5000, 4, 4);
1713 db
= rocksdb_open(options
, dbname
, &err
);
1717 // Simple sanity check that options setting db_paths work.
1718 StartPhase("open_db_paths");
1721 rocksdb_destroy_db(options
, dbname
, &err
);
1723 const rocksdb_dbpath_t
* paths
[1] = {dbpath
};
1724 rocksdb_options_set_db_paths(options
, paths
, 1);
1725 db
= rocksdb_open(options
, dbname
, &err
);
1729 StartPhase("cleanup");
1731 rocksdb_options_destroy(options
);
1732 rocksdb_block_based_options_destroy(table_options
);
1733 rocksdb_readoptions_destroy(roptions
);
1734 rocksdb_writeoptions_destroy(woptions
);
1735 rocksdb_compactoptions_destroy(coptions
);
1736 rocksdb_cache_destroy(cache
);
1737 rocksdb_comparator_destroy(cmp
);
1738 rocksdb_dbpath_destroy(dbpath
);
1739 rocksdb_env_destroy(env
);
1741 fprintf(stderr
, "PASS\n");
1748 fprintf(stderr
, "SKIPPED\n");
1752 #endif // !ROCKSDB_LITE