]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/java/src/test/java/org/rocksdb/RocksDBTest.java
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / rocksdb / java / src / test / java / org / rocksdb / RocksDBTest.java
1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
5 package org.rocksdb;
6
7 import org.junit.*;
8 import org.junit.rules.ExpectedException;
9 import org.junit.rules.TemporaryFolder;
10
11 import java.nio.ByteBuffer;
12 import java.util.*;
13
14 import static java.nio.charset.StandardCharsets.UTF_8;
15 import static org.assertj.core.api.Assertions.assertThat;
16 import static org.junit.Assert.fail;
17
18 public class RocksDBTest {
19
20 @ClassRule
21 public static final RocksNativeLibraryResource ROCKS_NATIVE_LIBRARY_RESOURCE =
22 new RocksNativeLibraryResource();
23
24 @Rule
25 public TemporaryFolder dbFolder = new TemporaryFolder();
26
27 public static final Random rand = PlatformRandomHelper.
28 getPlatformSpecificRandomFactory();
29
30 @Test
31 public void open() throws RocksDBException {
32 try (final RocksDB db =
33 RocksDB.open(dbFolder.getRoot().getAbsolutePath())) {
34 assertThat(db).isNotNull();
35 }
36 }
37
38 @Test
39 public void open_opt() throws RocksDBException {
40 try (final Options opt = new Options().setCreateIfMissing(true);
41 final RocksDB db = RocksDB.open(opt,
42 dbFolder.getRoot().getAbsolutePath())) {
43 assertThat(db).isNotNull();
44 }
45 }
46
47 @Test
48 public void openWhenOpen() throws RocksDBException {
49 final String dbPath = dbFolder.getRoot().getAbsolutePath();
50
51 try (final RocksDB db1 = RocksDB.open(dbPath)) {
52 try (final RocksDB db2 = RocksDB.open(dbPath)) {
53 fail("Should have thrown an exception when opening the same db twice");
54 } catch (final RocksDBException e) {
55 assertThat(e.getStatus().getCode()).isEqualTo(Status.Code.IOError);
56 assertThat(e.getStatus().getSubCode()).isEqualTo(Status.SubCode.None);
57 assertThat(e.getStatus().getState()).contains("lock ");
58 }
59 }
60 }
61
62 @Test
63 public void createColumnFamily() throws RocksDBException {
64 final byte[] col1Name = "col1".getBytes(UTF_8);
65
66 try (final RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath());
67 final ColumnFamilyOptions cfOpts = new ColumnFamilyOptions()
68 ) {
69 try (final ColumnFamilyHandle col1 =
70 db.createColumnFamily(new ColumnFamilyDescriptor(col1Name, cfOpts))) {
71 assertThat(col1).isNotNull();
72 assertThat(col1.getName()).isEqualTo(col1Name);
73 }
74 }
75
76 final List<ColumnFamilyHandle> cfHandles = new ArrayList<>();
77 try (final RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath(),
78 Arrays.asList(
79 new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY),
80 new ColumnFamilyDescriptor(col1Name)),
81 cfHandles)) {
82 try {
83 assertThat(cfHandles.size()).isEqualTo(2);
84 assertThat(cfHandles.get(1)).isNotNull();
85 assertThat(cfHandles.get(1).getName()).isEqualTo(col1Name);
86 } finally {
87 for (final ColumnFamilyHandle cfHandle :
88 cfHandles) {
89 cfHandle.close();
90 }
91 }
92 }
93 }
94
95
96 @Test
97 public void createColumnFamilies() throws RocksDBException {
98 final byte[] col1Name = "col1".getBytes(UTF_8);
99 final byte[] col2Name = "col2".getBytes(UTF_8);
100
101 List<ColumnFamilyHandle> cfHandles;
102 try (final RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath());
103 final ColumnFamilyOptions cfOpts = new ColumnFamilyOptions()
104 ) {
105 cfHandles =
106 db.createColumnFamilies(cfOpts, Arrays.asList(col1Name, col2Name));
107 try {
108 assertThat(cfHandles).isNotNull();
109 assertThat(cfHandles.size()).isEqualTo(2);
110 assertThat(cfHandles.get(0).getName()).isEqualTo(col1Name);
111 assertThat(cfHandles.get(1).getName()).isEqualTo(col2Name);
112 } finally {
113 for (final ColumnFamilyHandle cfHandle : cfHandles) {
114 cfHandle.close();
115 }
116 }
117 }
118
119 cfHandles = new ArrayList<>();
120 try (final RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath(),
121 Arrays.asList(
122 new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY),
123 new ColumnFamilyDescriptor(col1Name),
124 new ColumnFamilyDescriptor(col2Name)),
125 cfHandles)) {
126 try {
127 assertThat(cfHandles.size()).isEqualTo(3);
128 assertThat(cfHandles.get(1)).isNotNull();
129 assertThat(cfHandles.get(1).getName()).isEqualTo(col1Name);
130 assertThat(cfHandles.get(2)).isNotNull();
131 assertThat(cfHandles.get(2).getName()).isEqualTo(col2Name);
132 } finally {
133 for (final ColumnFamilyHandle cfHandle : cfHandles) {
134 cfHandle.close();
135 }
136 }
137 }
138 }
139
140 @Test
141 public void createColumnFamiliesfromDescriptors() throws RocksDBException {
142 final byte[] col1Name = "col1".getBytes(UTF_8);
143 final byte[] col2Name = "col2".getBytes(UTF_8);
144
145 List<ColumnFamilyHandle> cfHandles;
146 try (final RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath());
147 final ColumnFamilyOptions cfOpts = new ColumnFamilyOptions()
148 ) {
149 cfHandles =
150 db.createColumnFamilies(Arrays.asList(
151 new ColumnFamilyDescriptor(col1Name, cfOpts),
152 new ColumnFamilyDescriptor(col2Name, cfOpts)));
153 try {
154 assertThat(cfHandles).isNotNull();
155 assertThat(cfHandles.size()).isEqualTo(2);
156 assertThat(cfHandles.get(0).getName()).isEqualTo(col1Name);
157 assertThat(cfHandles.get(1).getName()).isEqualTo(col2Name);
158 } finally {
159 for (final ColumnFamilyHandle cfHandle : cfHandles) {
160 cfHandle.close();
161 }
162 }
163 }
164
165 cfHandles = new ArrayList<>();
166 try (final RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath(),
167 Arrays.asList(
168 new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY),
169 new ColumnFamilyDescriptor(col1Name),
170 new ColumnFamilyDescriptor(col2Name)),
171 cfHandles)) {
172 try {
173 assertThat(cfHandles.size()).isEqualTo(3);
174 assertThat(cfHandles.get(1)).isNotNull();
175 assertThat(cfHandles.get(1).getName()).isEqualTo(col1Name);
176 assertThat(cfHandles.get(2)).isNotNull();
177 assertThat(cfHandles.get(2).getName()).isEqualTo(col2Name);
178 } finally {
179 for (final ColumnFamilyHandle cfHandle : cfHandles) {
180 cfHandle.close();
181 }
182 }
183 }
184 }
185
186 @Test
187 public void put() throws RocksDBException {
188 try (final RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath());
189 final WriteOptions opt = new WriteOptions(); final ReadOptions optr = new ReadOptions()) {
190 db.put("key1".getBytes(), "value".getBytes());
191 db.put(opt, "key2".getBytes(), "12345678".getBytes());
192 assertThat(db.get("key1".getBytes())).isEqualTo(
193 "value".getBytes());
194 assertThat(db.get("key2".getBytes())).isEqualTo(
195 "12345678".getBytes());
196
197 ByteBuffer key = ByteBuffer.allocateDirect(12);
198 ByteBuffer value = ByteBuffer.allocateDirect(12);
199 key.position(4);
200 key.put("key3".getBytes());
201 key.position(4).limit(8);
202 value.position(4);
203 value.put("val3".getBytes());
204 value.position(4).limit(8);
205
206 db.put(opt, key, value);
207
208 assertThat(key.position()).isEqualTo(8);
209 assertThat(key.limit()).isEqualTo(8);
210
211 assertThat(value.position()).isEqualTo(8);
212 assertThat(value.limit()).isEqualTo(8);
213
214 key.position(4);
215
216 ByteBuffer result = ByteBuffer.allocateDirect(12);
217 assertThat(db.get(optr, key, result)).isEqualTo(4);
218 assertThat(result.position()).isEqualTo(0);
219 assertThat(result.limit()).isEqualTo(4);
220 assertThat(key.position()).isEqualTo(8);
221 assertThat(key.limit()).isEqualTo(8);
222
223 byte[] tmp = new byte[4];
224 result.get(tmp);
225 assertThat(tmp).isEqualTo("val3".getBytes());
226
227 key.position(4);
228
229 result.clear().position(9);
230 assertThat(db.get(optr, key, result)).isEqualTo(4);
231 assertThat(result.position()).isEqualTo(9);
232 assertThat(result.limit()).isEqualTo(12);
233 assertThat(key.position()).isEqualTo(8);
234 assertThat(key.limit()).isEqualTo(8);
235 byte[] tmp2 = new byte[3];
236 result.get(tmp2);
237 assertThat(tmp2).isEqualTo("val".getBytes());
238
239 // put
240 Segment key3 = sliceSegment("key3");
241 Segment key4 = sliceSegment("key4");
242 Segment value0 = sliceSegment("value 0");
243 Segment value1 = sliceSegment("value 1");
244 db.put(key3.data, key3.offset, key3.len, value0.data, value0.offset, value0.len);
245 db.put(opt, key4.data, key4.offset, key4.len, value1.data, value1.offset, value1.len);
246
247 // compare
248 Assert.assertTrue(value0.isSamePayload(db.get(key3.data, key3.offset, key3.len)));
249 Assert.assertTrue(value1.isSamePayload(db.get(key4.data, key4.offset, key4.len)));
250 }
251 }
252
253 private static Segment sliceSegment(String key) {
254 ByteBuffer rawKey = ByteBuffer.allocate(key.length() + 4);
255 rawKey.put((byte)0);
256 rawKey.put((byte)0);
257 rawKey.put(key.getBytes());
258
259 return new Segment(rawKey.array(), 2, key.length());
260 }
261
262 private static class Segment {
263 final byte[] data;
264 final int offset;
265 final int len;
266
267 public boolean isSamePayload(byte[] value) {
268 if (value == null) {
269 return false;
270 }
271 if (value.length != len) {
272 return false;
273 }
274
275 for (int i = 0; i < value.length; i++) {
276 if (data[i + offset] != value[i]) {
277 return false;
278 }
279 }
280
281 return true;
282 }
283
284 public Segment(byte[] value, int offset, int len) {
285 this.data = value;
286 this.offset = offset;
287 this.len = len;
288 }
289 }
290
291 @Test
292 public void write() throws RocksDBException {
293 try (final StringAppendOperator stringAppendOperator = new StringAppendOperator();
294 final Options options = new Options()
295 .setMergeOperator(stringAppendOperator)
296 .setCreateIfMissing(true);
297 final RocksDB db = RocksDB.open(options,
298 dbFolder.getRoot().getAbsolutePath());
299 final WriteOptions opts = new WriteOptions()) {
300
301 try (final WriteBatch wb1 = new WriteBatch()) {
302 wb1.put("key1".getBytes(), "aa".getBytes());
303 wb1.merge("key1".getBytes(), "bb".getBytes());
304
305 try (final WriteBatch wb2 = new WriteBatch()) {
306 wb2.put("key2".getBytes(), "xx".getBytes());
307 wb2.merge("key2".getBytes(), "yy".getBytes());
308 db.write(opts, wb1);
309 db.write(opts, wb2);
310 }
311 }
312
313 assertThat(db.get("key1".getBytes())).isEqualTo(
314 "aa,bb".getBytes());
315 assertThat(db.get("key2".getBytes())).isEqualTo(
316 "xx,yy".getBytes());
317 }
318 }
319
320 @Test
321 public void getWithOutValue() throws RocksDBException {
322 try (final RocksDB db =
323 RocksDB.open(dbFolder.getRoot().getAbsolutePath())) {
324 db.put("key1".getBytes(), "value".getBytes());
325 db.put("key2".getBytes(), "12345678".getBytes());
326 byte[] outValue = new byte[5];
327 // not found value
328 int getResult = db.get("keyNotFound".getBytes(), outValue);
329 assertThat(getResult).isEqualTo(RocksDB.NOT_FOUND);
330 // found value which fits in outValue
331 getResult = db.get("key1".getBytes(), outValue);
332 assertThat(getResult).isNotEqualTo(RocksDB.NOT_FOUND);
333 assertThat(outValue).isEqualTo("value".getBytes());
334 // found value which fits partially
335 getResult = db.get("key2".getBytes(), outValue);
336 assertThat(getResult).isNotEqualTo(RocksDB.NOT_FOUND);
337 assertThat(outValue).isEqualTo("12345".getBytes());
338 }
339 }
340
341 @Test
342 public void getWithOutValueReadOptions() throws RocksDBException {
343 try (final RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath());
344 final ReadOptions rOpt = new ReadOptions()) {
345 db.put("key1".getBytes(), "value".getBytes());
346 db.put("key2".getBytes(), "12345678".getBytes());
347 byte[] outValue = new byte[5];
348 // not found value
349 int getResult = db.get(rOpt, "keyNotFound".getBytes(),
350 outValue);
351 assertThat(getResult).isEqualTo(RocksDB.NOT_FOUND);
352 // found value which fits in outValue
353 getResult = db.get(rOpt, "key1".getBytes(), outValue);
354 assertThat(getResult).isNotEqualTo(RocksDB.NOT_FOUND);
355 assertThat(outValue).isEqualTo("value".getBytes());
356 // found value which fits partially
357 getResult = db.get(rOpt, "key2".getBytes(), outValue);
358 assertThat(getResult).isNotEqualTo(RocksDB.NOT_FOUND);
359 assertThat(outValue).isEqualTo("12345".getBytes());
360 }
361 }
362
363 @Rule
364 public ExpectedException thrown = ExpectedException.none();
365
366 @Test
367 public void getOutOfArrayMaxSizeValue() throws RocksDBException {
368 final int numberOfValueSplits = 10;
369 final int splitSize = Integer.MAX_VALUE / numberOfValueSplits;
370
371 Runtime runtime = Runtime.getRuntime();
372 long neededMemory = ((long)(splitSize)) * (((long)numberOfValueSplits) + 3);
373 boolean isEnoughMemory = runtime.maxMemory() - runtime.totalMemory() > neededMemory;
374 Assume.assumeTrue(isEnoughMemory);
375
376 final byte[] valueSplit = new byte[splitSize];
377 final byte[] key = "key".getBytes();
378
379 thrown.expect(RocksDBException.class);
380 thrown.expectMessage("Requested array size exceeds VM limit");
381
382 // merge (numberOfValueSplits + 1) valueSplit's to get value size exceeding Integer.MAX_VALUE
383 try (final StringAppendOperator stringAppendOperator = new StringAppendOperator();
384 final Options opt = new Options()
385 .setCreateIfMissing(true)
386 .setMergeOperator(stringAppendOperator);
387 final RocksDB db = RocksDB.open(opt, dbFolder.getRoot().getAbsolutePath())) {
388 db.put(key, valueSplit);
389 for (int i = 0; i < numberOfValueSplits; i++) {
390 db.merge(key, valueSplit);
391 }
392 db.get(key);
393 }
394 }
395
396 @SuppressWarnings("deprecated")
397 @Test
398 public void multiGet() throws RocksDBException {
399 try (final RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath());
400 final ReadOptions rOpt = new ReadOptions()) {
401 db.put("key1".getBytes(), "value".getBytes());
402 db.put("key2".getBytes(), "12345678".getBytes());
403 List<byte[]> lookupKeys = new ArrayList<>();
404 lookupKeys.add("key1".getBytes());
405 lookupKeys.add("key2".getBytes());
406 Map<byte[], byte[]> results = db.multiGet(lookupKeys);
407 assertThat(results).isNotNull();
408 assertThat(results.values()).isNotNull();
409 assertThat(results.values()).
410 contains("value".getBytes(), "12345678".getBytes());
411 // test same method with ReadOptions
412 results = db.multiGet(rOpt, lookupKeys);
413 assertThat(results).isNotNull();
414 assertThat(results.values()).isNotNull();
415 assertThat(results.values()).
416 contains("value".getBytes(), "12345678".getBytes());
417
418 // remove existing key
419 lookupKeys.remove("key2".getBytes());
420 // add non existing key
421 lookupKeys.add("key3".getBytes());
422 results = db.multiGet(lookupKeys);
423 assertThat(results).isNotNull();
424 assertThat(results.values()).isNotNull();
425 assertThat(results.values()).
426 contains("value".getBytes());
427 // test same call with readOptions
428 results = db.multiGet(rOpt, lookupKeys);
429 assertThat(results).isNotNull();
430 assertThat(results.values()).isNotNull();
431 assertThat(results.values()).
432 contains("value".getBytes());
433 }
434 }
435
436 @Test
437 public void multiGetAsList() throws RocksDBException {
438 try (final RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath());
439 final ReadOptions rOpt = new ReadOptions()) {
440 db.put("key1".getBytes(), "value".getBytes());
441 db.put("key2".getBytes(), "12345678".getBytes());
442 List<byte[]> lookupKeys = new ArrayList<>();
443 lookupKeys.add("key1".getBytes());
444 lookupKeys.add("key2".getBytes());
445 List<byte[]> results = db.multiGetAsList(lookupKeys);
446 assertThat(results).isNotNull();
447 assertThat(results).hasSize(lookupKeys.size());
448 assertThat(results).
449 containsExactly("value".getBytes(), "12345678".getBytes());
450 // test same method with ReadOptions
451 results = db.multiGetAsList(rOpt, lookupKeys);
452 assertThat(results).isNotNull();
453 assertThat(results).
454 contains("value".getBytes(), "12345678".getBytes());
455
456 // remove existing key
457 lookupKeys.remove(1);
458 // add non existing key
459 lookupKeys.add("key3".getBytes());
460 results = db.multiGetAsList(lookupKeys);
461 assertThat(results).isNotNull();
462 assertThat(results).
463 containsExactly("value".getBytes(), null);
464 // test same call with readOptions
465 results = db.multiGetAsList(rOpt, lookupKeys);
466 assertThat(results).isNotNull();
467 assertThat(results).contains("value".getBytes());
468 }
469 }
470
471 @Test
472 public void merge() throws RocksDBException {
473 try (final StringAppendOperator stringAppendOperator = new StringAppendOperator();
474 final Options opt = new Options()
475 .setCreateIfMissing(true)
476 .setMergeOperator(stringAppendOperator);
477 final WriteOptions wOpt = new WriteOptions();
478 final RocksDB db = RocksDB.open(opt,
479 dbFolder.getRoot().getAbsolutePath())
480 ) {
481 db.put("key1".getBytes(), "value".getBytes());
482 assertThat(db.get("key1".getBytes())).isEqualTo(
483 "value".getBytes());
484 // merge key1 with another value portion
485 db.merge("key1".getBytes(), "value2".getBytes());
486 assertThat(db.get("key1".getBytes())).isEqualTo(
487 "value,value2".getBytes());
488 // merge key1 with another value portion
489 db.merge(wOpt, "key1".getBytes(), "value3".getBytes());
490 assertThat(db.get("key1".getBytes())).isEqualTo(
491 "value,value2,value3".getBytes());
492 // merge on non existent key shall insert the value
493 db.merge(wOpt, "key2".getBytes(), "xxxx".getBytes());
494 assertThat(db.get("key2".getBytes())).isEqualTo(
495 "xxxx".getBytes());
496
497 Segment key3 = sliceSegment("key3");
498 Segment key4 = sliceSegment("key4");
499 Segment value0 = sliceSegment("value 0");
500 Segment value1 = sliceSegment("value 1");
501
502 db.merge(key3.data, key3.offset, key3.len, value0.data, value0.offset, value0.len);
503 db.merge(wOpt, key4.data, key4.offset, key4.len, value1.data, value1.offset, value1.len);
504
505 // compare
506 Assert.assertTrue(value0.isSamePayload(db.get(key3.data, key3.offset, key3.len)));
507 Assert.assertTrue(value1.isSamePayload(db.get(key4.data, key4.offset, key4.len)));
508 }
509 }
510
511 @Test
512 public void delete() throws RocksDBException {
513 try (final RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath());
514 final WriteOptions wOpt = new WriteOptions()) {
515 db.put("key1".getBytes(), "value".getBytes());
516 db.put("key2".getBytes(), "12345678".getBytes());
517 db.put("key3".getBytes(), "33".getBytes());
518 assertThat(db.get("key1".getBytes())).isEqualTo(
519 "value".getBytes());
520 assertThat(db.get("key2".getBytes())).isEqualTo(
521 "12345678".getBytes());
522 assertThat(db.get("key3".getBytes())).isEqualTo("33".getBytes());
523 db.delete("key1".getBytes());
524 db.delete(wOpt, "key2".getBytes());
525 ByteBuffer key = ByteBuffer.allocateDirect(16);
526 key.put("key3".getBytes()).flip();
527 db.delete(wOpt, key);
528 assertThat(key.position()).isEqualTo(4);
529 assertThat(key.limit()).isEqualTo(4);
530
531 assertThat(db.get("key1".getBytes())).isNull();
532 assertThat(db.get("key2".getBytes())).isNull();
533
534 Segment key3 = sliceSegment("key3");
535 Segment key4 = sliceSegment("key4");
536 db.put("key3".getBytes(), "key3 value".getBytes());
537 db.put("key4".getBytes(), "key4 value".getBytes());
538
539 db.delete(key3.data, key3.offset, key3.len);
540 db.delete(wOpt, key4.data, key4.offset, key4.len);
541
542 assertThat(db.get("key3".getBytes())).isNull();
543 assertThat(db.get("key4".getBytes())).isNull();
544 }
545 }
546
547 @Test
548 public void singleDelete() throws RocksDBException {
549 try (final RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath());
550 final WriteOptions wOpt = new WriteOptions()) {
551 db.put("key1".getBytes(), "value".getBytes());
552 db.put("key2".getBytes(), "12345678".getBytes());
553 assertThat(db.get("key1".getBytes())).isEqualTo(
554 "value".getBytes());
555 assertThat(db.get("key2".getBytes())).isEqualTo(
556 "12345678".getBytes());
557 db.singleDelete("key1".getBytes());
558 db.singleDelete(wOpt, "key2".getBytes());
559 assertThat(db.get("key1".getBytes())).isNull();
560 assertThat(db.get("key2".getBytes())).isNull();
561 }
562 }
563
564 @Test
565 public void singleDelete_nonExisting() throws RocksDBException {
566 try (final RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath());
567 final WriteOptions wOpt = new WriteOptions()) {
568 db.singleDelete("key1".getBytes());
569 db.singleDelete(wOpt, "key2".getBytes());
570 assertThat(db.get("key1".getBytes())).isNull();
571 assertThat(db.get("key2".getBytes())).isNull();
572 }
573 }
574
575 @Test
576 public void deleteRange() throws RocksDBException {
577 try (final RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath())) {
578 db.put("key1".getBytes(), "value".getBytes());
579 db.put("key2".getBytes(), "12345678".getBytes());
580 db.put("key3".getBytes(), "abcdefg".getBytes());
581 db.put("key4".getBytes(), "xyz".getBytes());
582 assertThat(db.get("key1".getBytes())).isEqualTo("value".getBytes());
583 assertThat(db.get("key2".getBytes())).isEqualTo("12345678".getBytes());
584 assertThat(db.get("key3".getBytes())).isEqualTo("abcdefg".getBytes());
585 assertThat(db.get("key4".getBytes())).isEqualTo("xyz".getBytes());
586 db.deleteRange("key2".getBytes(), "key4".getBytes());
587 assertThat(db.get("key1".getBytes())).isEqualTo("value".getBytes());
588 assertThat(db.get("key2".getBytes())).isNull();
589 assertThat(db.get("key3".getBytes())).isNull();
590 assertThat(db.get("key4".getBytes())).isEqualTo("xyz".getBytes());
591 }
592 }
593
594 @Test
595 public void getIntProperty() throws RocksDBException {
596 try (
597 final Options options = new Options()
598 .setCreateIfMissing(true)
599 .setMaxWriteBufferNumber(10)
600 .setMinWriteBufferNumberToMerge(10);
601 final RocksDB db = RocksDB.open(options,
602 dbFolder.getRoot().getAbsolutePath());
603 final WriteOptions wOpt = new WriteOptions().setDisableWAL(true)
604 ) {
605 db.put(wOpt, "key1".getBytes(), "value1".getBytes());
606 db.put(wOpt, "key2".getBytes(), "value2".getBytes());
607 db.put(wOpt, "key3".getBytes(), "value3".getBytes());
608 db.put(wOpt, "key4".getBytes(), "value4".getBytes());
609 assertThat(db.getLongProperty("rocksdb.num-entries-active-mem-table"))
610 .isGreaterThan(0);
611 assertThat(db.getLongProperty("rocksdb.cur-size-active-mem-table"))
612 .isGreaterThan(0);
613 }
614 }
615
616 @Test
617 public void fullCompactRange() throws RocksDBException {
618 try (final Options opt = new Options().
619 setCreateIfMissing(true).
620 setDisableAutoCompactions(true).
621 setCompactionStyle(CompactionStyle.LEVEL).
622 setNumLevels(4).
623 setWriteBufferSize(100 << 10).
624 setLevelZeroFileNumCompactionTrigger(3).
625 setTargetFileSizeBase(200 << 10).
626 setTargetFileSizeMultiplier(1).
627 setMaxBytesForLevelBase(500 << 10).
628 setMaxBytesForLevelMultiplier(1).
629 setDisableAutoCompactions(false);
630 final RocksDB db = RocksDB.open(opt,
631 dbFolder.getRoot().getAbsolutePath())) {
632 // fill database with key/value pairs
633 byte[] b = new byte[10000];
634 for (int i = 0; i < 200; i++) {
635 rand.nextBytes(b);
636 db.put((String.valueOf(i)).getBytes(), b);
637 }
638 db.compactRange();
639 }
640 }
641
642 @Test
643 public void fullCompactRangeColumnFamily()
644 throws RocksDBException {
645 try (
646 final DBOptions opt = new DBOptions().
647 setCreateIfMissing(true).
648 setCreateMissingColumnFamilies(true);
649 final ColumnFamilyOptions new_cf_opts = new ColumnFamilyOptions().
650 setDisableAutoCompactions(true).
651 setCompactionStyle(CompactionStyle.LEVEL).
652 setNumLevels(4).
653 setWriteBufferSize(100 << 10).
654 setLevelZeroFileNumCompactionTrigger(3).
655 setTargetFileSizeBase(200 << 10).
656 setTargetFileSizeMultiplier(1).
657 setMaxBytesForLevelBase(500 << 10).
658 setMaxBytesForLevelMultiplier(1).
659 setDisableAutoCompactions(false)
660 ) {
661 final List<ColumnFamilyDescriptor> columnFamilyDescriptors =
662 Arrays.asList(
663 new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY),
664 new ColumnFamilyDescriptor("new_cf".getBytes(), new_cf_opts));
665
666 // open database
667 final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>();
668 try (final RocksDB db = RocksDB.open(opt,
669 dbFolder.getRoot().getAbsolutePath(),
670 columnFamilyDescriptors,
671 columnFamilyHandles)) {
672 try {
673 // fill database with key/value pairs
674 byte[] b = new byte[10000];
675 for (int i = 0; i < 200; i++) {
676 rand.nextBytes(b);
677 db.put(columnFamilyHandles.get(1),
678 String.valueOf(i).getBytes(), b);
679 }
680 db.compactRange(columnFamilyHandles.get(1));
681 } finally {
682 for (final ColumnFamilyHandle handle : columnFamilyHandles) {
683 handle.close();
684 }
685 }
686 }
687 }
688 }
689
690 @Test
691 public void compactRangeWithKeys()
692 throws RocksDBException {
693 try (final Options opt = new Options().
694 setCreateIfMissing(true).
695 setDisableAutoCompactions(true).
696 setCompactionStyle(CompactionStyle.LEVEL).
697 setNumLevels(4).
698 setWriteBufferSize(100 << 10).
699 setLevelZeroFileNumCompactionTrigger(3).
700 setTargetFileSizeBase(200 << 10).
701 setTargetFileSizeMultiplier(1).
702 setMaxBytesForLevelBase(500 << 10).
703 setMaxBytesForLevelMultiplier(1).
704 setDisableAutoCompactions(false);
705 final RocksDB db = RocksDB.open(opt,
706 dbFolder.getRoot().getAbsolutePath())) {
707 // fill database with key/value pairs
708 byte[] b = new byte[10000];
709 for (int i = 0; i < 200; i++) {
710 rand.nextBytes(b);
711 db.put((String.valueOf(i)).getBytes(), b);
712 }
713 db.compactRange("0".getBytes(), "201".getBytes());
714 }
715 }
716
717 @Test
718 public void compactRangeWithKeysReduce()
719 throws RocksDBException {
720 try (
721 final Options opt = new Options().
722 setCreateIfMissing(true).
723 setDisableAutoCompactions(true).
724 setCompactionStyle(CompactionStyle.LEVEL).
725 setNumLevels(4).
726 setWriteBufferSize(100 << 10).
727 setLevelZeroFileNumCompactionTrigger(3).
728 setTargetFileSizeBase(200 << 10).
729 setTargetFileSizeMultiplier(1).
730 setMaxBytesForLevelBase(500 << 10).
731 setMaxBytesForLevelMultiplier(1).
732 setDisableAutoCompactions(false);
733 final RocksDB db = RocksDB.open(opt,
734 dbFolder.getRoot().getAbsolutePath())) {
735 // fill database with key/value pairs
736 byte[] b = new byte[10000];
737 for (int i = 0; i < 200; i++) {
738 rand.nextBytes(b);
739 db.put((String.valueOf(i)).getBytes(), b);
740 }
741 db.flush(new FlushOptions().setWaitForFlush(true));
742 try (final CompactRangeOptions compactRangeOpts = new CompactRangeOptions()
743 .setChangeLevel(true)
744 .setTargetLevel(-1)
745 .setTargetPathId(0)) {
746 db.compactRange(null, "0".getBytes(), "201".getBytes(),
747 compactRangeOpts);
748 }
749 }
750 }
751
752 @Test
753 public void compactRangeWithKeysColumnFamily()
754 throws RocksDBException {
755 try (final DBOptions opt = new DBOptions().
756 setCreateIfMissing(true).
757 setCreateMissingColumnFamilies(true);
758 final ColumnFamilyOptions new_cf_opts = new ColumnFamilyOptions().
759 setDisableAutoCompactions(true).
760 setCompactionStyle(CompactionStyle.LEVEL).
761 setNumLevels(4).
762 setWriteBufferSize(100 << 10).
763 setLevelZeroFileNumCompactionTrigger(3).
764 setTargetFileSizeBase(200 << 10).
765 setTargetFileSizeMultiplier(1).
766 setMaxBytesForLevelBase(500 << 10).
767 setMaxBytesForLevelMultiplier(1).
768 setDisableAutoCompactions(false)
769 ) {
770 final List<ColumnFamilyDescriptor> columnFamilyDescriptors =
771 Arrays.asList(
772 new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY),
773 new ColumnFamilyDescriptor("new_cf".getBytes(), new_cf_opts)
774 );
775
776 // open database
777 final List<ColumnFamilyHandle> columnFamilyHandles =
778 new ArrayList<>();
779 try (final RocksDB db = RocksDB.open(opt,
780 dbFolder.getRoot().getAbsolutePath(),
781 columnFamilyDescriptors,
782 columnFamilyHandles)) {
783 try {
784 // fill database with key/value pairs
785 byte[] b = new byte[10000];
786 for (int i = 0; i < 200; i++) {
787 rand.nextBytes(b);
788 db.put(columnFamilyHandles.get(1),
789 String.valueOf(i).getBytes(), b);
790 }
791 db.compactRange(columnFamilyHandles.get(1),
792 "0".getBytes(), "201".getBytes());
793 } finally {
794 for (final ColumnFamilyHandle handle : columnFamilyHandles) {
795 handle.close();
796 }
797 }
798 }
799 }
800 }
801
802 @Test
803 public void compactRangeWithKeysReduceColumnFamily()
804 throws RocksDBException {
805 try (final DBOptions opt = new DBOptions().
806 setCreateIfMissing(true).
807 setCreateMissingColumnFamilies(true);
808 final ColumnFamilyOptions new_cf_opts = new ColumnFamilyOptions().
809 setDisableAutoCompactions(true).
810 setCompactionStyle(CompactionStyle.LEVEL).
811 setNumLevels(4).
812 setWriteBufferSize(100 << 10).
813 setLevelZeroFileNumCompactionTrigger(3).
814 setTargetFileSizeBase(200 << 10).
815 setTargetFileSizeMultiplier(1).
816 setMaxBytesForLevelBase(500 << 10).
817 setMaxBytesForLevelMultiplier(1).
818 setDisableAutoCompactions(false)
819 ) {
820 final List<ColumnFamilyDescriptor> columnFamilyDescriptors =
821 Arrays.asList(
822 new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY),
823 new ColumnFamilyDescriptor("new_cf".getBytes(), new_cf_opts)
824 );
825
826 final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>();
827 // open database
828 try (final RocksDB db = RocksDB.open(opt,
829 dbFolder.getRoot().getAbsolutePath(),
830 columnFamilyDescriptors,
831 columnFamilyHandles)) {
832 try (final CompactRangeOptions compactRangeOpts = new CompactRangeOptions()
833 .setChangeLevel(true)
834 .setTargetLevel(-1)
835 .setTargetPathId(0)) {
836 // fill database with key/value pairs
837 byte[] b = new byte[10000];
838 for (int i = 0; i < 200; i++) {
839 rand.nextBytes(b);
840 db.put(columnFamilyHandles.get(1),
841 String.valueOf(i).getBytes(), b);
842 }
843 db.compactRange(columnFamilyHandles.get(1), "0".getBytes(),
844 "201".getBytes(), compactRangeOpts);
845 } finally {
846 for (final ColumnFamilyHandle handle : columnFamilyHandles) {
847 handle.close();
848 }
849 }
850 }
851 }
852 }
853
854 @Test
855 public void compactRangeToLevel()
856 throws RocksDBException, InterruptedException {
857 final int NUM_KEYS_PER_L0_FILE = 100;
858 final int KEY_SIZE = 20;
859 final int VALUE_SIZE = 300;
860 final int L0_FILE_SIZE =
861 NUM_KEYS_PER_L0_FILE * (KEY_SIZE + VALUE_SIZE);
862 final int NUM_L0_FILES = 10;
863 final int TEST_SCALE = 5;
864 final int KEY_INTERVAL = 100;
865 try (final Options opt = new Options().
866 setCreateIfMissing(true).
867 setCompactionStyle(CompactionStyle.LEVEL).
868 setNumLevels(5).
869 // a slightly bigger write buffer than L0 file
870 // so that we can ensure manual flush always
871 // go before background flush happens.
872 setWriteBufferSize(L0_FILE_SIZE * 2).
873 // Disable auto L0 -> L1 compaction
874 setLevelZeroFileNumCompactionTrigger(20).
875 setTargetFileSizeBase(L0_FILE_SIZE * 100).
876 setTargetFileSizeMultiplier(1).
877 // To disable auto compaction
878 setMaxBytesForLevelBase(NUM_L0_FILES * L0_FILE_SIZE * 100).
879 setMaxBytesForLevelMultiplier(2).
880 setDisableAutoCompactions(true);
881 final RocksDB db = RocksDB.open(opt,
882 dbFolder.getRoot().getAbsolutePath())
883 ) {
884 // fill database with key/value pairs
885 byte[] value = new byte[VALUE_SIZE];
886 int int_key = 0;
887 for (int round = 0; round < 5; ++round) {
888 int initial_key = int_key;
889 for (int f = 1; f <= NUM_L0_FILES; ++f) {
890 for (int i = 0; i < NUM_KEYS_PER_L0_FILE; ++i) {
891 int_key += KEY_INTERVAL;
892 rand.nextBytes(value);
893
894 db.put(String.format("%020d", int_key).getBytes(),
895 value);
896 }
897 db.flush(new FlushOptions().setWaitForFlush(true));
898 // Make sure we do create one more L0 files.
899 assertThat(
900 db.getProperty("rocksdb.num-files-at-level0")).
901 isEqualTo("" + f);
902 }
903
904 // Compact all L0 files we just created
905 db.compactRange(
906 String.format("%020d", initial_key).getBytes(),
907 String.format("%020d", int_key - 1).getBytes());
908 // Making sure there isn't any L0 files.
909 assertThat(
910 db.getProperty("rocksdb.num-files-at-level0")).
911 isEqualTo("0");
912 // Making sure there are some L1 files.
913 // Here we only use != 0 instead of a specific number
914 // as we don't want the test make any assumption on
915 // how compaction works.
916 assertThat(
917 db.getProperty("rocksdb.num-files-at-level1")).
918 isNotEqualTo("0");
919 // Because we only compacted those keys we issued
920 // in this round, there shouldn't be any L1 -> L2
921 // compaction. So we expect zero L2 files here.
922 assertThat(
923 db.getProperty("rocksdb.num-files-at-level2")).
924 isEqualTo("0");
925 }
926 }
927 }
928
929 @Test
930 public void deleteFilesInRange() throws RocksDBException, InterruptedException {
931 final int KEY_SIZE = 20;
932 final int VALUE_SIZE = 1000;
933 final int FILE_SIZE = 64000;
934 final int NUM_FILES = 10;
935
936 final int KEY_INTERVAL = 10000;
937 /*
938 * Intention of these options is to end up reliably with 10 files
939 * we will be deleting using deleteFilesInRange.
940 * It is writing roughly number of keys that will fit in 10 files (target size)
941 * It is writing interleaved so that files from memory on L0 will overlap
942 * Then compaction cleans everything and we should end up with 10 files
943 */
944 try (final Options opt = new Options()
945 .setCreateIfMissing(true)
946 .setCompressionType(CompressionType.NO_COMPRESSION)
947 .setTargetFileSizeBase(FILE_SIZE)
948 .setWriteBufferSize(FILE_SIZE / 2)
949 .setDisableAutoCompactions(true);
950 final RocksDB db = RocksDB.open(opt, dbFolder.getRoot().getAbsolutePath())) {
951 int records = FILE_SIZE / (KEY_SIZE + VALUE_SIZE);
952
953 // fill database with key/value pairs
954 byte[] value = new byte[VALUE_SIZE];
955 int key_init = 0;
956 for (int o = 0; o < NUM_FILES; ++o) {
957 int int_key = key_init++;
958 for (int i = 0; i < records; ++i) {
959 int_key += KEY_INTERVAL;
960 rand.nextBytes(value);
961
962 db.put(String.format("%020d", int_key).getBytes(), value);
963 }
964 }
965 db.flush(new FlushOptions().setWaitForFlush(true));
966 db.compactRange();
967 // Make sure we do create one more L0 files.
968 assertThat(db.getProperty("rocksdb.num-files-at-level0")).isEqualTo("0");
969
970 // Should be 10, but we are OK with asserting +- 2
971 int files = Integer.parseInt(db.getProperty("rocksdb.num-files-at-level1"));
972 assertThat(files).isBetween(8, 12);
973
974 // Delete lower 60% (roughly). Result should be 5, but we are OK with asserting +- 2
975 // Important is that we know something was deleted (JNI call did something)
976 // Exact assertions are done in C++ unit tests
977 db.deleteFilesInRanges(null,
978 Arrays.asList(null, String.format("%020d", records * KEY_INTERVAL * 6 / 10).getBytes()),
979 false);
980 files = Integer.parseInt(db.getProperty("rocksdb.num-files-at-level1"));
981 assertThat(files).isBetween(3, 7);
982 }
983 }
984
985 @Test
986 public void compactRangeToLevelColumnFamily()
987 throws RocksDBException {
988 final int NUM_KEYS_PER_L0_FILE = 100;
989 final int KEY_SIZE = 20;
990 final int VALUE_SIZE = 300;
991 final int L0_FILE_SIZE =
992 NUM_KEYS_PER_L0_FILE * (KEY_SIZE + VALUE_SIZE);
993 final int NUM_L0_FILES = 10;
994 final int TEST_SCALE = 5;
995 final int KEY_INTERVAL = 100;
996
997 try (final DBOptions opt = new DBOptions().
998 setCreateIfMissing(true).
999 setCreateMissingColumnFamilies(true);
1000 final ColumnFamilyOptions new_cf_opts = new ColumnFamilyOptions().
1001 setCompactionStyle(CompactionStyle.LEVEL).
1002 setNumLevels(5).
1003 // a slightly bigger write buffer than L0 file
1004 // so that we can ensure manual flush always
1005 // go before background flush happens.
1006 setWriteBufferSize(L0_FILE_SIZE * 2).
1007 // Disable auto L0 -> L1 compaction
1008 setLevelZeroFileNumCompactionTrigger(20).
1009 setTargetFileSizeBase(L0_FILE_SIZE * 100).
1010 setTargetFileSizeMultiplier(1).
1011 // To disable auto compaction
1012 setMaxBytesForLevelBase(NUM_L0_FILES * L0_FILE_SIZE * 100).
1013 setMaxBytesForLevelMultiplier(2).
1014 setDisableAutoCompactions(true)
1015 ) {
1016 final List<ColumnFamilyDescriptor> columnFamilyDescriptors =
1017 Arrays.asList(
1018 new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY),
1019 new ColumnFamilyDescriptor("new_cf".getBytes(), new_cf_opts)
1020 );
1021
1022 final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>();
1023 // open database
1024 try (final RocksDB db = RocksDB.open(opt,
1025 dbFolder.getRoot().getAbsolutePath(),
1026 columnFamilyDescriptors,
1027 columnFamilyHandles)) {
1028 try {
1029 // fill database with key/value pairs
1030 byte[] value = new byte[VALUE_SIZE];
1031 int int_key = 0;
1032 for (int round = 0; round < 5; ++round) {
1033 int initial_key = int_key;
1034 for (int f = 1; f <= NUM_L0_FILES; ++f) {
1035 for (int i = 0; i < NUM_KEYS_PER_L0_FILE; ++i) {
1036 int_key += KEY_INTERVAL;
1037 rand.nextBytes(value);
1038
1039 db.put(columnFamilyHandles.get(1),
1040 String.format("%020d", int_key).getBytes(),
1041 value);
1042 }
1043 db.flush(new FlushOptions().setWaitForFlush(true),
1044 columnFamilyHandles.get(1));
1045 // Make sure we do create one more L0 files.
1046 assertThat(
1047 db.getProperty(columnFamilyHandles.get(1),
1048 "rocksdb.num-files-at-level0")).
1049 isEqualTo("" + f);
1050 }
1051
1052 // Compact all L0 files we just created
1053 db.compactRange(
1054 columnFamilyHandles.get(1),
1055 String.format("%020d", initial_key).getBytes(),
1056 String.format("%020d", int_key - 1).getBytes());
1057 // Making sure there isn't any L0 files.
1058 assertThat(
1059 db.getProperty(columnFamilyHandles.get(1),
1060 "rocksdb.num-files-at-level0")).
1061 isEqualTo("0");
1062 // Making sure there are some L1 files.
1063 // Here we only use != 0 instead of a specific number
1064 // as we don't want the test make any assumption on
1065 // how compaction works.
1066 assertThat(
1067 db.getProperty(columnFamilyHandles.get(1),
1068 "rocksdb.num-files-at-level1")).
1069 isNotEqualTo("0");
1070 // Because we only compacted those keys we issued
1071 // in this round, there shouldn't be any L1 -> L2
1072 // compaction. So we expect zero L2 files here.
1073 assertThat(
1074 db.getProperty(columnFamilyHandles.get(1),
1075 "rocksdb.num-files-at-level2")).
1076 isEqualTo("0");
1077 }
1078 } finally {
1079 for (final ColumnFamilyHandle handle : columnFamilyHandles) {
1080 handle.close();
1081 }
1082 }
1083 }
1084 }
1085 }
1086
1087 @Test
1088 public void pauseContinueBackgroundWork() throws RocksDBException {
1089 try (final Options options = new Options().setCreateIfMissing(true);
1090 final RocksDB db = RocksDB.open(options,
1091 dbFolder.getRoot().getAbsolutePath())
1092 ) {
1093 db.pauseBackgroundWork();
1094 db.continueBackgroundWork();
1095 db.pauseBackgroundWork();
1096 db.continueBackgroundWork();
1097 }
1098 }
1099
1100 @Test
1101 public void enableDisableFileDeletions() throws RocksDBException {
1102 try (final Options options = new Options().setCreateIfMissing(true);
1103 final RocksDB db = RocksDB.open(options,
1104 dbFolder.getRoot().getAbsolutePath())
1105 ) {
1106 db.disableFileDeletions();
1107 db.enableFileDeletions(false);
1108 db.disableFileDeletions();
1109 db.enableFileDeletions(true);
1110 }
1111 }
1112
1113 @Test
1114 public void setOptions() throws RocksDBException {
1115 try (final DBOptions options = new DBOptions()
1116 .setCreateIfMissing(true)
1117 .setCreateMissingColumnFamilies(true);
1118 final ColumnFamilyOptions new_cf_opts = new ColumnFamilyOptions()
1119 .setWriteBufferSize(4096)) {
1120
1121 final List<ColumnFamilyDescriptor> columnFamilyDescriptors =
1122 Arrays.asList(
1123 new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY),
1124 new ColumnFamilyDescriptor("new_cf".getBytes(), new_cf_opts));
1125
1126 // open database
1127 final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>();
1128 try (final RocksDB db = RocksDB.open(options,
1129 dbFolder.getRoot().getAbsolutePath(), columnFamilyDescriptors, columnFamilyHandles)) {
1130 try {
1131 final MutableColumnFamilyOptions mutableOptions =
1132 MutableColumnFamilyOptions.builder()
1133 .setWriteBufferSize(2048)
1134 .build();
1135
1136 db.setOptions(columnFamilyHandles.get(1), mutableOptions);
1137
1138 } finally {
1139 for (final ColumnFamilyHandle handle : columnFamilyHandles) {
1140 handle.close();
1141 }
1142 }
1143 }
1144 }
1145 }
1146
1147 @Test
1148 public void destroyDB() throws RocksDBException {
1149 try (final Options options = new Options().setCreateIfMissing(true)) {
1150 String dbPath = dbFolder.getRoot().getAbsolutePath();
1151 try (final RocksDB db = RocksDB.open(options, dbPath)) {
1152 db.put("key1".getBytes(), "value".getBytes());
1153 }
1154 assertThat(dbFolder.getRoot().exists() && dbFolder.getRoot().listFiles().length != 0)
1155 .isTrue();
1156 RocksDB.destroyDB(dbPath, options);
1157 assertThat(dbFolder.getRoot().exists() && dbFolder.getRoot().listFiles().length != 0)
1158 .isFalse();
1159 }
1160 }
1161
1162 @Test(expected = RocksDBException.class)
1163 public void destroyDBFailIfOpen() throws RocksDBException {
1164 try (final Options options = new Options().setCreateIfMissing(true)) {
1165 String dbPath = dbFolder.getRoot().getAbsolutePath();
1166 try (final RocksDB db = RocksDB.open(options, dbPath)) {
1167 // Fails as the db is open and locked.
1168 RocksDB.destroyDB(dbPath, options);
1169 }
1170 }
1171 }
1172
1173 @Ignore("This test crashes. Re-enable after fixing.")
1174 @Test
1175 public void getApproximateSizes() throws RocksDBException {
1176 final byte key1[] = "key1".getBytes(UTF_8);
1177 final byte key2[] = "key2".getBytes(UTF_8);
1178 final byte key3[] = "key3".getBytes(UTF_8);
1179 try (final Options options = new Options().setCreateIfMissing(true)) {
1180 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1181 try (final RocksDB db = RocksDB.open(options, dbPath)) {
1182 db.put(key1, key1);
1183 db.put(key2, key2);
1184 db.put(key3, key3);
1185
1186 final long[] sizes = db.getApproximateSizes(
1187 Arrays.asList(
1188 new Range(new Slice(key1), new Slice(key2)),
1189 new Range(new Slice(key2), new Slice(key3))
1190 ),
1191 SizeApproximationFlag.INCLUDE_FILES,
1192 SizeApproximationFlag.INCLUDE_MEMTABLES);
1193
1194 assertThat(sizes.length).isEqualTo(2);
1195 assertThat(sizes[0]).isEqualTo(0);
1196 assertThat(sizes[1]).isGreaterThanOrEqualTo(1);
1197 }
1198 }
1199 }
1200
1201 @Test
1202 public void getApproximateMemTableStats() throws RocksDBException {
1203 final byte key1[] = "key1".getBytes(UTF_8);
1204 final byte key2[] = "key2".getBytes(UTF_8);
1205 final byte key3[] = "key3".getBytes(UTF_8);
1206 try (final Options options = new Options().setCreateIfMissing(true)) {
1207 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1208 try (final RocksDB db = RocksDB.open(options, dbPath)) {
1209 db.put(key1, key1);
1210 db.put(key2, key2);
1211 db.put(key3, key3);
1212
1213 final RocksDB.CountAndSize stats =
1214 db.getApproximateMemTableStats(
1215 new Range(new Slice(key1), new Slice(key3)));
1216
1217 assertThat(stats).isNotNull();
1218 assertThat(stats.count).isGreaterThan(1);
1219 assertThat(stats.size).isGreaterThan(1);
1220 }
1221 }
1222 }
1223
1224 @Ignore("TODO(AR) re-enable when ready!")
1225 @Test
1226 public void compactFiles() throws RocksDBException {
1227 final int kTestKeySize = 16;
1228 final int kTestValueSize = 984;
1229 final int kEntrySize = kTestKeySize + kTestValueSize;
1230 final int kEntriesPerBuffer = 100;
1231 final int writeBufferSize = kEntrySize * kEntriesPerBuffer;
1232 final byte[] cfName = "pikachu".getBytes(UTF_8);
1233
1234 try (final Options options = new Options()
1235 .setCreateIfMissing(true)
1236 .setWriteBufferSize(writeBufferSize)
1237 .setCompactionStyle(CompactionStyle.LEVEL)
1238 .setTargetFileSizeBase(writeBufferSize)
1239 .setMaxBytesForLevelBase(writeBufferSize * 2)
1240 .setLevel0StopWritesTrigger(2)
1241 .setMaxBytesForLevelMultiplier(2)
1242 .setCompressionType(CompressionType.NO_COMPRESSION)
1243 .setMaxSubcompactions(4)) {
1244 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1245 try (final RocksDB db = RocksDB.open(options, dbPath);
1246 final ColumnFamilyOptions cfOptions = new ColumnFamilyOptions(options)) {
1247 db.createColumnFamily(new ColumnFamilyDescriptor(cfName,
1248 cfOptions)).close();
1249 }
1250
1251 try (final ColumnFamilyOptions cfOptions = new ColumnFamilyOptions(options)) {
1252 final List<ColumnFamilyDescriptor> cfDescriptors = Arrays.asList(
1253 new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY, cfOptions),
1254 new ColumnFamilyDescriptor(cfName, cfOptions)
1255 );
1256 final List<ColumnFamilyHandle> cfHandles = new ArrayList<>();
1257 try (final DBOptions dbOptions = new DBOptions(options);
1258 final RocksDB db = RocksDB.open(dbOptions, dbPath, cfDescriptors,
1259 cfHandles);
1260 ) {
1261 try (final FlushOptions flushOptions = new FlushOptions()
1262 .setWaitForFlush(true)
1263 .setAllowWriteStall(true);
1264 final CompactionOptions compactionOptions = new CompactionOptions()) {
1265 final Random rnd = new Random(301);
1266 for (int key = 64 * kEntriesPerBuffer; key >= 0; --key) {
1267 final byte[] value = new byte[kTestValueSize];
1268 rnd.nextBytes(value);
1269 db.put(cfHandles.get(1), Integer.toString(key).getBytes(UTF_8),
1270 value);
1271 }
1272 db.flush(flushOptions, cfHandles);
1273
1274 final RocksDB.LiveFiles liveFiles = db.getLiveFiles();
1275 final List<String> compactedFiles =
1276 db.compactFiles(compactionOptions, cfHandles.get(1),
1277 liveFiles.files, 1, -1, null);
1278 assertThat(compactedFiles).isNotEmpty();
1279 } finally {
1280 for (final ColumnFamilyHandle cfHandle : cfHandles) {
1281 cfHandle.close();
1282 }
1283 }
1284 }
1285 }
1286 }
1287 }
1288
1289 @Test
1290 public void enableAutoCompaction() throws RocksDBException {
1291 try (final DBOptions options = new DBOptions()
1292 .setCreateIfMissing(true)) {
1293 final List<ColumnFamilyDescriptor> cfDescs = Arrays.asList(
1294 new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY)
1295 );
1296 final List<ColumnFamilyHandle> cfHandles = new ArrayList<>();
1297 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1298 try (final RocksDB db = RocksDB.open(options, dbPath, cfDescs, cfHandles)) {
1299 try {
1300 db.enableAutoCompaction(cfHandles);
1301 } finally {
1302 for (final ColumnFamilyHandle cfHandle : cfHandles) {
1303 cfHandle.close();
1304 }
1305 }
1306 }
1307 }
1308 }
1309
1310 @Test
1311 public void numberLevels() throws RocksDBException {
1312 try (final Options options = new Options().setCreateIfMissing(true)) {
1313 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1314 try (final RocksDB db = RocksDB.open(options, dbPath)) {
1315 assertThat(db.numberLevels()).isEqualTo(7);
1316 }
1317 }
1318 }
1319
1320 @Test
1321 public void maxMemCompactionLevel() throws RocksDBException {
1322 try (final Options options = new Options().setCreateIfMissing(true)) {
1323 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1324 try (final RocksDB db = RocksDB.open(options, dbPath)) {
1325 assertThat(db.maxMemCompactionLevel()).isEqualTo(0);
1326 }
1327 }
1328 }
1329
1330 @Test
1331 public void level0StopWriteTrigger() throws RocksDBException {
1332 try (final Options options = new Options().setCreateIfMissing(true)) {
1333 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1334 try (final RocksDB db = RocksDB.open(options, dbPath)) {
1335 assertThat(db.level0StopWriteTrigger()).isEqualTo(36);
1336 }
1337 }
1338 }
1339
1340 @Test
1341 public void getName() throws RocksDBException {
1342 try (final Options options = new Options().setCreateIfMissing(true)) {
1343 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1344 try (final RocksDB db = RocksDB.open(options, dbPath)) {
1345 assertThat(db.getName()).isEqualTo(dbPath);
1346 }
1347 }
1348 }
1349
1350 @Test
1351 public void getEnv() throws RocksDBException {
1352 try (final Options options = new Options().setCreateIfMissing(true)) {
1353 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1354 try (final RocksDB db = RocksDB.open(options, dbPath)) {
1355 assertThat(db.getEnv()).isEqualTo(Env.getDefault());
1356 }
1357 }
1358 }
1359
1360 @Test
1361 public void flush() throws RocksDBException {
1362 try (final Options options = new Options().setCreateIfMissing(true)) {
1363 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1364 try (final RocksDB db = RocksDB.open(options, dbPath);
1365 final FlushOptions flushOptions = new FlushOptions()) {
1366 db.flush(flushOptions);
1367 }
1368 }
1369 }
1370
1371 @Test
1372 public void flushWal() throws RocksDBException {
1373 try (final Options options = new Options().setCreateIfMissing(true)) {
1374 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1375 try (final RocksDB db = RocksDB.open(options, dbPath)) {
1376 db.flushWal(true);
1377 }
1378 }
1379 }
1380
1381 @Test
1382 public void syncWal() throws RocksDBException {
1383 try (final Options options = new Options().setCreateIfMissing(true)) {
1384 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1385 try (final RocksDB db = RocksDB.open(options, dbPath)) {
1386 db.syncWal();
1387 }
1388 }
1389 }
1390
1391 @Test
1392 public void setPreserveDeletesSequenceNumber() throws RocksDBException {
1393 try (final Options options = new Options().setCreateIfMissing(true)) {
1394 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1395 try (final RocksDB db = RocksDB.open(options, dbPath)) {
1396 assertThat(db.setPreserveDeletesSequenceNumber(db.getLatestSequenceNumber()))
1397 .isFalse();
1398 }
1399 }
1400 }
1401
1402 @Test
1403 public void getLiveFiles() throws RocksDBException {
1404 try (final Options options = new Options().setCreateIfMissing(true)) {
1405 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1406 try (final RocksDB db = RocksDB.open(options, dbPath)) {
1407 final RocksDB.LiveFiles livefiles = db.getLiveFiles(true);
1408 assertThat(livefiles).isNotNull();
1409 assertThat(livefiles.manifestFileSize).isEqualTo(13);
1410 assertThat(livefiles.files.size()).isEqualTo(3);
1411 assertThat(livefiles.files.get(0)).isEqualTo("/CURRENT");
1412 assertThat(livefiles.files.get(1)).isEqualTo("/MANIFEST-000001");
1413 assertThat(livefiles.files.get(2)).isEqualTo("/OPTIONS-000005");
1414 }
1415 }
1416 }
1417
1418 @Test
1419 public void getSortedWalFiles() throws RocksDBException {
1420 try (final Options options = new Options().setCreateIfMissing(true)) {
1421 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1422 try (final RocksDB db = RocksDB.open(options, dbPath)) {
1423 db.put("key1".getBytes(UTF_8), "value1".getBytes(UTF_8));
1424 final List<LogFile> logFiles = db.getSortedWalFiles();
1425 assertThat(logFiles).isNotNull();
1426 assertThat(logFiles.size()).isEqualTo(1);
1427 assertThat(logFiles.get(0).type())
1428 .isEqualTo(WalFileType.kAliveLogFile);
1429 }
1430 }
1431 }
1432
1433 @Test
1434 public void deleteFile() throws RocksDBException {
1435 try (final Options options = new Options().setCreateIfMissing(true)) {
1436 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1437 try (final RocksDB db = RocksDB.open(options, dbPath)) {
1438 db.deleteFile("unknown");
1439 }
1440 }
1441 }
1442
1443 @Test
1444 public void getLiveFilesMetaData() throws RocksDBException {
1445 try (final Options options = new Options().setCreateIfMissing(true)) {
1446 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1447 try (final RocksDB db = RocksDB.open(options, dbPath)) {
1448 db.put("key1".getBytes(UTF_8), "value1".getBytes(UTF_8));
1449 final List<LiveFileMetaData> liveFilesMetaData
1450 = db.getLiveFilesMetaData();
1451 assertThat(liveFilesMetaData).isEmpty();
1452 }
1453 }
1454 }
1455
1456 @Test
1457 public void getColumnFamilyMetaData() throws RocksDBException {
1458 try (final DBOptions options = new DBOptions()
1459 .setCreateIfMissing(true)) {
1460 final List<ColumnFamilyDescriptor> cfDescs = Arrays.asList(
1461 new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY)
1462 );
1463 final List<ColumnFamilyHandle> cfHandles = new ArrayList<>();
1464 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1465 try (final RocksDB db = RocksDB.open(options, dbPath, cfDescs, cfHandles)) {
1466 db.put(cfHandles.get(0), "key1".getBytes(UTF_8), "value1".getBytes(UTF_8));
1467 try {
1468 final ColumnFamilyMetaData cfMetadata =
1469 db.getColumnFamilyMetaData(cfHandles.get(0));
1470 assertThat(cfMetadata).isNotNull();
1471 assertThat(cfMetadata.name()).isEqualTo(RocksDB.DEFAULT_COLUMN_FAMILY);
1472 assertThat(cfMetadata.levels().size()).isEqualTo(7);
1473 } finally {
1474 for (final ColumnFamilyHandle cfHandle : cfHandles) {
1475 cfHandle.close();
1476 }
1477 }
1478 }
1479 }
1480 }
1481
1482 @Test
1483 public void verifyChecksum() throws RocksDBException {
1484 try (final Options options = new Options().setCreateIfMissing(true)) {
1485 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1486 try (final RocksDB db = RocksDB.open(options, dbPath)) {
1487 db.verifyChecksum();
1488 }
1489 }
1490 }
1491
1492 @Test
1493 public void getPropertiesOfAllTables() throws RocksDBException {
1494 try (final DBOptions options = new DBOptions()
1495 .setCreateIfMissing(true)) {
1496 final List<ColumnFamilyDescriptor> cfDescs = Arrays.asList(
1497 new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY)
1498 );
1499 final List<ColumnFamilyHandle> cfHandles = new ArrayList<>();
1500 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1501 try (final RocksDB db = RocksDB.open(options, dbPath, cfDescs, cfHandles)) {
1502 db.put(cfHandles.get(0), "key1".getBytes(UTF_8), "value1".getBytes(UTF_8));
1503 try {
1504 final Map<String, TableProperties> properties =
1505 db.getPropertiesOfAllTables(cfHandles.get(0));
1506 assertThat(properties).isNotNull();
1507 } finally {
1508 for (final ColumnFamilyHandle cfHandle : cfHandles) {
1509 cfHandle.close();
1510 }
1511 }
1512 }
1513 }
1514 }
1515
1516 @Test
1517 public void getPropertiesOfTablesInRange() throws RocksDBException {
1518 try (final DBOptions options = new DBOptions()
1519 .setCreateIfMissing(true)) {
1520 final List<ColumnFamilyDescriptor> cfDescs = Arrays.asList(
1521 new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY)
1522 );
1523 final List<ColumnFamilyHandle> cfHandles = new ArrayList<>();
1524 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1525 try (final RocksDB db = RocksDB.open(options, dbPath, cfDescs, cfHandles)) {
1526 db.put(cfHandles.get(0), "key1".getBytes(UTF_8), "value1".getBytes(UTF_8));
1527 db.put(cfHandles.get(0), "key2".getBytes(UTF_8), "value2".getBytes(UTF_8));
1528 db.put(cfHandles.get(0), "key3".getBytes(UTF_8), "value3".getBytes(UTF_8));
1529 try {
1530 final Range range = new Range(
1531 new Slice("key1".getBytes(UTF_8)),
1532 new Slice("key3".getBytes(UTF_8)));
1533 final Map<String, TableProperties> properties =
1534 db.getPropertiesOfTablesInRange(
1535 cfHandles.get(0), Arrays.asList(range));
1536 assertThat(properties).isNotNull();
1537 } finally {
1538 for (final ColumnFamilyHandle cfHandle : cfHandles) {
1539 cfHandle.close();
1540 }
1541 }
1542 }
1543 }
1544 }
1545
1546 @Test
1547 public void suggestCompactRange() throws RocksDBException {
1548 try (final DBOptions options = new DBOptions()
1549 .setCreateIfMissing(true)) {
1550 final List<ColumnFamilyDescriptor> cfDescs = Arrays.asList(
1551 new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY)
1552 );
1553 final List<ColumnFamilyHandle> cfHandles = new ArrayList<>();
1554 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1555 try (final RocksDB db = RocksDB.open(options, dbPath, cfDescs, cfHandles)) {
1556 db.put(cfHandles.get(0), "key1".getBytes(UTF_8), "value1".getBytes(UTF_8));
1557 db.put(cfHandles.get(0), "key2".getBytes(UTF_8), "value2".getBytes(UTF_8));
1558 db.put(cfHandles.get(0), "key3".getBytes(UTF_8), "value3".getBytes(UTF_8));
1559 try {
1560 final Range range = db.suggestCompactRange(cfHandles.get(0));
1561 assertThat(range).isNotNull();
1562 } finally {
1563 for (final ColumnFamilyHandle cfHandle : cfHandles) {
1564 cfHandle.close();
1565 }
1566 }
1567 }
1568 }
1569 }
1570
1571 @Test
1572 public void promoteL0() throws RocksDBException {
1573 try (final Options options = new Options().setCreateIfMissing(true)) {
1574 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1575 try (final RocksDB db = RocksDB.open(options, dbPath)) {
1576 db.promoteL0(2);
1577 }
1578 }
1579 }
1580
1581 @Test
1582 public void startTrace() throws RocksDBException {
1583 try (final Options options = new Options().setCreateIfMissing(true)) {
1584 final String dbPath = dbFolder.getRoot().getAbsolutePath();
1585 try (final RocksDB db = RocksDB.open(options, dbPath)) {
1586 final TraceOptions traceOptions = new TraceOptions();
1587
1588 try (final InMemoryTraceWriter traceWriter = new InMemoryTraceWriter()) {
1589 db.startTrace(traceOptions, traceWriter);
1590
1591 db.put("key1".getBytes(UTF_8), "value1".getBytes(UTF_8));
1592
1593 db.endTrace();
1594
1595 final List<byte[]> writes = traceWriter.getWrites();
1596 assertThat(writes.size()).isGreaterThan(0);
1597 }
1598 }
1599 }
1600 }
1601
1602 @Test
1603 public void setDBOptions() throws RocksDBException {
1604 try (final DBOptions options = new DBOptions()
1605 .setCreateIfMissing(true)
1606 .setCreateMissingColumnFamilies(true);
1607 final ColumnFamilyOptions new_cf_opts = new ColumnFamilyOptions()
1608 .setWriteBufferSize(4096)) {
1609
1610 final List<ColumnFamilyDescriptor> columnFamilyDescriptors =
1611 Arrays.asList(
1612 new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY),
1613 new ColumnFamilyDescriptor("new_cf".getBytes(), new_cf_opts));
1614
1615 // open database
1616 final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>();
1617 try (final RocksDB db = RocksDB.open(options,
1618 dbFolder.getRoot().getAbsolutePath(), columnFamilyDescriptors, columnFamilyHandles)) {
1619 try {
1620 final MutableDBOptions mutableOptions =
1621 MutableDBOptions.builder()
1622 .setBytesPerSync(1024 * 1027 * 7)
1623 .setAvoidFlushDuringShutdown(false)
1624 .build();
1625
1626 db.setDBOptions(mutableOptions);
1627 } finally {
1628 for (final ColumnFamilyHandle handle : columnFamilyHandles) {
1629 handle.close();
1630 }
1631 }
1632 }
1633 }
1634 }
1635
1636 private static class InMemoryTraceWriter extends AbstractTraceWriter {
1637 private final List<byte[]> writes = new ArrayList<>();
1638 private volatile boolean closed = false;
1639
1640 @Override
1641 public void write(final Slice slice) {
1642 if (closed) {
1643 return;
1644 }
1645 final byte[] data = slice.data();
1646 final byte[] dataCopy = new byte[data.length];
1647 System.arraycopy(data, 0, dataCopy, 0, data.length);
1648 writes.add(dataCopy);
1649 }
1650
1651 @Override
1652 public void closeWriter() {
1653 closed = true;
1654 }
1655
1656 @Override
1657 public long getFileSize() {
1658 long size = 0;
1659 for (int i = 0; i < writes.size(); i++) {
1660 size += writes.get(i).length;
1661 }
1662 return size;
1663 }
1664
1665 public List<byte[]> getWrites() {
1666 return writes;
1667 }
1668 }
1669 }