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/29 23:26:53 UTC

[ignite-3] 01/04: 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 b8def668b3d9f98f6d98cda6cd5dfceae6dccdb8
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 7910714..05ce46d 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/raft-client</module>
         <module>modules/rest</module>
         <module>modules/runner</module>