From 8db8b98f98e414b9c2f5b2dd04bb9d6b9c509073 Mon Sep 17 00:00:00 2001 From: Alan Paxton Date: Tue, 26 Jul 2022 17:14:43 -0700 Subject: [PATCH] Transaction.prepare should be public (#10412) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: The absence of a public modifier appears to be an omission. prepare() is necessary for the TM to participate as a peer in a distributed transaction. Also add basic “yes it does work in java” tests. Resolves https://github.com/facebook/rocksdb/issues/10283 Pull Request resolved: https://github.com/facebook/rocksdb/pull/10412 Reviewed By: ajkr Differential Revision: D38135513 Pulled By: riversand963 fbshipit-source-id: ff52b96bc7218bc3bf12845dee49f5d8edf0e297 --- .../main/java/org/rocksdb/Transaction.java | 2 +- .../rocksdb/OptimisticTransactionTest.java | 32 ++++- .../java/org/rocksdb/TransactionTest.java | 114 ++++++++++++++++++ 3 files changed, 142 insertions(+), 6 deletions(-) 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);