]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/java/src/test/java/org/rocksdb/WriteBatchTest.java
import 14.2.4 nautilus point release
[ceph.git] / ceph / src / rocksdb / java / src / test / java / org / rocksdb / WriteBatchTest.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 package org.rocksdb;
10
11 import org.junit.ClassRule;
12 import org.junit.Rule;
13 import org.junit.Test;
14 import org.junit.rules.TemporaryFolder;
15 import org.rocksdb.util.CapturingWriteBatchHandler;
16 import org.rocksdb.util.CapturingWriteBatchHandler.Event;
17 import org.rocksdb.util.WriteBatchGetter;
18
19 import static org.assertj.core.api.Assertions.assertThat;
20 import static org.rocksdb.util.CapturingWriteBatchHandler.Action.*;
21 import static java.nio.charset.StandardCharsets.UTF_8;
22
23 /**
24 * This class mimics the db/write_batch_test.cc
25 * in the c++ rocksdb library.
26 */
27 public class WriteBatchTest {
28 @ClassRule
29 public static final RocksMemoryResource rocksMemoryResource =
30 new RocksMemoryResource();
31
32 @Rule
33 public TemporaryFolder dbFolder = new TemporaryFolder();
34
35 @Test
36 public void emptyWriteBatch() {
37 try (final WriteBatch batch = new WriteBatch()) {
38 assertThat(batch.count()).isEqualTo(0);
39 }
40 }
41
42 @Test
43 public void multipleBatchOperations()
44 throws RocksDBException {
45
46 final byte[] foo = "foo".getBytes(UTF_8);
47 final byte[] bar = "bar".getBytes(UTF_8);
48 final byte[] box = "box".getBytes(UTF_8);
49 final byte[] baz = "baz".getBytes(UTF_8);
50 final byte[] boo = "boo".getBytes(UTF_8);
51 final byte[] hoo = "hoo".getBytes(UTF_8);
52 final byte[] hello = "hello".getBytes(UTF_8);
53
54 try (final WriteBatch batch = new WriteBatch()) {
55 batch.put(foo, bar);
56 batch.delete(box);
57 batch.put(baz, boo);
58 batch.merge(baz, hoo);
59 batch.singleDelete(foo);
60 batch.deleteRange(baz, foo);
61 batch.putLogData(hello);
62
63 try(final CapturingWriteBatchHandler handler =
64 new CapturingWriteBatchHandler()) {
65 batch.iterate(handler);
66
67 assertThat(handler.getEvents().size()).isEqualTo(7);
68
69 assertThat(handler.getEvents().get(0)).isEqualTo(new Event(PUT, foo, bar));
70 assertThat(handler.getEvents().get(1)).isEqualTo(new Event(DELETE, box, null));
71 assertThat(handler.getEvents().get(2)).isEqualTo(new Event(PUT, baz, boo));
72 assertThat(handler.getEvents().get(3)).isEqualTo(new Event(MERGE, baz, hoo));
73 assertThat(handler.getEvents().get(4)).isEqualTo(new Event(SINGLE_DELETE, foo, null));
74 assertThat(handler.getEvents().get(5)).isEqualTo(new Event(DELETE_RANGE, baz, foo));
75 assertThat(handler.getEvents().get(6)).isEqualTo(new Event(LOG, null, hello));
76 }
77 }
78 }
79
80 @Test
81 public void testAppendOperation()
82 throws RocksDBException {
83 try (final WriteBatch b1 = new WriteBatch();
84 final WriteBatch b2 = new WriteBatch()) {
85 WriteBatchTestInternalHelper.setSequence(b1, 200);
86 WriteBatchTestInternalHelper.setSequence(b2, 300);
87 WriteBatchTestInternalHelper.append(b1, b2);
88 assertThat(getContents(b1).length).isEqualTo(0);
89 assertThat(b1.count()).isEqualTo(0);
90 b2.put("a".getBytes(UTF_8), "va".getBytes(UTF_8));
91 WriteBatchTestInternalHelper.append(b1, b2);
92 assertThat("Put(a, va)@200".equals(new String(getContents(b1),
93 UTF_8)));
94 assertThat(b1.count()).isEqualTo(1);
95 b2.clear();
96 b2.put("b".getBytes(UTF_8), "vb".getBytes(UTF_8));
97 WriteBatchTestInternalHelper.append(b1, b2);
98 assertThat(("Put(a, va)@200" +
99 "Put(b, vb)@201")
100 .equals(new String(getContents(b1), UTF_8)));
101 assertThat(b1.count()).isEqualTo(2);
102 b2.delete("foo".getBytes(UTF_8));
103 WriteBatchTestInternalHelper.append(b1, b2);
104 assertThat(("Put(a, va)@200" +
105 "Put(b, vb)@202" +
106 "Put(b, vb)@201" +
107 "Delete(foo)@203")
108 .equals(new String(getContents(b1), UTF_8)));
109 assertThat(b1.count()).isEqualTo(4);
110 }
111 }
112
113 @Test
114 public void blobOperation()
115 throws RocksDBException {
116 try (final WriteBatch batch = new WriteBatch()) {
117 batch.put("k1".getBytes(UTF_8), "v1".getBytes(UTF_8));
118 batch.put("k2".getBytes(UTF_8), "v2".getBytes(UTF_8));
119 batch.put("k3".getBytes(UTF_8), "v3".getBytes(UTF_8));
120 batch.putLogData("blob1".getBytes(UTF_8));
121 batch.delete("k2".getBytes(UTF_8));
122 batch.putLogData("blob2".getBytes(UTF_8));
123 batch.merge("foo".getBytes(UTF_8), "bar".getBytes(UTF_8));
124 assertThat(batch.count()).isEqualTo(5);
125 assertThat(("Merge(foo, bar)@4" +
126 "Put(k1, v1)@0" +
127 "Delete(k2)@3" +
128 "Put(k2, v2)@1" +
129 "Put(k3, v3)@2")
130 .equals(new String(getContents(batch), UTF_8)));
131 }
132 }
133
134 @Test
135 public void savePoints()
136 throws RocksDBException {
137 try (final WriteBatch batch = new WriteBatch()) {
138 batch.put("k1".getBytes(UTF_8), "v1".getBytes(UTF_8));
139 batch.put("k2".getBytes(UTF_8), "v2".getBytes(UTF_8));
140 batch.put("k3".getBytes(UTF_8), "v3".getBytes(UTF_8));
141
142 assertThat(getFromWriteBatch(batch, "k1")).isEqualTo("v1");
143 assertThat(getFromWriteBatch(batch, "k2")).isEqualTo("v2");
144 assertThat(getFromWriteBatch(batch, "k3")).isEqualTo("v3");
145
146 batch.setSavePoint();
147
148 batch.delete("k2".getBytes(UTF_8));
149 batch.put("k3".getBytes(UTF_8), "v3-2".getBytes(UTF_8));
150
151 assertThat(getFromWriteBatch(batch, "k2")).isNull();
152 assertThat(getFromWriteBatch(batch, "k3")).isEqualTo("v3-2");
153
154
155 batch.setSavePoint();
156
157 batch.put("k3".getBytes(UTF_8), "v3-3".getBytes(UTF_8));
158 batch.put("k4".getBytes(UTF_8), "v4".getBytes(UTF_8));
159
160 assertThat(getFromWriteBatch(batch, "k3")).isEqualTo("v3-3");
161 assertThat(getFromWriteBatch(batch, "k4")).isEqualTo("v4");
162
163
164 batch.rollbackToSavePoint();
165
166 assertThat(getFromWriteBatch(batch, "k2")).isNull();
167 assertThat(getFromWriteBatch(batch, "k3")).isEqualTo("v3-2");
168 assertThat(getFromWriteBatch(batch, "k4")).isNull();
169
170
171 batch.rollbackToSavePoint();
172
173 assertThat(getFromWriteBatch(batch, "k1")).isEqualTo("v1");
174 assertThat(getFromWriteBatch(batch, "k2")).isEqualTo("v2");
175 assertThat(getFromWriteBatch(batch, "k3")).isEqualTo("v3");
176 assertThat(getFromWriteBatch(batch, "k4")).isNull();
177 }
178 }
179
180 @Test
181 public void deleteRange() throws RocksDBException {
182 try (final RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath());
183 final WriteBatch batch = new WriteBatch();
184 final WriteOptions wOpt = new WriteOptions()) {
185 db.put("key1".getBytes(), "value".getBytes());
186 db.put("key2".getBytes(), "12345678".getBytes());
187 db.put("key3".getBytes(), "abcdefg".getBytes());
188 db.put("key4".getBytes(), "xyz".getBytes());
189 assertThat(db.get("key1".getBytes())).isEqualTo("value".getBytes());
190 assertThat(db.get("key2".getBytes())).isEqualTo("12345678".getBytes());
191 assertThat(db.get("key3".getBytes())).isEqualTo("abcdefg".getBytes());
192 assertThat(db.get("key4".getBytes())).isEqualTo("xyz".getBytes());
193
194 batch.deleteRange("key2".getBytes(), "key4".getBytes());
195 db.write(wOpt, batch);
196
197 assertThat(db.get("key1".getBytes())).isEqualTo("value".getBytes());
198 assertThat(db.get("key2".getBytes())).isNull();
199 assertThat(db.get("key3".getBytes())).isNull();
200 assertThat(db.get("key4".getBytes())).isEqualTo("xyz".getBytes());
201 }
202 }
203
204 @Test
205 public void restorePoints() throws RocksDBException {
206 try (final WriteBatch batch = new WriteBatch()) {
207
208 batch.put("k1".getBytes(), "v1".getBytes());
209 batch.put("k2".getBytes(), "v2".getBytes());
210
211 batch.setSavePoint();
212
213 batch.put("k1".getBytes(), "123456789".getBytes());
214 batch.delete("k2".getBytes());
215
216 batch.rollbackToSavePoint();
217
218 try(final CapturingWriteBatchHandler handler = new CapturingWriteBatchHandler()) {
219 batch.iterate(handler);
220
221 assertThat(handler.getEvents().size()).isEqualTo(2);
222 assertThat(handler.getEvents().get(0)).isEqualTo(new Event(PUT, "k1".getBytes(), "v1".getBytes()));
223 assertThat(handler.getEvents().get(1)).isEqualTo(new Event(PUT, "k2".getBytes(), "v2".getBytes()));
224 }
225 }
226 }
227
228 @Test(expected = RocksDBException.class)
229 public void restorePoints_withoutSavePoints() throws RocksDBException {
230 try (final WriteBatch batch = new WriteBatch()) {
231 batch.rollbackToSavePoint();
232 }
233 }
234
235 @Test(expected = RocksDBException.class)
236 public void restorePoints_withoutSavePoints_nested() throws RocksDBException {
237 try (final WriteBatch batch = new WriteBatch()) {
238
239 batch.setSavePoint();
240 batch.rollbackToSavePoint();
241
242 // without previous corresponding setSavePoint
243 batch.rollbackToSavePoint();
244 }
245 }
246
247 @Test
248 public void popSavePoint() throws RocksDBException {
249 try (final WriteBatch batch = new WriteBatch()) {
250
251 batch.put("k1".getBytes(), "v1".getBytes());
252 batch.put("k2".getBytes(), "v2".getBytes());
253
254 batch.setSavePoint();
255
256 batch.put("k1".getBytes(), "123456789".getBytes());
257 batch.delete("k2".getBytes());
258
259 batch.setSavePoint();
260
261 batch.popSavePoint();
262
263 batch.rollbackToSavePoint();
264
265 try(final CapturingWriteBatchHandler handler = new CapturingWriteBatchHandler()) {
266 batch.iterate(handler);
267
268 assertThat(handler.getEvents().size()).isEqualTo(2);
269 assertThat(handler.getEvents().get(0)).isEqualTo(new Event(PUT, "k1".getBytes(), "v1".getBytes()));
270 assertThat(handler.getEvents().get(1)).isEqualTo(new Event(PUT, "k2".getBytes(), "v2".getBytes()));
271 }
272 }
273 }
274
275 @Test(expected = RocksDBException.class)
276 public void popSavePoint_withoutSavePoints() throws RocksDBException {
277 try (final WriteBatch batch = new WriteBatch()) {
278 batch.popSavePoint();
279 }
280 }
281
282 @Test(expected = RocksDBException.class)
283 public void popSavePoint_withoutSavePoints_nested() throws RocksDBException {
284 try (final WriteBatch batch = new WriteBatch()) {
285
286 batch.setSavePoint();
287 batch.popSavePoint();
288
289 // without previous corresponding setSavePoint
290 batch.popSavePoint();
291 }
292 }
293
294 @Test
295 public void maxBytes() throws RocksDBException {
296 try (final WriteBatch batch = new WriteBatch()) {
297 batch.setMaxBytes(19);
298
299 batch.put("k1".getBytes(), "v1".getBytes());
300 }
301 }
302
303 @Test(expected = RocksDBException.class)
304 public void maxBytes_over() throws RocksDBException {
305 try (final WriteBatch batch = new WriteBatch()) {
306 batch.setMaxBytes(1);
307
308 batch.put("k1".getBytes(), "v1".getBytes());
309 }
310 }
311
312 @Test
313 public void data() throws RocksDBException {
314 try (final WriteBatch batch1 = new WriteBatch()) {
315 batch1.delete("k0".getBytes());
316 batch1.put("k1".getBytes(), "v1".getBytes());
317 batch1.put("k2".getBytes(), "v2".getBytes());
318 batch1.put("k3".getBytes(), "v3".getBytes());
319 batch1.putLogData("log1".getBytes());
320 batch1.merge("k2".getBytes(), "v22".getBytes());
321 batch1.delete("k3".getBytes());
322
323 final byte[] serialized = batch1.data();
324
325 try(final WriteBatch batch2 = new WriteBatch(serialized)) {
326 assertThat(batch2.count()).isEqualTo(batch1.count());
327
328 try(final CapturingWriteBatchHandler handler1 = new CapturingWriteBatchHandler()) {
329 batch1.iterate(handler1);
330
331 try (final CapturingWriteBatchHandler handler2 = new CapturingWriteBatchHandler()) {
332 batch2.iterate(handler2);
333
334 assertThat(handler1.getEvents().equals(handler2.getEvents())).isTrue();
335 }
336 }
337 }
338 }
339 }
340
341 @Test
342 public void dataSize() throws RocksDBException {
343 try (final WriteBatch batch = new WriteBatch()) {
344 batch.put("k1".getBytes(), "v1".getBytes());
345
346 assertThat(batch.getDataSize()).isEqualTo(19);
347 }
348 }
349
350 @Test
351 public void hasPut() throws RocksDBException {
352 try (final WriteBatch batch = new WriteBatch()) {
353 assertThat(batch.hasPut()).isFalse();
354
355 batch.put("k1".getBytes(), "v1".getBytes());
356
357 assertThat(batch.hasPut()).isTrue();
358 }
359 }
360
361 @Test
362 public void hasDelete() throws RocksDBException {
363 try (final WriteBatch batch = new WriteBatch()) {
364 assertThat(batch.hasDelete()).isFalse();
365
366 batch.delete("k1".getBytes());
367
368 assertThat(batch.hasDelete()).isTrue();
369 }
370 }
371
372 @Test
373 public void hasSingleDelete() throws RocksDBException {
374 try (final WriteBatch batch = new WriteBatch()) {
375 assertThat(batch.hasSingleDelete()).isFalse();
376
377 batch.singleDelete("k1".getBytes());
378
379 assertThat(batch.hasSingleDelete()).isTrue();
380 }
381 }
382
383 @Test
384 public void hasDeleteRange() throws RocksDBException {
385 try (final WriteBatch batch = new WriteBatch()) {
386 assertThat(batch.hasDeleteRange()).isFalse();
387
388 batch.deleteRange("k1".getBytes(), "k2".getBytes());
389
390 assertThat(batch.hasDeleteRange()).isTrue();
391 }
392 }
393
394 @Test
395 public void hasBeginPrepareRange() throws RocksDBException {
396 try (final WriteBatch batch = new WriteBatch()) {
397 assertThat(batch.hasBeginPrepare()).isFalse();
398 }
399 }
400
401 @Test
402 public void hasEndPrepareRange() throws RocksDBException {
403 try (final WriteBatch batch = new WriteBatch()) {
404 assertThat(batch.hasEndPrepare()).isFalse();
405 }
406 }
407
408 @Test
409 public void hasCommit() throws RocksDBException {
410 try (final WriteBatch batch = new WriteBatch()) {
411 assertThat(batch.hasCommit()).isFalse();
412 }
413 }
414
415 @Test
416 public void hasRollback() throws RocksDBException {
417 try (final WriteBatch batch = new WriteBatch()) {
418 assertThat(batch.hasRollback()).isFalse();
419 }
420 }
421
422 @Test
423 public void walTerminationPoint() throws RocksDBException {
424 try (final WriteBatch batch = new WriteBatch()) {
425 WriteBatch.SavePoint walTerminationPoint = batch.getWalTerminationPoint();
426 assertThat(walTerminationPoint.isCleared()).isTrue();
427
428 batch.put("k1".getBytes(UTF_8), "v1".getBytes(UTF_8));
429
430 batch.markWalTerminationPoint();
431
432 walTerminationPoint = batch.getWalTerminationPoint();
433 assertThat(walTerminationPoint.getSize()).isEqualTo(19);
434 assertThat(walTerminationPoint.getCount()).isEqualTo(1);
435 assertThat(walTerminationPoint.getContentFlags()).isEqualTo(2);
436 }
437 }
438
439 @Test
440 public void getWriteBatch() {
441 try (final WriteBatch batch = new WriteBatch()) {
442 assertThat(batch.getWriteBatch()).isEqualTo(batch);
443 }
444 }
445
446 static byte[] getContents(final WriteBatch wb) {
447 return getContents(wb.nativeHandle_);
448 }
449
450 static String getFromWriteBatch(final WriteBatch wb, final String key)
451 throws RocksDBException {
452 final WriteBatchGetter getter =
453 new WriteBatchGetter(key.getBytes(UTF_8));
454 wb.iterate(getter);
455 if(getter.getValue() != null) {
456 return new String(getter.getValue(), UTF_8);
457 } else {
458 return null;
459 }
460 }
461
462 private static native byte[] getContents(final long writeBatchHandle);
463 }
464
465 /**
466 * Package-private class which provides java api to access
467 * c++ WriteBatchInternal.
468 */
469 class WriteBatchTestInternalHelper {
470 static void setSequence(final WriteBatch wb, final long sn) {
471 setSequence(wb.nativeHandle_, sn);
472 }
473
474 static long sequence(final WriteBatch wb) {
475 return sequence(wb.nativeHandle_);
476 }
477
478 static void append(final WriteBatch wb1, final WriteBatch wb2) {
479 append(wb1.nativeHandle_, wb2.nativeHandle_);
480 }
481
482 private static native void setSequence(final long writeBatchHandle,
483 final long sn);
484
485 private static native long sequence(final long writeBatchHandle);
486
487 private static native void append(final long writeBatchHandle1,
488 final long writeBatchHandle2);
489 }