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.List; 9 10 /** 11 * Database with Transaction support. 12 */ 13 public class OptimisticTransactionDB extends RocksDB 14 implements TransactionalDB<OptimisticTransactionOptions> { 15 16 /** 17 * Private constructor. 18 * 19 * @param nativeHandle The native handle of the C++ OptimisticTransactionDB 20 * object 21 */ OptimisticTransactionDB(final long nativeHandle)22 private OptimisticTransactionDB(final long nativeHandle) { 23 super(nativeHandle); 24 } 25 26 /** 27 * Open an OptimisticTransactionDB similar to 28 * {@link RocksDB#open(Options, String)}. 29 * 30 * @param options {@link org.rocksdb.Options} instance. 31 * @param path the path to the rocksdb. 32 * 33 * @return a {@link OptimisticTransactionDB} instance on success, null if the 34 * specified {@link OptimisticTransactionDB} can not be opened. 35 * 36 * @throws RocksDBException if an error occurs whilst opening the database. 37 */ open(final Options options, final String path)38 public static OptimisticTransactionDB open(final Options options, 39 final String path) throws RocksDBException { 40 final OptimisticTransactionDB otdb = new OptimisticTransactionDB(open( 41 options.nativeHandle_, path)); 42 43 // when non-default Options is used, keeping an Options reference 44 // in RocksDB can prevent Java to GC during the life-time of 45 // the currently-created RocksDB. 46 otdb.storeOptionsInstance(options); 47 48 return otdb; 49 } 50 51 /** 52 * Open an OptimisticTransactionDB similar to 53 * {@link RocksDB#open(DBOptions, String, List, List)}. 54 * 55 * @param dbOptions {@link org.rocksdb.DBOptions} instance. 56 * @param path the path to the rocksdb. 57 * @param columnFamilyDescriptors list of column family descriptors 58 * @param columnFamilyHandles will be filled with ColumnFamilyHandle instances 59 * 60 * @return a {@link OptimisticTransactionDB} instance on success, null if the 61 * specified {@link OptimisticTransactionDB} can not be opened. 62 * 63 * @throws RocksDBException if an error occurs whilst opening the database. 64 */ open(final DBOptions dbOptions, final String path, final List<ColumnFamilyDescriptor> columnFamilyDescriptors, final List<ColumnFamilyHandle> columnFamilyHandles)65 public static OptimisticTransactionDB open(final DBOptions dbOptions, 66 final String path, 67 final List<ColumnFamilyDescriptor> columnFamilyDescriptors, 68 final List<ColumnFamilyHandle> columnFamilyHandles) 69 throws RocksDBException { 70 71 final byte[][] cfNames = new byte[columnFamilyDescriptors.size()][]; 72 final long[] cfOptionHandles = new long[columnFamilyDescriptors.size()]; 73 for (int i = 0; i < columnFamilyDescriptors.size(); i++) { 74 final ColumnFamilyDescriptor cfDescriptor = columnFamilyDescriptors 75 .get(i); 76 cfNames[i] = cfDescriptor.getName(); 77 cfOptionHandles[i] = cfDescriptor.getOptions().nativeHandle_; 78 } 79 80 final long[] handles = open(dbOptions.nativeHandle_, path, cfNames, 81 cfOptionHandles); 82 final OptimisticTransactionDB otdb = 83 new OptimisticTransactionDB(handles[0]); 84 85 // when non-default Options is used, keeping an Options reference 86 // in RocksDB can prevent Java to GC during the life-time of 87 // the currently-created RocksDB. 88 otdb.storeOptionsInstance(dbOptions); 89 90 for (int i = 1; i < handles.length; i++) { 91 columnFamilyHandles.add(new ColumnFamilyHandle(otdb, handles[i])); 92 } 93 94 return otdb; 95 } 96 97 98 /** 99 * This is similar to {@link #close()} except that it 100 * throws an exception if any error occurs. 101 * 102 * This will not fsync the WAL files. 103 * If syncing is required, the caller must first call {@link #syncWal()} 104 * or {@link #write(WriteOptions, WriteBatch)} using an empty write batch 105 * with {@link WriteOptions#setSync(boolean)} set to true. 106 * 107 * See also {@link #close()}. 108 * 109 * @throws RocksDBException if an error occurs whilst closing. 110 */ closeE()111 public void closeE() throws RocksDBException { 112 if (owningHandle_.compareAndSet(true, false)) { 113 try { 114 closeDatabase(nativeHandle_); 115 } finally { 116 disposeInternal(); 117 } 118 } 119 } 120 121 /** 122 * This is similar to {@link #closeE()} except that it 123 * silently ignores any errors. 124 * 125 * This will not fsync the WAL files. 126 * If syncing is required, the caller must first call {@link #syncWal()} 127 * or {@link #write(WriteOptions, WriteBatch)} using an empty write batch 128 * with {@link WriteOptions#setSync(boolean)} set to true. 129 * 130 * See also {@link #close()}. 131 */ 132 @Override close()133 public void close() { 134 if (owningHandle_.compareAndSet(true, false)) { 135 try { 136 closeDatabase(nativeHandle_); 137 } catch (final RocksDBException e) { 138 // silently ignore the error report 139 } finally { 140 disposeInternal(); 141 } 142 } 143 } 144 145 @Override beginTransaction(final WriteOptions writeOptions)146 public Transaction beginTransaction(final WriteOptions writeOptions) { 147 return new Transaction(this, beginTransaction(nativeHandle_, 148 writeOptions.nativeHandle_)); 149 } 150 151 @Override beginTransaction(final WriteOptions writeOptions, final OptimisticTransactionOptions optimisticTransactionOptions)152 public Transaction beginTransaction(final WriteOptions writeOptions, 153 final OptimisticTransactionOptions optimisticTransactionOptions) { 154 return new Transaction(this, beginTransaction(nativeHandle_, 155 writeOptions.nativeHandle_, 156 optimisticTransactionOptions.nativeHandle_)); 157 } 158 159 // TODO(AR) consider having beingTransaction(... oldTransaction) set a 160 // reference count inside Transaction, so that we can always call 161 // Transaction#close but the object is only disposed when there are as many 162 // closes as beginTransaction. Makes the try-with-resources paradigm easier for 163 // java developers 164 165 @Override beginTransaction(final WriteOptions writeOptions, final Transaction oldTransaction)166 public Transaction beginTransaction(final WriteOptions writeOptions, 167 final Transaction oldTransaction) { 168 final long jtxn_handle = beginTransaction_withOld(nativeHandle_, 169 writeOptions.nativeHandle_, oldTransaction.nativeHandle_); 170 171 // RocksJava relies on the assumption that 172 // we do not allocate a new Transaction object 173 // when providing an old_txn 174 assert(jtxn_handle == oldTransaction.nativeHandle_); 175 176 return oldTransaction; 177 } 178 179 @Override beginTransaction(final WriteOptions writeOptions, final OptimisticTransactionOptions optimisticTransactionOptions, final Transaction oldTransaction)180 public Transaction beginTransaction(final WriteOptions writeOptions, 181 final OptimisticTransactionOptions optimisticTransactionOptions, 182 final Transaction oldTransaction) { 183 final long jtxn_handle = beginTransaction_withOld(nativeHandle_, 184 writeOptions.nativeHandle_, optimisticTransactionOptions.nativeHandle_, 185 oldTransaction.nativeHandle_); 186 187 // RocksJava relies on the assumption that 188 // we do not allocate a new Transaction object 189 // when providing an old_txn 190 assert(jtxn_handle == oldTransaction.nativeHandle_); 191 192 return oldTransaction; 193 } 194 195 /** 196 * Get the underlying database that was opened. 197 * 198 * @return The underlying database that was opened. 199 */ getBaseDB()200 public RocksDB getBaseDB() { 201 final RocksDB db = new RocksDB(getBaseDB(nativeHandle_)); 202 db.disOwnNativeHandle(); 203 return db; 204 } 205 disposeInternal(final long handle)206 @Override protected final native void disposeInternal(final long handle); 207 open(final long optionsHandle, final String path)208 protected static native long open(final long optionsHandle, 209 final String path) throws RocksDBException; open(final long handle, final String path, final byte[][] columnFamilyNames, final long[] columnFamilyOptions)210 protected static native long[] open(final long handle, final String path, 211 final byte[][] columnFamilyNames, final long[] columnFamilyOptions); closeDatabase(final long handle)212 private native static void closeDatabase(final long handle) 213 throws RocksDBException; beginTransaction(final long handle, final long writeOptionsHandle)214 private native long beginTransaction(final long handle, 215 final long writeOptionsHandle); beginTransaction(final long handle, final long writeOptionsHandle, final long optimisticTransactionOptionsHandle)216 private native long beginTransaction(final long handle, 217 final long writeOptionsHandle, 218 final long optimisticTransactionOptionsHandle); beginTransaction_withOld(final long handle, final long writeOptionsHandle, final long oldTransactionHandle)219 private native long beginTransaction_withOld(final long handle, 220 final long writeOptionsHandle, final long oldTransactionHandle); beginTransaction_withOld(final long handle, final long writeOptionsHandle, final long optimisticTransactionOptionsHandle, final long oldTransactionHandle)221 private native long beginTransaction_withOld(final long handle, 222 final long writeOptionsHandle, 223 final long optimisticTransactionOptionsHandle, 224 final long oldTransactionHandle); getBaseDB(final long handle)225 private native long getBaseDB(final long handle); 226 } 227