You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ag...@apache.org on 2021/03/25 21:22:40 UTC
[ignite-3] 01/03: IGNITE-14198 Meta storage client interface
This is an automated email from the ASF dual-hosted git repository.
agura pushed a commit to branch ignite-14198
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
commit 40ded7fddb474253f2b504c96f6ad70db0d53171
Author: Andrey Gura <ag...@apache.org>
AuthorDate: Wed Feb 17 18:53:22 2021 +0300
IGNITE-14198 Meta storage client interface
---
modules/metastorage-client/pom.xml | 42 +++
.../metastorage/client/MetaStorageService.java | 334 +++++++++++++++++++
.../ignite/metastorage/client/package-info.java | 21 ++
modules/metastorage-common/pom.xml | 41 +++
.../metastorage/common/CompactedException.java | 59 ++++
.../ignite/metastorage/common/Condition.java | 357 +++++++++++++++++++++
.../ignite/metastorage/common/Conditions.java | 53 +++
.../apache/ignite/metastorage/common/Cursor.java | 27 ++
.../apache/ignite/metastorage/common/Entry.java | 52 +++
.../ignite/metastorage/common/Operation.java | 84 +++++
.../common/OperationTimeoutException.java | 59 ++++
.../ignite/metastorage/common/Operations.java | 61 ++++
.../ignite/metastorage/common/WatchEvent.java | 58 ++++
.../ignite/metastorage/common/WatchListener.java | 42 +++
.../ignite/metastorage/common/package-info.java | 21 ++
pom.xml | 2 +
16 files changed, 1313 insertions(+)
diff --git a/modules/metastorage-client/pom.xml b/modules/metastorage-client/pom.xml
new file mode 100644
index 0000000..0d21c81
--- /dev/null
+++ b/modules/metastorage-client/pom.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.ignite</groupId>
+ <artifactId>ignite-parent</artifactId>
+ <version>1</version>
+ <relativePath>../../parent/pom.xml</relativePath>
+ </parent>
+
+ <artifactId>metastorage-client</artifactId>
+ <version>3.0.0-SNAPSHOT</version>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.ignite</groupId>
+ <artifactId>metastorage-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/metastorage-client/src/main/java/org/apache/ignite/metastorage/client/MetaStorageService.java b/modules/metastorage-client/src/main/java/org/apache/ignite/metastorage/client/MetaStorageService.java
new file mode 100644
index 0000000..255ce4b
--- /dev/null
+++ b/modules/metastorage-client/src/main/java/org/apache/ignite/metastorage/client/MetaStorageService.java
@@ -0,0 +1,334 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.metastorage.client;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
+import org.apache.ignite.metastorage.common.CompactedException;
+import org.apache.ignite.metastorage.common.Condition;
+import org.apache.ignite.metastorage.common.Cursor;
+import org.apache.ignite.metastorage.common.Entry;
+import org.apache.ignite.metastorage.common.Operation;
+import org.apache.ignite.metastorage.common.OperationTimeoutException;
+import org.apache.ignite.metastorage.common.WatchListener;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Defines interface for access to a meta storage service.
+ */
+public interface MetaStorageService {
+ /**
+ * Retrieves an entry for the given key.
+ *
+ * @param key Key. Couldn't be {@code null}.
+ * @return An entry for the given key. Couldn't be {@code null}.
+ * @throws OperationTimeoutException If the operation is timed out. Will be thrown on getting future result.
+ * @see Entry
+ */
+ @NotNull
+ CompletableFuture<Entry> get(@NotNull byte[] key);
+
+ /**
+ * Retrieves an entry for the given key and the revision upper bound.
+ *
+ * @param key The key. Couldn't be {@code null}.
+ * @param revUpperBound The upper bound for entry revisions. Must be positive.
+ * @return An entry for the given key and maximum revision limited by {@code revUpperBound}.
+ * Couldn't be {@code null}.
+ * @throws OperationTimeoutException If the operation is timed out. Will be thrown on getting future result.
+ * @throws CompactedException If the desired revisions are removed from the storage due to a compaction.
+ * Will be thrown on getting future result.
+ * @see Entry
+ */
+ @NotNull
+ CompletableFuture<Entry> get(@NotNull byte[] key, long revUpperBound);
+
+ /**
+ * Retrieves entries for given keys.
+ *
+ * @param keys The collection of keys. Couldn't be {@code null} or empty.
+ * Collection elements couldn't be {@code null}.
+ * @return A list of entries for given keys. The order of entries in the result list corresponds to
+ * the traversal order of {@code keys} collection. Couldn't be {@code null}.
+ * @throws OperationTimeoutException If the operation is timed out. Will be thrown on getting future result.
+ * @see Entry
+ */
+ @NotNull
+ CompletableFuture<List<Entry>> getAll(Collection<byte[]> keys);
+
+ /**
+ * Retrieves entries for given keys and the revision upper bound.
+ *
+ * @param keys The collection of keys. Couldn't be {@code null} or empty.
+ * Collection elements couldn't be {@code null}.
+ * @param revUpperBound The upper bound for entry revisions. Must be positive.
+ * @return A list of entries for given keys and maximum revision limited by {@code revUpperBound}.
+ * The order of entries in the result list corresponds to the traversal order of {@code keys} collection.
+ * Couldn't be {@code null}.
+ * @throws OperationTimeoutException If the operation is timed out. Will be thrown on getting future result.
+ * @throws CompactedException If the desired revisions are removed from the storage due to a compaction.
+ * Will be thrown on getting future result.
+ * @see Entry
+ */
+ @NotNull
+ CompletableFuture<List<Entry>> getAll(Collection<byte[]> keys, long revUpperBound);
+
+ /**
+ * Inserts or updates an entry with the given key and the given value.
+ *
+ * @param key The key. Couldn't be {@code null}.
+ * @param value The value.Couldn't be {@code null}.
+ * @return Completed future.
+ * @throws OperationTimeoutException If the operation is timed out. Will be thrown on getting future result.
+ * @see Entry
+ */
+ @NotNull
+ CompletableFuture<Void> put(@NotNull byte[] key, @NotNull byte[] value);
+
+ /**
+ * Inserts or updates an entry with the given key and the given value and
+ * retrieves a previous entry for the given key.
+ *
+ * @param key The key. Couldn't be {@code null}.
+ * @param value The value.Couldn't be {@code null}.
+ * @return A previous entry for the given key. Couldn't be {@code null}.
+ * @throws OperationTimeoutException If the operation is timed out. Will be thrown on getting future result.
+ * @see Entry
+ */
+ @NotNull
+ CompletableFuture<Entry> getAndPut(@NotNull byte[] key, @NotNull byte[] value);
+
+ /**
+ * Inserts or updates entries with given keys and given values.
+ * Size of {@code keys} and {@code values} must be the same.
+ *
+ * @param keys The list of keys. Couldn't be {@code null} or empty.
+ * @param values The list of values corresponding to the list of keys. Couldn't be {@code null} or empty.
+ * @return Completed future.
+ * @throws OperationTimeoutException If the operation is timed out. Will be thrown on getting future result.
+ * @see Entry
+ */
+ @NotNull
+ CompletableFuture<Void> putAll(@NotNull List<byte[]> keys, @NotNull List<byte[]> values);
+
+ /**
+ * Inserts or updates entries with given keys and given values and
+ * retrieves a previous entries for given keys.
+ * Size of {@code keys} and {@code values} must be the same.
+ *
+ * @param keys The list of keys. Couldn't be {@code null} or empty.
+ * @param values The list of values corresponding to the list of keys. Couldn't be {@code null} or empty.
+ * @return A list of entries for given keys. Couldn't be {@code null}.
+ * @throws OperationTimeoutException If the operation is timed out. Will be thrown on getting future result.
+ * @see Entry
+ */
+ @NotNull
+ CompletableFuture<List<Entry>> getAndPutAll(@NotNull List<byte[]> keys, @NotNull List<byte[]> values);
+
+ /**
+ * Removes an entry for the given key.
+ *
+ * @param key The key. Couldn't be {@code null}.
+ * @return Completed future.
+ * @throws OperationTimeoutException If the operation is timed out. Will be thrown on getting future result.
+ * @see Entry
+ */
+ @NotNull
+ CompletableFuture<Void> remove(@NotNull byte[] key);
+
+ /**
+ * Removes an entry for the given key.
+ *
+ * @param key The key. Couldn't be {@code null}.
+ * @return A previous entry for the given key. Couldn't be {@code null}.
+ * @throws OperationTimeoutException If the operation is timed out. Will be thrown on getting future result.
+ * @see Entry
+ */
+ @NotNull
+ CompletableFuture<Void> getAndRemove(@NotNull byte[] key);
+
+ /**
+ * Removes entries for given keys.
+ *
+ * @param key The key. Couldn't be {@code null}.
+ * @return Completed future.
+ * @throws OperationTimeoutException If the operation is timed out. Will be thrown on getting future result.
+ * @see Entry
+ */
+ @NotNull
+ CompletableFuture<Void> removeAll(@NotNull Collection<byte[]> key);
+
+ /**
+ * Removes entries for given keys and retrieves previous entries.
+ *
+ * @param key The key. Couldn't be {@code null}.
+ * @return A list of previous entries for given keys..
+ * The order of entries in the result list corresponds to the traversal order of {@code keys} collection.
+ * Couldn't be {@code null}.
+ * @throws OperationTimeoutException If the operation is timed out. Will be thrown on getting future result.
+ * @see Entry
+ */
+ @NotNull
+ CompletableFuture<List<Entry>> getAndRemoveAll(@NotNull Collection<byte[]> key);
+
+
+ /**
+ * Updates an entry for the given key conditionally.
+ *
+ * <p>Conditional update could be treated as <i>if(condition)-then(success)-else(failure)</i> expression.</p>
+ *
+ * @param key The key. Couldn't be {@code null}.
+ * @param condition The condition.
+ * @param success The update which will be applied in case of condition evaluation yields {@code true}.
+ * @param failure The update which will be applied in case of condition evaluation yields {@code false}.
+ * @return Future result {@code true} if {@code success} update was applied, otherwise {@code false}.
+ * @throws OperationTimeoutException If the operation is timed out. Will be thrown on getting future result.
+ * @see Entry
+ * @see Condition
+ * @see Operation
+ */
+ // TODO: https://issues.apache.org/jira/browse/IGNITE-14269: will be replaced by conditional multi update.
+ @NotNull
+ CompletableFuture<Boolean> invoke(@NotNull byte[] key, @NotNull Condition condition,
+ @NotNull Operation success, @NotNull Operation failure);
+
+ /**
+ * Updates an entry for the given key conditionally.
+ *
+ * <p>Conditional update could be treated as <i>if(condition)-then(success)-else(failure)</i> expression.</p>
+ *
+ * @param key The key. Couldn't be {@code null}.
+ * @param condition The condition.
+ * @param success The update which will be applied in case of condition evaluation yields {@code true}.
+ * @param failure The update which will be applied in case of condition evaluation yields {@code false}.
+ * @return A previous entry for the given key.
+ * @throws OperationTimeoutException If the operation is timed out. Will be thrown on getting future result.
+ * @see Entry
+ * @see Condition
+ * @see Operation
+ */
+ //TODO: https://issues.apache.org/jira/browse/IGNITE-14269: will be replaced by conditional multi update.
+ @NotNull
+ CompletableFuture<Entry> getAndInvoke(@NotNull byte[] key, @NotNull Condition condition,
+ @NotNull Operation success, @NotNull Operation failure);
+
+ /**
+ * Retrieves entries for the given key range in lexicographic order. Entries will be filtered out by upper bound
+ * of given revision number.
+ *
+ * @param keyFrom Start key of range (inclusive). Couldn't be {@code null}.
+ * @param keyTo End key of range (exclusive). Could be {@code null}.
+ * @param revUpperBound The upper bound for entry revision. {@code -1} means latest revision.
+ * @return Cursor built upon entries corresponding to the given range and revision.
+ * @throws OperationTimeoutException If the operation is timed out.
+ * @throws CompactedException If the desired revisions are removed from the storage due to a compaction.
+ * @see Entry
+ */
+ @NotNull
+ Cursor<Entry> range(@NotNull byte[] keyFrom, @Nullable byte[] keyTo, long revUpperBound);
+
+ /**
+ * Retrieves entries for the given key range in lexicographic order. Short cut for
+ * {@link #range(byte[], byte[], long)} where {@code revUpperBound == -1}.
+ *
+ * @param keyFrom Start key of range (inclusive). Couldn't be {@code null}.
+ * @param keyTo End key of range (exclusive). Could be {@code null}.
+ * @return Cursor built upon entries corresponding to the given range and revision.
+ * @throws OperationTimeoutException If the operation is timed out.
+ * @throws CompactedException If the desired revisions are removed from the storage due to a compaction.
+ * @see Entry
+ */
+ @NotNull
+ Cursor<Entry> range(@NotNull byte[] keyFrom, @Nullable byte[] keyTo);
+
+ /**
+ * Subscribes on meta storage updates matching the parameters.
+ *
+ * @param keyFrom Start key of range (inclusive). Could be {@code null}.
+ * @param keyTo End key of range (exclusive). Could be {@code null}.
+ * @param revision Start revision inclusive. {@code 0} - all revision,
+ * {@code -1} - latest revision (accordingly to current meta storage state).
+ * @param lsnr Listener which will be notified for each update.
+ * @return Subscription identifier. Could be used in {@link #stopWatch} method in order to cancel subscription.
+ * @throws OperationTimeoutException If the operation is timed out. Will be thrown on getting future result.
+ * @throws CompactedException If the desired revisions are removed from the storage due to a compaction.
+ * Will be thrown on getting future result.
+ * @see Entry
+ */
+ @NotNull
+ //TODO: UUID Should be replaced by IgniteUUID when it will be introduced.
+ CompletableFuture<UUID> watch(@Nullable byte[] keyFrom, @Nullable byte[] keyTo,
+ long revision, @NotNull WatchListener lsnr);
+
+ /**
+ * Subscribes on meta storage updates for the given key.
+ *
+ * @param key The target key. Could be {@code null}.
+ * @param revision Start revision inclusive. {@code 0} - all revision,
+ * {@code -1} - latest revision (accordingly to current meta storage state).
+ * @param lsnr Listener which will be notified for each update.
+ * @return Subscription identifier. Could be used in {@link #stopWatch} method in order to cancel subscription.
+ * @throws OperationTimeoutException If the operation is timed out. Will be thrown on getting future result.
+ * @throws CompactedException If the desired revisions are removed from the storage due to a compaction.
+ * Will be thrown on getting future result.
+ * @see Entry
+ */
+ @NotNull
+ //TODO: UUID Should be replaced by IgniteUUID when it will be introduced.
+ CompletableFuture<UUID> watch(@NotNull byte[] key, long revision, @NotNull WatchListener lsnr);
+
+ /**
+ * Subscribes on meta storage updates for given keys.
+ *
+ * @param keys Collection of target keys. Could be {@code null}.
+ * @param revision Start revision inclusive. {@code 0} - all revision,
+ * {@code -1} - latest revision (accordingly to current meta storage state).
+ * @param lsnr Listener which will be notified for each update.
+ * @return Subscription identifier. Could be used in {@link #stopWatch} method in order to cancel subscription.
+ * @throws OperationTimeoutException If the operation is timed out. Will be thrown on getting future result.
+ * @throws CompactedException If the desired revisions are removed from the storage due to a compaction.
+ * Will be thrown on getting future result.
+ * @see Entry
+ */
+ @NotNull
+ //TODO: UUID Should be replaced by IgniteUUID when it will be introduced.
+ CompletableFuture<UUID> watch(@NotNull Collection<byte[]> keys, long revision, @NotNull WatchListener lsnr);
+
+ /**
+ * Cancels subscription for the given identifier.
+ *
+ * @param id Subscription identifier.
+ * @return Completed future in case of operation success. Couldn't be {@code null}.
+ * @throws OperationTimeoutException If the operation is timed out. Will be thrown on getting future result.
+ */
+ @NotNull
+ //TODO: UUID Should be replaced by IgniteUUID when it will be introduced.
+ CompletableFuture<Void> stopWatch(@NotNull UUID id);
+
+ /**
+ * Compacts meta storage (removes all tombstone entries and old entries except of entries with latest revision).
+ *
+ * @return Completed future. Couldn't be {@code null}.
+ * @throws OperationTimeoutException If the operation is timed out. Will be thrown on getting future result.
+ */
+ CompletableFuture<Void> compact();
+}
+
diff --git a/modules/metastorage-client/src/main/java/org/apache/ignite/metastorage/client/package-info.java b/modules/metastorage-client/src/main/java/org/apache/ignite/metastorage/client/package-info.java
new file mode 100644
index 0000000..26bfb69
--- /dev/null
+++ b/modules/metastorage-client/src/main/java/org/apache/ignite/metastorage/client/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Defines client interface for access to a meta storage server.
+ */
+package org.apache.ignite.metastorage.client;
\ No newline at end of file
diff --git a/modules/metastorage-common/pom.xml b/modules/metastorage-common/pom.xml
new file mode 100644
index 0000000..cd9e1c6
--- /dev/null
+++ b/modules/metastorage-common/pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.ignite</groupId>
+ <artifactId>ignite-parent</artifactId>
+ <version>1</version>
+ <relativePath>../../parent/pom.xml</relativePath>
+ </parent>
+
+ <artifactId>metastorage-common</artifactId>
+ <version>3.0.0-SNAPSHOT</version>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.jetbrains</groupId>
+ <artifactId>annotations</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/CompactedException.java b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/CompactedException.java
new file mode 100644
index 0000000..6ea9f43
--- /dev/null
+++ b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/CompactedException.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.metastorage.common;
+
+/**
+ * Thrown when a requested operation on meta storage could not be performed because target revisions were removed
+ * from storage due to a compaction procedure. In such case the operation should be retried with actual revision.
+ */
+public class CompactedException extends RuntimeException {
+ /**
+ * Constructs an exception.
+ */
+ public CompactedException() {
+ super();
+ }
+
+ /**
+ * Constructs an exception with a given message.
+ *
+ * @param message Detail message.
+ */
+ public CompactedException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs an exception with a given message and a cause.
+ *
+ * @param message Detail message.
+ * @param cause Cause.
+ */
+ public CompactedException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Constructs an exception with a given cause.
+ *
+ * @param cause Cause.
+ */
+ public CompactedException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/Condition.java b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/Condition.java
new file mode 100644
index 0000000..ee3cab6
--- /dev/null
+++ b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/Condition.java
@@ -0,0 +1,357 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.metastorage.common;
+
+import java.util.Arrays;
+
+/**
+ * Represents a condition for conditional update.
+ */
+public final class Condition {
+ /** Actual condition implementation. */
+ private final InnerCondition cond;
+
+ /**
+ * Constructs a condition which wraps the actual condition implementation.
+ *
+ * @param cond The actual condition implementation.
+ */
+ Condition(InnerCondition cond) {
+ this.cond = cond;
+ }
+
+ /**
+ * Tests the given entry on satisfaction of the condition.
+ *
+ * @param e Entry.
+ * @return The result of condition test. {@code true} - if the entry satisfies to the condition,
+ * otherwise - {@code false}.
+ */
+ public boolean test(Entry e) {
+ return cond.test(e);
+ }
+
+ /**
+ * 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}.
+ */
+ public static final class RevisionCondition implements InnerCondition {
+ /**
+ * The type of condition.
+ *
+ * @see Type
+ */
+ private Type type;
+
+ /**
+ * The revision as the condition argument.
+ */
+ private long rev;
+
+ /**
+ * Default no-op constructor.
+ */
+ RevisionCondition() {
+ // No-op.
+ }
+
+ // TODO: eq, ne, lt, le, gt, ge
+ /**
+ * Produces the condition of type {@link Type#EQUAL}. This condition tests the given revision on equality with
+ * target entry revision.
+ *
+ * @param rev The revision.
+ * @return The condition of type {@link Type#EQUAL}.
+ * @throws IllegalStateException In case when the condition is already defined.
+ */
+ public Condition eq(long rev) {
+ validate(type);
+
+ this.type = Type.EQUAL;
+ this.rev = rev;
+
+ return new Condition(this);
+ }
+
+ /**
+ * Produces the condition of type {@link Type#NOT_EQUAL}. This condition tests the given revision on inequality
+ * with target entry revision.
+ *
+ * @param rev The revision.
+ * @return The condition of type {@link Type#NOT_EQUAL}.
+ * @throws IllegalStateException In case when the condition is already defined.
+ */
+ public Condition ne(long rev) {
+ validate(type);
+
+ this.type = Type.NOT_EQUAL;
+ this.rev = rev;
+
+ return new Condition(this);
+ }
+
+ /**
+ * Produces the condition of type {@link Type#GREATER}. This condition tests that the target entry revision
+ * is greater than given revision.
+ *
+ * @param rev The revision.
+ * @return The condition of type {@link Type#GREATER}.
+ * @throws IllegalStateException In case when the condition is already defined.
+ */
+ public Condition gt(long rev) {
+ validate(type);
+
+ this.type = Type.GREATER;
+ this.rev = rev;
+
+ return new Condition(this);
+ }
+
+ /**
+ * Produces the condition of type {@link Type#GREATER_OR_EQUAL}. This condition tests that the target entry
+ * revision is greater than or equal to given revision.
+ *
+ * @param rev The revision.
+ * @return The condition of type {@link Type#GREATER_OR_EQUAL}.
+ * @throws IllegalStateException In case when the condition is already defined.
+ */
+ public Condition ge(long rev) {
+ validate(type);
+
+ this.type = Type.GREATER_OR_EQUAL;
+ this.rev = rev;
+
+ return new Condition(this);
+ }
+
+ /**
+ * Produces the condition of type {@link Type#LESS}. This condition tests that target entry revision
+ * is less than the given revision.
+ *
+ * @param rev The revision.
+ * @return The condition of type {@link Type#LESS}.
+ * @throws IllegalStateException In case when the condition is already defined.
+ */
+ public Condition lt(long rev) {
+ validate(type);
+
+ this.type = Type.LESS;
+ this.rev = rev;
+
+ return new Condition(this);
+ }
+
+ /**
+ * Produces the condition of type {@link Type#LESS_OR_EQUAL}. This condition tests that target entry revision
+ * is less than or equal to the given revision.
+ *
+ * @param rev The revision.
+ * @return The condition of type {@link Type#LESS_OR_EQUAL}.
+ * @throws IllegalStateException In case when the condition is already defined.
+ */
+ public Condition le(long rev) {
+ validate(type);
+
+ this.type = Type.LESS_OR_EQUAL;
+ this.rev = rev;
+
+ return new Condition(this);
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean test(Entry e) {
+ int res = Long.compare(e.revision(), rev);
+
+ return type.test(res);
+ }
+
+ /**
+ * Defines possible condition types which can be applied to the revision.
+ */
+ enum Type {
+ /** Equality condition type. */
+ EQUAL {
+ @Override public boolean test(long res) {
+ return res == 0;
+ }
+ },
+
+ /** Inequality condition type. */
+ NOT_EQUAL {
+ @Override 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;
+ }
+ };
+
+ /**
+ * Interprets comparison result.
+ *
+ * @param res The result of comparison.
+ * @return The interpretation of the comparison result.
+ */
+ public abstract boolean test(long res);
+ }
+ }
+
+ /**
+ * 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}.
+ */
+ public static final class ValueCondition implements InnerCondition {
+ /**
+ * The type of condition.
+ *
+ * @see Type
+ */
+ private Type type;
+
+ /**
+ * The value as the condition argument.
+ */
+ private byte[] val;
+
+ /**
+ * Default no-op constructor.
+ */
+ ValueCondition() {
+ // No-op.
+ }
+
+ /**
+ * Produces the condition of type {@link Type#EQUAL}. This condition tests the given value on equality with
+ * target entry value.
+ *
+ * @param val The value.
+ * @return The condition of type {@link Type#EQUAL}.
+ * @throws IllegalStateException In case when the condition is already defined.
+ */
+ public Condition eq(byte[] val) {
+ validate(type);
+
+ this.type = Type.EQUAL;
+ this.val = val;
+
+ return new Condition(this);
+ }
+
+ /**
+ * Produces the condition of type {@link Type#NOT_EQUAL}. This condition tests the given мфдгу on inequality
+ * with target entry мфдгу.
+ *
+ * @param val The value.
+ * @return The condition of type {@link Type#NOT_EQUAL}.
+ * @throws IllegalStateException In case when the condition is already defined.
+ */
+ public Condition ne(byte[] val) {
+ validate(type);
+
+ this.type = Type.NOT_EQUAL;
+ this.val = val;
+
+ return new Condition(this);
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean test(Entry e) {
+ int res = Arrays.compare(e.value(), val);
+
+ return type.test(res);
+ }
+
+ /**
+ * Defines possible condition types which can be applied to the value.
+ */
+ enum Type {
+ /** Equality condition type. */
+ EQUAL {
+ @Override public boolean test(long res) {
+ return res == 0;
+ }
+ },
+
+ /** Inequality condition type. */
+ NOT_EQUAL {
+ @Override public boolean test(long res) {
+ return res != 0;
+ }
+ };
+
+ /**
+ * Interprets comparison result.
+ *
+ * @param res The result of comparison.
+ * @return The interpretation of the comparison result.
+ */
+ public abstract boolean test(long res);
+ }
+ }
+
+ /**
+ * Checks that condition is not defined yet. If the condition is already defined then exception will be thrown.
+ *
+ * @throws IllegalStateException In case when the condition is already defined.
+ */
+ private static void validate(Enum<?> type) {
+ if (type != null)
+ throw new IllegalStateException("Condition type " + type.name() + " is already defined.");
+ }
+
+ /**
+ * Defines condition interface.
+ */
+ private interface InnerCondition {
+ /**
+ * Tests the given entry on satisfaction of the condition.
+ *
+ * @param e Entry.
+ * @return The result of condition test. {@code true} - if the entry satisfies to the condition,
+ * otherwise - {@code false}.
+ */
+ boolean test(Entry e);
+ }
+}
diff --git a/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/Conditions.java b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/Conditions.java
new file mode 100644
index 0000000..f83849a
--- /dev/null
+++ b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/Conditions.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.metastorage.common;
+
+/**
+ * This class contains fabric methods which produce conditions needed for conditional multi update functionality
+ * provided by meta storage service.
+ *
+ * @see Condition
+ */
+public final class Conditions {
+ /**
+ * Creates condition on entry revision.
+ *
+ * @return Condition on entry revision.
+ * @see Condition.RevisionCondition
+ */
+ public static Condition.RevisionCondition revision() {
+ return new Condition.RevisionCondition();
+ }
+
+ /**
+ * Creates condition on entry value.
+ *
+ * @return Condition on entry value.
+ * @see Condition.ValueCondition
+ */
+ public static Condition.ValueCondition value() {
+ return new Condition.ValueCondition();
+ }
+
+ /**
+ * Default no-op constructor.
+ */
+ private Conditions() {
+ // No-op.
+ }
+}
diff --git a/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/Cursor.java b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/Cursor.java
new file mode 100644
index 0000000..dcc1c94
--- /dev/null
+++ b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/Cursor.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.metastorage.common;
+
+/**
+ * Closeable cursor.
+ *
+ * @param <T>
+ */
+//TODO: Should be replaced by common entity from org.ignite.lang or org.ignite.core package.
+public interface Cursor<T> extends Iterable<T>, AutoCloseable {
+}
diff --git a/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/Entry.java b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/Entry.java
new file mode 100644
index 0000000..b01128e
--- /dev/null
+++ b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/Entry.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.metastorage.common;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Represents a storage unit as entry with key, value and revision, where
+ * <ul>
+ * <li>key - an unique entry's key represented by an array of bytes. Keys are comparable in lexicographic manner.</li>
+ * <ul>value - a data which is associated with a key and represented as an array of bytes.</ul>
+ * <ul>revision - a number which denotes a version of whole meta storage. Each change increments the revision.</ul>
+ * </ul>
+ */
+public interface Entry {
+ /**
+ * Returns a key.
+ *
+ * @return The key.
+ */
+ @NotNull byte[] key();
+
+ /**
+ * Returns a value. Could be {@code null} for empty entry.
+ *
+ * @return Value.
+ */
+ @Nullable byte[] value();
+
+ /**
+ * Returns a revision.
+ *
+ * @return Revision.
+ */
+ long revision();
+}
diff --git a/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/Operation.java b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/Operation.java
new file mode 100644
index 0000000..98196a9
--- /dev/null
+++ b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/Operation.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.metastorage.common;
+
+/**
+ * Defines operation for meta storage conditional update (invoke).
+ */
+public final class Operation {
+ /** Actual operation implementation. */
+ @SuppressWarnings({"FieldCanBeLocal", "unused"})
+ private final InnerOp upd;
+
+ /**
+ * Constructs an operation which wraps the actual operation implementation.
+ *
+ * @param upd The actual operation implementation.
+ */
+ Operation(InnerOp upd) {
+ this.upd = upd;
+ }
+
+ /**
+ * Represents operation of type <i>remove</i>.
+ */
+ public static final class RemoveOp implements InnerOp {
+ /**
+ * Default no-op constructor.
+ */
+ RemoveOp() {
+ // No-op.
+ }
+ }
+
+ /**
+ * Represents operation of type <i>put</i>.
+ */
+ public static final class PutOp implements InnerOp {
+ /** Value. */
+ private final byte[] val;
+
+ /**
+ * Constructs operation of type <i>put</i>.
+ *
+ * @param val The value to which the entry should be updated.
+ */
+ PutOp(byte[] val) {
+ this.val = val;
+ }
+ }
+
+ /**
+ * Represents operation of type <i>no-op</i>.
+ */
+ public static final class NoOp implements InnerOp {
+ /**
+ * Default no-op constructor.
+ */
+ NoOp() {
+ // No-op.
+ }
+ }
+
+ /**
+ * Defines operation interface.
+ */
+ private interface InnerOp {
+ // Marker interface.
+ }
+}
\ No newline at end of file
diff --git a/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/OperationTimeoutException.java b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/OperationTimeoutException.java
new file mode 100644
index 0000000..4edcf02
--- /dev/null
+++ b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/OperationTimeoutException.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.metastorage.common;
+
+/**
+ * Thrown when an operation is not executed within a specified time period. Usually in such cases the operation
+ * should be retried.
+ */
+public class OperationTimeoutException extends RuntimeException {
+ /**
+ * Constructs an exception.
+ */
+ public OperationTimeoutException() {
+ super();
+ }
+
+ /**
+ * Constructs an exception with a given message.
+ *
+ * @param message Detail message.
+ */
+ public OperationTimeoutException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs an exception with a given message and a cause.
+ *
+ * @param message Detail message.
+ * @param cause Cause.
+ */
+ public OperationTimeoutException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Constructs an exception with a given cause.
+ *
+ * @param cause Cause.
+ */
+ public OperationTimeoutException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/Operations.java b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/Operations.java
new file mode 100644
index 0000000..d7296a7
--- /dev/null
+++ b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/Operations.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.metastorage.common;
+
+/**
+ * This class contains fabric methods which produce operations needed for conditional multi update functionality
+ * (invoke) provided by meta storage service.
+ *
+ * @see Operation
+ */
+public final class Operations {
+ /**
+ * Creates operation of type <i>remove</i>. This type of operation removes entry.
+ *
+ * @return Operation of type <i>remove</i>.
+ */
+ public static Operation remove() {
+ return new Operation(new Operation.RemoveOp());
+ }
+
+ /**
+ * Creates operation of type <i>put</i>. This type of operation inserts or updates value of entry.
+ *
+ * @param value Value.
+ * @return Operation of type <i>put</i>.
+ */
+ public static Operation put(byte[] value) {
+ return new Operation(new Operation.PutOp(value));
+ }
+
+ /**
+ * Creates operation of type <i>noop</i>. It is a special type of operation which doesn't perform any action.
+ *
+ * @return Operation of type <i>noop</i>.
+ */
+ public static Operation noop() {
+ return new Operation(new Operation.NoOp());
+ }
+
+ /**
+ * Default no-op constructor.
+ */
+ private Operations() {
+ // No-op.
+ }
+}
diff --git a/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/WatchEvent.java b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/WatchEvent.java
new file mode 100644
index 0000000..bd78ea5
--- /dev/null
+++ b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/WatchEvent.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.metastorage.common;
+
+/**
+ * Watch event which can be processed by {@link WatchListener}.
+ */
+public final class WatchEvent {
+ /** Old (previous) entry */
+ private final Entry oldEntry;
+
+ /** New (updated) entry. */
+ private final Entry newEntry;
+
+ /**
+ * Constructs an event with given old and new entries.
+ *
+ * @param oldEntry Old entry.
+ * @param newEntry New entry/
+ */
+ public WatchEvent(Entry oldEntry, Entry newEntry) {
+ this.oldEntry = oldEntry;
+ this.newEntry = newEntry;
+ }
+
+ /**
+ * Returns old entry.
+ *
+ * @return Old entry.
+ */
+ public Entry oldEntry() {
+ return oldEntry;
+ }
+
+ /**
+ * Returns new entry.
+ *
+ * @return New entry.
+ */
+ public Entry newEntry() {
+ return newEntry;
+ }
+}
diff --git a/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/WatchListener.java b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/WatchListener.java
new file mode 100644
index 0000000..32785e0
--- /dev/null
+++ b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/WatchListener.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.metastorage.common;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * The listener which receives and handles watch updates.
+ */
+public interface WatchListener {
+ /**
+ * The method will be called on each meta storage update.
+ *
+ * @param events A single event or batch.
+ * @return {@code True} if listener must continue event handling. If returns {@code false} then the listener and
+ * corresponding watch will be unregistered.
+ */
+ boolean onUpdate(@NotNull Iterable<WatchEvent> events);
+
+ /**
+ * The method will be called in case of an error occurred. The listener and corresponding watch will be
+ * unregistered.
+ *
+ * @param e Exception.
+ */
+ void onError(@NotNull Throwable e);
+}
diff --git a/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/package-info.java b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/package-info.java
new file mode 100644
index 0000000..084638b
--- /dev/null
+++ b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Contains entities required by both meta storage client and server implementations.
+ */
+package org.apache.ignite.metastorage.common;
diff --git a/pom.xml b/pom.xml
index 1c0872b..d25bad9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -42,6 +42,8 @@
<module>modules/configuration-annotation-processor</module>
<module>modules/core</module>
<module>modules/network</module>
+ <module>modules/metastorage-common</module>
+ <module>modules/metastorage-client</module>
<module>modules/rest</module>
<module>modules/runner</module>
<module>modules/schema</module>