]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | |
11fdf7f2 | 22 | #include <windows.h> |
7c673cae FG |
23 | |
24 | // Ok for uniqueness | |
25 | int geteuid() { | |
26 | int result = 0; | |
27 | ||
28 | result = ((int)GetCurrentProcessId() << 16); | |
29 | result |= (int)GetCurrentThreadId(); | |
30 | ||
31 | return result; | |
32 | } | |
33 | ||
11fdf7f2 TL |
34 | // VS < 2015 |
35 | #if defined(_MSC_VER) && (_MSC_VER < 1900) | |
36 | #define snprintf _snprintf | |
37 | #endif | |
38 | ||
7c673cae FG |
39 | #endif |
40 | ||
41 | const char* phase = ""; | |
42 | static char dbname[200]; | |
43 | static char sstfilename[200]; | |
44 | static char dbbackupname[200]; | |
11fdf7f2 TL |
45 | static char dbcheckpointname[200]; |
46 | static char dbpathname[200]; | |
7c673cae FG |
47 | |
48 | static void StartPhase(const char* name) { | |
49 | fprintf(stderr, "=== Test %s\n", name); | |
50 | phase = name; | |
51 | } | |
11fdf7f2 TL |
52 | #ifdef _MSC_VER |
53 | #pragma warning(push) | |
54 | #pragma warning (disable: 4996) // getenv security warning | |
55 | #endif | |
7c673cae FG |
56 | static const char* GetTempDir(void) { |
57 | const char* ret = getenv("TEST_TMPDIR"); | |
58 | if (ret == NULL || ret[0] == '\0') | |
59 | ret = "/tmp"; | |
60 | return ret; | |
61 | } | |
11fdf7f2 TL |
62 | #ifdef _MSC_VER |
63 | #pragma warning(pop) | |
64 | #endif | |
7c673cae FG |
65 | |
66 | #define CheckNoError(err) \ | |
67 | if ((err) != NULL) { \ | |
68 | fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, (err)); \ | |
69 | abort(); \ | |
70 | } | |
71 | ||
72 | #define CheckCondition(cond) \ | |
73 | if (!(cond)) { \ | |
74 | fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, #cond); \ | |
75 | abort(); \ | |
76 | } | |
77 | ||
78 | static void CheckEqual(const char* expected, const char* v, size_t n) { | |
79 | if (expected == NULL && v == NULL) { | |
80 | // ok | |
81 | } else if (expected != NULL && v != NULL && n == strlen(expected) && | |
82 | memcmp(expected, v, n) == 0) { | |
83 | // ok | |
84 | return; | |
85 | } else { | |
86 | fprintf(stderr, "%s: expected '%s', got '%s'\n", | |
87 | phase, | |
88 | (expected ? expected : "(null)"), | |
89 | (v ? v : "(null")); | |
90 | abort(); | |
91 | } | |
92 | } | |
93 | ||
94 | static void Free(char** ptr) { | |
95 | if (*ptr) { | |
96 | free(*ptr); | |
97 | *ptr = NULL; | |
98 | } | |
99 | } | |
100 | ||
101 | static void CheckValue( | |
102 | char* err, | |
103 | const char* expected, | |
104 | char** actual, | |
105 | size_t actual_length) { | |
106 | CheckNoError(err); | |
107 | CheckEqual(expected, *actual, actual_length); | |
108 | Free(actual); | |
109 | } | |
110 | ||
111 | static void CheckGet( | |
112 | rocksdb_t* db, | |
113 | const rocksdb_readoptions_t* options, | |
114 | const char* key, | |
115 | const char* expected) { | |
116 | char* err = NULL; | |
117 | size_t val_len; | |
118 | char* val; | |
119 | val = rocksdb_get(db, options, key, strlen(key), &val_len, &err); | |
120 | CheckNoError(err); | |
121 | CheckEqual(expected, val, val_len); | |
122 | Free(&val); | |
123 | } | |
124 | ||
125 | static void CheckGetCF( | |
126 | rocksdb_t* db, | |
127 | const rocksdb_readoptions_t* options, | |
128 | rocksdb_column_family_handle_t* handle, | |
129 | const char* key, | |
130 | const char* expected) { | |
131 | char* err = NULL; | |
132 | size_t val_len; | |
133 | char* val; | |
134 | val = rocksdb_get_cf(db, options, handle, key, strlen(key), &val_len, &err); | |
135 | CheckNoError(err); | |
136 | CheckEqual(expected, val, val_len); | |
137 | Free(&val); | |
138 | } | |
139 | ||
11fdf7f2 TL |
140 | static void CheckPinGet(rocksdb_t* db, const rocksdb_readoptions_t* options, |
141 | const char* key, const char* expected) { | |
142 | char* err = NULL; | |
143 | size_t val_len; | |
144 | const char* val; | |
145 | rocksdb_pinnableslice_t* p; | |
146 | p = rocksdb_get_pinned(db, options, key, strlen(key), &err); | |
147 | CheckNoError(err); | |
148 | val = rocksdb_pinnableslice_value(p, &val_len); | |
149 | CheckEqual(expected, val, val_len); | |
150 | rocksdb_pinnableslice_destroy(p); | |
151 | } | |
152 | ||
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) { | |
156 | char* err = NULL; | |
157 | size_t val_len; | |
158 | const char* val; | |
159 | rocksdb_pinnableslice_t* p; | |
160 | p = rocksdb_get_pinned_cf(db, options, handle, key, strlen(key), &err); | |
161 | CheckNoError(err); | |
162 | val = rocksdb_pinnableslice_value(p, &val_len); | |
163 | CheckEqual(expected, val, val_len); | |
164 | rocksdb_pinnableslice_destroy(p); | |
165 | } | |
7c673cae FG |
166 | |
167 | static void CheckIter(rocksdb_iterator_t* iter, | |
168 | const char* key, const char* val) { | |
169 | size_t len; | |
170 | const char* str; | |
171 | str = rocksdb_iter_key(iter, &len); | |
172 | CheckEqual(key, str, len); | |
173 | str = rocksdb_iter_value(iter, &len); | |
174 | CheckEqual(val, str, len); | |
175 | } | |
176 | ||
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); | |
183 | switch (*state) { | |
184 | case 0: | |
185 | CheckEqual("bar", k, klen); | |
186 | CheckEqual("b", v, vlen); | |
187 | break; | |
188 | case 1: | |
189 | CheckEqual("box", k, klen); | |
190 | CheckEqual("c", v, vlen); | |
191 | break; | |
192 | } | |
193 | (*state)++; | |
194 | } | |
195 | ||
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); | |
201 | (*state)++; | |
202 | } | |
203 | ||
11fdf7f2 | 204 | static void CmpDestroy(void* arg) { (void)arg; } |
7c673cae FG |
205 | |
206 | static int CmpCompare(void* arg, const char* a, size_t alen, | |
207 | const char* b, size_t blen) { | |
11fdf7f2 | 208 | (void)arg; |
7c673cae FG |
209 | size_t n = (alen < blen) ? alen : blen; |
210 | int r = memcmp(a, b, n); | |
211 | if (r == 0) { | |
212 | if (alen < blen) r = -1; | |
213 | else if (alen > blen) r = +1; | |
214 | } | |
215 | return r; | |
216 | } | |
217 | ||
218 | static const char* CmpName(void* arg) { | |
11fdf7f2 | 219 | (void)arg; |
7c673cae FG |
220 | return "foo"; |
221 | } | |
222 | ||
223 | // Custom filter policy | |
224 | static unsigned char fake_filter_result = 1; | |
11fdf7f2 | 225 | static void FilterDestroy(void* arg) { (void)arg; } |
7c673cae | 226 | static const char* FilterName(void* arg) { |
11fdf7f2 | 227 | (void)arg; |
7c673cae FG |
228 | return "TestFilter"; |
229 | } | |
230 | static char* FilterCreate( | |
231 | void* arg, | |
232 | const char* const* key_array, const size_t* key_length_array, | |
233 | int num_keys, | |
234 | size_t* filter_length) { | |
11fdf7f2 TL |
235 | (void)arg; |
236 | (void)key_array; | |
237 | (void)key_length_array; | |
238 | (void)num_keys; | |
7c673cae FG |
239 | *filter_length = 4; |
240 | char* result = malloc(4); | |
241 | memcpy(result, "fake", 4); | |
242 | return result; | |
243 | } | |
244 | static unsigned char FilterKeyMatch( | |
245 | void* arg, | |
246 | const char* key, size_t length, | |
247 | const char* filter, size_t filter_length) { | |
11fdf7f2 TL |
248 | (void)arg; |
249 | (void)key; | |
250 | (void)length; | |
7c673cae FG |
251 | CheckCondition(filter_length == 4); |
252 | CheckCondition(memcmp(filter, "fake", 4) == 0); | |
253 | return fake_filter_result; | |
254 | } | |
255 | ||
256 | // Custom compaction filter | |
11fdf7f2 TL |
257 | static void CFilterDestroy(void* arg) { (void)arg; } |
258 | static const char* CFilterName(void* arg) { | |
259 | (void)arg; | |
260 | return "foo"; | |
261 | } | |
7c673cae FG |
262 | static unsigned char CFilterFilter(void* arg, int level, const char* key, |
263 | size_t key_length, | |
264 | const char* existing_value, | |
265 | size_t value_length, char** new_value, | |
266 | size_t* new_value_length, | |
267 | unsigned char* value_changed) { | |
11fdf7f2 TL |
268 | (void)arg; |
269 | (void)level; | |
270 | (void)existing_value; | |
271 | (void)value_length; | |
7c673cae FG |
272 | if (key_length == 3) { |
273 | if (memcmp(key, "bar", key_length) == 0) { | |
274 | return 1; | |
275 | } else if (memcmp(key, "baz", key_length) == 0) { | |
276 | *value_changed = 1; | |
277 | *new_value = "newbazvalue"; | |
278 | *new_value_length = 11; | |
279 | return 0; | |
280 | } | |
281 | } | |
282 | return 0; | |
283 | } | |
284 | ||
11fdf7f2 TL |
285 | static void CFilterFactoryDestroy(void* arg) { (void)arg; } |
286 | static const char* CFilterFactoryName(void* arg) { | |
287 | (void)arg; | |
288 | return "foo"; | |
289 | } | |
7c673cae FG |
290 | static rocksdb_compactionfilter_t* CFilterCreate( |
291 | void* arg, rocksdb_compactionfiltercontext_t* context) { | |
11fdf7f2 TL |
292 | (void)arg; |
293 | (void)context; | |
7c673cae FG |
294 | return rocksdb_compactionfilter_create(NULL, CFilterDestroy, CFilterFilter, |
295 | CFilterName); | |
296 | } | |
297 | ||
298 | static rocksdb_t* CheckCompaction(rocksdb_t* db, rocksdb_options_t* options, | |
299 | rocksdb_readoptions_t* roptions, | |
300 | rocksdb_writeoptions_t* woptions) { | |
301 | char* err = NULL; | |
302 | db = rocksdb_open(options, dbname, &err); | |
303 | CheckNoError(err); | |
304 | rocksdb_put(db, woptions, "foo", 3, "foovalue", 8, &err); | |
305 | CheckNoError(err); | |
306 | CheckGet(db, roptions, "foo", "foovalue"); | |
307 | rocksdb_put(db, woptions, "bar", 3, "barvalue", 8, &err); | |
308 | CheckNoError(err); | |
309 | CheckGet(db, roptions, "bar", "barvalue"); | |
310 | rocksdb_put(db, woptions, "baz", 3, "bazvalue", 8, &err); | |
311 | CheckNoError(err); | |
312 | CheckGet(db, roptions, "baz", "bazvalue"); | |
313 | ||
314 | // Force compaction | |
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"); | |
320 | return db; | |
321 | } | |
322 | ||
323 | // Custom merge operator | |
11fdf7f2 | 324 | static void MergeOperatorDestroy(void* arg) { (void)arg; } |
7c673cae | 325 | static const char* MergeOperatorName(void* arg) { |
11fdf7f2 | 326 | (void)arg; |
7c673cae FG |
327 | return "TestMergeOperator"; |
328 | } | |
329 | static char* MergeOperatorFullMerge( | |
330 | void* arg, | |
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, | |
334 | int num_operands, | |
335 | unsigned char* success, size_t* new_value_length) { | |
11fdf7f2 TL |
336 | (void)arg; |
337 | (void)key; | |
338 | (void)key_length; | |
339 | (void)existing_value; | |
340 | (void)existing_value_length; | |
341 | (void)operands_list; | |
342 | (void)operands_list_length; | |
343 | (void)num_operands; | |
7c673cae FG |
344 | *new_value_length = 4; |
345 | *success = 1; | |
346 | char* result = malloc(4); | |
347 | memcpy(result, "fake", 4); | |
348 | return result; | |
349 | } | |
350 | static char* MergeOperatorPartialMerge( | |
351 | void* arg, | |
352 | const char* key, size_t key_length, | |
353 | const char* const* operands_list, const size_t* operands_list_length, | |
354 | int num_operands, | |
355 | unsigned char* success, size_t* new_value_length) { | |
11fdf7f2 TL |
356 | (void)arg; |
357 | (void)key; | |
358 | (void)key_length; | |
359 | (void)operands_list; | |
360 | (void)operands_list_length; | |
361 | (void)num_operands; | |
7c673cae FG |
362 | *new_value_length = 4; |
363 | *success = 1; | |
364 | char* result = malloc(4); | |
365 | memcpy(result, "fake", 4); | |
366 | return result; | |
367 | } | |
368 | ||
11fdf7f2 TL |
369 | static void CheckTxnGet( |
370 | rocksdb_transaction_t* txn, | |
371 | const rocksdb_readoptions_t* options, | |
372 | const char* key, | |
373 | const char* expected) { | |
374 | char* err = NULL; | |
375 | size_t val_len; | |
376 | char* val; | |
377 | val = rocksdb_transaction_get(txn, options, key, strlen(key), &val_len, &err); | |
378 | CheckNoError(err); | |
379 | CheckEqual(expected, val, val_len); | |
380 | Free(&val); | |
381 | } | |
382 | ||
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) { | |
387 | char* err = NULL; | |
388 | size_t val_len; | |
389 | char* val; | |
390 | val = rocksdb_transaction_get_cf(txn, options, column_family, key, | |
391 | strlen(key), &val_len, &err); | |
392 | CheckNoError(err); | |
393 | CheckEqual(expected, val, val_len); | |
394 | Free(&val); | |
395 | } | |
396 | ||
397 | static void CheckTxnDBGet( | |
398 | rocksdb_transactiondb_t* txn_db, | |
399 | const rocksdb_readoptions_t* options, | |
400 | const char* key, | |
401 | const char* expected) { | |
402 | char* err = NULL; | |
403 | size_t val_len; | |
404 | char* val; | |
405 | val = rocksdb_transactiondb_get(txn_db, options, key, strlen(key), &val_len, &err); | |
406 | CheckNoError(err); | |
407 | CheckEqual(expected, val, val_len); | |
408 | Free(&val); | |
409 | } | |
410 | ||
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) { | |
415 | char* err = NULL; | |
416 | size_t val_len; | |
417 | char* val; | |
418 | val = rocksdb_transactiondb_get_cf(txn_db, options, column_family, key, | |
419 | strlen(key), &val_len, &err); | |
420 | CheckNoError(err); | |
421 | CheckEqual(expected, val, val_len); | |
422 | Free(&val); | |
423 | } | |
424 | ||
7c673cae | 425 | int main(int argc, char** argv) { |
11fdf7f2 TL |
426 | (void)argc; |
427 | (void)argv; | |
7c673cae FG |
428 | rocksdb_t* db; |
429 | rocksdb_comparator_t* cmp; | |
430 | rocksdb_cache_t* cache; | |
11fdf7f2 | 431 | rocksdb_dbpath_t *dbpath; |
7c673cae FG |
432 | rocksdb_env_t* env; |
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; | |
11fdf7f2 TL |
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; | |
7c673cae FG |
445 | char* err = NULL; |
446 | int run = -1; | |
447 | ||
448 | snprintf(dbname, sizeof(dbname), | |
449 | "%s/rocksdb_c_test-%d", | |
450 | GetTempDir(), | |
451 | ((int) geteuid())); | |
452 | ||
453 | snprintf(dbbackupname, sizeof(dbbackupname), | |
454 | "%s/rocksdb_c_test-%d-backup", | |
455 | GetTempDir(), | |
456 | ((int) geteuid())); | |
457 | ||
11fdf7f2 TL |
458 | snprintf(dbcheckpointname, sizeof(dbcheckpointname), |
459 | "%s/rocksdb_c_test-%d-checkpoint", | |
460 | GetTempDir(), | |
461 | ((int) geteuid())); | |
462 | ||
7c673cae FG |
463 | snprintf(sstfilename, sizeof(sstfilename), |
464 | "%s/rocksdb_c_test-%d-sst", | |
465 | GetTempDir(), | |
466 | ((int)geteuid())); | |
467 | ||
11fdf7f2 TL |
468 | snprintf(dbpathname, sizeof(dbpathname), |
469 | "%s/rocksdb_c_test-%d-dbpath", | |
470 | GetTempDir(), | |
471 | ((int) geteuid())); | |
472 | ||
7c673cae FG |
473 | StartPhase("create_objects"); |
474 | cmp = rocksdb_comparator_create(NULL, CmpDestroy, CmpCompare, CmpName); | |
11fdf7f2 | 475 | dbpath = rocksdb_dbpath_create(dbpathname, 1024 * 1024); |
7c673cae FG |
476 | env = rocksdb_create_default_env(); |
477 | cache = rocksdb_cache_create_lru(100000); | |
478 | ||
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); | |
491 | ||
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); | |
500 | ||
501 | roptions = rocksdb_readoptions_create(); | |
502 | rocksdb_readoptions_set_verify_checksums(roptions, 1); | |
503 | rocksdb_readoptions_set_fill_cache(roptions, 1); | |
504 | ||
505 | woptions = rocksdb_writeoptions_create(); | |
506 | rocksdb_writeoptions_set_sync(woptions, 1); | |
507 | ||
508 | coptions = rocksdb_compactoptions_create(); | |
509 | rocksdb_compactoptions_set_exclusive_manual_compaction(coptions, 1); | |
510 | ||
511 | StartPhase("destroy"); | |
512 | rocksdb_destroy_db(options, dbname, &err); | |
513 | Free(&err); | |
514 | ||
515 | StartPhase("open_error"); | |
516 | rocksdb_open(options, dbname, &err); | |
517 | CheckCondition(err != NULL); | |
518 | Free(&err); | |
519 | ||
520 | StartPhase("open"); | |
521 | rocksdb_options_set_create_if_missing(options, 1); | |
522 | db = rocksdb_open(options, dbname, &err); | |
523 | CheckNoError(err); | |
524 | CheckGet(db, roptions, "foo", NULL); | |
525 | ||
526 | StartPhase("put"); | |
527 | rocksdb_put(db, woptions, "foo", 3, "hello", 5, &err); | |
528 | CheckNoError(err); | |
529 | CheckGet(db, roptions, "foo", "hello"); | |
530 | ||
531 | StartPhase("backup_and_restore"); | |
532 | { | |
533 | rocksdb_destroy_db(options, dbbackupname, &err); | |
534 | CheckNoError(err); | |
535 | ||
536 | rocksdb_backup_engine_t *be = rocksdb_backup_engine_open(options, dbbackupname, &err); | |
537 | CheckNoError(err); | |
538 | ||
539 | rocksdb_backup_engine_create_new_backup(be, db, &err); | |
540 | CheckNoError(err); | |
541 | ||
542 | // need a change to trigger a new backup | |
543 | rocksdb_delete(db, woptions, "does-not-exist", 14, &err); | |
544 | CheckNoError(err); | |
545 | ||
546 | rocksdb_backup_engine_create_new_backup(be, db, &err); | |
547 | CheckNoError(err); | |
548 | ||
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); | |
552 | ||
553 | rocksdb_backup_engine_purge_old_backups(be, 1, &err); | |
554 | CheckNoError(err); | |
555 | ||
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); | |
559 | ||
560 | rocksdb_delete(db, woptions, "foo", 3, &err); | |
561 | CheckNoError(err); | |
562 | ||
563 | rocksdb_close(db); | |
564 | ||
565 | rocksdb_destroy_db(options, dbname, &err); | |
566 | CheckNoError(err); | |
567 | ||
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); | |
571 | CheckNoError(err); | |
572 | rocksdb_restore_options_destroy(restore_options); | |
573 | ||
574 | rocksdb_options_set_error_if_exists(options, 0); | |
575 | db = rocksdb_open(options, dbname, &err); | |
576 | CheckNoError(err); | |
577 | rocksdb_options_set_error_if_exists(options, 1); | |
578 | ||
579 | CheckGet(db, roptions, "foo", "hello"); | |
580 | ||
581 | rocksdb_backup_engine_close(be); | |
582 | } | |
583 | ||
11fdf7f2 TL |
584 | StartPhase("checkpoint"); |
585 | { | |
586 | rocksdb_destroy_db(options, dbcheckpointname, &err); | |
587 | CheckNoError(err); | |
588 | ||
589 | rocksdb_checkpoint_t* checkpoint = rocksdb_checkpoint_object_create(db, &err); | |
590 | CheckNoError(err); | |
591 | ||
592 | rocksdb_checkpoint_create(checkpoint, dbcheckpointname, 0, &err); | |
593 | CheckNoError(err); | |
594 | ||
595 | // start a new database from the checkpoint | |
596 | rocksdb_close(db); | |
597 | rocksdb_options_set_error_if_exists(options, 0); | |
598 | db = rocksdb_open(options, dbcheckpointname, &err); | |
599 | CheckNoError(err); | |
600 | ||
601 | CheckGet(db, roptions, "foo", "hello"); | |
602 | ||
603 | rocksdb_checkpoint_object_destroy(checkpoint); | |
604 | ||
605 | rocksdb_close(db); | |
606 | rocksdb_destroy_db(options, dbcheckpointname, &err); | |
607 | CheckNoError(err); | |
608 | ||
609 | db = rocksdb_open(options, dbname, &err); | |
610 | CheckNoError(err); | |
611 | rocksdb_options_set_error_if_exists(options, 1); | |
612 | } | |
613 | ||
7c673cae FG |
614 | StartPhase("compactall"); |
615 | rocksdb_compact_range(db, NULL, 0, NULL, 0); | |
616 | CheckGet(db, roptions, "foo", "hello"); | |
617 | ||
618 | StartPhase("compactrange"); | |
619 | rocksdb_compact_range(db, "a", 1, "z", 1); | |
620 | CheckGet(db, roptions, "foo", "hello"); | |
621 | ||
622 | StartPhase("compactallopt"); | |
623 | rocksdb_compact_range_opt(db, coptions, NULL, 0, NULL, 0); | |
624 | CheckGet(db, roptions, "foo", "hello"); | |
625 | ||
626 | StartPhase("compactrangeopt"); | |
627 | rocksdb_compact_range_opt(db, coptions, "a", 1, "z", 1); | |
628 | CheckGet(db, roptions, "foo", "hello"); | |
629 | ||
630 | // Simple check cache usage | |
631 | StartPhase("cache_usage"); | |
632 | { | |
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); | |
636 | ||
637 | size_t usage = rocksdb_cache_get_usage(cache); | |
638 | CheckCondition(usage > 0); | |
639 | ||
640 | size_t pin_usage = rocksdb_cache_get_pinned_usage(cache); | |
641 | CheckCondition(pin_usage > 0); | |
642 | ||
643 | rocksdb_iter_next(iter); | |
644 | rocksdb_iter_destroy(iter); | |
645 | rocksdb_readoptions_set_pin_data(roptions, 0); | |
646 | } | |
647 | ||
648 | StartPhase("addfile"); | |
649 | { | |
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); | |
654 | ||
11fdf7f2 | 655 | remove(sstfilename); |
7c673cae FG |
656 | rocksdb_sstfilewriter_open(writer, sstfilename, &err); |
657 | CheckNoError(err); | |
11fdf7f2 | 658 | rocksdb_sstfilewriter_put(writer, "sstk1", 5, "v1", 2, &err); |
7c673cae | 659 | CheckNoError(err); |
11fdf7f2 | 660 | rocksdb_sstfilewriter_put(writer, "sstk2", 5, "v2", 2, &err); |
7c673cae | 661 | CheckNoError(err); |
11fdf7f2 | 662 | rocksdb_sstfilewriter_put(writer, "sstk3", 5, "v3", 2, &err); |
7c673cae FG |
663 | CheckNoError(err); |
664 | rocksdb_sstfilewriter_finish(writer, &err); | |
665 | CheckNoError(err); | |
666 | ||
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); | |
671 | CheckNoError(err); | |
672 | CheckGet(db, roptions, "sstk1", "v1"); | |
673 | CheckGet(db, roptions, "sstk2", "v2"); | |
674 | CheckGet(db, roptions, "sstk3", "v3"); | |
675 | ||
11fdf7f2 | 676 | remove(sstfilename); |
7c673cae FG |
677 | rocksdb_sstfilewriter_open(writer, sstfilename, &err); |
678 | CheckNoError(err); | |
11fdf7f2 | 679 | rocksdb_sstfilewriter_put(writer, "sstk2", 5, "v4", 2, &err); |
7c673cae | 680 | CheckNoError(err); |
11fdf7f2 | 681 | rocksdb_sstfilewriter_put(writer, "sstk22", 6, "v5", 2, &err); |
7c673cae | 682 | CheckNoError(err); |
11fdf7f2 | 683 | rocksdb_sstfilewriter_put(writer, "sstk3", 5, "v6", 2, &err); |
7c673cae FG |
684 | CheckNoError(err); |
685 | rocksdb_sstfilewriter_finish(writer, &err); | |
686 | CheckNoError(err); | |
687 | ||
688 | rocksdb_ingest_external_file(db, file_list, 1, ing_opt, &err); | |
689 | CheckNoError(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"); | |
694 | ||
695 | rocksdb_ingestexternalfileoptions_destroy(ing_opt); | |
696 | rocksdb_sstfilewriter_destroy(writer); | |
697 | rocksdb_options_destroy(io_options); | |
698 | rocksdb_envoptions_destroy(env_opt); | |
699 | ||
700 | // Delete all keys we just ingested | |
701 | rocksdb_delete(db, woptions, "sstk1", 5, &err); | |
702 | CheckNoError(err); | |
703 | rocksdb_delete(db, woptions, "sstk2", 5, &err); | |
704 | CheckNoError(err); | |
705 | rocksdb_delete(db, woptions, "sstk22", 6, &err); | |
706 | CheckNoError(err); | |
707 | rocksdb_delete(db, woptions, "sstk3", 5, &err); | |
708 | CheckNoError(err); | |
709 | } | |
710 | ||
711 | StartPhase("writebatch"); | |
712 | { | |
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); | |
720 | CheckNoError(err); | |
721 | CheckGet(db, roptions, "foo", "hello"); | |
722 | CheckGet(db, roptions, "bar", NULL); | |
723 | CheckGet(db, roptions, "box", "c"); | |
724 | int pos = 0; | |
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); | |
732 | CheckNoError(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, | |
741 | end_sizes); | |
742 | rocksdb_write(db, woptions, wb, &err); | |
743 | CheckNoError(err); | |
744 | CheckGet(db, roptions, "bay", NULL); | |
745 | rocksdb_writebatch_destroy(wb); | |
746 | } | |
747 | ||
748 | StartPhase("writebatch_vectors"); | |
749 | { | |
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); | |
757 | CheckNoError(err); | |
758 | CheckGet(db, roptions, "zap", "xyz"); | |
759 | rocksdb_writebatch_delete(wb, "zap", 3); | |
760 | rocksdb_write(db, woptions, wb, &err); | |
761 | CheckNoError(err); | |
762 | CheckGet(db, roptions, "zap", NULL); | |
763 | rocksdb_writebatch_destroy(wb); | |
764 | } | |
765 | ||
766 | StartPhase("writebatch_savepoint"); | |
767 | { | |
768 | rocksdb_writebatch_t* wb = rocksdb_writebatch_create(); | |
769 | rocksdb_writebatch_set_save_point(wb); | |
11fdf7f2 | 770 | rocksdb_writebatch_set_save_point(wb); |
7c673cae FG |
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}; | |
11fdf7f2 TL |
775 | rocksdb_writebatch_pop_save_point(wb, &err); |
776 | CheckNoError(err); | |
7c673cae FG |
777 | rocksdb_writebatch_putv(wb, 2, k_list, k_sizes, 3, v_list, v_sizes); |
778 | rocksdb_writebatch_rollback_to_save_point(wb, &err); | |
779 | CheckNoError(err); | |
780 | rocksdb_write(db, woptions, wb, &err); | |
781 | CheckNoError(err); | |
782 | CheckGet(db, roptions, "zap", NULL); | |
783 | rocksdb_writebatch_destroy(wb); | |
784 | } | |
785 | ||
786 | StartPhase("writebatch_rep"); | |
787 | { | |
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); | |
792 | size_t repsize1 = 0; | |
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)); | |
797 | size_t repsize2 = 0; | |
798 | CheckCondition( | |
799 | memcmp(rep, rocksdb_writebatch_data(wb2, &repsize2), repsize1) == 0); | |
800 | rocksdb_writebatch_destroy(wb1); | |
801 | rocksdb_writebatch_destroy(wb2); | |
802 | } | |
803 | ||
804 | StartPhase("writebatch_wi"); | |
805 | { | |
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); | |
814 | size_t size; | |
815 | char* value; | |
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); | |
825 | CheckNoError(err); | |
826 | CheckGet(db, roptions, "foo", "hello"); | |
827 | CheckGet(db, roptions, "bar", NULL); | |
828 | CheckGet(db, roptions, "box", "c"); | |
829 | int pos = 0; | |
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); | |
837 | CheckNoError(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, | |
846 | end_sizes); | |
847 | rocksdb_write_writebatch_wi(db, woptions, wbi, &err); | |
848 | CheckNoError(err); | |
849 | CheckGet(db, roptions, "bay", NULL); | |
850 | rocksdb_writebatch_wi_destroy(wbi); | |
851 | } | |
852 | ||
853 | StartPhase("writebatch_wi_vectors"); | |
854 | { | |
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); | |
862 | CheckNoError(err); | |
863 | CheckGet(db, roptions, "zap", "xyz"); | |
864 | rocksdb_writebatch_wi_delete(wb, "zap", 3); | |
865 | rocksdb_write_writebatch_wi(db, woptions, wb, &err); | |
866 | CheckNoError(err); | |
867 | CheckGet(db, roptions, "zap", NULL); | |
868 | rocksdb_writebatch_wi_destroy(wb); | |
869 | } | |
870 | ||
871 | StartPhase("writebatch_wi_savepoint"); | |
872 | { | |
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); | |
881 | CheckNoError(err); | |
882 | rocksdb_write_writebatch_wi(db, woptions, wb, &err); | |
883 | CheckNoError(err); | |
884 | CheckGet(db, roptions, "zap", NULL); | |
885 | rocksdb_writebatch_wi_destroy(wb); | |
886 | } | |
887 | ||
888 | StartPhase("iter"); | |
889 | { | |
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); | |
910 | CheckNoError(err); | |
911 | rocksdb_iter_destroy(iter); | |
912 | } | |
913 | ||
914 | StartPhase("wbwi_iter"); | |
915 | { | |
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); | |
494da23a TL |
920 | rocksdb_iterator_t* iter = |
921 | rocksdb_writebatch_wi_create_iterator_with_base(wbi, base_iter); | |
7c673cae FG |
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); | |
941 | CheckNoError(err); | |
942 | rocksdb_iter_destroy(iter); | |
943 | rocksdb_writebatch_wi_destroy(wbi); | |
944 | } | |
945 | ||
946 | StartPhase("multiget"); | |
947 | { | |
948 | const char* keys[3] = { "box", "foo", "notfound" }; | |
949 | const size_t keys_sizes[3] = { 3, 3, 8 }; | |
950 | char* vals[3]; | |
951 | size_t vals_sizes[3]; | |
952 | char* errs[3]; | |
953 | rocksdb_multi_get(db, roptions, 3, keys, keys_sizes, vals, vals_sizes, errs); | |
954 | ||
955 | int i; | |
956 | for (i = 0; i < 3; i++) { | |
957 | CheckEqual(NULL, errs[i], 0); | |
958 | switch (i) { | |
959 | case 0: | |
960 | CheckEqual("c", vals[i], vals_sizes[i]); | |
961 | break; | |
962 | case 1: | |
963 | CheckEqual("hello", vals[i], vals_sizes[i]); | |
964 | break; | |
965 | case 2: | |
966 | CheckEqual(NULL, vals[i], vals_sizes[i]); | |
967 | break; | |
968 | } | |
969 | Free(&vals[i]); | |
970 | } | |
971 | } | |
972 | ||
11fdf7f2 TL |
973 | StartPhase("pin_get"); |
974 | { | |
975 | CheckPinGet(db, roptions, "box", "c"); | |
976 | CheckPinGet(db, roptions, "foo", "hello"); | |
977 | CheckPinGet(db, roptions, "notfound", NULL); | |
978 | } | |
979 | ||
7c673cae FG |
980 | StartPhase("approximate_sizes"); |
981 | { | |
982 | int i; | |
983 | int n = 20000; | |
984 | char keybuf[100]; | |
985 | char valbuf[100]; | |
986 | uint64_t sizes[2]; | |
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), | |
996 | &err); | |
997 | CheckNoError(err); | |
998 | } | |
999 | rocksdb_approximate_sizes(db, 2, start, start_len, limit, limit_len, sizes); | |
1000 | CheckCondition(sizes[0] > 0); | |
1001 | CheckCondition(sizes[1] > 0); | |
1002 | } | |
1003 | ||
1004 | StartPhase("property"); | |
1005 | { | |
1006 | char* prop = rocksdb_property_value(db, "nosuchprop"); | |
1007 | CheckCondition(prop == NULL); | |
1008 | prop = rocksdb_property_value(db, "rocksdb.stats"); | |
1009 | CheckCondition(prop != NULL); | |
1010 | Free(&prop); | |
1011 | } | |
1012 | ||
1013 | StartPhase("snapshot"); | |
1014 | { | |
1015 | const rocksdb_snapshot_t* snap; | |
1016 | snap = rocksdb_create_snapshot(db); | |
1017 | rocksdb_delete(db, woptions, "foo", 3, &err); | |
1018 | CheckNoError(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); | |
1024 | } | |
1025 | ||
1026 | StartPhase("repair"); | |
1027 | { | |
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); | |
1033 | rocksdb_close(db); | |
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); | |
1038 | CheckNoError(err); | |
1039 | db = rocksdb_open(options, dbname, &err); | |
1040 | CheckNoError(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); | |
1046 | } | |
1047 | ||
1048 | StartPhase("filter"); | |
1049 | for (run = 0; run < 2; run++) { | |
1050 | // First run uses custom filter, second run uses bloom filter | |
1051 | CheckNoError(err); | |
1052 | rocksdb_filterpolicy_t* policy; | |
1053 | if (run == 0) { | |
1054 | policy = rocksdb_filterpolicy_create( | |
1055 | NULL, FilterDestroy, FilterCreate, FilterKeyMatch, NULL, FilterName); | |
1056 | } else { | |
1057 | policy = rocksdb_filterpolicy_create_bloom(10); | |
1058 | } | |
1059 | ||
1060 | rocksdb_block_based_options_set_filter_policy(table_options, policy); | |
1061 | ||
1062 | // Create new database | |
1063 | rocksdb_close(db); | |
1064 | rocksdb_destroy_db(options, dbname, &err); | |
1065 | rocksdb_options_set_block_based_table_factory(options, table_options); | |
1066 | db = rocksdb_open(options, dbname, &err); | |
1067 | CheckNoError(err); | |
1068 | rocksdb_put(db, woptions, "foo", 3, "foovalue", 8, &err); | |
1069 | CheckNoError(err); | |
1070 | rocksdb_put(db, woptions, "bar", 3, "barvalue", 8, &err); | |
1071 | CheckNoError(err); | |
1072 | rocksdb_compact_range(db, NULL, 0, NULL, 0); | |
1073 | ||
1074 | fake_filter_result = 1; | |
1075 | CheckGet(db, roptions, "foo", "foovalue"); | |
1076 | CheckGet(db, roptions, "bar", "barvalue"); | |
1077 | if (phase == 0) { | |
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; | |
1083 | ||
1084 | CheckGet(db, roptions, "foo", "foovalue"); | |
1085 | CheckGet(db, roptions, "bar", "barvalue"); | |
1086 | } | |
1087 | // Reset the policy | |
1088 | rocksdb_block_based_options_set_filter_policy(table_options, NULL); | |
1089 | rocksdb_options_set_block_based_table_factory(options, table_options); | |
1090 | } | |
1091 | ||
1092 | StartPhase("compaction_filter"); | |
1093 | { | |
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 | |
1100 | rocksdb_close(db); | |
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); | |
1104 | ||
1105 | rocksdb_options_set_compaction_filter(options_with_filter, NULL); | |
1106 | rocksdb_compactionfilter_destroy(cfilter); | |
1107 | rocksdb_options_destroy(options_with_filter); | |
1108 | } | |
1109 | ||
1110 | StartPhase("compaction_filter_factory"); | |
1111 | { | |
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 | |
1118 | rocksdb_close(db); | |
1119 | rocksdb_destroy_db(options_with_filter_factory, dbname, &err); | |
1120 | rocksdb_options_set_compaction_filter_factory(options_with_filter_factory, | |
1121 | factory); | |
1122 | db = CheckCompaction(db, options_with_filter_factory, roptions, woptions); | |
1123 | ||
1124 | rocksdb_options_set_compaction_filter_factory( | |
1125 | options_with_filter_factory, NULL); | |
1126 | rocksdb_options_destroy(options_with_filter_factory); | |
1127 | } | |
1128 | ||
1129 | StartPhase("merge_operator"); | |
1130 | { | |
1131 | rocksdb_mergeoperator_t* merge_operator; | |
1132 | merge_operator = rocksdb_mergeoperator_create( | |
1133 | NULL, MergeOperatorDestroy, MergeOperatorFullMerge, | |
1134 | MergeOperatorPartialMerge, NULL, MergeOperatorName); | |
1135 | // Create new database | |
1136 | rocksdb_close(db); | |
1137 | rocksdb_destroy_db(options, dbname, &err); | |
1138 | rocksdb_options_set_merge_operator(options, merge_operator); | |
1139 | db = rocksdb_open(options, dbname, &err); | |
1140 | CheckNoError(err); | |
1141 | rocksdb_put(db, woptions, "foo", 3, "foovalue", 8, &err); | |
1142 | CheckNoError(err); | |
1143 | CheckGet(db, roptions, "foo", "foovalue"); | |
1144 | rocksdb_merge(db, woptions, "foo", 3, "barvalue", 8, &err); | |
1145 | CheckNoError(err); | |
1146 | CheckGet(db, roptions, "foo", "fake"); | |
1147 | ||
1148 | // Merge of a non-existing value | |
1149 | rocksdb_merge(db, woptions, "bar", 3, "barvalue", 8, &err); | |
1150 | CheckNoError(err); | |
1151 | CheckGet(db, roptions, "bar", "fake"); | |
1152 | ||
1153 | } | |
1154 | ||
1155 | StartPhase("columnfamilies"); | |
1156 | { | |
1157 | rocksdb_close(db); | |
1158 | rocksdb_destroy_db(options, dbname, &err); | |
1159 | CheckNoError(err); | |
1160 | ||
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); | |
1164 | CheckNoError(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); | |
1168 | CheckNoError(err); | |
1169 | rocksdb_close(db); | |
1170 | ||
1171 | size_t cflen; | |
1172 | char** column_fams = rocksdb_list_column_families(db_options, dbname, &cflen, &err); | |
1173 | CheckNoError(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); | |
1178 | ||
1179 | rocksdb_options_t* cf_options = rocksdb_options_create(); | |
1180 | ||
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); | |
1185 | CheckNoError(err); | |
1186 | ||
1187 | rocksdb_put_cf(db, woptions, handles[1], "foo", 3, "hello", 5, &err); | |
1188 | CheckNoError(err); | |
1189 | ||
1190 | CheckGetCF(db, roptions, handles[1], "foo", "hello"); | |
11fdf7f2 | 1191 | CheckPinGetCF(db, roptions, handles[1], "foo", "hello"); |
7c673cae FG |
1192 | |
1193 | rocksdb_delete_cf(db, woptions, handles[1], "foo", 3, &err); | |
1194 | CheckNoError(err); | |
1195 | ||
1196 | CheckGetCF(db, roptions, handles[1], "foo", NULL); | |
11fdf7f2 | 1197 | CheckPinGetCF(db, roptions, handles[1], "foo", NULL); |
7c673cae FG |
1198 | |
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); | |
1206 | CheckNoError(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"); | |
11fdf7f2 TL |
1210 | CheckPinGetCF(db, roptions, handles[1], "baz", NULL); |
1211 | CheckPinGetCF(db, roptions, handles[1], "bar", NULL); | |
1212 | CheckPinGetCF(db, roptions, handles[1], "box", "c"); | |
7c673cae FG |
1213 | rocksdb_writebatch_destroy(wb); |
1214 | ||
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 }; | |
1218 | char* vals[3]; | |
1219 | size_t vals_sizes[3]; | |
1220 | char* errs[3]; | |
1221 | rocksdb_multi_get_cf(db, roptions, get_handles, 3, keys, keys_sizes, vals, vals_sizes, errs); | |
1222 | ||
1223 | int i; | |
1224 | for (i = 0; i < 3; i++) { | |
1225 | CheckEqual(NULL, errs[i], 0); | |
1226 | switch (i) { | |
1227 | case 0: | |
1228 | CheckEqual(NULL, vals[i], vals_sizes[i]); // wrong cf | |
1229 | break; | |
1230 | case 1: | |
1231 | CheckEqual("c", vals[i], vals_sizes[i]); // bingo | |
1232 | break; | |
1233 | case 2: | |
1234 | CheckEqual(NULL, vals[i], vals_sizes[i]); // normal not found | |
1235 | break; | |
1236 | } | |
1237 | Free(&vals[i]); | |
1238 | } | |
1239 | ||
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)); | |
1244 | ||
1245 | for (i = 0; rocksdb_iter_valid(iter) != 0; rocksdb_iter_next(iter)) { | |
1246 | i++; | |
1247 | } | |
1248 | CheckCondition(i == 1); | |
1249 | rocksdb_iter_get_error(iter, &err); | |
1250 | CheckNoError(err); | |
1251 | rocksdb_iter_destroy(iter); | |
1252 | ||
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); | |
1256 | CheckNoError(err); | |
1257 | ||
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); | |
1263 | ||
1264 | iter = iters_handles[1]; | |
1265 | CheckCondition(!rocksdb_iter_valid(iter)); | |
1266 | rocksdb_iter_seek_to_first(iter); | |
1267 | CheckCondition(rocksdb_iter_valid(iter)); | |
1268 | ||
1269 | for (i = 0; rocksdb_iter_valid(iter) != 0; rocksdb_iter_next(iter)) { | |
1270 | i++; | |
1271 | } | |
1272 | CheckCondition(i == 1); | |
1273 | rocksdb_iter_get_error(iter, &err); | |
1274 | CheckNoError(err); | |
1275 | rocksdb_iter_destroy(iter); | |
1276 | ||
1277 | rocksdb_drop_column_family(db, handles[1], &err); | |
1278 | CheckNoError(err); | |
1279 | for (i = 0; i < 2; i++) { | |
1280 | rocksdb_column_family_handle_destroy(handles[i]); | |
1281 | } | |
1282 | rocksdb_close(db); | |
1283 | rocksdb_destroy_db(options, dbname, &err); | |
1284 | rocksdb_options_destroy(db_options); | |
1285 | rocksdb_options_destroy(cf_options); | |
1286 | } | |
1287 | ||
1288 | StartPhase("prefix"); | |
1289 | { | |
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); | |
1296 | ||
1297 | db = rocksdb_open(options, dbname, &err); | |
1298 | CheckNoError(err); | |
1299 | ||
1300 | rocksdb_put(db, woptions, "foo1", 4, "foo", 3, &err); | |
1301 | CheckNoError(err); | |
1302 | rocksdb_put(db, woptions, "foo2", 4, "foo", 3, &err); | |
1303 | CheckNoError(err); | |
1304 | rocksdb_put(db, woptions, "foo3", 4, "foo", 3, &err); | |
1305 | CheckNoError(err); | |
1306 | rocksdb_put(db, woptions, "bar1", 4, "bar", 3, &err); | |
1307 | CheckNoError(err); | |
1308 | rocksdb_put(db, woptions, "bar2", 4, "bar", 3, &err); | |
1309 | CheckNoError(err); | |
1310 | rocksdb_put(db, woptions, "bar3", 4, "bar", 3, &err); | |
1311 | CheckNoError(err); | |
1312 | ||
1313 | rocksdb_iterator_t* iter = rocksdb_create_iterator(db, roptions); | |
1314 | CheckCondition(!rocksdb_iter_valid(iter)); | |
1315 | ||
1316 | rocksdb_iter_seek(iter, "bar", 3); | |
1317 | rocksdb_iter_get_error(iter, &err); | |
1318 | CheckNoError(err); | |
1319 | CheckCondition(rocksdb_iter_valid(iter)); | |
1320 | ||
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); | |
1327 | CheckNoError(err); | |
1328 | rocksdb_iter_destroy(iter); | |
1329 | ||
1330 | rocksdb_readoptions_set_total_order_seek(roptions, 1); | |
1331 | iter = rocksdb_create_iterator(db, roptions); | |
1332 | CheckCondition(!rocksdb_iter_valid(iter)); | |
1333 | ||
1334 | rocksdb_iter_seek(iter, "ba", 2); | |
1335 | rocksdb_iter_get_error(iter, &err); | |
1336 | CheckNoError(err); | |
1337 | CheckCondition(rocksdb_iter_valid(iter)); | |
1338 | CheckIter(iter, "bar1", "bar"); | |
1339 | ||
1340 | rocksdb_iter_destroy(iter); | |
1341 | rocksdb_readoptions_set_total_order_seek(roptions, 0); | |
1342 | ||
1343 | rocksdb_close(db); | |
1344 | rocksdb_destroy_db(options, dbname, &err); | |
1345 | } | |
1346 | ||
11fdf7f2 TL |
1347 | // Check memory usage stats |
1348 | StartPhase("approximate_memory_usage"); | |
1349 | { | |
1350 | // Create database | |
1351 | db = rocksdb_open(options, dbname, &err); | |
1352 | CheckNoError(err); | |
1353 | ||
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); | |
1358 | ||
1359 | // take memory usage report before write-read operation | |
1360 | rocksdb_memory_usage_t* mu1; | |
1361 | mu1 = rocksdb_approximate_memory_usage_create(consumers, &err); | |
1362 | CheckNoError(err); | |
1363 | ||
1364 | // Put data (this should affect memtables) | |
1365 | rocksdb_put(db, woptions, "memory", 6, "test", 4, &err); | |
1366 | CheckNoError(err); | |
1367 | CheckGet(db, roptions, "memory", "test"); | |
1368 | ||
1369 | // take memory usage report after write-read operation | |
1370 | rocksdb_memory_usage_t* mu2; | |
1371 | mu2 = rocksdb_approximate_memory_usage_create(consumers, &err); | |
1372 | CheckNoError(err); | |
1373 | ||
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)); | |
1379 | ||
1380 | rocksdb_memory_consumers_destroy(consumers); | |
1381 | rocksdb_approximate_memory_usage_destroy(mu1); | |
1382 | rocksdb_approximate_memory_usage_destroy(mu2); | |
1383 | rocksdb_close(db); | |
1384 | rocksdb_destroy_db(options, dbname, &err); | |
1385 | CheckNoError(err); | |
1386 | } | |
1387 | ||
7c673cae FG |
1388 | StartPhase("cuckoo_options"); |
1389 | { | |
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); | |
1398 | ||
1399 | db = rocksdb_open(options, dbname, &err); | |
1400 | CheckNoError(err); | |
1401 | ||
1402 | rocksdb_cuckoo_options_destroy(cuckoo_options); | |
1403 | } | |
1404 | ||
1405 | StartPhase("iterate_upper_bound"); | |
1406 | { | |
1407 | // Create new empty database | |
1408 | rocksdb_close(db); | |
1409 | rocksdb_destroy_db(options, dbname, &err); | |
1410 | CheckNoError(err); | |
1411 | ||
1412 | rocksdb_options_set_prefix_extractor(options, NULL); | |
1413 | db = rocksdb_open(options, dbname, &err); | |
1414 | CheckNoError(err); | |
1415 | ||
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); | |
1420 | ||
1421 | // testing basic case with no iterate_upper_bound and no prefix_extractor | |
1422 | { | |
1423 | rocksdb_readoptions_set_iterate_upper_bound(roptions, NULL, 0); | |
1424 | rocksdb_iterator_t* iter = rocksdb_create_iterator(db, roptions); | |
1425 | ||
1426 | rocksdb_iter_seek(iter, "foo", 3); | |
1427 | CheckCondition(rocksdb_iter_valid(iter)); | |
1428 | CheckIter(iter, "foo", "bar"); | |
1429 | ||
1430 | rocksdb_iter_next(iter); | |
1431 | CheckCondition(rocksdb_iter_valid(iter)); | |
1432 | CheckIter(iter, "foo1", "bar1"); | |
1433 | ||
1434 | rocksdb_iter_next(iter); | |
1435 | CheckCondition(rocksdb_iter_valid(iter)); | |
1436 | CheckIter(iter, "g1", "0"); | |
1437 | ||
1438 | rocksdb_iter_destroy(iter); | |
1439 | } | |
1440 | ||
1441 | // testing iterate_upper_bound and forward iterator | |
1442 | // to make sure it stops at bound | |
1443 | { | |
1444 | // iterate_upper_bound points beyond the last expected entry | |
1445 | rocksdb_readoptions_set_iterate_upper_bound(roptions, "foo2", 4); | |
1446 | ||
1447 | rocksdb_iterator_t* iter = rocksdb_create_iterator(db, roptions); | |
1448 | ||
1449 | rocksdb_iter_seek(iter, "foo", 3); | |
1450 | CheckCondition(rocksdb_iter_valid(iter)); | |
1451 | CheckIter(iter, "foo", "bar"); | |
1452 | ||
1453 | rocksdb_iter_next(iter); | |
1454 | CheckCondition(rocksdb_iter_valid(iter)); | |
1455 | CheckIter(iter, "foo1", "bar1"); | |
1456 | ||
1457 | rocksdb_iter_next(iter); | |
1458 | // should stop here... | |
1459 | CheckCondition(!rocksdb_iter_valid(iter)); | |
1460 | ||
1461 | rocksdb_iter_destroy(iter); | |
1462 | } | |
1463 | } | |
1464 | ||
11fdf7f2 | 1465 | StartPhase("transactions"); |
7c673cae | 1466 | { |
7c673cae FG |
1467 | rocksdb_close(db); |
1468 | rocksdb_destroy_db(options, dbname, &err); | |
1469 | CheckNoError(err); | |
1470 | ||
11fdf7f2 TL |
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); | |
1476 | CheckNoError(err); | |
1477 | ||
1478 | // put outside a transaction | |
1479 | rocksdb_transactiondb_put(txn_db, woptions, "foo", 3, "hello", 5, &err); | |
1480 | CheckNoError(err); | |
1481 | CheckTxnDBGet(txn_db, roptions, "foo", "hello"); | |
1482 | ||
1483 | // delete from outside transaction | |
1484 | rocksdb_transactiondb_delete(txn_db, woptions, "foo", 3, &err); | |
1485 | CheckNoError(err); | |
1486 | CheckTxnDBGet(txn_db, roptions, "foo", NULL); | |
1487 | ||
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"); | |
1498 | CheckNoError(err); | |
1499 | ||
1500 | // begin a transaction | |
1501 | txn = rocksdb_transaction_begin(txn_db, woptions, txn_options, NULL); | |
1502 | // put | |
1503 | rocksdb_transaction_put(txn, "foo", 3, "hello", 5, &err); | |
1504 | CheckNoError(err); | |
1505 | CheckTxnGet(txn, roptions, "foo", "hello"); | |
1506 | // delete | |
1507 | rocksdb_transaction_delete(txn, "foo", 3, &err); | |
1508 | CheckNoError(err); | |
1509 | CheckTxnGet(txn, roptions, "foo", NULL); | |
1510 | ||
1511 | rocksdb_transaction_put(txn, "foo", 3, "hello", 5, &err); | |
1512 | CheckNoError(err); | |
1513 | ||
1514 | // read from outside transaction, before commit | |
1515 | CheckTxnDBGet(txn_db, roptions, "foo", NULL); | |
1516 | ||
1517 | // commit | |
1518 | rocksdb_transaction_commit(txn, &err); | |
1519 | CheckNoError(err); | |
1520 | ||
1521 | // read from outside transaction, after commit | |
1522 | CheckTxnDBGet(txn_db, roptions, "foo", "hello"); | |
1523 | ||
1524 | // reuse old transaction | |
1525 | txn = rocksdb_transaction_begin(txn_db, woptions, txn_options, txn); | |
1526 | ||
1527 | // snapshot | |
1528 | const rocksdb_snapshot_t* snapshot; | |
1529 | snapshot = rocksdb_transactiondb_create_snapshot(txn_db); | |
1530 | rocksdb_readoptions_set_snapshot(roptions, snapshot); | |
494da23a | 1531 | |
11fdf7f2 TL |
1532 | rocksdb_transactiondb_put(txn_db, woptions, "foo", 3, "hey", 3, &err); |
1533 | CheckNoError(err); | |
1534 | ||
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"); | |
1539 | ||
1540 | // iterate | |
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); | |
1548 | CheckNoError(err); | |
1549 | rocksdb_iter_destroy(iter); | |
1550 | ||
1551 | // rollback | |
1552 | rocksdb_transaction_rollback(txn, &err); | |
1553 | CheckNoError(err); | |
1554 | CheckTxnDBGet(txn_db, roptions, "bar", NULL); | |
1555 | ||
1556 | // save point | |
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"); | |
1562 | ||
1563 | // rollback to savepoint | |
1564 | rocksdb_transaction_rollback_to_savepoint(txn, &err); | |
1565 | CheckNoError(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); | |
1571 | CheckNoError(err); | |
1572 | CheckTxnDBGet(txn_db, roptions, "foo1", "hi1"); | |
1573 | CheckTxnDBGet(txn_db, roptions, "foo2", NULL); | |
1574 | ||
1575 | // Column families. | |
1576 | rocksdb_column_family_handle_t* cfh; | |
1577 | cfh = rocksdb_transactiondb_create_column_family(txn_db, options, | |
1578 | "txn_db_cf", &err); | |
1579 | CheckNoError(err); | |
1580 | ||
1581 | rocksdb_transactiondb_put_cf(txn_db, woptions, cfh, "cf_foo", 6, "cf_hello", | |
1582 | 8, &err); | |
1583 | CheckNoError(err); | |
1584 | CheckTxnDBGetCF(txn_db, roptions, cfh, "cf_foo", "cf_hello"); | |
1585 | ||
1586 | rocksdb_transactiondb_delete_cf(txn_db, woptions, cfh, "cf_foo", 6, &err); | |
1587 | CheckNoError(err); | |
1588 | CheckTxnDBGetCF(txn_db, roptions, cfh, "cf_foo", NULL); | |
1589 | ||
1590 | rocksdb_column_family_handle_destroy(cfh); | |
1591 | ||
1592 | // close and destroy | |
1593 | rocksdb_transaction_destroy(txn); | |
1594 | rocksdb_transactiondb_close(txn_db); | |
1595 | rocksdb_destroy_db(options, dbname, &err); | |
1596 | CheckNoError(err); | |
1597 | rocksdb_transaction_options_destroy(txn_options); | |
1598 | rocksdb_transactiondb_options_destroy(txn_db_options); | |
1599 | } | |
1600 | ||
1601 | StartPhase("optimistic_transactions"); | |
1602 | { | |
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); | |
1613 | CheckNoError(err); | |
1614 | rocksdb_transaction_put(txn2, "key1", 4, "value1", 6, &err); | |
1615 | CheckNoError(err); | |
1616 | CheckTxnGet(txn1, roptions, "key", "value"); | |
1617 | rocksdb_transaction_commit(txn1, &err); | |
1618 | CheckNoError(err); | |
1619 | rocksdb_transaction_commit(txn2, &err); | |
1620 | CheckNoError(err); | |
1621 | rocksdb_transaction_destroy(txn1); | |
1622 | rocksdb_transaction_destroy(txn2); | |
1623 | ||
1624 | // Check column family | |
1625 | db = rocksdb_optimistictransactiondb_get_base_db(otxn_db); | |
1626 | rocksdb_put(db, woptions, "key", 3, "value", 5, &err); | |
1627 | CheckNoError(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, | |
1632 | NULL); | |
1633 | rocksdb_transaction_put_cf(txn, cfh1, "key_cf1", 7, "val_cf1", 7, &err); | |
1634 | CheckNoError(err); | |
1635 | rocksdb_transaction_put_cf(txn, cfh2, "key_cf2", 7, "val_cf2", 7, &err); | |
1636 | CheckNoError(err); | |
1637 | rocksdb_transaction_commit(txn, &err); | |
1638 | CheckNoError(err); | |
1639 | txn = rocksdb_optimistictransaction_begin(otxn_db, woptions, otxn_options, | |
1640 | txn); | |
1641 | CheckGetCF(db, roptions, cfh1, "key_cf1", "val_cf1"); | |
1642 | CheckTxnGetCF(txn, roptions, cfh1, "key_cf1", "val_cf1"); | |
1643 | ||
1644 | // Check iterator with column family | |
1645 | rocksdb_transaction_put_cf(txn, cfh1, "key1_cf", 7, "val1_cf", 7, &err); | |
1646 | CheckNoError(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); | |
1654 | CheckNoError(err); | |
1655 | rocksdb_iter_destroy(iter); | |
1656 | ||
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); | |
1662 | ||
1663 | // Check open optimistic transaction db with column families | |
1664 | size_t cf_len; | |
1665 | char** column_fams = | |
1666 | rocksdb_list_column_families(db_options, dbname, &cf_len, &err); | |
1667 | CheckNoError(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); | |
1673 | ||
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}; | |
1677 | ||
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); | |
1682 | CheckNoError(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); | |
1697 | CheckNoError(err); | |
1698 | } | |
1699 | ||
1700 | // Simple sanity check that setting memtable rep works. | |
1701 | StartPhase("memtable_reps"); | |
1702 | { | |
1703 | // Create database with vector memtable. | |
7c673cae FG |
1704 | rocksdb_options_set_memtable_vector_rep(options); |
1705 | db = rocksdb_open(options, dbname, &err); | |
1706 | CheckNoError(err); | |
1707 | ||
1708 | // Create database with hash skiplist memtable. | |
1709 | rocksdb_close(db); | |
1710 | rocksdb_destroy_db(options, dbname, &err); | |
1711 | CheckNoError(err); | |
1712 | ||
1713 | rocksdb_options_set_hash_skip_list_rep(options, 5000, 4, 4); | |
1714 | db = rocksdb_open(options, dbname, &err); | |
1715 | CheckNoError(err); | |
1716 | } | |
1717 | ||
11fdf7f2 TL |
1718 | // Simple sanity check that options setting db_paths work. |
1719 | StartPhase("open_db_paths"); | |
1720 | { | |
1721 | rocksdb_close(db); | |
1722 | rocksdb_destroy_db(options, dbname, &err); | |
1723 | ||
1724 | const rocksdb_dbpath_t* paths[1] = {dbpath}; | |
1725 | rocksdb_options_set_db_paths(options, paths, 1); | |
1726 | db = rocksdb_open(options, dbname, &err); | |
1727 | CheckNoError(err); | |
1728 | } | |
1729 | ||
7c673cae FG |
1730 | StartPhase("cleanup"); |
1731 | rocksdb_close(db); | |
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); | |
11fdf7f2 | 1739 | rocksdb_dbpath_destroy(dbpath); |
7c673cae FG |
1740 | rocksdb_env_destroy(env); |
1741 | ||
1742 | fprintf(stderr, "PASS\n"); | |
1743 | return 0; | |
1744 | } | |
1745 | ||
1746 | #else | |
1747 | ||
1748 | int main() { | |
1749 | fprintf(stderr, "SKIPPED\n"); | |
1750 | return 0; | |
1751 | } | |
1752 | ||
1753 | #endif // !ROCKSDB_LITE |