You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sk...@apache.org on 2022/03/10 14:58:40 UTC

[ignite-3] branch main updated: IGNITE-16654 Added an ability to compare entry values in meta storage conditional updates. Fixes #706

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

sk0x50 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 b5b3e71  IGNITE-16654 Added an ability to compare entry values in meta storage conditional updates. Fixes #706
b5b3e71 is described below

commit b5b3e711134a787a69fc89223f663ab2676e11b0
Author: Mirza Aliev <al...@gmail.com>
AuthorDate: Thu Mar 10 17:58:25 2022 +0300

    IGNITE-16654 Added an ability to compare entry values in meta storage conditional updates. Fixes #706
    
    Signed-off-by: Slava Koptilin <sl...@gmail.com>
---
 .../client/ItMetaStorageServiceTest.java           |  38 +++--
 .../internal/metastorage/client/Conditions.java    |  18 +--
 .../ignite/internal/metastorage/client/If.java     |   4 +-
 .../metastorage/client/SimpleCondition.java        | 166 +++++++++++++++------
 .../internal/metastorage/common/ConditionType.java |  36 +++--
 .../ignite/internal/metastorage/server/If.java     |   2 +-
 .../metastorage/server/ValueCondition.java         |  42 +++++-
 .../server/raft/MetaStorageListener.java           |   8 +
 .../metastorage/server/RevisionConditionTest.java  |   4 +-
 .../metastorage/server/ValueConditionTest.java     |  74 +++++++++
 10 files changed, 305 insertions(+), 87 deletions(-)

diff --git a/modules/metastorage-client/src/integrationTest/java/org/apache/ignite/internal/metastorage/client/ItMetaStorageServiceTest.java b/modules/metastorage-client/src/integrationTest/java/org/apache/ignite/internal/metastorage/client/ItMetaStorageServiceTest.java
index c54f084..e73a8be 100644
--- a/modules/metastorage-client/src/integrationTest/java/org/apache/ignite/internal/metastorage/client/ItMetaStorageServiceTest.java
+++ b/modules/metastorage-client/src/integrationTest/java/org/apache/ignite/internal/metastorage/client/ItMetaStorageServiceTest.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.metastorage.client;
 
 import static java.util.stream.Collectors.toList;
+import static org.apache.ignite.internal.metastorage.client.CompoundCondition.and;
 import static org.apache.ignite.internal.metastorage.client.CompoundCondition.or;
 import static org.apache.ignite.internal.metastorage.client.Conditions.revision;
 import static org.apache.ignite.internal.metastorage.client.Conditions.value;
@@ -48,6 +49,7 @@ import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -63,6 +65,7 @@ import java.util.stream.Collectors;
 import org.apache.ignite.internal.metastorage.common.OperationType;
 import org.apache.ignite.internal.metastorage.server.AbstractCompoundCondition;
 import org.apache.ignite.internal.metastorage.server.AbstractSimpleCondition;
+import org.apache.ignite.internal.metastorage.server.AndCondition;
 import org.apache.ignite.internal.metastorage.server.EntryEvent;
 import org.apache.ignite.internal.metastorage.server.KeyValueStorage;
 import org.apache.ignite.internal.metastorage.server.OrCondition;
@@ -777,22 +780,27 @@ public class ItMetaStorageServiceTest {
 
         /*
         if (key1.value == val1 || key2.value != val2)
-            if (key3.revision == 3):
+            if (key3.revision == 3 || key2.value > val1 || key1.value >= val2):
                 put(key1, rval1)
                 return true
             else
-                put(key1, rval1)
-                remove(key2, rval2)
-                return false
+                if (key2.value < val1 && key1.value <= val2):
+                    put(key1, rval1)
+                    remove(key2, rval2)
+                    return false
+                else
+                    return true
         else
             put(key2, rval2)
             return false
          */
 
         var iif = If.iif(or(value(key1).eq(val1), value(key2).ne(val2)),
-                iif(revision(key3).eq(3),
+                iif(or(revision(key3).eq(3), or(value(key2).gt(val1), value(key1).ge(val2))),
                         ops(put(key1, rval1)).yield(true),
-                        ops(put(key1, rval1), remove(key2)).yield(false)),
+                        iif(and(value(key2).lt(val1), value(key1).le(val2)),
+                                ops(put(key1, rval1), remove(key2)).yield(false),
+                                ops().yield(true))),
                 ops(put(key2, rval2)).yield(false));
 
         var ifCaptor = ArgumentCaptor.forClass(org.apache.ignite.internal.metastorage.server.If.class);
@@ -808,19 +816,29 @@ public class ItMetaStorageServiceTest {
         assertThat(resultIf.cond(), cond(new OrCondition(new ValueCondition(Type.EQUAL, key1.bytes(), val1),
                 new ValueCondition(Type.NOT_EQUAL, key2.bytes(), val2))));
 
-        assertThat(resultIf.andThen().iif().cond(), cond(new RevisionCondition(RevisionCondition.Type.EQUAL, key3.bytes(), 3)));
+        assertThat(resultIf.andThen().iif().cond(),
+                cond(new OrCondition(new RevisionCondition(RevisionCondition.Type.EQUAL, key3.bytes(), 3),
+                        new OrCondition(new ValueCondition(ValueCondition.Type.GREATER, key2.bytes(), val1), new ValueCondition(
+                                Type.GREATER_OR_EQUAL, key1.bytes(), val2)))));
+
+        assertThat(resultIf.andThen().iif().orElse().iif().cond(),
+                cond(new AndCondition(new ValueCondition(ValueCondition.Type.LESS, key2.bytes(), val1), new ValueCondition(
+                        Type.LESS_OR_EQUAL, key1.bytes(), val2))));
 
         assertThat(resultIf.andThen().iif().andThen().update(), upd(new Update(
-                Arrays.asList(new org.apache.ignite.internal.metastorage.server.Operation(OperationType.PUT, key1.bytes(), rval1)),
+                List.of(new org.apache.ignite.internal.metastorage.server.Operation(OperationType.PUT, key1.bytes(), rval1)),
                 new StatementResult(true))));
 
-        assertThat(resultIf.andThen().iif().orElse().update(), upd(new Update(
+        assertThat(resultIf.andThen().iif().orElse().iif().andThen().update(), upd(new Update(
                 Arrays.asList(new org.apache.ignite.internal.metastorage.server.Operation(OperationType.PUT, key1.bytes(), rval1),
                         new org.apache.ignite.internal.metastorage.server.Operation(OperationType.REMOVE, key2.bytes(), null)),
                 new StatementResult(false))));
 
+        assertThat(resultIf.andThen().iif().orElse().iif().orElse().update(),
+                upd(new Update(Collections.emptyList(), new StatementResult(true))));
+
         assertThat(resultIf.orElse().update(), upd(new Update(
-                Arrays.asList(new org.apache.ignite.internal.metastorage.server.Operation(OperationType.PUT, key2.bytes(), rval2)),
+                List.of(new org.apache.ignite.internal.metastorage.server.Operation(OperationType.PUT, key2.bytes(), rval2)),
                 new StatementResult(false))));
     }
 
diff --git a/modules/metastorage-client/src/main/java/org/apache/ignite/internal/metastorage/client/Conditions.java b/modules/metastorage-client/src/main/java/org/apache/ignite/internal/metastorage/client/Conditions.java
index 8713fe0..8e65790 100644
--- a/modules/metastorage-client/src/main/java/org/apache/ignite/internal/metastorage/client/Conditions.java
+++ b/modules/metastorage-client/src/main/java/org/apache/ignite/internal/metastorage/client/Conditions.java
@@ -21,8 +21,8 @@ import org.apache.ignite.lang.ByteArray;
 import org.jetbrains.annotations.NotNull;
 
 /**
- * This class contains fabric methods which produce conditions needed for conditional multi update functionality provided by meta storage
- * service.
+ * This class contains fabric methods which produce conditions needed for a conditional multi update functionality provided by the meta
+ * storage service.
  *
  * @see SimpleCondition
  */
@@ -41,7 +41,7 @@ public final class Conditions {
     /**
      * Creates condition on entry value.
      *
-     * @param key Identifies an entry which condition will be applied to. Can't be {@code null}.
+     * @param key Identifies an entry, which condition will be applied to. Can't be {@code null}.
      * @return Condition on entry value.
      * @see SimpleCondition.ValueCondition
      */
@@ -50,9 +50,9 @@ public final class Conditions {
     }
 
     /**
-     * Creates condition on entry existence.
+     * Creates condition on an entry existence.
      *
-     * @param key Identifies an entry which condition will be applied to. Can't be {@code null}.
+     * @param key Identifies an entry, which condition will be applied to. Can't be {@code null}.
      * @return Condition on entry existence.
      */
     public static SimpleCondition exists(@NotNull ByteArray key) {
@@ -60,9 +60,9 @@ public final class Conditions {
     }
 
     /**
-     * Creates condition on entry not existence.
+     * Creates a condition on an entry not existence.
      *
-     * @param key Identifies an entry which condition will be applied to. Can't be {@code null}.
+     * @param key Identifies an entry, which condition will be applied to. Can't be {@code null}.
      * @return Condition on entry not existence.
      */
     public static SimpleCondition notExists(@NotNull ByteArray key) {
@@ -70,9 +70,9 @@ public final class Conditions {
     }
 
     /**
-     * Creates condition on an entry's value which checks whether value is tombstone or not.
+     * Creates a condition on an entry's value, which checks whether a value is tombstone or not.
      *
-     * @param key Identifies an entry which condition will be applied to. Can't be {@code null}.
+     * @param key Identifies an entry, which condition will be applied to. Can't be {@code null}.
      * @return Condition on entry's value is tombstone.
      */
     public static SimpleCondition tombstone(@NotNull ByteArray key) {
diff --git a/modules/metastorage-client/src/main/java/org/apache/ignite/internal/metastorage/client/If.java b/modules/metastorage-client/src/main/java/org/apache/ignite/internal/metastorage/client/If.java
index d613e99..ad3ae0d 100644
--- a/modules/metastorage-client/src/main/java/org/apache/ignite/internal/metastorage/client/If.java
+++ b/modules/metastorage-client/src/main/java/org/apache/ignite/internal/metastorage/client/If.java
@@ -18,12 +18,12 @@
 package org.apache.ignite.internal.metastorage.client;
 
 /**
- * Root building block for the compound metas torage invoke command.
+ * Root building block for the compound meta storage invoke command.
  * Contains of boolean condition and 2 branches of execution, like usual programming language's if.
  * Every branch can be either new {@link If} statement (non-terminal) or result terminal statement {@link Update}.
  *
  * <p>The easiest way to construct the needed {@link If} conditional statement is the builtin shortcut methods.
- * For example to create the statement, which implement the following pseudo code:
+ * For example to create the statement, which implement the following pseudocode:
  * <pre>
  * {@code
  *                {@link CompoundCondition}
diff --git a/modules/metastorage-client/src/main/java/org/apache/ignite/internal/metastorage/client/SimpleCondition.java b/modules/metastorage-client/src/main/java/org/apache/ignite/internal/metastorage/client/SimpleCondition.java
index 559dd34..6382a0d 100644
--- a/modules/metastorage-client/src/main/java/org/apache/ignite/internal/metastorage/client/SimpleCondition.java
+++ b/modules/metastorage-client/src/main/java/org/apache/ignite/internal/metastorage/client/SimpleCondition.java
@@ -21,7 +21,7 @@ import java.util.Collection;
 import org.apache.ignite.internal.metastorage.common.ConditionType;
 
 /**
- * Represents a condition for meta storage conditional update.
+ * Represents a condition for a meta storage conditional update.
  *
  * @see MetaStorageService#invoke(Condition, Operation, Operation)
  * @see MetaStorageService#invoke(Condition, Collection, Collection)
@@ -31,7 +31,7 @@ public final class SimpleCondition implements Condition {
     private final InnerCondition cond;
 
     /**
-     * Constructs a condition which wraps the actual condition implementation.
+     * Constructs a condition, which wraps the actual condition implementation.
      *
      * @param cond The actual condition implementation.
      */
@@ -48,8 +48,8 @@ public final class SimpleCondition implements Condition {
     }
 
     /**
-     * Represents condition on entry revision. Only one type of condition could be applied to the one instance of condition. Subsequent
-     * invocations of any method which produces condition will throw {@link IllegalStateException}.
+     * Represents a condition on an entry revision. Only one type of condition could be applied to the one instance of a condition.
+     * Subsequent invocations of any method, which produces a condition will throw {@link IllegalStateException}.
      */
     public static final class RevisionCondition extends AbstractCondition {
         /** The revision as the condition argument. */
@@ -58,7 +58,7 @@ public final class SimpleCondition implements Condition {
         /**
          * Constructs a condition by a revision for an entry identified by the given key.
          *
-         * @param key Identifies an entry which condition will be applied to.
+         * @param key Identifies an entry, which condition will be applied to.
          */
         RevisionCondition(byte[] key) {
             super(key);
@@ -69,12 +69,12 @@ public final class SimpleCondition implements Condition {
         }
 
         /**
-         * Produces the condition of type {@link ConditionType#REV_EQUAL}. This condition tests the given revision on equality with target
-         * entry revision.
+         * Produces the condition of type {@link ConditionType#REV_EQUAL}. This condition tests the given revision on equality
+         * with the target entry revision.
          *
          * @param rev The revision.
          * @return The condition of type {@link ConditionType#REV_EQUAL}.
-         * @throws IllegalStateException In case when the condition is already defined.
+         * @throws IllegalStateException In the case when the condition is already defined.
          */
         public SimpleCondition eq(long rev) {
             validate(type());
@@ -88,11 +88,11 @@ public final class SimpleCondition implements Condition {
 
         /**
          * Produces the condition of type {@link ConditionType#REV_NOT_EQUAL}. This condition tests the given revision on inequality with
-         * target entry revision.
+         * the target entry revision.
          *
          * @param rev The revision.
          * @return The condition of type {@link ConditionType#REV_NOT_EQUAL}.
-         * @throws IllegalStateException In case when the condition is already defined.
+         * @throws IllegalStateException In the case when the condition is already defined.
          */
         public SimpleCondition ne(long rev) {
             validate(type());
@@ -106,11 +106,11 @@ public final class SimpleCondition implements Condition {
 
         /**
          * Produces the condition of type {@link ConditionType#REV_GREATER}. This condition tests that the target entry revision is greater
-         * than given revision.
+         * than the given revision.
          *
          * @param rev The revision.
          * @return The condition of type {@link ConditionType#REV_GREATER}.
-         * @throws IllegalStateException In case when the condition is already defined.
+         * @throws IllegalStateException In the case when the condition is already defined.
          */
         public SimpleCondition gt(long rev) {
             validate(type());
@@ -124,11 +124,11 @@ public final class SimpleCondition implements Condition {
 
         /**
          * Produces the condition of type {@link ConditionType#REV_GREATER_OR_EQUAL}. This condition tests that the target entry revision is
-         * greater than or equal to given revision.
+         * greater than or equals to the given revision.
          *
          * @param rev The revision.
          * @return The condition of type {@link ConditionType#REV_GREATER_OR_EQUAL}.
-         * @throws IllegalStateException In case when the condition is already defined.
+         * @throws IllegalStateException In the case when the condition is already defined.
          */
         public SimpleCondition ge(long rev) {
             validate(type());
@@ -141,29 +141,30 @@ public final class SimpleCondition implements Condition {
         }
 
         /**
-         * Produces the condition of type {@link ConditionType#REV_LESS}. This condition tests that target entry revision is less than the
-         * given revision.
+         * Produces the condition of type {@link ConditionType#REV_LESS}. This condition tests that the target entry revision is less
+         * than the given revision.
          *
          * @param rev The revision.
          * @return The condition of type {@link ConditionType#REV_LESS}.
-         * @throws IllegalStateException In case when the condition is already defined.
+         * @throws IllegalStateException In the case when the condition is already defined.
          */
         public SimpleCondition lt(long rev) {
             validate(type());
 
             type(ConditionType.REV_LESS);
+
             this.rev = rev;
 
             return new SimpleCondition(this);
         }
 
         /**
-         * Produces the condition of type {@link ConditionType#REV_LESS_OR_EQUAL}. This condition tests that target entry revision is less
-         * than or equal to the given revision.
+         * Produces the condition of type {@link ConditionType#REV_LESS_OR_EQUAL}. This condition tests that the target entry revision
+         * is less than or equals to the given revision.
          *
          * @param rev The revision.
          * @return The condition of type {@link ConditionType#REV_LESS_OR_EQUAL}.
-         * @throws IllegalStateException In case when the condition is already defined.
+         * @throws IllegalStateException In the case when the condition is already defined.
          */
         public SimpleCondition le(long rev) {
             validate(type());
@@ -177,8 +178,8 @@ public final class SimpleCondition implements Condition {
     }
 
     /**
-     * Represents condition on entry value. Only one type of condition could be applied to the one instance of condition. Subsequent
-     * invocations of any method which produces condition will throw {@link IllegalStateException}.
+     * Represents a condition on an entry value. Only the one type of condition could be applied to the one instance of a condition.
+     * Subsequent invocations of any method, which produces a condition will throw {@link IllegalStateException}.
      */
     public static final class ValueCondition extends AbstractCondition {
         /** The value as the condition argument. */
@@ -187,7 +188,7 @@ public final class SimpleCondition implements Condition {
         /**
          * Constructs a condition by a value for an entry identified by the given key.
          *
-         * @param key Identifies an entry which condition will be applied to.
+         * @param key Identifies an entry, which condition will be applied to.
          */
         ValueCondition(byte[] key) {
             super(key);
@@ -198,12 +199,12 @@ public final class SimpleCondition implements Condition {
         }
 
         /**
-         * Produces the condition of type {@link ConditionType#VAL_EQUAL}. This condition tests the given value on equality with target
+         * Produces the condition of type {@link ConditionType#VAL_EQUAL}. This condition tests the given value on equality with the target
          * entry value.
          *
          * @param val The value.
          * @return The condition of type {@link ConditionType#VAL_EQUAL}.
-         * @throws IllegalStateException In case when the condition is already defined.
+         * @throws IllegalStateException In the case when the condition is already defined.
          */
         public SimpleCondition eq(byte[] val) {
             validate(type());
@@ -217,11 +218,11 @@ public final class SimpleCondition implements Condition {
 
         /**
          * Produces the condition of type {@link ConditionType#VAL_NOT_EQUAL}. This condition tests the given value on inequality with
-         * target entry value.
+         * the target entry value.
          *
          * @param val The value.
          * @return The condition of type {@link ConditionType#VAL_NOT_EQUAL}.
-         * @throws IllegalStateException In case when the condition is already defined.
+         * @throws IllegalStateException In the case when the condition is already defined.
          */
         public SimpleCondition ne(byte[] val) {
             validate(type());
@@ -232,17 +233,90 @@ public final class SimpleCondition implements Condition {
 
             return new SimpleCondition(this);
         }
+
+
+        /**
+         * Produces the condition of type {@link ConditionType#VAL_GREATER}. This condition tests that the target entry value is greater
+         * than the given value in the lexicographical order.
+         *
+         * @param val The value.
+         * @return The condition of type {@link ConditionType#VAL_GREATER}.
+         * @throws IllegalStateException In the case when the condition is already defined.
+         */
+        public SimpleCondition gt(byte[] val) {
+            validate(type());
+
+            type(ConditionType.VAL_GREATER);
+
+            this.val = val;
+
+            return new SimpleCondition(this);
+        }
+
+        /**
+         * Produces the condition of type {@link ConditionType#VAL_GREATER_OR_EQUAL}. This condition tests that the target entry value is
+         * greater than or equals to the given value in the lexicographical order.
+         *
+         * @param val The value.
+         * @return The condition of type {@link ConditionType#VAL_GREATER_OR_EQUAL}.
+         * @throws IllegalStateException In the case when the condition is already defined.
+         */
+        public SimpleCondition ge(byte[] val) {
+            validate(type());
+
+            type(ConditionType.VAL_GREATER_OR_EQUAL);
+
+            this.val = val;
+
+            return new SimpleCondition(this);
+        }
+
+        /**
+         * Produces the condition of type {@link ConditionType#VAL_LESS}. This condition tests that the target entry value is less than the
+         * given value in the lexicographical order.
+         *
+         * @param val The value.
+         * @return The condition of type {@link ConditionType#VAL_LESS}.
+         * @throws IllegalStateException In the case when the condition is already defined.
+         */
+        public SimpleCondition lt(byte[] val) {
+            validate(type());
+
+            type(ConditionType.VAL_LESS);
+
+            this.val = val;
+
+            return new SimpleCondition(this);
+        }
+
+        /**
+         * Produces the condition of type {@link ConditionType#VAL_LESS_OR_EQUAL}. This condition tests that the target entry value is less
+         * than or equals to the given value in the lexicographical order.
+         *
+         * @param val The value.
+         * @return The condition of type {@link ConditionType#VAL_LESS_OR_EQUAL}.
+         * @throws IllegalStateException In the case when the condition is already defined.
+         */
+        public SimpleCondition le(byte[] val) {
+            validate(type());
+
+            type(ConditionType.VAL_LESS_OR_EQUAL);
+
+            this.val = val;
+
+            return new SimpleCondition(this);
+        }
     }
 
     /**
-     * Represents condition on an entry existence. Only one type of condition could be applied to the one instance of condition. Subsequent
-     * invocations of any method which produces condition will throw {@link IllegalStateException}.
+     * Represents a condition on an entry existence. Only the one type of a condition could be applied to the one instance of a condition.
+     * Subsequent invocations of any method, which produces a condition will throw {@link IllegalStateException}.
      */
     public static final class ExistenceCondition extends AbstractCondition {
         /**
          * Constructs a condition on existence an entry identified by the given key.
          *
-         * @param key Identifies an entry which condition will be applied to.
+         * @param key Identifies an entry, which condition will be applied to.
          */
         ExistenceCondition(byte[] key) {
             super(key);
@@ -253,7 +327,7 @@ public final class SimpleCondition implements Condition {
          * given key.
          *
          * @return The condition of type {@link ConditionType#KEY_EXISTS}.
-         * @throws IllegalStateException In case when the condition is already defined.
+         * @throws IllegalStateException In the case when the condition is already defined.
          */
         public SimpleCondition exists() {
             validate(type());
@@ -268,7 +342,7 @@ public final class SimpleCondition implements Condition {
          * identified by the given key.
          *
          * @return The condition of type {@link ConditionType#KEY_NOT_EXISTS}.
-         * @throws IllegalStateException In case when the condition is already defined.
+         * @throws IllegalStateException In the case when the condition is already defined.
          */
         public SimpleCondition notExists() {
             validate(type());
@@ -280,15 +354,15 @@ public final class SimpleCondition implements Condition {
     }
 
     /**
-     * Represents condition on an entry's value which checks whether value is tombstone or not. Only one type of condition could be applied
-     * to the one instance of condition. Subsequent invocations of any method which produces condition will throw {@link
-     * IllegalStateException}.
+     * Represents a condition on an entry's value, which checks whether a value is tombstone or not. Only the one type of condition
+     * could be applied to the one instance of a condition. Subsequent invocations of any method which produces a condition
+     * will throw {@link IllegalStateException}.
      */
     public static final class TombstoneCondition extends AbstractCondition {
         /**
          * Constructs a condition on an entry, identified by the given key, is tombstone.
          *
-         * @param key Identifies an entry which condition will be applied to.
+         * @param key Identifies an entry, which condition will be applied to.
          */
         TombstoneCondition(byte[] key) {
             super(key);
@@ -299,7 +373,7 @@ public final class SimpleCondition implements Condition {
          * given key, is tombstone.
          *
          * @return The condition of type {@link ConditionType#TOMBSTONE}.
-         * @throws IllegalStateException In case when the condition is already defined.
+         * @throws IllegalStateException In the case when the condition is already defined.
          */
         public SimpleCondition tombstone() {
             validate(type());
@@ -311,9 +385,9 @@ public final class SimpleCondition implements Condition {
     }
 
     /**
-     * Checks that condition is not defined yet. If the condition is already defined then exception will be thrown.
+     * Checks that condition is not defined yet. If the condition is already defined then the {@link IllegalStateException} will be thrown.
      *
-     * @throws IllegalStateException In case when the condition is already defined.
+     * @throws IllegalStateException In the case when the condition is already defined.
      */
     private static void validate(Enum<?> type) {
         if (type != null) {
@@ -322,13 +396,13 @@ public final class SimpleCondition implements Condition {
     }
 
     /**
-     * Defines condition interface.
+     * Defines a condition interface.
      */
     public interface InnerCondition {
         /**
-         * Returns key which identifies an entry which condition will be applied to.
+         * Returns a key, which identifies an entry, which condition will be applied to.
          *
-         * @return Key which identifies an entry which condition will be applied to.
+         * @return Key, which identifies an entry, which condition will be applied to.
          */
         byte[] key();
 
@@ -336,7 +410,7 @@ public final class SimpleCondition implements Condition {
     }
 
     /**
-     * Defines an abstract condition with the key which identifies an entry which condition will be applied to.
+     * Defines an abstract condition with the key, which identifies an entry, which condition will be applied to.
      */
     private abstract static class AbstractCondition implements InnerCondition {
         /** Entry key. */
@@ -350,16 +424,16 @@ public final class SimpleCondition implements Condition {
         /**
          * Constructs a condition with the given entry key.
          *
-         * @param key Key which identifies an entry which condition will be applied to.
+         * @param key Key, which identifies an entry, which condition will be applied to.
          */
         private AbstractCondition(byte[] key) {
             this.key = key;
         }
 
         /**
-         * Returns the key which identifies an entry which condition will be applied to.
+         * Returns the key, which identifies an entry, which condition will be applied to.
          *
-         * @return Key which identifies an entry which condition will be applied to.
+         * @return Key, which identifies an entry, which condition will be applied to.
          */
         @Override
         public byte[] key() {
diff --git a/modules/metastorage-common/src/main/java/org/apache/ignite/internal/metastorage/common/ConditionType.java b/modules/metastorage-common/src/main/java/org/apache/ignite/internal/metastorage/common/ConditionType.java
index 28d1770..08ae8bf 100644
--- a/modules/metastorage-common/src/main/java/org/apache/ignite/internal/metastorage/common/ConditionType.java
+++ b/modules/metastorage-common/src/main/java/org/apache/ignite/internal/metastorage/common/ConditionType.java
@@ -18,39 +18,51 @@
 package org.apache.ignite.internal.metastorage.common;
 
 /**
- * Defines possible condition types which can be applied to the revision.
+ * Defines possible condition types, which can be applied to a revision.
  */
 public enum ConditionType {
-    /** Equality condition type for revision. */
+    /** Equality condition type for a revision. */
     REV_EQUAL,
 
-    /** Inequality condition type for revision. */
+    /** Inequality condition type for a revision. */
     REV_NOT_EQUAL,
 
-    /** Greater than condition type for revision. */
+    /** Greater than condition type for a revision. */
     REV_GREATER,
 
-    /** Less than condition type for revision. */
+    /** Less than condition type for a revision. */
     REV_LESS,
 
-    /** Less than or equal to condition type for revision. */
+    /** Less than or equal to condition type for a revision. */
     REV_LESS_OR_EQUAL,
 
-    /** Greater than or equal to condition type for revision. */
+    /** Greater than or equal to condition type for a revision. */
     REV_GREATER_OR_EQUAL,
 
-    /** Equality condition type for value. */
+    /** Equality condition type for a value. */
     VAL_EQUAL,
 
-    /** Inequality condition type for value. */
+    /** Inequality condition type for a value. */
     VAL_NOT_EQUAL,
 
-    /** Existence condition type for key. */
+    /** Greater than condition type for a value. */
+    VAL_GREATER,
+
+    /** Less than condition type for a value. */
+    VAL_LESS,
+
+    /** Less than or equal to condition type for a value. */
+    VAL_LESS_OR_EQUAL,
+
+    /** Greater than or equal to condition type for a value. */
+    VAL_GREATER_OR_EQUAL,
+
+    /** Existence condition type for a key. */
     KEY_EXISTS,
 
-    /** Non-existence condition type for key. */
+    /** Non-existence condition type for a key. */
     KEY_NOT_EXISTS,
 
-    /** Tombstone condition type for key. */
+    /** Tombstone condition type for a key. */
     TOMBSTONE
 }
diff --git a/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/If.java b/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/If.java
index 5477d59..f5b3152 100644
--- a/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/If.java
+++ b/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/If.java
@@ -20,7 +20,7 @@ package org.apache.ignite.internal.metastorage.server;
 /**
  * Root building block for the compound meta storage invoke command.
  * Contains of boolean condition and 2 branches of execution, like usual programming language's if.
- * Every branch can be either new {@link If} statement (non-terminal) or result terminal statement {@link Update}.
+ * Every branch can be either a new {@link If} statement (non-terminal) or a result terminal statement {@link Update}.
  */
 public class If {
     /** Boolean condition. */
diff --git a/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/ValueCondition.java b/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/ValueCondition.java
index 605d5be..cc3594b 100644
--- a/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/ValueCondition.java
+++ b/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/ValueCondition.java
@@ -21,14 +21,14 @@ import java.util.Arrays;
 import org.jetbrains.annotations.NotNull;
 
 /**
- * Defines condition on entry value.
+ * Defines condition on entry value. Values are compared in the lexicographical order.
  */
 public class ValueCondition extends AbstractSimpleCondition {
     /** Condition type. */
     @NotNull
     private final Type type;
 
-    /** Value which will be tested against an entry value. */
+    /** Value, which will be tested against an entry value. */
     @NotNull
     private final byte[] val;
 
@@ -36,8 +36,8 @@ public class ValueCondition extends AbstractSimpleCondition {
      * Constructs value condition with the given type, key and value.
      *
      * @param type Condition type. Can't be {@code null}.
-     * @param key  Key identifies an entry which condition will be applied to. Can't be {@code null}.
-     * @param val  Value which will be tested against an entry value. Can't be {@code null}.
+     * @param key  Key identifies an entry, which condition will be applied to. Can't be {@code null}.
+     * @param val  Value, which will be tested against an entry value. Can't be {@code null}.
      */
     public ValueCondition(@NotNull Type type, @NotNull byte[] key, @NotNull byte[] val) {
         super(key);
@@ -55,7 +55,7 @@ public class ValueCondition extends AbstractSimpleCondition {
     }
 
     /**
-     * Defines possible condition types which can be applied to the value.
+     * Defines possible condition types, which can be applied to the value. Values are compared in the lexicographical order.
      */
     public enum Type {
         /** Equality condition type. */
@@ -72,6 +72,38 @@ public class ValueCondition extends AbstractSimpleCondition {
             public boolean test(long res) {
                 return res != 0;
             }
+        },
+
+        /** Greater than condition type. */
+        GREATER {
+            @Override
+            public boolean test(long res) {
+                return res > 0;
+            }
+        },
+
+        /** Less than condition type. */
+        LESS {
+            @Override
+            public boolean test(long res) {
+                return res < 0;
+            }
+        },
+
+        /** Less than or equal to condition type. */
+        LESS_OR_EQUAL {
+            @Override
+            public boolean test(long res) {
+                return res <= 0;
+            }
+        },
+
+        /** Greater than or equal to condition type. */
+        GREATER_OR_EQUAL {
+            @Override
+            public boolean test(long res) {
+                return res >= 0;
+            }
         };
 
         /**
diff --git a/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/raft/MetaStorageListener.java b/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/raft/MetaStorageListener.java
index 17d9658..8bb6460 100644
--- a/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/raft/MetaStorageListener.java
+++ b/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/raft/MetaStorageListener.java
@@ -450,6 +450,14 @@ public class MetaStorageListener implements RaftGroupListener {
                 return new ValueCondition(ValueCondition.Type.EQUAL, key, inf.value());
             } else if (type == ConditionType.VAL_NOT_EQUAL) {
                 return new ValueCondition(ValueCondition.Type.NOT_EQUAL, key, inf.value());
+            } else if (type == ConditionType.VAL_GREATER) {
+                return new ValueCondition(ValueCondition.Type.GREATER, key, inf.value());
+            } else if (type == ConditionType.VAL_GREATER_OR_EQUAL) {
+                return new ValueCondition(ValueCondition.Type.GREATER_OR_EQUAL, key, inf.value());
+            } else if (type == ConditionType.VAL_LESS) {
+                return new ValueCondition(ValueCondition.Type.LESS, key, inf.value());
+            } else if (type == ConditionType.VAL_LESS_OR_EQUAL) {
+                return new ValueCondition(ValueCondition.Type.LESS_OR_EQUAL, key, inf.value());
             } else if (type == ConditionType.REV_EQUAL) {
                 return new RevisionCondition(RevisionCondition.Type.EQUAL, key, inf.revision());
             } else if (type == ConditionType.REV_NOT_EQUAL) {
diff --git a/modules/metastorage-server/src/test/java/org/apache/ignite/internal/metastorage/server/RevisionConditionTest.java b/modules/metastorage-server/src/test/java/org/apache/ignite/internal/metastorage/server/RevisionConditionTest.java
index 29f14c5..93cf451 100644
--- a/modules/metastorage-server/src/test/java/org/apache/ignite/internal/metastorage/server/RevisionConditionTest.java
+++ b/modules/metastorage-server/src/test/java/org/apache/ignite/internal/metastorage/server/RevisionConditionTest.java
@@ -73,7 +73,7 @@ public class RevisionConditionTest {
     }
 
     /**
-     * Tests that revision is greater than or equal to another one .
+     * Tests that revision is greater than or equal to another one.
      */
     @Test
     public void ge() {
@@ -98,7 +98,7 @@ public class RevisionConditionTest {
     }
 
     /**
-     * Tests that revision is less than or equal to another one .
+     * Tests that revision is less than or equal to another one.
      */
     @Test
     public void le() {
diff --git a/modules/metastorage-server/src/test/java/org/apache/ignite/internal/metastorage/server/ValueConditionTest.java b/modules/metastorage-server/src/test/java/org/apache/ignite/internal/metastorage/server/ValueConditionTest.java
index f515cf9..0d592b5 100644
--- a/modules/metastorage-server/src/test/java/org/apache/ignite/internal/metastorage/server/ValueConditionTest.java
+++ b/modules/metastorage-server/src/test/java/org/apache/ignite/internal/metastorage/server/ValueConditionTest.java
@@ -18,7 +18,12 @@
 package org.apache.ignite.internal.metastorage.server;
 
 import static org.apache.ignite.internal.metastorage.server.ValueCondition.Type.EQUAL;
+import static org.apache.ignite.internal.metastorage.server.ValueCondition.Type.GREATER;
+import static org.apache.ignite.internal.metastorage.server.ValueCondition.Type.GREATER_OR_EQUAL;
+import static org.apache.ignite.internal.metastorage.server.ValueCondition.Type.LESS;
+import static org.apache.ignite.internal.metastorage.server.ValueCondition.Type.LESS_OR_EQUAL;
 import static org.apache.ignite.internal.metastorage.server.ValueCondition.Type.NOT_EQUAL;
+import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import org.junit.jupiter.api.Test;
@@ -38,6 +43,9 @@ public class ValueConditionTest {
     /** Other entry value. */
     private static final byte[] VAL_2 = new byte[]{22};
 
+    /** Yet another entry value. */
+    private static final byte[] VAL_3 = new byte[]{33};
+
     /**
      * Tests values equality.
      */
@@ -46,6 +54,8 @@ public class ValueConditionTest {
         Condition cond = new ValueCondition(EQUAL, KEY, VAL_1);
 
         assertTrue(cond.test(new Entry(KEY, VAL_1, 1, 1)));
+
+        assertFalse(cond.test(new Entry(KEY, VAL_2, 1, 1)));
     }
 
     /**
@@ -56,5 +66,69 @@ public class ValueConditionTest {
         Condition cond = new ValueCondition(NOT_EQUAL, KEY, VAL_1);
 
         assertTrue(cond.test(new Entry(KEY, VAL_2, 1, 1)));
+
+        assertFalse(cond.test(new Entry(KEY, VAL_1, 1, 1)));
+    }
+
+    /**
+     * Tests that value is greater than another one.
+     */
+    @Test
+    public void gt() {
+        Condition cond = new ValueCondition(GREATER, KEY, VAL_1);
+
+        // byte[]{22} > byte[]{11}.
+        assertTrue(cond.test(new Entry(KEY, VAL_2, 1, 1)));
+
+        // byte[]{11} > byte[]{11}.
+        assertFalse(cond.test(new Entry(KEY, VAL_1, 1, 1)));
+    }
+
+    /**
+     * Tests that value is greater than or equal to another one.
+     */
+    @Test
+    public void ge() {
+        Condition cond = new ValueCondition(GREATER_OR_EQUAL, KEY, VAL_2);
+
+        // byte[]{33} >= byte[]{22}.
+        assertTrue(cond.test(new Entry(KEY, VAL_3, 1, 1)));
+
+        // byte[]{22} >= byte[]{22}.
+        assertTrue(cond.test(new Entry(KEY, VAL_2, 1, 1)));
+
+        // byte[]{11} >= byte[]{22}.
+        assertFalse(cond.test(new Entry(KEY, VAL_1, 1, 1)));
+    }
+
+    /**
+     * Tests that value is less than another one.
+     */
+    @Test
+    public void lt() {
+        Condition cond = new ValueCondition(LESS, KEY, VAL_2);
+
+        // byte[]{11} < byte[]{22}
+        assertTrue(cond.test(new Entry(KEY, VAL_1, 1, 1)));
+
+        // byte[]{22} < byte[]{22}
+        assertFalse(cond.test(new Entry(KEY, VAL_2, 1, 1)));
+    }
+
+    /**
+     * Tests that value is less than or equal to another one.
+     */
+    @Test
+    public void le() {
+        Condition cond = new ValueCondition(LESS_OR_EQUAL, KEY, VAL_2);
+
+        // byte[]{11} <= byte[]{22}
+        assertTrue(cond.test(new Entry(KEY, VAL_1, 1, 1)));
+
+        // byte[]{22} <= byte[]{22}
+        assertTrue(cond.test(new Entry(KEY, VAL_2, 1, 1)));
+
+        // byte[]{33} <= byte[]{22}
+        assertFalse(cond.test(new Entry(KEY, VAL_3, 1, 1)));
     }
 }