diff --git a/java/src/main/java/org/rocksdb/Transaction.java b/java/src/main/java/org/rocksdb/Transaction.java index 6280c26bb..b2cc8a932 100644 --- a/java/src/main/java/org/rocksdb/Transaction.java +++ b/java/src/main/java/org/rocksdb/Transaction.java @@ -178,7 +178,7 @@ public class Transaction extends RocksObject { /** * Prepare the current transaction for 2PC */ - void prepare() throws RocksDBException { + public void prepare() throws RocksDBException { //TODO(AR) consider a Java'ish version of this function, which returns an AutoCloseable (commit) assert(isOwningHandle()); prepare(nativeHandle_); diff --git a/java/src/test/java/org/rocksdb/OptimisticTransactionTest.java b/java/src/test/java/org/rocksdb/OptimisticTransactionTest.java index f23080242..d2f92e1ff 100644 --- a/java/src/test/java/org/rocksdb/OptimisticTransactionTest.java +++ b/java/src/test/java/org/rocksdb/OptimisticTransactionTest.java @@ -5,17 +5,39 @@ package org.rocksdb; -import org.junit.Test; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.assertj.core.api.Assertions.*; import java.util.ArrayList; import java.util.Arrays; import java.util.List; - -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; +import org.junit.Test; public class OptimisticTransactionTest extends AbstractTransactionTest { + @Test + public void prepare_commit() throws RocksDBException { + final byte[] k1 = "key1".getBytes(UTF_8); + final byte[] v1 = "value1".getBytes(UTF_8); + final byte[] v12 = "value12".getBytes(UTF_8); + + try (final DBContainer dbContainer = startDb(); + final ReadOptions readOptions = new ReadOptions()) { + try (final Transaction txn = dbContainer.beginTransaction()) { + txn.put(k1, v1); + txn.commit(); + } + + try (final Transaction txn = dbContainer.beginTransaction()) { + txn.put(k1, v12); + txn.prepare(); + + failBecauseExceptionWasNotThrown(RocksDBException.class); + } catch (final RocksDBException e) { + assertThat(e.getMessage()) + .contains("Two phase commit not supported for optimistic transactions"); + } + } + } @Test public void getForUpdate_cf_conflict() throws RocksDBException { diff --git a/java/src/test/java/org/rocksdb/TransactionTest.java b/java/src/test/java/org/rocksdb/TransactionTest.java index ebe08ce20..8a3067de9 100644 --- a/java/src/test/java/org/rocksdb/TransactionTest.java +++ b/java/src/test/java/org/rocksdb/TransactionTest.java @@ -51,6 +51,120 @@ public class TransactionTest extends AbstractTransactionTest { } } + @Test + public void prepare_commit() throws RocksDBException { + final byte[] k1 = "key1".getBytes(UTF_8); + final byte[] v1 = "value1".getBytes(UTF_8); + final byte[] v12 = "value12".getBytes(UTF_8); + + try (final DBContainer dbContainer = startDb(); + final ReadOptions readOptions = new ReadOptions()) { + try (final Transaction txn = dbContainer.beginTransaction()) { + txn.put(k1, v1); + txn.commit(); + } + + try (final Transaction txn = dbContainer.beginTransaction()) { + txn.setName("txnPrepare1"); + txn.put(k1, v12); + txn.prepare(); + txn.commit(); + } + + try (final Transaction txn = dbContainer.beginTransaction()) { + assertThat(txn.get(readOptions, k1)).isEqualTo(v12); + } + } + } + + @Test + public void prepare_rollback() throws RocksDBException { + final byte[] k1 = "key1".getBytes(UTF_8); + final byte[] v1 = "value1".getBytes(UTF_8); + final byte[] v12 = "value12".getBytes(UTF_8); + + try (final DBContainer dbContainer = startDb(); + final ReadOptions readOptions = new ReadOptions()) { + try (final Transaction txn = dbContainer.beginTransaction()) { + txn.put(k1, v1); + txn.commit(); + } + + try (final Transaction txn = dbContainer.beginTransaction()) { + txn.setName("txnPrepare1"); + txn.put(k1, v12); + txn.prepare(); + txn.rollback(); + } + + try (final Transaction txn = dbContainer.beginTransaction()) { + assertThat(txn.get(readOptions, k1)).isEqualTo(v1); + } + } + } + + @Test + public void prepare_read_prepared_commit() throws RocksDBException { + final byte[] k1 = "key1".getBytes(UTF_8); + final byte[] v1 = "value1".getBytes(UTF_8); + final byte[] v12 = "value12".getBytes(UTF_8); + + try (final DBContainer dbContainer = startDb(); + final ReadOptions readOptions = new ReadOptions()) { + try (final Transaction txn = dbContainer.beginTransaction()) { + txn.put(k1, v1); + txn.commit(); + } + + Transaction txnPrepare; + txnPrepare = dbContainer.beginTransaction(); + txnPrepare.setName("txnPrepare1"); + txnPrepare.put(k1, v12); + txnPrepare.prepare(); + + try (final Transaction txn = dbContainer.beginTransaction()) { + assertThat(txn.get(readOptions, k1)).isEqualTo(v1); + } + + txnPrepare.commit(); + + try (final Transaction txn = dbContainer.beginTransaction()) { + assertThat(txn.get(readOptions, k1)).isEqualTo(v12); + } + } + } + + @Test + public void prepare_read_prepared_rollback() throws RocksDBException { + final byte[] k1 = "key1".getBytes(UTF_8); + final byte[] v1 = "value1".getBytes(UTF_8); + final byte[] v12 = "value12".getBytes(UTF_8); + + try (final DBContainer dbContainer = startDb(); + final ReadOptions readOptions = new ReadOptions()) { + try (final Transaction txn = dbContainer.beginTransaction()) { + txn.put(k1, v1); + txn.commit(); + } + + Transaction txnPrepare; + txnPrepare = dbContainer.beginTransaction(); + txnPrepare.setName("txnPrepare1"); + txnPrepare.put(k1, v12); + txnPrepare.prepare(); + + try (final Transaction txn = dbContainer.beginTransaction()) { + assertThat(txn.get(readOptions, k1)).isEqualTo(v1); + } + + txnPrepare.rollback(); + + try (final Transaction txn = dbContainer.beginTransaction()) { + assertThat(txn.get(readOptions, k1)).isEqualTo(v1); + } + } + } + @Test public void getForUpdate_conflict() throws RocksDBException { final byte[] k1 = "key1".getBytes(UTF_8);