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
=
921 rocksdb_writebatch_wi_create_iterator_with_base(wbi
, base_iter
);
922 CheckCondition(!rocksdb_iter_valid(iter
));
923 rocksdb_iter_seek_to_first(iter
);
924 CheckCondition(rocksdb_iter_valid(iter
));
925 CheckIter(iter
, "bar", "b");
926 rocksdb_iter_next(iter
);
927 CheckIter(iter
, "box", "c");
928 rocksdb_iter_prev(iter
);
929 CheckIter(iter
, "bar", "b");
930 rocksdb_iter_prev(iter
);
931 CheckCondition(!rocksdb_iter_valid(iter
));
932 rocksdb_iter_seek_to_last(iter
);
933 CheckIter(iter
, "box", "c");
934 rocksdb_iter_seek(iter
, "b", 1);
935 CheckIter(iter
, "bar", "b");
936 rocksdb_iter_seek_for_prev(iter
, "c", 1);
937 CheckIter(iter
, "box", "c");
938 rocksdb_iter_seek_for_prev(iter
, "box", 3);
939 CheckIter(iter
, "box", "c");
940 rocksdb_iter_get_error(iter
, &err
);
942 rocksdb_iter_destroy(iter
);
943 rocksdb_writebatch_wi_destroy(wbi
);
946 StartPhase("multiget");
948 const char* keys
[3] = { "box", "foo", "notfound" };
949 const size_t keys_sizes
[3] = { 3, 3, 8 };
951 size_t vals_sizes
[3];
953 rocksdb_multi_get(db
, roptions
, 3, keys
, keys_sizes
, vals
, vals_sizes
, errs
);
956 for (i
= 0; i
< 3; i
++) {
957 CheckEqual(NULL
, errs
[i
], 0);
960 CheckEqual("c", vals
[i
], vals_sizes
[i
]);
963 CheckEqual("hello", vals
[i
], vals_sizes
[i
]);
966 CheckEqual(NULL
, vals
[i
], vals_sizes
[i
]);
973 StartPhase("pin_get");
975 CheckPinGet(db
, roptions
, "box", "c");
976 CheckPinGet(db
, roptions
, "foo", "hello");
977 CheckPinGet(db
, roptions
, "notfound", NULL
);
980 StartPhase("approximate_sizes");
987 const char* start
[2] = { "a", "k00000000000000010000" };
988 size_t start_len
[2] = { 1, 21 };
989 const char* limit
[2] = { "k00000000000000010000", "z" };
990 size_t limit_len
[2] = { 21, 1 };
991 rocksdb_writeoptions_set_sync(woptions
, 0);
992 for (i
= 0; i
< n
; i
++) {
993 snprintf(keybuf
, sizeof(keybuf
), "k%020d", i
);
994 snprintf(valbuf
, sizeof(valbuf
), "v%020d", i
);
995 rocksdb_put(db
, woptions
, keybuf
, strlen(keybuf
), valbuf
, strlen(valbuf
),
999 rocksdb_approximate_sizes(db
, 2, start
, start_len
, limit
, limit_len
, sizes
);
1000 CheckCondition(sizes
[0] > 0);
1001 CheckCondition(sizes
[1] > 0);
1004 StartPhase("property");
1006 char* prop
= rocksdb_property_value(db
, "nosuchprop");
1007 CheckCondition(prop
== NULL
);
1008 prop
= rocksdb_property_value(db
, "rocksdb.stats");
1009 CheckCondition(prop
!= NULL
);
1013 StartPhase("snapshot");
1015 const rocksdb_snapshot_t
* snap
;
1016 snap
= rocksdb_create_snapshot(db
);
1017 rocksdb_delete(db
, woptions
, "foo", 3, &err
);
1019 rocksdb_readoptions_set_snapshot(roptions
, snap
);
1020 CheckGet(db
, roptions
, "foo", "hello");
1021 rocksdb_readoptions_set_snapshot(roptions
, NULL
);
1022 CheckGet(db
, roptions
, "foo", NULL
);
1023 rocksdb_release_snapshot(db
, snap
);
1026 StartPhase("repair");
1028 // If we do not compact here, then the lazy deletion of
1029 // files (https://reviews.facebook.net/D6123) would leave
1030 // around deleted files and the repair process will find
1031 // those files and put them back into the database.
1032 rocksdb_compact_range(db
, NULL
, 0, NULL
, 0);
1034 rocksdb_options_set_create_if_missing(options
, 0);
1035 rocksdb_options_set_error_if_exists(options
, 0);
1036 rocksdb_options_set_wal_recovery_mode(options
, 2);
1037 rocksdb_repair_db(options
, dbname
, &err
);
1039 db
= rocksdb_open(options
, dbname
, &err
);
1041 CheckGet(db
, roptions
, "foo", NULL
);
1042 CheckGet(db
, roptions
, "bar", NULL
);
1043 CheckGet(db
, roptions
, "box", "c");
1044 rocksdb_options_set_create_if_missing(options
, 1);
1045 rocksdb_options_set_error_if_exists(options
, 1);
1048 StartPhase("filter");
1049 for (run
= 0; run
< 2; run
++) {
1050 // First run uses custom filter, second run uses bloom filter
1052 rocksdb_filterpolicy_t
* policy
;
1054 policy
= rocksdb_filterpolicy_create(
1055 NULL
, FilterDestroy
, FilterCreate
, FilterKeyMatch
, NULL
, FilterName
);
1057 policy
= rocksdb_filterpolicy_create_bloom(10);
1060 rocksdb_block_based_options_set_filter_policy(table_options
, policy
);
1062 // Create new database
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
);
1068 rocksdb_put(db
, woptions
, "foo", 3, "foovalue", 8, &err
);
1070 rocksdb_put(db
, woptions
, "bar", 3, "barvalue", 8, &err
);
1072 rocksdb_compact_range(db
, NULL
, 0, NULL
, 0);
1074 fake_filter_result
= 1;
1075 CheckGet(db
, roptions
, "foo", "foovalue");
1076 CheckGet(db
, roptions
, "bar", "barvalue");
1078 // Must not find value when custom filter returns false
1079 fake_filter_result
= 0;
1080 CheckGet(db
, roptions
, "foo", NULL
);
1081 CheckGet(db
, roptions
, "bar", NULL
);
1082 fake_filter_result
= 1;
1084 CheckGet(db
, roptions
, "foo", "foovalue");
1085 CheckGet(db
, roptions
, "bar", "barvalue");
1088 rocksdb_block_based_options_set_filter_policy(table_options
, NULL
);
1089 rocksdb_options_set_block_based_table_factory(options
, table_options
);
1092 StartPhase("compaction_filter");
1094 rocksdb_options_t
* options_with_filter
= rocksdb_options_create();
1095 rocksdb_options_set_create_if_missing(options_with_filter
, 1);
1096 rocksdb_compactionfilter_t
* cfilter
;
1097 cfilter
= rocksdb_compactionfilter_create(NULL
, CFilterDestroy
,
1098 CFilterFilter
, CFilterName
);
1099 // Create new database
1101 rocksdb_destroy_db(options_with_filter
, dbname
, &err
);
1102 rocksdb_options_set_compaction_filter(options_with_filter
, cfilter
);
1103 db
= CheckCompaction(db
, options_with_filter
, roptions
, woptions
);
1105 rocksdb_options_set_compaction_filter(options_with_filter
, NULL
);
1106 rocksdb_compactionfilter_destroy(cfilter
);
1107 rocksdb_options_destroy(options_with_filter
);
1110 StartPhase("compaction_filter_factory");
1112 rocksdb_options_t
* options_with_filter_factory
= rocksdb_options_create();
1113 rocksdb_options_set_create_if_missing(options_with_filter_factory
, 1);
1114 rocksdb_compactionfilterfactory_t
* factory
;
1115 factory
= rocksdb_compactionfilterfactory_create(
1116 NULL
, CFilterFactoryDestroy
, CFilterCreate
, CFilterFactoryName
);
1117 // Create new database
1119 rocksdb_destroy_db(options_with_filter_factory
, dbname
, &err
);
1120 rocksdb_options_set_compaction_filter_factory(options_with_filter_factory
,
1122 db
= CheckCompaction(db
, options_with_filter_factory
, roptions
, woptions
);
1124 rocksdb_options_set_compaction_filter_factory(
1125 options_with_filter_factory
, NULL
);
1126 rocksdb_options_destroy(options_with_filter_factory
);
1129 StartPhase("merge_operator");
1131 rocksdb_mergeoperator_t
* merge_operator
;
1132 merge_operator
= rocksdb_mergeoperator_create(
1133 NULL
, MergeOperatorDestroy
, MergeOperatorFullMerge
,
1134 MergeOperatorPartialMerge
, NULL
, MergeOperatorName
);
1135 // Create new database
1137 rocksdb_destroy_db(options
, dbname
, &err
);
1138 rocksdb_options_set_merge_operator(options
, merge_operator
);
1139 db
= rocksdb_open(options
, dbname
, &err
);
1141 rocksdb_put(db
, woptions
, "foo", 3, "foovalue", 8, &err
);
1143 CheckGet(db
, roptions
, "foo", "foovalue");
1144 rocksdb_merge(db
, woptions
, "foo", 3, "barvalue", 8, &err
);
1146 CheckGet(db
, roptions
, "foo", "fake");
1148 // Merge of a non-existing value
1149 rocksdb_merge(db
, woptions
, "bar", 3, "barvalue", 8, &err
);
1151 CheckGet(db
, roptions
, "bar", "fake");
1155 StartPhase("columnfamilies");
1158 rocksdb_destroy_db(options
, dbname
, &err
);
1161 rocksdb_options_t
* db_options
= rocksdb_options_create();
1162 rocksdb_options_set_create_if_missing(db_options
, 1);
1163 db
= rocksdb_open(db_options
, dbname
, &err
);
1165 rocksdb_column_family_handle_t
* cfh
;
1166 cfh
= rocksdb_create_column_family(db
, db_options
, "cf1", &err
);
1167 rocksdb_column_family_handle_destroy(cfh
);
1172 char** column_fams
= rocksdb_list_column_families(db_options
, dbname
, &cflen
, &err
);
1174 CheckEqual("default", column_fams
[0], 7);
1175 CheckEqual("cf1", column_fams
[1], 3);
1176 CheckCondition(cflen
== 2);
1177 rocksdb_list_column_families_destroy(column_fams
, cflen
);
1179 rocksdb_options_t
* cf_options
= rocksdb_options_create();
1181 const char* cf_names
[2] = {"default", "cf1"};
1182 const rocksdb_options_t
* cf_opts
[2] = {cf_options
, cf_options
};
1183 rocksdb_column_family_handle_t
* handles
[2];
1184 db
= rocksdb_open_column_families(db_options
, dbname
, 2, cf_names
, cf_opts
, handles
, &err
);
1187 rocksdb_put_cf(db
, woptions
, handles
[1], "foo", 3, "hello", 5, &err
);
1190 CheckGetCF(db
, roptions
, handles
[1], "foo", "hello");
1191 CheckPinGetCF(db
, roptions
, handles
[1], "foo", "hello");
1193 rocksdb_delete_cf(db
, woptions
, handles
[1], "foo", 3, &err
);
1196 CheckGetCF(db
, roptions
, handles
[1], "foo", NULL
);
1197 CheckPinGetCF(db
, roptions
, handles
[1], "foo", NULL
);
1199 rocksdb_writebatch_t
* wb
= rocksdb_writebatch_create();
1200 rocksdb_writebatch_put_cf(wb
, handles
[1], "baz", 3, "a", 1);
1201 rocksdb_writebatch_clear(wb
);
1202 rocksdb_writebatch_put_cf(wb
, handles
[1], "bar", 3, "b", 1);
1203 rocksdb_writebatch_put_cf(wb
, handles
[1], "box", 3, "c", 1);
1204 rocksdb_writebatch_delete_cf(wb
, handles
[1], "bar", 3);
1205 rocksdb_write(db
, woptions
, wb
, &err
);
1207 CheckGetCF(db
, roptions
, handles
[1], "baz", NULL
);
1208 CheckGetCF(db
, roptions
, handles
[1], "bar", NULL
);
1209 CheckGetCF(db
, roptions
, handles
[1], "box", "c");
1210 CheckPinGetCF(db
, roptions
, handles
[1], "baz", NULL
);
1211 CheckPinGetCF(db
, roptions
, handles
[1], "bar", NULL
);
1212 CheckPinGetCF(db
, roptions
, handles
[1], "box", "c");
1213 rocksdb_writebatch_destroy(wb
);
1215 const char* keys
[3] = { "box", "box", "barfooxx" };
1216 const rocksdb_column_family_handle_t
* get_handles
[3] = { handles
[0], handles
[1], handles
[1] };
1217 const size_t keys_sizes
[3] = { 3, 3, 8 };
1219 size_t vals_sizes
[3];
1221 rocksdb_multi_get_cf(db
, roptions
, get_handles
, 3, keys
, keys_sizes
, vals
, vals_sizes
, errs
);
1224 for (i
= 0; i
< 3; i
++) {
1225 CheckEqual(NULL
, errs
[i
], 0);
1228 CheckEqual(NULL
, vals
[i
], vals_sizes
[i
]); // wrong cf
1231 CheckEqual("c", vals
[i
], vals_sizes
[i
]); // bingo
1234 CheckEqual(NULL
, vals
[i
], vals_sizes
[i
]); // normal not found
1240 rocksdb_iterator_t
* iter
= rocksdb_create_iterator_cf(db
, roptions
, handles
[1]);
1241 CheckCondition(!rocksdb_iter_valid(iter
));
1242 rocksdb_iter_seek_to_first(iter
);
1243 CheckCondition(rocksdb_iter_valid(iter
));
1245 for (i
= 0; rocksdb_iter_valid(iter
) != 0; rocksdb_iter_next(iter
)) {
1248 CheckCondition(i
== 1);
1249 rocksdb_iter_get_error(iter
, &err
);
1251 rocksdb_iter_destroy(iter
);
1253 rocksdb_column_family_handle_t
* iters_cf_handles
[2] = { handles
[0], handles
[1] };
1254 rocksdb_iterator_t
* iters_handles
[2];
1255 rocksdb_create_iterators(db
, roptions
, iters_cf_handles
, iters_handles
, 2, &err
);
1258 iter
= iters_handles
[0];
1259 CheckCondition(!rocksdb_iter_valid(iter
));
1260 rocksdb_iter_seek_to_first(iter
);
1261 CheckCondition(!rocksdb_iter_valid(iter
));
1262 rocksdb_iter_destroy(iter
);
1264 iter
= iters_handles
[1];
1265 CheckCondition(!rocksdb_iter_valid(iter
));
1266 rocksdb_iter_seek_to_first(iter
);
1267 CheckCondition(rocksdb_iter_valid(iter
));
1269 for (i
= 0; rocksdb_iter_valid(iter
) != 0; rocksdb_iter_next(iter
)) {
1272 CheckCondition(i
== 1);
1273 rocksdb_iter_get_error(iter
, &err
);
1275 rocksdb_iter_destroy(iter
);
1277 rocksdb_drop_column_family(db
, handles
[1], &err
);
1279 for (i
= 0; i
< 2; i
++) {
1280 rocksdb_column_family_handle_destroy(handles
[i
]);
1283 rocksdb_destroy_db(options
, dbname
, &err
);
1284 rocksdb_options_destroy(db_options
);
1285 rocksdb_options_destroy(cf_options
);
1288 StartPhase("prefix");
1290 // Create new database
1291 rocksdb_options_set_allow_mmap_reads(options
, 1);
1292 rocksdb_options_set_prefix_extractor(options
, rocksdb_slicetransform_create_fixed_prefix(3));
1293 rocksdb_options_set_hash_skip_list_rep(options
, 5000, 4, 4);
1294 rocksdb_options_set_plain_table_factory(options
, 4, 10, 0.75, 16);
1295 rocksdb_options_set_allow_concurrent_memtable_write(options
, 0);
1297 db
= rocksdb_open(options
, dbname
, &err
);
1300 rocksdb_put(db
, woptions
, "foo1", 4, "foo", 3, &err
);
1302 rocksdb_put(db
, woptions
, "foo2", 4, "foo", 3, &err
);
1304 rocksdb_put(db
, woptions
, "foo3", 4, "foo", 3, &err
);
1306 rocksdb_put(db
, woptions
, "bar1", 4, "bar", 3, &err
);
1308 rocksdb_put(db
, woptions
, "bar2", 4, "bar", 3, &err
);
1310 rocksdb_put(db
, woptions
, "bar3", 4, "bar", 3, &err
);
1313 rocksdb_iterator_t
* iter
= rocksdb_create_iterator(db
, roptions
);
1314 CheckCondition(!rocksdb_iter_valid(iter
));
1316 rocksdb_iter_seek(iter
, "bar", 3);
1317 rocksdb_iter_get_error(iter
, &err
);
1319 CheckCondition(rocksdb_iter_valid(iter
));
1321 CheckIter(iter
, "bar1", "bar");
1322 rocksdb_iter_next(iter
);
1323 CheckIter(iter
, "bar2", "bar");
1324 rocksdb_iter_next(iter
);
1325 CheckIter(iter
, "bar3", "bar");
1326 rocksdb_iter_get_error(iter
, &err
);
1328 rocksdb_iter_destroy(iter
);
1330 rocksdb_readoptions_set_total_order_seek(roptions
, 1);
1331 iter
= rocksdb_create_iterator(db
, roptions
);
1332 CheckCondition(!rocksdb_iter_valid(iter
));
1334 rocksdb_iter_seek(iter
, "ba", 2);
1335 rocksdb_iter_get_error(iter
, &err
);
1337 CheckCondition(rocksdb_iter_valid(iter
));
1338 CheckIter(iter
, "bar1", "bar");
1340 rocksdb_iter_destroy(iter
);
1341 rocksdb_readoptions_set_total_order_seek(roptions
, 0);
1344 rocksdb_destroy_db(options
, dbname
, &err
);
1347 // Check memory usage stats
1348 StartPhase("approximate_memory_usage");
1351 db
= rocksdb_open(options
, dbname
, &err
);
1354 rocksdb_memory_consumers_t
* consumers
;
1355 consumers
= rocksdb_memory_consumers_create();
1356 rocksdb_memory_consumers_add_db(consumers
, db
);
1357 rocksdb_memory_consumers_add_cache(consumers
, cache
);
1359 // take memory usage report before write-read operation
1360 rocksdb_memory_usage_t
* mu1
;
1361 mu1
= rocksdb_approximate_memory_usage_create(consumers
, &err
);
1364 // Put data (this should affect memtables)
1365 rocksdb_put(db
, woptions
, "memory", 6, "test", 4, &err
);
1367 CheckGet(db
, roptions
, "memory", "test");
1369 // take memory usage report after write-read operation
1370 rocksdb_memory_usage_t
* mu2
;
1371 mu2
= rocksdb_approximate_memory_usage_create(consumers
, &err
);
1374 // amount of memory used within memtables should grow
1375 CheckCondition(rocksdb_approximate_memory_usage_get_mem_table_total(mu2
) >=
1376 rocksdb_approximate_memory_usage_get_mem_table_total(mu1
));
1377 CheckCondition(rocksdb_approximate_memory_usage_get_mem_table_unflushed(mu2
) >=
1378 rocksdb_approximate_memory_usage_get_mem_table_unflushed(mu1
));
1380 rocksdb_memory_consumers_destroy(consumers
);
1381 rocksdb_approximate_memory_usage_destroy(mu1
);
1382 rocksdb_approximate_memory_usage_destroy(mu2
);
1384 rocksdb_destroy_db(options
, dbname
, &err
);
1388 StartPhase("cuckoo_options");
1390 rocksdb_cuckoo_table_options_t
* cuckoo_options
;
1391 cuckoo_options
= rocksdb_cuckoo_options_create();
1392 rocksdb_cuckoo_options_set_hash_ratio(cuckoo_options
, 0.5);
1393 rocksdb_cuckoo_options_set_max_search_depth(cuckoo_options
, 200);
1394 rocksdb_cuckoo_options_set_cuckoo_block_size(cuckoo_options
, 10);
1395 rocksdb_cuckoo_options_set_identity_as_first_hash(cuckoo_options
, 1);
1396 rocksdb_cuckoo_options_set_use_module_hash(cuckoo_options
, 0);
1397 rocksdb_options_set_cuckoo_table_factory(options
, cuckoo_options
);
1399 db
= rocksdb_open(options
, dbname
, &err
);
1402 rocksdb_cuckoo_options_destroy(cuckoo_options
);
1405 StartPhase("iterate_upper_bound");
1407 // Create new empty database
1409 rocksdb_destroy_db(options
, dbname
, &err
);
1412 rocksdb_options_set_prefix_extractor(options
, NULL
);
1413 db
= rocksdb_open(options
, dbname
, &err
);
1416 rocksdb_put(db
, woptions
, "a", 1, "0", 1, &err
); CheckNoError(err
);
1417 rocksdb_put(db
, woptions
, "foo", 3, "bar", 3, &err
); CheckNoError(err
);
1418 rocksdb_put(db
, woptions
, "foo1", 4, "bar1", 4, &err
); CheckNoError(err
);
1419 rocksdb_put(db
, woptions
, "g1", 2, "0", 1, &err
); CheckNoError(err
);
1421 // testing basic case with no iterate_upper_bound and no prefix_extractor
1423 rocksdb_readoptions_set_iterate_upper_bound(roptions
, NULL
, 0);
1424 rocksdb_iterator_t
* iter
= rocksdb_create_iterator(db
, roptions
);
1426 rocksdb_iter_seek(iter
, "foo", 3);
1427 CheckCondition(rocksdb_iter_valid(iter
));
1428 CheckIter(iter
, "foo", "bar");
1430 rocksdb_iter_next(iter
);
1431 CheckCondition(rocksdb_iter_valid(iter
));
1432 CheckIter(iter
, "foo1", "bar1");
1434 rocksdb_iter_next(iter
);
1435 CheckCondition(rocksdb_iter_valid(iter
));
1436 CheckIter(iter
, "g1", "0");
1438 rocksdb_iter_destroy(iter
);
1441 // testing iterate_upper_bound and forward iterator
1442 // to make sure it stops at bound
1444 // iterate_upper_bound points beyond the last expected entry
1445 rocksdb_readoptions_set_iterate_upper_bound(roptions
, "foo2", 4);
1447 rocksdb_iterator_t
* iter
= rocksdb_create_iterator(db
, roptions
);
1449 rocksdb_iter_seek(iter
, "foo", 3);
1450 CheckCondition(rocksdb_iter_valid(iter
));
1451 CheckIter(iter
, "foo", "bar");
1453 rocksdb_iter_next(iter
);
1454 CheckCondition(rocksdb_iter_valid(iter
));
1455 CheckIter(iter
, "foo1", "bar1");
1457 rocksdb_iter_next(iter
);
1458 // should stop here...
1459 CheckCondition(!rocksdb_iter_valid(iter
));
1461 rocksdb_iter_destroy(iter
);
1465 StartPhase("transactions");
1468 rocksdb_destroy_db(options
, dbname
, &err
);
1471 // open a TransactionDB
1472 txn_db_options
= rocksdb_transactiondb_options_create();
1473 txn_options
= rocksdb_transaction_options_create();
1474 rocksdb_options_set_create_if_missing(options
, 1);
1475 txn_db
= rocksdb_transactiondb_open(options
, txn_db_options
, dbname
, &err
);
1478 // put outside a transaction
1479 rocksdb_transactiondb_put(txn_db
, woptions
, "foo", 3, "hello", 5, &err
);
1481 CheckTxnDBGet(txn_db
, roptions
, "foo", "hello");
1483 // delete from outside transaction
1484 rocksdb_transactiondb_delete(txn_db
, woptions
, "foo", 3, &err
);
1486 CheckTxnDBGet(txn_db
, roptions
, "foo", NULL
);
1488 // write batch into TransactionDB
1489 rocksdb_writebatch_t
* wb
= rocksdb_writebatch_create();
1490 rocksdb_writebatch_put(wb
, "foo", 3, "a", 1);
1491 rocksdb_writebatch_clear(wb
);
1492 rocksdb_writebatch_put(wb
, "bar", 3, "b", 1);
1493 rocksdb_writebatch_put(wb
, "box", 3, "c", 1);
1494 rocksdb_writebatch_delete(wb
, "bar", 3);
1495 rocksdb_transactiondb_write(txn_db
, woptions
, wb
, &err
);
1496 rocksdb_writebatch_destroy(wb
);
1497 CheckTxnDBGet(txn_db
, roptions
, "box", "c");
1500 // begin a transaction
1501 txn
= rocksdb_transaction_begin(txn_db
, woptions
, txn_options
, NULL
);
1503 rocksdb_transaction_put(txn
, "foo", 3, "hello", 5, &err
);
1505 CheckTxnGet(txn
, roptions
, "foo", "hello");
1507 rocksdb_transaction_delete(txn
, "foo", 3, &err
);
1509 CheckTxnGet(txn
, roptions
, "foo", NULL
);
1511 rocksdb_transaction_put(txn
, "foo", 3, "hello", 5, &err
);
1514 // read from outside transaction, before commit
1515 CheckTxnDBGet(txn_db
, roptions
, "foo", NULL
);
1518 rocksdb_transaction_commit(txn
, &err
);
1521 // read from outside transaction, after commit
1522 CheckTxnDBGet(txn_db
, roptions
, "foo", "hello");
1524 // reuse old transaction
1525 txn
= rocksdb_transaction_begin(txn_db
, woptions
, txn_options
, txn
);
1528 const rocksdb_snapshot_t
* snapshot
;
1529 snapshot
= rocksdb_transactiondb_create_snapshot(txn_db
);
1530 rocksdb_readoptions_set_snapshot(roptions
, snapshot
);
1532 rocksdb_transactiondb_put(txn_db
, woptions
, "foo", 3, "hey", 3, &err
);
1535 CheckTxnDBGet(txn_db
, roptions
, "foo", "hello");
1536 rocksdb_readoptions_set_snapshot(roptions
, NULL
);
1537 rocksdb_transactiondb_release_snapshot(txn_db
, snapshot
);
1538 CheckTxnDBGet(txn_db
, roptions
, "foo", "hey");
1541 rocksdb_transaction_put(txn
, "bar", 3, "hi", 2, &err
);
1542 rocksdb_iterator_t
* iter
= rocksdb_transaction_create_iterator(txn
, roptions
);
1543 CheckCondition(!rocksdb_iter_valid(iter
));
1544 rocksdb_iter_seek_to_first(iter
);
1545 CheckCondition(rocksdb_iter_valid(iter
));
1546 CheckIter(iter
, "bar", "hi");
1547 rocksdb_iter_get_error(iter
, &err
);
1549 rocksdb_iter_destroy(iter
);
1552 rocksdb_transaction_rollback(txn
, &err
);
1554 CheckTxnDBGet(txn_db
, roptions
, "bar", NULL
);
1557 rocksdb_transaction_put(txn
, "foo1", 4, "hi1", 3, &err
);
1558 rocksdb_transaction_set_savepoint(txn
);
1559 CheckTxnGet(txn
, roptions
, "foo1", "hi1");
1560 rocksdb_transaction_put(txn
, "foo2", 4, "hi2", 3, &err
);
1561 CheckTxnGet(txn
, roptions
, "foo2", "hi2");
1563 // rollback to savepoint
1564 rocksdb_transaction_rollback_to_savepoint(txn
, &err
);
1566 CheckTxnGet(txn
, roptions
, "foo2", NULL
);
1567 CheckTxnGet(txn
, roptions
, "foo1", "hi1");
1568 CheckTxnDBGet(txn_db
, roptions
, "foo1", NULL
);
1569 CheckTxnDBGet(txn_db
, roptions
, "foo2", NULL
);
1570 rocksdb_transaction_commit(txn
, &err
);
1572 CheckTxnDBGet(txn_db
, roptions
, "foo1", "hi1");
1573 CheckTxnDBGet(txn_db
, roptions
, "foo2", NULL
);
1576 rocksdb_column_family_handle_t
* cfh
;
1577 cfh
= rocksdb_transactiondb_create_column_family(txn_db
, options
,
1581 rocksdb_transactiondb_put_cf(txn_db
, woptions
, cfh
, "cf_foo", 6, "cf_hello",
1584 CheckTxnDBGetCF(txn_db
, roptions
, cfh
, "cf_foo", "cf_hello");
1586 rocksdb_transactiondb_delete_cf(txn_db
, woptions
, cfh
, "cf_foo", 6, &err
);
1588 CheckTxnDBGetCF(txn_db
, roptions
, cfh
, "cf_foo", NULL
);
1590 rocksdb_column_family_handle_destroy(cfh
);
1592 // close and destroy
1593 rocksdb_transaction_destroy(txn
);
1594 rocksdb_transactiondb_close(txn_db
);
1595 rocksdb_destroy_db(options
, dbname
, &err
);
1597 rocksdb_transaction_options_destroy(txn_options
);
1598 rocksdb_transactiondb_options_destroy(txn_db_options
);
1601 StartPhase("optimistic_transactions");
1603 rocksdb_options_t
* db_options
= rocksdb_options_create();
1604 rocksdb_options_set_create_if_missing(db_options
, 1);
1605 rocksdb_options_set_allow_concurrent_memtable_write(db_options
, 1);
1606 otxn_db
= rocksdb_optimistictransactiondb_open(db_options
, dbname
, &err
);
1607 otxn_options
= rocksdb_optimistictransaction_options_create();
1608 rocksdb_transaction_t
* txn1
= rocksdb_optimistictransaction_begin(
1609 otxn_db
, woptions
, otxn_options
, NULL
);
1610 rocksdb_transaction_t
* txn2
= rocksdb_optimistictransaction_begin(
1611 otxn_db
, woptions
, otxn_options
, NULL
);
1612 rocksdb_transaction_put(txn1
, "key", 3, "value", 5, &err
);
1614 rocksdb_transaction_put(txn2
, "key1", 4, "value1", 6, &err
);
1616 CheckTxnGet(txn1
, roptions
, "key", "value");
1617 rocksdb_transaction_commit(txn1
, &err
);
1619 rocksdb_transaction_commit(txn2
, &err
);
1621 rocksdb_transaction_destroy(txn1
);
1622 rocksdb_transaction_destroy(txn2
);
1624 // Check column family
1625 db
= rocksdb_optimistictransactiondb_get_base_db(otxn_db
);
1626 rocksdb_put(db
, woptions
, "key", 3, "value", 5, &err
);
1628 rocksdb_column_family_handle_t
*cfh1
, *cfh2
;
1629 cfh1
= rocksdb_create_column_family(db
, db_options
, "txn_db_cf1", &err
);
1630 cfh2
= rocksdb_create_column_family(db
, db_options
, "txn_db_cf2", &err
);
1631 txn
= rocksdb_optimistictransaction_begin(otxn_db
, woptions
, otxn_options
,
1633 rocksdb_transaction_put_cf(txn
, cfh1
, "key_cf1", 7, "val_cf1", 7, &err
);
1635 rocksdb_transaction_put_cf(txn
, cfh2
, "key_cf2", 7, "val_cf2", 7, &err
);
1637 rocksdb_transaction_commit(txn
, &err
);
1639 txn
= rocksdb_optimistictransaction_begin(otxn_db
, woptions
, otxn_options
,
1641 CheckGetCF(db
, roptions
, cfh1
, "key_cf1", "val_cf1");
1642 CheckTxnGetCF(txn
, roptions
, cfh1
, "key_cf1", "val_cf1");
1644 // Check iterator with column family
1645 rocksdb_transaction_put_cf(txn
, cfh1
, "key1_cf", 7, "val1_cf", 7, &err
);
1647 rocksdb_iterator_t
* iter
=
1648 rocksdb_transaction_create_iterator_cf(txn
, roptions
, cfh1
);
1649 CheckCondition(!rocksdb_iter_valid(iter
));
1650 rocksdb_iter_seek_to_first(iter
);
1651 CheckCondition(rocksdb_iter_valid(iter
));
1652 CheckIter(iter
, "key1_cf", "val1_cf");
1653 rocksdb_iter_get_error(iter
, &err
);
1655 rocksdb_iter_destroy(iter
);
1657 rocksdb_transaction_destroy(txn
);
1658 rocksdb_column_family_handle_destroy(cfh1
);
1659 rocksdb_column_family_handle_destroy(cfh2
);
1660 rocksdb_optimistictransactiondb_close_base_db(db
);
1661 rocksdb_optimistictransactiondb_close(otxn_db
);
1663 // Check open optimistic transaction db with column families
1665 char** column_fams
=
1666 rocksdb_list_column_families(db_options
, dbname
, &cf_len
, &err
);
1668 CheckEqual("default", column_fams
[0], 7);
1669 CheckEqual("txn_db_cf1", column_fams
[1], 10);
1670 CheckEqual("txn_db_cf2", column_fams
[2], 10);
1671 CheckCondition(cf_len
== 3);
1672 rocksdb_list_column_families_destroy(column_fams
, cf_len
);
1674 const char* cf_names
[3] = {"default", "txn_db_cf1", "txn_db_cf2"};
1675 rocksdb_options_t
* cf_options
= rocksdb_options_create();
1676 const rocksdb_options_t
* cf_opts
[3] = {cf_options
, cf_options
, cf_options
};
1678 rocksdb_options_set_error_if_exists(cf_options
, 0);
1679 rocksdb_column_family_handle_t
* cf_handles
[3];
1680 otxn_db
= rocksdb_optimistictransactiondb_open_column_families(
1681 db_options
, dbname
, 3, cf_names
, cf_opts
, cf_handles
, &err
);
1683 rocksdb_transaction_t
* txn_cf
= rocksdb_optimistictransaction_begin(
1684 otxn_db
, woptions
, otxn_options
, NULL
);
1685 CheckTxnGetCF(txn_cf
, roptions
, cf_handles
[0], "key", "value");
1686 CheckTxnGetCF(txn_cf
, roptions
, cf_handles
[1], "key_cf1", "val_cf1");
1687 CheckTxnGetCF(txn_cf
, roptions
, cf_handles
[2], "key_cf2", "val_cf2");
1688 rocksdb_transaction_destroy(txn_cf
);
1689 rocksdb_options_destroy(cf_options
);
1690 rocksdb_column_family_handle_destroy(cf_handles
[0]);
1691 rocksdb_column_family_handle_destroy(cf_handles
[1]);
1692 rocksdb_column_family_handle_destroy(cf_handles
[2]);
1693 rocksdb_optimistictransactiondb_close(otxn_db
);
1694 rocksdb_destroy_db(db_options
, dbname
, &err
);
1695 rocksdb_options_destroy(db_options
);
1696 rocksdb_optimistictransaction_options_destroy(otxn_options
);
1700 // Simple sanity check that setting memtable rep works.
1701 StartPhase("memtable_reps");
1703 // Create database with vector memtable.
1704 rocksdb_options_set_memtable_vector_rep(options
);
1705 db
= rocksdb_open(options
, dbname
, &err
);
1708 // Create database with hash skiplist memtable.
1710 rocksdb_destroy_db(options
, dbname
, &err
);
1713 rocksdb_options_set_hash_skip_list_rep(options
, 5000, 4, 4);
1714 db
= rocksdb_open(options
, dbname
, &err
);
1718 // Simple sanity check that options setting db_paths work.
1719 StartPhase("open_db_paths");
1722 rocksdb_destroy_db(options
, dbname
, &err
);
1724 const rocksdb_dbpath_t
* paths
[1] = {dbpath
};
1725 rocksdb_options_set_db_paths(options
, paths
, 1);
1726 db
= rocksdb_open(options
, dbname
, &err
);
1730 StartPhase("cleanup");
1732 rocksdb_options_destroy(options
);
1733 rocksdb_block_based_options_destroy(table_options
);
1734 rocksdb_readoptions_destroy(roptions
);
1735 rocksdb_writeoptions_destroy(woptions
);
1736 rocksdb_compactoptions_destroy(coptions
);
1737 rocksdb_cache_destroy(cache
);
1738 rocksdb_comparator_destroy(cmp
);
1739 rocksdb_dbpath_destroy(dbpath
);
1740 rocksdb_env_destroy(env
);
1742 fprintf(stderr
, "PASS\n");
1749 fprintf(stderr
, "SKIPPED\n");
1753 #endif // !ROCKSDB_LITE