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 5911d727e3 IGNITE-23286 Throw CompactedException for get list 
metastorage methods (#4541)
5911d727e3 is described below

commit 5911d727e3ef801a5dc4cfaa714b208bd615d18f
Author: Kirill Tkalenko <[email protected]>
AuthorDate: Fri Oct 11 15:03:01 2024 +0300

    IGNITE-23286 Throw CompactedException for get list metastorage methods 
(#4541)
---
 .../internal/metastorage/MetaStorageManager.java   |  88 +++++++++--
 .../metastorage/impl/MetaStorageManagerImpl.java   |  11 +-
 .../metastorage/server/KeyValueStorage.java        |  84 +++++++++-
 .../metastorage/server/KeyValueStorageUtils.java   |  23 ++-
 .../server/persistence/RocksDbKeyValueStorage.java | 110 +++++---------
 .../AbstractCompactionKeyValueStorageTest.java     | 169 +++++++++++++++++++++
 .../server/KeyValueStorageUtilsTest.java           |  19 +++
 .../server/SimpleInMemoryKeyValueStorage.java      |  85 ++++-------
 8 files changed, 431 insertions(+), 158 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 4685ff6f3b..9cf32ec6b4 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
@@ -124,18 +124,88 @@ public interface MetaStorageManager extends 
IgniteComponent {
     CompletableFuture<Entry> get(ByteArray key, long revUpperBound);
 
     /**
-     * Returns all entries corresponding to the given key and bounded by given 
revisions.
-     * All these entries are ordered by revisions and have the same key.
-     * The lower bound and the upper bound are inclusive.
+     * Returns all entries (ordered by revisions) corresponding to the given 
key and bounded by given revisions locally.
      *
      * <p>This method doesn't wait for the storage's revision to become 
greater or equal to the revUpperBound parameter, so it is
-     * up to user to wait for the appropriate time to call this method.
-     * TODO: IGNITE-19735 move this method to another interface for 
interaction with local KeyValueStorage.
+     * up to user to wait for the appropriate time to call this method.</p>
      *
-     * @param key The key.
-     * @param revLowerBound The lower bound of revision.
-     * @param revUpperBound The upper bound of revision.
-     * @return Entries corresponding to the given key.
+     * <p>Let's consider examples of the work of the method and compaction of 
the metastorage. Let's assume that we have keys with
+     * revisions "foo" [2, 4] and "bar" [2, 4 (tombstone)], and the key "some" 
has never been in the metastorage.</p>
+     * <ul>
+     *     <li>Compaction revision is {@code 1}.
+     *     <ul>
+     *         <li>getLocally("foo", 1, 1) - a {@link CompactedException} will 
be thrown.</li>
+     *         <li>getLocally("foo", 1, 2) - will return a single value with 
revision 2.</li>
+     *         <li>getLocally("foo", 1, 3) - will return a single value with 
revision 2.</li>
+     *         <li>getLocally("bar", 1, 1) - a {@link CompactedException} will 
be thrown.</li>
+     *         <li>getLocally("bar", 1, 2) - will return a single value with 
revision 2.</li>
+     *         <li>getLocally("bar", 1, 3) - will return a single value with 
revision 2.</li>
+     *         <li>getLocally("some", 1, 1) - a {@link CompactedException} 
will be thrown.</li>
+     *         <li>getLocally("some", 1, 2) - will return an empty list.</li>
+     *         <li>getLocally("some", 1, 3) - will return an empty list.</li>
+     *     </ul>
+     *     </li>
+     *     <li>Compaction revision is {@code 2}.
+     *     <ul>
+     *         <li>getLocally("foo", 1, 2) - a {@link CompactedException} will 
be thrown.</li>
+     *         <li>getLocally("foo", 2, 2) - a {@link CompactedException} will 
be thrown.</li>
+     *         <li>getLocally("foo", 1, 3) - a {@link CompactedException} will 
be thrown.</li>
+     *         <li>getLocally("foo", 2, 3) - a {@link CompactedException} will 
be thrown.</li>
+     *         <li>getLocally("foo", 3, 3) - will return an empty list.</li>
+     *         <li>getLocally("foo", 3, 4) - will return a single value with 
revision 4.</li>
+     *         <li>getLocally("bar", 1, 2) - a {@link CompactedException} will 
be thrown.</li>
+     *         <li>getLocally("bar", 2, 2) - a {@link CompactedException} will 
be thrown.</li>
+     *         <li>getLocally("bar", 1, 3) - a {@link CompactedException} will 
be thrown.</li>
+     *         <li>getLocally("bar", 2, 3) - a {@link CompactedException} will 
be thrown.</li>
+     *         <li>getLocally("bar", 3, 3) - will return an empty list.</li>
+     *         <li>getLocally("bar", 3, 4) - will return a single value with 
revision 4.</li>
+     *         <li>getLocally("some", 1, 2) - a {@link CompactedException} 
will be thrown.</li>
+     *         <li>getLocally("some", 2, 2) - a {@link CompactedException} 
will be thrown.</li>
+     *         <li>getLocally("some", 2, 3) - a {@link CompactedException} 
will be thrown.</li>
+     *         <li>getLocally("some", 3, 3) - will return an empty list.</li>
+     *     </ul>
+     *     </li>
+     *     <li>Compaction revision is {@code 3}.
+     *     <ul>
+     *         <li>getLocally("foo", 1, 3) - a {@link CompactedException} will 
be thrown.</li>
+     *         <li>getLocally("foo", 2, 3) - a {@link CompactedException} will 
be thrown.</li>
+     *         <li>getLocally("foo", 3, 3) - a {@link CompactedException} will 
be thrown.</li>
+     *         <li>getLocally("foo", 3, 4) - will return a single value with 
revision 4.</li>
+     *         <li>getLocally("foo", 4, 4) - will return a single value with 
revision 4.</li>
+     *         <li>getLocally("bar", 1, 3) - a {@link CompactedException} will 
be thrown.</li>
+     *         <li>getLocally("bar", 2, 3) - a {@link CompactedException} will 
be thrown.</li>
+     *         <li>getLocally("bar", 3, 3) - a {@link CompactedException} will 
be thrown.</li>
+     *         <li>getLocally("bar", 3, 4) - will return a single value with 
revision 4.</li>
+     *         <li>getLocally("bar", 4, 4) - will return a single value with 
revision 4.</li>
+     *         <li>getLocally("some", 2, 3) - a {@link CompactedException} 
will be thrown.</li>
+     *         <li>getLocally("some", 3, 4) - a {@link CompactedException} 
will be thrown.</li>
+     *         <li>getLocally("some", 4, 4) - will return an empty list.</li>
+     *     </ul>
+     *     </li>
+     *     <li>Compaction revision is {@code 4}.
+     *     <ul>
+     *         <li>getLocally("foo", 3, 4) - will return a single value with 
revision 4.</li>
+     *         <li>getLocally("foo", 4, 4) - will return a single value with 
revision 4.</li>
+     *         <li>getLocally("foo", 4, 5) - will return a single value with 
revision 4.</li>
+     *         <li>getLocally("foo", 5, 5) - will return an empty list.</li>
+     *         <li>getLocally("bar", 3, 4) - a {@link CompactedException} will 
be thrown.</li>
+     *         <li>getLocally("bar", 4, 4) - a {@link CompactedException} will 
be thrown.</li>
+     *         <li>getLocally("bar", 4, 5) - a {@link CompactedException} will 
be thrown.</li>
+     *         <li>getLocally("bar", 5, 5) - will return an empty list.</li>
+     *         <li>getLocally("some", 3, 4) - a {@link CompactedException} 
will be thrown.</li>
+     *         <li>getLocally("some", 4, 4) - a {@link CompactedException} 
will be thrown.</li>
+     *         <li>getLocally("some", 4, 5) - a {@link CompactedException} 
will be thrown.</li>
+     *         <li>getLocally("some", 5, 5) - will return an empty list.</li>
+     *     </ul>
+     *     </li>
+     * </ul>
+     *
+     * @param key Key.
+     * @param revLowerBound Lower bound of revision (inclusive).
+     * @param revUpperBound Upper bound of revision (inclusive).
+     * @throws IgniteInternalException with cause {@link 
NodeStoppingException} if the node is in the process of stopping.
+     * @throws CompactedException If no entries could be found and the {@code 
revLowerBound} is less than or equal to the last compacted
+     *      one.
      */
     @Deprecated
     List<Entry> getLocally(byte[] key, long revLowerBound, long revUpperBound);
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 936495685f..fee2698fcf 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
@@ -93,7 +93,6 @@ import org.apache.ignite.internal.util.Cursor;
 import org.apache.ignite.internal.util.ExceptionUtils;
 import org.apache.ignite.internal.util.IgniteSpinBusyLock;
 import org.apache.ignite.internal.util.IgniteUtils;
-import org.apache.ignite.lang.IgniteException;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.TestOnly;
 
@@ -755,15 +754,7 @@ public class MetaStorageManagerImpl implements 
MetaStorageManager, MetastorageGr
 
     @Override
     public List<Entry> getLocally(byte[] key, long revLowerBound, long 
revUpperBound) {
-        if (!busyLock.enterBusy()) {
-            throw new IgniteException(new NodeStoppingException());
-        }
-
-        try {
-            return storage.get(key, revLowerBound, revUpperBound);
-        } finally {
-            busyLock.leaveBusy();
-        }
+        return inBusyLock(busyLock, () -> storage.get(key, revLowerBound, 
revUpperBound));
     }
 
     @Override
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 15d9357bbd..0120df0c88 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
@@ -119,14 +119,84 @@ public interface KeyValueStorage extends 
ManuallyCloseable {
     Entry get(byte[] key, long revUpperBound);
 
     /**
-     * Returns all entries corresponding to the given key and bounded by given 
revisions.
-     * All these entries are ordered by revisions and have the same key.
-     * The lower bound and the upper bound are inclusive.
+     * Returns all entries (ordered by revisions) corresponding to the given 
key and bounded by given revisions.
      *
-     * @param key The key.
-     * @param revLowerBound The lower bound of revision.
-     * @param revUpperBound The upper bound of revision.
-     * @return Entries corresponding to the given key.
+     * <p>Let's consider examples of the work of the method and compaction of 
the metastorage. Let's assume that we have keys with
+     * revisions "foo" [2, 4] and "bar" [2, 4 (tombstone)], and the key "some" 
has never been in the metastorage.</p>
+     * <ul>
+     *     <li>Compaction revision is {@code 1}.
+     *     <ul>
+     *         <li>get("foo", 1, 1) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("foo", 1, 2) - will return a single value with revision 
2.</li>
+     *         <li>get("foo", 1, 3) - will return a single value with revision 
2.</li>
+     *         <li>get("bar", 1, 1) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("bar", 1, 2) - will return a single value with revision 
2.</li>
+     *         <li>get("bar", 1, 3) - will return a single value with revision 
2.</li>
+     *         <li>get("some", 1, 1) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("some", 1, 2) - will return an empty list.</li>
+     *         <li>get("some", 1, 3) - will return an empty list.</li>
+     *     </ul>
+     *     </li>
+     *     <li>Compaction revision is {@code 2}.
+     *     <ul>
+     *         <li>get("foo", 1, 2) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("foo", 2, 2) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("foo", 1, 3) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("foo", 2, 3) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("foo", 3, 3) - will return an empty list.</li>
+     *         <li>get("foo", 3, 4) - will return a single value with revision 
4.</li>
+     *         <li>get("bar", 1, 2) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("bar", 2, 2) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("bar", 1, 3) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("bar", 2, 3) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("bar", 3, 3) - will return an empty list.</li>
+     *         <li>get("bar", 3, 4) - will return a single value with revision 
4.</li>
+     *         <li>get("some", 1, 2) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("some", 2, 2) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("some", 2, 3) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("some", 3, 3) - will return an empty list.</li>
+     *     </ul>
+     *     </li>
+     *     <li>Compaction revision is {@code 3}.
+     *     <ul>
+     *         <li>get("foo", 1, 3) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("foo", 2, 3) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("foo", 3, 3) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("foo", 3, 4) - will return a single value with revision 
4.</li>
+     *         <li>get("foo", 4, 4) - will return a single value with revision 
4.</li>
+     *         <li>get("bar", 1, 3) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("bar", 2, 3) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("bar", 3, 3) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("bar", 3, 4) - will return a single value with revision 
4.</li>
+     *         <li>get("bar", 4, 4) - will return a single value with revision 
4.</li>
+     *         <li>get("some", 2, 3) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("some", 3, 4) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("some", 4, 4) - will return an empty list.</li>
+     *     </ul>
+     *     </li>
+     *     <li>Compaction revision is {@code 4}.
+     *     <ul>
+     *         <li>get("foo", 3, 4) - will return a single value with revision 
4.</li>
+     *         <li>get("foo", 4, 4) - will return a single value with revision 
4.</li>
+     *         <li>get("foo", 4, 5) - will return a single value with revision 
4.</li>
+     *         <li>get("foo", 5, 5) - will return an empty list.</li>
+     *         <li>get("bar", 3, 4) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("bar", 4, 4) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("bar", 4, 5) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("bar", 5, 5) - will return an empty list.</li>
+     *         <li>get("some", 3, 4) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("some", 4, 4) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("some", 4, 5) - a {@link CompactedException} will be 
thrown.</li>
+     *         <li>get("some", 5, 5) - will return an empty list.</li>
+     *     </ul>
+     *     </li>
+     * </ul>
+     *
+     * @param key Key.
+     * @param revLowerBound Lower bound of revision (inclusive).
+     * @param revUpperBound Upper bound of revision (inclusive).
+     * @throws CompactedException If no entries could be found and the {@code 
revLowerBound} is less than or equal to the last
+     *      {@link #setCompactionRevision compacted} one.
      */
     List<Entry> get(byte[] key, long revLowerBound, long revUpperBound);
 
diff --git 
a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/KeyValueStorageUtils.java
 
b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/KeyValueStorageUtils.java
index 5657008a34..705907e08a 100644
--- 
a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/KeyValueStorageUtils.java
+++ 
b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/KeyValueStorageUtils.java
@@ -57,7 +57,7 @@ public class KeyValueStorageUtils {
     }
 
     /**
-     * Returns index of maximum revision which must be less or equal to {@code 
upperBoundRevision}. If there is no such revision then
+     * Returns index of maximum revision which is less or equal to {@code 
upperBoundRevision}. If there is no such revision then
      * {@link #NOT_FOUND} will be returned.
      *
      * @param keyRevisions Metastorage key revisions in ascending order.
@@ -77,6 +77,27 @@ public class KeyValueStorageUtils {
         return i;
     }
 
+    /**
+     * Returns index of minimum revision which is greater or equal to {@code 
lowerBoundRevision}. If there is no such revision then
+     * {@link #NOT_FOUND} will be returned.
+     *
+     * @param keyRevisions Metastorage key revisions in ascending order.
+     * @param lowerBoundRevision Revision lower bound.
+     */
+    public static int minRevisionIndex(long[] keyRevisions, long 
lowerBoundRevision) {
+        int i = binarySearch(keyRevisions, lowerBoundRevision);
+
+        if (i < 0) {
+            if (i == -(keyRevisions.length + 1)) {
+                return NOT_FOUND;
+            }
+
+            i = -(i + 1);
+        }
+
+        return i;
+    }
+
     /** Returns {@link true} if the requested index is the last index of the 
array. */
     public static boolean isLastIndex(long[] arr, int index) {
         assert index >= 0 && index < arr.length : "index=" + index + ", 
arr.length=" + arr.length;
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 39e96deda2..d288d7b6bd 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
@@ -24,6 +24,8 @@ import static 
org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils
 import static 
org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils.assertRequestedRevisionLessThanOrEqualToCurrent;
 import static 
org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils.indexToCompact;
 import static 
org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils.isLastIndex;
+import static 
org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils.maxRevisionIndex;
+import static 
org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils.minRevisionIndex;
 import static 
org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils.toUtf8String;
 import static org.apache.ignite.internal.metastorage.server.Value.TOMBSTONE;
 import static 
org.apache.ignite.internal.metastorage.server.persistence.RocksStorageUtils.appendLong;
@@ -98,7 +100,6 @@ import 
org.apache.ignite.internal.metastorage.impl.MetaStorageManagerImpl;
 import org.apache.ignite.internal.metastorage.server.Condition;
 import org.apache.ignite.internal.metastorage.server.If;
 import org.apache.ignite.internal.metastorage.server.KeyValueStorage;
-import org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils;
 import org.apache.ignite.internal.metastorage.server.MetastorageChecksum;
 import org.apache.ignite.internal.metastorage.server.OnRevisionAppliedCallback;
 import org.apache.ignite.internal.metastorage.server.Statement;
@@ -1138,7 +1139,7 @@ public class RocksDbKeyValueStorage implements 
KeyValueStorage {
         assert revUpperBound >= 0 : revUpperBound;
 
         long[] keyRevisions = getRevisionsForOperation(key);
-        int maxRevisionIndex = 
KeyValueStorageUtils.maxRevisionIndex(keyRevisions, revUpperBound);
+        int maxRevisionIndex = maxRevisionIndex(keyRevisions, revUpperBound);
 
         if (maxRevisionIndex == NOT_FOUND) {
             
CompactedException.throwIfRequestedRevisionLessThanOrEqualToCompacted(revUpperBound,
 compactionRevision);
@@ -1157,46 +1158,49 @@ public class RocksDbKeyValueStorage implements 
KeyValueStorage {
         return EntryImpl.toEntry(key, revision, value);
     }
 
-    /**
-     * Returns all entries corresponding to the given key and bounded by given 
revisions.
-     * All these entries are ordered by revisions and have the same key.
-     * The lower bound and the upper bound are inclusive.
-     *
-     * @param key The key.
-     * @param revLowerBound The lower bound of revision.
-     * @param revUpperBound The upper bound of revision.
-     * @return Entries corresponding to the given key.
-     */
     private List<Entry> doGet(byte[] key, long revLowerBound, long 
revUpperBound) {
-        assert revLowerBound >= 0 : "Invalid arguments: [revLowerBound=" + 
revLowerBound + ']';
-        assert revUpperBound >= 0 : "Invalid arguments: [revUpperBound=" + 
revUpperBound + ']';
-        assert revUpperBound >= revLowerBound
-                : "Invalid arguments: [revLowerBound=" + revLowerBound + ", 
revUpperBound=" + revUpperBound + ']';
+        assert revLowerBound >= 0 : revLowerBound;
+        assert revUpperBound >= 0 : revUpperBound;
+        assert revUpperBound >= revLowerBound : "revLowerBound=" + 
revLowerBound + ", revUpperBound=" + revUpperBound;
 
-        long[] revs;
+        long[] keyRevisions = getRevisionsForOperation(key);
 
-        try {
-            revs = getRevisions(key);
-        } catch (RocksDBException e) {
-            throw new MetaStorageException(OP_EXECUTION_ERR, e);
-        }
+        int minRevisionIndex = minRevisionIndex(keyRevisions, revLowerBound);
+        int maxRevisionIndex = maxRevisionIndex(keyRevisions, revUpperBound);
 
-        if (revs.length == 0) {
-            return Collections.emptyList();
+        if (minRevisionIndex == NOT_FOUND || maxRevisionIndex == NOT_FOUND) {
+            
CompactedException.throwIfRequestedRevisionLessThanOrEqualToCompacted(revLowerBound,
 compactionRevision);
+
+            return List.of();
         }
 
-        int firstRevIndex = minRevisionIndex(revs, revLowerBound);
-        int lastRevIndex = maxRevisionIndex(revs, revUpperBound);
+        var entries = new ArrayList<Entry>();
 
-        // firstRevIndex can be -1 if minRevisionIndex return -1. lastRevIndex 
can be -1 if maxRevisionIndex return -1.
-        if (firstRevIndex == -1 || lastRevIndex == -1) {
-            return Collections.emptyList();
-        }
+        for (int i = minRevisionIndex; i <= maxRevisionIndex; i++) {
+            long revision = keyRevisions[i];
+
+            Value value;
 
-        List<Entry> entries = new ArrayList<>();
+            // More complex check to read less from disk.
+            if (revision <= compactionRevision) {
+                if (!isLastIndex(keyRevisions, i)) {
+                    continue;
+                }
+
+                value = getValueForOperation(key, revision);
+
+                if (value.tombstone()) {
+                    continue;
+                }
+            } else {
+                value = getValueForOperation(key, revision);
+            }
 
-        for (int i = firstRevIndex; i <= lastRevIndex; i++) {
-            entries.add(doGetValue(key, revs[i]));
+            entries.add(EntryImpl.toEntry(key, revision, value));
+        }
+
+        if (entries.isEmpty()) {
+            
CompactedException.throwIfRequestedRevisionLessThanOrEqualToCompacted(revLowerBound,
 compactionRevision);
         }
 
         return entries;
@@ -1252,46 +1256,6 @@ public class RocksDbKeyValueStorage implements 
KeyValueStorage {
         return -1;
     }
 
-    /**
-     * Returns index of minimum revision which must be greater or equal to 
{@code lowerBoundRev}.
-     * If there is no such revision then {@code -1} will be returned.
-     *
-     * @param revs          Revisions list.
-     * @param lowerBoundRev Revision lower bound.
-     * @return Index of minimum revision or {@code -1} if there is no such 
revision.
-     */
-    private static int minRevisionIndex(long[] revs, long lowerBoundRev) {
-        for (int i = 0; i < revs.length; i++) {
-            long rev = revs[i];
-
-            if (rev >= lowerBoundRev) {
-                return i;
-            }
-        }
-
-        return -1;
-    }
-
-    /**
-     * Returns index of maximum revision which must be less or equal to {@code 
upperBoundRev}.
-     * If there is no such revision then {@code -1} will be returned.
-     *
-     * @param revs          Revisions list.
-     * @param upperBoundRev Revision upper bound.
-     * @return Index of maximum revision or {@code -1} if there is no such 
revision.
-     */
-    private static int maxRevisionIndex(long[] revs, long upperBoundRev) {
-        for (int i = revs.length - 1; i >= 0; i--) {
-            long rev = revs[i];
-
-            if (rev <= upperBoundRev) {
-                return i;
-            }
-        }
-
-        return -1;
-    }
-
     /**
      * Gets the value by a key and a 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 e5c6cca3ac..c3e10a8316 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
@@ -534,6 +534,160 @@ public abstract class 
AbstractCompactionKeyValueStorageTest extends AbstractKeyV
         assertDoesNotThrowCompactedExceptionForGetAll(6, FOO_KEY, BAR_KEY, 
NOT_EXISTS_KEY);
     }
 
+    @Test
+    void testGetListAndCompactionForFooKey() {
+        // FOO_KEY has revisions: [1, 3, 5].
+        storage.setCompactionRevision(1);
+        assertThrowsCompactedExceptionForGetList(FOO_KEY, 1, 1);
+        assertThrowsCompactedExceptionForGetList(FOO_KEY, 1, 2);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 1, 3);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 2, 2);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 2, 3);
+
+        storage.setCompactionRevision(2);
+        assertThrowsCompactedExceptionForGetList(FOO_KEY, 1, 1);
+        assertThrowsCompactedExceptionForGetList(FOO_KEY, 1, 2);
+        assertThrowsCompactedExceptionForGetList(FOO_KEY, 2, 2);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 1, 3);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 2, 3);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 3, 3);
+
+        storage.setCompactionRevision(3);
+        assertThrowsCompactedExceptionForGetList(FOO_KEY, 1, 3);
+        assertThrowsCompactedExceptionForGetList(FOO_KEY, 2, 3);
+        assertThrowsCompactedExceptionForGetList(FOO_KEY, 3, 3);
+        assertThrowsCompactedExceptionForGetList(FOO_KEY, 3, 4);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 4, 4);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 1, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 2, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 4, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 3, 5);
+
+        storage.setCompactionRevision(4);
+        assertThrowsCompactedExceptionForGetList(FOO_KEY, 3, 4);
+        assertThrowsCompactedExceptionForGetList(FOO_KEY, 4, 4);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 1, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 2, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 3, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 4, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 5, 5);
+
+        storage.setCompactionRevision(5);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 1, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 2, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 3, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 4, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 5, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 5, 6);
+
+        storage.setCompactionRevision(6);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 1, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 2, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 3, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 4, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 5, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(FOO_KEY, 5, 6);
+        assertThrowsCompactedExceptionForGetList(FOO_KEY, 6, 6);
+        assertThrowsCompactedExceptionForGetList(FOO_KEY, 6, 7);
+    }
+
+    @Test
+    void testGetListAndCompactionForBarKey() {
+        // BAR_KEY has revisions: [1, 2, 5 (tombstone)].
+        storage.setCompactionRevision(1);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 1, 1);
+        assertDoesNotThrowsCompactedExceptionForGetList(BAR_KEY, 1, 2);
+        assertDoesNotThrowsCompactedExceptionForGetList(BAR_KEY, 1, 3);
+        assertDoesNotThrowsCompactedExceptionForGetList(BAR_KEY, 2, 2);
+        assertDoesNotThrowsCompactedExceptionForGetList(BAR_KEY, 2, 3);
+
+        storage.setCompactionRevision(2);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 1, 1);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 1, 2);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 2, 2);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 1, 3);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 2, 3);
+        assertDoesNotThrowsCompactedExceptionForGetList(BAR_KEY, 3, 3);
+
+        storage.setCompactionRevision(3);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 1, 3);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 2, 3);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 3, 3);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 3, 4);
+        assertDoesNotThrowsCompactedExceptionForGetList(BAR_KEY, 4, 4);
+        assertDoesNotThrowsCompactedExceptionForGetList(BAR_KEY, 1, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(BAR_KEY, 2, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(BAR_KEY, 4, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(BAR_KEY, 3, 5);
+
+        storage.setCompactionRevision(4);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 3, 4);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 4, 4);
+        assertDoesNotThrowsCompactedExceptionForGetList(BAR_KEY, 1, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(BAR_KEY, 2, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(BAR_KEY, 3, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(BAR_KEY, 4, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(BAR_KEY, 5, 5);
+
+        storage.setCompactionRevision(5);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 1, 5);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 2, 5);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 3, 5);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 4, 5);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 5, 5);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 5, 6);
+        assertDoesNotThrowsCompactedExceptionForGetList(BAR_KEY, 6, 6);
+
+        storage.setCompactionRevision(6);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 1, 5);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 2, 5);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 3, 5);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 4, 5);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 5, 5);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 5, 6);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 6, 6);
+        assertThrowsCompactedExceptionForGetList(BAR_KEY, 6, 7);
+        assertDoesNotThrowsCompactedExceptionForGetList(BAR_KEY, 7, 7);
+    }
+
+    @Test
+    void testGetListAndCompactionForNotExistsKey() {
+        storage.setCompactionRevision(1);
+        assertThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 1, 1);
+        assertThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 1, 2);
+        assertDoesNotThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 2, 2);
+
+        storage.setCompactionRevision(2);
+        assertThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 1, 2);
+        assertThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 2, 2);
+        assertThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 2, 3);
+        assertDoesNotThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 3, 3);
+
+        storage.setCompactionRevision(3);
+        assertThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 2, 3);
+        assertThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 3, 3);
+        assertThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 3, 4);
+        assertDoesNotThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 4, 4);
+
+        storage.setCompactionRevision(4);
+        assertThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 3, 4);
+        assertThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 4, 4);
+        assertThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 4, 5);
+        assertDoesNotThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 5, 5);
+
+        storage.setCompactionRevision(5);
+        assertThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 4, 5);
+        assertThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 5, 5);
+        assertThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 5, 6);
+        assertDoesNotThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 6, 6);
+
+        storage.setCompactionRevision(6);
+        assertThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 5, 6);
+        assertThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 6, 6);
+        assertThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 6, 7);
+        assertDoesNotThrowsCompactedExceptionForGetList(NOT_EXISTS_KEY, 7, 7);
+    }
+
     private List<Integer> collectRevisions(byte[] key) {
         var revisions = new ArrayList<Integer>();
 
@@ -598,6 +752,21 @@ public abstract class 
AbstractCompactionKeyValueStorageTest extends AbstractKeyV
         }
     }
 
+    private void assertThrowsCompactedExceptionForGetList(byte[] key, long 
revLowerBound, long revUpperBound) {
+        assertThrows(
+                CompactedException.class,
+                () -> storage.get(key, revLowerBound, revUpperBound),
+                () -> String.format("key=%s, revLowerBound=%s, 
revUpperBound=%s", toUtf8String(key), revLowerBound, revUpperBound)
+        );
+    }
+
+    private void assertDoesNotThrowsCompactedExceptionForGetList(byte[] key, 
long revLowerBound, long revUpperBound) {
+        assertDoesNotThrow(
+                () -> storage.get(key, revLowerBound, revUpperBound),
+                () -> String.format("key=%s, revLowerBound=%s, 
revUpperBound=%s", toUtf8String(key), revLowerBound, revUpperBound)
+        );
+    }
+
     private static String toUtf8String(byte[]... keys) {
         return Arrays.stream(keys)
                 .map(KeyValueStorageUtils::toUtf8String)
diff --git 
a/modules/metastorage/src/test/java/org/apache/ignite/internal/metastorage/server/KeyValueStorageUtilsTest.java
 
b/modules/metastorage/src/test/java/org/apache/ignite/internal/metastorage/server/KeyValueStorageUtilsTest.java
index 4211790552..121d4827eb 100644
--- 
a/modules/metastorage/src/test/java/org/apache/ignite/internal/metastorage/server/KeyValueStorageUtilsTest.java
+++ 
b/modules/metastorage/src/test/java/org/apache/ignite/internal/metastorage/server/KeyValueStorageUtilsTest.java
@@ -22,6 +22,7 @@ import static 
org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils
 import static 
org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils.indexToCompact;
 import static 
org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils.isLastIndex;
 import static 
org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils.maxRevisionIndex;
+import static 
org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils.minRevisionIndex;
 import static 
org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils.toUtf8String;
 import static org.apache.ignite.internal.util.ArrayUtils.LONG_EMPTY_ARRAY;
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -107,4 +108,22 @@ public class KeyValueStorageUtilsTest {
 
         assertTrue(isLastIndex(array, 2));
     }
+
+    @Test
+    void testMinRevisionIndex() {
+        long[] keyRevisions = {3, 5, 7};
+
+        assertEquals(0, minRevisionIndex(keyRevisions, 1));
+        assertEquals(0, minRevisionIndex(keyRevisions, 2));
+        assertEquals(0, minRevisionIndex(keyRevisions, 3));
+
+        assertEquals(1, minRevisionIndex(keyRevisions, 4));
+        assertEquals(1, minRevisionIndex(keyRevisions, 5));
+
+        assertEquals(2, minRevisionIndex(keyRevisions, 6));
+        assertEquals(2, minRevisionIndex(keyRevisions, 7));
+
+        assertEquals(NOT_FOUND, minRevisionIndex(keyRevisions, 8));
+        assertEquals(NOT_FOUND, minRevisionIndex(keyRevisions, 9));
+    }
 }
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 4068ab8531..06bb3e10c0 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
@@ -27,6 +27,8 @@ import static 
org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils
 import static 
org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils.assertRequestedRevisionLessThanOrEqualToCurrent;
 import static 
org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils.indexToCompact;
 import static 
org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils.isLastIndex;
+import static 
org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils.maxRevisionIndex;
+import static 
org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils.minRevisionIndex;
 import static 
org.apache.ignite.internal.metastorage.server.KeyValueStorageUtils.toUtf8String;
 import static org.apache.ignite.internal.metastorage.server.Value.TOMBSTONE;
 import static 
org.apache.ignite.internal.metastorage.server.raft.MetaStorageWriteHandler.IDEMPOTENT_COMMAND_PREFIX;
@@ -43,7 +45,6 @@ import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -728,7 +729,7 @@ public class SimpleInMemoryKeyValueStorage implements 
KeyValueStorage {
         assert revUpperBound >= 0 : revUpperBound;
 
         long[] keyRevisions = toLongArray(keysIdx.get(key));
-        int maxRevisionIndex = 
KeyValueStorageUtils.maxRevisionIndex(keyRevisions, revUpperBound);
+        int maxRevisionIndex = maxRevisionIndex(keyRevisions, revUpperBound);
 
         if (maxRevisionIndex == NOT_FOUND) {
             
CompactedException.throwIfRequestedRevisionLessThanOrEqualToCompacted(revUpperBound,
 compactionRevision);
@@ -748,29 +749,37 @@ public class SimpleInMemoryKeyValueStorage implements 
KeyValueStorage {
     }
 
     private List<Entry> doGet(byte[] key, long revLowerBound, long 
revUpperBound) {
-        assert revLowerBound >= 0 : "Invalid arguments: [revLowerBound=" + 
revLowerBound + ']';
-        assert revUpperBound >= 0 : "Invalid arguments: [revUpperBound=" + 
revUpperBound + ']';
-        assert revUpperBound >= revLowerBound
-                : "Invalid arguments: [revLowerBound=" + revLowerBound + ", 
revUpperBound=" + revUpperBound + ']';
+        assert revLowerBound >= 0 : revLowerBound;
+        assert revUpperBound >= 0 : revUpperBound;
+        assert revUpperBound >= revLowerBound : "revLowerBound=" + 
revLowerBound + ", revUpperBound=" + revUpperBound;
 
-        List<Long> revs = keysIdx.get(key);
+        long[] keyRevisions = toLongArray(keysIdx.get(key));
 
-        if (revs == null || revs.isEmpty()) {
-            return Collections.emptyList();
-        }
+        int minRevisionIndex = minRevisionIndex(keyRevisions, revLowerBound);
+        int maxRevisionIndex = maxRevisionIndex(keyRevisions, revUpperBound);
 
-        int firstRevIndex = minRevisionIndex(revs, revLowerBound);
-        int lastRevIndex = maxRevisionIndex(revs, revUpperBound);
+        if (minRevisionIndex == NOT_FOUND || maxRevisionIndex == NOT_FOUND) {
+            
CompactedException.throwIfRequestedRevisionLessThanOrEqualToCompacted(revLowerBound,
 compactionRevision);
 
-        // firstRevIndex can be -1 if minRevisionIndex return -1. lastRevIndex 
can be -1 if maxRevisionIndex return -1.
-        if (firstRevIndex == -1 || lastRevIndex == -1) {
-            return Collections.emptyList();
+            return List.of();
         }
 
-        List<Entry> entries = new ArrayList<>();
+        var entries = new ArrayList<Entry>();
+
+        for (int i = minRevisionIndex; i <= maxRevisionIndex; i++) {
+            long revision = keyRevisions[i];
+
+            Value value = getValue(key, revision);
+
+            if (revision <= compactionRevision && (!isLastIndex(keyRevisions, 
i) || value.tombstone())) {
+                continue;
+            }
+
+            entries.add(EntryImpl.toEntry(key, revision, value));
+        }
 
-        for (int i = firstRevIndex; i <= lastRevIndex; i++) {
-            entries.add(doGetValue(key, revs.get(i)));
+        if (entries.isEmpty()) {
+            
CompactedException.throwIfRequestedRevisionLessThanOrEqualToCompacted(revLowerBound,
 compactionRevision);
         }
 
         return entries;
@@ -798,46 +807,6 @@ public class SimpleInMemoryKeyValueStorage implements 
KeyValueStorage {
         return -1;
     }
 
-    /**
-     * Returns index of minimum revision which must be greater or equal to 
{@code lowerBoundRev}.
-     * If there is no such revision then {@code -1} will be returned.
-     *
-     * @param revs          Revisions list.
-     * @param lowerBoundRev Revision lower bound.
-     * @return Index of minimum revision or {@code -1} if there is no such 
revision.
-     */
-    private static int minRevisionIndex(List<Long> revs, long lowerBoundRev) {
-        for (int i = 0; i < revs.size(); i++) {
-            long rev = revs.get(i);
-
-            if (rev >= lowerBoundRev) {
-                return i;
-            }
-        }
-
-        return -1;
-    }
-
-    /**
-     * Returns index of maximum revision which must be less or equal to {@code 
upperBoundRev}.
-     * If there is no such revision then {@code -1} will be returned.
-     *
-     * @param revs          Revisions list.
-     * @param upperBoundRev Revision upper bound.
-     * @return Index of maximum revision or {@code -1} if there is no such 
revision.
-     */
-    private static int maxRevisionIndex(List<Long> revs, long upperBoundRev) {
-        for (int i = revs.size() - 1; i >= 0; i--) {
-            long rev = revs.get(i);
-
-            if (rev <= upperBoundRev) {
-                return i;
-            }
-        }
-
-        return -1;
-    }
-
     private Entry doGetValue(byte[] key, long lastRev) {
         if (lastRev == 0) {
             return EntryImpl.empty(key);


Reply via email to