This is an automated email from the ASF dual-hosted git repository.

tkalkirill pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new e1044be4cd IGNITE-23287 Throw CompactedException for getAll 
metastorage methods (#4529)
e1044be4cd is described below

commit e1044be4cdf11b9854c7d1afcd7dca7ce358099a
Author: Kirill Tkalenko <[email protected]>
AuthorDate: Wed Oct 9 15:26:44 2024 +0300

    IGNITE-23287 Throw CompactedException for getAll metastorage methods (#4529)
---
 .../internal/metastorage/MetaStorageManager.java   |   8 +-
 .../metastorage/impl/ItMetaStorageServiceTest.java |   2 +-
 .../metastorage/impl/MetaStorageManagerImpl.java   |  27 +---
 .../metastorage/server/KeyValueStorage.java        |  24 ++--
 .../server/persistence/RocksDbKeyValueStorage.java |  20 +--
 .../server/raft/MetaStorageListener.java           |   4 +-
 .../AbstractCompactionKeyValueStorageTest.java     | 136 ++++++++++++++++++++-
 .../server/SimpleInMemoryKeyValueStorage.java      |  15 ++-
 8 files changed, 172 insertions(+), 64 deletions(-)

diff --git 
a/modules/metastorage-api/src/main/java/org/apache/ignite/internal/metastorage/MetaStorageManager.java
 
b/modules/metastorage-api/src/main/java/org/apache/ignite/internal/metastorage/MetaStorageManager.java
index c83eeadc8d..e24cd3877f 100644
--- 
a/modules/metastorage-api/src/main/java/org/apache/ignite/internal/metastorage/MetaStorageManager.java
+++ 
b/modules/metastorage-api/src/main/java/org/apache/ignite/internal/metastorage/MetaStorageManager.java
@@ -241,7 +241,13 @@ public interface MetaStorageManager extends 
IgniteComponent {
     HybridTimestamp timestampByRevisionLocally(long revision);
 
     /**
-     * Retrieves entries for given keys.
+     * Returns a future of getting the latest version of entries corresponding 
to the given keys from the metastore leader.
+     *
+     * <p>Never completes with a {@link CompactedException}.</p>
+     *
+     * <p>Future may complete with {@link NodeStoppingException} if the node 
is in the process of stopping.</p>
+     *
+     * @param keys Set of keys (must not be empty).
      */
     CompletableFuture<Map<ByteArray, Entry>> getAll(Set<ByteArray> keys);
 
diff --git 
a/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageServiceTest.java
 
b/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageServiceTest.java
index 7e06ecc851..c7cec67a67 100644
--- 
a/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageServiceTest.java
+++ 
b/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageServiceTest.java
@@ -154,7 +154,7 @@ public class ItMetaStorageServiceTest extends 
BaseIgniteAbstractTest {
     private static final NavigableMap<ByteArray, Entry> EXPECTED_RESULT_MAP;
 
     /** Expected server result collection. */
-    private static final Collection<Entry> EXPECTED_SRV_RESULT_COLL;
+    private static final List<Entry> EXPECTED_SRV_RESULT_COLL;
 
     static {
         EXPECTED_RESULT_MAP = new TreeMap<>();
diff --git 
a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/impl/MetaStorageManagerImpl.java
 
b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/impl/MetaStorageManagerImpl.java
index 560f5ece69..668ffe73d8 100644
--- 
a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/impl/MetaStorageManagerImpl.java
+++ 
b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/impl/MetaStorageManagerImpl.java
@@ -732,32 +732,7 @@ public class MetaStorageManagerImpl implements 
MetaStorageManager, MetastorageGr
 
     @Override
     public CompletableFuture<Map<ByteArray, Entry>> getAll(Set<ByteArray> 
keys) {
-        if (!busyLock.enterBusy()) {
-            return failedFuture(new NodeStoppingException());
-        }
-
-        try {
-            return metaStorageSvcFut.thenCompose(svc -> svc.getAll(keys));
-        } finally {
-            busyLock.leaveBusy();
-        }
-    }
-
-    /**
-     * Retrieves entries for given keys and the revision upper bound.
-     *
-     * @see MetaStorageService#getAll(Set, long)
-     */
-    public CompletableFuture<Map<ByteArray, Entry>> getAll(Set<ByteArray> 
keys, long revUpperBound) {
-        if (!busyLock.enterBusy()) {
-            return failedFuture(new NodeStoppingException());
-        }
-
-        try {
-            return metaStorageSvcFut.thenCompose(svc -> svc.getAll(keys, 
revUpperBound));
-        } finally {
-            busyLock.leaveBusy();
-        }
+        return inBusyLock(busyLock, () -> metaStorageSvcFut.thenCompose(svc -> 
svc.getAll(keys)));
     }
 
     /**
diff --git 
a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/KeyValueStorage.java
 
b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/KeyValueStorage.java
index ad40c44db3..104c2d8bb4 100644
--- 
a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/KeyValueStorage.java
+++ 
b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/KeyValueStorage.java
@@ -60,8 +60,7 @@ public interface KeyValueStorage extends ManuallyCloseable {
      *
      * <p>Never throws {@link CompactedException}.</p>
      *
-     * @param key The key.
-     * @return Value corresponding to the given key.
+     * @param key Key.
      */
     Entry get(byte[] key);
 
@@ -112,7 +111,7 @@ public interface KeyValueStorage extends ManuallyCloseable {
      *     </li>
      * </ul>
      *
-     * @param key The key.
+     * @param key Key.
      * @param revUpperBound The upper bound of revision.
      * @throws CompactedException If the requested entry was not found and the 
{@code revUpperBound} is less than or equal to the last
      *      {@link #setCompactionRevision compacted} one.
@@ -132,21 +131,24 @@ public interface KeyValueStorage extends 
ManuallyCloseable {
     List<Entry> get(byte[] key, long revLowerBound, long revUpperBound);
 
     /**
-     * Returns all entries corresponding to given keys.
+     * Returns the latest version of entries corresponding to the given keys.
+     *
+     * <p>Never throws {@link CompactedException}.</p>
      *
-     * @param keys Keys collection.
-     * @return Entries corresponding to given keys.
+     * @param keys Not empty keys.
      */
-    Collection<Entry> getAll(List<byte[]> keys);
+    List<Entry> getAll(List<byte[]> keys);
 
     /**
-     * Returns all entries corresponding to given keys and bounded by the 
given revision.
+     * Returns entries corresponding to the given keys and bounded by the 
given revision.
      *
-     * @param keys Keys collection.
+     * @param keys Not empty keys.
      * @param revUpperBound Upper bound of revision.
-     * @return Entries corresponding to given keys.
+     * @throws CompactedException If getting any of the individual entries 
would have thrown this exception as if
+     *      {@link #get(byte[], long)} was used.
+     * @see #get(byte[], long)
      */
-    Collection<Entry> getAll(List<byte[]> keys, long revUpperBound);
+    List<Entry> getAll(List<byte[]> keys, long revUpperBound);
 
     /**
      * Inserts an entry with the given key and given value.
diff --git 
a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/persistence/RocksDbKeyValueStorage.java
 
b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/persistence/RocksDbKeyValueStorage.java
index a0769a46e3..dbc0c08e97 100644
--- 
a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/persistence/RocksDbKeyValueStorage.java
+++ 
b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/persistence/RocksDbKeyValueStorage.java
@@ -602,7 +602,7 @@ public class RocksDbKeyValueStorage implements 
KeyValueStorage {
     }
 
     @Override
-    public Collection<Entry> getAll(List<byte[]> keys) {
+    public List<Entry> getAll(List<byte[]> keys) {
         rwLock.readLock().lock();
 
         try {
@@ -613,7 +613,7 @@ public class RocksDbKeyValueStorage implements 
KeyValueStorage {
     }
 
     @Override
-    public Collection<Entry> getAll(List<byte[]> keys, long revUpperBound) {
+    public List<Entry> getAll(List<byte[]> keys, long revUpperBound) {
         rwLock.readLock().lock();
 
         try {
@@ -1046,22 +1046,14 @@ public class RocksDbKeyValueStorage implements 
KeyValueStorage {
         }
     }
 
-    /**
-     * Gets all entries with given keys and a revision.
-     *
-     * @param keys Target keys.
-     * @param rev  Target revision.
-     * @return Collection of entries.
-     */
-    private Collection<Entry> doGetAll(Collection<byte[]> keys, long rev) {
-        assert keys != null : "keys list can't be null.";
-        assert !keys.isEmpty() : "keys list can't be empty.";
-        assert rev >= 0;
+    private List<Entry> doGetAll(Collection<byte[]> keys, long revUpperBound) {
+        assert !keys.isEmpty();
+        assert revUpperBound >= 0 : revUpperBound;
 
         var res = new ArrayList<Entry>(keys.size());
 
         for (byte[] key : keys) {
-            res.add(doGet(key, rev));
+            res.add(doGet(key, revUpperBound));
         }
 
         return res;
diff --git 
a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/raft/MetaStorageListener.java
 
b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/raft/MetaStorageListener.java
index 94c0e6a82a..3829623520 100644
--- 
a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/raft/MetaStorageListener.java
+++ 
b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/raft/MetaStorageListener.java
@@ -24,8 +24,8 @@ import static 
org.apache.ignite.internal.util.ByteUtils.toByteArrayList;
 import java.io.Serializable;
 import java.nio.file.Path;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Iterator;
+import java.util.List;
 import java.util.function.Consumer;
 import org.apache.ignite.internal.metastorage.Entry;
 import org.apache.ignite.internal.metastorage.MetaStorageManager;
@@ -121,7 +121,7 @@ public class MetaStorageListener implements 
RaftGroupListener, BeforeApplyHandle
                 } else if (command instanceof GetAllCommand) {
                     GetAllCommand getAllCmd = (GetAllCommand) command;
 
-                    Collection<Entry> entries = getAllCmd.revision() == 
MetaStorageManager.LATEST_REVISION
+                    List<Entry> entries = getAllCmd.revision() == 
MetaStorageManager.LATEST_REVISION
                             ? storage.getAll(toByteArrayList(getAllCmd.keys()))
                             : 
storage.getAll(toByteArrayList(getAllCmd.keys()), getAllCmd.revision());
 
diff --git 
a/modules/metastorage/src/test/java/org/apache/ignite/internal/metastorage/server/AbstractCompactionKeyValueStorageTest.java
 
b/modules/metastorage/src/test/java/org/apache/ignite/internal/metastorage/server/AbstractCompactionKeyValueStorageTest.java
index 6bee5c9472..e5c6cca3ac 100644
--- 
a/modules/metastorage/src/test/java/org/apache/ignite/internal/metastorage/server/AbstractCompactionKeyValueStorageTest.java
+++ 
b/modules/metastorage/src/test/java/org/apache/ignite/internal/metastorage/server/AbstractCompactionKeyValueStorageTest.java
@@ -18,11 +18,11 @@
 package org.apache.ignite.internal.metastorage.server;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.util.stream.Collectors.joining;
 import static org.apache.ignite.internal.metastorage.dsl.Operations.noop;
 import static org.apache.ignite.internal.metastorage.dsl.Operations.ops;
 import static org.apache.ignite.internal.metastorage.dsl.Operations.put;
 import static org.apache.ignite.internal.metastorage.dsl.Operations.remove;
-import static 
org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils.toUtf8String;
 import static 
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
@@ -32,6 +32,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
 
 import java.nio.file.Path;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.UUID;
 import org.apache.ignite.internal.hlc.HybridClock;
@@ -429,6 +430,110 @@ public abstract class 
AbstractCompactionKeyValueStorageTest extends AbstractKeyV
         assertDoesNotThrowCompactedExceptionForGetSingleValue(NOT_EXISTS_KEY, 
7);
     }
 
+    @Test
+    void testGetAllLatestAndCompaction() {
+        storage.setCompactionRevision(6);
+
+        assertDoesNotThrow(() -> storage.getAll(List.of(FOO_KEY, BAR_KEY, 
NOT_EXISTS_KEY)));
+    }
+
+    @Test
+    void testGetAllAndCompactionForFooKey() {
+        // FOO_KEY has revisions: [1, 3, 5].
+        storage.setCompactionRevision(1);
+        assertThrowsCompactedExceptionForGetAll(1, FOO_KEY);
+        assertDoesNotThrowCompactedExceptionForGetAll(2, FOO_KEY);
+
+        storage.setCompactionRevision(2);
+        assertThrowsCompactedExceptionForGetAll(2, FOO_KEY);
+        assertDoesNotThrowCompactedExceptionForGetAll(3, FOO_KEY);
+
+        storage.setCompactionRevision(3);
+        assertThrowsCompactedExceptionForGetAll(3, FOO_KEY);
+        assertDoesNotThrowCompactedExceptionForGetAll(4, FOO_KEY);
+
+        storage.setCompactionRevision(4);
+        assertThrowsCompactedExceptionForGetAll(4, FOO_KEY);
+        assertDoesNotThrowCompactedExceptionForGetAll(5, FOO_KEY);
+
+        storage.setCompactionRevision(5);
+        assertThrowsCompactedExceptionForGetAll(4, FOO_KEY);
+        assertDoesNotThrowCompactedExceptionForGetAll(5, FOO_KEY);
+
+        storage.setCompactionRevision(6);
+        assertThrowsCompactedExceptionForGetAll(4, FOO_KEY);
+        assertDoesNotThrowCompactedExceptionForGetAll(5, FOO_KEY);
+    }
+
+    @Test
+    void testGetAllAndCompactionForBarKey() {
+        // BAR_KEY has revisions: [1, 2, 5 (tombstone)].
+        storage.setCompactionRevision(1);
+        assertThrowsCompactedExceptionForGetAll(1, BAR_KEY);
+        assertDoesNotThrowCompactedExceptionForGetAll(2, BAR_KEY);
+
+        storage.setCompactionRevision(2);
+        assertThrowsCompactedExceptionForGetAll(2, BAR_KEY);
+        assertDoesNotThrowCompactedExceptionForGetAll(3, BAR_KEY);
+
+        storage.setCompactionRevision(3);
+        assertThrowsCompactedExceptionForGetAll(3, BAR_KEY);
+        assertDoesNotThrowCompactedExceptionForGetAll(4, BAR_KEY);
+
+        storage.setCompactionRevision(4);
+        assertThrowsCompactedExceptionForGetAll(4, BAR_KEY);
+        assertDoesNotThrowCompactedExceptionForGetAll(5, BAR_KEY);
+
+        storage.setCompactionRevision(5);
+        assertThrowsCompactedExceptionForGetAll(5, BAR_KEY);
+        assertDoesNotThrowCompactedExceptionForGetAll(6, BAR_KEY);
+
+        storage.setCompactionRevision(6);
+        assertThrowsCompactedExceptionForGetAll(6, BAR_KEY);
+        assertDoesNotThrowCompactedExceptionForGetAll(7, BAR_KEY);
+    }
+
+    @Test
+    void testGetAllAndCompactionForNotExistsKey() {
+        storage.setCompactionRevision(1);
+        assertThrowsCompactedExceptionForGetAll(1, NOT_EXISTS_KEY);
+        assertDoesNotThrowCompactedExceptionForGetAll(2, NOT_EXISTS_KEY);
+
+        storage.setCompactionRevision(2);
+        assertThrowsCompactedExceptionForGetAll(2, NOT_EXISTS_KEY);
+        assertDoesNotThrowCompactedExceptionForGetAll(3, NOT_EXISTS_KEY);
+
+        storage.setCompactionRevision(3);
+        assertThrowsCompactedExceptionForGetAll(3, NOT_EXISTS_KEY);
+        assertDoesNotThrowCompactedExceptionForGetAll(4, NOT_EXISTS_KEY);
+
+        storage.setCompactionRevision(4);
+        assertThrowsCompactedExceptionForGetAll(4, NOT_EXISTS_KEY);
+        assertDoesNotThrowCompactedExceptionForGetAll(5, NOT_EXISTS_KEY);
+
+        storage.setCompactionRevision(5);
+        assertThrowsCompactedExceptionForGetAll(5, NOT_EXISTS_KEY);
+        assertDoesNotThrowCompactedExceptionForGetAll(6, NOT_EXISTS_KEY);
+
+        storage.setCompactionRevision(6);
+        assertThrowsCompactedExceptionForGetAll(6, NOT_EXISTS_KEY);
+        assertDoesNotThrowCompactedExceptionForGetAll(7, NOT_EXISTS_KEY);
+    }
+
+    @Test
+    void testGetAllAndCompactionForMultipleKeys() {
+        storage.setCompactionRevision(1);
+        assertThrowsCompactedExceptionForGetAll(1, FOO_KEY, BAR_KEY, 
NOT_EXISTS_KEY);
+        assertDoesNotThrowCompactedExceptionForGetAll(2, FOO_KEY, BAR_KEY, 
NOT_EXISTS_KEY);
+
+        storage.setCompactionRevision(5);
+        assertThrowsCompactedExceptionForGetAll(5, FOO_KEY, BAR_KEY, 
NOT_EXISTS_KEY);
+        assertThrowsCompactedExceptionForGetAll(5, FOO_KEY, BAR_KEY);
+        assertThrowsCompactedExceptionForGetAll(5, FOO_KEY, NOT_EXISTS_KEY);
+        assertThrowsCompactedExceptionForGetAll(5, BAR_KEY, NOT_EXISTS_KEY);
+        assertDoesNotThrowCompactedExceptionForGetAll(6, FOO_KEY, BAR_KEY, 
NOT_EXISTS_KEY);
+    }
+
     private List<Integer> collectRevisions(byte[] key) {
         var revisions = new ArrayList<Integer>();
 
@@ -469,4 +574,33 @@ public abstract class 
AbstractCompactionKeyValueStorageTest extends AbstractKeyV
             );
         }
     }
+
+    private void assertThrowsCompactedExceptionForGetAll(long 
endRevisionInclusive, byte[]... keys) {
+        for (long i = 0; i <= endRevisionInclusive; i++) {
+            long revisionUpperBound = i;
+
+            assertThrows(
+                    CompactedException.class,
+                    () -> storage.getAll(List.of(keys), revisionUpperBound),
+                    () -> String.format("keys=%s, revision=%s", 
toUtf8String(keys), revisionUpperBound)
+            );
+        }
+    }
+
+    private void assertDoesNotThrowCompactedExceptionForGetAll(long 
startRevisionInclusive, byte[]... keys) {
+        for (long i = startRevisionInclusive; i <= storage.revision(); i++) {
+            long revisionUpperBound = i;
+
+            assertDoesNotThrow(
+                    () -> storage.getAll(List.of(keys), revisionUpperBound),
+                    () -> String.format("keys=%s, revision=%s", 
toUtf8String(keys), revisionUpperBound)
+            );
+        }
+    }
+
+    private static String toUtf8String(byte[]... keys) {
+        return Arrays.stream(keys)
+                .map(KeyValueStorageUtils::toUtf8String)
+                .collect(joining(", ", "[", "]"));
+    }
 }
diff --git 
a/modules/metastorage/src/testFixtures/java/org/apache/ignite/internal/metastorage/server/SimpleInMemoryKeyValueStorage.java
 
b/modules/metastorage/src/testFixtures/java/org/apache/ignite/internal/metastorage/server/SimpleInMemoryKeyValueStorage.java
index b92d7a611a..eb0df212ce 100644
--- 
a/modules/metastorage/src/testFixtures/java/org/apache/ignite/internal/metastorage/server/SimpleInMemoryKeyValueStorage.java
+++ 
b/modules/metastorage/src/testFixtures/java/org/apache/ignite/internal/metastorage/server/SimpleInMemoryKeyValueStorage.java
@@ -233,14 +233,14 @@ public class SimpleInMemoryKeyValueStorage implements 
KeyValueStorage {
     }
 
     @Override
-    public Collection<Entry> getAll(List<byte[]> keys) {
+    public List<Entry> getAll(List<byte[]> keys) {
         synchronized (mux) {
             return doGetAll(keys, rev);
         }
     }
 
     @Override
-    public Collection<Entry> getAll(List<byte[]> keys, long revUpperBound) {
+    public List<Entry> getAll(List<byte[]> keys, long revUpperBound) {
         synchronized (mux) {
             return doGetAll(keys, revUpperBound);
         }
@@ -711,15 +711,14 @@ public class SimpleInMemoryKeyValueStorage implements 
KeyValueStorage {
         }
     }
 
-    private Collection<Entry> doGetAll(List<byte[]> keys, long rev) {
-        assert keys != null : "keys list can't be null.";
-        assert !keys.isEmpty() : "keys list can't be empty.";
-        assert rev >= 0;
+    private List<Entry> doGetAll(List<byte[]> keys, long revUpperBound) {
+        assert !keys.isEmpty();
+        assert revUpperBound >= 0 : revUpperBound;
 
-        Collection<Entry> res = new ArrayList<>(keys.size());
+        var res = new ArrayList<Entry>(keys.size());
 
         for (byte[] key : keys) {
-            res.add(doGet(key, rev));
+            res.add(doGet(key, revUpperBound));
         }
 
         return res;

Reply via email to