]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/java/src/test/java/org/rocksdb/WriteBatchWithIndexTest.java
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / rocksdb / java / src / test / java / org / rocksdb / WriteBatchWithIndexTest.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 //
6 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7 // Use of this source code is governed by a BSD-style license that can be
8 // found in the LICENSE file. See the AUTHORS file for names of contributors.
9
10 package org.rocksdb;
11
12 import static java.nio.charset.StandardCharsets.UTF_8;
13 import static org.assertj.core.api.Assertions.assertThat;
14
15 import java.nio.ByteBuffer;
16 import java.util.Arrays;
17 import org.junit.ClassRule;
18 import org.junit.Rule;
19 import org.junit.Test;
20 import org.junit.rules.TemporaryFolder;
21
22 public class WriteBatchWithIndexTest {
23
24 @ClassRule
25 public static final RocksNativeLibraryResource ROCKS_NATIVE_LIBRARY_RESOURCE =
26 new RocksNativeLibraryResource();
27
28 @Rule
29 public TemporaryFolder dbFolder = new TemporaryFolder();
30
31 @Test
32 public void readYourOwnWrites() throws RocksDBException {
33 try (final Options options = new Options().setCreateIfMissing(true);
34 final RocksDB db = RocksDB.open(options,
35 dbFolder.getRoot().getAbsolutePath())) {
36
37 final byte[] k1 = "key1".getBytes();
38 final byte[] v1 = "value1".getBytes();
39 final byte[] k2 = "key2".getBytes();
40 final byte[] v2 = "value2".getBytes();
41
42 db.put(k1, v1);
43 db.put(k2, v2);
44
45 try (final WriteBatchWithIndex wbwi = new WriteBatchWithIndex(true);
46 final RocksIterator base = db.newIterator();
47 final RocksIterator it = wbwi.newIteratorWithBase(base)) {
48 it.seek(k1);
49 assertThat(it.isValid()).isTrue();
50 assertThat(it.key()).isEqualTo(k1);
51 assertThat(it.value()).isEqualTo(v1);
52
53 it.seek(k2);
54 assertThat(it.isValid()).isTrue();
55 assertThat(it.key()).isEqualTo(k2);
56 assertThat(it.value()).isEqualTo(v2);
57
58 //put data to the write batch and make sure we can read it.
59 final byte[] k3 = "key3".getBytes();
60 final byte[] v3 = "value3".getBytes();
61 wbwi.put(k3, v3);
62 it.seek(k3);
63 assertThat(it.isValid()).isTrue();
64 assertThat(it.key()).isEqualTo(k3);
65 assertThat(it.value()).isEqualTo(v3);
66
67 //update k2 in the write batch and check the value
68 final byte[] v2Other = "otherValue2".getBytes();
69 wbwi.put(k2, v2Other);
70 it.seek(k2);
71 assertThat(it.isValid()).isTrue();
72 assertThat(it.key()).isEqualTo(k2);
73 assertThat(it.value()).isEqualTo(v2Other);
74
75 //delete k1 and make sure we can read back the write
76 wbwi.delete(k1);
77 it.seek(k1);
78 assertThat(it.key()).isNotEqualTo(k1);
79
80 //reinsert k1 and make sure we see the new value
81 final byte[] v1Other = "otherValue1".getBytes();
82 wbwi.put(k1, v1Other);
83 it.seek(k1);
84 assertThat(it.isValid()).isTrue();
85 assertThat(it.key()).isEqualTo(k1);
86 assertThat(it.value()).isEqualTo(v1Other);
87
88 //single remove k3 and make sure we can read back the write
89 wbwi.singleDelete(k3);
90 it.seek(k3);
91 assertThat(it.isValid()).isEqualTo(false);
92
93 //reinsert k3 and make sure we see the new value
94 final byte[] v3Other = "otherValue3".getBytes();
95 wbwi.put(k3, v3Other);
96 it.seek(k3);
97 assertThat(it.isValid()).isTrue();
98 assertThat(it.key()).isEqualTo(k3);
99 assertThat(it.value()).isEqualTo(v3Other);
100 }
101 }
102 }
103
104 @Test
105 public void writeBatchWithIndex() throws RocksDBException {
106 try (final Options options = new Options().setCreateIfMissing(true);
107 final RocksDB db = RocksDB.open(options,
108 dbFolder.getRoot().getAbsolutePath())) {
109
110 final byte[] k1 = "key1".getBytes();
111 final byte[] v1 = "value1".getBytes();
112 final byte[] k2 = "key2".getBytes();
113 final byte[] v2 = "value2".getBytes();
114
115 try (final WriteBatchWithIndex wbwi = new WriteBatchWithIndex();
116 final WriteOptions wOpt = new WriteOptions()) {
117 wbwi.put(k1, v1);
118 wbwi.put(k2, v2);
119
120 db.write(wOpt, wbwi);
121 }
122
123 assertThat(db.get(k1)).isEqualTo(v1);
124 assertThat(db.get(k2)).isEqualTo(v2);
125 }
126 }
127
128 @Test
129 public void write_writeBatchWithIndexDirect() throws RocksDBException {
130 try (final Options options = new Options().setCreateIfMissing(true);
131 final RocksDB db = RocksDB.open(options, dbFolder.getRoot().getAbsolutePath())) {
132 ByteBuffer k1 = ByteBuffer.allocateDirect(16);
133 ByteBuffer v1 = ByteBuffer.allocateDirect(16);
134 ByteBuffer k2 = ByteBuffer.allocateDirect(16);
135 ByteBuffer v2 = ByteBuffer.allocateDirect(16);
136 k1.put("key1".getBytes()).flip();
137 v1.put("value1".getBytes()).flip();
138 k2.put("key2".getBytes()).flip();
139 v2.put("value2".getBytes()).flip();
140
141 try (final WriteBatchWithIndex wbwi = new WriteBatchWithIndex()) {
142 wbwi.put(k1, v1);
143 assertThat(k1.position()).isEqualTo(4);
144 assertThat(k1.limit()).isEqualTo(4);
145 assertThat(v1.position()).isEqualTo(6);
146 assertThat(v1.limit()).isEqualTo(6);
147
148 wbwi.put(k2, v2);
149
150 db.write(new WriteOptions(), wbwi);
151 }
152
153 assertThat(db.get("key1".getBytes())).isEqualTo("value1".getBytes());
154 assertThat(db.get("key2".getBytes())).isEqualTo("value2".getBytes());
155 }
156 }
157
158 @Test
159 public void iterator() throws RocksDBException {
160 try (final WriteBatchWithIndex wbwi = new WriteBatchWithIndex(true)) {
161
162 final String k1 = "key1";
163 final String v1 = "value1";
164 final String k2 = "key2";
165 final String v2 = "value2";
166 final String k3 = "key3";
167 final String v3 = "value3";
168 final String k4 = "key4";
169 final String k5 = "key5";
170 final String k6 = "key6";
171 final String k7 = "key7";
172 final String v8 = "value8";
173 final byte[] k1b = k1.getBytes(UTF_8);
174 final byte[] v1b = v1.getBytes(UTF_8);
175 final byte[] k2b = k2.getBytes(UTF_8);
176 final byte[] v2b = v2.getBytes(UTF_8);
177 final byte[] k3b = k3.getBytes(UTF_8);
178 final byte[] v3b = v3.getBytes(UTF_8);
179 final byte[] k4b = k4.getBytes(UTF_8);
180 final byte[] k5b = k5.getBytes(UTF_8);
181 final byte[] k6b = k6.getBytes(UTF_8);
182 final byte[] k7b = k7.getBytes(UTF_8);
183 final byte[] v8b = v8.getBytes(UTF_8);
184
185 // add put records
186 wbwi.put(k1b, v1b);
187 wbwi.put(k2b, v2b);
188 wbwi.put(k3b, v3b);
189
190 // add a deletion record
191 wbwi.delete(k4b);
192
193 // add a single deletion record
194 wbwi.singleDelete(k5b);
195
196 // add a log record
197 wbwi.putLogData(v8b);
198
199 final WBWIRocksIterator.WriteEntry[] expected = {
200 new WBWIRocksIterator.WriteEntry(WBWIRocksIterator.WriteType.PUT,
201 new DirectSlice(k1), new DirectSlice(v1)),
202 new WBWIRocksIterator.WriteEntry(WBWIRocksIterator.WriteType.PUT,
203 new DirectSlice(k2), new DirectSlice(v2)),
204 new WBWIRocksIterator.WriteEntry(WBWIRocksIterator.WriteType.PUT,
205 new DirectSlice(k3), new DirectSlice(v3)),
206 new WBWIRocksIterator.WriteEntry(WBWIRocksIterator.WriteType.DELETE,
207 new DirectSlice(k4), DirectSlice.NONE),
208 new WBWIRocksIterator.WriteEntry(WBWIRocksIterator.WriteType.SINGLE_DELETE,
209 new DirectSlice(k5), DirectSlice.NONE),
210 };
211
212 try (final WBWIRocksIterator it = wbwi.newIterator()) {
213 //direct access - seek to key offsets
214 final int[] testOffsets = {2, 0, 3, 4, 1};
215
216 for (int i = 0; i < testOffsets.length; i++) {
217 final int testOffset = testOffsets[i];
218 final byte[] key = toArray(expected[testOffset].getKey().data());
219
220 it.seek(key);
221 assertThat(it.isValid()).isTrue();
222
223 final WBWIRocksIterator.WriteEntry entry = it.entry();
224 assertThat(entry).isEqualTo(expected[testOffset]);
225
226 // Direct buffer seek
227 expected[testOffset].getKey().data().mark();
228 ByteBuffer db = expected[testOffset].getKey().data();
229 it.seek(db);
230 assertThat(db.position()).isEqualTo(key.length);
231 assertThat(it.isValid()).isTrue();
232 }
233
234 //forward iterative access
235 int i = 0;
236 for (it.seekToFirst(); it.isValid(); it.next()) {
237 assertThat(it.entry()).isEqualTo(expected[i++]);
238 }
239
240 //reverse iterative access
241 i = expected.length - 1;
242 for (it.seekToLast(); it.isValid(); it.prev()) {
243 assertThat(it.entry()).isEqualTo(expected[i--]);
244 }
245 }
246 }
247 }
248
249 @Test
250 public void zeroByteTests() throws RocksDBException {
251 try (final WriteBatchWithIndex wbwi = new WriteBatchWithIndex(true)) {
252 final byte[] zeroByteValue = new byte[]{0, 0};
253 //add zero byte value
254 wbwi.put(zeroByteValue, zeroByteValue);
255
256 final ByteBuffer buffer = ByteBuffer.allocateDirect(zeroByteValue.length);
257 buffer.put(zeroByteValue);
258
259 final WBWIRocksIterator.WriteEntry expected =
260 new WBWIRocksIterator.WriteEntry(WBWIRocksIterator.WriteType.PUT,
261 new DirectSlice(buffer, zeroByteValue.length),
262 new DirectSlice(buffer, zeroByteValue.length));
263
264 try (final WBWIRocksIterator it = wbwi.newIterator()) {
265 it.seekToFirst();
266 final WBWIRocksIterator.WriteEntry actual = it.entry();
267 assertThat(actual.equals(expected)).isTrue();
268 assertThat(it.entry().hashCode() == expected.hashCode()).isTrue();
269 }
270 }
271 }
272
273 @Test
274 public void savePoints() throws RocksDBException {
275 try (final Options options = new Options().setCreateIfMissing(true);
276 final RocksDB db = RocksDB.open(options,
277 dbFolder.getRoot().getAbsolutePath())) {
278 try (final WriteBatchWithIndex wbwi = new WriteBatchWithIndex(true);
279 final ReadOptions readOptions = new ReadOptions()) {
280 wbwi.put("k1".getBytes(), "v1".getBytes());
281 wbwi.put("k2".getBytes(), "v2".getBytes());
282 wbwi.put("k3".getBytes(), "v3".getBytes());
283
284 assertThat(getFromWriteBatchWithIndex(db, readOptions, wbwi, "k1"))
285 .isEqualTo("v1");
286 assertThat(getFromWriteBatchWithIndex(db, readOptions, wbwi, "k2"))
287 .isEqualTo("v2");
288 assertThat(getFromWriteBatchWithIndex(db, readOptions, wbwi, "k3"))
289 .isEqualTo("v3");
290
291
292 wbwi.setSavePoint();
293
294 wbwi.delete("k2".getBytes());
295 wbwi.put("k3".getBytes(), "v3-2".getBytes());
296
297 assertThat(getFromWriteBatchWithIndex(db, readOptions, wbwi, "k2"))
298 .isNull();
299 assertThat(getFromWriteBatchWithIndex(db, readOptions, wbwi, "k3"))
300 .isEqualTo("v3-2");
301
302
303 wbwi.setSavePoint();
304
305 wbwi.put("k3".getBytes(), "v3-3".getBytes());
306 wbwi.put("k4".getBytes(), "v4".getBytes());
307
308 assertThat(getFromWriteBatchWithIndex(db, readOptions, wbwi, "k3"))
309 .isEqualTo("v3-3");
310 assertThat(getFromWriteBatchWithIndex(db, readOptions, wbwi, "k4"))
311 .isEqualTo("v4");
312
313
314 wbwi.rollbackToSavePoint();
315
316 assertThat(getFromWriteBatchWithIndex(db, readOptions, wbwi, "k2"))
317 .isNull();
318 assertThat(getFromWriteBatchWithIndex(db, readOptions, wbwi, "k3"))
319 .isEqualTo("v3-2");
320 assertThat(getFromWriteBatchWithIndex(db, readOptions, wbwi, "k4"))
321 .isNull();
322
323
324 wbwi.rollbackToSavePoint();
325
326 assertThat(getFromWriteBatchWithIndex(db, readOptions, wbwi, "k1"))
327 .isEqualTo("v1");
328 assertThat(getFromWriteBatchWithIndex(db, readOptions, wbwi, "k2"))
329 .isEqualTo("v2");
330 assertThat(getFromWriteBatchWithIndex(db, readOptions, wbwi, "k3"))
331 .isEqualTo("v3");
332 assertThat(getFromWriteBatchWithIndex(db, readOptions, wbwi, "k4"))
333 .isNull();
334 }
335 }
336 }
337
338 @Test
339 public void restorePoints() throws RocksDBException {
340 try (final WriteBatchWithIndex wbwi = new WriteBatchWithIndex()) {
341
342 wbwi.put("k1".getBytes(UTF_8), "v1".getBytes(UTF_8));
343 wbwi.put("k2".getBytes(UTF_8), "v2".getBytes(UTF_8));
344
345 wbwi.setSavePoint();
346
347 wbwi.put("k1".getBytes(UTF_8), "123456789".getBytes(UTF_8));
348 wbwi.delete("k2".getBytes(UTF_8));
349
350 wbwi.rollbackToSavePoint();
351
352 try(final DBOptions options = new DBOptions()) {
353 assertThat(wbwi.getFromBatch(options,"k1".getBytes(UTF_8))).isEqualTo("v1".getBytes());
354 assertThat(wbwi.getFromBatch(options,"k2".getBytes(UTF_8))).isEqualTo("v2".getBytes());
355 }
356 }
357 }
358
359 @Test(expected = RocksDBException.class)
360 public void restorePoints_withoutSavePoints() throws RocksDBException {
361 try (final WriteBatchWithIndex wbwi = new WriteBatchWithIndex()) {
362 wbwi.rollbackToSavePoint();
363 }
364 }
365
366 @Test(expected = RocksDBException.class)
367 public void restorePoints_withoutSavePoints_nested() throws RocksDBException {
368 try (final WriteBatchWithIndex wbwi = new WriteBatchWithIndex()) {
369
370 wbwi.setSavePoint();
371 wbwi.rollbackToSavePoint();
372
373 // without previous corresponding setSavePoint
374 wbwi.rollbackToSavePoint();
375 }
376 }
377
378 @Test
379 public void popSavePoint() throws RocksDBException {
380 try (final WriteBatchWithIndex wbwi = new WriteBatchWithIndex()) {
381
382 wbwi.put("k1".getBytes(), "v1".getBytes());
383 wbwi.put("k2".getBytes(), "v2".getBytes());
384
385 wbwi.setSavePoint();
386
387 wbwi.put("k1".getBytes(), "123456789".getBytes());
388 wbwi.delete("k2".getBytes());
389
390 wbwi.setSavePoint();
391
392 wbwi.popSavePoint();
393
394 wbwi.rollbackToSavePoint();
395
396 try(final DBOptions options = new DBOptions()) {
397 assertThat(wbwi.getFromBatch(options,"k1".getBytes(UTF_8))).isEqualTo("v1".getBytes());
398 assertThat(wbwi.getFromBatch(options,"k2".getBytes(UTF_8))).isEqualTo("v2".getBytes());
399 }
400 }
401 }
402
403 @Test(expected = RocksDBException.class)
404 public void popSavePoint_withoutSavePoints() throws RocksDBException {
405 try (final WriteBatchWithIndex wbwi = new WriteBatchWithIndex()) {
406 wbwi.popSavePoint();
407 }
408 }
409
410 @Test(expected = RocksDBException.class)
411 public void popSavePoint_withoutSavePoints_nested() throws RocksDBException {
412 try (final WriteBatchWithIndex wbwi = new WriteBatchWithIndex()) {
413
414 wbwi.setSavePoint();
415 wbwi.popSavePoint();
416
417 // without previous corresponding setSavePoint
418 wbwi.popSavePoint();
419 }
420 }
421
422 @Test
423 public void maxBytes() throws RocksDBException {
424 try (final WriteBatchWithIndex wbwi = new WriteBatchWithIndex()) {
425 wbwi.setMaxBytes(19);
426
427 wbwi.put("k1".getBytes(), "v1".getBytes());
428 }
429 }
430
431 @Test(expected = RocksDBException.class)
432 public void maxBytes_over() throws RocksDBException {
433 try (final WriteBatchWithIndex wbwi = new WriteBatchWithIndex()) {
434 wbwi.setMaxBytes(1);
435
436 wbwi.put("k1".getBytes(), "v1".getBytes());
437 }
438 }
439
440 @Test
441 public void getWriteBatch() {
442 try (final WriteBatchWithIndex wbwi = new WriteBatchWithIndex()) {
443
444 final WriteBatch wb = wbwi.getWriteBatch();
445 assertThat(wb).isNotNull();
446 assertThat(wb.isOwningHandle()).isFalse();
447 }
448 }
449
450 private static String getFromWriteBatchWithIndex(final RocksDB db,
451 final ReadOptions readOptions, final WriteBatchWithIndex wbwi,
452 final String skey) {
453 final byte[] key = skey.getBytes();
454 try (final RocksIterator baseIterator = db.newIterator(readOptions);
455 final RocksIterator iterator = wbwi.newIteratorWithBase(baseIterator)) {
456 iterator.seek(key);
457
458 // Arrays.equals(key, iterator.key()) ensures an exact match in Rocks,
459 // instead of a nearest match
460 return iterator.isValid() &&
461 Arrays.equals(key, iterator.key()) ?
462 new String(iterator.value()) : null;
463 }
464 }
465
466 @Test
467 public void getFromBatch() throws RocksDBException {
468 final byte[] k1 = "k1".getBytes();
469 final byte[] k2 = "k2".getBytes();
470 final byte[] k3 = "k3".getBytes();
471 final byte[] k4 = "k4".getBytes();
472
473 final byte[] v1 = "v1".getBytes();
474 final byte[] v2 = "v2".getBytes();
475 final byte[] v3 = "v3".getBytes();
476
477 try (final WriteBatchWithIndex wbwi = new WriteBatchWithIndex(true);
478 final DBOptions dbOptions = new DBOptions()) {
479 wbwi.put(k1, v1);
480 wbwi.put(k2, v2);
481 wbwi.put(k3, v3);
482
483 assertThat(wbwi.getFromBatch(dbOptions, k1)).isEqualTo(v1);
484 assertThat(wbwi.getFromBatch(dbOptions, k2)).isEqualTo(v2);
485 assertThat(wbwi.getFromBatch(dbOptions, k3)).isEqualTo(v3);
486 assertThat(wbwi.getFromBatch(dbOptions, k4)).isNull();
487
488 wbwi.delete(k2);
489
490 assertThat(wbwi.getFromBatch(dbOptions, k2)).isNull();
491 }
492 }
493
494 @Test
495 public void getFromBatchAndDB() throws RocksDBException {
496 final byte[] k1 = "k1".getBytes();
497 final byte[] k2 = "k2".getBytes();
498 final byte[] k3 = "k3".getBytes();
499 final byte[] k4 = "k4".getBytes();
500
501 final byte[] v1 = "v1".getBytes();
502 final byte[] v2 = "v2".getBytes();
503 final byte[] v3 = "v3".getBytes();
504 final byte[] v4 = "v4".getBytes();
505
506 try (final Options options = new Options().setCreateIfMissing(true);
507 final RocksDB db = RocksDB.open(options,
508 dbFolder.getRoot().getAbsolutePath())) {
509
510 db.put(k1, v1);
511 db.put(k2, v2);
512 db.put(k4, v4);
513
514 try (final WriteBatchWithIndex wbwi = new WriteBatchWithIndex(true);
515 final DBOptions dbOptions = new DBOptions();
516 final ReadOptions readOptions = new ReadOptions()) {
517
518 assertThat(wbwi.getFromBatch(dbOptions, k1)).isNull();
519 assertThat(wbwi.getFromBatch(dbOptions, k2)).isNull();
520 assertThat(wbwi.getFromBatch(dbOptions, k4)).isNull();
521
522 wbwi.put(k3, v3);
523
524 assertThat(wbwi.getFromBatch(dbOptions, k3)).isEqualTo(v3);
525
526 assertThat(wbwi.getFromBatchAndDB(db, readOptions, k1)).isEqualTo(v1);
527 assertThat(wbwi.getFromBatchAndDB(db, readOptions, k2)).isEqualTo(v2);
528 assertThat(wbwi.getFromBatchAndDB(db, readOptions, k3)).isEqualTo(v3);
529 assertThat(wbwi.getFromBatchAndDB(db, readOptions, k4)).isEqualTo(v4);
530
531 wbwi.delete(k4);
532
533 assertThat(wbwi.getFromBatchAndDB(db, readOptions, k4)).isNull();
534 }
535 }
536 }
537 private byte[] toArray(final ByteBuffer buf) {
538 final byte[] ary = new byte[buf.remaining()];
539 buf.get(ary);
540 return ary;
541 }
542
543 @Test
544 public void deleteRange() throws RocksDBException {
545 try (final RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath());
546 final WriteBatch batch = new WriteBatch();
547 final WriteOptions wOpt = new WriteOptions()) {
548 db.put("key1".getBytes(), "value".getBytes());
549 db.put("key2".getBytes(), "12345678".getBytes());
550 db.put("key3".getBytes(), "abcdefg".getBytes());
551 db.put("key4".getBytes(), "xyz".getBytes());
552 assertThat(db.get("key1".getBytes())).isEqualTo("value".getBytes());
553 assertThat(db.get("key2".getBytes())).isEqualTo("12345678".getBytes());
554 assertThat(db.get("key3".getBytes())).isEqualTo("abcdefg".getBytes());
555 assertThat(db.get("key4".getBytes())).isEqualTo("xyz".getBytes());
556
557 batch.deleteRange("key2".getBytes(), "key4".getBytes());
558 db.write(wOpt, batch);
559
560 assertThat(db.get("key1".getBytes())).isEqualTo("value".getBytes());
561 assertThat(db.get("key2".getBytes())).isNull();
562 assertThat(db.get("key3".getBytes())).isNull();
563 assertThat(db.get("key4".getBytes())).isEqualTo("xyz".getBytes());
564 }
565 }
566 }