]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
11fdf7f2 TL |
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). | |
7c673cae FG |
5 | package org.rocksdb; |
6 | ||
494da23a | 7 | import org.junit.*; |
11fdf7f2 | 8 | import org.junit.rules.ExpectedException; |
7c673cae FG |
9 | import org.junit.rules.TemporaryFolder; |
10 | ||
494da23a | 11 | import java.nio.ByteBuffer; |
7c673cae FG |
12 | import java.util.*; |
13 | ||
494da23a | 14 | import static java.nio.charset.StandardCharsets.UTF_8; |
7c673cae FG |
15 | import static org.assertj.core.api.Assertions.assertThat; |
16 | import static org.junit.Assert.fail; | |
17 | ||
18 | public class RocksDBTest { | |
19 | ||
20 | @ClassRule | |
f67539c2 TL |
21 | public static final RocksNativeLibraryResource ROCKS_NATIVE_LIBRARY_RESOURCE = |
22 | new RocksNativeLibraryResource(); | |
7c673cae FG |
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 | ||
494da23a TL |
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 | ||
7c673cae FG |
186 | @Test |
187 | public void put() throws RocksDBException { | |
188 | try (final RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath()); | |
f67539c2 | 189 | final WriteOptions opt = new WriteOptions(); final ReadOptions optr = new ReadOptions()) { |
7c673cae FG |
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()); | |
494da23a | 196 | |
f67539c2 TL |
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()); | |
494da23a TL |
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; | |
7c673cae FG |
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 | ||
11fdf7f2 TL |
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 | ||
f67539c2 | 396 | @SuppressWarnings("deprecated") |
7c673cae | 397 | @Test |
f67539c2 | 398 | public void multiGet() throws RocksDBException { |
7c673cae FG |
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 | ||
494da23a | 436 | @Test |
f67539c2 | 437 | public void multiGetAsList() throws RocksDBException { |
494da23a TL |
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 | ||
7c673cae FG |
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()); | |
494da23a TL |
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))); | |
7c673cae FG |
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()); | |
f67539c2 | 517 | db.put("key3".getBytes(), "33".getBytes()); |
7c673cae FG |
518 | assertThat(db.get("key1".getBytes())).isEqualTo( |
519 | "value".getBytes()); | |
520 | assertThat(db.get("key2".getBytes())).isEqualTo( | |
521 | "12345678".getBytes()); | |
f67539c2 | 522 | assertThat(db.get("key3".getBytes())).isEqualTo("33".getBytes()); |
7c673cae FG |
523 | db.delete("key1".getBytes()); |
524 | db.delete(wOpt, "key2".getBytes()); | |
f67539c2 TL |
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 | ||
7c673cae FG |
531 | assertThat(db.get("key1".getBytes())).isNull(); |
532 | assertThat(db.get("key2".getBytes())).isNull(); | |
494da23a | 533 | |
494da23a TL |
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(); | |
7c673cae FG |
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 { | |
494da23a | 577 | try (final RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath())) { |
7c673cae FG |
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)); | |
f67539c2 TL |
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 | } | |
7c673cae FG |
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)) { | |
f67539c2 TL |
832 | try (final CompactRangeOptions compactRangeOpts = new CompactRangeOptions() |
833 | .setChangeLevel(true) | |
834 | .setTargetLevel(-1) | |
835 | .setTargetPathId(0)) { | |
7c673cae FG |
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(), | |
f67539c2 | 844 | "201".getBytes(), compactRangeOpts); |
7c673cae FG |
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 | ||
f67539c2 TL |
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 | ||
7c673cae FG |
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 | ||
20effc67 TL |
1087 | @Test |
1088 | public void continueBackgroundWorkAfterCancelAllBackgroundWork() throws RocksDBException { | |
1089 | final int KEY_SIZE = 20; | |
1090 | final int VALUE_SIZE = 300; | |
1091 | try (final DBOptions opt = new DBOptions(). | |
1092 | setCreateIfMissing(true). | |
1093 | setCreateMissingColumnFamilies(true); | |
1094 | final ColumnFamilyOptions new_cf_opts = new ColumnFamilyOptions() | |
1095 | ) { | |
1096 | final List<ColumnFamilyDescriptor> columnFamilyDescriptors = | |
1097 | Arrays.asList( | |
1098 | new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY), | |
1099 | new ColumnFamilyDescriptor("new_cf".getBytes(), new_cf_opts) | |
1100 | ); | |
1101 | ||
1102 | final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>(); | |
1103 | // open the database | |
1104 | try (final RocksDB db = RocksDB.open(opt, | |
1105 | dbFolder.getRoot().getAbsolutePath(), | |
1106 | columnFamilyDescriptors, | |
1107 | columnFamilyHandles)) { | |
1108 | try { | |
1109 | db.cancelAllBackgroundWork(true); | |
1110 | try { | |
1111 | db.put(new byte[KEY_SIZE], new byte[VALUE_SIZE]); | |
1112 | db.flush(new FlushOptions().setWaitForFlush(true)); | |
1113 | fail("Expected RocksDBException to be thrown if we attempt to trigger a flush after" + | |
1114 | " all background work is cancelled."); | |
1115 | } catch (RocksDBException ignored) { } | |
1116 | } finally { | |
1117 | for (final ColumnFamilyHandle handle : columnFamilyHandles) { | |
1118 | handle.close(); | |
1119 | } | |
1120 | } | |
1121 | } | |
1122 | } | |
1123 | } | |
1124 | ||
1125 | @Test | |
1126 | public void cancelAllBackgroundWorkTwice() throws RocksDBException { | |
1127 | try (final Options options = new Options().setCreateIfMissing(true); | |
1128 | final RocksDB db = RocksDB.open(options, | |
1129 | dbFolder.getRoot().getAbsolutePath()) | |
1130 | ) { | |
1131 | // Cancel all background work synchronously | |
1132 | db.cancelAllBackgroundWork(true); | |
1133 | // Cancel all background work asynchronously | |
1134 | db.cancelAllBackgroundWork(false); | |
1135 | } | |
1136 | } | |
1137 | ||
7c673cae FG |
1138 | @Test |
1139 | public void pauseContinueBackgroundWork() throws RocksDBException { | |
1140 | try (final Options options = new Options().setCreateIfMissing(true); | |
1141 | final RocksDB db = RocksDB.open(options, | |
1142 | dbFolder.getRoot().getAbsolutePath()) | |
1143 | ) { | |
1144 | db.pauseBackgroundWork(); | |
1145 | db.continueBackgroundWork(); | |
1146 | db.pauseBackgroundWork(); | |
1147 | db.continueBackgroundWork(); | |
1148 | } | |
1149 | } | |
1150 | ||
1151 | @Test | |
1152 | public void enableDisableFileDeletions() throws RocksDBException { | |
1153 | try (final Options options = new Options().setCreateIfMissing(true); | |
1154 | final RocksDB db = RocksDB.open(options, | |
1155 | dbFolder.getRoot().getAbsolutePath()) | |
1156 | ) { | |
1157 | db.disableFileDeletions(); | |
1158 | db.enableFileDeletions(false); | |
1159 | db.disableFileDeletions(); | |
1160 | db.enableFileDeletions(true); | |
1161 | } | |
1162 | } | |
1163 | ||
1164 | @Test | |
1165 | public void setOptions() throws RocksDBException { | |
1166 | try (final DBOptions options = new DBOptions() | |
1167 | .setCreateIfMissing(true) | |
1168 | .setCreateMissingColumnFamilies(true); | |
1169 | final ColumnFamilyOptions new_cf_opts = new ColumnFamilyOptions() | |
1170 | .setWriteBufferSize(4096)) { | |
1171 | ||
1172 | final List<ColumnFamilyDescriptor> columnFamilyDescriptors = | |
1173 | Arrays.asList( | |
1174 | new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY), | |
1175 | new ColumnFamilyDescriptor("new_cf".getBytes(), new_cf_opts)); | |
1176 | ||
1177 | // open database | |
1178 | final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>(); | |
1179 | try (final RocksDB db = RocksDB.open(options, | |
1180 | dbFolder.getRoot().getAbsolutePath(), columnFamilyDescriptors, columnFamilyHandles)) { | |
1181 | try { | |
1182 | final MutableColumnFamilyOptions mutableOptions = | |
1183 | MutableColumnFamilyOptions.builder() | |
1184 | .setWriteBufferSize(2048) | |
1185 | .build(); | |
1186 | ||
1187 | db.setOptions(columnFamilyHandles.get(1), mutableOptions); | |
1188 | ||
1189 | } finally { | |
1190 | for (final ColumnFamilyHandle handle : columnFamilyHandles) { | |
1191 | handle.close(); | |
1192 | } | |
1193 | } | |
1194 | } | |
1195 | } | |
1196 | } | |
11fdf7f2 TL |
1197 | |
1198 | @Test | |
1199 | public void destroyDB() throws RocksDBException { | |
1200 | try (final Options options = new Options().setCreateIfMissing(true)) { | |
1201 | String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1202 | try (final RocksDB db = RocksDB.open(options, dbPath)) { | |
1203 | db.put("key1".getBytes(), "value".getBytes()); | |
1204 | } | |
f67539c2 TL |
1205 | assertThat(dbFolder.getRoot().exists() && dbFolder.getRoot().listFiles().length != 0) |
1206 | .isTrue(); | |
11fdf7f2 | 1207 | RocksDB.destroyDB(dbPath, options); |
f67539c2 TL |
1208 | assertThat(dbFolder.getRoot().exists() && dbFolder.getRoot().listFiles().length != 0) |
1209 | .isFalse(); | |
11fdf7f2 TL |
1210 | } |
1211 | } | |
1212 | ||
1213 | @Test(expected = RocksDBException.class) | |
1214 | public void destroyDBFailIfOpen() throws RocksDBException { | |
1215 | try (final Options options = new Options().setCreateIfMissing(true)) { | |
1216 | String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1217 | try (final RocksDB db = RocksDB.open(options, dbPath)) { | |
1218 | // Fails as the db is open and locked. | |
1219 | RocksDB.destroyDB(dbPath, options); | |
1220 | } | |
1221 | } | |
1222 | } | |
494da23a | 1223 | |
494da23a TL |
1224 | @Test |
1225 | public void getApproximateSizes() throws RocksDBException { | |
1226 | final byte key1[] = "key1".getBytes(UTF_8); | |
1227 | final byte key2[] = "key2".getBytes(UTF_8); | |
1228 | final byte key3[] = "key3".getBytes(UTF_8); | |
1229 | try (final Options options = new Options().setCreateIfMissing(true)) { | |
1230 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1231 | try (final RocksDB db = RocksDB.open(options, dbPath)) { | |
1232 | db.put(key1, key1); | |
1233 | db.put(key2, key2); | |
1234 | db.put(key3, key3); | |
1235 | ||
1236 | final long[] sizes = db.getApproximateSizes( | |
1237 | Arrays.asList( | |
20effc67 | 1238 | new Range(new Slice(key1), new Slice(key1)), |
494da23a TL |
1239 | new Range(new Slice(key2), new Slice(key3)) |
1240 | ), | |
1241 | SizeApproximationFlag.INCLUDE_FILES, | |
1242 | SizeApproximationFlag.INCLUDE_MEMTABLES); | |
1243 | ||
1244 | assertThat(sizes.length).isEqualTo(2); | |
1245 | assertThat(sizes[0]).isEqualTo(0); | |
1246 | assertThat(sizes[1]).isGreaterThanOrEqualTo(1); | |
1247 | } | |
1248 | } | |
1249 | } | |
1250 | ||
1251 | @Test | |
1252 | public void getApproximateMemTableStats() throws RocksDBException { | |
1253 | final byte key1[] = "key1".getBytes(UTF_8); | |
1254 | final byte key2[] = "key2".getBytes(UTF_8); | |
1255 | final byte key3[] = "key3".getBytes(UTF_8); | |
1256 | try (final Options options = new Options().setCreateIfMissing(true)) { | |
1257 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1258 | try (final RocksDB db = RocksDB.open(options, dbPath)) { | |
1259 | db.put(key1, key1); | |
1260 | db.put(key2, key2); | |
1261 | db.put(key3, key3); | |
1262 | ||
1263 | final RocksDB.CountAndSize stats = | |
1264 | db.getApproximateMemTableStats( | |
1265 | new Range(new Slice(key1), new Slice(key3))); | |
1266 | ||
1267 | assertThat(stats).isNotNull(); | |
1268 | assertThat(stats.count).isGreaterThan(1); | |
1269 | assertThat(stats.size).isGreaterThan(1); | |
1270 | } | |
1271 | } | |
1272 | } | |
1273 | ||
1274 | @Ignore("TODO(AR) re-enable when ready!") | |
1275 | @Test | |
1276 | public void compactFiles() throws RocksDBException { | |
1277 | final int kTestKeySize = 16; | |
1278 | final int kTestValueSize = 984; | |
1279 | final int kEntrySize = kTestKeySize + kTestValueSize; | |
1280 | final int kEntriesPerBuffer = 100; | |
1281 | final int writeBufferSize = kEntrySize * kEntriesPerBuffer; | |
1282 | final byte[] cfName = "pikachu".getBytes(UTF_8); | |
1283 | ||
1284 | try (final Options options = new Options() | |
1285 | .setCreateIfMissing(true) | |
1286 | .setWriteBufferSize(writeBufferSize) | |
1287 | .setCompactionStyle(CompactionStyle.LEVEL) | |
1288 | .setTargetFileSizeBase(writeBufferSize) | |
1289 | .setMaxBytesForLevelBase(writeBufferSize * 2) | |
1290 | .setLevel0StopWritesTrigger(2) | |
1291 | .setMaxBytesForLevelMultiplier(2) | |
1292 | .setCompressionType(CompressionType.NO_COMPRESSION) | |
1293 | .setMaxSubcompactions(4)) { | |
1294 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1295 | try (final RocksDB db = RocksDB.open(options, dbPath); | |
1296 | final ColumnFamilyOptions cfOptions = new ColumnFamilyOptions(options)) { | |
1297 | db.createColumnFamily(new ColumnFamilyDescriptor(cfName, | |
1298 | cfOptions)).close(); | |
1299 | } | |
1300 | ||
1301 | try (final ColumnFamilyOptions cfOptions = new ColumnFamilyOptions(options)) { | |
1302 | final List<ColumnFamilyDescriptor> cfDescriptors = Arrays.asList( | |
1303 | new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY, cfOptions), | |
1304 | new ColumnFamilyDescriptor(cfName, cfOptions) | |
1305 | ); | |
1306 | final List<ColumnFamilyHandle> cfHandles = new ArrayList<>(); | |
1307 | try (final DBOptions dbOptions = new DBOptions(options); | |
1308 | final RocksDB db = RocksDB.open(dbOptions, dbPath, cfDescriptors, | |
1309 | cfHandles); | |
1310 | ) { | |
1311 | try (final FlushOptions flushOptions = new FlushOptions() | |
1312 | .setWaitForFlush(true) | |
1313 | .setAllowWriteStall(true); | |
1314 | final CompactionOptions compactionOptions = new CompactionOptions()) { | |
1315 | final Random rnd = new Random(301); | |
1316 | for (int key = 64 * kEntriesPerBuffer; key >= 0; --key) { | |
1317 | final byte[] value = new byte[kTestValueSize]; | |
1318 | rnd.nextBytes(value); | |
1319 | db.put(cfHandles.get(1), Integer.toString(key).getBytes(UTF_8), | |
1320 | value); | |
1321 | } | |
1322 | db.flush(flushOptions, cfHandles); | |
1323 | ||
1324 | final RocksDB.LiveFiles liveFiles = db.getLiveFiles(); | |
1325 | final List<String> compactedFiles = | |
1326 | db.compactFiles(compactionOptions, cfHandles.get(1), | |
1327 | liveFiles.files, 1, -1, null); | |
1328 | assertThat(compactedFiles).isNotEmpty(); | |
1329 | } finally { | |
1330 | for (final ColumnFamilyHandle cfHandle : cfHandles) { | |
1331 | cfHandle.close(); | |
1332 | } | |
1333 | } | |
1334 | } | |
1335 | } | |
1336 | } | |
1337 | } | |
1338 | ||
1339 | @Test | |
1340 | public void enableAutoCompaction() throws RocksDBException { | |
1341 | try (final DBOptions options = new DBOptions() | |
1342 | .setCreateIfMissing(true)) { | |
1343 | final List<ColumnFamilyDescriptor> cfDescs = Arrays.asList( | |
1344 | new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY) | |
1345 | ); | |
1346 | final List<ColumnFamilyHandle> cfHandles = new ArrayList<>(); | |
1347 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1348 | try (final RocksDB db = RocksDB.open(options, dbPath, cfDescs, cfHandles)) { | |
1349 | try { | |
1350 | db.enableAutoCompaction(cfHandles); | |
1351 | } finally { | |
1352 | for (final ColumnFamilyHandle cfHandle : cfHandles) { | |
1353 | cfHandle.close(); | |
1354 | } | |
1355 | } | |
1356 | } | |
1357 | } | |
1358 | } | |
1359 | ||
1360 | @Test | |
1361 | public void numberLevels() 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 | assertThat(db.numberLevels()).isEqualTo(7); | |
1366 | } | |
1367 | } | |
1368 | } | |
1369 | ||
1370 | @Test | |
1371 | public void maxMemCompactionLevel() throws RocksDBException { | |
1372 | try (final Options options = new Options().setCreateIfMissing(true)) { | |
1373 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1374 | try (final RocksDB db = RocksDB.open(options, dbPath)) { | |
1375 | assertThat(db.maxMemCompactionLevel()).isEqualTo(0); | |
1376 | } | |
1377 | } | |
1378 | } | |
1379 | ||
1380 | @Test | |
1381 | public void level0StopWriteTrigger() throws RocksDBException { | |
1382 | try (final Options options = new Options().setCreateIfMissing(true)) { | |
1383 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1384 | try (final RocksDB db = RocksDB.open(options, dbPath)) { | |
1385 | assertThat(db.level0StopWriteTrigger()).isEqualTo(36); | |
1386 | } | |
1387 | } | |
1388 | } | |
1389 | ||
1390 | @Test | |
1391 | public void getName() throws RocksDBException { | |
1392 | try (final Options options = new Options().setCreateIfMissing(true)) { | |
1393 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1394 | try (final RocksDB db = RocksDB.open(options, dbPath)) { | |
1395 | assertThat(db.getName()).isEqualTo(dbPath); | |
1396 | } | |
1397 | } | |
1398 | } | |
1399 | ||
1400 | @Test | |
1401 | public void getEnv() throws RocksDBException { | |
1402 | try (final Options options = new Options().setCreateIfMissing(true)) { | |
1403 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1404 | try (final RocksDB db = RocksDB.open(options, dbPath)) { | |
1405 | assertThat(db.getEnv()).isEqualTo(Env.getDefault()); | |
1406 | } | |
1407 | } | |
1408 | } | |
1409 | ||
1410 | @Test | |
1411 | public void flush() throws RocksDBException { | |
1412 | try (final Options options = new Options().setCreateIfMissing(true)) { | |
1413 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1414 | try (final RocksDB db = RocksDB.open(options, dbPath); | |
1415 | final FlushOptions flushOptions = new FlushOptions()) { | |
1416 | db.flush(flushOptions); | |
1417 | } | |
1418 | } | |
1419 | } | |
1420 | ||
1421 | @Test | |
1422 | public void flushWal() throws RocksDBException { | |
1423 | try (final Options options = new Options().setCreateIfMissing(true)) { | |
1424 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1425 | try (final RocksDB db = RocksDB.open(options, dbPath)) { | |
1426 | db.flushWal(true); | |
1427 | } | |
1428 | } | |
1429 | } | |
1430 | ||
1431 | @Test | |
1432 | public void syncWal() throws RocksDBException { | |
1433 | try (final Options options = new Options().setCreateIfMissing(true)) { | |
1434 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1435 | try (final RocksDB db = RocksDB.open(options, dbPath)) { | |
1436 | db.syncWal(); | |
1437 | } | |
1438 | } | |
1439 | } | |
1440 | ||
1441 | @Test | |
1442 | public void setPreserveDeletesSequenceNumber() throws RocksDBException { | |
1443 | try (final Options options = new Options().setCreateIfMissing(true)) { | |
1444 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1445 | try (final RocksDB db = RocksDB.open(options, dbPath)) { | |
1446 | assertThat(db.setPreserveDeletesSequenceNumber(db.getLatestSequenceNumber())) | |
1447 | .isFalse(); | |
1448 | } | |
1449 | } | |
1450 | } | |
1451 | ||
1452 | @Test | |
1453 | public void getLiveFiles() throws RocksDBException { | |
1454 | try (final Options options = new Options().setCreateIfMissing(true)) { | |
1455 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1456 | try (final RocksDB db = RocksDB.open(options, dbPath)) { | |
1457 | final RocksDB.LiveFiles livefiles = db.getLiveFiles(true); | |
1458 | assertThat(livefiles).isNotNull(); | |
20effc67 | 1459 | assertThat(livefiles.manifestFileSize).isEqualTo(57); |
494da23a TL |
1460 | assertThat(livefiles.files.size()).isEqualTo(3); |
1461 | assertThat(livefiles.files.get(0)).isEqualTo("/CURRENT"); | |
20effc67 TL |
1462 | assertThat(livefiles.files.get(1)).isEqualTo("/MANIFEST-000003"); |
1463 | assertThat(livefiles.files.get(2)).isEqualTo("/OPTIONS-000006"); | |
494da23a TL |
1464 | } |
1465 | } | |
1466 | } | |
1467 | ||
1468 | @Test | |
1469 | public void getSortedWalFiles() throws RocksDBException { | |
1470 | try (final Options options = new Options().setCreateIfMissing(true)) { | |
1471 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1472 | try (final RocksDB db = RocksDB.open(options, dbPath)) { | |
1473 | db.put("key1".getBytes(UTF_8), "value1".getBytes(UTF_8)); | |
1474 | final List<LogFile> logFiles = db.getSortedWalFiles(); | |
1475 | assertThat(logFiles).isNotNull(); | |
1476 | assertThat(logFiles.size()).isEqualTo(1); | |
1477 | assertThat(logFiles.get(0).type()) | |
1478 | .isEqualTo(WalFileType.kAliveLogFile); | |
1479 | } | |
1480 | } | |
1481 | } | |
1482 | ||
1483 | @Test | |
1484 | public void deleteFile() throws RocksDBException { | |
1485 | try (final Options options = new Options().setCreateIfMissing(true)) { | |
1486 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1487 | try (final RocksDB db = RocksDB.open(options, dbPath)) { | |
1488 | db.deleteFile("unknown"); | |
1489 | } | |
1490 | } | |
1491 | } | |
1492 | ||
1493 | @Test | |
1494 | public void getLiveFilesMetaData() throws RocksDBException { | |
1495 | try (final Options options = new Options().setCreateIfMissing(true)) { | |
1496 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1497 | try (final RocksDB db = RocksDB.open(options, dbPath)) { | |
1498 | db.put("key1".getBytes(UTF_8), "value1".getBytes(UTF_8)); | |
1499 | final List<LiveFileMetaData> liveFilesMetaData | |
1500 | = db.getLiveFilesMetaData(); | |
1501 | assertThat(liveFilesMetaData).isEmpty(); | |
1502 | } | |
1503 | } | |
1504 | } | |
1505 | ||
1506 | @Test | |
1507 | public void getColumnFamilyMetaData() throws RocksDBException { | |
1508 | try (final DBOptions options = new DBOptions() | |
1509 | .setCreateIfMissing(true)) { | |
1510 | final List<ColumnFamilyDescriptor> cfDescs = Arrays.asList( | |
1511 | new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY) | |
1512 | ); | |
1513 | final List<ColumnFamilyHandle> cfHandles = new ArrayList<>(); | |
1514 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1515 | try (final RocksDB db = RocksDB.open(options, dbPath, cfDescs, cfHandles)) { | |
1516 | db.put(cfHandles.get(0), "key1".getBytes(UTF_8), "value1".getBytes(UTF_8)); | |
1517 | try { | |
1518 | final ColumnFamilyMetaData cfMetadata = | |
1519 | db.getColumnFamilyMetaData(cfHandles.get(0)); | |
1520 | assertThat(cfMetadata).isNotNull(); | |
1521 | assertThat(cfMetadata.name()).isEqualTo(RocksDB.DEFAULT_COLUMN_FAMILY); | |
1522 | assertThat(cfMetadata.levels().size()).isEqualTo(7); | |
1523 | } finally { | |
1524 | for (final ColumnFamilyHandle cfHandle : cfHandles) { | |
1525 | cfHandle.close(); | |
1526 | } | |
1527 | } | |
1528 | } | |
1529 | } | |
1530 | } | |
1531 | ||
1532 | @Test | |
1533 | public void verifyChecksum() throws RocksDBException { | |
1534 | try (final Options options = new Options().setCreateIfMissing(true)) { | |
1535 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1536 | try (final RocksDB db = RocksDB.open(options, dbPath)) { | |
1537 | db.verifyChecksum(); | |
1538 | } | |
1539 | } | |
1540 | } | |
1541 | ||
1542 | @Test | |
1543 | public void getPropertiesOfAllTables() throws RocksDBException { | |
1544 | try (final DBOptions options = new DBOptions() | |
1545 | .setCreateIfMissing(true)) { | |
1546 | final List<ColumnFamilyDescriptor> cfDescs = Arrays.asList( | |
1547 | new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY) | |
1548 | ); | |
1549 | final List<ColumnFamilyHandle> cfHandles = new ArrayList<>(); | |
1550 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1551 | try (final RocksDB db = RocksDB.open(options, dbPath, cfDescs, cfHandles)) { | |
1552 | db.put(cfHandles.get(0), "key1".getBytes(UTF_8), "value1".getBytes(UTF_8)); | |
1553 | try { | |
1554 | final Map<String, TableProperties> properties = | |
1555 | db.getPropertiesOfAllTables(cfHandles.get(0)); | |
1556 | assertThat(properties).isNotNull(); | |
1557 | } finally { | |
1558 | for (final ColumnFamilyHandle cfHandle : cfHandles) { | |
1559 | cfHandle.close(); | |
1560 | } | |
1561 | } | |
1562 | } | |
1563 | } | |
1564 | } | |
1565 | ||
1566 | @Test | |
1567 | public void getPropertiesOfTablesInRange() throws RocksDBException { | |
1568 | try (final DBOptions options = new DBOptions() | |
1569 | .setCreateIfMissing(true)) { | |
1570 | final List<ColumnFamilyDescriptor> cfDescs = Arrays.asList( | |
1571 | new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY) | |
1572 | ); | |
1573 | final List<ColumnFamilyHandle> cfHandles = new ArrayList<>(); | |
1574 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1575 | try (final RocksDB db = RocksDB.open(options, dbPath, cfDescs, cfHandles)) { | |
1576 | db.put(cfHandles.get(0), "key1".getBytes(UTF_8), "value1".getBytes(UTF_8)); | |
1577 | db.put(cfHandles.get(0), "key2".getBytes(UTF_8), "value2".getBytes(UTF_8)); | |
1578 | db.put(cfHandles.get(0), "key3".getBytes(UTF_8), "value3".getBytes(UTF_8)); | |
1579 | try { | |
1580 | final Range range = new Range( | |
1581 | new Slice("key1".getBytes(UTF_8)), | |
1582 | new Slice("key3".getBytes(UTF_8))); | |
1583 | final Map<String, TableProperties> properties = | |
1584 | db.getPropertiesOfTablesInRange( | |
1585 | cfHandles.get(0), Arrays.asList(range)); | |
1586 | assertThat(properties).isNotNull(); | |
1587 | } finally { | |
1588 | for (final ColumnFamilyHandle cfHandle : cfHandles) { | |
1589 | cfHandle.close(); | |
1590 | } | |
1591 | } | |
1592 | } | |
1593 | } | |
1594 | } | |
1595 | ||
1596 | @Test | |
1597 | public void suggestCompactRange() throws RocksDBException { | |
1598 | try (final DBOptions options = new DBOptions() | |
1599 | .setCreateIfMissing(true)) { | |
1600 | final List<ColumnFamilyDescriptor> cfDescs = Arrays.asList( | |
1601 | new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY) | |
1602 | ); | |
1603 | final List<ColumnFamilyHandle> cfHandles = new ArrayList<>(); | |
1604 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1605 | try (final RocksDB db = RocksDB.open(options, dbPath, cfDescs, cfHandles)) { | |
1606 | db.put(cfHandles.get(0), "key1".getBytes(UTF_8), "value1".getBytes(UTF_8)); | |
1607 | db.put(cfHandles.get(0), "key2".getBytes(UTF_8), "value2".getBytes(UTF_8)); | |
1608 | db.put(cfHandles.get(0), "key3".getBytes(UTF_8), "value3".getBytes(UTF_8)); | |
1609 | try { | |
1610 | final Range range = db.suggestCompactRange(cfHandles.get(0)); | |
1611 | assertThat(range).isNotNull(); | |
1612 | } finally { | |
1613 | for (final ColumnFamilyHandle cfHandle : cfHandles) { | |
1614 | cfHandle.close(); | |
1615 | } | |
1616 | } | |
1617 | } | |
1618 | } | |
1619 | } | |
1620 | ||
1621 | @Test | |
1622 | public void promoteL0() throws RocksDBException { | |
1623 | try (final Options options = new Options().setCreateIfMissing(true)) { | |
1624 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1625 | try (final RocksDB db = RocksDB.open(options, dbPath)) { | |
1626 | db.promoteL0(2); | |
1627 | } | |
1628 | } | |
1629 | } | |
1630 | ||
1631 | @Test | |
1632 | public void startTrace() throws RocksDBException { | |
1633 | try (final Options options = new Options().setCreateIfMissing(true)) { | |
1634 | final String dbPath = dbFolder.getRoot().getAbsolutePath(); | |
1635 | try (final RocksDB db = RocksDB.open(options, dbPath)) { | |
1636 | final TraceOptions traceOptions = new TraceOptions(); | |
1637 | ||
1638 | try (final InMemoryTraceWriter traceWriter = new InMemoryTraceWriter()) { | |
1639 | db.startTrace(traceOptions, traceWriter); | |
1640 | ||
1641 | db.put("key1".getBytes(UTF_8), "value1".getBytes(UTF_8)); | |
1642 | ||
1643 | db.endTrace(); | |
1644 | ||
1645 | final List<byte[]> writes = traceWriter.getWrites(); | |
1646 | assertThat(writes.size()).isGreaterThan(0); | |
1647 | } | |
1648 | } | |
1649 | } | |
1650 | } | |
1651 | ||
1652 | @Test | |
1653 | public void setDBOptions() throws RocksDBException { | |
1654 | try (final DBOptions options = new DBOptions() | |
1655 | .setCreateIfMissing(true) | |
1656 | .setCreateMissingColumnFamilies(true); | |
1657 | final ColumnFamilyOptions new_cf_opts = new ColumnFamilyOptions() | |
1658 | .setWriteBufferSize(4096)) { | |
1659 | ||
1660 | final List<ColumnFamilyDescriptor> columnFamilyDescriptors = | |
1661 | Arrays.asList( | |
1662 | new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY), | |
1663 | new ColumnFamilyDescriptor("new_cf".getBytes(), new_cf_opts)); | |
1664 | ||
1665 | // open database | |
1666 | final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>(); | |
1667 | try (final RocksDB db = RocksDB.open(options, | |
1668 | dbFolder.getRoot().getAbsolutePath(), columnFamilyDescriptors, columnFamilyHandles)) { | |
1669 | try { | |
1670 | final MutableDBOptions mutableOptions = | |
1671 | MutableDBOptions.builder() | |
1672 | .setBytesPerSync(1024 * 1027 * 7) | |
1673 | .setAvoidFlushDuringShutdown(false) | |
1674 | .build(); | |
1675 | ||
1676 | db.setDBOptions(mutableOptions); | |
1677 | } finally { | |
1678 | for (final ColumnFamilyHandle handle : columnFamilyHandles) { | |
1679 | handle.close(); | |
1680 | } | |
1681 | } | |
1682 | } | |
1683 | } | |
1684 | } | |
1685 | ||
20effc67 TL |
1686 | @Test |
1687 | public void rocksdbVersion() { | |
1688 | final RocksDB.Version version = RocksDB.rocksdbVersion(); | |
1689 | assertThat(version).isNotNull(); | |
1690 | assertThat(version.getMajor()).isGreaterThan(1); | |
1691 | } | |
1692 | ||
494da23a TL |
1693 | private static class InMemoryTraceWriter extends AbstractTraceWriter { |
1694 | private final List<byte[]> writes = new ArrayList<>(); | |
1695 | private volatile boolean closed = false; | |
1696 | ||
1697 | @Override | |
1698 | public void write(final Slice slice) { | |
1699 | if (closed) { | |
1700 | return; | |
1701 | } | |
1702 | final byte[] data = slice.data(); | |
1703 | final byte[] dataCopy = new byte[data.length]; | |
1704 | System.arraycopy(data, 0, dataCopy, 0, data.length); | |
1705 | writes.add(dataCopy); | |
1706 | } | |
1707 | ||
1708 | @Override | |
1709 | public void closeWriter() { | |
1710 | closed = true; | |
1711 | } | |
1712 | ||
1713 | @Override | |
1714 | public long getFileSize() { | |
1715 | long size = 0; | |
1716 | for (int i = 0; i < writes.size(); i++) { | |
1717 | size += writes.get(i).length; | |
1718 | } | |
1719 | return size; | |
1720 | } | |
1721 | ||
1722 | public List<byte[]> getWrites() { | |
1723 | return writes; | |
1724 | } | |
1725 | } | |
7c673cae | 1726 | } |