diff --git a/java/CMakeLists.txt b/java/CMakeLists.txt index 879ef59a5..6a335949e 100644 --- a/java/CMakeLists.txt +++ b/java/CMakeLists.txt @@ -3,6 +3,8 @@ cmake_minimum_required(VERSION 3.4) set(JNI_NATIVE_SOURCES rocksjni/backupablejni.cc rocksjni/backupenginejni.cc + rocksjni/cassandra_compactionfilterjni.cc + rocksjni/cassandra_value_operator.cc rocksjni/checkpoint.cc rocksjni/clock_cache.cc rocksjni/columnfamilyhandle.cc @@ -25,14 +27,14 @@ set(JNI_NATIVE_SOURCES rocksjni/memtablejni.cc rocksjni/merge_operator.cc rocksjni/native_comparator_wrapper_test.cc + rocksjni/optimistic_transaction_db.cc + rocksjni/optimistic_transaction_options.cc rocksjni/options.cc rocksjni/options_util.cc rocksjni/ratelimiterjni.cc rocksjni/remove_emptyvalue_compactionfilterjni.cc - rocksjni/rocks_callback_object.cc - rocksjni/cassandra_compactionfilterjni.cc - rocksjni/cassandra_value_operator.cc rocksjni/restorejni.cc + rocksjni/rocks_callback_object.cc rocksjni/rocksdb_exception_test.cc rocksjni/rocksjni.cc rocksjni/slice.cc @@ -42,28 +44,33 @@ set(JNI_NATIVE_SOURCES rocksjni/statistics.cc rocksjni/statisticsjni.cc rocksjni/table.cc + rocksjni/transaction.cc + rocksjni/transaction_db.cc + rocksjni/transaction_db_options.cc rocksjni/transaction_log.cc + rocksjni/transaction_notifier.cc + rocksjni/transaction_notifier_jnicallback.cc + rocksjni/transaction_options.cc rocksjni/ttl.cc rocksjni/write_batch.cc + rocksjni/writebatchhandlerjnicallback.cc rocksjni/write_batch_test.cc rocksjni/write_batch_with_index.cc - rocksjni/writebatchhandlerjnicallback.cc ) set(NATIVE_JAVA_CLASSES org.rocksdb.AbstractCompactionFilter org.rocksdb.AbstractCompactionFilterFactory + org.rocksdb.AbstractComparator org.rocksdb.AbstractImmutableNativeReference org.rocksdb.AbstractNativeReference org.rocksdb.AbstractRocksIterator org.rocksdb.AbstractSlice - org.rocksdb.AbstractWriteBatch + org.rocksdb.AbstractTransactionNotifier org.rocksdb.BackupableDBOptions org.rocksdb.BackupEngine - org.rocksdb.BackupEngineTest org.rocksdb.BlockBasedTableConfig org.rocksdb.BloomFilter - org.rocksdb.Cache org.rocksdb.CassandraCompactionFilter org.rocksdb.CassandraValueMergeOperator org.rocksdb.Checkpoint @@ -88,10 +95,10 @@ set(NATIVE_JAVA_CLASSES org.rocksdb.Logger org.rocksdb.LRUCache org.rocksdb.MemTableConfig - org.rocksdb.MergeOperator org.rocksdb.NativeComparatorWrapper - org.rocksdb.NativeComparatorWrapperTest.NativeStringComparatorWrapper org.rocksdb.NativeLibraryLoader + org.rocksdb.OptimisticTransactionDB + org.rocksdb.OptimisticTransactionOptions org.rocksdb.Options org.rocksdb.OptionsUtil org.rocksdb.PlainTableConfig @@ -101,7 +108,6 @@ set(NATIVE_JAVA_CLASSES org.rocksdb.RestoreOptions org.rocksdb.RocksCallbackObject org.rocksdb.RocksDB - org.rocksdb.RocksDBExceptionTest org.rocksdb.RocksEnv org.rocksdb.RocksIterator org.rocksdb.RocksIteratorInterface @@ -111,24 +117,29 @@ set(NATIVE_JAVA_CLASSES org.rocksdb.SkipListMemTableConfig org.rocksdb.Slice org.rocksdb.Snapshot - org.rocksdb.SnapshotTest org.rocksdb.SstFileManager org.rocksdb.SstFileWriter org.rocksdb.Statistics org.rocksdb.StringAppendOperator org.rocksdb.TableFormatConfig + org.rocksdb.Transaction + org.rocksdb.TransactionDB + org.rocksdb.TransactionDBOptions org.rocksdb.TransactionLogIterator + org.rocksdb.TransactionOptions org.rocksdb.TtlDB org.rocksdb.VectorMemTableConfig org.rocksdb.WBWIRocksIterator org.rocksdb.WriteBatch org.rocksdb.WriteBatch.Handler - org.rocksdb.WriteBatchTest - org.rocksdb.WriteBatchTestInternalHelper + org.rocksdb.WriteBatchInterface org.rocksdb.WriteBatchWithIndex org.rocksdb.WriteOptions - org.rocksdb.util.CapturingWriteBatchHandler - org.rocksdb.util.WriteBatchGetter + org.rocksdb.NativeComparatorWrapperTest + org.rocksdb.RocksDBExceptionTest + org.rocksdb.SnapshotTest + org.rocksdb.WriteBatchTest + org.rocksdb.WriteBatchTestInternalHelper ) include(FindJava) @@ -150,13 +161,14 @@ set(JAVA_TESTCLASSPATH ${JAVA_JUNIT_JAR} ${JAVA_HAMCR_JAR} ${JAVA_MOCKITO_JAR} $ add_jar( rocksdbjni_classes SOURCES - src/main/java/org/rocksdb/AbstractCompactionFilter.java src/main/java/org/rocksdb/AbstractCompactionFilterFactory.java + src/main/java/org/rocksdb/AbstractCompactionFilter.java src/main/java/org/rocksdb/AbstractComparator.java src/main/java/org/rocksdb/AbstractImmutableNativeReference.java src/main/java/org/rocksdb/AbstractNativeReference.java src/main/java/org/rocksdb/AbstractRocksIterator.java src/main/java/org/rocksdb/AbstractSlice.java + src/main/java/org/rocksdb/AbstractTransactionNotifier.java src/main/java/org/rocksdb/AbstractWriteBatch.java src/main/java/org/rocksdb/AccessHint.java src/main/java/org/rocksdb/AdvancedColumnFamilyOptionsInterface.java @@ -175,8 +187,8 @@ add_jar( src/main/java/org/rocksdb/ClockCache.java src/main/java/org/rocksdb/ColumnFamilyDescriptor.java src/main/java/org/rocksdb/ColumnFamilyHandle.java - src/main/java/org/rocksdb/ColumnFamilyOptions.java src/main/java/org/rocksdb/ColumnFamilyOptionsInterface.java + src/main/java/org/rocksdb/ColumnFamilyOptions.java src/main/java/org/rocksdb/CompactionOptionsFIFO.java src/main/java/org/rocksdb/CompactionOptionsUniversal.java src/main/java/org/rocksdb/CompactionPriority.java @@ -187,8 +199,8 @@ add_jar( src/main/java/org/rocksdb/ComparatorType.java src/main/java/org/rocksdb/CompressionOptions.java src/main/java/org/rocksdb/CompressionType.java - src/main/java/org/rocksdb/DBOptions.java src/main/java/org/rocksdb/DBOptionsInterface.java + src/main/java/org/rocksdb/DBOptions.java src/main/java/org/rocksdb/DbPath.java src/main/java/org/rocksdb/DirectComparator.java src/main/java/org/rocksdb/DirectSlice.java @@ -209,10 +221,12 @@ add_jar( src/main/java/org/rocksdb/LRUCache.java src/main/java/org/rocksdb/MemTableConfig.java src/main/java/org/rocksdb/MergeOperator.java - src/main/java/org/rocksdb/MutableColumnFamilyOptions.java src/main/java/org/rocksdb/MutableColumnFamilyOptionsInterface.java + src/main/java/org/rocksdb/MutableColumnFamilyOptions.java src/main/java/org/rocksdb/NativeComparatorWrapper.java src/main/java/org/rocksdb/NativeLibraryLoader.java + src/main/java/org/rocksdb/OptimisticTransactionDB.java + src/main/java/org/rocksdb/OptimisticTransactionOptions.java src/main/java/org/rocksdb/Options.java src/main/java/org/rocksdb/OptionsUtil.java src/main/java/org/rocksdb/PlainTableConfig.java @@ -223,11 +237,11 @@ add_jar( src/main/java/org/rocksdb/RemoveEmptyValueCompactionFilter.java src/main/java/org/rocksdb/RestoreOptions.java src/main/java/org/rocksdb/RocksCallbackObject.java - src/main/java/org/rocksdb/RocksDB.java src/main/java/org/rocksdb/RocksDBException.java + src/main/java/org/rocksdb/RocksDB.java src/main/java/org/rocksdb/RocksEnv.java - src/main/java/org/rocksdb/RocksIterator.java src/main/java/org/rocksdb/RocksIteratorInterface.java + src/main/java/org/rocksdb/RocksIterator.java src/main/java/org/rocksdb/RocksMemEnv.java src/main/java/org/rocksdb/RocksMutableObject.java src/main/java/org/rocksdb/RocksObject.java @@ -236,22 +250,36 @@ add_jar( src/main/java/org/rocksdb/Snapshot.java src/main/java/org/rocksdb/SstFileManager.java src/main/java/org/rocksdb/SstFileWriter.java + src/main/java/org/rocksdb/StatisticsCollectorCallback.java + src/main/java/org/rocksdb/StatisticsCollector.java src/main/java/org/rocksdb/Statistics.java + src/main/java/org/rocksdb/StatsCollectorInput.java src/main/java/org/rocksdb/StatsLevel.java src/main/java/org/rocksdb/Status.java src/main/java/org/rocksdb/StringAppendOperator.java src/main/java/org/rocksdb/TableFormatConfig.java src/main/java/org/rocksdb/TickerType.java + src/main/java/org/rocksdb/TransactionalDB.java + src/main/java/org/rocksdb/TransactionalOptions.java + src/main/java/org/rocksdb/TransactionDB.java + src/main/java/org/rocksdb/TransactionDBOptions.java + src/main/java/org/rocksdb/Transaction.java src/main/java/org/rocksdb/TransactionLogIterator.java + src/main/java/org/rocksdb/TransactionOptions.java src/main/java/org/rocksdb/TtlDB.java - src/main/java/org/rocksdb/util/Environment.java + src/main/java/org/rocksdb/TxnDBWritePolicy.java src/main/java/org/rocksdb/VectorMemTableConfig.java src/main/java/org/rocksdb/WALRecoveryMode.java src/main/java/org/rocksdb/WBWIRocksIterator.java - src/main/java/org/rocksdb/WriteBatch.java src/main/java/org/rocksdb/WriteBatchInterface.java + src/main/java/org/rocksdb/WriteBatch.java src/main/java/org/rocksdb/WriteBatchWithIndex.java src/main/java/org/rocksdb/WriteOptions.java + src/main/java/org/rocksdb/util/BytewiseComparator.java + src/main/java/org/rocksdb/util/DirectBytewiseComparator.java + src/main/java/org/rocksdb/util/Environment.java + src/main/java/org/rocksdb/util/ReverseBytewiseComparator.java + src/main/java/org/rocksdb/util/SizeUnit.java src/test/java/org/rocksdb/BackupEngineTest.java src/test/java/org/rocksdb/IngestExternalFileOptionsTest.java src/test/java/org/rocksdb/NativeComparatorWrapperTest.java diff --git a/java/rocksjni/transaction.cc b/java/rocksjni/transaction.cc index 123ae06c0..62bf9e922 100644 --- a/java/rocksjni/transaction.cc +++ b/java/rocksjni/transaction.cc @@ -16,6 +16,11 @@ using namespace std::placeholders; +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4503) // identifier' : decorated name length exceeded, name was truncated +#endif + /* * Class: org_rocksdb_Transaction * Method: setSnapshot @@ -264,15 +269,14 @@ typedef std::function( std::vector*)> FnMultiGet; -void free_key_parts( +void free_parts( JNIEnv* env, - std::vector> key_parts_to_free) { - for (std::vector>::size_type i = 0; - i < key_parts_to_free.size(); i++) { + std::vector> &parts_to_free) { + for (auto &value : parts_to_free) { jobject jk; jbyteArray jk_ba; jbyte* jk_val; - std::tie(jk_ba, jk_val, jk) = key_parts_to_free[i]; + std::tie(jk_ba, jk_val, jk) = value; env->ReleaseByteArrayElements(jk_ba, jk_val, JNI_ABORT); env->DeleteLocalRef(jk); } @@ -295,7 +299,7 @@ jobjectArray txn_multi_get_helper(JNIEnv* env, const FnMultiGet& fn_multi_get, const jobject jk = env->GetObjectArrayElement(jkey_parts, i); if (env->ExceptionCheck()) { // exception thrown: ArrayIndexOutOfBoundsException - free_key_parts(env, key_parts_to_free); + free_parts(env, key_parts_to_free); return nullptr; } jbyteArray jk_ba = reinterpret_cast(jk); @@ -303,14 +307,14 @@ jobjectArray txn_multi_get_helper(JNIEnv* env, const FnMultiGet& fn_multi_get, if (env->EnsureLocalCapacity(len_key) != 0) { // out of memory env->DeleteLocalRef(jk); - free_key_parts(env, key_parts_to_free); + free_parts(env, key_parts_to_free); return nullptr; } jbyte* jk_val = env->GetByteArrayElements(jk_ba, nullptr); if (jk_val == nullptr) { // exception thrown: OutOfMemoryError env->DeleteLocalRef(jk); - free_key_parts(env, key_parts_to_free); + free_parts(env, key_parts_to_free); return nullptr; } @@ -327,7 +331,7 @@ jobjectArray txn_multi_get_helper(JNIEnv* env, const FnMultiGet& fn_multi_get, fn_multi_get(*read_options, key_parts, &value_parts); // free up allocated byte arrays - free_key_parts(env, key_parts_to_free); + free_parts(env, key_parts_to_free); // prepare the results const jclass jcls_ba = env->FindClass("[B"); @@ -600,28 +604,6 @@ typedef std::function FnWriteKVParts; -void free_key_value_parts( - JNIEnv* env, const int32_t len, - std::tuple jkey_parts_to_free[], - std::tuple jvalue_parts_to_free[]) { - for (int32_t i = len - 1; i >= 0; --i) { - jbyteArray jba_value_part; - jbyte* jvalue_part; - jobject jobj_value_part; - std::tie(jba_value_part, jvalue_part, jobj_value_part) = - jvalue_parts_to_free[i]; - env->ReleaseByteArrayElements(jba_value_part, jvalue_part, JNI_ABORT); - env->DeleteLocalRef(jobj_value_part); - - jbyteArray jba_key_part; - jbyte* jkey_part; - jobject jobj_key_part; - std::tie(jba_key_part, jkey_part, jobj_key_part) = jkey_parts_to_free[i]; - env->ReleaseByteArrayElements(jba_key_part, jkey_part, JNI_ABORT); - env->DeleteLocalRef(jobj_key_part); - } -} - // TODO(AR) consider refactoring to share this between here and rocksjni.cc void txn_write_kv_parts_helper(JNIEnv* env, const FnWriteKVParts& fn_write_kv_parts, @@ -631,27 +613,23 @@ void txn_write_kv_parts_helper(JNIEnv* env, const jint& jvalue_parts_len) { assert(jkey_parts_len == jvalue_parts_len); - rocksdb::Slice key_parts[jkey_parts_len]; - rocksdb::Slice value_parts[jvalue_parts_len]; - std::tuple jkey_parts_to_free[jkey_parts_len]; - std::tuple - jvalue_parts_to_free[jvalue_parts_len]; + auto key_parts = std::vector(); + auto value_parts = std::vector(); + auto jparts_to_free = std::vector>(); // convert java key_parts/value_parts byte[][] to Slice(s) for (jsize i = 0; i < jkey_parts_len; ++i) { const jobject jobj_key_part = env->GetObjectArrayElement(jkey_parts, i); if (env->ExceptionCheck()) { // exception thrown: ArrayIndexOutOfBoundsException - free_key_value_parts(env, jkey_parts_len, jkey_parts_to_free, - jvalue_parts_to_free); + free_parts(env, jparts_to_free); return; } const jobject jobj_value_part = env->GetObjectArrayElement(jvalue_parts, i); if (env->ExceptionCheck()) { // exception thrown: ArrayIndexOutOfBoundsException env->DeleteLocalRef(jobj_key_part); - free_key_value_parts(env, jkey_parts_len, jkey_parts_to_free, - jvalue_parts_to_free); + free_parts(env, jparts_to_free); return; } @@ -661,8 +639,7 @@ void txn_write_kv_parts_helper(JNIEnv* env, // out of memory env->DeleteLocalRef(jobj_value_part); env->DeleteLocalRef(jobj_key_part); - free_key_value_parts(env, jkey_parts_len, jkey_parts_to_free, - jvalue_parts_to_free); + free_parts(env, jparts_to_free); return; } jbyte* jkey_part = env->GetByteArrayElements(jba_key_part, nullptr); @@ -670,8 +647,7 @@ void txn_write_kv_parts_helper(JNIEnv* env, // exception thrown: OutOfMemoryError env->DeleteLocalRef(jobj_value_part); env->DeleteLocalRef(jobj_key_part); - free_key_value_parts(env, jkey_parts_len, jkey_parts_to_free, - jvalue_parts_to_free); + free_parts(env, jparts_to_free); return; } @@ -682,8 +658,7 @@ void txn_write_kv_parts_helper(JNIEnv* env, // out of memory env->DeleteLocalRef(jobj_value_part); env->DeleteLocalRef(jobj_key_part); - free_key_value_parts(env, jkey_parts_len, jkey_parts_to_free, - jvalue_parts_to_free); + free_parts(env, jparts_to_free); return; } jbyte* jvalue_part = env->GetByteArrayElements(jba_value_part, nullptr); @@ -692,30 +667,28 @@ void txn_write_kv_parts_helper(JNIEnv* env, env->ReleaseByteArrayElements(jba_value_part, jvalue_part, JNI_ABORT); env->DeleteLocalRef(jobj_value_part); env->DeleteLocalRef(jobj_key_part); - free_key_value_parts(env, jkey_parts_len, jkey_parts_to_free, - jvalue_parts_to_free); + free_parts(env, jparts_to_free); return; } - jkey_parts_to_free[i] = std::tuple( - jba_key_part, jkey_part, jobj_key_part); - jvalue_parts_to_free[i] = std::tuple( - jba_value_part, jvalue_part, jobj_value_part); + jparts_to_free.push_back(std::make_tuple( + jba_key_part, jkey_part, jobj_key_part)); + jparts_to_free.push_back(std::make_tuple( + jba_value_part, jvalue_part, jobj_value_part)); - key_parts[i] = - rocksdb::Slice(reinterpret_cast(jkey_part), jkey_part_len); - value_parts[i] = - rocksdb::Slice(reinterpret_cast(jvalue_part), jvalue_part_len); + key_parts.push_back( + rocksdb::Slice(reinterpret_cast(jkey_part), jkey_part_len)); + value_parts.push_back( + rocksdb::Slice(reinterpret_cast(jvalue_part), jvalue_part_len)); } // call the write_multi function - rocksdb::Status s = - fn_write_kv_parts(rocksdb::SliceParts(key_parts, jkey_parts_len), - rocksdb::SliceParts(value_parts, jvalue_parts_len)); + rocksdb::Status s = fn_write_kv_parts( + rocksdb::SliceParts(key_parts.data(), (int)key_parts.size()), + rocksdb::SliceParts(value_parts.data(), (int)value_parts.size())); // cleanup temporary memory - free_key_value_parts(env, jkey_parts_len, jkey_parts_to_free, - jvalue_parts_to_free); + free_parts(env, jparts_to_free); // return if (s.ok()) { @@ -857,33 +830,22 @@ void Java_org_rocksdb_Transaction_delete__J_3BI(JNIEnv* env, jobject /*jobj*/, typedef std::function FnWriteKParts; -void free_key_parts( - JNIEnv* env, const int32_t len, - std::tuple jkey_parts_to_free[]) { - for (int32_t i = len - 1; i >= 0; --i) { - jbyteArray jba_key_part; - jbyte* jkey; - jobject jobj_key_part; - std::tie(jba_key_part, jkey, jobj_key_part) = jkey_parts_to_free[i]; - env->ReleaseByteArrayElements(jba_key_part, jkey, JNI_ABORT); - env->DeleteLocalRef(jobj_key_part); - } -} // TODO(AR) consider refactoring to share this between here and rocksjni.cc void txn_write_k_parts_helper(JNIEnv* env, const FnWriteKParts& fn_write_k_parts, const jobjectArray& jkey_parts, const jint& jkey_parts_len) { - rocksdb::Slice key_parts[jkey_parts_len]; - std::tuple jkey_parts_to_free[jkey_parts_len]; + + std::vector key_parts; + std::vector> jkey_parts_to_free; // convert java key_parts byte[][] to Slice(s) for (jint i = 0; i < jkey_parts_len; ++i) { const jobject jobj_key_part = env->GetObjectArrayElement(jkey_parts, i); if (env->ExceptionCheck()) { // exception thrown: ArrayIndexOutOfBoundsException - free_key_parts(env, jkey_parts_len, jkey_parts_to_free); + free_parts(env, jkey_parts_to_free); return; } @@ -892,30 +854,29 @@ void txn_write_k_parts_helper(JNIEnv* env, if (env->EnsureLocalCapacity(jkey_part_len) != 0) { // out of memory env->DeleteLocalRef(jobj_key_part); - free_key_parts(env, jkey_parts_len, jkey_parts_to_free); + free_parts(env, jkey_parts_to_free); return; } jbyte* jkey_part = env->GetByteArrayElements(jba_key_part, nullptr); if (jkey_part == nullptr) { // exception thrown: OutOfMemoryError env->DeleteLocalRef(jobj_key_part); - free_key_parts(env, jkey_parts_len, jkey_parts_to_free); + free_parts(env, jkey_parts_to_free); return; } - jkey_parts_to_free[i] = std::tuple( - jba_key_part, jkey_part, jobj_key_part); + jkey_parts_to_free.push_back(std::tuple( + jba_key_part, jkey_part, jobj_key_part)); - key_parts[i] = - rocksdb::Slice(reinterpret_cast(jkey_part), jkey_part_len); + key_parts.push_back(rocksdb::Slice(reinterpret_cast(jkey_part), jkey_part_len)); } // call the write_multi function rocksdb::Status s = - fn_write_k_parts(rocksdb::SliceParts(key_parts, jkey_parts_len)); + fn_write_k_parts(rocksdb::SliceParts(key_parts.data(), (int)key_parts.size())); // cleanup temporary memory - free_key_parts(env, jkey_parts_len, jkey_parts_to_free); + free_parts(env, jkey_parts_to_free); // return if (s.ok()) { @@ -1582,7 +1543,7 @@ jbyte Java_org_rocksdb_Transaction_getState(JNIEnv* /*env*/, jobject /*jobj*/, } assert(false); - return 0xFF; + return static_cast(-1); } /* diff --git a/java/rocksjni/transaction_db.cc b/java/rocksjni/transaction_db.cc index 9d6d62557..1914a2422 100644 --- a/java/rocksjni/transaction_db.cc +++ b/java/rocksjni/transaction_db.cc @@ -269,7 +269,7 @@ jlongArray Java_org_rocksdb_TransactionDB_getAllPreparedTransactions( assert(size < UINT32_MAX); // does it fit in a jint? const jsize len = static_cast(size); - jlong tmp[len]; + std::vector tmp(len); for (jsize i = 0; i < len; ++i) { tmp[i] = reinterpret_cast(txns[i]); } @@ -279,7 +279,7 @@ jlongArray Java_org_rocksdb_TransactionDB_getAllPreparedTransactions( // exception thrown: OutOfMemoryError return nullptr; } - env->SetLongArrayRegion(jtxns, 0, len, tmp); + env->SetLongArrayRegion(jtxns, 0, len, tmp.data()); if (env->ExceptionCheck()) { // exception thrown: ArrayIndexOutOfBoundsException env->DeleteLocalRef(jtxns); diff --git a/java/src/test/java/org/rocksdb/AbstractTransactionTest.java b/java/src/test/java/org/rocksdb/AbstractTransactionTest.java index 08f3dbf58..3a30b4b22 100644 --- a/java/src/test/java/org/rocksdb/AbstractTransactionTest.java +++ b/java/src/test/java/org/rocksdb/AbstractTransactionTest.java @@ -688,7 +688,7 @@ public abstract class AbstractTransactionTest { final long preStartTxnTime = System.currentTimeMillis(); try(final DBContainer dbContainer = startDb(); final Transaction txn = dbContainer.beginTransaction()) { - Thread.sleep(1); + Thread.sleep(2); final long txnElapsedTime = txn.getElapsedTime(); assertThat(txnElapsedTime).isLessThan(System.currentTimeMillis()