You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sa...@apache.org on 2022/10/25 19:20:31 UTC
[ignite-3] branch ignite-3.0.0-beta1 updated: IGNITE-17260 IgniteTransactions and Transaction interfaces enriched with RO related methods (#1248)
This is an automated email from the ASF dual-hosted git repository.
sanpwc pushed a commit to branch ignite-3.0.0-beta1
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/ignite-3.0.0-beta1 by this push:
new 3d5771c5ba IGNITE-17260 IgniteTransactions and Transaction interfaces enriched with RO related methods (#1248)
3d5771c5ba is described below
commit 3d5771c5ba0a7e5ac21f9d08b2b52cb7c781bfb0
Author: Alexander Lapin <la...@gmail.com>
AuthorDate: Tue Oct 25 22:20:25 2022 +0300
IGNITE-17260 IgniteTransactions and Transaction interfaces enriched with RO related methods (#1248)
---
.../org/apache/ignite/tx/IgniteTransactions.java | 7 +
.../java/org/apache/ignite/tx/Transaction.java | 15 ++
.../org/apache/ignite/tx/TransactionException.java | 11 +
.../internal/client/tx/ClientTransaction.java | 15 ++
.../internal/client/tx/ClientTransactions.java | 6 +
.../org/apache/ignite/client/fakes/FakeIgnite.java | 17 ++
.../ignite/client/fakes/FakeInternalTable.java | 31 +++
.../internal/cluster/management/MockNode.java | 2 +-
.../management/raft/ItCmgRaftServiceTest.java | 2 +-
.../ignite/{ => internal}/hlc/HybridClock.java | 2 +-
.../ignite/{ => internal}/hlc/HybridTimestamp.java | 4 +-
.../java/org/apache/ignite/lang/ErrorGroups.java | 7 +
.../ignite/{hlc => internal}/HybridClockTest.java | 4 +-
.../{hlc => internal}/HybridClockTestUtils.java | 2 +-
.../{hlc => internal}/HybridTimestampTest.java | 4 +-
.../apache/ignite/internal/raft/ItLozaTest.java | 2 +-
.../internal/raft/ItRaftGroupServiceTest.java | 2 +-
.../apache/ignite/raft/jraft/core/ItNodeTest.java | 2 +-
.../ignite/raft/server/ItJraftHlcServerTest.java | 2 +-
.../java/org/apache/ignite/internal/raft/Loza.java | 2 +-
.../apache/ignite/raft/jraft/core/NodeImpl.java | 5 +-
.../ignite/raft/jraft/option/NodeOptions.java | 2 +-
.../apache/ignite/raft/jraft/rpc/RpcRequests.java | 2 +-
.../org/apache/ignite/internal/raft/LozaTest.java | 2 +-
.../apache/ignite/raft/jraft/core/TestCluster.java | 2 +-
.../ignite/internal/replicator/ReplicaManager.java | 4 +-
.../ignite/internal/replicator/ReplicaService.java | 2 +-
.../replicator/message/TimestampAware.java | 2 +-
.../ItDistributedConfigurationPropertiesTest.java | 2 +-
.../ItDistributedConfigurationStorageTest.java | 2 +-
.../storage/ItRebalanceDistributedTest.java | 2 +-
.../runner/app/ItIgniteNodeRestartTest.java | 2 +-
.../app/client/ItThinClientTransactionsTest.java | 11 +
.../org/apache/ignite/internal/app/IgniteImpl.java | 2 +-
.../internal/sql/engine/IgniteSqlApiTest.java | 11 +
.../engine/exec/rel/TableScanExecutionTest.java | 2 +-
.../internal/storage/MvPartitionStorage.java | 2 +-
.../internal/storage/PartitionTimestampCursor.java | 2 +-
.../apache/ignite/internal/storage/ReadResult.java | 2 +-
.../storage/AbstractMvPartitionStorageTest.java | 4 +-
.../storage/AbstractMvTableStorageTest.java | 2 +-
.../storage/impl/TestMvPartitionStorage.java | 2 +-
.../mv/AbstractPageMemoryMvPartitionStorage.java | 2 +-
.../storage/pagememory/mv/HybridTimestamps.java | 4 +-
.../storage/pagememory/mv/ReadRowVersion.java | 2 +-
.../internal/storage/pagememory/mv/RowVersion.java | 4 +-
.../storage/pagememory/mv/RowVersionFreeList.java | 2 +-
.../storage/pagememory/mv/io/RowVersionDataIo.java | 2 +-
.../AbstractPageMemoryMvPartitionStorageTest.java | 2 +-
...PersistentPageMemoryMvPartitionStorageTest.java | 2 +-
.../storage/rocksdb/RocksDbMvPartitionStorage.java | 4 +-
.../storage/rocksdb/RocksDbMvTableStorageTest.java | 2 +-
...t.java => ItAbstractInternalTableScanTest.java} | 41 ++--
.../ItInternalTableReadOnlyOperationsTest.java | 260 +++++++++++++++++++++
.../ItInternalTableReadOnlyScanTest.java | 51 ++++
.../ItInternalTableReadWriteScanTest.java} | 27 +--
.../ignite/distributed/ItTablePersistenceTest.java | 4 +-
.../distributed/ItTxDistributedTestSingleNode.java | 22 +-
...butedTestThreeNodesThreeReplicasCollocated.java | 4 +-
.../ignite/internal/table/ItColocationTest.java | 2 +-
.../ignite/internal/table/InternalTable.java | 50 ++++
.../internal/table/distributed/TableManager.java | 2 +-
.../table/distributed/command/FinishTxCommand.java | 2 +-
.../distributed/command/TxCleanupCommand.java | 2 +-
.../snapshot/message/SnapshotMvDataResponse.java | 2 +-
.../request/ReadOnlyReplicaRequest.java | 7 +-
.../ReadOnlyScanRetrieveBatchReplicaRequest.java | 2 +
.../replicator/PartitionReplicaListener.java | 133 ++++++++---
.../distributed/storage/InternalTableImpl.java | 231 +++++++++++++++---
.../ignite/internal/table/TxAbstractTest.java | 120 ++++++++++
.../apache/ignite/internal/table/TxLocalTest.java | 2 +-
.../PartitionRaftCommandsSerializationTest.java | 2 +-
.../raft/PartitionCommandListenerTest.java | 4 +-
.../replication/PartitionReplicaListenerTest.java | 19 +-
.../table/impl/DummyInternalTableImpl.java | 10 +-
.../ignite/internal/tx/InternalTransaction.java | 1 +
.../org/apache/ignite/internal/tx/TxManager.java | 13 +-
.../java/org/apache/ignite/internal/tx/TxMeta.java | 2 +-
.../tx/impl/IgniteAbstractTransactionImpl.java | 107 +++++++++
.../internal/tx/impl/IgniteTransactionsImpl.java | 23 +-
.../internal/tx/impl/ReadOnlyTransactionImpl.java | 101 ++++++++
...tionImpl.java => ReadWriteTransactionImpl.java} | 95 ++------
.../ignite/internal/tx/impl/TxManagerImpl.java | 12 +-
.../tx/message/TxCleanupReplicaRequest.java | 2 +-
.../tx/message/TxFinishReplicaRequest.java | 2 +-
.../internal/tx/message/TxStateReplicaRequest.java | 2 +-
.../apache/ignite/internal/tx/TxManagerTest.java | 2 +-
.../storage/state/TxStateStorageAbstractTest.java | 2 +-
88 files changed, 1326 insertions(+), 271 deletions(-)
diff --git a/modules/api/src/main/java/org/apache/ignite/tx/IgniteTransactions.java b/modules/api/src/main/java/org/apache/ignite/tx/IgniteTransactions.java
index de22c0273d..f4b90ea139 100644
--- a/modules/api/src/main/java/org/apache/ignite/tx/IgniteTransactions.java
+++ b/modules/api/src/main/java/org/apache/ignite/tx/IgniteTransactions.java
@@ -70,6 +70,13 @@ public interface IgniteTransactions {
*/
IgniteTransactions withTimeout(long timeout);
+ /**
+ * Returns a decorated {@code IgniteTransactions} instance that will start read-only transactions.
+ *
+ * @return Decorated {@code IgniteTransactions} instance that will start read-only transactions.
+ */
+ IgniteTransactions readOnly();
+
/**
* Begins a transaction.
*
diff --git a/modules/api/src/main/java/org/apache/ignite/tx/Transaction.java b/modules/api/src/main/java/org/apache/ignite/tx/Transaction.java
index 8086ae4fb3..3caa02de44 100644
--- a/modules/api/src/main/java/org/apache/ignite/tx/Transaction.java
+++ b/modules/api/src/main/java/org/apache/ignite/tx/Transaction.java
@@ -18,6 +18,7 @@
package org.apache.ignite.tx;
import java.util.concurrent.CompletableFuture;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
/**
* The transaction.
@@ -50,4 +51,18 @@ public interface Transaction {
* @return The future.
*/
CompletableFuture<Void> rollbackAsync();
+
+ /**
+ * Returns {code true} if given transaction is a read-only, {@code false otherwise}.
+ *
+ * @return {code true} if given transaction is a read-only, {@code false otherwise}.
+ */
+ boolean isReadOnly();
+
+ /**
+ * Returns read timestamp for the given transaction if it is a read-only one or {code null} otherwise.
+ *
+ * @return Read timestamp for the given transaction if it is a read-only one or {code null} otherwise.
+ */
+ HybridTimestamp readTimestamp();
}
diff --git a/modules/api/src/main/java/org/apache/ignite/tx/TransactionException.java b/modules/api/src/main/java/org/apache/ignite/tx/TransactionException.java
index 0f75c8a614..49895f2737 100644
--- a/modules/api/src/main/java/org/apache/ignite/tx/TransactionException.java
+++ b/modules/api/src/main/java/org/apache/ignite/tx/TransactionException.java
@@ -52,6 +52,17 @@ public class TransactionException extends IgniteException {
super(code, cause);
}
+ /**
+ * Creates a new transaction exception with the given error code and detail message.
+ *
+ * @param code Full error code.
+ * @param message Detail message.
+ */
+ public TransactionException(int code, String message) {
+ super(code, message);
+ }
+
+
/**
* Creates a new transaction exception with the given trace id, error code and cause.
*
diff --git a/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransaction.java b/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransaction.java
index 10fc90e62f..74dce7fb19 100644
--- a/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransaction.java
+++ b/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransaction.java
@@ -23,6 +23,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.ignite.internal.client.ClientChannel;
import org.apache.ignite.internal.client.proto.ClientOp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.tx.Transaction;
import org.apache.ignite.tx.TransactionException;
@@ -118,4 +119,18 @@ public class ClientTransaction implements Transaction {
throw new TransactionException(message);
}
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isReadOnly() {
+ // TODO: IGNITE-17929 Add read-only support to ClientTransactions
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public HybridTimestamp readTimestamp() {
+ // TODO: IGNITE-17929 Add read-only support to ClientTransactions
+ return null;
+ }
}
diff --git a/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransactions.java b/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransactions.java
index 9bfe17c8fc..6572c51a19 100644
--- a/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransactions.java
+++ b/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransactions.java
@@ -59,4 +59,10 @@ public class ClientTransactions implements IgniteTransactions {
public CompletableFuture<Transaction> beginAsync() {
return ch.serviceAsync(ClientOp.TX_BEGIN, w -> {}, r -> new ClientTransaction(r.clientChannel(), r.in().unpackLong()));
}
+
+ @Override
+ public IgniteTransactions readOnly() {
+ // TODO: IGNITE-17929 Add read-only support to ClientTransactions
+ return null;
+ }
}
diff --git a/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeIgnite.java b/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeIgnite.java
index fcaa85853f..85b08b405a 100644
--- a/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeIgnite.java
+++ b/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeIgnite.java
@@ -22,6 +22,7 @@ import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import org.apache.ignite.Ignite;
import org.apache.ignite.compute.IgniteCompute;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.replicator.ReplicationGroupId;
import org.apache.ignite.internal.sql.engine.QueryProcessor;
import org.apache.ignite.internal.tx.InternalTransaction;
@@ -143,8 +144,24 @@ public class FakeIgnite implements Ignite {
public CompletableFuture<Void> rollbackAsync() {
return CompletableFuture.completedFuture(null);
}
+
+ @Override
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ @Override
+ public HybridTimestamp readTimestamp() {
+ return null;
+ }
});
}
+
+ /** {@inheritDoc} */
+ @Override
+ public IgniteTransactions readOnly() {
+ throw new UnsupportedOperationException();
+ }
};
}
diff --git a/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeInternalTable.java b/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeInternalTable.java
index da457b78bf..bef9e1f75e 100644
--- a/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeInternalTable.java
+++ b/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeInternalTable.java
@@ -27,6 +27,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Flow.Publisher;
import java.util.function.BiConsumer;
import javax.naming.OperationNotSupportedException;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.schema.BinaryRow;
import org.apache.ignite.internal.schema.BinaryRowEx;
import org.apache.ignite.internal.storage.engine.MvTableStorage;
@@ -36,6 +37,7 @@ import org.apache.ignite.internal.tx.storage.state.TxStateTableStorage;
import org.apache.ignite.lang.IgniteInternalException;
import org.apache.ignite.network.ClusterNode;
import org.apache.ignite.raft.client.service.RaftGroupService;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -97,6 +99,15 @@ public class FakeInternalTable implements InternalTable {
return CompletableFuture.completedFuture(data.get(keyRow.keySlice()));
}
+ /** {@inheritDoc} */
+ @Override
+ public CompletableFuture<BinaryRow> get(
+ BinaryRowEx keyRow,
+ @NotNull HybridTimestamp readTimestamp,
+ @NotNull ClusterNode recipientNode) {
+ return null;
+ }
+
/** {@inheritDoc} */
@Override
public CompletableFuture<Collection<BinaryRow>> getAll(Collection<BinaryRowEx> keyRows,
@@ -115,6 +126,16 @@ public class FakeInternalTable implements InternalTable {
return CompletableFuture.completedFuture(res);
}
+ /** {@inheritDoc} */
+ @Override
+ public CompletableFuture<Collection<BinaryRow>> getAll(
+ Collection<BinaryRowEx> keyRows,
+ @NotNull HybridTimestamp readTimestamp,
+ @NotNull ClusterNode recipientNode
+ ) {
+ return null;
+ }
+
/** {@inheritDoc} */
@Override
public CompletableFuture<Void> upsert(BinaryRowEx row, @Nullable InternalTransaction tx) {
@@ -302,6 +323,16 @@ public class FakeInternalTable implements InternalTable {
throw new IgniteInternalException(new OperationNotSupportedException());
}
+ /** {@inheritDoc} */
+ @Override
+ public Publisher<BinaryRow> scan(
+ int p,
+ @NotNull HybridTimestamp readTimestamp,
+ @NotNull ClusterNode recipientNode
+ ) {
+ return null;
+ }
+
/** {@inheritDoc} */
@Override
public List<String> assignments() {
diff --git a/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/MockNode.java b/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/MockNode.java
index cebb8067e0..28c95c33b1 100644
--- a/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/MockNode.java
+++ b/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/MockNode.java
@@ -24,8 +24,8 @@ import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
-import org.apache.ignite.hlc.HybridClock;
import org.apache.ignite.internal.cluster.management.raft.RocksDbClusterStateStorage;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.manager.IgniteComponent;
import org.apache.ignite.internal.raft.Loza;
import org.apache.ignite.internal.util.ReverseIterator;
diff --git a/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/raft/ItCmgRaftServiceTest.java b/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/raft/ItCmgRaftServiceTest.java
index abe50a0997..017abd973f 100644
--- a/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/raft/ItCmgRaftServiceTest.java
+++ b/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/raft/ItCmgRaftServiceTest.java
@@ -39,7 +39,6 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
-import org.apache.ignite.hlc.HybridClock;
import org.apache.ignite.internal.cluster.management.ClusterState;
import org.apache.ignite.internal.cluster.management.ClusterTag;
import org.apache.ignite.internal.cluster.management.network.messages.CmgMessagesFactory;
@@ -47,6 +46,7 @@ import org.apache.ignite.internal.cluster.management.raft.commands.JoinReadyComm
import org.apache.ignite.internal.cluster.management.raft.commands.JoinRequestCommand;
import org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
import org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.properties.IgniteProductVersion;
import org.apache.ignite.internal.raft.Loza;
import org.apache.ignite.internal.raft.configuration.RaftConfiguration;
diff --git a/modules/core/src/main/java/org/apache/ignite/hlc/HybridClock.java b/modules/core/src/main/java/org/apache/ignite/internal/hlc/HybridClock.java
similarity index 98%
rename from modules/core/src/main/java/org/apache/ignite/hlc/HybridClock.java
rename to modules/core/src/main/java/org/apache/ignite/internal/hlc/HybridClock.java
index f538239960..591c96c516 100644
--- a/modules/core/src/main/java/org/apache/ignite/hlc/HybridClock.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/hlc/HybridClock.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.ignite.hlc;
+package org.apache.ignite.internal.hlc;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
diff --git a/modules/core/src/main/java/org/apache/ignite/hlc/HybridTimestamp.java b/modules/core/src/main/java/org/apache/ignite/internal/hlc/HybridTimestamp.java
similarity index 95%
rename from modules/core/src/main/java/org/apache/ignite/hlc/HybridTimestamp.java
rename to modules/core/src/main/java/org/apache/ignite/internal/hlc/HybridTimestamp.java
index c086c65524..79495518bc 100644
--- a/modules/core/src/main/java/org/apache/ignite/hlc/HybridTimestamp.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/hlc/HybridTimestamp.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.ignite.hlc;
+package org.apache.ignite.internal.hlc;
import java.io.Serializable;
import org.apache.ignite.internal.tostring.S;
@@ -48,7 +48,7 @@ public final class HybridTimestamp implements Comparable<HybridTimestamp>, Seria
*/
public HybridTimestamp(long physical, int logical) {
assert physical > 0 : physical;
- // Value -1 is used in "org.apache.ignite.hlc.HybridClock.update" to produce "0" after the increment.
+ // Value -1 is used in "org.apache.ignite.internal.hlc.HybridClock.update" to produce "0" after the increment.
// Real usable value cannot be negative.
assert logical >= -1 : logical;
diff --git a/modules/core/src/main/java/org/apache/ignite/lang/ErrorGroups.java b/modules/core/src/main/java/org/apache/ignite/lang/ErrorGroups.java
index 0d4a3d8c78..0edbbd3b69 100755
--- a/modules/core/src/main/java/org/apache/ignite/lang/ErrorGroups.java
+++ b/modules/core/src/main/java/org/apache/ignite/lang/ErrorGroups.java
@@ -276,6 +276,9 @@ public class ErrorGroups {
/** Failed to rollback a transaction. */
public static final int TX_ROLLBACK_ERR = TX_ERR_GROUP.registerErrorCode(8);
+
+ /** Failed to enlist read-write operation into read-only transaction. */
+ public static final int TX_INSUFFICIENT_READ_WRITE_OPERATION_ERR = TX_ERR_GROUP.registerErrorCode(9);
}
/** Replicator error group. */
@@ -300,6 +303,10 @@ public class ErrorGroups {
/** The error happens when the replica is not the current primary replica. */
public static final int REPLICA_MISS_ERR = REPLICATOR_ERR_GROUP.registerErrorCode(6);
+
+ /** Failed to close cursor. */
+ public static final int CURSOR_CLOSE_ERR = REPLICATOR_ERR_GROUP.registerErrorCode(7);
+
}
/** Storage error group. */
diff --git a/modules/core/src/test/java/org/apache/ignite/hlc/HybridClockTest.java b/modules/core/src/test/java/org/apache/ignite/internal/HybridClockTest.java
similarity index 96%
rename from modules/core/src/test/java/org/apache/ignite/hlc/HybridClockTest.java
rename to modules/core/src/test/java/org/apache/ignite/internal/HybridClockTest.java
index 3962b97e30..5442de531b 100644
--- a/modules/core/src/test/java/org/apache/ignite/hlc/HybridClockTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/HybridClockTest.java
@@ -15,9 +15,9 @@
* limitations under the License.
*/
-package org.apache.ignite.hlc;
+package org.apache.ignite.internal.hlc;
-import static org.apache.ignite.hlc.HybridClockTestUtils.mockToEpochMilli;
+import static org.apache.ignite.internal.hlc.HybridClockTestUtils.mockToEpochMilli;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.time.Clock;
diff --git a/modules/core/src/test/java/org/apache/ignite/hlc/HybridClockTestUtils.java b/modules/core/src/test/java/org/apache/ignite/internal/HybridClockTestUtils.java
similarity index 97%
rename from modules/core/src/test/java/org/apache/ignite/hlc/HybridClockTestUtils.java
rename to modules/core/src/test/java/org/apache/ignite/internal/HybridClockTestUtils.java
index 8d244f4feb..cb30cd2686 100644
--- a/modules/core/src/test/java/org/apache/ignite/hlc/HybridClockTestUtils.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/HybridClockTestUtils.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.ignite.hlc;
+package org.apache.ignite.internal.hlc;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.spy;
diff --git a/modules/core/src/test/java/org/apache/ignite/hlc/HybridTimestampTest.java b/modules/core/src/test/java/org/apache/ignite/internal/HybridTimestampTest.java
similarity index 93%
rename from modules/core/src/test/java/org/apache/ignite/hlc/HybridTimestampTest.java
rename to modules/core/src/test/java/org/apache/ignite/internal/HybridTimestampTest.java
index bf111500c1..95a5429a00 100644
--- a/modules/core/src/test/java/org/apache/ignite/hlc/HybridTimestampTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/HybridTimestampTest.java
@@ -15,9 +15,9 @@
* limitations under the License.
*/
-package org.apache.ignite.hlc;
+package org.apache.ignite.internal.hlc;
-import static org.apache.ignite.hlc.HybridTimestamp.max;
+import static org.apache.ignite.internal.hlc.HybridTimestamp.max;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
diff --git a/modules/raft/src/integrationTest/java/org/apache/ignite/internal/raft/ItLozaTest.java b/modules/raft/src/integrationTest/java/org/apache/ignite/internal/raft/ItLozaTest.java
index a100881f07..b4d247f228 100644
--- a/modules/raft/src/integrationTest/java/org/apache/ignite/internal/raft/ItLozaTest.java
+++ b/modules/raft/src/integrationTest/java/org/apache/ignite/internal/raft/ItLozaTest.java
@@ -36,9 +36,9 @@ import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
-import org.apache.ignite.hlc.HybridClock;
import org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
import org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.raft.configuration.RaftConfiguration;
import org.apache.ignite.internal.replicator.ReplicationGroupId;
import org.apache.ignite.internal.testframework.WorkDirectory;
diff --git a/modules/raft/src/integrationTest/java/org/apache/ignite/internal/raft/ItRaftGroupServiceTest.java b/modules/raft/src/integrationTest/java/org/apache/ignite/internal/raft/ItRaftGroupServiceTest.java
index f17cb31bd3..2ba4b40c49 100644
--- a/modules/raft/src/integrationTest/java/org/apache/ignite/internal/raft/ItRaftGroupServiceTest.java
+++ b/modules/raft/src/integrationTest/java/org/apache/ignite/internal/raft/ItRaftGroupServiceTest.java
@@ -32,9 +32,9 @@ import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
-import org.apache.ignite.hlc.HybridClock;
import org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
import org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.raft.configuration.RaftConfiguration;
import org.apache.ignite.internal.replicator.ReplicationGroupId;
import org.apache.ignite.internal.testframework.WorkDirectory;
diff --git a/modules/raft/src/integrationTest/java/org/apache/ignite/raft/jraft/core/ItNodeTest.java b/modules/raft/src/integrationTest/java/org/apache/ignite/raft/jraft/core/ItNodeTest.java
index 0357964a78..55210e4cd3 100644
--- a/modules/raft/src/integrationTest/java/org/apache/ignite/raft/jraft/core/ItNodeTest.java
+++ b/modules/raft/src/integrationTest/java/org/apache/ignite/raft/jraft/core/ItNodeTest.java
@@ -68,7 +68,7 @@ import java.util.function.BiPredicate;
import java.util.function.BooleanSupplier;
import java.util.stream.IntStream;
import java.util.stream.Stream;
-import org.apache.ignite.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.logger.IgniteLogger;
import org.apache.ignite.internal.logger.Loggers;
import org.apache.ignite.internal.raft.server.RaftGroupEventsListener;
diff --git a/modules/raft/src/integrationTest/java/org/apache/ignite/raft/server/ItJraftHlcServerTest.java b/modules/raft/src/integrationTest/java/org/apache/ignite/raft/server/ItJraftHlcServerTest.java
index 2ae91d709d..6cf4cd74fd 100644
--- a/modules/raft/src/integrationTest/java/org/apache/ignite/raft/server/ItJraftHlcServerTest.java
+++ b/modules/raft/src/integrationTest/java/org/apache/ignite/raft/server/ItJraftHlcServerTest.java
@@ -32,7 +32,7 @@ import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
-import org.apache.ignite.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.logger.IgniteLogger;
import org.apache.ignite.internal.logger.Loggers;
import org.apache.ignite.internal.raft.server.RaftServer;
diff --git a/modules/raft/src/main/java/org/apache/ignite/internal/raft/Loza.java b/modules/raft/src/main/java/org/apache/ignite/internal/raft/Loza.java
index 387b8008fa..83238dd978 100644
--- a/modules/raft/src/main/java/org/apache/ignite/internal/raft/Loza.java
+++ b/modules/raft/src/main/java/org/apache/ignite/internal/raft/Loza.java
@@ -28,7 +28,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;
import java.util.stream.Collectors;
-import org.apache.ignite.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.logger.IgniteLogger;
import org.apache.ignite.internal.logger.Loggers;
import org.apache.ignite.internal.manager.IgniteComponent;
diff --git a/modules/raft/src/main/java/org/apache/ignite/raft/jraft/core/NodeImpl.java b/modules/raft/src/main/java/org/apache/ignite/raft/jraft/core/NodeImpl.java
index 1afcfe934e..064546cb0f 100644
--- a/modules/raft/src/main/java/org/apache/ignite/raft/jraft/core/NodeImpl.java
+++ b/modules/raft/src/main/java/org/apache/ignite/raft/jraft/core/NodeImpl.java
@@ -34,8 +34,8 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.stream.Collectors;
-import org.apache.ignite.hlc.HybridClock;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.logger.IgniteLogger;
import org.apache.ignite.internal.logger.Loggers;
import org.apache.ignite.internal.thread.NamedThreadFactory;
@@ -90,7 +90,6 @@ import org.apache.ignite.raft.jraft.rpc.RaftClientService;
import org.apache.ignite.raft.jraft.rpc.RaftRpcFactory;
import org.apache.ignite.raft.jraft.rpc.RaftServerService;
import org.apache.ignite.raft.jraft.rpc.ReadIndexResponseBuilder;
-import org.apache.ignite.raft.jraft.rpc.RequestVoteResponseBuilder;
import org.apache.ignite.raft.jraft.rpc.RpcRequestClosure;
import org.apache.ignite.raft.jraft.rpc.RpcRequests.AppendEntriesRequest;
import org.apache.ignite.raft.jraft.rpc.RpcRequests.AppendEntriesResponse;
diff --git a/modules/raft/src/main/java/org/apache/ignite/raft/jraft/option/NodeOptions.java b/modules/raft/src/main/java/org/apache/ignite/raft/jraft/option/NodeOptions.java
index a56b1e9eaf..158efeeb95 100644
--- a/modules/raft/src/main/java/org/apache/ignite/raft/jraft/option/NodeOptions.java
+++ b/modules/raft/src/main/java/org/apache/ignite/raft/jraft/option/NodeOptions.java
@@ -18,7 +18,7 @@ package org.apache.ignite.raft.jraft.option;
import java.util.List;
import java.util.concurrent.ExecutorService;
-import org.apache.ignite.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.raft.server.RaftGroupEventsListener;
import org.apache.ignite.raft.jraft.JRaftServiceFactory;
import org.apache.ignite.raft.jraft.StateMachine;
diff --git a/modules/raft/src/main/java/org/apache/ignite/raft/jraft/rpc/RpcRequests.java b/modules/raft/src/main/java/org/apache/ignite/raft/jraft/rpc/RpcRequests.java
index f0d0571922..91dbde9cfb 100644
--- a/modules/raft/src/main/java/org/apache/ignite/raft/jraft/rpc/RpcRequests.java
+++ b/modules/raft/src/main/java/org/apache/ignite/raft/jraft/rpc/RpcRequests.java
@@ -19,7 +19,7 @@ package org.apache.ignite.raft.jraft.rpc;
import java.util.Collection;
import java.util.List;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.network.annotations.Marshallable;
import org.apache.ignite.network.annotations.Transferable;
import org.apache.ignite.raft.jraft.RaftMessageGroup;
diff --git a/modules/raft/src/test/java/org/apache/ignite/internal/raft/LozaTest.java b/modules/raft/src/test/java/org/apache/ignite/internal/raft/LozaTest.java
index 3960ba2d57..6cc9758794 100644
--- a/modules/raft/src/test/java/org/apache/ignite/internal/raft/LozaTest.java
+++ b/modules/raft/src/test/java/org/apache/ignite/internal/raft/LozaTest.java
@@ -25,7 +25,7 @@ import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.function.Supplier;
-import org.apache.ignite.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.raft.configuration.RaftConfiguration;
import org.apache.ignite.internal.replicator.ReplicationGroupId;
import org.apache.ignite.internal.testframework.IgniteAbstractTest;
diff --git a/modules/raft/src/test/java/org/apache/ignite/raft/jraft/core/TestCluster.java b/modules/raft/src/test/java/org/apache/ignite/raft/jraft/core/TestCluster.java
index 351ec74972..6cb5e9614c 100644
--- a/modules/raft/src/test/java/org/apache/ignite/raft/jraft/core/TestCluster.java
+++ b/modules/raft/src/test/java/org/apache/ignite/raft/jraft/core/TestCluster.java
@@ -39,7 +39,7 @@ import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
-import org.apache.ignite.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.logger.IgniteLogger;
import org.apache.ignite.internal.logger.Loggers;
import org.apache.ignite.internal.raft.server.RaftGroupEventsListener;
diff --git a/modules/replicator/src/main/java/org/apache/ignite/internal/replicator/ReplicaManager.java b/modules/replicator/src/main/java/org/apache/ignite/internal/replicator/ReplicaManager.java
index e91c644f1e..a15fd2b7cc 100644
--- a/modules/replicator/src/main/java/org/apache/ignite/internal/replicator/ReplicaManager.java
+++ b/modules/replicator/src/main/java/org/apache/ignite/internal/replicator/ReplicaManager.java
@@ -22,8 +22,8 @@ import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
-import org.apache.ignite.hlc.HybridClock;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.logger.IgniteLogger;
import org.apache.ignite.internal.logger.Loggers;
import org.apache.ignite.internal.manager.IgniteComponent;
diff --git a/modules/replicator/src/main/java/org/apache/ignite/internal/replicator/ReplicaService.java b/modules/replicator/src/main/java/org/apache/ignite/internal/replicator/ReplicaService.java
index 26cf100d05..86e71be80a 100644
--- a/modules/replicator/src/main/java/org/apache/ignite/internal/replicator/ReplicaService.java
+++ b/modules/replicator/src/main/java/org/apache/ignite/internal/replicator/ReplicaService.java
@@ -23,7 +23,7 @@ import static org.apache.ignite.lang.ErrorGroups.Replicator.REPLICA_COMMON_ERR;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.TimeoutException;
-import org.apache.ignite.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.replicator.exception.ReplicaUnavailableException;
import org.apache.ignite.internal.replicator.exception.ReplicationException;
import org.apache.ignite.internal.replicator.exception.ReplicationTimeoutException;
diff --git a/modules/replicator/src/main/java/org/apache/ignite/internal/replicator/message/TimestampAware.java b/modules/replicator/src/main/java/org/apache/ignite/internal/replicator/message/TimestampAware.java
index f63712d651..60c31942b6 100644
--- a/modules/replicator/src/main/java/org/apache/ignite/internal/replicator/message/TimestampAware.java
+++ b/modules/replicator/src/main/java/org/apache/ignite/internal/replicator/message/TimestampAware.java
@@ -17,7 +17,7 @@
package org.apache.ignite.internal.replicator.message;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.network.NetworkMessage;
import org.apache.ignite.network.annotations.Marshallable;
import org.apache.ignite.network.annotations.Transferable;
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDistributedConfigurationPropertiesTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDistributedConfigurationPropertiesTest.java
index cb9ff5c2ba..822a1604a0 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDistributedConfigurationPropertiesTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDistributedConfigurationPropertiesTest.java
@@ -37,13 +37,13 @@ import org.apache.ignite.configuration.ConfigurationValue;
import org.apache.ignite.configuration.annotation.ConfigurationRoot;
import org.apache.ignite.configuration.annotation.ConfigurationType;
import org.apache.ignite.configuration.annotation.Value;
-import org.apache.ignite.hlc.HybridClock;
import org.apache.ignite.internal.cluster.management.ClusterManagementGroupManager;
import org.apache.ignite.internal.cluster.management.raft.TestClusterStateStorage;
import org.apache.ignite.internal.configuration.storage.ConfigurationStorageListener;
import org.apache.ignite.internal.configuration.storage.DistributedConfigurationStorage;
import org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
import org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.manager.IgniteComponent;
import org.apache.ignite.internal.metastorage.MetaStorageManager;
import org.apache.ignite.internal.metastorage.server.SimpleInMemoryKeyValueStorage;
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/storage/ItDistributedConfigurationStorageTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/storage/ItDistributedConfigurationStorageTest.java
index e27b67e093..ce14c25d27 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/storage/ItDistributedConfigurationStorageTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/storage/ItDistributedConfigurationStorageTest.java
@@ -30,11 +30,11 @@ import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Stream;
-import org.apache.ignite.hlc.HybridClock;
import org.apache.ignite.internal.cluster.management.ClusterManagementGroupManager;
import org.apache.ignite.internal.cluster.management.raft.TestClusterStateStorage;
import org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
import org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.manager.IgniteComponent;
import org.apache.ignite.internal.metastorage.MetaStorageManager;
import org.apache.ignite.internal.metastorage.server.SimpleInMemoryKeyValueStorage;
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/storage/ItRebalanceDistributedTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/storage/ItRebalanceDistributedTest.java
index 83c9c25382..7c6a1c1190 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/storage/ItRebalanceDistributedTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/storage/ItRebalanceDistributedTest.java
@@ -39,13 +39,13 @@ import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.apache.ignite.client.handler.configuration.ClientConnectorConfiguration;
import org.apache.ignite.configuration.schemas.network.NetworkConfiguration;
-import org.apache.ignite.hlc.HybridClock;
import org.apache.ignite.internal.baseline.BaselineManager;
import org.apache.ignite.internal.cluster.management.ClusterManagementGroupManager;
import org.apache.ignite.internal.cluster.management.raft.TestClusterStateStorage;
import org.apache.ignite.internal.configuration.ConfigurationManager;
import org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
import org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.logger.IgniteLogger;
import org.apache.ignite.internal.logger.Loggers;
import org.apache.ignite.internal.manager.IgniteComponent;
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
index 87d1c17d27..25c353226f 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
@@ -49,7 +49,6 @@ import java.util.stream.IntStream;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgnitionManager;
import org.apache.ignite.configuration.schemas.network.NetworkConfiguration;
-import org.apache.ignite.hlc.HybridClock;
import org.apache.ignite.internal.app.IgniteImpl;
import org.apache.ignite.internal.baseline.BaselineManager;
import org.apache.ignite.internal.cluster.management.ClusterManagementGroupManager;
@@ -64,6 +63,7 @@ import org.apache.ignite.internal.configuration.storage.DistributedConfiguration
import org.apache.ignite.internal.configuration.storage.LocalConfigurationStorage;
import org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
import org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.logger.IgniteLogger;
import org.apache.ignite.internal.manager.IgniteComponent;
import org.apache.ignite.internal.metastorage.MetaStorageManager;
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientTransactionsTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientTransactionsTest.java
index 4920f5bdd5..6824e411c0 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientTransactionsTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientTransactionsTest.java
@@ -29,6 +29,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import org.apache.ignite.client.IgniteClient;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.lang.IgniteException;
import org.apache.ignite.table.KeyValueView;
import org.apache.ignite.table.RecordView;
@@ -233,6 +234,16 @@ public class ItThinClientTransactionsTest extends ItAbstractThinClientTest {
public CompletableFuture<Void> rollbackAsync() {
return null;
}
+
+ @Override
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ @Override
+ public HybridTimestamp readTimestamp() {
+ return null;
+ }
};
var ex = assertThrows(IgniteException.class, () -> kvView().put(tx, 1, "1"));
diff --git a/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
index 178c16f26a..4a9f9e97f3 100644
--- a/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
+++ b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
@@ -34,7 +34,6 @@ import org.apache.ignite.IgnitionManager;
import org.apache.ignite.client.handler.ClientHandlerModule;
import org.apache.ignite.compute.IgniteCompute;
import org.apache.ignite.configuration.schemas.network.NetworkConfiguration;
-import org.apache.ignite.hlc.HybridClock;
import org.apache.ignite.internal.baseline.BaselineManager;
import org.apache.ignite.internal.cluster.management.ClusterManagementGroupManager;
import org.apache.ignite.internal.cluster.management.network.messages.CmgMessagesSerializationRegistryInitializer;
@@ -54,6 +53,7 @@ import org.apache.ignite.internal.configuration.ServiceLoaderModulesProvider;
import org.apache.ignite.internal.configuration.storage.ConfigurationStorage;
import org.apache.ignite.internal.configuration.storage.DistributedConfigurationStorage;
import org.apache.ignite.internal.configuration.storage.LocalConfigurationStorage;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.index.IndexManager;
import org.apache.ignite.internal.logger.IgniteLogger;
import org.apache.ignite.internal.logger.Loggers;
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/IgniteSqlApiTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/IgniteSqlApiTest.java
index 41bac8c4ce..3b8b3a1aa0 100644
--- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/IgniteSqlApiTest.java
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/IgniteSqlApiTest.java
@@ -34,6 +34,7 @@ import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.schema.Column;
import org.apache.ignite.internal.schema.NativeTypes;
import org.apache.ignite.internal.schema.SchemaDescriptor;
@@ -664,5 +665,15 @@ public class IgniteSqlApiTest {
rollback();
return CompletableFuture.completedFuture(null);
}
+
+ @Override
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ @Override
+ public HybridTimestamp readTimestamp() {
+ return null;
+ }
}
}
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/rel/TableScanExecutionTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/rel/TableScanExecutionTest.java
index b1ab1d1a35..47d70d6953 100644
--- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/rel/TableScanExecutionTest.java
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/rel/TableScanExecutionTest.java
@@ -28,7 +28,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadLocalRandom;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.util.ImmutableBitSet;
-import org.apache.ignite.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.replicator.ReplicaService;
import org.apache.ignite.internal.schema.BinaryRow;
import org.apache.ignite.internal.schema.ByteBufferRow;
diff --git a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/MvPartitionStorage.java b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/MvPartitionStorage.java
index 8e742f54d3..7f87994f03 100644
--- a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/MvPartitionStorage.java
+++ b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/MvPartitionStorage.java
@@ -20,7 +20,7 @@ package org.apache.ignite.internal.storage;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.schema.BinaryRow;
import org.apache.ignite.internal.util.Cursor;
import org.jetbrains.annotations.Nullable;
diff --git a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/PartitionTimestampCursor.java b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/PartitionTimestampCursor.java
index dd11f5d4e1..308f882541 100644
--- a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/PartitionTimestampCursor.java
+++ b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/PartitionTimestampCursor.java
@@ -17,7 +17,7 @@
package org.apache.ignite.internal.storage;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.schema.BinaryRow;
import org.apache.ignite.internal.util.Cursor;
import org.jetbrains.annotations.Nullable;
diff --git a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/ReadResult.java b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/ReadResult.java
index 41819efe8e..735f7dfb11 100644
--- a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/ReadResult.java
+++ b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/ReadResult.java
@@ -18,7 +18,7 @@
package org.apache.ignite.internal.storage;
import java.util.UUID;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.schema.BinaryRow;
import org.jetbrains.annotations.Nullable;
diff --git a/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/AbstractMvPartitionStorageTest.java b/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/AbstractMvPartitionStorageTest.java
index 09e1b2cc3a..98e25e1f2f 100644
--- a/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/AbstractMvPartitionStorageTest.java
+++ b/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/AbstractMvPartitionStorageTest.java
@@ -41,8 +41,8 @@ import java.util.NoSuchElementException;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
-import org.apache.ignite.hlc.HybridClock;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.schema.BinaryRow;
import org.apache.ignite.internal.tx.Timestamp;
import org.apache.ignite.internal.util.Cursor;
diff --git a/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/AbstractMvTableStorageTest.java b/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/AbstractMvTableStorageTest.java
index 995a856848..13f251f9be 100644
--- a/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/AbstractMvTableStorageTest.java
+++ b/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/AbstractMvTableStorageTest.java
@@ -33,9 +33,9 @@ import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
-import org.apache.ignite.hlc.HybridTimestamp;
import org.apache.ignite.internal.binarytuple.BinaryTupleBuilder;
import org.apache.ignite.internal.configuration.util.ConfigurationUtil;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.schema.BinaryTuple;
import org.apache.ignite.internal.schema.BinaryTupleSchema;
import org.apache.ignite.internal.schema.BinaryTupleSchema.Element;
diff --git a/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/impl/TestMvPartitionStorage.java b/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/impl/TestMvPartitionStorage.java
index 846cfe78f2..f6043ae9a8 100644
--- a/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/impl/TestMvPartitionStorage.java
+++ b/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/impl/TestMvPartitionStorage.java
@@ -27,7 +27,7 @@ import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.function.BiConsumer;
import java.util.stream.Stream;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.schema.BinaryRow;
import org.apache.ignite.internal.storage.MvPartitionStorage;
import org.apache.ignite.internal.storage.PartitionTimestampCursor;
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/AbstractPageMemoryMvPartitionStorage.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/AbstractPageMemoryMvPartitionStorage.java
index eaf33041c3..60dccdc65e 100644
--- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/AbstractPageMemoryMvPartitionStorage.java
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/AbstractPageMemoryMvPartitionStorage.java
@@ -31,7 +31,7 @@ import java.util.function.BiConsumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
import org.apache.ignite.configuration.NamedListView;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.pagememory.PageIdAllocator;
import org.apache.ignite.internal.pagememory.PageMemory;
import org.apache.ignite.internal.pagememory.datapage.DataPageReader;
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/HybridTimestamps.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/HybridTimestamps.java
index 542c0aa182..e04848be7b 100644
--- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/HybridTimestamps.java
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/HybridTimestamps.java
@@ -17,14 +17,14 @@
package org.apache.ignite.internal.storage.pagememory.mv;
-import static org.apache.ignite.hlc.HybridTimestamp.HYBRID_TIMESTAMP_SIZE;
+import static org.apache.ignite.internal.hlc.HybridTimestamp.HYBRID_TIMESTAMP_SIZE;
import static org.apache.ignite.internal.pagememory.util.PageUtils.getInt;
import static org.apache.ignite.internal.pagememory.util.PageUtils.getLong;
import static org.apache.ignite.internal.pagememory.util.PageUtils.putInt;
import static org.apache.ignite.internal.pagememory.util.PageUtils.putLong;
import java.nio.ByteBuffer;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.jetbrains.annotations.Nullable;
/**
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/ReadRowVersion.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/ReadRowVersion.java
index 5d60a27b15..e5f83b0650 100644
--- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/ReadRowVersion.java
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/ReadRowVersion.java
@@ -21,7 +21,7 @@ import static org.apache.ignite.internal.pagememory.util.PartitionlessLinks.read
import java.nio.ByteBuffer;
import java.util.function.Predicate;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.pagememory.datapage.PageMemoryTraversal;
import org.apache.ignite.internal.pagememory.io.DataPagePayload;
import org.apache.ignite.internal.pagememory.util.PageIdUtils;
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/RowVersion.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/RowVersion.java
index c51d8b888b..200ddee03f 100644
--- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/RowVersion.java
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/RowVersion.java
@@ -17,12 +17,12 @@
package org.apache.ignite.internal.storage.pagememory.mv;
-import static org.apache.ignite.hlc.HybridTimestamp.HYBRID_TIMESTAMP_SIZE;
+import static org.apache.ignite.internal.hlc.HybridTimestamp.HYBRID_TIMESTAMP_SIZE;
import static org.apache.ignite.internal.pagememory.util.PageIdUtils.NULL_LINK;
import java.nio.ByteBuffer;
import java.util.Objects;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.pagememory.Storable;
import org.apache.ignite.internal.pagememory.io.AbstractDataPageIo;
import org.apache.ignite.internal.pagememory.io.IoVersions;
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/RowVersionFreeList.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/RowVersionFreeList.java
index 56546140fd..3bc3cac725 100644
--- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/RowVersionFreeList.java
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/RowVersionFreeList.java
@@ -18,7 +18,7 @@
package org.apache.ignite.internal.storage.pagememory.mv;
import java.util.concurrent.atomic.AtomicLong;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.logger.IgniteLogger;
import org.apache.ignite.internal.logger.Loggers;
import org.apache.ignite.internal.pagememory.PageMemory;
diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/RowVersionDataIo.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/RowVersionDataIo.java
index 5b0ec438df..fd1913792a 100644
--- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/RowVersionDataIo.java
+++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/io/RowVersionDataIo.java
@@ -23,7 +23,7 @@ import static org.apache.ignite.internal.pagememory.util.PageUtils.putShort;
import static org.apache.ignite.internal.pagememory.util.PartitionlessLinks.writePartitionless;
import java.nio.ByteBuffer;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.pagememory.io.AbstractDataPageIo;
import org.apache.ignite.internal.pagememory.io.IoVersions;
import org.apache.ignite.internal.pagememory.util.PartitionlessLinks;
diff --git a/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/mv/AbstractPageMemoryMvPartitionStorageTest.java b/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/mv/AbstractPageMemoryMvPartitionStorageTest.java
index 42c22c02fa..7d6cf962b0 100644
--- a/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/mv/AbstractPageMemoryMvPartitionStorageTest.java
+++ b/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/mv/AbstractPageMemoryMvPartitionStorageTest.java
@@ -20,7 +20,7 @@ package org.apache.ignite.internal.storage.pagememory.mv;
import static java.util.stream.Collectors.joining;
import java.util.stream.IntStream;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.pagememory.io.PageIoRegistry;
import org.apache.ignite.internal.schema.BinaryRow;
import org.apache.ignite.internal.storage.AbstractMvPartitionStorageTest;
diff --git a/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorageTest.java b/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorageTest.java
index 9290509941..d6eed10be8 100644
--- a/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorageTest.java
+++ b/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorageTest.java
@@ -21,10 +21,10 @@ import static org.apache.ignite.internal.pagememory.persistence.checkpoint.Check
import java.nio.file.Path;
import java.util.concurrent.TimeUnit;
-import org.apache.ignite.hlc.HybridTimestamp;
import org.apache.ignite.internal.components.LongJvmPauseDetector;
import org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
import org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.logger.Loggers;
import org.apache.ignite.internal.schema.configuration.TablesConfiguration;
import org.apache.ignite.internal.storage.RowId;
diff --git a/modules/storage-rocksdb/src/main/java/org/apache/ignite/internal/storage/rocksdb/RocksDbMvPartitionStorage.java b/modules/storage-rocksdb/src/main/java/org/apache/ignite/internal/storage/rocksdb/RocksDbMvPartitionStorage.java
index cebb731a4a..85375c72ac 100644
--- a/modules/storage-rocksdb/src/main/java/org/apache/ignite/internal/storage/rocksdb/RocksDbMvPartitionStorage.java
+++ b/modules/storage-rocksdb/src/main/java/org/apache/ignite/internal/storage/rocksdb/RocksDbMvPartitionStorage.java
@@ -21,7 +21,7 @@ import static java.lang.ThreadLocal.withInitial;
import static java.nio.ByteBuffer.allocateDirect;
import static java.util.Arrays.copyOf;
import static java.util.Arrays.copyOfRange;
-import static org.apache.ignite.hlc.HybridTimestamp.HYBRID_TIMESTAMP_SIZE;
+import static org.apache.ignite.internal.hlc.HybridTimestamp.HYBRID_TIMESTAMP_SIZE;
import static org.apache.ignite.internal.util.ByteUtils.bytesToLong;
import static org.apache.ignite.internal.util.ByteUtils.bytesToUuid;
import static org.apache.ignite.internal.util.ByteUtils.putUuidToBytes;
@@ -35,7 +35,7 @@ import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.rocksdb.RocksIteratorAdapter;
import org.apache.ignite.internal.rocksdb.RocksUtils;
import org.apache.ignite.internal.schema.BinaryRow;
diff --git a/modules/storage-rocksdb/src/test/java/org/apache/ignite/internal/storage/rocksdb/RocksDbMvTableStorageTest.java b/modules/storage-rocksdb/src/test/java/org/apache/ignite/internal/storage/rocksdb/RocksDbMvTableStorageTest.java
index d7920537bc..038404585b 100644
--- a/modules/storage-rocksdb/src/test/java/org/apache/ignite/internal/storage/rocksdb/RocksDbMvTableStorageTest.java
+++ b/modules/storage-rocksdb/src/test/java/org/apache/ignite/internal/storage/rocksdb/RocksDbMvTableStorageTest.java
@@ -28,9 +28,9 @@ import static org.hamcrest.MatcherAssert.assertThat;
import java.nio.file.Path;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
-import org.apache.ignite.hlc.HybridTimestamp;
import org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
import org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.schema.configuration.TablesConfiguration;
import org.apache.ignite.internal.storage.AbstractMvTableStorageTest;
import org.apache.ignite.internal.storage.MvPartitionStorage;
diff --git a/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItInternalTableScanTest.java b/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItAbstractInternalTableScanTest.java
similarity index 92%
rename from modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItInternalTableScanTest.java
rename to modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItAbstractInternalTableScanTest.java
index 714b50818e..47218e7f57 100644
--- a/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItInternalTableScanTest.java
+++ b/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItAbstractInternalTableScanTest.java
@@ -36,13 +36,14 @@ import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Flow;
+import java.util.concurrent.Flow.Publisher;
import java.util.concurrent.Flow.Subscriber;
import java.util.concurrent.Flow.Subscription;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
-import org.apache.ignite.hlc.HybridClock;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.replicator.ReplicaService;
import org.apache.ignite.internal.schema.BinaryRow;
import org.apache.ignite.internal.schema.ByteBufferRow;
@@ -53,6 +54,8 @@ import org.apache.ignite.internal.storage.ReadResult;
import org.apache.ignite.internal.storage.StorageException;
import org.apache.ignite.internal.table.InternalTable;
import org.apache.ignite.internal.table.impl.DummyInternalTableImpl;
+import org.apache.ignite.internal.testframework.IgniteAbstractTest;
+import org.apache.ignite.internal.tx.InternalTransaction;
import org.apache.ignite.internal.util.ByteUtils;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.BeforeEach;
@@ -67,13 +70,13 @@ import org.mockito.junit.jupiter.MockitoExtension;
* Tests for {@link InternalTable#scan(int, org.apache.ignite.internal.tx.InternalTransaction)}.
*/
@ExtendWith(MockitoExtension.class)
-public class ItInternalTableScanTest {
+public abstract class ItAbstractInternalTableScanTest extends IgniteAbstractTest {
/** Mock partition storage. */
@Mock
private MvPartitionStorage mockStorage;
/** Internal table to test. */
- private InternalTable internalTbl;
+ protected InternalTable internalTbl;
private final HybridClock clock = new HybridClock();
@@ -182,7 +185,7 @@ public class ItInternalTableScanTest {
return cursor;
});
- internalTbl.scan(0, null).subscribe(new Subscriber<>() {
+ scan(0, null).subscribe(new Subscriber<>() {
@Override
public void onSubscribe(Subscription subscription) {
@@ -223,7 +226,7 @@ public class ItInternalTableScanTest {
when(mockStorage.scan(any(HybridTimestamp.class))).thenThrow(new StorageException("Some storage exception"));
- internalTbl.scan(0, null).subscribe(new Subscriber<>() {
+ scan(0, null).subscribe(new Subscriber<>() {
@Override
public void onSubscribe(Subscription subscription) {
@@ -260,12 +263,12 @@ public class ItInternalTableScanTest {
public void testInvalidPartitionParameterScan() {
assertThrows(
IllegalArgumentException.class,
- () -> internalTbl.scan(-1, null)
+ () -> scan(-1, null)
);
assertThrows(
IllegalArgumentException.class,
- () -> internalTbl.scan(1, null)
+ () -> scan(1, null)
);
}
@@ -276,7 +279,7 @@ public class ItInternalTableScanTest {
*/
@Test
public void testSecondSubscriptionFiresIllegalStateException() throws Exception {
- Flow.Publisher<BinaryRow> scan = internalTbl.scan(0, null);
+ Flow.Publisher<BinaryRow> scan = scan(0, null);
scan.subscribe(new Subscriber<>() {
@Override
@@ -340,7 +343,7 @@ public class ItInternalTableScanTest {
public void testNullPointerExceptionIsThrownInCaseOfNullSubscription() {
assertThrows(
NullPointerException.class,
- () -> internalTbl.scan(0, null).subscribe(null)
+ () -> scan(0, null).subscribe(null)
);
}
@@ -352,8 +355,7 @@ public class ItInternalTableScanTest {
* @return {@link DataRow} based on given key and value.
* @throws java.io.IOException If failed to close output stream that was used to convertation.
*/
- private static @NotNull BinaryRow prepareRow(@NotNull String entryKey,
- @NotNull String entryVal) throws IOException {
+ private static @NotNull BinaryRow prepareRow(@NotNull String entryKey, @NotNull String entryVal) throws IOException {
byte[] keyBytes = ByteUtils.toBytes(entryKey);
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
@@ -381,7 +383,7 @@ public class ItInternalTableScanTest {
when(cursor.hasNext()).thenAnswer(hnInvocation -> cursorTouchCnt.get() < submittedItems.size());
- when(cursor.next()).thenAnswer(ninvocation ->
+ lenient().when(cursor.next()).thenAnswer(ninvocation ->
ReadResult.createFromCommitted(submittedItems.get(cursorTouchCnt.getAndIncrement()), clock.now()));
return cursor;
@@ -390,7 +392,7 @@ public class ItInternalTableScanTest {
// The latch that allows to await Subscriber.onError() before asserting test invariants.
CountDownLatch subscriberAllDataAwaitLatch = new CountDownLatch(1);
- internalTbl.scan(0, null).subscribe(new Subscriber<>() {
+ scan(0, null).subscribe(new Subscriber<>() {
private Subscription subscription;
@Override
@@ -463,7 +465,7 @@ public class ItInternalTableScanTest {
AtomicReference<Throwable> gotException = new AtomicReference<>();
- internalTbl.scan(0, null).subscribe(new Subscriber<>() {
+ scan(0, null).subscribe(new Subscriber<>() {
@Override
public void onSubscribe(Subscription subscription) {
subscription.request(reqAmount);
@@ -495,4 +497,13 @@ public class ItInternalTableScanTest {
}
);
}
+
+ /**
+ * Either read-write or read-only publisher producer.
+ *
+ * @param part The partition.
+ * @param tx The transaction.
+ * @return {@link Publisher} that reactively notifies about partition rows.
+ */
+ protected abstract Publisher<BinaryRow> scan(int part, InternalTransaction tx);
}
diff --git a/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItInternalTableReadOnlyOperationsTest.java b/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItInternalTableReadOnlyOperationsTest.java
new file mode 100644
index 0000000000..4f3920c9de
--- /dev/null
+++ b/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItInternalTableReadOnlyOperationsTest.java
@@ -0,0 +1,260 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.distributed;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.ignite.internal.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
+import org.apache.ignite.internal.replicator.ReplicaService;
+import org.apache.ignite.internal.schema.BinaryRow;
+import org.apache.ignite.internal.schema.ByteBufferRow;
+import org.apache.ignite.internal.schema.Column;
+import org.apache.ignite.internal.schema.NativeTypes;
+import org.apache.ignite.internal.schema.SchemaDescriptor;
+import org.apache.ignite.internal.schema.row.Row;
+import org.apache.ignite.internal.schema.row.RowAssembler;
+import org.apache.ignite.internal.storage.MvPartitionStorage;
+import org.apache.ignite.internal.storage.PartitionTimestampCursor;
+import org.apache.ignite.internal.storage.ReadResult;
+import org.apache.ignite.internal.table.InternalTable;
+import org.apache.ignite.internal.table.impl.DummyInternalTableImpl;
+import org.apache.ignite.internal.testframework.IgniteAbstractTest;
+import org.apache.ignite.internal.tx.InternalTransaction;
+import org.apache.ignite.network.ClusterNode;
+import org.apache.ignite.tx.TransactionException;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.function.Executable;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+/**
+ * Tests for {@link InternalTable} read-only operations.
+ */
+@ExtendWith(MockitoExtension.class)
+public class ItInternalTableReadOnlyOperationsTest extends IgniteAbstractTest {
+ private static final SchemaDescriptor SCHEMA = new SchemaDescriptor(
+ 1,
+ new Column[]{new Column("key", NativeTypes.INT64, false)},
+ new Column[]{new Column("value", NativeTypes.INT64, false)}
+ );
+
+ private static final HybridClock CLOCK = new HybridClock();
+
+ private static final Row ROW_1 = createKeyValueRow(1, 1001);
+
+ private static final Row ROW_2 = createKeyValueRow(2, 1002);
+
+
+ /** Mock partition storage. */
+ @Mock
+ private MvPartitionStorage mockStorage;
+
+ /** Transaction mock. */
+ @Mock
+ private InternalTransaction readOnlyTx;
+
+ /** Internal table to test. */
+ private InternalTable internalTbl;
+
+ /**
+ * Prepare test environment using DummyInternalTableImpl and Mocked storage.
+ */
+ @BeforeEach
+ public void setUp(TestInfo testInfo) {
+ internalTbl = new DummyInternalTableImpl(Mockito.mock(ReplicaService.class), mockStorage);
+
+ mockStorage(List.of(ROW_1, ROW_2));
+
+ lenient().when(readOnlyTx.isReadOnly()).thenReturn(true);
+ lenient().when(readOnlyTx.readTimestamp()).thenReturn(CLOCK.now());
+ }
+
+ @Test
+ public void testReadOnlyGetNonExistingKeyWithReadTimestamp() {
+ assertNull(internalTbl.get(createKeyRow(0), CLOCK.now(), mock(ClusterNode.class)).join());
+ }
+
+ @Test
+ public void testReadOnlyGetNonExistingKeyWithTx() {
+ assertNull(internalTbl.get(createKeyRow(0), readOnlyTx).join());
+ }
+
+ @Test
+ public void testReadOnlyGetExistingKeyWithReadTimestamp() {
+ assertEquals(ROW_2, internalTbl.get(createKeyRow(2), CLOCK.now(), mock(ClusterNode.class)).join());
+ }
+
+ @Test
+ public void testReadOnlyGetExistingKeyWithTx() {
+ assertEquals(ROW_2, internalTbl.get(createKeyRow(2), readOnlyTx).join());
+ }
+
+
+ @Test
+ public void testReadOnlyGetAllNonExistingKeysWithReadTimestamp() {
+ assertEquals(0,
+ internalTbl.getAll(Collections.singleton(createKeyRow(0)), CLOCK.now(), mock(ClusterNode.class)).join().size()
+ );
+ }
+
+ @Test
+ public void testReadOnlyGetAllNonExistingKeysWithTx() {
+ assertEquals(0,
+ internalTbl.getAll(Collections.singleton(createKeyRow(0)), readOnlyTx).join().size()
+ );
+ }
+
+ @Test
+ public void testReadOnlyGetAllPartiallyExistingKeysWithReadTimestamp() {
+ assertEquals(
+ Collections.singletonList(ROW_2),
+ internalTbl.getAll(Collections.singleton(createKeyRow(2)), CLOCK.now(), mock(ClusterNode.class)).join()
+ );
+ }
+
+ @Test
+ public void testReadOnlyGetAllPartiallyExistingKeysWithTx() {
+ assertEquals(
+ Collections.singletonList(ROW_2),
+ internalTbl.getAll(Collections.singleton(createKeyRow(2)), readOnlyTx).join()
+ );
+ }
+
+ @Test
+ public void testReadOnlyGetAllExistingKeysWithReadTimestamp() {
+ assertEquals(
+ List.of(ROW_1, ROW_2),
+ internalTbl.getAll(List.of(createKeyRow(1), createKeyRow(2)), CLOCK.now(), mock(ClusterNode.class)).join()
+ );
+ }
+
+ @Test
+ public void testReadOnlyGetAllExistingKeysWithTx() {
+ assertEquals(
+ List.of(ROW_1, ROW_2),
+ internalTbl.getAll(List.of(createKeyRow(1), createKeyRow(2)), readOnlyTx).join()
+ );
+ }
+
+ @Test()
+ public void testEnlistingReadWriteOperationIntoReadOnlyTransactionThrowsAnException() {
+ InternalTransaction tx = mock(InternalTransaction.class);
+ when(tx.isReadOnly()).thenReturn(true);
+
+ List<Executable> executables = List.of(
+ () -> internalTbl.delete(null, tx).get(),
+ () -> internalTbl.deleteAll(null, tx).get(),
+ () -> internalTbl.deleteExact(null, tx).get(),
+ () -> internalTbl.deleteAllExact(null, tx).get(),
+ () -> internalTbl.getAndDelete(null, tx).get(),
+ () -> internalTbl.getAndReplace(null, tx).get(),
+ () -> internalTbl.getAndUpsert(null, tx).get(),
+ () -> internalTbl.upsert(null, tx).get(),
+ () -> internalTbl.upsertAll(null, tx).get(),
+ () -> internalTbl.insert(null, tx).get(),
+ () -> internalTbl.insertAll(null, tx).get(),
+ () -> internalTbl.replace(null, tx).get(),
+ () -> internalTbl.replace(null, null, tx).get()
+ );
+
+ executables.forEach(executable -> {
+ ExecutionException ex = assertThrows(ExecutionException.class, executable);
+
+ assertThat(ex.getCause(), is(instanceOf(TransactionException.class)));
+ assertThat(
+ ex.getCause().getMessage(),
+ containsString("Failed to enlist read-write operation into read-only transaction"));
+ });
+
+ TransactionException ex = assertThrows(TransactionException.class, () -> internalTbl.scan(0, tx));
+ assertThat(
+ ex.getMessage(),
+ containsString("Failed to enlist read-write operation into read-only transaction"));
+ }
+
+ private void mockStorage(List<BinaryRow> submittedItems) {
+ // TODO: IGNITE-17859 After index integration get and getAll methods should be used instead of scan.
+ AtomicInteger cursorTouchCnt = new AtomicInteger(0);
+
+ lenient().when(mockStorage.scan(any(HybridTimestamp.class))).thenAnswer(invocation -> {
+ var cursor = mock(PartitionTimestampCursor.class);
+
+ lenient().when(cursor.hasNext()).thenAnswer(hnInvocation -> cursorTouchCnt.get() < submittedItems.size());
+
+ lenient().when(cursor.next()).thenAnswer(
+ ninvocation ->
+ ReadResult.createFromCommitted(submittedItems.get(
+ cursorTouchCnt.getAndIncrement()),
+ new HybridTimestamp(1, 0)
+ )
+ );
+
+ return cursor;
+ });
+
+ }
+
+ /**
+ * Creates a {@link Row} with the supplied key.
+ *
+ * @param id Key.
+ * @return Row.
+ */
+ private static Row createKeyRow(long id) {
+ RowAssembler rowBuilder = new RowAssembler(SCHEMA, 0, 0);
+
+ rowBuilder.appendLong(id);
+
+ return new Row(SCHEMA, new ByteBufferRow(rowBuilder.toBytes()));
+ }
+
+ /**
+ * Creates a {@link Row} with the supplied key and value.
+ *
+ * @param id Key.
+ * @param value Value.
+ * @return Row.
+ */
+ private static Row createKeyValueRow(long id, long value) {
+ RowAssembler rowBuilder = new RowAssembler(SCHEMA, 0, 0);
+
+ rowBuilder.appendLong(id);
+ rowBuilder.appendLong(value);
+
+ return new Row(SCHEMA, new ByteBufferRow(rowBuilder.toBytes()));
+ }
+}
diff --git a/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItInternalTableReadOnlyScanTest.java b/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItInternalTableReadOnlyScanTest.java
new file mode 100644
index 0000000000..80871da334
--- /dev/null
+++ b/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItInternalTableReadOnlyScanTest.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.distributed;
+
+import static org.mockito.Mockito.mock;
+
+import java.util.concurrent.Flow.Publisher;
+import org.apache.ignite.internal.hlc.HybridClock;
+import org.apache.ignite.internal.schema.BinaryRow;
+import org.apache.ignite.internal.table.InternalTable;
+import org.apache.ignite.internal.tx.InternalTransaction;
+import org.apache.ignite.network.ClusterNode;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+/**
+ * Tests for {@link InternalTable#scan(int, org.apache.ignite.internal.tx.InternalTransaction)}.
+ */
+@ExtendWith(MockitoExtension.class)
+public class ItInternalTableReadOnlyScanTest extends ItAbstractInternalTableScanTest {
+ private static final HybridClock CLOCK = new HybridClock();
+
+ /** {@inheritDoc} */
+ @Override
+ protected Publisher<BinaryRow> scan(int part, InternalTransaction tx) {
+ return internalTbl.scan(part, CLOCK.now(), mock(ClusterNode.class));
+ }
+
+ // TODO: IGNITE-17666 Use super test as is.
+ @Disabled("https://issues.apache.org/jira/browse/IGNITE-17666")
+ @Override
+ public void testExceptionRowScanCursorHasNext() throws Exception {
+ super.testExceptionRowScanCursorHasNext();
+ }
+}
diff --git a/modules/replicator/src/main/java/org/apache/ignite/internal/replicator/message/TimestampAware.java b/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItInternalTableReadWriteScanTest.java
similarity index 57%
copy from modules/replicator/src/main/java/org/apache/ignite/internal/replicator/message/TimestampAware.java
copy to modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItInternalTableReadWriteScanTest.java
index f63712d651..3f6f15cf13 100644
--- a/modules/replicator/src/main/java/org/apache/ignite/internal/replicator/message/TimestampAware.java
+++ b/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItInternalTableReadWriteScanTest.java
@@ -15,23 +15,20 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.replicator.message;
+package org.apache.ignite.distributed;
-import org.apache.ignite.hlc.HybridTimestamp;
-import org.apache.ignite.network.NetworkMessage;
-import org.apache.ignite.network.annotations.Marshallable;
-import org.apache.ignite.network.annotations.Transferable;
+import java.util.concurrent.Flow.Publisher;
+import org.apache.ignite.internal.schema.BinaryRow;
+import org.apache.ignite.internal.table.InternalTable;
+import org.apache.ignite.internal.tx.InternalTransaction;
/**
- * Message with a timestamp to adjust a hybrid logical clock.
+ * Tests for {@link InternalTable#scan(int, org.apache.ignite.internal.tx.InternalTransaction)}.
*/
-@Transferable(ReplicaMessageGroup.TIMESTAMP_AWARE)
-public interface TimestampAware extends NetworkMessage {
- /**
- * Gets a hybrid timestamp.
- *
- * @return Gets a hybrid timestamp.
- */
- @Marshallable
- HybridTimestamp timestamp();
+public class ItInternalTableReadWriteScanTest extends ItAbstractInternalTableScanTest {
+ /** {@inheritDoc} */
+ @Override
+ protected Publisher<BinaryRow> scan(int part, InternalTransaction tx) {
+ return internalTbl.scan(part, tx);
+ }
}
diff --git a/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItTablePersistenceTest.java b/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItTablePersistenceTest.java
index 70e27682d7..5900c51822 100644
--- a/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItTablePersistenceTest.java
+++ b/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItTablePersistenceTest.java
@@ -31,8 +31,8 @@ import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BooleanSupplier;
import java.util.function.Function;
-import org.apache.ignite.hlc.HybridClock;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.raft.server.impl.JraftServerImpl;
import org.apache.ignite.internal.replicator.ReplicaService;
import org.apache.ignite.internal.schema.ByteBufferRow;
diff --git a/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItTxDistributedTestSingleNode.java b/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItTxDistributedTestSingleNode.java
index 658737a72d..93bbb5afaf 100644
--- a/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItTxDistributedTestSingleNode.java
+++ b/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItTxDistributedTestSingleNode.java
@@ -19,7 +19,9 @@ package org.apache.ignite.distributed;
import static org.apache.ignite.raft.jraft.test.TestUtils.waitForTopology;
import static org.apache.ignite.utils.ClusterServiceTestUtils.findLocalAddresses;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
@@ -39,10 +41,10 @@ import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
-import org.apache.ignite.hlc.HybridClock;
import org.apache.ignite.internal.affinity.RendezvousAffinityFunction;
import org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
import org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.logger.IgniteLogger;
import org.apache.ignite.internal.logger.Loggers;
import org.apache.ignite.internal.raft.Loza;
@@ -86,9 +88,11 @@ import org.apache.ignite.raft.client.service.RaftGroupService;
import org.apache.ignite.raft.jraft.RaftMessagesFactory;
import org.apache.ignite.raft.jraft.rpc.impl.RaftGroupServiceImpl;
import org.apache.ignite.table.Table;
+import org.apache.ignite.tx.Transaction;
import org.apache.ignite.utils.ClusterServiceTestUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
@@ -585,4 +589,20 @@ public class ItTxDistributedTestSingleNode extends TxAbstractTest {
return true;
}
+
+ @Test
+ public void testIgniteTransactionsAndReadTimestamp() {
+ Transaction readWriteTx = igniteTransactions.begin();
+ assertFalse(readWriteTx.isReadOnly());
+ assertNull(readWriteTx.readTimestamp());
+
+ Transaction readOnlyTx = igniteTransactions.readOnly().begin();
+ assertTrue(readOnlyTx.isReadOnly());
+ assertNotNull(readOnlyTx.readTimestamp());
+
+ readWriteTx.commit();
+
+ Transaction readOnlyTx2 = igniteTransactions.readOnly().begin();
+ readOnlyTx2.rollback();
+ }
}
diff --git a/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItTxDistributedTestThreeNodesThreeReplicasCollocated.java b/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItTxDistributedTestThreeNodesThreeReplicasCollocated.java
index 8def19ea7b..254eb50cd8 100644
--- a/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItTxDistributedTestThreeNodesThreeReplicasCollocated.java
+++ b/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ItTxDistributedTestThreeNodesThreeReplicasCollocated.java
@@ -23,7 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.UUID;
import java.util.stream.Collectors;
import org.apache.ignite.internal.tx.TxState;
-import org.apache.ignite.internal.tx.impl.TransactionImpl;
+import org.apache.ignite.internal.tx.impl.ReadWriteTransactionImpl;
import org.apache.ignite.raft.jraft.test.TestUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -57,7 +57,7 @@ public class ItTxDistributedTestThreeNodesThreeReplicasCollocated extends ItTxDi
@Test
public void testTxStateReplication() {
- TransactionImpl tx = (TransactionImpl) igniteTransactions.begin();
+ ReadWriteTransactionImpl tx = (ReadWriteTransactionImpl) igniteTransactions.begin();
UUID txId = tx.id();
diff --git a/modules/table/src/integrationTest/java/org/apache/ignite/internal/table/ItColocationTest.java b/modules/table/src/integrationTest/java/org/apache/ignite/internal/table/ItColocationTest.java
index 1b20a55077..78a59e7fd2 100644
--- a/modules/table/src/integrationTest/java/org/apache/ignite/internal/table/ItColocationTest.java
+++ b/modules/table/src/integrationTest/java/org/apache/ignite/internal/table/ItColocationTest.java
@@ -51,7 +51,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
-import org.apache.ignite.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.replicator.ReplicaService;
import org.apache.ignite.internal.replicator.ReplicationGroupId;
import org.apache.ignite.internal.replicator.message.ReplicaRequest;
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/InternalTable.java b/modules/table/src/main/java/org/apache/ignite/internal/table/InternalTable.java
index 78ee0022fc..fc00c816d6 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/InternalTable.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/InternalTable.java
@@ -22,6 +22,7 @@ import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Flow.Publisher;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.schema.BinaryRow;
import org.apache.ignite.internal.schema.BinaryRowEx;
import org.apache.ignite.internal.storage.engine.MvTableStorage;
@@ -30,6 +31,8 @@ import org.apache.ignite.internal.tx.LockException;
import org.apache.ignite.internal.tx.storage.state.TxStateTableStorage;
import org.apache.ignite.network.ClusterNode;
import org.apache.ignite.raft.client.service.RaftGroupService;
+import org.apache.ignite.tx.TransactionException;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -68,6 +71,21 @@ public interface InternalTable extends AutoCloseable {
*/
CompletableFuture<BinaryRow> get(BinaryRowEx keyRow, @Nullable InternalTransaction tx);
+ /**
+ * Asynchronously gets a row with same key columns values as given one from the table on a specific node for the proposed readTimestamp.
+ *
+ * @param keyRow Row with key columns set.
+ * @param readTimestamp Read timestamp.
+ * @param recipientNode Cluster node that will handle given get request.
+ * @return Future representing pending completion of the operation.
+ * @throws LockException If a lock can't be acquired by some reason.
+ */
+ CompletableFuture<BinaryRow> get(
+ BinaryRowEx keyRow,
+ @NotNull HybridTimestamp readTimestamp,
+ @NotNull ClusterNode recipientNode
+ );
+
/**
* Asynchronously get rows from the table.
*
@@ -77,6 +95,21 @@ public interface InternalTable extends AutoCloseable {
*/
CompletableFuture<Collection<BinaryRow>> getAll(Collection<BinaryRowEx> keyRows, @Nullable InternalTransaction tx);
+ /**
+ * Asynchronously get rows from the table for the proposed read timestamp.
+ *
+ * @param keyRows Rows with key columns set.
+ * @param readTimestamp Read timestamp.
+ * @param recipientNode Cluster node that will handle given get request.
+ * @return Future representing pending completion of the operation.
+ */
+ CompletableFuture<Collection<BinaryRow>> getAll(
+ Collection<BinaryRowEx> keyRows,
+ @NotNull HybridTimestamp readTimestamp,
+ @NotNull ClusterNode recipientNode
+ );
+
+
/**
* Asynchronously inserts a row into the table if does not exist or replaces the existed one.
*
@@ -210,9 +243,26 @@ public interface InternalTable extends AutoCloseable {
* @param p The partition.
* @param tx The transaction.
* @return {@link Publisher} that reactively notifies about partition rows.
+ * @throws IllegalArgumentException If proposed partition index {@code p} is out of bounds.
*/
Publisher<BinaryRow> scan(int p, @Nullable InternalTransaction tx);
+ /**
+ * Scans given partition with the proposed read timestamp, providing {@link Publisher} that reactively notifies about partition rows.
+ *
+ * @param p The partition.
+ * @param readTimestamp Read timestamp.
+ * @param recipientNode Cluster node that will handle given get request.
+ * @return {@link Publisher} that reactively notifies about partition rows.
+ * @throws IllegalArgumentException If proposed partition index {@code p} is out of bounds.
+ * @throws TransactionException If proposed {@code tx} is read-write. Transaction itself won't be automatically rolled back.
+ */
+ Publisher<BinaryRow> scan(
+ int p,
+ @NotNull HybridTimestamp readTimestamp,
+ @NotNull ClusterNode recipientNode
+ );
+
/**
* Gets a count of partitions of the table.
*
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManager.java b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManager.java
index 42fc63b908..6bd629ffaf 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManager.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManager.java
@@ -74,11 +74,11 @@ import org.apache.ignite.configuration.ConfigurationProperty;
import org.apache.ignite.configuration.notifications.ConfigurationNamedListListener;
import org.apache.ignite.configuration.notifications.ConfigurationNotificationEvent;
import org.apache.ignite.configuration.validation.ConfigurationValidationException;
-import org.apache.ignite.hlc.HybridClock;
import org.apache.ignite.internal.affinity.AffinityUtils;
import org.apache.ignite.internal.baseline.BaselineManager;
import org.apache.ignite.internal.causality.VersionedValue;
import org.apache.ignite.internal.configuration.util.ConfigurationUtil;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.logger.IgniteLogger;
import org.apache.ignite.internal.logger.Loggers;
import org.apache.ignite.internal.manager.EventListener;
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/command/FinishTxCommand.java b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/command/FinishTxCommand.java
index 750f359924..f640f2c33f 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/command/FinishTxCommand.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/command/FinishTxCommand.java
@@ -19,7 +19,7 @@ package org.apache.ignite.internal.table.distributed.command;
import java.util.List;
import java.util.UUID;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.replicator.ReplicationGroupId;
/**
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/command/TxCleanupCommand.java b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/command/TxCleanupCommand.java
index 345f78e3ac..9a8af04bd5 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/command/TxCleanupCommand.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/command/TxCleanupCommand.java
@@ -18,7 +18,7 @@
package org.apache.ignite.internal.table.distributed.command;
import java.util.UUID;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
/**
* State machine command to cleanup on a transaction commit.
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/message/SnapshotMvDataResponse.java b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/message/SnapshotMvDataResponse.java
index 3bf4004504..5d4c9418cc 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/message/SnapshotMvDataResponse.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/snapshot/message/SnapshotMvDataResponse.java
@@ -20,7 +20,7 @@ package org.apache.ignite.internal.table.distributed.raft.snapshot.message;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.UUID;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.schema.BinaryRow;
import org.apache.ignite.internal.table.distributed.TableMessageGroup;
import org.apache.ignite.network.NetworkMessage;
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/replication/request/ReadOnlyReplicaRequest.java b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/replication/request/ReadOnlyReplicaRequest.java
index 72623a317d..5a61b2e23e 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/replication/request/ReadOnlyReplicaRequest.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/replication/request/ReadOnlyReplicaRequest.java
@@ -17,8 +17,7 @@
package org.apache.ignite.internal.table.distributed.replication.request;
-import java.util.UUID;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.replicator.message.ReplicaRequest;
import org.apache.ignite.network.annotations.Marshallable;
@@ -26,8 +25,6 @@ import org.apache.ignite.network.annotations.Marshallable;
* Read only replica request.
*/
public interface ReadOnlyReplicaRequest extends ReplicaRequest {
- UUID transactionId();
-
@Marshallable
- HybridTimestamp timestamp();
+ HybridTimestamp readTimestamp();
}
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/replication/request/ReadOnlyScanRetrieveBatchReplicaRequest.java b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/replication/request/ReadOnlyScanRetrieveBatchReplicaRequest.java
index 37c1d37239..b0465e0b06 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/replication/request/ReadOnlyScanRetrieveBatchReplicaRequest.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/replication/request/ReadOnlyScanRetrieveBatchReplicaRequest.java
@@ -17,6 +17,7 @@
package org.apache.ignite.internal.table.distributed.replication.request;
+import java.util.UUID;
import org.apache.ignite.internal.table.distributed.TableMessageGroup;
import org.apache.ignite.network.annotations.Transferable;
@@ -25,4 +26,5 @@ import org.apache.ignite.network.annotations.Transferable;
*/
@Transferable(TableMessageGroup.RO_SCAN_RETRIEVE_BATCH_REPLICA_REQUEST)
public interface ReadOnlyScanRetrieveBatchReplicaRequest extends ScanRetrieveBatchReplicaRequest, ReadOnlyReplicaRequest {
+ UUID transactionId();
}
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/replicator/PartitionReplicaListener.java b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/replicator/PartitionReplicaListener.java
index 91f807c1d5..89f034f077 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/replicator/PartitionReplicaListener.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/replicator/PartitionReplicaListener.java
@@ -19,6 +19,8 @@ package org.apache.ignite.internal.table.distributed.replicator;
import static java.util.concurrent.CompletableFuture.allOf;
import static java.util.concurrent.CompletableFuture.failedFuture;
+import static org.apache.ignite.internal.util.ExceptionUtils.withCause;
+import static org.apache.ignite.lang.ErrorGroups.Replicator.CURSOR_CLOSE_ERR;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@@ -35,8 +37,8 @@ import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
import java.util.stream.Collectors;
-import org.apache.ignite.hlc.HybridClock;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.replicator.ReplicationGroupId;
import org.apache.ignite.internal.replicator.exception.PrimaryReplicaMissException;
import org.apache.ignite.internal.replicator.exception.ReplicationException;
@@ -307,7 +309,7 @@ public class PartitionReplicaListener implements ReplicaListener {
private CompletableFuture<Object> processReadOnlyScanRetrieveBatchAction(ReadOnlyScanRetrieveBatchReplicaRequest request) {
UUID txId = request.transactionId();
int batchCount = request.batchSize();
- HybridTimestamp timestamp = request.timestamp();
+ HybridTimestamp readTimestamp = request.readTimestamp();
IgniteUuid cursorId = new IgniteUuid(txId, request.scanId());
@@ -317,7 +319,7 @@ public class PartitionReplicaListener implements ReplicaListener {
id -> mvDataStorage.scan(HybridTimestamp.MAX_VALUE));
while (batchRows.size() < batchCount && cursor.hasNext()) {
- BinaryRow resolvedReadResult = resolveReadResult(cursor.next(), timestamp, () -> cursor.committed(timestamp));
+ BinaryRow resolvedReadResult = resolveReadResult(cursor.next(), readTimestamp, () -> cursor.committed(readTimestamp));
if (resolvedReadResult != null) {
batchRows.add(resolvedReadResult);
@@ -336,33 +338,60 @@ public class PartitionReplicaListener implements ReplicaListener {
private CompletableFuture<Object> processReadOnlySingleEntryAction(ReadOnlySingleRowReplicaRequest request) {
ByteBuffer searchKey = request.binaryRow().keySlice();
- UUID indexId = indexIdOrDefault(indexScanId/*request.indexToUse()*/);
-
if (request.requestType() != RequestType.RO_GET) {
throw new IgniteInternalException(Replicator.REPLICA_COMMON_ERR,
IgniteStringFormatter.format("Unknown single request [actionType={}]", request.requestType()));
}
//TODO: IGNITE-17868 Integrate indexes into rowIds resolution along with proper lock management on search rows.
- RowId rowId = rowIdByKey(indexId, searchKey);
-
- ReadResult readResult = rowId == null ? null : mvDataStorage.read(rowId, request.timestamp());
+ HybridTimestamp readTimestamp = request.readTimestamp();
- BinaryRow result = readResult == null ? null : resolveReadResult(readResult, request.timestamp(), () -> {
- if (readResult.newestCommitTimestamp() == null) {
- return null;
- }
+ try (PartitionTimestampCursor scan = mvDataStorage.scan(readTimestamp)) {
+ while (scan.hasNext()) {
+ ReadResult readResult = scan.next();
+ HybridTimestamp newestCommitTimestamp = readResult.newestCommitTimestamp();
- ReadResult committedReadResult = mvDataStorage.read(rowId, readResult.newestCommitTimestamp());
+ if (readResult.binaryRow() == null) {
+ if (newestCommitTimestamp == null) {
+ throw new AssertionError("Unexpected null value of the newest committed timestamp.");
+ }
- assert !committedReadResult.isWriteIntent() :
- "The result is not committed [rowId=" + rowId + ", timestamp="
- + readResult.newestCommitTimestamp() + ']';
+ BinaryRow candidate = scan.committed(newestCommitTimestamp);
+ if (candidate == null) {
+ throw new AssertionError("Unexpected null value of the candidate binary row.");
+ }
- return committedReadResult.binaryRow();
- });
+ if (candidate.keySlice().equals(searchKey)) {
+ return CompletableFuture.completedFuture(
+ resolveReadResult(
+ readResult,
+ readTimestamp,
+ () -> scan.committed(newestCommitTimestamp)
+ )
+ );
+ }
+ } else if (readResult.binaryRow().keySlice().equals(searchKey)) {
+ return CompletableFuture.completedFuture(
+ resolveReadResult(
+ readResult,
+ readTimestamp,
+ () -> newestCommitTimestamp == null ? null : scan.committed(newestCommitTimestamp)
+ )
+ );
+ }
+ }
+ } catch (Exception e) {
+ return failedFuture(
+ withCause(
+ ReplicationException::new,
+ CURSOR_CLOSE_ERR,
+ "Failed to close cursor.",
+ e
+ )
+ );
+ }
- return CompletableFuture.completedFuture(result);
+ return CompletableFuture.completedFuture(null);
}
/**
@@ -375,34 +404,61 @@ public class PartitionReplicaListener implements ReplicaListener {
Collection<ByteBuffer> keyRows = request.binaryRows().stream().map(br -> br.keySlice()).collect(
Collectors.toList());
- UUID indexId = indexIdOrDefault(indexScanId/*request.indexToUse()*/);
-
- if (request.requestType() != RequestType.RO_GET_ALL) {
+ if (request.requestType() != RequestType.RO_GET_ALL) {
throw new IgniteInternalException(Replicator.REPLICA_COMMON_ERR,
IgniteStringFormatter.format("Unknown single request [actionType={}]", request.requestType()));
}
ArrayList<BinaryRow> result = new ArrayList<>(keyRows.size());
- for (ByteBuffer searchKey : keyRows) {
- //TODO: IGNITE-17868 Integrate indexes into rowIds resolution along with proper lock management on search rows.
- RowId rowId = rowIdByKey(indexId, searchKey);
-
- ReadResult readResult = rowId == null ? null : mvDataStorage.read(rowId, request.timestamp());
+ //TODO: IGNITE-17868 Integrate indexes into rowIds resolution along with proper lock management on search rows.
+ HybridTimestamp readTimestamp = request.readTimestamp();
- result.add(readResult == null ? null : resolveReadResult(readResult, request.timestamp(), () -> {
- if (readResult.newestCommitTimestamp() == null) {
- return null;
- }
+ try (PartitionTimestampCursor scan = mvDataStorage.scan(readTimestamp)) {
+ while (scan.hasNext()) {
+ ReadResult readResult = scan.next();
+ HybridTimestamp newestCommitTimestamp = readResult.newestCommitTimestamp();
- ReadResult committedReadResult = mvDataStorage.read(rowId, readResult.newestCommitTimestamp());
+ for (ByteBuffer searchKey : keyRows) {
+ if (readResult.binaryRow() == null) {
+ if (newestCommitTimestamp == null) {
+ throw new AssertionError("Unexpected null value of the newest committed timestamp.");
+ }
- assert !committedReadResult.isWriteIntent() :
- "The result is not committed [rowId=" + rowId + ", timestamp="
- + readResult.newestCommitTimestamp() + ']';
+ BinaryRow candidate = scan.committed(readResult.newestCommitTimestamp());
+ if (candidate == null) {
+ throw new AssertionError("Unexpected null value of the candidate binary row.");
+ }
- return committedReadResult.binaryRow();
- }));
+ if (candidate.keySlice().equals(searchKey)) {
+ result.add(
+ resolveReadResult(
+ readResult,
+ readTimestamp,
+ () -> scan.committed(readResult.newestCommitTimestamp())
+ )
+ );
+ }
+ } else if (readResult.binaryRow().keySlice().equals(searchKey)) {
+ result.add(
+ resolveReadResult(
+ readResult,
+ readTimestamp,
+ () -> newestCommitTimestamp == null ? null : scan.committed(readResult.newestCommitTimestamp())
+ )
+ );
+ }
+ }
+ }
+ } catch (Exception e) {
+ return failedFuture(
+ withCause(
+ ReplicationException::new,
+ CURSOR_CLOSE_ERR,
+ "Failed to close cursor.",
+ e
+ )
+ );
}
return CompletableFuture.completedFuture(result);
@@ -1344,6 +1400,7 @@ public class PartitionReplicaListener implements ReplicaListener {
* @return Resolved binary row.
*/
private BinaryRow resolveReadResult(ReadResult readResult, HybridTimestamp timestamp, Supplier<BinaryRow> lastCommitted) {
+
return resolveReadResult(readResult, null, timestamp, lastCommitted);
}
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/storage/InternalTableImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/storage/InternalTableImpl.java
index 2f96fefa3b..c9d53a903b 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/storage/InternalTableImpl.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/storage/InternalTableImpl.java
@@ -19,11 +19,15 @@ package org.apache.ignite.internal.table.distributed.storage;
import static java.util.concurrent.CompletableFuture.completedFuture;
import static java.util.concurrent.CompletableFuture.failedFuture;
+import static org.apache.ignite.internal.util.ExceptionUtils.withCause;
+import static org.apache.ignite.lang.ErrorGroups.Replicator.REPLICA_UNAVAILABLE_ERR;
+import static org.apache.ignite.lang.ErrorGroups.Transactions.TX_INSUFFICIENT_READ_WRITE_OPERATION_ERR;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
@@ -37,7 +41,8 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
-import org.apache.ignite.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.replicator.ReplicaService;
import org.apache.ignite.internal.replicator.ReplicationGroupId;
import org.apache.ignite.internal.replicator.exception.PrimaryReplicaMissException;
@@ -47,6 +52,7 @@ import org.apache.ignite.internal.schema.BinaryRowEx;
import org.apache.ignite.internal.storage.engine.MvTableStorage;
import org.apache.ignite.internal.table.InternalTable;
import org.apache.ignite.internal.table.distributed.TableMessagesFactory;
+import org.apache.ignite.internal.table.distributed.replication.request.ReadOnlyScanRetrieveBatchReplicaRequest;
import org.apache.ignite.internal.table.distributed.replication.request.ReadWriteScanRetrieveBatchReplicaRequest;
import org.apache.ignite.internal.table.distributed.replication.request.ReadWriteScanRetrieveBatchReplicaRequestBuilder;
import org.apache.ignite.internal.table.distributed.replicator.TablePartitionId;
@@ -194,6 +200,18 @@ public class InternalTableImpl implements InternalTable {
InternalTransaction tx,
IgniteTetraFunction<TablePartitionId, InternalTransaction, ReplicationGroupId, Long, ReplicaRequest> op
) {
+ // Check whether proposed tx is read-only. Complete future exceptionally if true.
+ // Attempting to enlist a read-only in a read-write transaction does not corrupt the transaction itself, thus read-write transaction
+ // won't be rolled back automatically - it's up to the user or outer engine.
+ if (tx != null && tx.isReadOnly()) {
+ return failedFuture(
+ new TransactionException(
+ TX_INSUFFICIENT_READ_WRITE_OPERATION_ERR,
+ "Failed to enlist read-write operation into read-only transaction txId={" + tx.id() + '}'
+ )
+ );
+ }
+
final boolean implicit = tx == null;
final InternalTransaction tx0 = implicit ? txManager.begin() : tx;
@@ -245,6 +263,19 @@ public class InternalTableImpl implements InternalTable {
IgniteFiveFunction<TablePartitionId, Collection<BinaryRow>, InternalTransaction, ReplicationGroupId, Long, ReplicaRequest> op,
Function<CompletableFuture<Object>[], CompletableFuture<T>> reducer
) {
+ // Check whether proposed tx is read-only. Complete future exceptionally if true.
+ // Attempting to enlist a read-only in a read-write transaction does not corrupt the transaction itself, thus read-write transaction
+ // won't be rolled back automatically - it's up to the user or outer engine.
+ if (tx != null && tx.isReadOnly()) {
+ return failedFuture(
+ new TransactionException(
+ TX_INSUFFICIENT_READ_WRITE_OPERATION_ERR,
+ "Failed to enlist read-write operation into read-only transaction txId={" + tx.id() + '}'
+ )
+ );
+ }
+
+
final boolean implicit = tx == null;
if (!implicit && tx.state() != null) {
@@ -431,35 +462,100 @@ public class InternalTableImpl implements InternalTable {
/** {@inheritDoc} */
@Override
public CompletableFuture<BinaryRow> get(BinaryRowEx keyRow, InternalTransaction tx) {
- return enlistInTx(
- keyRow,
- tx,
- (commitPart, txo, groupId, term) -> tableMessagesFactory.readWriteSingleRowReplicaRequest()
- .groupId(groupId)
- .binaryRow(keyRow)
- .transactionId(txo.id())
- .term(term)
- .requestType(RequestType.RW_GET)
- .timestamp(clock.now())
- .build()
+ if (tx != null && tx.isReadOnly()) {
+ return evaluateReadOnlyRecipientNode(partId(keyRow))
+ .thenCompose(recipientNode -> get(keyRow, tx.readTimestamp(), recipientNode));
+ } else {
+ return enlistInTx(
+ keyRow,
+ tx,
+ (commitPart, txo, groupId, term) -> tableMessagesFactory.readWriteSingleRowReplicaRequest()
+ .groupId(groupId)
+ .binaryRow(keyRow)
+ .transactionId(txo.id())
+ .term(term)
+ .requestType(RequestType.RW_GET)
+ .timestamp(clock.now())
+ .build()
+ );
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public CompletableFuture<BinaryRow> get(
+ BinaryRowEx keyRow,
+ @NotNull HybridTimestamp readTimestamp,
+ @NotNull ClusterNode recipientNode
+ ) {
+ int partId = partId(keyRow);
+ ReplicationGroupId partGroupId = partitionMap.get(partId).groupId();
+
+ return replicaSvc.invoke(recipientNode, tableMessagesFactory.readOnlySingleRowReplicaRequest()
+ .groupId(partGroupId)
+ .binaryRow(keyRow)
+ .requestType(RequestType.RO_GET)
+ .readTimestamp(readTimestamp)
+ .build()
);
}
/** {@inheritDoc} */
@Override
public CompletableFuture<Collection<BinaryRow>> getAll(Collection<BinaryRowEx> keyRows, InternalTransaction tx) {
- return enlistInTx(
- keyRows,
- tx,
- (commitPart, keyRows0, txo, groupId, term) -> tableMessagesFactory.readWriteMultiRowReplicaRequest()
- .groupId(groupId)
- .binaryRows(keyRows0)
- .transactionId(txo.id())
- .term(term)
- .requestType(RequestType.RW_GET_ALL)
- .timestamp(clock.now())
- .build(),
- this::collectMultiRowsResponses);
+ if (tx != null && tx.isReadOnly()) {
+ BinaryRowEx firstRow = keyRows.iterator().next();
+
+ if (firstRow == null) {
+ return CompletableFuture.completedFuture(Collections.emptyList());
+ } else {
+ return evaluateReadOnlyRecipientNode(partId(firstRow))
+ .thenCompose(recipientNode -> getAll(keyRows, tx.readTimestamp(), recipientNode));
+ }
+ } else {
+ return enlistInTx(
+ keyRows,
+ tx,
+ (commitPart, keyRows0, txo, groupId, term) -> tableMessagesFactory.readWriteMultiRowReplicaRequest()
+ .groupId(groupId)
+ .binaryRows(keyRows0)
+ .transactionId(txo.id())
+ .term(term)
+ .requestType(RequestType.RW_GET_ALL)
+ .timestamp(clock.now())
+ .build(),
+ this::collectMultiRowsResponses);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public CompletableFuture<Collection<BinaryRow>> getAll(
+ Collection<BinaryRowEx> keyRows,
+ @NotNull HybridTimestamp readTimestamp,
+ @NotNull ClusterNode recipientNode
+ ) {
+ Int2ObjectOpenHashMap<List<BinaryRow>> keyRowsByPartition = mapRowsToPartitions(keyRows);
+
+ CompletableFuture<Object>[] futures = new CompletableFuture[keyRowsByPartition.size()];
+
+ int batchNum = 0;
+
+ for (Int2ObjectOpenHashMap.Entry<List<BinaryRow>> partToRows : keyRowsByPartition.int2ObjectEntrySet()) {
+ ReplicationGroupId partGroupId = partitionMap.get(partToRows.getIntKey()).groupId();
+
+ CompletableFuture<Object> fut = replicaSvc.invoke(recipientNode, tableMessagesFactory.readOnlyMultiRowReplicaRequest()
+ .groupId(partGroupId)
+ .binaryRows(partToRows.getValue())
+ .requestType(RequestType.RO_GET_ALL)
+ .readTimestamp(clock.now())
+ .build()
+ );
+
+ futures[batchNum++] = fut;
+ }
+
+ return collectMultiRowsResponses(futures);
}
/** {@inheritDoc} */
@@ -702,17 +798,20 @@ public class InternalTableImpl implements InternalTable {
/** {@inheritDoc} */
@Override
public Publisher<BinaryRow> scan(int p, @Nullable InternalTransaction tx) {
- if (p < 0 || p >= partitions) {
- throw new IllegalArgumentException(
- IgniteStringFormatter.format(
- "Invalid partition [partition={}, minValue={}, maxValue={}].",
- p,
- 0,
- partitions - 1
+ // Check whether proposed tx is read-only. Complete future exceptionally if true.
+ // Attempting to enlist a read-only in a read-write transaction does not corrupt the transaction itself, thus read-write transaction
+ // won't be rolled back automatically - it's up to the user or outer engine.
+ if (tx != null && tx.isReadOnly()) {
+ throw new TransactionException(
+ new TransactionException(
+ TX_INSUFFICIENT_READ_WRITE_OPERATION_ERR,
+ "Failed to enlist read-write operation into read-only transaction txId={" + tx.id() + '}'
)
);
}
+ validatePartitionIndex(p);
+
final boolean implicit = tx == null;
final InternalTransaction tx0 = implicit ? txManager.begin() : tx;
@@ -723,6 +822,53 @@ public class InternalTableImpl implements InternalTable {
);
}
+ /** {@inheritDoc} */
+ @Override
+ public Publisher<BinaryRow> scan(
+ int p,
+ @NotNull HybridTimestamp readTimestamp,
+ @NotNull ClusterNode recipientNode
+ ) {
+ validatePartitionIndex(p);
+
+ return new PartitionScanPublisher(
+ (scanId, batchSize) -> {
+ ReplicationGroupId partGroupId = partitionMap.get(p).groupId();
+
+ ReadOnlyScanRetrieveBatchReplicaRequest request = tableMessagesFactory.readOnlyScanRetrieveBatchReplicaRequest()
+ .groupId(partGroupId)
+ // TODO: IGNITE-17666 Close cursor tx finish.
+ .transactionId(UUID.randomUUID())
+ .scanId(scanId)
+ .batchSize(batchSize)
+ .readTimestamp(clock.now())
+ .build();
+
+ return replicaSvc.invoke(recipientNode, request);
+ },
+ // TODO: IGNITE-17666 Close cursor tx finish.
+ Function.identity());
+ }
+
+ /**
+ * Validates partition index.
+ *
+ * @param p Partition index.
+ * @throws IllegalArgumentException If proposed partition is out of bounds.
+ */
+ private void validatePartitionIndex(int p) {
+ if (p < 0 || p >= partitions) {
+ throw new IllegalArgumentException(
+ IgniteStringFormatter.format(
+ "Invalid partition [partition={}, minValue={}, maxValue={}].",
+ p,
+ 0,
+ partitions - 1
+ )
+ );
+ }
+ }
+
/**
* Map rows to partitions.
*
@@ -1057,4 +1203,27 @@ public class InternalTableImpl implements InternalTable {
srv.shutdown();
}
}
+
+ // TODO: IGNITE-17963 Use smarter logic for recipient node evaluation.
+ /**
+ * Evaluated cluster node for read-only request processing.
+ *
+ * @param partId Partition id.
+ * @return Cluster node to evalute read-only request.
+ */
+ protected CompletableFuture<ClusterNode> evaluateReadOnlyRecipientNode(int partId) {
+ RaftGroupService svc = partitionMap.get(partId);
+
+ return svc.refreshAndGetLeaderWithTerm().handle((res, e) -> {
+ if (e != null) {
+ throw withCause(TransactionException::new, REPLICA_UNAVAILABLE_ERR, e);
+ } else {
+ if (res == null || res.getKey() == null) {
+ throw withCause(TransactionException::new, REPLICA_UNAVAILABLE_ERR, e);
+ } else {
+ return clusterNodeResolver.apply(res.get1().address());
+ }
+ }
+ });
+ }
}
diff --git a/modules/table/src/test/java/org/apache/ignite/internal/table/TxAbstractTest.java b/modules/table/src/test/java/org/apache/ignite/internal/table/TxAbstractTest.java
index 08c67303b1..0d9cc2d77b 100644
--- a/modules/table/src/test/java/org/apache/ignite/internal/table/TxAbstractTest.java
+++ b/modules/table/src/test/java/org/apache/ignite/internal/table/TxAbstractTest.java
@@ -1788,4 +1788,124 @@ public abstract class TxAbstractTest extends IgniteAbstractTest {
completedFuture(Tuple.create().set("balance1", val1).set("balance2", val2))));
});
}
+
+
+ @Test
+ public void testReadOnlyGet() {
+ accounts.recordView().upsert(null, makeValue(1, 100.));
+
+ Transaction readOnlyTx = igniteTransactions.readOnly().begin();
+ assertEquals(100., accounts.recordView().get(readOnlyTx, makeKey(1)).doubleValue("balance"));
+ }
+
+ @Disabled("https://issues.apache.org/jira/browse/IGNITE-17967")
+ @Test
+ public void testReadOnlyGetWriteIntentResolutionUpdate() {
+ accounts.recordView().upsert(null, makeValue(1, 100.));
+
+ // Pending tx
+ Transaction tx = igniteTransactions.begin();
+ accounts.recordView().upsert(tx, makeValue(1, 300.));
+
+ // Update
+ Transaction readOnlyTx = igniteTransactions.readOnly().begin();
+ assertEquals(100., accounts.recordView().get(readOnlyTx, makeKey(1)).doubleValue("balance"));
+
+ // Commit pending tx.
+ tx.commit();
+
+ // Same read-only transaction.
+ assertEquals(100., accounts.recordView().get(readOnlyTx, makeKey(1)).doubleValue("balance"));
+
+ // New read-only transaction.
+ Transaction readOnlyTx2 = igniteTransactions.readOnly().begin();
+ assertEquals(300., accounts.recordView().get(readOnlyTx2, makeKey(1)).doubleValue("balance"));
+ }
+
+ @Disabled("https://issues.apache.org/jira/browse/IGNITE-17967, https://issues.apache.org/jira/browse/IGNITE-17968")
+ @Test
+ public void testReadOnlyGetWriteIntentResolutionRemove() {
+ accounts.recordView().upsert(null, makeValue(1, 100.));
+
+ // Pending tx
+ Transaction tx = igniteTransactions.begin();
+ accounts.recordView().delete(tx, makeKey(1));
+
+ // Remove.
+ Transaction readOnlyTx = igniteTransactions.readOnly().begin();
+ assertEquals(100., accounts.recordView().get(readOnlyTx, makeKey(1)).doubleValue("balance"));
+
+ // Commit pending tx.
+ tx.commit();
+
+ // Same read-only transaction.
+ assertEquals(100., accounts.recordView().get(readOnlyTx, makeKey(1)).doubleValue("balance"));
+
+ // New read-only transaction.
+ Transaction readOnlyTx2 = igniteTransactions.readOnly().begin();
+ assertNull(accounts.recordView().get(readOnlyTx2, makeKey(1)).doubleValue("balance"));
+ }
+
+ @Test
+ public void testReadOnlyGetAll() {
+ accounts.recordView().upsert(null, makeValue(1, 100.));
+ accounts.recordView().upsert(null, makeValue(2, 200.));
+ accounts.recordView().upsert(null, makeValue(3, 300.));
+
+ Transaction readOnlyTx = igniteTransactions.readOnly().begin();
+ Collection<Tuple> retrievedKeys = accounts.recordView().getAll(readOnlyTx, List.of(makeKey(1), makeKey(2)));
+ validateBalance(retrievedKeys, 100., 200.);
+ }
+
+ @Disabled("https://issues.apache.org/jira/browse/IGNITE-17967")
+ // TODO: IGNITE-17968 Remove after fix.
+ @Test
+ public void testReadOnlyPendingWriteIntentSkipped() {
+ accounts.recordView().upsert(null, makeValue(1, 100.));
+ accounts.recordView().upsert(null, makeValue(2, 200.));
+
+ // Pending tx
+ Transaction tx = igniteTransactions.begin();
+ accounts.recordView().upsert(tx, makeValue(2, 300.));
+
+ Transaction readOnlyTx = igniteTransactions.readOnly().begin();
+ Collection<Tuple> retrievedKeys = accounts.recordView().getAll(readOnlyTx, List.of(makeKey(1), makeKey(2)));
+ validateBalance(retrievedKeys, 100., 200.);
+
+ // Commit pending tx.
+ tx.commit();
+
+ Collection<Tuple> retrievedKeys2 = accounts.recordView().getAll(readOnlyTx, List.of(makeKey(1), makeKey(2)));
+ validateBalance(retrievedKeys2, 100., 300.);
+
+ Transaction readOnlyTx2 = igniteTransactions.readOnly().begin();
+ Collection<Tuple> retrievedKeys3 = accounts.recordView().getAll(readOnlyTx2, List.of(makeKey(1), makeKey(2)));
+ validateBalance(retrievedKeys3, 100., 300.);
+ }
+
+ @Disabled("https://issues.apache.org/jira/browse/IGNITE-17967, https://issues.apache.org/jira/browse/IGNITE-17968")
+ @Test
+ public void testReadOnlyPendingWriteIntentSkippedCombined() {
+ accounts.recordView().upsert(null, makeValue(1, 100.));
+ accounts.recordView().upsert(null, makeValue(2, 200.));
+
+ // Pending tx
+ Transaction tx = igniteTransactions.begin();
+ accounts.recordView().delete(tx, makeKey(1));
+ accounts.recordView().upsert(tx, makeValue(2, 300.));
+
+ Transaction readOnlyTx = igniteTransactions.readOnly().begin();
+ Collection<Tuple> retrievedKeys = accounts.recordView().getAll(readOnlyTx, List.of(makeKey(1), makeKey(2)));
+ validateBalance(retrievedKeys, 100., 200.);
+
+ // Commit pending tx.
+ tx.commit();
+
+ Collection<Tuple> retrievedKeys2 = accounts.recordView().getAll(readOnlyTx, List.of(makeKey(1), makeKey(2)));
+ validateBalance(retrievedKeys2, 100., 300.);
+
+ Transaction readOnlyTx2 = igniteTransactions.readOnly().begin();
+ Collection<Tuple> retrievedKeys3 = accounts.recordView().getAll(readOnlyTx2, List.of(makeKey(1), makeKey(2)));
+ validateBalance(retrievedKeys3, 300.);
+ }
}
diff --git a/modules/table/src/test/java/org/apache/ignite/internal/table/TxLocalTest.java b/modules/table/src/test/java/org/apache/ignite/internal/table/TxLocalTest.java
index c5fa5638f9..cb0bdcab87 100644
--- a/modules/table/src/test/java/org/apache/ignite/internal/table/TxLocalTest.java
+++ b/modules/table/src/test/java/org/apache/ignite/internal/table/TxLocalTest.java
@@ -26,7 +26,7 @@ import static org.mockito.Mockito.when;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
-import org.apache.ignite.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.replicator.ReplicaService;
import org.apache.ignite.internal.replicator.ReplicationGroupId;
import org.apache.ignite.internal.replicator.listener.ReplicaListener;
diff --git a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/command/PartitionRaftCommandsSerializationTest.java b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/command/PartitionRaftCommandsSerializationTest.java
index d828c4c80e..f5435165e7 100644
--- a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/command/PartitionRaftCommandsSerializationTest.java
+++ b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/command/PartitionRaftCommandsSerializationTest.java
@@ -33,7 +33,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
-import org.apache.ignite.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.replicator.ReplicationGroupId;
import org.apache.ignite.internal.schema.BinaryRow;
import org.apache.ignite.internal.schema.Column;
diff --git a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/PartitionCommandListenerTest.java b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/PartitionCommandListenerTest.java
index ee1df2e071..23555da62c 100644
--- a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/PartitionCommandListenerTest.java
+++ b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/PartitionCommandListenerTest.java
@@ -39,8 +39,8 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
-import org.apache.ignite.hlc.HybridClock;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.replicator.ReplicaService;
import org.apache.ignite.internal.schema.BinaryRow;
import org.apache.ignite.internal.schema.Column;
diff --git a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/replication/PartitionReplicaListenerTest.java b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/replication/PartitionReplicaListenerTest.java
index dbf62d6d59..eb1c640790 100644
--- a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/replication/PartitionReplicaListenerTest.java
+++ b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/replication/PartitionReplicaListenerTest.java
@@ -33,8 +33,8 @@ import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
-import org.apache.ignite.hlc.HybridClock;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.replicator.ReplicationGroupId;
import org.apache.ignite.internal.schema.BinaryRow;
import org.apache.ignite.internal.schema.Column;
@@ -266,8 +266,7 @@ public class PartitionReplicaListenerTest extends IgniteAbstractTest {
CompletableFuture fut = partitionReplicaListener.invoke(TABLE_MESSAGES_FACTORY.readOnlySingleRowReplicaRequest()
.groupId(grpId)
- .timestamp(clock.now())
- .transactionId(Timestamp.nextVersion().toUuid())
+ .readTimestamp(clock.now())
.binaryRow(testBinaryKey)
.requestType(RequestType.RO_GET)
.build());
@@ -290,8 +289,7 @@ public class PartitionReplicaListenerTest extends IgniteAbstractTest {
CompletableFuture fut = partitionReplicaListener.invoke(TABLE_MESSAGES_FACTORY.readOnlySingleRowReplicaRequest()
.groupId(grpId)
- .timestamp(clock.now())
- .transactionId(Timestamp.nextVersion().toUuid())
+ .readTimestamp(clock.now())
.binaryRow(testBinaryKey)
.requestType(RequestType.RO_GET)
.build());
@@ -314,8 +312,7 @@ public class PartitionReplicaListenerTest extends IgniteAbstractTest {
CompletableFuture fut = partitionReplicaListener.invoke(TABLE_MESSAGES_FACTORY.readOnlySingleRowReplicaRequest()
.groupId(grpId)
- .timestamp(clock.now())
- .transactionId(Timestamp.nextVersion().toUuid())
+ .readTimestamp(clock.now())
.binaryRow(testBinaryKey)
.requestType(RequestType.RO_GET)
.build());
@@ -337,8 +334,7 @@ public class PartitionReplicaListenerTest extends IgniteAbstractTest {
CompletableFuture fut = partitionReplicaListener.invoke(TABLE_MESSAGES_FACTORY.readOnlySingleRowReplicaRequest()
.groupId(grpId)
- .timestamp(clock.now())
- .transactionId(Timestamp.nextVersion().toUuid())
+ .readTimestamp(clock.now())
.binaryRow(testBinaryKey)
.requestType(RequestType.RO_GET)
.build());
@@ -361,8 +357,7 @@ public class PartitionReplicaListenerTest extends IgniteAbstractTest {
CompletableFuture fut = partitionReplicaListener.invoke(TABLE_MESSAGES_FACTORY.readOnlySingleRowReplicaRequest()
.groupId(grpId)
- .timestamp(clock.now())
- .transactionId(Timestamp.nextVersion().toUuid())
+ .readTimestamp(clock.now())
.binaryRow(testBinaryKey)
.requestType(RequestType.RO_GET)
.build());
diff --git a/modules/table/src/test/java/org/apache/ignite/internal/table/impl/DummyInternalTableImpl.java b/modules/table/src/test/java/org/apache/ignite/internal/table/impl/DummyInternalTableImpl.java
index f30ac90119..a0c1b15dbf 100644
--- a/modules/table/src/test/java/org/apache/ignite/internal/table/impl/DummyInternalTableImpl.java
+++ b/modules/table/src/test/java/org/apache/ignite/internal/table/impl/DummyInternalTableImpl.java
@@ -30,7 +30,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import javax.naming.OperationNotSupportedException;
-import org.apache.ignite.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.replicator.ReplicaService;
import org.apache.ignite.internal.replicator.ReplicationGroupId;
import org.apache.ignite.internal.replicator.listener.ReplicaListener;
@@ -135,7 +135,7 @@ public class DummyInternalTableImpl extends InternalTableImpl {
mock(MvTableStorage.class),
mock(TxStateTableStorage.class),
replicaSvc,
- mock(HybridClock.class)
+ new HybridClock()
);
RaftGroupService svc = partitionMap.get(0);
@@ -268,4 +268,10 @@ public class DummyInternalTableImpl extends InternalTableImpl {
public int partition(BinaryRowEx keyRow) {
return 0;
}
+
+ /** {@inheritDoc} */
+ @Override
+ public CompletableFuture<ClusterNode> evaluateReadOnlyRecipientNode(int partId) {
+ return CompletableFuture.completedFuture(mock(ClusterNode.class));
+ }
}
diff --git a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/InternalTransaction.java b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/InternalTransaction.java
index 0baefbbc33..c66ddbc260 100644
--- a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/InternalTransaction.java
+++ b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/InternalTransaction.java
@@ -82,5 +82,6 @@ public interface InternalTransaction extends Transaction {
*
* @param resultFuture Operation result future.
*/
+ @Deprecated
void enlistResultFuture(CompletableFuture<?> resultFuture);
}
diff --git a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/TxManager.java b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/TxManager.java
index cbacf446d2..96f5cf1ffd 100644
--- a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/TxManager.java
+++ b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/TxManager.java
@@ -21,7 +21,7 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.manager.IgniteComponent;
import org.apache.ignite.internal.replicator.ReplicationGroupId;
import org.apache.ignite.lang.IgniteBiTuple;
@@ -34,12 +34,21 @@ import org.jetbrains.annotations.TestOnly;
*/
public interface TxManager extends IgniteComponent {
/**
- * Starts a transaction coordinated by a local node.
+ * Starts a read-write transaction coordinated by a local node.
*
* @return The transaction.
*/
InternalTransaction begin();
+ /**
+ * Starts either read-write or read-only transaction, depending on {@code readOnly} parameter value.
+ *
+ * @param readOnly {@code true} in order to start a read-only transaction, {@code false} in order to start read-write one.
+ * Calling begin with readOnly {@code false} is an equivalent of TxManager#begin().
+ * @return The started transaction.
+ */
+ InternalTransaction begin(boolean readOnly);
+
/**
* Returns a transaction state.
*
diff --git a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/TxMeta.java b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/TxMeta.java
index 450c868885..4953e51217 100644
--- a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/TxMeta.java
+++ b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/TxMeta.java
@@ -21,7 +21,7 @@ import static java.util.Collections.unmodifiableList;
import java.io.Serializable;
import java.util.List;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.replicator.ReplicationGroupId;
import org.apache.ignite.internal.tostring.S;
diff --git a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/IgniteAbstractTransactionImpl.java b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/IgniteAbstractTransactionImpl.java
new file mode 100644
index 0000000000..0cf02f7fa6
--- /dev/null
+++ b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/IgniteAbstractTransactionImpl.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.tx.impl;
+
+import static org.apache.ignite.internal.util.ExceptionUtils.withCause;
+import static org.apache.ignite.lang.ErrorGroups.Transactions.TX_COMMIT_ERR;
+import static org.apache.ignite.lang.ErrorGroups.Transactions.TX_ROLLBACK_ERR;
+
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
+import org.apache.ignite.internal.tx.InternalTransaction;
+import org.apache.ignite.internal.tx.TxManager;
+import org.apache.ignite.internal.tx.TxState;
+import org.apache.ignite.tx.TransactionException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * An abstract implementation of an ignite internal transaction.
+ */
+public abstract class IgniteAbstractTransactionImpl implements InternalTransaction {
+ /** The id. */
+ private final UUID id;
+
+ /** The transaction manager. */
+ protected final TxManager txManager;
+
+ /**
+ * The constructor.
+ *
+ * @param txManager The tx manager.
+ * @param id The id.
+ */
+ public IgniteAbstractTransactionImpl(TxManager txManager, @NotNull UUID id) {
+ this.txManager = txManager;
+ this.id = id;
+ }
+
+ /** {@inheritDoc} */
+ @NotNull
+ @Override
+ public UUID id() {
+ return id;
+ }
+
+ /** {@inheritDoc} */
+ @Nullable
+ @Override
+ public TxState state() {
+ return txManager.state(id);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void commit() throws TransactionException {
+ try {
+ commitAsync().get();
+ } catch (Exception e) {
+ throw withCause(TransactionException::new, TX_COMMIT_ERR, e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public CompletableFuture<Void> commitAsync() {
+ return finish(true);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void rollback() throws TransactionException {
+ try {
+ rollbackAsync().get();
+ } catch (Exception e) {
+ throw withCause(TransactionException::new, TX_ROLLBACK_ERR, e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public CompletableFuture<Void> rollbackAsync() {
+ return finish(false);
+ }
+
+ /**
+ * Finishes a transaction.
+ *
+ * @param commit {@code true} to commit, false to rollback.
+ * @return The future.
+ */
+ protected abstract CompletableFuture<Void> finish(boolean commit);
+}
diff --git a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/IgniteTransactionsImpl.java b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/IgniteTransactionsImpl.java
index 81384a09df..1e988363d0 100644
--- a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/IgniteTransactionsImpl.java
+++ b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/IgniteTransactionsImpl.java
@@ -28,6 +28,8 @@ import org.apache.ignite.tx.Transaction;
public class IgniteTransactionsImpl implements IgniteTransactions {
private final TxManager txManager;
+ private boolean readOnly = false;
+
/**
* The constructor.
*
@@ -37,6 +39,17 @@ public class IgniteTransactionsImpl implements IgniteTransactions {
this.txManager = txManager;
}
+ /**
+ * The constructor.
+ *
+ * @param txManager The manager.
+ * @param readOnly Read-only
+ */
+ public IgniteTransactionsImpl(TxManager txManager, boolean readOnly) {
+ this(txManager);
+ this.readOnly = readOnly;
+ }
+
/** {@inheritDoc} */
@Override
public IgniteTransactions withTimeout(long timeout) {
@@ -44,15 +57,21 @@ public class IgniteTransactionsImpl implements IgniteTransactions {
throw new UnsupportedOperationException();
}
+ /** {@inheritDoc} */
+ @Override
+ public IgniteTransactions readOnly() {
+ return new IgniteTransactionsImpl(txManager, true);
+ }
+
/** {@inheritDoc} */
@Override
public Transaction begin() {
- return txManager.begin();
+ return txManager.begin(readOnly);
}
/** {@inheritDoc} */
@Override
public CompletableFuture<Transaction> beginAsync() {
- return CompletableFuture.completedFuture(txManager.begin());
+ return CompletableFuture.completedFuture(txManager.begin(readOnly));
}
}
diff --git a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/ReadOnlyTransactionImpl.java b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/ReadOnlyTransactionImpl.java
new file mode 100644
index 0000000000..7d8308821e
--- /dev/null
+++ b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/ReadOnlyTransactionImpl.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.tx.impl;
+
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
+import org.apache.ignite.internal.replicator.ReplicationGroupId;
+import org.apache.ignite.internal.tx.TxManager;
+import org.apache.ignite.lang.IgniteBiTuple;
+import org.apache.ignite.network.ClusterNode;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * The read-only implementation of an internal transaction.
+ */
+public class ReadOnlyTransactionImpl extends IgniteAbstractTransactionImpl {
+ /** The read timestamp. */
+ private final HybridTimestamp readTimestamp;
+
+ /**
+ * The constructor.
+ *
+ * @param txManager The tx manager.
+ * @param id The id.
+ * @param readTimestamp The read timestamp.
+ */
+ public ReadOnlyTransactionImpl(
+ TxManager txManager,
+ @NotNull UUID id,
+ HybridTimestamp readTimestamp
+ ) {
+ super(txManager, id);
+ this.readTimestamp = readTimestamp;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public HybridTimestamp readTimestamp() {
+ return readTimestamp;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public IgniteBiTuple<ClusterNode, Long> enlist(ReplicationGroupId replicationGroupId, IgniteBiTuple<ClusterNode, Long> nodeAndTerm) {
+ // TODO: IGNITE-17666 Close cursor tx finish.
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public IgniteBiTuple<ClusterNode, Long> enlistedNodeAndTerm(ReplicationGroupId replicationGroupId) {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean assignCommitPartition(ReplicationGroupId replicationGroupId) {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ReplicationGroupId commitPartition() {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void enlistResultFuture(CompletableFuture<?> resultFuture) {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected CompletableFuture<Void> finish(boolean commit) {
+ // TODO: IGNITE-17666 Close cursor tx finish.
+ return CompletableFuture.completedFuture(null);
+ }
+}
diff --git a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/TransactionImpl.java b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/ReadWriteTransactionImpl.java
similarity index 73%
rename from modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/TransactionImpl.java
rename to modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/ReadWriteTransactionImpl.java
index e740c8428d..c7652adb88 100644
--- a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/TransactionImpl.java
+++ b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/ReadWriteTransactionImpl.java
@@ -17,10 +17,6 @@
package org.apache.ignite.internal.tx.impl;
-import static org.apache.ignite.internal.util.ExceptionUtils.withCause;
-import static org.apache.ignite.lang.ErrorGroups.Transactions.TX_COMMIT_ERR;
-import static org.apache.ignite.lang.ErrorGroups.Transactions.TX_ROLLBACK_ERR;
-
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
@@ -30,32 +26,22 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicReference;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.logger.IgniteLogger;
import org.apache.ignite.internal.logger.Loggers;
import org.apache.ignite.internal.replicator.ReplicationGroupId;
import org.apache.ignite.internal.tx.InternalTransaction;
import org.apache.ignite.internal.tx.TxManager;
-import org.apache.ignite.internal.tx.TxState;
import org.apache.ignite.lang.IgniteBiTuple;
import org.apache.ignite.network.ClusterNode;
-import org.apache.ignite.tx.TransactionException;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
/**
- * The implementation of an internal transaction.
- *
- * <p>Delegates state management to tx manager.
+ * The read-write implementation of an internal transaction.
*/
-public class TransactionImpl implements InternalTransaction {
+public class ReadWriteTransactionImpl extends IgniteAbstractTransactionImpl {
private static final IgniteLogger LOG = Loggers.forClass(InternalTransaction.class);
- /** The id. */
- private final UUID id;
-
- /** The transaction manager. */
- private final TxManager txManager;
-
/** Enlisted replication groups: replication group id -> (primary replica node, raft term). */
private final Map<ReplicationGroupId, IgniteBiTuple<ClusterNode, Long>> enlisted = new ConcurrentHashMap<>();
@@ -71,9 +57,8 @@ public class TransactionImpl implements InternalTransaction {
* @param txManager The tx manager.
* @param id The id.
*/
- public TransactionImpl(TxManager txManager, @NotNull UUID id) {
- this.txManager = txManager;
- this.id = id;
+ public ReadWriteTransactionImpl(TxManager txManager, @NotNull UUID id) {
+ super(txManager, id);
}
/** {@inheritDoc} */
@@ -88,26 +73,12 @@ public class TransactionImpl implements InternalTransaction {
return commitPartitionRef.get();
}
- /** {@inheritDoc} */
- @NotNull
- @Override
- public UUID id() {
- return id;
- }
-
/** {@inheritDoc} */
@Override
public IgniteBiTuple<ClusterNode, Long> enlistedNodeAndTerm(ReplicationGroupId partGroupId) {
return enlisted.get(partGroupId);
}
- /** {@inheritDoc} */
- @Nullable
- @Override
- public TxState state() {
- return txManager.state(id);
- }
-
/** {@inheritDoc} */
@Override
public IgniteBiTuple<ClusterNode, Long> enlist(ReplicationGroupId replicationGroupId, IgniteBiTuple<ClusterNode, Long> nodeAndTerm) {
@@ -118,43 +89,7 @@ public class TransactionImpl implements InternalTransaction {
/** {@inheritDoc} */
@Override
- public void commit() throws TransactionException {
- try {
- commitAsync().get();
- } catch (Exception e) {
- throw withCause(TransactionException::new, TX_COMMIT_ERR, e);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public CompletableFuture<Void> commitAsync() {
- return finish(true);
- }
-
- /** {@inheritDoc} */
- @Override
- public void rollback() throws TransactionException {
- try {
- rollbackAsync().get();
- } catch (Exception e) {
- throw withCause(TransactionException::new, TX_ROLLBACK_ERR, e);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public CompletableFuture<Void> rollbackAsync() {
- return finish(false);
- }
-
- /**
- * Finishes a transaction.
- *
- * @param commit {@code true} to commit, false to rollback.
- * @return The future.
- */
- private CompletableFuture<Void> finish(boolean commit) {
+ protected CompletableFuture<Void> finish(boolean commit) {
// TODO: https://issues.apache.org/jira/browse/IGNITE-17688 Add proper exception handling.
return CompletableFuture
.allOf(enlistedResults.toArray(new CompletableFuture[0]))
@@ -181,8 +116,8 @@ public class TransactionImpl implements InternalTransaction {
ClusterNode recipientNode = enlisted.get(commitPart).get1();
Long term = enlisted.get(commitPart).get2();
- LOG.debug("Finish [recipientNode={}, term={} commit={}, txId={}, groups={} commitPart={}",
- recipientNode, term, commit, id, groups, commitPart);
+ LOG.debug("Finish [recipientNode={}, term={} commit={}, txId={}, groups={}",
+ recipientNode, term, commit, id(), groups);
return txManager.finish(
commitPart,
@@ -190,7 +125,7 @@ public class TransactionImpl implements InternalTransaction {
term,
commit,
groups,
- id
+ id()
);
} else {
return CompletableFuture.completedFuture(null);
@@ -204,4 +139,16 @@ public class TransactionImpl implements InternalTransaction {
public void enlistResultFuture(CompletableFuture<?> resultFuture) {
enlistedResults.add(resultFuture);
}
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public HybridTimestamp readTimestamp() {
+ return null;
+ }
}
diff --git a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/TxManagerImpl.java b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/TxManagerImpl.java
index 8e187438de..9179fc35c8 100644
--- a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/TxManagerImpl.java
+++ b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/impl/TxManagerImpl.java
@@ -24,8 +24,8 @@ import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
-import org.apache.ignite.hlc.HybridClock;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.replicator.ReplicaService;
import org.apache.ignite.internal.replicator.ReplicationGroupId;
import org.apache.ignite.internal.tx.InternalTransaction;
@@ -77,9 +77,15 @@ public class TxManagerImpl implements TxManager {
/** {@inheritDoc} */
@Override
public InternalTransaction begin() {
+ return begin(false);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public InternalTransaction begin(boolean readOnly) {
UUID txId = Timestamp.nextVersion().toUuid();
- return new TransactionImpl(this, txId);
+ return readOnly ? new ReadOnlyTransactionImpl(this, txId, clock.now()) : new ReadWriteTransactionImpl(this, txId);
}
/** {@inheritDoc} */
diff --git a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/message/TxCleanupReplicaRequest.java b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/message/TxCleanupReplicaRequest.java
index 8e63947127..1b8a23162a 100644
--- a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/message/TxCleanupReplicaRequest.java
+++ b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/message/TxCleanupReplicaRequest.java
@@ -18,7 +18,7 @@
package org.apache.ignite.internal.tx.message;
import java.util.UUID;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.replicator.message.ReplicaRequest;
import org.apache.ignite.internal.replicator.message.TimestampAware;
import org.apache.ignite.network.annotations.Marshallable;
diff --git a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/message/TxFinishReplicaRequest.java b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/message/TxFinishReplicaRequest.java
index c1bcee3451..4a6f91f669 100644
--- a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/message/TxFinishReplicaRequest.java
+++ b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/message/TxFinishReplicaRequest.java
@@ -20,7 +20,7 @@ package org.apache.ignite.internal.tx.message;
import java.util.List;
import java.util.Map;
import java.util.UUID;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.replicator.ReplicationGroupId;
import org.apache.ignite.internal.replicator.message.ReplicaRequest;
import org.apache.ignite.internal.replicator.message.TimestampAware;
diff --git a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/message/TxStateReplicaRequest.java b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/message/TxStateReplicaRequest.java
index 43a8466cb3..983b9133e9 100644
--- a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/message/TxStateReplicaRequest.java
+++ b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/message/TxStateReplicaRequest.java
@@ -18,7 +18,7 @@
package org.apache.ignite.internal.tx.message;
import java.util.UUID;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.replicator.message.ReplicaRequest;
import org.apache.ignite.network.annotations.Marshallable;
import org.apache.ignite.network.annotations.Transferable;
diff --git a/modules/transactions/src/test/java/org/apache/ignite/internal/tx/TxManagerTest.java b/modules/transactions/src/test/java/org/apache/ignite/internal/tx/TxManagerTest.java
index 907335cbd5..5a6ffa759f 100644
--- a/modules/transactions/src/test/java/org/apache/ignite/internal/tx/TxManagerTest.java
+++ b/modules/transactions/src/test/java/org/apache/ignite/internal/tx/TxManagerTest.java
@@ -25,7 +25,7 @@ import static org.mockito.Answers.RETURNS_DEEP_STUBS;
import java.util.Objects;
import java.util.UUID;
-import org.apache.ignite.hlc.HybridClock;
+import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.replicator.ReplicaService;
import org.apache.ignite.internal.replicator.ReplicationGroupId;
import org.apache.ignite.internal.testframework.IgniteAbstractTest;
diff --git a/modules/transactions/src/test/java/org/apache/ignite/internal/tx/storage/state/TxStateStorageAbstractTest.java b/modules/transactions/src/test/java/org/apache/ignite/internal/tx/storage/state/TxStateStorageAbstractTest.java
index 2361df443d..2c0b393934 100644
--- a/modules/transactions/src/test/java/org/apache/ignite/internal/tx/storage/state/TxStateStorageAbstractTest.java
+++ b/modules/transactions/src/test/java/org/apache/ignite/internal/tx/storage/state/TxStateStorageAbstractTest.java
@@ -32,7 +32,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.IntStream;
-import org.apache.ignite.hlc.HybridTimestamp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.replicator.ReplicationGroupId;
import org.apache.ignite.internal.testframework.WorkDirectory;
import org.apache.ignite.internal.testframework.WorkDirectoryExtension;