]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/java/src/main/java/org/rocksdb/TransactionDB.java
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / rocksdb / java / src / main / java / org / rocksdb / TransactionDB.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 java.util.ArrayList;
9 import java.util.HashMap;
10 import java.util.List;
11 import java.util.Map;
12
13 /**
14 * Database with Transaction support
15 */
16 public 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
107 @Override
108 public Transaction beginTransaction(final WriteOptions writeOptions) {
109 return new Transaction(this, beginTransaction(nativeHandle_,
110 writeOptions.nativeHandle_));
111 }
112
113 @Override
114 public Transaction beginTransaction(final WriteOptions writeOptions,
115 final TransactionOptions transactionOptions) {
116 return new Transaction(this, beginTransaction(nativeHandle_,
117 writeOptions.nativeHandle_, transactionOptions.nativeHandle_));
118 }
119
120 // TODO(AR) consider having beingTransaction(... oldTransaction) set a
121 // reference count inside Transaction, so that we can always call
122 // Transaction#close but the object is only disposed when there are as many
123 // closes as beginTransaction. Makes the try-with-resources paradigm easier for
124 // java developers
125
126 @Override
127 public Transaction beginTransaction(final WriteOptions writeOptions,
128 final Transaction oldTransaction) {
129 final long jtxnHandle = beginTransaction_withOld(nativeHandle_,
130 writeOptions.nativeHandle_, oldTransaction.nativeHandle_);
131
132 // RocksJava relies on the assumption that
133 // we do not allocate a new Transaction object
134 // when providing an old_txn
135 assert(jtxnHandle == oldTransaction.nativeHandle_);
136
137 return oldTransaction;
138 }
139
140 @Override
141 public Transaction beginTransaction(final WriteOptions writeOptions,
142 final TransactionOptions transactionOptions,
143 final Transaction oldTransaction) {
144 final long jtxn_handle = beginTransaction_withOld(nativeHandle_,
145 writeOptions.nativeHandle_, transactionOptions.nativeHandle_,
146 oldTransaction.nativeHandle_);
147
148 // RocksJava relies on the assumption that
149 // we do not allocate a new Transaction object
150 // when providing an old_txn
151 assert(jtxn_handle == oldTransaction.nativeHandle_);
152
153 return oldTransaction;
154 }
155
156 public Transaction getTransactionByName(final String transactionName) {
157 final long jtxnHandle = getTransactionByName(nativeHandle_, transactionName);
158 if(jtxnHandle == 0) {
159 return null;
160 }
161
162 final Transaction txn = new Transaction(this, jtxnHandle);
163
164 // this instance doesn't own the underlying C++ object
165 txn.disOwnNativeHandle();
166
167 return txn;
168 }
169
170 public List<Transaction> getAllPreparedTransactions() {
171 final long[] jtxnHandles = getAllPreparedTransactions(nativeHandle_);
172
173 final List<Transaction> txns = new ArrayList<>();
174 for(final long jtxnHandle : jtxnHandles) {
175 final Transaction txn = new Transaction(this, jtxnHandle);
176
177 // this instance doesn't own the underlying C++ object
178 txn.disOwnNativeHandle();
179
180 txns.add(txn);
181 }
182 return txns;
183 }
184
185 public static class KeyLockInfo {
186 private final String key;
187 private final long[] transactionIDs;
188 private final boolean exclusive;
189
190 public KeyLockInfo(final String key, final long transactionIDs[],
191 final boolean exclusive) {
192 this.key = key;
193 this.transactionIDs = transactionIDs;
194 this.exclusive = exclusive;
195 }
196
197 /**
198 * Get the key.
199 *
200 * @return the key
201 */
202 public String getKey() {
203 return key;
204 }
205
206 /**
207 * Get the Transaction IDs.
208 *
209 * @return the Transaction IDs.
210 */
211 public long[] getTransactionIDs() {
212 return transactionIDs;
213 }
214
215 /**
216 * Get the Lock status.
217 *
218 * @return true if the lock is exclusive, false if the lock is shared.
219 */
220 public boolean isExclusive() {
221 return exclusive;
222 }
223 }
224
225 /**
226 * Returns map of all locks held.
227 *
228 * @return a map of all the locks held.
229 */
230 public Map<Long, KeyLockInfo> getLockStatusData() {
231 return getLockStatusData(nativeHandle_);
232 }
233
234 /**
235 * Called from C++ native method {@link #getDeadlockInfoBuffer(long)}
236 * to construct a DeadlockInfo object.
237 *
238 * @param transactionID The transaction id
239 * @param columnFamilyId The id of the {@link ColumnFamilyHandle}
240 * @param waitingKey the key that we are waiting on
241 * @param exclusive true if the lock is exclusive, false if the lock is shared
242 *
243 * @return The waiting transactions
244 */
245 private DeadlockInfo newDeadlockInfo(
246 final long transactionID, final long columnFamilyId,
247 final String waitingKey, final boolean exclusive) {
248 return new DeadlockInfo(transactionID, columnFamilyId,
249 waitingKey, exclusive);
250 }
251
252 public static class DeadlockInfo {
253 private final long transactionID;
254 private final long columnFamilyId;
255 private final String waitingKey;
256 private final boolean exclusive;
257
258 private DeadlockInfo(final long transactionID, final long columnFamilyId,
259 final String waitingKey, final boolean exclusive) {
260 this.transactionID = transactionID;
261 this.columnFamilyId = columnFamilyId;
262 this.waitingKey = waitingKey;
263 this.exclusive = exclusive;
264 }
265
266 /**
267 * Get the Transaction ID.
268 *
269 * @return the transaction ID
270 */
271 public long getTransactionID() {
272 return transactionID;
273 }
274
275 /**
276 * Get the Column Family ID.
277 *
278 * @return The column family ID
279 */
280 public long getColumnFamilyId() {
281 return columnFamilyId;
282 }
283
284 /**
285 * Get the key that we are waiting on.
286 *
287 * @return the key that we are waiting on
288 */
289 public String getWaitingKey() {
290 return waitingKey;
291 }
292
293 /**
294 * Get the Lock status.
295 *
296 * @return true if the lock is exclusive, false if the lock is shared.
297 */
298 public boolean isExclusive() {
299 return exclusive;
300 }
301 }
302
303 public static class DeadlockPath {
304 final DeadlockInfo[] path;
305 final boolean limitExceeded;
306
307 public DeadlockPath(final DeadlockInfo[] path, final boolean limitExceeded) {
308 this.path = path;
309 this.limitExceeded = limitExceeded;
310 }
311
312 public boolean isEmpty() {
313 return path.length == 0 && !limitExceeded;
314 }
315 }
316
317 public DeadlockPath[] getDeadlockInfoBuffer() {
318 return getDeadlockInfoBuffer(nativeHandle_);
319 }
320
321 public void setDeadlockInfoBufferSize(final int targetSize) {
322 setDeadlockInfoBufferSize(nativeHandle_, targetSize);
323 }
324
325 private void storeTransactionDbOptions(
326 final TransactionDBOptions transactionDbOptions) {
327 this.transactionDbOptions_ = transactionDbOptions;
328 }
329
330 private static native long open(final long optionsHandle,
331 final long transactionDbOptionsHandle, final String path)
332 throws RocksDBException;
333 private static native long[] open(final long dbOptionsHandle,
334 final long transactionDbOptionsHandle, final String path,
335 final byte[][] columnFamilyNames, final long[] columnFamilyOptions);
336 private native long beginTransaction(final long handle,
337 final long writeOptionsHandle);
338 private native long beginTransaction(final long handle,
339 final long writeOptionsHandle, final long transactionOptionsHandle);
340 private native long beginTransaction_withOld(final long handle,
341 final long writeOptionsHandle, final long oldTransactionHandle);
342 private native long beginTransaction_withOld(final long handle,
343 final long writeOptionsHandle, final long transactionOptionsHandle,
344 final long oldTransactionHandle);
345 private native long getTransactionByName(final long handle,
346 final String name);
347 private native long[] getAllPreparedTransactions(final long handle);
348 private native Map<Long, KeyLockInfo> getLockStatusData(
349 final long handle);
350 private native DeadlockPath[] getDeadlockInfoBuffer(final long handle);
351 private native void setDeadlockInfoBufferSize(final long handle,
352 final int targetSize);
353 @Override protected final native void disposeInternal(final long handle);
354 }