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