]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/java/src/test/java/org/rocksdb/TransactionTest.java
import quincy beta 17.1.0
[ceph.git] / ceph / src / rocksdb / java / src / test / java / org / rocksdb / TransactionTest.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 package org.rocksdb;
7
8 import org.junit.Test;
9
10 import java.util.ArrayList;
11 import java.util.Arrays;
12 import java.util.List;
13
14 import static java.nio.charset.StandardCharsets.UTF_8;
15 import static org.assertj.core.api.Assertions.assertThat;
16 import static org.assertj.core.api.Assertions.fail;
17
18 public class TransactionTest extends AbstractTransactionTest {
19
20 @Test
21 public void getForUpdate_cf_conflict() throws RocksDBException {
22 final byte k1[] = "key1".getBytes(UTF_8);
23 final byte v1[] = "value1".getBytes(UTF_8);
24 final byte v12[] = "value12".getBytes(UTF_8);
25 try(final DBContainer dbContainer = startDb();
26 final ReadOptions readOptions = new ReadOptions()) {
27 final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
28
29 try(final Transaction txn = dbContainer.beginTransaction()) {
30 txn.put(testCf, k1, v1);
31 assertThat(txn.getForUpdate(readOptions, testCf, k1, true)).isEqualTo(v1);
32 txn.commit();
33 }
34
35 try(final Transaction txn2 = dbContainer.beginTransaction()) {
36 try(final Transaction txn3 = dbContainer.beginTransaction()) {
37 assertThat(txn3.getForUpdate(readOptions, testCf, k1, true)).isEqualTo(v1);
38
39 // NOTE: txn2 updates k1, during txn3
40 try {
41 txn2.put(testCf, k1, v12); // should cause an exception!
42 } catch(final RocksDBException e) {
43 assertThat(e.getStatus().getCode()).isSameAs(Status.Code.TimedOut);
44 return;
45 }
46 }
47 }
48
49 fail("Expected an exception for put after getForUpdate from conflicting" +
50 "transactions");
51 }
52 }
53
54 @Test
55 public void getForUpdate_conflict() throws RocksDBException {
56 final byte k1[] = "key1".getBytes(UTF_8);
57 final byte v1[] = "value1".getBytes(UTF_8);
58 final byte v12[] = "value12".getBytes(UTF_8);
59 try(final DBContainer dbContainer = startDb();
60 final ReadOptions readOptions = new ReadOptions()) {
61
62 try(final Transaction txn = dbContainer.beginTransaction()) {
63 txn.put(k1, v1);
64 assertThat(txn.getForUpdate(readOptions, k1, true)).isEqualTo(v1);
65 txn.commit();
66 }
67
68 try(final Transaction txn2 = dbContainer.beginTransaction()) {
69 try(final Transaction txn3 = dbContainer.beginTransaction()) {
70 assertThat(txn3.getForUpdate(readOptions, k1, true)).isEqualTo(v1);
71
72 // NOTE: txn2 updates k1, during txn3
73 try {
74 txn2.put(k1, v12); // should cause an exception!
75 } catch(final RocksDBException e) {
76 assertThat(e.getStatus().getCode()).isSameAs(Status.Code.TimedOut);
77 return;
78 }
79 }
80 }
81
82 fail("Expected an exception for put after getForUpdate from conflicting" +
83 "transactions");
84 }
85 }
86
87 @Test
88 public void multiGetForUpdate_cf_conflict() throws RocksDBException {
89 final byte keys[][] = new byte[][] {
90 "key1".getBytes(UTF_8),
91 "key2".getBytes(UTF_8)};
92 final byte values[][] = new byte[][] {
93 "value1".getBytes(UTF_8),
94 "value2".getBytes(UTF_8)};
95 final byte[] otherValue = "otherValue".getBytes(UTF_8);
96
97 try(final DBContainer dbContainer = startDb();
98 final ReadOptions readOptions = new ReadOptions()) {
99 final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
100 final List<ColumnFamilyHandle> cfList = Arrays.asList(testCf, testCf);
101
102 try(final Transaction txn = dbContainer.beginTransaction()) {
103 txn.put(testCf, keys[0], values[0]);
104 txn.put(testCf, keys[1], values[1]);
105 assertThat(txn.multiGet(readOptions, cfList, keys)).isEqualTo(values);
106 txn.commit();
107 }
108
109 try(final Transaction txn2 = dbContainer.beginTransaction()) {
110 try(final Transaction txn3 = dbContainer.beginTransaction()) {
111 assertThat(txn3.multiGetForUpdate(readOptions, cfList, keys))
112 .isEqualTo(values);
113
114 // NOTE: txn2 updates k1, during txn3
115 try {
116 txn2.put(testCf, keys[0], otherValue); // should cause an exception!
117 } catch(final RocksDBException e) {
118 assertThat(e.getStatus().getCode()).isSameAs(Status.Code.TimedOut);
119 return;
120 }
121 }
122 }
123
124 fail("Expected an exception for put after getForUpdate from conflicting" +
125 "transactions");
126 }
127 }
128
129 @Test
130 public void multiGetForUpdate_conflict() throws RocksDBException {
131 final byte keys[][] = new byte[][] {
132 "key1".getBytes(UTF_8),
133 "key2".getBytes(UTF_8)};
134 final byte values[][] = new byte[][] {
135 "value1".getBytes(UTF_8),
136 "value2".getBytes(UTF_8)};
137 final byte[] otherValue = "otherValue".getBytes(UTF_8);
138
139 try(final DBContainer dbContainer = startDb();
140 final ReadOptions readOptions = new ReadOptions()) {
141 try(final Transaction txn = dbContainer.beginTransaction()) {
142 txn.put(keys[0], values[0]);
143 txn.put(keys[1], values[1]);
144 assertThat(txn.multiGet(readOptions, keys)).isEqualTo(values);
145 txn.commit();
146 }
147
148 try(final Transaction txn2 = dbContainer.beginTransaction()) {
149 try(final Transaction txn3 = dbContainer.beginTransaction()) {
150 assertThat(txn3.multiGetForUpdate(readOptions, keys))
151 .isEqualTo(values);
152
153 // NOTE: txn2 updates k1, during txn3
154 try {
155 txn2.put(keys[0], otherValue); // should cause an exception!
156 } catch(final RocksDBException e) {
157 assertThat(e.getStatus().getCode()).isSameAs(Status.Code.TimedOut);
158 return;
159 }
160 }
161 }
162
163 fail("Expected an exception for put after getForUpdate from conflicting" +
164 "transactions");
165 }
166 }
167
168 @Test
169 public void name() throws RocksDBException {
170 try(final DBContainer dbContainer = startDb();
171 final Transaction txn = dbContainer.beginTransaction()) {
172 assertThat(txn.getName()).isEmpty();
173 final String name = "my-transaction-" + rand.nextLong();
174 txn.setName(name);
175 assertThat(txn.getName()).isEqualTo(name);
176 }
177 }
178
179 @Test
180 public void ID() throws RocksDBException {
181 try(final DBContainer dbContainer = startDb();
182 final Transaction txn = dbContainer.beginTransaction()) {
183 assertThat(txn.getID()).isGreaterThan(0);
184 }
185 }
186
187 @Test
188 public void deadlockDetect() throws RocksDBException {
189 try(final DBContainer dbContainer = startDb();
190 final Transaction txn = dbContainer.beginTransaction()) {
191 assertThat(txn.isDeadlockDetect()).isFalse();
192 }
193 }
194
195 @Test
196 public void waitingTxns() throws RocksDBException {
197 try(final DBContainer dbContainer = startDb();
198 final Transaction txn = dbContainer.beginTransaction()) {
199 assertThat(txn.getWaitingTxns().getTransactionIds().length).isEqualTo(0);
200 }
201 }
202
203 @Test
204 public void state() throws RocksDBException {
205 try(final DBContainer dbContainer = startDb()) {
206
207 try(final Transaction txn = dbContainer.beginTransaction()) {
208 assertThat(txn.getState())
209 .isSameAs(Transaction.TransactionState.STARTED);
210 txn.commit();
211 assertThat(txn.getState())
212 .isSameAs(Transaction.TransactionState.COMMITTED);
213 }
214
215 try(final Transaction txn = dbContainer.beginTransaction()) {
216 assertThat(txn.getState())
217 .isSameAs(Transaction.TransactionState.STARTED);
218 txn.rollback();
219 assertThat(txn.getState())
220 .isSameAs(Transaction.TransactionState.STARTED);
221 }
222 }
223 }
224
225 @Test
226 public void Id() throws RocksDBException {
227 try(final DBContainer dbContainer = startDb();
228 final Transaction txn = dbContainer.beginTransaction()) {
229 assertThat(txn.getId()).isNotNull();
230 }
231 }
232
233 @Override
234 public TransactionDBContainer startDb() throws RocksDBException {
235 final DBOptions options = new DBOptions()
236 .setCreateIfMissing(true)
237 .setCreateMissingColumnFamilies(true);
238 final TransactionDBOptions txnDbOptions = new TransactionDBOptions();
239 final ColumnFamilyOptions columnFamilyOptions = new ColumnFamilyOptions();
240 final List<ColumnFamilyDescriptor> columnFamilyDescriptors =
241 Arrays.asList(
242 new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY),
243 new ColumnFamilyDescriptor(TXN_TEST_COLUMN_FAMILY,
244 columnFamilyOptions));
245 final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>();
246
247 final TransactionDB txnDb;
248 try {
249 txnDb = TransactionDB.open(options, txnDbOptions,
250 dbFolder.getRoot().getAbsolutePath(), columnFamilyDescriptors,
251 columnFamilyHandles);
252 } catch(final RocksDBException e) {
253 columnFamilyOptions.close();
254 txnDbOptions.close();
255 options.close();
256 throw e;
257 }
258
259 final WriteOptions writeOptions = new WriteOptions();
260 final TransactionOptions txnOptions = new TransactionOptions();
261
262 return new TransactionDBContainer(txnOptions, writeOptions,
263 columnFamilyHandles, txnDb, txnDbOptions, columnFamilyOptions, options);
264 }
265
266 private static class TransactionDBContainer
267 extends DBContainer {
268 private final TransactionOptions txnOptions;
269 private final TransactionDB txnDb;
270 private final TransactionDBOptions txnDbOptions;
271
272 public TransactionDBContainer(
273 final TransactionOptions txnOptions, final WriteOptions writeOptions,
274 final List<ColumnFamilyHandle> columnFamilyHandles,
275 final TransactionDB txnDb, final TransactionDBOptions txnDbOptions,
276 final ColumnFamilyOptions columnFamilyOptions,
277 final DBOptions options) {
278 super(writeOptions, columnFamilyHandles, columnFamilyOptions,
279 options);
280 this.txnOptions = txnOptions;
281 this.txnDb = txnDb;
282 this.txnDbOptions = txnDbOptions;
283 }
284
285 @Override
286 public Transaction beginTransaction() {
287 return txnDb.beginTransaction(writeOptions, txnOptions);
288 }
289
290 @Override
291 public Transaction beginTransaction(final WriteOptions writeOptions) {
292 return txnDb.beginTransaction(writeOptions, txnOptions);
293 }
294
295 @Override
296 public void close() {
297 txnOptions.close();
298 writeOptions.close();
299 for(final ColumnFamilyHandle columnFamilyHandle : columnFamilyHandles) {
300 columnFamilyHandle.close();
301 }
302 txnDb.close();
303 txnDbOptions.close();
304 options.close();
305 }
306 }
307
308 }