diff --git a/core/src/main/java/io/atomix/core/Atomix.java b/core/src/main/java/io/atomix/core/Atomix.java index e980ee5e02..4530c1a3df 100644 --- a/core/src/main/java/io/atomix/core/Atomix.java +++ b/core/src/main/java/io/atomix/core/Atomix.java @@ -35,8 +35,10 @@ import io.atomix.core.map.AtomicCounterMap; import io.atomix.core.map.AtomicMap; import io.atomix.core.map.AtomicNavigableMap; +import io.atomix.core.map.AtomicSortedMap; import io.atomix.core.map.DistributedMap; import io.atomix.core.map.DistributedNavigableMap; +import io.atomix.core.map.DistributedSortedMap; import io.atomix.core.multimap.AtomicMultimap; import io.atomix.core.multimap.DistributedMultimap; import io.atomix.core.multiset.DistributedMultiset; @@ -354,6 +356,11 @@ public DistributedMap getMap(String name) { return primitives.getMap(name); } + @Override + public , V> DistributedSortedMap getSortedMap(String name) { + return primitives.getSortedMap(name); + } + @Override public , V> DistributedNavigableMap getNavigableMap(String name) { return primitives.getNavigableMap(name); @@ -374,6 +381,11 @@ public AtomicDocumentTree getAtomicDocumentTree(String name) { return primitives.getAtomicDocumentTree(name); } + @Override + public , V> AtomicSortedMap getAtomicSortedMap(String name) { + return primitives.getAtomicSortedMap(name); + } + @Override public , V> AtomicNavigableMap getAtomicNavigableMap(String name) { return primitives.getAtomicNavigableMap(name); diff --git a/core/src/main/java/io/atomix/core/PrimitivesService.java b/core/src/main/java/io/atomix/core/PrimitivesService.java index 86e9a8d2e8..6086401e26 100644 --- a/core/src/main/java/io/atomix/core/PrimitivesService.java +++ b/core/src/main/java/io/atomix/core/PrimitivesService.java @@ -51,12 +51,18 @@ import io.atomix.core.map.AtomicNavigableMap; import io.atomix.core.map.AtomicNavigableMapBuilder; import io.atomix.core.map.AtomicNavigableMapType; +import io.atomix.core.map.AtomicSortedMap; +import io.atomix.core.map.AtomicSortedMapBuilder; +import io.atomix.core.map.AtomicSortedMapType; import io.atomix.core.map.DistributedMap; import io.atomix.core.map.DistributedMapBuilder; import io.atomix.core.map.DistributedMapType; import io.atomix.core.map.DistributedNavigableMap; import io.atomix.core.map.DistributedNavigableMapBuilder; import io.atomix.core.map.DistributedNavigableMapType; +import io.atomix.core.map.DistributedSortedMap; +import io.atomix.core.map.DistributedSortedMapBuilder; +import io.atomix.core.map.DistributedSortedMapType; import io.atomix.core.multimap.AtomicMultimap; import io.atomix.core.multimap.AtomicMultimapBuilder; import io.atomix.core.multimap.AtomicMultimapType; @@ -138,6 +144,31 @@ default DistributedMapBuilder mapBuilder(String name, PrimitiveProt return primitiveBuilder(name, DistributedMapType.instance(), protocol); } + /** + * Creates a new AtomicMapBuilder. + * + * @param name the primitive name + * @param key type + * @param value type + * @return builder for a tree map + */ + default , V> DistributedSortedMapBuilder sortedMapBuilder(String name) { + return primitiveBuilder(name, DistributedSortedMapType.instance()); + } + + /** + * Creates a new AtomicMapBuilder. + * + * @param name the primitive name + * @param protocol the primitive protocol + * @param key type + * @param value type + * @return builder for a tree map + */ + default , V> DistributedSortedMapBuilder sortedMapBuilder(String name, PrimitiveProtocol protocol) { + return primitiveBuilder(name, DistributedSortedMapType.instance(), protocol); + } + /** * Creates a new AtomicMapBuilder. * @@ -236,6 +267,31 @@ default AtomicDocumentTreeBuilder atomicDocumentTreeBuilder(String name, return primitiveBuilder(name, AtomicDocumentTreeType.instance(), protocol); } + /** + * Creates a new {@code AtomicSortedMapBuilder}. + * + * @param name the primitive name + * @param key type + * @param value type + * @return builder for a async atomic tree map + */ + default , V> AtomicSortedMapBuilder atomicSortedMapBuilder(String name) { + return primitiveBuilder(name, AtomicSortedMapType.instance()); + } + + /** + * Creates a new {@code AtomicSortedMapBuilder}. + * + * @param name the primitive name + * @param protocol the primitive protocol + * @param key type + * @param value type + * @return builder for a async atomic tree map + */ + default , V> AtomicSortedMapBuilder atomicSortedMapBuilder(String name, PrimitiveProtocol protocol) { + return primitiveBuilder(name, AtomicSortedMapType.instance(), protocol); + } + /** * Creates a new {@code AtomicNavigableMapBuilder}. * @@ -730,6 +786,16 @@ default TransactionBuilder transactionBuilder() { */ DistributedMap getMap(String name); + /** + * Creates a new DistributedSortedMap. + * + * @param name the primitive name + * @param key type + * @param value type + * @return a new distributed map + */ + , V> DistributedSortedMap getSortedMap(String name); + /** * Creates a new DistributedNavigableMap. * @@ -770,7 +836,17 @@ default TransactionBuilder transactionBuilder() { AtomicDocumentTree getAtomicDocumentTree(String name); /** - * Creates a new {@code AtomicTreeMap}. + * Creates a new {@code AtomicSortedMap}. + * + * @param name the primitive name + * @param key type + * @param value type + * @return a new atomic tree map + */ + , V> AtomicSortedMap getAtomicSortedMap(String name); + + /** + * Creates a new {@code AtomicNavigableMap}. * * @param name the primitive name * @param key type diff --git a/core/src/main/java/io/atomix/core/impl/CorePrimitivesService.java b/core/src/main/java/io/atomix/core/impl/CorePrimitivesService.java index 8f23ea1376..fd7a7329a0 100644 --- a/core/src/main/java/io/atomix/core/impl/CorePrimitivesService.java +++ b/core/src/main/java/io/atomix/core/impl/CorePrimitivesService.java @@ -45,10 +45,14 @@ import io.atomix.core.map.AtomicMapType; import io.atomix.core.map.AtomicNavigableMap; import io.atomix.core.map.AtomicNavigableMapType; +import io.atomix.core.map.AtomicSortedMap; +import io.atomix.core.map.AtomicSortedMapType; import io.atomix.core.map.DistributedMap; import io.atomix.core.map.DistributedMapType; import io.atomix.core.map.DistributedNavigableMap; import io.atomix.core.map.DistributedNavigableMapType; +import io.atomix.core.map.DistributedSortedMap; +import io.atomix.core.map.DistributedSortedMapType; import io.atomix.core.multimap.AtomicMultimap; import io.atomix.core.multimap.AtomicMultimapType; import io.atomix.core.multimap.DistributedMultimap; @@ -161,6 +165,11 @@ public DistributedMap getMap(String name) { return getPrimitive(name, DistributedMapType.instance(), configService.getConfig(name)); } + @Override + public , V> DistributedSortedMap getSortedMap(String name) { + return getPrimitive(name, DistributedSortedMapType.instance(), configService.getConfig(name)); + } + @Override public , V> DistributedNavigableMap getNavigableMap(String name) { return getPrimitive(name, DistributedNavigableMapType.instance(), configService.getConfig(name)); @@ -181,6 +190,11 @@ public AtomicDocumentTree getAtomicDocumentTree(String name) { return getPrimitive(name, AtomicDocumentTreeType.instance(), configService.getConfig(name)); } + @Override + public , V> AtomicSortedMap getAtomicSortedMap(String name) { + return getPrimitive(name, AtomicSortedMapType.instance(), configService.getConfig(name)); + } + @Override public , V> AtomicNavigableMap getAtomicNavigableMap(String name) { return getPrimitive(name, AtomicNavigableMapType.instance(), configService.getConfig(name)); diff --git a/core/src/main/java/io/atomix/core/map/AtomicNavigableMapType.java b/core/src/main/java/io/atomix/core/map/AtomicNavigableMapType.java index 41be98774a..cfbee254b0 100644 --- a/core/src/main/java/io/atomix/core/map/AtomicNavigableMapType.java +++ b/core/src/main/java/io/atomix/core/map/AtomicNavigableMapType.java @@ -30,7 +30,7 @@ */ public class AtomicNavigableMapType, V> implements PrimitiveType, AtomicNavigableMapConfig, AtomicNavigableMap> { - private static final String NAME = "atomic-tree-map"; + private static final String NAME = "atomic-navigable-map"; private static final AtomicNavigableMapType INSTANCE = new AtomicNavigableMapType(); /** diff --git a/core/src/main/java/io/atomix/core/map/AtomicSortedMapBuilder.java b/core/src/main/java/io/atomix/core/map/AtomicSortedMapBuilder.java new file mode 100644 index 0000000000..d07d42187c --- /dev/null +++ b/core/src/main/java/io/atomix/core/map/AtomicSortedMapBuilder.java @@ -0,0 +1,30 @@ +/* + * Copyright 2016-present Open Networking Foundation + * + * Licensed 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 io.atomix.core.map; + +import io.atomix.primitive.PrimitiveBuilder; +import io.atomix.primitive.PrimitiveManagementService; + +/** + * Builder for {@link AtomicSortedMap}. + */ +public abstract class AtomicSortedMapBuilder, V> + extends PrimitiveBuilder, AtomicSortedMapConfig, AtomicSortedMap> { + public AtomicSortedMapBuilder(String name, AtomicSortedMapConfig config, PrimitiveManagementService managementService) { + super(AtomicSortedMapType.instance(), name, config, managementService); + } +} diff --git a/core/src/main/java/io/atomix/core/map/AtomicSortedMapConfig.java b/core/src/main/java/io/atomix/core/map/AtomicSortedMapConfig.java new file mode 100644 index 0000000000..c1868c9428 --- /dev/null +++ b/core/src/main/java/io/atomix/core/map/AtomicSortedMapConfig.java @@ -0,0 +1,29 @@ +/* + * Copyright 2018-present Open Networking Foundation + * + * Licensed 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 io.atomix.core.map; + +import io.atomix.primitive.PrimitiveType; +import io.atomix.primitive.config.PrimitiveConfig; + +/** + * Consistent sorted map configuration. + */ +public class AtomicSortedMapConfig extends PrimitiveConfig { + @Override + public PrimitiveType getType() { + return AtomicSortedMapType.instance(); + } +} diff --git a/core/src/main/java/io/atomix/core/map/AtomicSortedMapType.java b/core/src/main/java/io/atomix/core/map/AtomicSortedMapType.java new file mode 100644 index 0000000000..ecc654802c --- /dev/null +++ b/core/src/main/java/io/atomix/core/map/AtomicSortedMapType.java @@ -0,0 +1,79 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed 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 io.atomix.core.map; + +import io.atomix.core.map.impl.DefaultAtomicNavigableMapService; +import io.atomix.core.map.impl.DefaultAtomicSortedMapBuilder; +import io.atomix.primitive.PrimitiveManagementService; +import io.atomix.primitive.PrimitiveType; +import io.atomix.primitive.service.PrimitiveService; +import io.atomix.primitive.service.ServiceConfig; +import io.atomix.utils.serializer.Namespace; + +import static com.google.common.base.MoreObjects.toStringHelper; + +/** + * Consistent sorted map primitive type. + */ +public class AtomicSortedMapType, V> + implements PrimitiveType, AtomicSortedMapConfig, AtomicSortedMap> { + private static final String NAME = "atomic-sortedf-map"; + private static final AtomicSortedMapType INSTANCE = new AtomicSortedMapType(); + + /** + * Returns a new consistent tree map type. + * + * @param the key type + * @param the value type + * @return a new consistent tree map type + */ + @SuppressWarnings("unchecked") + public static , V> AtomicSortedMapType instance() { + return INSTANCE; + } + + @Override + public String name() { + return NAME; + } + + @Override + public Namespace namespace() { + return AtomicMapType.instance().namespace(); + } + + @Override + public PrimitiveService newService(ServiceConfig config) { + return new DefaultAtomicNavigableMapService<>(); + } + + @Override + public AtomicSortedMapConfig newConfig() { + return new AtomicSortedMapConfig(); + } + + @Override + public AtomicSortedMapBuilder newBuilder(String name, AtomicSortedMapConfig config, PrimitiveManagementService managementService) { + return new DefaultAtomicSortedMapBuilder<>(name, config, managementService); + } + + @Override + public String toString() { + return toStringHelper(this) + .add("name", name()) + .toString(); + } +} \ No newline at end of file diff --git a/core/src/main/java/io/atomix/core/map/DistributedNavigableMapConfig.java b/core/src/main/java/io/atomix/core/map/DistributedNavigableMapConfig.java index ff283f206a..973259ce5a 100644 --- a/core/src/main/java/io/atomix/core/map/DistributedNavigableMapConfig.java +++ b/core/src/main/java/io/atomix/core/map/DistributedNavigableMapConfig.java @@ -26,7 +26,7 @@ public class DistributedNavigableMapConfig extends CachedPrimitiveConfig, V> implements PrimitiveType, DistributedNavigableMapConfig, DistributedNavigableMap> { - private static final String NAME = "treemap"; + private static final String NAME = "navigable-map"; private static final DistributedNavigableMapType INSTANCE = new DistributedNavigableMapType(); diff --git a/core/src/main/java/io/atomix/core/map/DistributedSortedMapBuilder.java b/core/src/main/java/io/atomix/core/map/DistributedSortedMapBuilder.java new file mode 100644 index 0000000000..1f7d41c8a9 --- /dev/null +++ b/core/src/main/java/io/atomix/core/map/DistributedSortedMapBuilder.java @@ -0,0 +1,54 @@ +/* + * Copyright 2015-present Open Networking Foundation + * + * Licensed 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 io.atomix.core.map; + +import io.atomix.core.cache.CachedPrimitiveBuilder; +import io.atomix.primitive.PrimitiveManagementService; + +/** + * Builder for {@link DistributedSortedMap} instances. + * + * @param type for map key + * @param type for map value + */ +public abstract class DistributedSortedMapBuilder, V> + extends CachedPrimitiveBuilder, DistributedSortedMapConfig, DistributedSortedMap> { + + public DistributedSortedMapBuilder(String name, DistributedSortedMapConfig config, PrimitiveManagementService managementService) { + super(DistributedSortedMapType.instance(), name, config, managementService); + } + + /** + * Enables null values in the map. + * + * @return this builder + */ + public DistributedSortedMapBuilder withNullValues() { + config.setNullValues(); + return this; + } + + /** + * Sets whether null values are allowed. + * + * @param nullValues whether null values are allowed + * @return this builder + */ + public DistributedSortedMapBuilder withNullValues(boolean nullValues) { + config.setNullValues(nullValues); + return this; + } +} diff --git a/core/src/main/java/io/atomix/core/map/DistributedSortedMapConfig.java b/core/src/main/java/io/atomix/core/map/DistributedSortedMapConfig.java new file mode 100644 index 0000000000..f7cb276986 --- /dev/null +++ b/core/src/main/java/io/atomix/core/map/DistributedSortedMapConfig.java @@ -0,0 +1,60 @@ +/* + * Copyright 2018-present Open Networking Foundation + * + * Licensed 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 io.atomix.core.map; + +import io.atomix.core.cache.CachedPrimitiveConfig; +import io.atomix.primitive.PrimitiveType; + +/** + * Distributed sorted map configuration. + */ +public class DistributedSortedMapConfig extends CachedPrimitiveConfig { + private boolean nullValues = false; + + @Override + public PrimitiveType getType() { + return DistributedSortedMapType.instance(); + } + + /** + * Enables null values in the map. + * + * @return the map configuration + */ + public DistributedSortedMapConfig setNullValues() { + return setNullValues(true); + } + + /** + * Enables null values in the map. + * + * @param nullValues whether null values are allowed + * @return the map configuration + */ + public DistributedSortedMapConfig setNullValues(boolean nullValues) { + this.nullValues = nullValues; + return this; + } + + /** + * Returns whether null values are supported by the map. + * + * @return {@code true} if null values are supported; {@code false} otherwise + */ + public boolean isNullValues() { + return nullValues; + } +} diff --git a/core/src/main/java/io/atomix/core/map/DistributedSortedMapType.java b/core/src/main/java/io/atomix/core/map/DistributedSortedMapType.java new file mode 100644 index 0000000000..9eaee7a8eb --- /dev/null +++ b/core/src/main/java/io/atomix/core/map/DistributedSortedMapType.java @@ -0,0 +1,79 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed 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 io.atomix.core.map; + +import io.atomix.core.map.impl.DefaultDistributedNavigableMapService; +import io.atomix.core.map.impl.DefaultDistributedSortedMapBuilder; +import io.atomix.primitive.PrimitiveManagementService; +import io.atomix.primitive.PrimitiveType; +import io.atomix.primitive.service.PrimitiveService; +import io.atomix.primitive.service.ServiceConfig; +import io.atomix.utils.serializer.Namespace; + +import static com.google.common.base.MoreObjects.toStringHelper; + +/** + * Distributed sorted map primitive type. + */ +public class DistributedSortedMapType, V> implements PrimitiveType, DistributedSortedMapConfig, DistributedSortedMap> { + private static final String NAME = "sorted-map"; + + private static final DistributedSortedMapType INSTANCE = new DistributedSortedMapType(); + + /** + * Returns a new distributed tree map type. + * + * @param the key type + * @param the value type + * @return a new distributed tree map type + */ + @SuppressWarnings("unchecked") + public static , V> DistributedSortedMapType instance() { + return INSTANCE; + } + + @Override + public String name() { + return NAME; + } + + @Override + public Namespace namespace() { + return AtomicNavigableMapType.instance().namespace(); + } + + @Override + public PrimitiveService newService(ServiceConfig config) { + return new DefaultDistributedNavigableMapService<>(); + } + + @Override + public DistributedSortedMapConfig newConfig() { + return new DistributedSortedMapConfig(); + } + + @Override + public DistributedSortedMapBuilder newBuilder(String name, DistributedSortedMapConfig config, PrimitiveManagementService managementService) { + return new DefaultDistributedSortedMapBuilder<>(name, config, managementService); + } + + @Override + public String toString() { + return toStringHelper(this) + .add("name", name()) + .toString(); + } +} \ No newline at end of file diff --git a/core/src/main/java/io/atomix/core/map/impl/DefaultAtomicSortedMapBuilder.java b/core/src/main/java/io/atomix/core/map/impl/DefaultAtomicSortedMapBuilder.java new file mode 100644 index 0000000000..6305807c24 --- /dev/null +++ b/core/src/main/java/io/atomix/core/map/impl/DefaultAtomicSortedMapBuilder.java @@ -0,0 +1,54 @@ +/* + * Copyright 2016-present Open Networking Foundation + * + * Licensed 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 io.atomix.core.map.impl; + +import io.atomix.core.map.AsyncAtomicSortedMap; +import io.atomix.core.map.AtomicSortedMap; +import io.atomix.core.map.AtomicSortedMapBuilder; +import io.atomix.core.map.AtomicSortedMapConfig; +import io.atomix.primitive.PrimitiveManagementService; +import io.atomix.primitive.protocol.PrimitiveProtocol; +import io.atomix.primitive.service.ServiceConfig; +import io.atomix.utils.serializer.Serializer; + +import java.util.concurrent.CompletableFuture; + +/** + * Default {@link AsyncAtomicSortedMap} builder. + * + * @param type for map value + */ +public class DefaultAtomicSortedMapBuilder, V> extends AtomicSortedMapBuilder { + public DefaultAtomicSortedMapBuilder(String name, AtomicSortedMapConfig config, PrimitiveManagementService managementService) { + super(name, config, managementService); + } + + @Override + @SuppressWarnings("unchecked") + public CompletableFuture> buildAsync() { + PrimitiveProtocol protocol = protocol(); + return newProxy(AtomicTreeMapService.class, new ServiceConfig()) + .thenCompose(proxy -> new AtomicNavigableMapProxy(proxy, managementService.getPrimitiveRegistry()).connect()) + .thenApply(map -> { + Serializer serializer = protocol.serializer(); + return new TranscodingAsyncAtomicSortedMap( + (AsyncAtomicSortedMap) map, + value -> serializer.encode(value), + bytes -> serializer.decode(bytes)) + .sync(); + }); + } +} diff --git a/core/src/main/java/io/atomix/core/map/impl/DefaultDistributedSortedMapBuilder.java b/core/src/main/java/io/atomix/core/map/impl/DefaultDistributedSortedMapBuilder.java new file mode 100644 index 0000000000..4612b9505f --- /dev/null +++ b/core/src/main/java/io/atomix/core/map/impl/DefaultDistributedSortedMapBuilder.java @@ -0,0 +1,66 @@ +/* + * Copyright 2018-present Open Networking Foundation + * + * Licensed 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 io.atomix.core.map.impl; + +import io.atomix.core.map.AsyncDistributedSortedMap; +import io.atomix.core.map.DistributedSortedMap; +import io.atomix.core.map.DistributedSortedMapBuilder; +import io.atomix.core.map.DistributedSortedMapConfig; +import io.atomix.primitive.PrimitiveManagementService; +import io.atomix.primitive.protocol.GossipProtocol; +import io.atomix.primitive.protocol.PrimitiveProtocol; +import io.atomix.primitive.protocol.map.SortedMapProtocolProvider; +import io.atomix.primitive.proxy.ProxyClient; +import io.atomix.primitive.service.ServiceConfig; +import io.atomix.utils.concurrent.Futures; +import io.atomix.utils.serializer.Serializer; + +import java.util.concurrent.CompletableFuture; + +/** + * Default distributed sorted map builder. + */ +public class DefaultDistributedSortedMapBuilder, V> extends DistributedSortedMapBuilder { + public DefaultDistributedSortedMapBuilder(String name, DistributedSortedMapConfig config, PrimitiveManagementService managementService) { + super(name, config, managementService); + } + + @Override + @SuppressWarnings("unchecked") + public CompletableFuture> buildAsync() { + PrimitiveProtocol protocol = protocol(); + if (protocol instanceof GossipProtocol) { + if (protocol instanceof SortedMapProtocolProvider) { + return managementService.getPrimitiveCache().getPrimitive(name, () -> + CompletableFuture.completedFuture(((SortedMapProtocolProvider) protocol).newSortedMapProtocol(name, managementService)) + .thenApply(set -> new GossipDistributedSortedMap<>(name, protocol, set))) + .thenApply(AsyncDistributedSortedMap::sync); + } else { + return Futures.exceptionalFuture(new UnsupportedOperationException("Sets are not supported by the provided gossip protocol")); + } + } else { + return newProxy(AtomicTreeMapService.class, new ServiceConfig()) + .thenCompose(proxy -> new AtomicNavigableMapProxy((ProxyClient) proxy, managementService.getPrimitiveRegistry()).connect()) + .thenApply(map -> { + Serializer serializer = protocol.serializer(); + return new TranscodingAsyncAtomicNavigableMap( + map, + value -> serializer.encode(value), + bytes -> serializer.decode(bytes)); + }).thenApply(atomicMap -> new DelegatingAsyncDistributedSortedMap<>(atomicMap).sync()); + } + } +} diff --git a/core/src/main/java/io/atomix/core/map/impl/GossipDistributedSortedMap.java b/core/src/main/java/io/atomix/core/map/impl/GossipDistributedSortedMap.java new file mode 100644 index 0000000000..c58280117b --- /dev/null +++ b/core/src/main/java/io/atomix/core/map/impl/GossipDistributedSortedMap.java @@ -0,0 +1,72 @@ +/* + * Copyright 2018-present Open Networking Foundation + * + * Licensed 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 io.atomix.core.map.impl; + +import com.google.common.collect.Maps; +import io.atomix.core.map.MapEvent; +import io.atomix.core.map.MapEventListener; +import io.atomix.primitive.protocol.PrimitiveProtocol; +import io.atomix.primitive.protocol.map.MapProtocolEventListener; +import io.atomix.primitive.protocol.map.SortedMapProtocol; + +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; + +/** + * Gossip-based distributed sorted map. + */ +public class GossipDistributedSortedMap, V> extends AsyncDistributedSortedJavaMap { + private final SortedMapProtocol map; + private final Map, MapProtocolEventListener> listenerMap = Maps.newConcurrentMap(); + + public GossipDistributedSortedMap(String name, PrimitiveProtocol protocol, SortedMapProtocol map) { + super(name, protocol, map); + this.map = map; + } + + @Override + public CompletableFuture addListener(MapEventListener listener, Executor executor) { + MapProtocolEventListener eventListener = event -> executor.execute(() -> { + switch (event.type()) { + case INSERT: + listener.event(new MapEvent<>(MapEvent.Type.INSERT, event.key(), event.value(), null)); + break; + case UPDATE: + listener.event(new MapEvent<>(MapEvent.Type.UPDATE, event.key(), event.value(), null)); + break; + case REMOVE: + listener.event(new MapEvent<>(MapEvent.Type.REMOVE, event.key(), null, event.value())); + break; + default: + break; + } + }); + if (listenerMap.putIfAbsent(listener, eventListener) == null) { + return complete(() -> map.addListener(eventListener)); + } + return CompletableFuture.completedFuture(null); + } + + @Override + public CompletableFuture removeListener(MapEventListener listener) { + MapProtocolEventListener eventListener = listenerMap.remove(listener); + if (eventListener != null) { + return complete(() -> map.removeListener(eventListener)); + } + return CompletableFuture.completedFuture(null); + } +} diff --git a/primitive/src/main/java/io/atomix/primitive/protocol/map/NavigableMapProtocol.java b/primitive/src/main/java/io/atomix/primitive/protocol/map/NavigableMapProtocol.java index a6a8c4ef56..eed0018b4f 100644 --- a/primitive/src/main/java/io/atomix/primitive/protocol/map/NavigableMapProtocol.java +++ b/primitive/src/main/java/io/atomix/primitive/protocol/map/NavigableMapProtocol.java @@ -20,5 +20,5 @@ /** * Navigable map protocol. */ -public interface NavigableMapProtocol extends MapProtocol, NavigableMap { +public interface NavigableMapProtocol extends SortedMapProtocol, NavigableMap { } diff --git a/primitive/src/main/java/io/atomix/primitive/protocol/map/SortedMapProtocol.java b/primitive/src/main/java/io/atomix/primitive/protocol/map/SortedMapProtocol.java new file mode 100644 index 0000000000..2f9f469a17 --- /dev/null +++ b/primitive/src/main/java/io/atomix/primitive/protocol/map/SortedMapProtocol.java @@ -0,0 +1,24 @@ +/* + * Copyright 2018-present Open Networking Foundation + * + * Licensed 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 io.atomix.primitive.protocol.map; + +import java.util.SortedMap; + +/** + * Sorted map protocol. + */ +public interface SortedMapProtocol extends MapProtocol, SortedMap { +} diff --git a/primitive/src/main/java/io/atomix/primitive/protocol/map/SortedMapProtocolProvider.java b/primitive/src/main/java/io/atomix/primitive/protocol/map/SortedMapProtocolProvider.java new file mode 100644 index 0000000000..5114e3105b --- /dev/null +++ b/primitive/src/main/java/io/atomix/primitive/protocol/map/SortedMapProtocolProvider.java @@ -0,0 +1,35 @@ +/* + * Copyright 2018-present Open Networking Foundation + * + * Licensed 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 io.atomix.primitive.protocol.map; + +import io.atomix.primitive.PrimitiveManagementService; +import io.atomix.primitive.protocol.GossipProtocol; + +/** + * Sorted map protocol provider. + */ +public interface SortedMapProtocolProvider extends GossipProtocol { + + /** + * Returns a new sorted map protocol. + * + * @param name the map name + * @param managementService the primitive management service + * @return a new map protocol + */ + NavigableMapProtocol newSortedMapProtocol(String name, PrimitiveManagementService managementService); + +}