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)));
}
}