diff --git a/core/src/main/java/io/atomix/AtomixClient.java b/core/src/main/java/io/atomix/AtomixClient.java index 1f2f0fa04b..738a1ca221 100644 --- a/core/src/main/java/io/atomix/AtomixClient.java +++ b/core/src/main/java/io/atomix/AtomixClient.java @@ -23,9 +23,9 @@ import io.atomix.copycat.client.CopycatClient; import io.atomix.manager.ResourceClient; import io.atomix.manager.ResourceServer; +import io.atomix.manager.options.ClientOptions; import io.atomix.resource.Resource; import io.atomix.resource.ResourceType; -import io.atomix.util.ClientProperties; import java.util.Arrays; import java.util.Collection; @@ -97,8 +97,8 @@ public static Builder builder(String properties) { * @return The replica builder. */ public static Builder builder(Properties properties) { - ClientProperties clientProperties = new ClientProperties(properties); - return builder(clientProperties.replicas()) + ClientOptions clientProperties = new ClientOptions(properties); + return builder(clientProperties.servers()) .withTransport(clientProperties.transport()) .withSerializer(clientProperties.serializer()); } @@ -133,8 +133,8 @@ public static Builder builder(Collection
members) { * Builds the underlying resource client from the given properties. */ private static ResourceClient buildClient(Properties properties) { - ClientProperties clientProperties = new ClientProperties(properties); - return ResourceClient.builder(clientProperties.replicas()) + ClientOptions clientProperties = new ClientOptions(properties); + return ResourceClient.builder(clientProperties.servers()) .withTransport(clientProperties.transport()) .build(); } diff --git a/core/src/main/java/io/atomix/AtomixReplica.java b/core/src/main/java/io/atomix/AtomixReplica.java index b88611bf0a..a55923f56d 100644 --- a/core/src/main/java/io/atomix/AtomixReplica.java +++ b/core/src/main/java/io/atomix/AtomixReplica.java @@ -15,17 +15,40 @@ */ package io.atomix; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import java.util.stream.Collectors; + import io.atomix.catalyst.serializer.Serializer; -import io.atomix.catalyst.transport.*; +import io.atomix.catalyst.transport.Address; +import io.atomix.catalyst.transport.Client; +import io.atomix.catalyst.transport.Connection; +import io.atomix.catalyst.transport.LocalServerRegistry; +import io.atomix.catalyst.transport.LocalTransport; +import io.atomix.catalyst.transport.Server; +import io.atomix.catalyst.transport.Transport; import io.atomix.catalyst.util.Assert; import io.atomix.catalyst.util.ConfigurationException; import io.atomix.catalyst.util.Listener; import io.atomix.catalyst.util.PropertiesReader; import io.atomix.catalyst.util.concurrent.ThreadContext; import io.atomix.concurrent.DistributedLock; +import io.atomix.config.ReplicaOptions; import io.atomix.copycat.Command; import io.atomix.copycat.Query; -import io.atomix.copycat.client.*; +import io.atomix.copycat.client.ConnectionStrategies; +import io.atomix.copycat.client.CopycatClient; +import io.atomix.copycat.client.RecoveryStrategies; +import io.atomix.copycat.client.RetryStrategies; +import io.atomix.copycat.client.ServerSelectionStrategies; +import io.atomix.copycat.client.ServerSelectionStrategy; import io.atomix.copycat.server.CopycatServer; import io.atomix.copycat.server.cluster.Member; import io.atomix.copycat.server.storage.Storage; @@ -39,13 +62,6 @@ import io.atomix.resource.ResourceType; import io.atomix.resource.util.ResourceRegistry; import io.atomix.util.ClusterBalancer; -import io.atomix.util.ReplicaProperties; - -import java.time.Duration; -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.function.Consumer; -import java.util.stream.Collectors; /** * Provides an interface for creating and operating on {@link io.atomix.resource.Resource}s as a stateful node. @@ -203,8 +219,8 @@ public static Builder builder(String properties) { * @return The replica builder. */ public static Builder builder(Properties properties) { - ReplicaProperties replicaProperties = new ReplicaProperties(properties); - Collection
replicas = replicaProperties.replicas(); + ReplicaOptions replicaProperties = new ReplicaOptions(properties); + Collection
replicas = replicaProperties.servers(); return builder(replicaProperties.clientAddress(), replicaProperties.serverAddress(), replicas) .withTransport(replicaProperties.transport()) .withStorage(Storage.builder() diff --git a/core/src/main/java/io/atomix/config/ReplicaOptions.java b/core/src/main/java/io/atomix/config/ReplicaOptions.java new file mode 100644 index 0000000000..c8ec999da4 --- /dev/null +++ b/core/src/main/java/io/atomix/config/ReplicaOptions.java @@ -0,0 +1,62 @@ +/* + * Copyright 2015 the original author or authors. + * + * 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.config; + +import java.util.Properties; + +import io.atomix.Quorum; +import io.atomix.manager.options.ServerOptions; + +/** + * Replica options. + * + * @author - standalone-server leader-election distributed-group distributed-value diff --git a/examples/standalone-server/src/main/java/io/atomix/examples/server/StandaloneServerExample.java b/examples/standalone-server/src/main/java/io/atomix/examples/server/StandaloneServerExample.java deleted file mode 100644 index 6fe1ad703f..0000000000 --- a/examples/standalone-server/src/main/java/io/atomix/examples/server/StandaloneServerExample.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * 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.examples.server; - -import io.atomix.Atomix; -import io.atomix.AtomixReplica; -import io.atomix.catalyst.transport.Address; -import io.atomix.catalyst.transport.NettyTransport; -import io.atomix.copycat.server.storage.Storage; - -import java.util.ArrayList; -import java.util.List; - -/** - * Server example. - * - * @author Jordan Halterman - */ -public class StandaloneServerExample { - - /** - * Starts the server. - */ - public static void main(String[] args) throws Exception { - if (args.length < 2) - throw new IllegalArgumentException("must supply a path and set of host:port tuples"); - - // Parse the address to which to bind the server. - String[] mainParts = args[1].split(":"); - Address address = new Address(mainParts[0], Integer.valueOf(mainParts[1])); - - // Build a list of all member addresses to which to connect. - List
members = new ArrayList<>(); - for (int i = 1; i < args.length; i++) { - String[] parts = args[i].split(":"); - members.add(new Address(parts[0], Integer.valueOf(parts[1]))); - } - - Atomix server = AtomixReplica.builder(address, members) - .withTransport(new NettyTransport()) - .withStorage(new Storage(args[0])) - .build(); - - server.open().join(); - - while (server.isOpen()) { - Thread.sleep(1000); - } - } - -} diff --git a/manager/pom.xml b/manager/pom.xml index 1b01a0fecf..24049ac67f 100644 --- a/manager/pom.xml +++ b/manager/pom.xml @@ -16,5 +16,11 @@ atomix-resource ${project.version} + + io.atomix.catalyst + catalyst-netty + ${catalyst.version} + test + diff --git a/manager/src/main/java/io/atomix/manager/ResourceClient.java b/manager/src/main/java/io/atomix/manager/ResourceClient.java index 60dc476cc2..cef0e832ff 100644 --- a/manager/src/main/java/io/atomix/manager/ResourceClient.java +++ b/manager/src/main/java/io/atomix/manager/ResourceClient.java @@ -15,14 +15,30 @@ */ package io.atomix.manager; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + import io.atomix.catalyst.serializer.Serializer; import io.atomix.catalyst.transport.Address; import io.atomix.catalyst.transport.Transport; import io.atomix.catalyst.util.Assert; import io.atomix.catalyst.util.ConfigurationException; +import io.atomix.catalyst.util.PropertiesReader; import io.atomix.catalyst.util.concurrent.Futures; import io.atomix.catalyst.util.concurrent.ThreadContext; -import io.atomix.copycat.client.*; +import io.atomix.copycat.client.ConnectionStrategies; +import io.atomix.copycat.client.CopycatClient; +import io.atomix.copycat.client.RecoveryStrategies; +import io.atomix.copycat.client.RetryStrategies; +import io.atomix.copycat.client.ServerSelectionStrategies; +import io.atomix.manager.options.ClientOptions; import io.atomix.manager.state.GetResourceKeys; import io.atomix.manager.state.ResourceExists; import io.atomix.manager.state.ResourceManagerException; @@ -33,11 +49,6 @@ import io.atomix.resource.util.ResourceInstance; import io.atomix.resource.util.ResourceRegistry; -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - /** * Provides an interface for creating and operating on {@link io.atomix.resource.Resource}s remotely. *

@@ -87,6 +98,29 @@ */ public class ResourceClient implements ResourceManager { + /** + * Returns a new ResourceClient builder from the given configuration file. + * + * @param properties The properties file from which to load the replica builder. + * @return The replica builder. + */ + public static Builder builder(String properties) { + return builder(PropertiesReader.load(properties).properties()); + } + + /** + * Returns a new ResourceClient builder from the given properties. + * + * @param properties The properties from which to load the replica builder. + * @return The replica builder. + */ + public static Builder builder(Properties properties) { + ClientOptions clientProperties = new ClientOptions(properties); + return builder(clientProperties.servers()) + .withTransport(clientProperties.transport()) + .withSerializer(clientProperties.serializer()); + } + /** * Returns a new Atomix client builder. *

diff --git a/manager/src/main/java/io/atomix/manager/ResourceServer.java b/manager/src/main/java/io/atomix/manager/ResourceServer.java index ded0388fa3..a869fd096a 100644 --- a/manager/src/main/java/io/atomix/manager/ResourceServer.java +++ b/manager/src/main/java/io/atomix/manager/ResourceServer.java @@ -15,14 +15,23 @@ */ package io.atomix.manager; +import java.time.Duration; +import java.util.Arrays; +import java.util.Collection; +import java.util.Properties; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; + import io.atomix.catalyst.serializer.Serializer; import io.atomix.catalyst.transport.Address; import io.atomix.catalyst.transport.Transport; import io.atomix.catalyst.util.Assert; import io.atomix.catalyst.util.ConfigurationException; +import io.atomix.catalyst.util.PropertiesReader; import io.atomix.catalyst.util.concurrent.ThreadContext; import io.atomix.copycat.server.CopycatServer; import io.atomix.copycat.server.storage.Storage; +import io.atomix.manager.options.ServerOptions; import io.atomix.manager.state.ResourceManagerException; import io.atomix.manager.state.ResourceManagerState; import io.atomix.manager.util.ResourceManagerTypeResolver; @@ -30,12 +39,6 @@ import io.atomix.resource.ResourceType; import io.atomix.resource.util.ResourceRegistry; -import java.time.Duration; -import java.util.Arrays; -import java.util.Collection; -import java.util.concurrent.CompletableFuture; -import java.util.stream.Collectors; - /** * Standalone Atomix server. *

@@ -79,6 +82,45 @@ */ public final class ResourceServer { + /** + * Returns a new ResourceServer builder from the given configuration file. + * + * @param properties The properties file from which to load the replica builder. + * @return The replica builder. + */ + public static Builder builder(String properties) { + return builder(PropertiesReader.load(properties).properties()); + } + + /** + * Returns a new ResourceServer builder from the given properties. + * + * @param properties The properties from which to load the replica builder. + * @return The replica builder. + */ + public static Builder builder(Properties properties) { + ServerOptions serverProperties = new ServerOptions(properties); + Collection

servers = serverProperties.servers(); + return builder(serverProperties.clientAddress(), serverProperties.serverAddress(), servers) + .withTransport(serverProperties.transport()) + .withStorage(Storage.builder() + .withStorageLevel(serverProperties.storageLevel()) + .withDirectory(serverProperties.storageDirectory()) + .withMaxSegmentSize(serverProperties.maxSegmentSize()) + .withMaxEntriesPerSegment(serverProperties.maxEntriesPerSegment()) + .withMaxSnapshotSize(serverProperties.maxSnapshotSize()) + .withRetainStaleSnapshots(serverProperties.retainStaleSnapshots()) + .withCompactionThreads(serverProperties.compactionThreads()) + .withMinorCompactionInterval(serverProperties.minorCompactionInterval()) + .withMajorCompactionInterval(serverProperties.majorCompactionInterval()) + .withCompactionThreshold(serverProperties.compactionThreshold()) + .build()) + .withSerializer(serverProperties.serializer()) + .withElectionTimeout(serverProperties.electionTimeout()) + .withHeartbeatInterval(serverProperties.heartbeatInterval()) + .withSessionTimeout(serverProperties.sessionTimeout()); + } + /** * Returns a new Atomix server builder. *

@@ -465,4 +507,4 @@ public ResourceServer build() { } } -} +} \ No newline at end of file diff --git a/core/src/main/java/io/atomix/util/AtomixProperties.java b/manager/src/main/java/io/atomix/manager/options/AtomixOptions.java similarity index 59% rename from core/src/main/java/io/atomix/util/AtomixProperties.java rename to manager/src/main/java/io/atomix/manager/options/AtomixOptions.java index 9e0c99acfe..2b7f12a7f4 100644 --- a/core/src/main/java/io/atomix/util/AtomixProperties.java +++ b/manager/src/main/java/io/atomix/manager/options/AtomixOptions.java @@ -13,58 +13,38 @@ * See the License for the specific language governing permissions and * limitations under the License */ -package io.atomix.util; +package io.atomix.manager.options; + +import java.util.Collection; +import java.util.Properties; import io.atomix.catalyst.serializer.Serializer; import io.atomix.catalyst.transport.Address; -import io.atomix.catalyst.util.ConfigurationException; import io.atomix.catalyst.util.PropertiesReader; import io.atomix.catalyst.util.QualifiedProperties; -import java.util.Collection; -import java.util.Properties; - /** - * Base class for Atomix properties. + * Atomix options. * * @author replicas() { - return reader.getCollection(SEED, p -> parseAddress(reader.getString(p))); - } - - /** - * Parses an address string. - * - * @param address The address string. - * @return The address. - */ - protected Address parseAddress(String address) { - String[] split = address.split(":"); - if (split.length != 2) { - throw new ConfigurationException("malformed address: " + address); - } - - try { - return new Address(split[0], Integer.valueOf(split[1])); - } catch (NumberFormatException e) { - throw new ConfigurationException("invalid port number: " + split[1]); - } + public Collection

servers() { + return reader.getCollection(SEED, p -> new Address(reader.getString(p))); } /** diff --git a/core/src/main/java/io/atomix/util/ClientProperties.java b/manager/src/main/java/io/atomix/manager/options/ClientOptions.java similarity index 91% rename from core/src/main/java/io/atomix/util/ClientProperties.java rename to manager/src/main/java/io/atomix/manager/options/ClientOptions.java index 5fa5e2156a..919ac41eba 100644 --- a/core/src/main/java/io/atomix/util/ClientProperties.java +++ b/manager/src/main/java/io/atomix/manager/options/ClientOptions.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License */ -package io.atomix.util; +package io.atomix.manager.options; import io.atomix.catalyst.transport.Transport; import io.atomix.catalyst.util.ConfigurationException; @@ -23,16 +23,16 @@ import java.util.Properties; /** - * Atomix client properties. + * Client options. * * @author concurrent variables core + standalone examples testing all @@ -150,7 +151,7 @@ Atomix API Reference (${jv}) Atomix API Reference (${jv}) true - io.atomix.examples*:*.state*:*.util*:io.atomix.testing* + io.atomix.examples*:*.state*:*.util*:io.atomix.testing*:*.config -Xdoclint:none -notimestamp diff --git a/standalone/.gitignore b/standalone/.gitignore new file mode 100644 index 0000000000..176aab5aa2 --- /dev/null +++ b/standalone/.gitignore @@ -0,0 +1,2 @@ +*.log +/target diff --git a/standalone/pom.xml b/standalone/pom.xml new file mode 100644 index 0000000000..032ae0133e --- /dev/null +++ b/standalone/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + + + io.atomix + atomix-parent + 1.0.0-SNAPSHOT + + + atomix-standalone-parent + pom + Atomix Standalone Parent Pom + Standalone Atomix Processes. + http://github.com/atomix/atomix + 2013 + + + 1.1.2 + + + + standalone-server + + + + + ch.qos.logback + logback-classic + ${logback.version} + + + diff --git a/standalone/standalone-server/conf/example.properties b/standalone/standalone-server/conf/example.properties new file mode 100644 index 0000000000..b48df391d1 --- /dev/null +++ b/standalone/standalone-server/conf/example.properties @@ -0,0 +1,115 @@ +# +# Copyright 2015 the original author or authors. +# +# 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 +# + +# This is the address to which to bind the local server. This address may or may +# not be present in the cluster.seed list below. If the address is present in the +# seed list, this node will start as a full member of the cluster. If the address is +# not present in the seed list, this node will join the cluster defined by the seeds. +server.address=localhost:5000 + +# This is the transport to use to communicate between replicas. The transport must +# be the same class on all replicas. +server.transport=io.atomix.catalyst.transport.NettyTransport + +# These are standard TCP configuration options. +server.transport.connectTimeout=5000 +server.transport.sendBufferSize=-1 +server.transport.receiveBufferSize=-1 +server.transport.reuseAddress=true +server.transport.tcpKeepAlive=true +server.transport.tcpNoDelay=false +server.transport.acceptBacklog=1024 + +# This property indicates whether SSL should be enabled for the transport. +server.transport.ssl.enabled=false + +# This is a list of members of the cluster to which to connect. If the local member +# is joining a cluster, its address will not be present in the seed list. If the +# local member is forming a new cluster, its address will be present in the seed +# list. The first time the cluster is started, n seed nodes should be started where +# n is the size of the Raft quorum. +cluster.seed.1=localhost:5000 +cluster.seed.2=localhost:5001 +cluster.seed.3=localhost:5002 + +# This property indicates the desired size of the quorum. The quorum consists +# of some set of nodes that participate in the Raft consensus algorithm. Writes to +# the cluster are synchronously replicated to a majority of the members in the quorum. +# Atomix guarantees that at least cluster.quorumHint replicas will be in the quorum +# so long as cluster.quorumHint members have joined the cluster. +# The default value of -1 indicates that the cluster.seed list represents the desired +# quorum size. This is typically a good default since clusters are normally started with +# the desired number of nodes as seed nodes. +cluster.quorumHint=-1 + +# This property indicates the desired number of backup replicas for each active member +# of the quorum. When a quorum member is partitioned or crashes, Atomix will attempt to +# replace that member with a backup replica. The process of replacing nodes can be shortened +# by replicating to more backup nodes. Members of the quorum replicate to backup nodes +# asynchronously, so the number of backups does not significantly impact latency. +cluster.backupCount=0 + +# These properties are Raft-specific configurations that define the intervals at which +# Raft servers and clients communicate with one another. The electionTimeout and heartbeatInterval +# control the frequency of communication between servers. The sessionTimeout controls the +# frequency of keep-alive requests from clients. Note that decreasing the sessionTimeout can +# result in e.g. a lock held by a crashed node being released sooner, but decreasing the sessionTimeout +# also implies more overhead for frequent keep-aive requests. +cluster.electionTimeout=1000 +cluster.heartbeatInterval=500 +cluster.sessionTimeout=10000 + +# These properties dictate how Raft logs are stored for this replica. By default, Atomix stores +# logs on disk. Alternatively, the MAPPED and MEMORY storage.level can be used for greater efficiency +# at the potential expense of more memory consumption and loss of safety. In order for writes to be +# lost in a cluster of replicas using storage.level=MEMORY, a majority of the cluster would have +# to crash and lose their logs from memory. +storage.level=DISK +storage.directory=logs +storage.maxSegmentSize=33554432 +storage.maxEntriesPerSegment=1048576 + +# These properties dictate the behavior of log compaction in Atomix. Log compaction includes a +# combination of incremental rewrites of the log and storage of snapshots of the system's state. +# Snapshots inherit the storage.level, so snapshots stored with storage.level=MEMORY will not +# be stored on disk but can be replicated to other servers. +storage.compaction.maxSnapshotSize=33554432 +storage.compaction.retainSnapshots=false +storage.compaction.threads=2 +storage.compaction.minor=60000 +storage.compaction.major=600000 +storage.compaction.threshold=0.5 + +# These properties dictate the behavior of the serializer. Serializable types can be registered +# along with serializable type IDs for more efficient serialization. + +# This property indicates whether serializable types must be whitelisted. If types must be whitelisted +# for serialization, serializable types must be registered in the serializer.types.* properties. +# If whitelisting is disabled, unregistered types may be serialized with their class name. +serializer.whitelist=false +serializer.allocator=io.atomix.catalyst.buffer.PooledHeapAllocator + +# This is an example of a serializable type and custom serializer. +#serializer.types.1=com.mycompany.FooClass +#serializer.serializers.1=com.mycompany.FooClassSerializer + +# This is an example of a serializable abstract type and a custom abstract type serializer. +#serializer.types.2=com.mycompany.AbstractFooClass +#serializer.abstractSerializers.2=com.mycompany.AbstractFooClassSerializer + +# This is an example of a serialization framework interface and the default framework serializer. +#serializer.types.3=com.mycompany.MyCompanySerializable +#serializer.defaultSerializers.3=com.mycompany.MyCompanySerializableSerializer diff --git a/examples/standalone-server/pom.xml b/standalone/standalone-server/pom.xml similarity index 74% rename from examples/standalone-server/pom.xml rename to standalone/standalone-server/pom.xml index a7cfaa3474..52af3dbbb8 100644 --- a/examples/standalone-server/pom.xml +++ b/standalone/standalone-server/pom.xml @@ -4,24 +4,35 @@ 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. --> - + 4.0.0 io.atomix - atomix-examples-parent + atomix-standalone-parent 1.0.0-SNAPSHOT - atomix-standalone-server-example - Atomix Resources Example + atomix-standalone-server + Atomix Standalone Server io.atomix - atomix-all + atomix-resource-manager ${project.version} + + io.atomix.catalyst + catalyst-netty + ${catalyst.version} + + + net.sourceforge.argparse4j + argparse4j + 0.7.0 + @@ -32,6 +43,7 @@ 1.6 true + true atomix-standalone-server @@ -56,7 +68,7 @@ - io.atomix.examples.server.StandaloneServerExample + io.atomix.standalone.server.StandaloneServer diff --git a/standalone/standalone-server/src/main/java/io/atomix/standalone/server/StandaloneServer.java b/standalone/standalone-server/src/main/java/io/atomix/standalone/server/StandaloneServer.java new file mode 100644 index 0000000000..0468ae8c56 --- /dev/null +++ b/standalone/standalone-server/src/main/java/io/atomix/standalone/server/StandaloneServer.java @@ -0,0 +1,80 @@ +/* + * Copyright 2016 the original author or authors. + * + * 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.standalone.server; + +import java.util.List; +import java.util.Properties; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import io.atomix.catalyst.transport.Address; +import io.atomix.catalyst.util.PropertiesReader; +import io.atomix.manager.ResourceServer; +import net.sourceforge.argparse4j.ArgumentParsers; +import net.sourceforge.argparse4j.inf.ArgumentParser; +import net.sourceforge.argparse4j.inf.ArgumentParserException; +import net.sourceforge.argparse4j.inf.Namespace; + +/** + * Standalone Server. + * + * @author Jonathan Halterman + */ +public class StandaloneServer { + public static void main(String[] args) throws Exception { + ArgumentParser parser = ArgumentParsers.newArgumentParser("AtomixServer") + .defaultHelp(true) + .description("Atomix server"); + parser.addArgument("-config").help("Atomix configuration file"); + parser.addArgument("-server").help("Server address in host:port format"); + parser.addArgument("-seed").help("Comma-separated list of seed node addresses in host:port format"); + + Namespace ns = null; + try { + ns = parser.parseArgs(args); + } catch (ArgumentParserException e) { + parser.handleError(e); + System.exit(1); + } + + ResourceServer.Builder builder = null; + String config = ns.getString("config"); + + if (config != null) { + Properties properties = PropertiesReader.load(config).properties(); + builder = ResourceServer.builder(properties); + } else { + String server = ns.getString("server"); + String seed = ns.getString("seed"); + if (server == null || seed == null) { + System.err.println("Must supply -config or -server and -seed"); + System.exit(1); + } + + List
seeds = Stream.of(seed.split(",")).map(a -> new Address(a)).collect(Collectors.toList()); + builder = ResourceServer.builder(new Address(server), seeds); + } + + ResourceServer server = builder.build(); + server.start().join(); + + while (server.isRunning()) { + synchronized (StandaloneServer.class) { + StandaloneServer.class.wait(); + } + } + } +} diff --git a/examples/standalone-server/src/main/resources/logback.xml b/standalone/standalone-server/src/main/resources/logback.xml similarity index 100% rename from examples/standalone-server/src/main/resources/logback.xml rename to standalone/standalone-server/src/main/resources/logback.xml