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 1bffc0e58acba4bb22b1de8ffca637234b35bcb3 Author: Andrey Gura <[email protected]> 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 | 83 +++++ .../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, 1312 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..7f2883d --- /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..db9d724 --- /dev/null +++ b/modules/metastorage-common/src/main/java/org/apache/ignite/metastorage/common/Operation.java @@ -0,0 +1,83 @@ +/* + * 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. */ + 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 ade1018..ad573a1 100644 --- a/pom.xml +++ b/pom.xml @@ -38,6 +38,8 @@ <module>modules/cli-common</module> <module>modules/configuration</module> <module>modules/configuration-annotation-processor</module> + <module>modules/metastorage-common</module> + <module>modules/metastorage-client</module> <module>modules/rest</module> <module>modules/runner</module> <module>modules/network</module>
