]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/db/c_test.c
29ff03a2512a2c697ea5b2e957e3bd8ebaecc4c7
[ceph.git] / ceph / src / rocksdb / db / c_test.c
1 /* Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2 Use of this source code is governed by a BSD-style license that can be
3 found in the LICENSE file. See the AUTHORS file for names of contributors. */
4
5 #include <stdio.h>
6
7 #ifndef ROCKSDB_LITE // Lite does not support C API
8
9 #include "rocksdb/c.h"
10
11 #include <stddef.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <sys/types.h>
15 #ifndef OS_WIN
16 #include <unistd.h>
17 #endif
18 #include <inttypes.h>
19
20 // Can not use port/port.h macros as this is a c file
21 #ifdef OS_WIN
22
23 #include <Windows.h>
24
25 #define snprintf _snprintf
26
27 // Ok for uniqueness
28 int geteuid() {
29 int result = 0;
30
31 result = ((int)GetCurrentProcessId() << 16);
32 result |= (int)GetCurrentThreadId();
33
34 return result;
35 }
36
37 #endif
38
39 const char* phase = "";
40 static char dbname[200];
41 static char sstfilename[200];
42 static char dbbackupname[200];
43
44 static void StartPhase(const char* name) {
45 fprintf(stderr, "=== Test %s\n", name);
46 phase = name;
47 }
48 static const char* GetTempDir(void) {
49 const char* ret = getenv("TEST_TMPDIR");
50 if (ret == NULL || ret[0] == '\0')
51 ret = "/tmp";
52 return ret;
53 }
54
55 #define CheckNoError(err) \
56 if ((err) != NULL) { \
57 fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, (err)); \
58 abort(); \
59 }
60
61 #define CheckCondition(cond) \
62 if (!(cond)) { \
63 fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, #cond); \
64 abort(); \
65 }
66
67 static void CheckEqual(const char* expected, const char* v, size_t n) {
68 if (expected == NULL && v == NULL) {
69 // ok
70 } else if (expected != NULL && v != NULL && n == strlen(expected) &&
71 memcmp(expected, v, n) == 0) {
72 // ok
73 return;
74 } else {
75 fprintf(stderr, "%s: expected '%s', got '%s'\n",
76 phase,
77 (expected ? expected : "(null)"),
78 (v ? v : "(null"));
79 abort();
80 }
81 }
82
83 static void Free(char** ptr) {
84 if (*ptr) {
85 free(*ptr);
86 *ptr = NULL;
87 }
88 }
89
90 static void CheckValue(
91 char* err,
92 const char* expected,
93 char** actual,
94 size_t actual_length) {
95 CheckNoError(err);
96 CheckEqual(expected, *actual, actual_length);
97 Free(actual);
98 }
99
100 static void CheckGet(
101 rocksdb_t* db,
102 const rocksdb_readoptions_t* options,
103 const char* key,
104 const char* expected) {
105 char* err = NULL;
106 size_t val_len;
107 char* val;
108 val = rocksdb_get(db, options, key, strlen(key), &val_len, &err);
109 CheckNoError(err);
110 CheckEqual(expected, val, val_len);
111 Free(&val);
112 }
113
114 static void CheckGetCF(
115 rocksdb_t* db,
116 const rocksdb_readoptions_t* options,
117 rocksdb_column_family_handle_t* handle,
118 const char* key,
119 const char* expected) {
120 char* err = NULL;
121 size_t val_len;
122 char* val;
123 val = rocksdb_get_cf(db, options, handle, key, strlen(key), &val_len, &err);
124 CheckNoError(err);
125 CheckEqual(expected, val, val_len);
126 Free(&val);
127 }
128
129
130 static void CheckIter(rocksdb_iterator_t* iter,
131 const char* key, const char* val) {
132 size_t len;
133 const char* str;
134 str = rocksdb_iter_key(iter, &len);
135 CheckEqual(key, str, len);
136 str = rocksdb_iter_value(iter, &len);
137 CheckEqual(val, str, len);
138 }
139
140 // Callback from rocksdb_writebatch_iterate()
141 static void CheckPut(void* ptr,
142 const char* k, size_t klen,
143 const char* v, size_t vlen) {
144 int* state = (int*) ptr;
145 CheckCondition(*state < 2);
146 switch (*state) {
147 case 0:
148 CheckEqual("bar", k, klen);
149 CheckEqual("b", v, vlen);
150 break;
151 case 1:
152 CheckEqual("box", k, klen);
153 CheckEqual("c", v, vlen);
154 break;
155 }
156 (*state)++;
157 }
158
159 // Callback from rocksdb_writebatch_iterate()
160 static void CheckDel(void* ptr, const char* k, size_t klen) {
161 int* state = (int*) ptr;
162 CheckCondition(*state == 2);
163 CheckEqual("bar", k, klen);
164 (*state)++;
165 }
166
167 static void CmpDestroy(void* arg) { }
168
169 static int CmpCompare(void* arg, const char* a, size_t alen,
170 const char* b, size_t blen) {
171 size_t n = (alen < blen) ? alen : blen;
172 int r = memcmp(a, b, n);
173 if (r == 0) {
174 if (alen < blen) r = -1;
175 else if (alen > blen) r = +1;
176 }
177 return r;
178 }
179
180 static const char* CmpName(void* arg) {
181 return "foo";
182 }
183
184 // Custom filter policy
185 static unsigned char fake_filter_result = 1;
186 static void FilterDestroy(void* arg) { }
187 static const char* FilterName(void* arg) {
188 return "TestFilter";
189 }
190 static char* FilterCreate(
191 void* arg,
192 const char* const* key_array, const size_t* key_length_array,
193 int num_keys,
194 size_t* filter_length) {
195 *filter_length = 4;
196 char* result = malloc(4);
197 memcpy(result, "fake", 4);
198 return result;
199 }
200 static unsigned char FilterKeyMatch(
201 void* arg,
202 const char* key, size_t length,
203 const char* filter, size_t filter_length) {
204 CheckCondition(filter_length == 4);
205 CheckCondition(memcmp(filter, "fake", 4) == 0);
206 return fake_filter_result;
207 }
208
209 // Custom compaction filter
210 static void CFilterDestroy(void* arg) {}
211 static const char* CFilterName(void* arg) { return "foo"; }
212 static unsigned char CFilterFilter(void* arg, int level, const char* key,
213 size_t key_length,
214 const char* existing_value,
215 size_t value_length, char** new_value,
216 size_t* new_value_length,
217 unsigned char* value_changed) {
218 if (key_length == 3) {
219 if (memcmp(key, "bar", key_length) == 0) {
220 return 1;
221 } else if (memcmp(key, "baz", key_length) == 0) {
222 *value_changed = 1;
223 *new_value = "newbazvalue";
224 *new_value_length = 11;
225 return 0;
226 }
227 }
228 return 0;
229 }
230
231 static void CFilterFactoryDestroy(void* arg) {}
232 static const char* CFilterFactoryName(void* arg) { return "foo"; }
233 static rocksdb_compactionfilter_t* CFilterCreate(
234 void* arg, rocksdb_compactionfiltercontext_t* context) {
235 return rocksdb_compactionfilter_create(NULL, CFilterDestroy, CFilterFilter,
236 CFilterName);
237 }
238
239 static rocksdb_t* CheckCompaction(rocksdb_t* db, rocksdb_options_t* options,
240 rocksdb_readoptions_t* roptions,
241 rocksdb_writeoptions_t* woptions) {
242 char* err = NULL;
243 db = rocksdb_open(options, dbname, &err);
244 CheckNoError(err);
245 rocksdb_put(db, woptions, "foo", 3, "foovalue", 8, &err);
246 CheckNoError(err);
247 CheckGet(db, roptions, "foo", "foovalue");
248 rocksdb_put(db, woptions, "bar", 3, "barvalue", 8, &err);
249 CheckNoError(err);
250 CheckGet(db, roptions, "bar", "barvalue");
251 rocksdb_put(db, woptions, "baz", 3, "bazvalue", 8, &err);
252 CheckNoError(err);
253 CheckGet(db, roptions, "baz", "bazvalue");
254
255 // Force compaction
256 rocksdb_compact_range(db, NULL, 0, NULL, 0);
257 // should have filtered bar, but not foo
258 CheckGet(db, roptions, "foo", "foovalue");
259 CheckGet(db, roptions, "bar", NULL);
260 CheckGet(db, roptions, "baz", "newbazvalue");
261 return db;
262 }
263
264 // Custom merge operator
265 static void MergeOperatorDestroy(void* arg) { }
266 static const char* MergeOperatorName(void* arg) {
267 return "TestMergeOperator";
268 }
269 static char* MergeOperatorFullMerge(
270 void* arg,
271 const char* key, size_t key_length,
272 const char* existing_value, size_t existing_value_length,
273 const char* const* operands_list, const size_t* operands_list_length,
274 int num_operands,
275 unsigned char* success, size_t* new_value_length) {
276 *new_value_length = 4;
277 *success = 1;
278 char* result = malloc(4);
279 memcpy(result, "fake", 4);
280 return result;
281 }
282 static char* MergeOperatorPartialMerge(
283 void* arg,
284 const char* key, size_t key_length,
285 const char* const* operands_list, const size_t* operands_list_length,
286 int num_operands,
287 unsigned char* success, size_t* new_value_length) {
288 *new_value_length = 4;
289 *success = 1;
290 char* result = malloc(4);
291 memcpy(result, "fake", 4);
292 return result;
293 }
294
295 int main(int argc, char** argv) {
296 rocksdb_t* db;
297 rocksdb_comparator_t* cmp;
298 rocksdb_cache_t* cache;
299 rocksdb_env_t* env;
300 rocksdb_options_t* options;
301 rocksdb_compactoptions_t* coptions;
302 rocksdb_block_based_table_options_t* table_options;
303 rocksdb_readoptions_t* roptions;
304 rocksdb_writeoptions_t* woptions;
305 rocksdb_ratelimiter_t* rate_limiter;
306 char* err = NULL;
307 int run = -1;
308
309 snprintf(dbname, sizeof(dbname),
310 "%s/rocksdb_c_test-%d",
311 GetTempDir(),
312 ((int) geteuid()));
313
314 snprintf(dbbackupname, sizeof(dbbackupname),
315 "%s/rocksdb_c_test-%d-backup",
316 GetTempDir(),
317 ((int) geteuid()));
318
319 snprintf(sstfilename, sizeof(sstfilename),
320 "%s/rocksdb_c_test-%d-sst",
321 GetTempDir(),
322 ((int)geteuid()));
323
324 StartPhase("create_objects");
325 cmp = rocksdb_comparator_create(NULL, CmpDestroy, CmpCompare, CmpName);
326 env = rocksdb_create_default_env();
327 cache = rocksdb_cache_create_lru(100000);
328
329 options = rocksdb_options_create();
330 rocksdb_options_set_comparator(options, cmp);
331 rocksdb_options_set_error_if_exists(options, 1);
332 rocksdb_options_set_env(options, env);
333 rocksdb_options_set_info_log(options, NULL);
334 rocksdb_options_set_write_buffer_size(options, 100000);
335 rocksdb_options_set_paranoid_checks(options, 1);
336 rocksdb_options_set_max_open_files(options, 10);
337 rocksdb_options_set_base_background_compactions(options, 1);
338 table_options = rocksdb_block_based_options_create();
339 rocksdb_block_based_options_set_block_cache(table_options, cache);
340 rocksdb_options_set_block_based_table_factory(options, table_options);
341
342 rocksdb_options_set_compression(options, rocksdb_no_compression);
343 rocksdb_options_set_compression_options(options, -14, -1, 0, 0);
344 int compression_levels[] = {rocksdb_no_compression, rocksdb_no_compression,
345 rocksdb_no_compression, rocksdb_no_compression};
346 rocksdb_options_set_compression_per_level(options, compression_levels, 4);
347 rate_limiter = rocksdb_ratelimiter_create(1000 * 1024 * 1024, 100 * 1000, 10);
348 rocksdb_options_set_ratelimiter(options, rate_limiter);
349 rocksdb_ratelimiter_destroy(rate_limiter);
350
351 roptions = rocksdb_readoptions_create();
352 rocksdb_readoptions_set_verify_checksums(roptions, 1);
353 rocksdb_readoptions_set_fill_cache(roptions, 1);
354
355 woptions = rocksdb_writeoptions_create();
356 rocksdb_writeoptions_set_sync(woptions, 1);
357
358 coptions = rocksdb_compactoptions_create();
359 rocksdb_compactoptions_set_exclusive_manual_compaction(coptions, 1);
360
361 StartPhase("destroy");
362 rocksdb_destroy_db(options, dbname, &err);
363 Free(&err);
364
365 StartPhase("open_error");
366 rocksdb_open(options, dbname, &err);
367 CheckCondition(err != NULL);
368 Free(&err);
369
370 StartPhase("open");
371 rocksdb_options_set_create_if_missing(options, 1);
372 db = rocksdb_open(options, dbname, &err);
373 CheckNoError(err);
374 CheckGet(db, roptions, "foo", NULL);
375
376 StartPhase("put");
377 rocksdb_put(db, woptions, "foo", 3, "hello", 5, &err);
378 CheckNoError(err);
379 CheckGet(db, roptions, "foo", "hello");
380
381 StartPhase("backup_and_restore");
382 {
383 rocksdb_destroy_db(options, dbbackupname, &err);
384 CheckNoError(err);
385
386 rocksdb_backup_engine_t *be = rocksdb_backup_engine_open(options, dbbackupname, &err);
387 CheckNoError(err);
388
389 rocksdb_backup_engine_create_new_backup(be, db, &err);
390 CheckNoError(err);
391
392 // need a change to trigger a new backup
393 rocksdb_delete(db, woptions, "does-not-exist", 14, &err);
394 CheckNoError(err);
395
396 rocksdb_backup_engine_create_new_backup(be, db, &err);
397 CheckNoError(err);
398
399 const rocksdb_backup_engine_info_t* bei = rocksdb_backup_engine_get_backup_info(be);
400 CheckCondition(rocksdb_backup_engine_info_count(bei) > 1);
401 rocksdb_backup_engine_info_destroy(bei);
402
403 rocksdb_backup_engine_purge_old_backups(be, 1, &err);
404 CheckNoError(err);
405
406 bei = rocksdb_backup_engine_get_backup_info(be);
407 CheckCondition(rocksdb_backup_engine_info_count(bei) == 1);
408 rocksdb_backup_engine_info_destroy(bei);
409
410 rocksdb_delete(db, woptions, "foo", 3, &err);
411 CheckNoError(err);
412
413 rocksdb_close(db);
414
415 rocksdb_destroy_db(options, dbname, &err);
416 CheckNoError(err);
417
418 rocksdb_restore_options_t *restore_options = rocksdb_restore_options_create();
419 rocksdb_restore_options_set_keep_log_files(restore_options, 0);
420 rocksdb_backup_engine_restore_db_from_latest_backup(be, dbname, dbname, restore_options, &err);
421 CheckNoError(err);
422 rocksdb_restore_options_destroy(restore_options);
423
424 rocksdb_options_set_error_if_exists(options, 0);
425 db = rocksdb_open(options, dbname, &err);
426 CheckNoError(err);
427 rocksdb_options_set_error_if_exists(options, 1);
428
429 CheckGet(db, roptions, "foo", "hello");
430
431 rocksdb_backup_engine_close(be);
432 }
433
434 StartPhase("compactall");
435 rocksdb_compact_range(db, NULL, 0, NULL, 0);
436 CheckGet(db, roptions, "foo", "hello");
437
438 StartPhase("compactrange");
439 rocksdb_compact_range(db, "a", 1, "z", 1);
440 CheckGet(db, roptions, "foo", "hello");
441
442 StartPhase("compactallopt");
443 rocksdb_compact_range_opt(db, coptions, NULL, 0, NULL, 0);
444 CheckGet(db, roptions, "foo", "hello");
445
446 StartPhase("compactrangeopt");
447 rocksdb_compact_range_opt(db, coptions, "a", 1, "z", 1);
448 CheckGet(db, roptions, "foo", "hello");
449
450 // Simple check cache usage
451 StartPhase("cache_usage");
452 {
453 rocksdb_readoptions_set_pin_data(roptions, 1);
454 rocksdb_iterator_t* iter = rocksdb_create_iterator(db, roptions);
455 rocksdb_iter_seek(iter, "foo", 3);
456
457 size_t usage = rocksdb_cache_get_usage(cache);
458 CheckCondition(usage > 0);
459
460 size_t pin_usage = rocksdb_cache_get_pinned_usage(cache);
461 CheckCondition(pin_usage > 0);
462
463 rocksdb_iter_next(iter);
464 rocksdb_iter_destroy(iter);
465 rocksdb_readoptions_set_pin_data(roptions, 0);
466 }
467
468 StartPhase("addfile");
469 {
470 rocksdb_envoptions_t* env_opt = rocksdb_envoptions_create();
471 rocksdb_options_t* io_options = rocksdb_options_create();
472 rocksdb_sstfilewriter_t* writer =
473 rocksdb_sstfilewriter_create(env_opt, io_options);
474
475 unlink(sstfilename);
476 rocksdb_sstfilewriter_open(writer, sstfilename, &err);
477 CheckNoError(err);
478 rocksdb_sstfilewriter_add(writer, "sstk1", 5, "v1", 2, &err);
479 CheckNoError(err);
480 rocksdb_sstfilewriter_add(writer, "sstk2", 5, "v2", 2, &err);
481 CheckNoError(err);
482 rocksdb_sstfilewriter_add(writer, "sstk3", 5, "v3", 2, &err);
483 CheckNoError(err);
484 rocksdb_sstfilewriter_finish(writer, &err);
485 CheckNoError(err);
486
487 rocksdb_ingestexternalfileoptions_t* ing_opt =
488 rocksdb_ingestexternalfileoptions_create();
489 const char* file_list[1] = {sstfilename};
490 rocksdb_ingest_external_file(db, file_list, 1, ing_opt, &err);
491 CheckNoError(err);
492 CheckGet(db, roptions, "sstk1", "v1");
493 CheckGet(db, roptions, "sstk2", "v2");
494 CheckGet(db, roptions, "sstk3", "v3");
495
496 unlink(sstfilename);
497 rocksdb_sstfilewriter_open(writer, sstfilename, &err);
498 CheckNoError(err);
499 rocksdb_sstfilewriter_add(writer, "sstk2", 5, "v4", 2, &err);
500 CheckNoError(err);
501 rocksdb_sstfilewriter_add(writer, "sstk22", 6, "v5", 2, &err);
502 CheckNoError(err);
503 rocksdb_sstfilewriter_add(writer, "sstk3", 5, "v6", 2, &err);
504 CheckNoError(err);
505 rocksdb_sstfilewriter_finish(writer, &err);
506 CheckNoError(err);
507
508 rocksdb_ingest_external_file(db, file_list, 1, ing_opt, &err);
509 CheckNoError(err);
510 CheckGet(db, roptions, "sstk1", "v1");
511 CheckGet(db, roptions, "sstk2", "v4");
512 CheckGet(db, roptions, "sstk22", "v5");
513 CheckGet(db, roptions, "sstk3", "v6");
514
515 rocksdb_ingestexternalfileoptions_destroy(ing_opt);
516 rocksdb_sstfilewriter_destroy(writer);
517 rocksdb_options_destroy(io_options);
518 rocksdb_envoptions_destroy(env_opt);
519
520 // Delete all keys we just ingested
521 rocksdb_delete(db, woptions, "sstk1", 5, &err);
522 CheckNoError(err);
523 rocksdb_delete(db, woptions, "sstk2", 5, &err);
524 CheckNoError(err);
525 rocksdb_delete(db, woptions, "sstk22", 6, &err);
526 CheckNoError(err);
527 rocksdb_delete(db, woptions, "sstk3", 5, &err);
528 CheckNoError(err);
529 }
530
531 StartPhase("writebatch");
532 {
533 rocksdb_writebatch_t* wb = rocksdb_writebatch_create();
534 rocksdb_writebatch_put(wb, "foo", 3, "a", 1);
535 rocksdb_writebatch_clear(wb);
536 rocksdb_writebatch_put(wb, "bar", 3, "b", 1);
537 rocksdb_writebatch_put(wb, "box", 3, "c", 1);
538 rocksdb_writebatch_delete(wb, "bar", 3);
539 rocksdb_write(db, woptions, wb, &err);
540 CheckNoError(err);
541 CheckGet(db, roptions, "foo", "hello");
542 CheckGet(db, roptions, "bar", NULL);
543 CheckGet(db, roptions, "box", "c");
544 int pos = 0;
545 rocksdb_writebatch_iterate(wb, &pos, CheckPut, CheckDel);
546 CheckCondition(pos == 3);
547 rocksdb_writebatch_clear(wb);
548 rocksdb_writebatch_put(wb, "bar", 3, "b", 1);
549 rocksdb_writebatch_put(wb, "bay", 3, "d", 1);
550 rocksdb_writebatch_delete_range(wb, "bar", 3, "bay", 3);
551 rocksdb_write(db, woptions, wb, &err);
552 CheckNoError(err);
553 CheckGet(db, roptions, "bar", NULL);
554 CheckGet(db, roptions, "bay", "d");
555 rocksdb_writebatch_clear(wb);
556 const char* start_list[1] = {"bay"};
557 const size_t start_sizes[1] = {3};
558 const char* end_list[1] = {"baz"};
559 const size_t end_sizes[1] = {3};
560 rocksdb_writebatch_delete_rangev(wb, 1, start_list, start_sizes, end_list,
561 end_sizes);
562 rocksdb_write(db, woptions, wb, &err);
563 CheckNoError(err);
564 CheckGet(db, roptions, "bay", NULL);
565 rocksdb_writebatch_destroy(wb);
566 }
567
568 StartPhase("writebatch_vectors");
569 {
570 rocksdb_writebatch_t* wb = rocksdb_writebatch_create();
571 const char* k_list[2] = { "z", "ap" };
572 const size_t k_sizes[2] = { 1, 2 };
573 const char* v_list[3] = { "x", "y", "z" };
574 const size_t v_sizes[3] = { 1, 1, 1 };
575 rocksdb_writebatch_putv(wb, 2, k_list, k_sizes, 3, v_list, v_sizes);
576 rocksdb_write(db, woptions, wb, &err);
577 CheckNoError(err);
578 CheckGet(db, roptions, "zap", "xyz");
579 rocksdb_writebatch_delete(wb, "zap", 3);
580 rocksdb_write(db, woptions, wb, &err);
581 CheckNoError(err);
582 CheckGet(db, roptions, "zap", NULL);
583 rocksdb_writebatch_destroy(wb);
584 }
585
586 StartPhase("writebatch_savepoint");
587 {
588 rocksdb_writebatch_t* wb = rocksdb_writebatch_create();
589 rocksdb_writebatch_set_save_point(wb);
590 const char* k_list[2] = {"z", "ap"};
591 const size_t k_sizes[2] = {1, 2};
592 const char* v_list[3] = {"x", "y", "z"};
593 const size_t v_sizes[3] = {1, 1, 1};
594 rocksdb_writebatch_putv(wb, 2, k_list, k_sizes, 3, v_list, v_sizes);
595 rocksdb_writebatch_rollback_to_save_point(wb, &err);
596 CheckNoError(err);
597 rocksdb_write(db, woptions, wb, &err);
598 CheckNoError(err);
599 CheckGet(db, roptions, "zap", NULL);
600 rocksdb_writebatch_destroy(wb);
601 }
602
603 StartPhase("writebatch_rep");
604 {
605 rocksdb_writebatch_t* wb1 = rocksdb_writebatch_create();
606 rocksdb_writebatch_put(wb1, "baz", 3, "d", 1);
607 rocksdb_writebatch_put(wb1, "quux", 4, "e", 1);
608 rocksdb_writebatch_delete(wb1, "quux", 4);
609 size_t repsize1 = 0;
610 const char* rep = rocksdb_writebatch_data(wb1, &repsize1);
611 rocksdb_writebatch_t* wb2 = rocksdb_writebatch_create_from(rep, repsize1);
612 CheckCondition(rocksdb_writebatch_count(wb1) ==
613 rocksdb_writebatch_count(wb2));
614 size_t repsize2 = 0;
615 CheckCondition(
616 memcmp(rep, rocksdb_writebatch_data(wb2, &repsize2), repsize1) == 0);
617 rocksdb_writebatch_destroy(wb1);
618 rocksdb_writebatch_destroy(wb2);
619 }
620
621 StartPhase("writebatch_wi");
622 {
623 rocksdb_writebatch_wi_t* wbi = rocksdb_writebatch_wi_create(0, 1);
624 rocksdb_writebatch_wi_put(wbi, "foo", 3, "a", 1);
625 rocksdb_writebatch_wi_clear(wbi);
626 rocksdb_writebatch_wi_put(wbi, "bar", 3, "b", 1);
627 rocksdb_writebatch_wi_put(wbi, "box", 3, "c", 1);
628 rocksdb_writebatch_wi_delete(wbi, "bar", 3);
629 int count = rocksdb_writebatch_wi_count(wbi);
630 CheckCondition(count == 3);
631 size_t size;
632 char* value;
633 value = rocksdb_writebatch_wi_get_from_batch(wbi, options, "box", 3, &size, &err);
634 CheckValue(err, "c", &value, size);
635 value = rocksdb_writebatch_wi_get_from_batch(wbi, options, "bar", 3, &size, &err);
636 CheckValue(err, NULL, &value, size);
637 value = rocksdb_writebatch_wi_get_from_batch_and_db(wbi, db, roptions, "foo", 3, &size, &err);
638 CheckValue(err, "hello", &value, size);
639 value = rocksdb_writebatch_wi_get_from_batch_and_db(wbi, db, roptions, "box", 3, &size, &err);
640 CheckValue(err, "c", &value, size);
641 rocksdb_write_writebatch_wi(db, woptions, wbi, &err);
642 CheckNoError(err);
643 CheckGet(db, roptions, "foo", "hello");
644 CheckGet(db, roptions, "bar", NULL);
645 CheckGet(db, roptions, "box", "c");
646 int pos = 0;
647 rocksdb_writebatch_wi_iterate(wbi, &pos, CheckPut, CheckDel);
648 CheckCondition(pos == 3);
649 rocksdb_writebatch_wi_clear(wbi);
650 rocksdb_writebatch_wi_put(wbi, "bar", 3, "b", 1);
651 rocksdb_writebatch_wi_put(wbi, "bay", 3, "d", 1);
652 rocksdb_writebatch_wi_delete_range(wbi, "bar", 3, "bay", 3);
653 rocksdb_write_writebatch_wi(db, woptions, wbi, &err);
654 CheckNoError(err);
655 CheckGet(db, roptions, "bar", NULL);
656 CheckGet(db, roptions, "bay", "d");
657 rocksdb_writebatch_wi_clear(wbi);
658 const char* start_list[1] = {"bay"};
659 const size_t start_sizes[1] = {3};
660 const char* end_list[1] = {"baz"};
661 const size_t end_sizes[1] = {3};
662 rocksdb_writebatch_wi_delete_rangev(wbi, 1, start_list, start_sizes, end_list,
663 end_sizes);
664 rocksdb_write_writebatch_wi(db, woptions, wbi, &err);
665 CheckNoError(err);
666 CheckGet(db, roptions, "bay", NULL);
667 rocksdb_writebatch_wi_destroy(wbi);
668 }
669
670 StartPhase("writebatch_wi_vectors");
671 {
672 rocksdb_writebatch_wi_t* wb = rocksdb_writebatch_wi_create(0, 1);
673 const char* k_list[2] = { "z", "ap" };
674 const size_t k_sizes[2] = { 1, 2 };
675 const char* v_list[3] = { "x", "y", "z" };
676 const size_t v_sizes[3] = { 1, 1, 1 };
677 rocksdb_writebatch_wi_putv(wb, 2, k_list, k_sizes, 3, v_list, v_sizes);
678 rocksdb_write_writebatch_wi(db, woptions, wb, &err);
679 CheckNoError(err);
680 CheckGet(db, roptions, "zap", "xyz");
681 rocksdb_writebatch_wi_delete(wb, "zap", 3);
682 rocksdb_write_writebatch_wi(db, woptions, wb, &err);
683 CheckNoError(err);
684 CheckGet(db, roptions, "zap", NULL);
685 rocksdb_writebatch_wi_destroy(wb);
686 }
687
688 StartPhase("writebatch_wi_savepoint");
689 {
690 rocksdb_writebatch_wi_t* wb = rocksdb_writebatch_wi_create(0, 1);
691 rocksdb_writebatch_wi_set_save_point(wb);
692 const char* k_list[2] = {"z", "ap"};
693 const size_t k_sizes[2] = {1, 2};
694 const char* v_list[3] = {"x", "y", "z"};
695 const size_t v_sizes[3] = {1, 1, 1};
696 rocksdb_writebatch_wi_putv(wb, 2, k_list, k_sizes, 3, v_list, v_sizes);
697 rocksdb_writebatch_wi_rollback_to_save_point(wb, &err);
698 CheckNoError(err);
699 rocksdb_write_writebatch_wi(db, woptions, wb, &err);
700 CheckNoError(err);
701 CheckGet(db, roptions, "zap", NULL);
702 rocksdb_writebatch_wi_destroy(wb);
703 }
704
705 StartPhase("iter");
706 {
707 rocksdb_iterator_t* iter = rocksdb_create_iterator(db, roptions);
708 CheckCondition(!rocksdb_iter_valid(iter));
709 rocksdb_iter_seek_to_first(iter);
710 CheckCondition(rocksdb_iter_valid(iter));
711 CheckIter(iter, "box", "c");
712 rocksdb_iter_next(iter);
713 CheckIter(iter, "foo", "hello");
714 rocksdb_iter_prev(iter);
715 CheckIter(iter, "box", "c");
716 rocksdb_iter_prev(iter);
717 CheckCondition(!rocksdb_iter_valid(iter));
718 rocksdb_iter_seek_to_last(iter);
719 CheckIter(iter, "foo", "hello");
720 rocksdb_iter_seek(iter, "b", 1);
721 CheckIter(iter, "box", "c");
722 rocksdb_iter_seek_for_prev(iter, "g", 1);
723 CheckIter(iter, "foo", "hello");
724 rocksdb_iter_seek_for_prev(iter, "box", 3);
725 CheckIter(iter, "box", "c");
726 rocksdb_iter_get_error(iter, &err);
727 CheckNoError(err);
728 rocksdb_iter_destroy(iter);
729 }
730
731 StartPhase("wbwi_iter");
732 {
733 rocksdb_iterator_t* base_iter = rocksdb_create_iterator(db, roptions);
734 rocksdb_writebatch_wi_t* wbi = rocksdb_writebatch_wi_create(0, 1);
735 rocksdb_writebatch_wi_put(wbi, "bar", 3, "b", 1);
736 rocksdb_writebatch_wi_delete(wbi, "foo", 3);
737 rocksdb_iterator_t* iter = rocksdb_writebatch_wi_create_iterator_with_base(wbi, base_iter);
738 CheckCondition(!rocksdb_iter_valid(iter));
739 rocksdb_iter_seek_to_first(iter);
740 CheckCondition(rocksdb_iter_valid(iter));
741 CheckIter(iter, "bar", "b");
742 rocksdb_iter_next(iter);
743 CheckIter(iter, "box", "c");
744 rocksdb_iter_prev(iter);
745 CheckIter(iter, "bar", "b");
746 rocksdb_iter_prev(iter);
747 CheckCondition(!rocksdb_iter_valid(iter));
748 rocksdb_iter_seek_to_last(iter);
749 CheckIter(iter, "box", "c");
750 rocksdb_iter_seek(iter, "b", 1);
751 CheckIter(iter, "bar", "b");
752 rocksdb_iter_seek_for_prev(iter, "c", 1);
753 CheckIter(iter, "box", "c");
754 rocksdb_iter_seek_for_prev(iter, "box", 3);
755 CheckIter(iter, "box", "c");
756 rocksdb_iter_get_error(iter, &err);
757 CheckNoError(err);
758 rocksdb_iter_destroy(iter);
759 rocksdb_writebatch_wi_destroy(wbi);
760 }
761
762 StartPhase("multiget");
763 {
764 const char* keys[3] = { "box", "foo", "notfound" };
765 const size_t keys_sizes[3] = { 3, 3, 8 };
766 char* vals[3];
767 size_t vals_sizes[3];
768 char* errs[3];
769 rocksdb_multi_get(db, roptions, 3, keys, keys_sizes, vals, vals_sizes, errs);
770
771 int i;
772 for (i = 0; i < 3; i++) {
773 CheckEqual(NULL, errs[i], 0);
774 switch (i) {
775 case 0:
776 CheckEqual("c", vals[i], vals_sizes[i]);
777 break;
778 case 1:
779 CheckEqual("hello", vals[i], vals_sizes[i]);
780 break;
781 case 2:
782 CheckEqual(NULL, vals[i], vals_sizes[i]);
783 break;
784 }
785 Free(&vals[i]);
786 }
787 }
788
789 StartPhase("approximate_sizes");
790 {
791 int i;
792 int n = 20000;
793 char keybuf[100];
794 char valbuf[100];
795 uint64_t sizes[2];
796 const char* start[2] = { "a", "k00000000000000010000" };
797 size_t start_len[2] = { 1, 21 };
798 const char* limit[2] = { "k00000000000000010000", "z" };
799 size_t limit_len[2] = { 21, 1 };
800 rocksdb_writeoptions_set_sync(woptions, 0);
801 for (i = 0; i < n; i++) {
802 snprintf(keybuf, sizeof(keybuf), "k%020d", i);
803 snprintf(valbuf, sizeof(valbuf), "v%020d", i);
804 rocksdb_put(db, woptions, keybuf, strlen(keybuf), valbuf, strlen(valbuf),
805 &err);
806 CheckNoError(err);
807 }
808 rocksdb_approximate_sizes(db, 2, start, start_len, limit, limit_len, sizes);
809 CheckCondition(sizes[0] > 0);
810 CheckCondition(sizes[1] > 0);
811 }
812
813 StartPhase("property");
814 {
815 char* prop = rocksdb_property_value(db, "nosuchprop");
816 CheckCondition(prop == NULL);
817 prop = rocksdb_property_value(db, "rocksdb.stats");
818 CheckCondition(prop != NULL);
819 Free(&prop);
820 }
821
822 StartPhase("snapshot");
823 {
824 const rocksdb_snapshot_t* snap;
825 snap = rocksdb_create_snapshot(db);
826 rocksdb_delete(db, woptions, "foo", 3, &err);
827 CheckNoError(err);
828 rocksdb_readoptions_set_snapshot(roptions, snap);
829 CheckGet(db, roptions, "foo", "hello");
830 rocksdb_readoptions_set_snapshot(roptions, NULL);
831 CheckGet(db, roptions, "foo", NULL);
832 rocksdb_release_snapshot(db, snap);
833 }
834
835 StartPhase("repair");
836 {
837 // If we do not compact here, then the lazy deletion of
838 // files (https://reviews.facebook.net/D6123) would leave
839 // around deleted files and the repair process will find
840 // those files and put them back into the database.
841 rocksdb_compact_range(db, NULL, 0, NULL, 0);
842 rocksdb_close(db);
843 rocksdb_options_set_create_if_missing(options, 0);
844 rocksdb_options_set_error_if_exists(options, 0);
845 rocksdb_options_set_wal_recovery_mode(options, 2);
846 rocksdb_repair_db(options, dbname, &err);
847 CheckNoError(err);
848 db = rocksdb_open(options, dbname, &err);
849 CheckNoError(err);
850 CheckGet(db, roptions, "foo", NULL);
851 CheckGet(db, roptions, "bar", NULL);
852 CheckGet(db, roptions, "box", "c");
853 rocksdb_options_set_create_if_missing(options, 1);
854 rocksdb_options_set_error_if_exists(options, 1);
855 }
856
857 StartPhase("filter");
858 for (run = 0; run < 2; run++) {
859 // First run uses custom filter, second run uses bloom filter
860 CheckNoError(err);
861 rocksdb_filterpolicy_t* policy;
862 if (run == 0) {
863 policy = rocksdb_filterpolicy_create(
864 NULL, FilterDestroy, FilterCreate, FilterKeyMatch, NULL, FilterName);
865 } else {
866 policy = rocksdb_filterpolicy_create_bloom(10);
867 }
868
869 rocksdb_block_based_options_set_filter_policy(table_options, policy);
870
871 // Create new database
872 rocksdb_close(db);
873 rocksdb_destroy_db(options, dbname, &err);
874 rocksdb_options_set_block_based_table_factory(options, table_options);
875 db = rocksdb_open(options, dbname, &err);
876 CheckNoError(err);
877 rocksdb_put(db, woptions, "foo", 3, "foovalue", 8, &err);
878 CheckNoError(err);
879 rocksdb_put(db, woptions, "bar", 3, "barvalue", 8, &err);
880 CheckNoError(err);
881 rocksdb_compact_range(db, NULL, 0, NULL, 0);
882
883 fake_filter_result = 1;
884 CheckGet(db, roptions, "foo", "foovalue");
885 CheckGet(db, roptions, "bar", "barvalue");
886 if (phase == 0) {
887 // Must not find value when custom filter returns false
888 fake_filter_result = 0;
889 CheckGet(db, roptions, "foo", NULL);
890 CheckGet(db, roptions, "bar", NULL);
891 fake_filter_result = 1;
892
893 CheckGet(db, roptions, "foo", "foovalue");
894 CheckGet(db, roptions, "bar", "barvalue");
895 }
896 // Reset the policy
897 rocksdb_block_based_options_set_filter_policy(table_options, NULL);
898 rocksdb_options_set_block_based_table_factory(options, table_options);
899 }
900
901 StartPhase("compaction_filter");
902 {
903 rocksdb_options_t* options_with_filter = rocksdb_options_create();
904 rocksdb_options_set_create_if_missing(options_with_filter, 1);
905 rocksdb_compactionfilter_t* cfilter;
906 cfilter = rocksdb_compactionfilter_create(NULL, CFilterDestroy,
907 CFilterFilter, CFilterName);
908 // Create new database
909 rocksdb_close(db);
910 rocksdb_destroy_db(options_with_filter, dbname, &err);
911 rocksdb_options_set_compaction_filter(options_with_filter, cfilter);
912 db = CheckCompaction(db, options_with_filter, roptions, woptions);
913
914 rocksdb_options_set_compaction_filter(options_with_filter, NULL);
915 rocksdb_compactionfilter_destroy(cfilter);
916 rocksdb_options_destroy(options_with_filter);
917 }
918
919 StartPhase("compaction_filter_factory");
920 {
921 rocksdb_options_t* options_with_filter_factory = rocksdb_options_create();
922 rocksdb_options_set_create_if_missing(options_with_filter_factory, 1);
923 rocksdb_compactionfilterfactory_t* factory;
924 factory = rocksdb_compactionfilterfactory_create(
925 NULL, CFilterFactoryDestroy, CFilterCreate, CFilterFactoryName);
926 // Create new database
927 rocksdb_close(db);
928 rocksdb_destroy_db(options_with_filter_factory, dbname, &err);
929 rocksdb_options_set_compaction_filter_factory(options_with_filter_factory,
930 factory);
931 db = CheckCompaction(db, options_with_filter_factory, roptions, woptions);
932
933 rocksdb_options_set_compaction_filter_factory(
934 options_with_filter_factory, NULL);
935 rocksdb_options_destroy(options_with_filter_factory);
936 }
937
938 StartPhase("merge_operator");
939 {
940 rocksdb_mergeoperator_t* merge_operator;
941 merge_operator = rocksdb_mergeoperator_create(
942 NULL, MergeOperatorDestroy, MergeOperatorFullMerge,
943 MergeOperatorPartialMerge, NULL, MergeOperatorName);
944 // Create new database
945 rocksdb_close(db);
946 rocksdb_destroy_db(options, dbname, &err);
947 rocksdb_options_set_merge_operator(options, merge_operator);
948 db = rocksdb_open(options, dbname, &err);
949 CheckNoError(err);
950 rocksdb_put(db, woptions, "foo", 3, "foovalue", 8, &err);
951 CheckNoError(err);
952 CheckGet(db, roptions, "foo", "foovalue");
953 rocksdb_merge(db, woptions, "foo", 3, "barvalue", 8, &err);
954 CheckNoError(err);
955 CheckGet(db, roptions, "foo", "fake");
956
957 // Merge of a non-existing value
958 rocksdb_merge(db, woptions, "bar", 3, "barvalue", 8, &err);
959 CheckNoError(err);
960 CheckGet(db, roptions, "bar", "fake");
961
962 }
963
964 StartPhase("columnfamilies");
965 {
966 rocksdb_close(db);
967 rocksdb_destroy_db(options, dbname, &err);
968 CheckNoError(err);
969
970 rocksdb_options_t* db_options = rocksdb_options_create();
971 rocksdb_options_set_create_if_missing(db_options, 1);
972 db = rocksdb_open(db_options, dbname, &err);
973 CheckNoError(err)
974 rocksdb_column_family_handle_t* cfh;
975 cfh = rocksdb_create_column_family(db, db_options, "cf1", &err);
976 rocksdb_column_family_handle_destroy(cfh);
977 CheckNoError(err);
978 rocksdb_close(db);
979
980 size_t cflen;
981 char** column_fams = rocksdb_list_column_families(db_options, dbname, &cflen, &err);
982 CheckNoError(err);
983 CheckEqual("default", column_fams[0], 7);
984 CheckEqual("cf1", column_fams[1], 3);
985 CheckCondition(cflen == 2);
986 rocksdb_list_column_families_destroy(column_fams, cflen);
987
988 rocksdb_options_t* cf_options = rocksdb_options_create();
989
990 const char* cf_names[2] = {"default", "cf1"};
991 const rocksdb_options_t* cf_opts[2] = {cf_options, cf_options};
992 rocksdb_column_family_handle_t* handles[2];
993 db = rocksdb_open_column_families(db_options, dbname, 2, cf_names, cf_opts, handles, &err);
994 CheckNoError(err);
995
996 rocksdb_put_cf(db, woptions, handles[1], "foo", 3, "hello", 5, &err);
997 CheckNoError(err);
998
999 CheckGetCF(db, roptions, handles[1], "foo", "hello");
1000
1001 rocksdb_delete_cf(db, woptions, handles[1], "foo", 3, &err);
1002 CheckNoError(err);
1003
1004 CheckGetCF(db, roptions, handles[1], "foo", NULL);
1005
1006 rocksdb_writebatch_t* wb = rocksdb_writebatch_create();
1007 rocksdb_writebatch_put_cf(wb, handles[1], "baz", 3, "a", 1);
1008 rocksdb_writebatch_clear(wb);
1009 rocksdb_writebatch_put_cf(wb, handles[1], "bar", 3, "b", 1);
1010 rocksdb_writebatch_put_cf(wb, handles[1], "box", 3, "c", 1);
1011 rocksdb_writebatch_delete_cf(wb, handles[1], "bar", 3);
1012 rocksdb_write(db, woptions, wb, &err);
1013 CheckNoError(err);
1014 CheckGetCF(db, roptions, handles[1], "baz", NULL);
1015 CheckGetCF(db, roptions, handles[1], "bar", NULL);
1016 CheckGetCF(db, roptions, handles[1], "box", "c");
1017 rocksdb_writebatch_destroy(wb);
1018
1019 const char* keys[3] = { "box", "box", "barfooxx" };
1020 const rocksdb_column_family_handle_t* get_handles[3] = { handles[0], handles[1], handles[1] };
1021 const size_t keys_sizes[3] = { 3, 3, 8 };
1022 char* vals[3];
1023 size_t vals_sizes[3];
1024 char* errs[3];
1025 rocksdb_multi_get_cf(db, roptions, get_handles, 3, keys, keys_sizes, vals, vals_sizes, errs);
1026
1027 int i;
1028 for (i = 0; i < 3; i++) {
1029 CheckEqual(NULL, errs[i], 0);
1030 switch (i) {
1031 case 0:
1032 CheckEqual(NULL, vals[i], vals_sizes[i]); // wrong cf
1033 break;
1034 case 1:
1035 CheckEqual("c", vals[i], vals_sizes[i]); // bingo
1036 break;
1037 case 2:
1038 CheckEqual(NULL, vals[i], vals_sizes[i]); // normal not found
1039 break;
1040 }
1041 Free(&vals[i]);
1042 }
1043
1044 rocksdb_iterator_t* iter = rocksdb_create_iterator_cf(db, roptions, handles[1]);
1045 CheckCondition(!rocksdb_iter_valid(iter));
1046 rocksdb_iter_seek_to_first(iter);
1047 CheckCondition(rocksdb_iter_valid(iter));
1048
1049 for (i = 0; rocksdb_iter_valid(iter) != 0; rocksdb_iter_next(iter)) {
1050 i++;
1051 }
1052 CheckCondition(i == 1);
1053 rocksdb_iter_get_error(iter, &err);
1054 CheckNoError(err);
1055 rocksdb_iter_destroy(iter);
1056
1057 rocksdb_column_family_handle_t* iters_cf_handles[2] = { handles[0], handles[1] };
1058 rocksdb_iterator_t* iters_handles[2];
1059 rocksdb_create_iterators(db, roptions, iters_cf_handles, iters_handles, 2, &err);
1060 CheckNoError(err);
1061
1062 iter = iters_handles[0];
1063 CheckCondition(!rocksdb_iter_valid(iter));
1064 rocksdb_iter_seek_to_first(iter);
1065 CheckCondition(!rocksdb_iter_valid(iter));
1066 rocksdb_iter_destroy(iter);
1067
1068 iter = iters_handles[1];
1069 CheckCondition(!rocksdb_iter_valid(iter));
1070 rocksdb_iter_seek_to_first(iter);
1071 CheckCondition(rocksdb_iter_valid(iter));
1072
1073 for (i = 0; rocksdb_iter_valid(iter) != 0; rocksdb_iter_next(iter)) {
1074 i++;
1075 }
1076 CheckCondition(i == 1);
1077 rocksdb_iter_get_error(iter, &err);
1078 CheckNoError(err);
1079 rocksdb_iter_destroy(iter);
1080
1081 rocksdb_drop_column_family(db, handles[1], &err);
1082 CheckNoError(err);
1083 for (i = 0; i < 2; i++) {
1084 rocksdb_column_family_handle_destroy(handles[i]);
1085 }
1086 rocksdb_close(db);
1087 rocksdb_destroy_db(options, dbname, &err);
1088 rocksdb_options_destroy(db_options);
1089 rocksdb_options_destroy(cf_options);
1090 }
1091
1092 StartPhase("prefix");
1093 {
1094 // Create new database
1095 rocksdb_options_set_allow_mmap_reads(options, 1);
1096 rocksdb_options_set_prefix_extractor(options, rocksdb_slicetransform_create_fixed_prefix(3));
1097 rocksdb_options_set_hash_skip_list_rep(options, 5000, 4, 4);
1098 rocksdb_options_set_plain_table_factory(options, 4, 10, 0.75, 16);
1099 rocksdb_options_set_allow_concurrent_memtable_write(options, 0);
1100
1101 db = rocksdb_open(options, dbname, &err);
1102 CheckNoError(err);
1103
1104 rocksdb_put(db, woptions, "foo1", 4, "foo", 3, &err);
1105 CheckNoError(err);
1106 rocksdb_put(db, woptions, "foo2", 4, "foo", 3, &err);
1107 CheckNoError(err);
1108 rocksdb_put(db, woptions, "foo3", 4, "foo", 3, &err);
1109 CheckNoError(err);
1110 rocksdb_put(db, woptions, "bar1", 4, "bar", 3, &err);
1111 CheckNoError(err);
1112 rocksdb_put(db, woptions, "bar2", 4, "bar", 3, &err);
1113 CheckNoError(err);
1114 rocksdb_put(db, woptions, "bar3", 4, "bar", 3, &err);
1115 CheckNoError(err);
1116
1117 rocksdb_iterator_t* iter = rocksdb_create_iterator(db, roptions);
1118 CheckCondition(!rocksdb_iter_valid(iter));
1119
1120 rocksdb_iter_seek(iter, "bar", 3);
1121 rocksdb_iter_get_error(iter, &err);
1122 CheckNoError(err);
1123 CheckCondition(rocksdb_iter_valid(iter));
1124
1125 CheckIter(iter, "bar1", "bar");
1126 rocksdb_iter_next(iter);
1127 CheckIter(iter, "bar2", "bar");
1128 rocksdb_iter_next(iter);
1129 CheckIter(iter, "bar3", "bar");
1130 rocksdb_iter_get_error(iter, &err);
1131 CheckNoError(err);
1132 rocksdb_iter_destroy(iter);
1133
1134 rocksdb_readoptions_set_total_order_seek(roptions, 1);
1135 iter = rocksdb_create_iterator(db, roptions);
1136 CheckCondition(!rocksdb_iter_valid(iter));
1137
1138 rocksdb_iter_seek(iter, "ba", 2);
1139 rocksdb_iter_get_error(iter, &err);
1140 CheckNoError(err);
1141 CheckCondition(rocksdb_iter_valid(iter));
1142 CheckIter(iter, "bar1", "bar");
1143
1144 rocksdb_iter_destroy(iter);
1145 rocksdb_readoptions_set_total_order_seek(roptions, 0);
1146
1147 rocksdb_close(db);
1148 rocksdb_destroy_db(options, dbname, &err);
1149 }
1150
1151 StartPhase("cuckoo_options");
1152 {
1153 rocksdb_cuckoo_table_options_t* cuckoo_options;
1154 cuckoo_options = rocksdb_cuckoo_options_create();
1155 rocksdb_cuckoo_options_set_hash_ratio(cuckoo_options, 0.5);
1156 rocksdb_cuckoo_options_set_max_search_depth(cuckoo_options, 200);
1157 rocksdb_cuckoo_options_set_cuckoo_block_size(cuckoo_options, 10);
1158 rocksdb_cuckoo_options_set_identity_as_first_hash(cuckoo_options, 1);
1159 rocksdb_cuckoo_options_set_use_module_hash(cuckoo_options, 0);
1160 rocksdb_options_set_cuckoo_table_factory(options, cuckoo_options);
1161
1162 db = rocksdb_open(options, dbname, &err);
1163 CheckNoError(err);
1164
1165 rocksdb_cuckoo_options_destroy(cuckoo_options);
1166 }
1167
1168 StartPhase("iterate_upper_bound");
1169 {
1170 // Create new empty database
1171 rocksdb_close(db);
1172 rocksdb_destroy_db(options, dbname, &err);
1173 CheckNoError(err);
1174
1175 rocksdb_options_set_prefix_extractor(options, NULL);
1176 db = rocksdb_open(options, dbname, &err);
1177 CheckNoError(err);
1178
1179 rocksdb_put(db, woptions, "a", 1, "0", 1, &err); CheckNoError(err);
1180 rocksdb_put(db, woptions, "foo", 3, "bar", 3, &err); CheckNoError(err);
1181 rocksdb_put(db, woptions, "foo1", 4, "bar1", 4, &err); CheckNoError(err);
1182 rocksdb_put(db, woptions, "g1", 2, "0", 1, &err); CheckNoError(err);
1183
1184 // testing basic case with no iterate_upper_bound and no prefix_extractor
1185 {
1186 rocksdb_readoptions_set_iterate_upper_bound(roptions, NULL, 0);
1187 rocksdb_iterator_t* iter = rocksdb_create_iterator(db, roptions);
1188
1189 rocksdb_iter_seek(iter, "foo", 3);
1190 CheckCondition(rocksdb_iter_valid(iter));
1191 CheckIter(iter, "foo", "bar");
1192
1193 rocksdb_iter_next(iter);
1194 CheckCondition(rocksdb_iter_valid(iter));
1195 CheckIter(iter, "foo1", "bar1");
1196
1197 rocksdb_iter_next(iter);
1198 CheckCondition(rocksdb_iter_valid(iter));
1199 CheckIter(iter, "g1", "0");
1200
1201 rocksdb_iter_destroy(iter);
1202 }
1203
1204 // testing iterate_upper_bound and forward iterator
1205 // to make sure it stops at bound
1206 {
1207 // iterate_upper_bound points beyond the last expected entry
1208 rocksdb_readoptions_set_iterate_upper_bound(roptions, "foo2", 4);
1209
1210 rocksdb_iterator_t* iter = rocksdb_create_iterator(db, roptions);
1211
1212 rocksdb_iter_seek(iter, "foo", 3);
1213 CheckCondition(rocksdb_iter_valid(iter));
1214 CheckIter(iter, "foo", "bar");
1215
1216 rocksdb_iter_next(iter);
1217 CheckCondition(rocksdb_iter_valid(iter));
1218 CheckIter(iter, "foo1", "bar1");
1219
1220 rocksdb_iter_next(iter);
1221 // should stop here...
1222 CheckCondition(!rocksdb_iter_valid(iter));
1223
1224 rocksdb_iter_destroy(iter);
1225 }
1226 }
1227
1228 // Simple sanity check that setting memtable rep works.
1229 StartPhase("memtable_reps");
1230 {
1231 // Create database with vector memtable.
1232 rocksdb_close(db);
1233 rocksdb_destroy_db(options, dbname, &err);
1234 CheckNoError(err);
1235
1236 rocksdb_options_set_memtable_vector_rep(options);
1237 db = rocksdb_open(options, dbname, &err);
1238 CheckNoError(err);
1239
1240 // Create database with hash skiplist memtable.
1241 rocksdb_close(db);
1242 rocksdb_destroy_db(options, dbname, &err);
1243 CheckNoError(err);
1244
1245 rocksdb_options_set_hash_skip_list_rep(options, 5000, 4, 4);
1246 db = rocksdb_open(options, dbname, &err);
1247 CheckNoError(err);
1248 }
1249
1250 StartPhase("cleanup");
1251 rocksdb_close(db);
1252 rocksdb_options_destroy(options);
1253 rocksdb_block_based_options_destroy(table_options);
1254 rocksdb_readoptions_destroy(roptions);
1255 rocksdb_writeoptions_destroy(woptions);
1256 rocksdb_compactoptions_destroy(coptions);
1257 rocksdb_cache_destroy(cache);
1258 rocksdb_comparator_destroy(cmp);
1259 rocksdb_env_destroy(env);
1260
1261 fprintf(stderr, "PASS\n");
1262 return 0;
1263 }
1264
1265 #else
1266
1267 int main() {
1268 fprintf(stderr, "SKIPPED\n");
1269 return 0;
1270 }
1271
1272 #endif // !ROCKSDB_LITE