]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/java/src/main/java/org/rocksdb/TransactionDB.java
import 14.2.4 nautilus point release
[ceph.git] / ceph / src / rocksdb / java / src / main / java / org / rocksdb / TransactionDB.java
CommitLineData
11fdf7f2
TL
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
6package org.rocksdb;
7
8import java.util.ArrayList;
9import java.util.HashMap;
10import java.util.List;
11import java.util.Map;
12
13/**
14 * Database with Transaction support
15 */
16public class TransactionDB extends RocksDB
17 implements TransactionalDB<TransactionOptions> {
18
19 private TransactionDBOptions transactionDbOptions_;
20
21 /**
22 * Private constructor.
23 *
24 * @param nativeHandle The native handle of the C++ TransactionDB object
25 */
26 private TransactionDB(final long nativeHandle) {
27 super(nativeHandle);
28 }
29
30 /**
31 * Open a TransactionDB, similar to {@link RocksDB#open(Options, String)}.
32 *
33 * @param options {@link org.rocksdb.Options} instance.
34 * @param transactionDbOptions {@link org.rocksdb.TransactionDBOptions}
35 * instance.
36 * @param path the path to the rocksdb.
37 *
38 * @return a {@link TransactionDB} instance on success, null if the specified
39 * {@link TransactionDB} can not be opened.
40 *
41 * @throws RocksDBException if an error occurs whilst opening the database.
42 */
43 public static TransactionDB open(final Options options,
44 final TransactionDBOptions transactionDbOptions, final String path)
45 throws RocksDBException {
46 final TransactionDB tdb = new TransactionDB(open(options.nativeHandle_,
47 transactionDbOptions.nativeHandle_, path));
48
49 // when non-default Options is used, keeping an Options reference
50 // in RocksDB can prevent Java to GC during the life-time of
51 // the currently-created RocksDB.
52 tdb.storeOptionsInstance(options);
53 tdb.storeTransactionDbOptions(transactionDbOptions);
54
55 return tdb;
56 }
57
58 /**
59 * Open a TransactionDB, similar to
60 * {@link RocksDB#open(DBOptions, String, List, List)}.
61 *
62 * @param dbOptions {@link org.rocksdb.DBOptions} instance.
63 * @param transactionDbOptions {@link org.rocksdb.TransactionDBOptions}
64 * instance.
65 * @param path the path to the rocksdb.
66 * @param columnFamilyDescriptors list of column family descriptors
67 * @param columnFamilyHandles will be filled with ColumnFamilyHandle instances
68 *
69 * @return a {@link TransactionDB} instance on success, null if the specified
70 * {@link TransactionDB} can not be opened.
71 *
72 * @throws RocksDBException if an error occurs whilst opening the database.
73 */
74 public static TransactionDB open(final DBOptions dbOptions,
75 final TransactionDBOptions transactionDbOptions,
76 final String path,
77 final List<ColumnFamilyDescriptor> columnFamilyDescriptors,
78 final List<ColumnFamilyHandle> columnFamilyHandles)
79 throws RocksDBException {
80
81 final byte[][] cfNames = new byte[columnFamilyDescriptors.size()][];
82 final long[] cfOptionHandles = new long[columnFamilyDescriptors.size()];
83 for (int i = 0; i < columnFamilyDescriptors.size(); i++) {
84 final ColumnFamilyDescriptor cfDescriptor = columnFamilyDescriptors
85 .get(i);
86 cfNames[i] = cfDescriptor.columnFamilyName();
87 cfOptionHandles[i] = cfDescriptor.columnFamilyOptions().nativeHandle_;
88 }
89
90 final long[] handles = open(dbOptions.nativeHandle_,
91 transactionDbOptions.nativeHandle_, path, cfNames, cfOptionHandles);
92 final TransactionDB tdb = new TransactionDB(handles[0]);
93
94 // when non-default Options is used, keeping an Options reference
95 // in RocksDB can prevent Java to GC during the life-time of
96 // the currently-created RocksDB.
97 tdb.storeOptionsInstance(dbOptions);
98 tdb.storeTransactionDbOptions(transactionDbOptions);
99
100 for (int i = 1; i < handles.length; i++) {
101 columnFamilyHandles.add(new ColumnFamilyHandle(tdb, handles[i]));
102 }
103
104 return tdb;
105 }
106
494da23a
TL
107 /**
108 * This is similar to {@link #close()} except that it
109 * throws an exception if any error occurs.
110 *
111 * This will not fsync the WAL files.
112 * If syncing is required, the caller must first call {@link #syncWal()}
113 * or {@link #write(WriteOptions, WriteBatch)} using an empty write batch
114 * with {@link WriteOptions#setSync(boolean)} set to true.
115 *
116 * See also {@link #close()}.
117 *
118 * @throws RocksDBException if an error occurs whilst closing.
119 */
120 public void closeE() throws RocksDBException {
121 if (owningHandle_.compareAndSet(true, false)) {
122 try {
123 closeDatabase(nativeHandle_);
124 } finally {
125 disposeInternal();
126 }
127 }
128 }
129
130 /**
131 * This is similar to {@link #closeE()} except that it
132 * silently ignores any errors.
133 *
134 * This will not fsync the WAL files.
135 * If syncing is required, the caller must first call {@link #syncWal()}
136 * or {@link #write(WriteOptions, WriteBatch)} using an empty write batch
137 * with {@link WriteOptions#setSync(boolean)} set to true.
138 *
139 * See also {@link #close()}.
140 */
141 @Override
142 public void close() {
143 if (owningHandle_.compareAndSet(true, false)) {
144 try {
145 closeDatabase(nativeHandle_);
146 } catch (final RocksDBException e) {
147 // silently ignore the error report
148 } finally {
149 disposeInternal();
150 }
151 }
152 }
153
11fdf7f2
TL
154 @Override
155 public Transaction beginTransaction(final WriteOptions writeOptions) {
156 return new Transaction(this, beginTransaction(nativeHandle_,
157 writeOptions.nativeHandle_));
158 }
159
160 @Override
161 public Transaction beginTransaction(final WriteOptions writeOptions,
162 final TransactionOptions transactionOptions) {
163 return new Transaction(this, beginTransaction(nativeHandle_,
164 writeOptions.nativeHandle_, transactionOptions.nativeHandle_));
165 }
166
167 // TODO(AR) consider having beingTransaction(... oldTransaction) set a
168 // reference count inside Transaction, so that we can always call
169 // Transaction#close but the object is only disposed when there are as many
170 // closes as beginTransaction. Makes the try-with-resources paradigm easier for
171 // java developers
172
173 @Override
174 public Transaction beginTransaction(final WriteOptions writeOptions,
175 final Transaction oldTransaction) {
176 final long jtxnHandle = beginTransaction_withOld(nativeHandle_,
177 writeOptions.nativeHandle_, oldTransaction.nativeHandle_);
178
179 // RocksJava relies on the assumption that
180 // we do not allocate a new Transaction object
181 // when providing an old_txn
182 assert(jtxnHandle == oldTransaction.nativeHandle_);
183
184 return oldTransaction;
185 }
186
187 @Override
188 public Transaction beginTransaction(final WriteOptions writeOptions,
189 final TransactionOptions transactionOptions,
190 final Transaction oldTransaction) {
191 final long jtxn_handle = beginTransaction_withOld(nativeHandle_,
192 writeOptions.nativeHandle_, transactionOptions.nativeHandle_,
193 oldTransaction.nativeHandle_);
194
195 // RocksJava relies on the assumption that
196 // we do not allocate a new Transaction object
197 // when providing an old_txn
198 assert(jtxn_handle == oldTransaction.nativeHandle_);
199
200 return oldTransaction;
201 }
202
203 public Transaction getTransactionByName(final String transactionName) {
204 final long jtxnHandle = getTransactionByName(nativeHandle_, transactionName);
205 if(jtxnHandle == 0) {
206 return null;
207 }
208
209 final Transaction txn = new Transaction(this, jtxnHandle);
210
211 // this instance doesn't own the underlying C++ object
212 txn.disOwnNativeHandle();
213
214 return txn;
215 }
216
217 public List<Transaction> getAllPreparedTransactions() {
218 final long[] jtxnHandles = getAllPreparedTransactions(nativeHandle_);
219
220 final List<Transaction> txns = new ArrayList<>();
221 for(final long jtxnHandle : jtxnHandles) {
222 final Transaction txn = new Transaction(this, jtxnHandle);
223
224 // this instance doesn't own the underlying C++ object
225 txn.disOwnNativeHandle();
226
227 txns.add(txn);
228 }
229 return txns;
230 }
231
232 public static class KeyLockInfo {
233 private final String key;
234 private final long[] transactionIDs;
235 private final boolean exclusive;
236
237 public KeyLockInfo(final String key, final long transactionIDs[],
238 final boolean exclusive) {
239 this.key = key;
240 this.transactionIDs = transactionIDs;
241 this.exclusive = exclusive;
242 }
243
244 /**
245 * Get the key.
246 *
247 * @return the key
248 */
249 public String getKey() {
250 return key;
251 }
252
253 /**
254 * Get the Transaction IDs.
255 *
256 * @return the Transaction IDs.
257 */
258 public long[] getTransactionIDs() {
259 return transactionIDs;
260 }
261
262 /**
263 * Get the Lock status.
264 *
265 * @return true if the lock is exclusive, false if the lock is shared.
266 */
267 public boolean isExclusive() {
268 return exclusive;
269 }
270 }
271
272 /**
273 * Returns map of all locks held.
274 *
275 * @return a map of all the locks held.
276 */
277 public Map<Long, KeyLockInfo> getLockStatusData() {
278 return getLockStatusData(nativeHandle_);
279 }
280
281 /**
282 * Called from C++ native method {@link #getDeadlockInfoBuffer(long)}
283 * to construct a DeadlockInfo object.
284 *
285 * @param transactionID The transaction id
286 * @param columnFamilyId The id of the {@link ColumnFamilyHandle}
287 * @param waitingKey the key that we are waiting on
288 * @param exclusive true if the lock is exclusive, false if the lock is shared
289 *
290 * @return The waiting transactions
291 */
292 private DeadlockInfo newDeadlockInfo(
293 final long transactionID, final long columnFamilyId,
294 final String waitingKey, final boolean exclusive) {
295 return new DeadlockInfo(transactionID, columnFamilyId,
296 waitingKey, exclusive);
297 }
298
299 public static class DeadlockInfo {
300 private final long transactionID;
301 private final long columnFamilyId;
302 private final String waitingKey;
303 private final boolean exclusive;
304
305 private DeadlockInfo(final long transactionID, final long columnFamilyId,
306 final String waitingKey, final boolean exclusive) {
307 this.transactionID = transactionID;
308 this.columnFamilyId = columnFamilyId;
309 this.waitingKey = waitingKey;
310 this.exclusive = exclusive;
311 }
312
313 /**
314 * Get the Transaction ID.
315 *
316 * @return the transaction ID
317 */
318 public long getTransactionID() {
319 return transactionID;
320 }
321
322 /**
323 * Get the Column Family ID.
324 *
325 * @return The column family ID
326 */
327 public long getColumnFamilyId() {
328 return columnFamilyId;
329 }
330
331 /**
332 * Get the key that we are waiting on.
333 *
334 * @return the key that we are waiting on
335 */
336 public String getWaitingKey() {
337 return waitingKey;
338 }
339
340 /**
341 * Get the Lock status.
342 *
343 * @return true if the lock is exclusive, false if the lock is shared.
344 */
345 public boolean isExclusive() {
346 return exclusive;
347 }
348 }
349
350 public static class DeadlockPath {
351 final DeadlockInfo[] path;
352 final boolean limitExceeded;
353
354 public DeadlockPath(final DeadlockInfo[] path, final boolean limitExceeded) {
355 this.path = path;
356 this.limitExceeded = limitExceeded;
357 }
358
359 public boolean isEmpty() {
360 return path.length == 0 && !limitExceeded;
361 }
362 }
363
364 public DeadlockPath[] getDeadlockInfoBuffer() {
365 return getDeadlockInfoBuffer(nativeHandle_);
366 }
367
368 public void setDeadlockInfoBufferSize(final int targetSize) {
369 setDeadlockInfoBufferSize(nativeHandle_, targetSize);
370 }
371
372 private void storeTransactionDbOptions(
373 final TransactionDBOptions transactionDbOptions) {
374 this.transactionDbOptions_ = transactionDbOptions;
375 }
376
494da23a
TL
377 @Override protected final native void disposeInternal(final long handle);
378
11fdf7f2
TL
379 private static native long open(final long optionsHandle,
380 final long transactionDbOptionsHandle, final String path)
381 throws RocksDBException;
382 private static native long[] open(final long dbOptionsHandle,
383 final long transactionDbOptionsHandle, final String path,
384 final byte[][] columnFamilyNames, final long[] columnFamilyOptions);
494da23a
TL
385 private native static void closeDatabase(final long handle)
386 throws RocksDBException;
11fdf7f2
TL
387 private native long beginTransaction(final long handle,
388 final long writeOptionsHandle);
389 private native long beginTransaction(final long handle,
390 final long writeOptionsHandle, final long transactionOptionsHandle);
391 private native long beginTransaction_withOld(final long handle,
392 final long writeOptionsHandle, final long oldTransactionHandle);
393 private native long beginTransaction_withOld(final long handle,
394 final long writeOptionsHandle, final long transactionOptionsHandle,
395 final long oldTransactionHandle);
396 private native long getTransactionByName(final long handle,
397 final String name);
398 private native long[] getAllPreparedTransactions(final long handle);
399 private native Map<Long, KeyLockInfo> getLockStatusData(
400 final long handle);
401 private native DeadlockPath[] getDeadlockInfoBuffer(final long handle);
402 private native void setDeadlockInfoBufferSize(final long handle,
403 final int targetSize);
11fdf7f2 404}