1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under the BSD-style license found in the
3 // LICENSE file in the root directory of this source tree. An additional grant
4 // of patent rights can be found in the PATENTS file in the same directory.
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.
11 import org
.junit
.ClassRule
;
12 import org
.junit
.Rule
;
13 import org
.junit
.Test
;
14 import org
.junit
.rules
.TemporaryFolder
;
16 import java
.io
.UnsupportedEncodingException
;
17 import java
.util
.Arrays
;
19 import static org
.assertj
.core
.api
.Assertions
.assertThat
;
22 * This class mimics the db/write_batch_test.cc
23 * in the c++ rocksdb library.
30 public class WriteBatchTest
{
32 public static final RocksMemoryResource rocksMemoryResource
=
33 new RocksMemoryResource();
36 public TemporaryFolder dbFolder
= new TemporaryFolder();
39 public void emptyWriteBatch() {
40 try (final WriteBatch batch
= new WriteBatch()) {
41 assertThat(batch
.count()).isEqualTo(0);
46 public void multipleBatchOperations()
47 throws UnsupportedEncodingException
{
48 try (WriteBatch batch
= new WriteBatch()) {
49 batch
.put("foo".getBytes("US-ASCII"), "bar".getBytes("US-ASCII"));
50 batch
.remove("box".getBytes("US-ASCII"));
51 batch
.put("baz".getBytes("US-ASCII"), "boo".getBytes("US-ASCII"));
53 WriteBatchTestInternalHelper
.setSequence(batch
, 100);
54 assertThat(WriteBatchTestInternalHelper
.sequence(batch
)).
57 assertThat(batch
.count()).isEqualTo(3);
58 assertThat(new String(getContents(batch
), "US-ASCII")).
59 isEqualTo("Put(baz, boo)@102" +
66 public void testAppendOperation()
67 throws UnsupportedEncodingException
{
68 try (final WriteBatch b1
= new WriteBatch();
69 final WriteBatch b2
= new WriteBatch()) {
70 WriteBatchTestInternalHelper
.setSequence(b1
, 200);
71 WriteBatchTestInternalHelper
.setSequence(b2
, 300);
72 WriteBatchTestInternalHelper
.append(b1
, b2
);
73 assertThat(getContents(b1
).length
).isEqualTo(0);
74 assertThat(b1
.count()).isEqualTo(0);
75 b2
.put("a".getBytes("US-ASCII"), "va".getBytes("US-ASCII"));
76 WriteBatchTestInternalHelper
.append(b1
, b2
);
77 assertThat("Put(a, va)@200".equals(new String(getContents(b1
),
79 assertThat(b1
.count()).isEqualTo(1);
81 b2
.put("b".getBytes("US-ASCII"), "vb".getBytes("US-ASCII"));
82 WriteBatchTestInternalHelper
.append(b1
, b2
);
83 assertThat(("Put(a, va)@200" +
85 .equals(new String(getContents(b1
), "US-ASCII")));
86 assertThat(b1
.count()).isEqualTo(2);
87 b2
.remove("foo".getBytes("US-ASCII"));
88 WriteBatchTestInternalHelper
.append(b1
, b2
);
89 assertThat(("Put(a, va)@200" +
93 .equals(new String(getContents(b1
), "US-ASCII")));
94 assertThat(b1
.count()).isEqualTo(4);
99 public void blobOperation()
100 throws UnsupportedEncodingException
{
101 try (final WriteBatch batch
= new WriteBatch()) {
102 batch
.put("k1".getBytes("US-ASCII"), "v1".getBytes("US-ASCII"));
103 batch
.put("k2".getBytes("US-ASCII"), "v2".getBytes("US-ASCII"));
104 batch
.put("k3".getBytes("US-ASCII"), "v3".getBytes("US-ASCII"));
105 batch
.putLogData("blob1".getBytes("US-ASCII"));
106 batch
.remove("k2".getBytes("US-ASCII"));
107 batch
.putLogData("blob2".getBytes("US-ASCII"));
108 batch
.merge("foo".getBytes("US-ASCII"), "bar".getBytes("US-ASCII"));
109 assertThat(batch
.count()).isEqualTo(5);
110 assertThat(("Merge(foo, bar)@4" +
115 .equals(new String(getContents(batch
), "US-ASCII")));
120 public void savePoints()
121 throws UnsupportedEncodingException
, RocksDBException
{
122 try (final WriteBatch batch
= new WriteBatch()) {
123 batch
.put("k1".getBytes("US-ASCII"), "v1".getBytes("US-ASCII"));
124 batch
.put("k2".getBytes("US-ASCII"), "v2".getBytes("US-ASCII"));
125 batch
.put("k3".getBytes("US-ASCII"), "v3".getBytes("US-ASCII"));
127 assertThat(getFromWriteBatch(batch
, "k1")).isEqualTo("v1");
128 assertThat(getFromWriteBatch(batch
, "k2")).isEqualTo("v2");
129 assertThat(getFromWriteBatch(batch
, "k3")).isEqualTo("v3");
132 batch
.setSavePoint();
134 batch
.remove("k2".getBytes("US-ASCII"));
135 batch
.put("k3".getBytes("US-ASCII"), "v3-2".getBytes("US-ASCII"));
137 assertThat(getFromWriteBatch(batch
, "k2")).isNull();
138 assertThat(getFromWriteBatch(batch
, "k3")).isEqualTo("v3-2");
141 batch
.setSavePoint();
143 batch
.put("k3".getBytes("US-ASCII"), "v3-3".getBytes("US-ASCII"));
144 batch
.put("k4".getBytes("US-ASCII"), "v4".getBytes("US-ASCII"));
146 assertThat(getFromWriteBatch(batch
, "k3")).isEqualTo("v3-3");
147 assertThat(getFromWriteBatch(batch
, "k4")).isEqualTo("v4");
150 batch
.rollbackToSavePoint();
152 assertThat(getFromWriteBatch(batch
, "k2")).isNull();
153 assertThat(getFromWriteBatch(batch
, "k3")).isEqualTo("v3-2");
154 assertThat(getFromWriteBatch(batch
, "k4")).isNull();
157 batch
.rollbackToSavePoint();
159 assertThat(getFromWriteBatch(batch
, "k1")).isEqualTo("v1");
160 assertThat(getFromWriteBatch(batch
, "k2")).isEqualTo("v2");
161 assertThat(getFromWriteBatch(batch
, "k3")).isEqualTo("v3");
162 assertThat(getFromWriteBatch(batch
, "k4")).isNull();
167 public void deleteRange() throws RocksDBException
{
168 try (final RocksDB db
= RocksDB
.open(dbFolder
.getRoot().getAbsolutePath());
169 final WriteOptions wOpt
= new WriteOptions()) {
170 db
.put("key1".getBytes(), "value".getBytes());
171 db
.put("key2".getBytes(), "12345678".getBytes());
172 db
.put("key3".getBytes(), "abcdefg".getBytes());
173 db
.put("key4".getBytes(), "xyz".getBytes());
174 assertThat(db
.get("key1".getBytes())).isEqualTo("value".getBytes());
175 assertThat(db
.get("key2".getBytes())).isEqualTo("12345678".getBytes());
176 assertThat(db
.get("key3".getBytes())).isEqualTo("abcdefg".getBytes());
177 assertThat(db
.get("key4".getBytes())).isEqualTo("xyz".getBytes());
179 WriteBatch batch
= new WriteBatch();
180 batch
.deleteRange("key2".getBytes(), "key4".getBytes());
181 db
.write(new WriteOptions(), batch
);
183 assertThat(db
.get("key1".getBytes())).isEqualTo("value".getBytes());
184 assertThat(db
.get("key2".getBytes())).isNull();
185 assertThat(db
.get("key3".getBytes())).isNull();
186 assertThat(db
.get("key4".getBytes())).isEqualTo("xyz".getBytes());
190 @Test(expected
= RocksDBException
.class)
191 public void restorePoints_withoutSavePoints() throws RocksDBException
{
192 try (final WriteBatch batch
= new WriteBatch()) {
193 batch
.rollbackToSavePoint();
197 @Test(expected
= RocksDBException
.class)
198 public void restorePoints_withoutSavePoints_nested() throws RocksDBException
{
199 try (final WriteBatch batch
= new WriteBatch()) {
201 batch
.setSavePoint();
202 batch
.rollbackToSavePoint();
204 // without previous corresponding setSavePoint
205 batch
.rollbackToSavePoint();
209 static byte[] getContents(final WriteBatch wb
) {
210 return getContents(wb
.nativeHandle_
);
213 static String
getFromWriteBatch(final WriteBatch wb
, final String key
)
214 throws RocksDBException
, UnsupportedEncodingException
{
215 final WriteBatchGetter getter
=
216 new WriteBatchGetter(key
.getBytes("US-ASCII"));
218 if(getter
.getValue() != null) {
219 return new String(getter
.getValue(), "US-ASCII");
225 private static native byte[] getContents(final long writeBatchHandle
);
227 private static class WriteBatchGetter
extends WriteBatch
.Handler
{
229 private final byte[] key
;
230 private byte[] value
;
232 public WriteBatchGetter(final byte[] key
) {
236 public byte[] getValue() {
241 public void put(final byte[] key
, final byte[] value
) {
242 if(Arrays
.equals(this.key
, key
)) {
248 public void merge(final byte[] key
, final byte[] value
) {
249 if(Arrays
.equals(this.key
, key
)) {
250 throw new UnsupportedOperationException();
255 public void delete(final byte[] key
) {
256 if(Arrays
.equals(this.key
, key
)) {
262 public void deleteRange(final byte[] beginKey
, final byte[] endKey
) {
263 throw new UnsupportedOperationException();
267 public void logData(final byte[] blob
) {
273 * Package-private class which provides java api to access
274 * c++ WriteBatchInternal.
276 class WriteBatchTestInternalHelper
{
277 static void setSequence(final WriteBatch wb
, final long sn
) {
278 setSequence(wb
.nativeHandle_
, sn
);
281 static long sequence(final WriteBatch wb
) {
282 return sequence(wb
.nativeHandle_
);
285 static void append(final WriteBatch wb1
, final WriteBatch wb2
) {
286 append(wb1
.nativeHandle_
, wb2
.nativeHandle_
);
289 private static native void setSequence(final long writeBatchHandle
,
292 private static native long sequence(final long writeBatchHandle
);
294 private static native void append(final long writeBatchHandle1
,
295 final long writeBatchHandle2
);