http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/0a1b1b7a/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientCompute.java ---------------------------------------------------------------------- diff --cc modules/core/src/main/java/org/apache/ignite/internal/client/GridClientCompute.java index 5dc8a9f,0000000..e26c004 mode 100644,000000..100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientCompute.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientCompute.java @@@ -1,419 -1,0 +1,476 @@@ +/* + * 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.internal.client; + +import org.apache.ignite.internal.client.balancer.*; +import org.jetbrains.annotations.*; + +import java.util.*; + +/** + * A compute projection of grid client. Contains various methods for task execution, full and partial (per node) + * topology refresh, and log viewing. An initial instance of compute projection over the whole remote grid is + * provided via {@link GridClient#compute()} method. Further sub-projections may be created via + * any of the {@code projection(...)} methods on this API. + * <p> + * You can create custom client projections based on any user-defined filtering. For example you can create + * a projection over a certain group of nodes, or over all nodes that have a certain attribute. Once projection + * is created, only nodes that belong to this projection will be contacted on remote grid for any operation. + * This essentially allows users to create virtual subgrids for remote task execution. + * <p> + * Use any of the {@code execute(...)} methods to execute tasks on remote grid. Note that tasks need + * to be deployed to remote grid first prior to execution. You can also use any of the + * {@code affinityExecute(...)} methods to execute tasks on node that have affinity with some data key. + * This way you can collocate your computation with the data cached on remote nodes. + * <p> + * You can also use any of the {@code refreshNode(...)} or {@code refreshTopology(...)} methods + * to eagerly refresh metrics or attributes on remote nodes (note that attributes are static, + * so it is sufficient to fetch and cache them only once). Metrics and attributes will be + * cached in {@link GridClientNode} instances automatically if {@link GridClientConfiguration#isEnableMetricsCache()} + * or {@link GridClientConfiguration#isEnableAttributesCache()} property is set to {@code true}. + * <p> + * Compute client also allows fetching contents of remote log files (including backwards mode) via any of + * the provided {@code log(...)} methods. + * <h1 class="header">Affinity Awareness</h1> - * One of the unique properties of the GridGain remote clients is that they are ++ * One of the unique properties of the Ignite remote clients is that they are + * affinity aware. In other words, both compute and data APIs will optionally + * contact exactly the node where the data is cached based on some affinity key. + * This allows for collocation of computations and data and avoids extra network + * hops that would be necessary if non-affinity nodes were contacted. Use + * {@link #affinityExecute(String, String, Object, Object)} and + * {@link #affinityExecuteAsync(String, String, Object, Object)} to synchronously + * or asynchronously execute remote tasks on affinity nodes based on provided + * affinity keys. + */ +public interface GridClientCompute { + /** + * Creates a projection that will communicate only with specified remote node. + * <p> + * If current projection is dynamic projection, then this method will check is passed node is in topology. + * If any filters were specified in current topology, this method will check if passed node is accepted by + * the filter. If current projection was restricted to any subset of nodes, this method will check if + * passed node is in that subset. If any of the checks fails an exception will be thrown. + * + * @param node Single node to which this projection will be restricted. + * @return Resulting static projection that is bound to a given node. + * @throws GridClientException If resulting projection is empty. + */ + public GridClientCompute projection(GridClientNode node) throws GridClientException; + + /** + * Creates a projection that will communicate only with nodes that are accepted by the passed filter. + * <p> + * If current projection is dynamic projection, then filter will be applied to the most relevant + * topology snapshot every time a node to communicate is selected. If current projection is a static projection, + * then resulting projection will only be restricted to nodes that were in parent projection and were + * accepted by the passed filter. If any of the checks fails an exception will be thrown. + * + * @param filter Filter that will select nodes for projection. If {@code null}, + * then no filter would be applied to nodes in projection. + * @return Resulting projection (static or dynamic, depending in parent projection type). + * @throws GridClientException If resulting projection is empty. + */ + public GridClientCompute projection(GridClientPredicate<? super GridClientNode> filter) throws GridClientException; + + /** + * Creates a projection that will communicate only with specified remote nodes. For any particular call + * a node to communicate will be selected with balancer of this projection. + * <p> + * If current projection is dynamic projection, then this method will check is passed nodes are in topology. + * If any filters were specified in current topology, this method will check if passed nodes are accepted by + * the filter. If current projection was restricted to any subset of nodes, this method will check if + * passed nodes are in that subset (i.e. calculate the intersection of two collections). + * If any of the checks fails an exception will be thrown. + * + * @param nodes Collection of nodes to which this projection will be restricted. If {@code null}, + * created projection is dynamic and will take nodes from topology. + * @return Resulting static projection that is bound to a given nodes. + * @throws GridClientException If resulting projection is empty. + */ + public GridClientCompute projection(Collection<GridClientNode> nodes) throws GridClientException; + + /** + * Creates a projection that will communicate only with nodes that are accepted by the passed filter. The + * balancer passed will override default balancer specified in configuration. + * <p> + * If current projection is dynamic projection, then filter will be applied to the most relevant + * topology snapshot every time a node to communicate is selected. If current projection is a static projection, + * then resulting projection will only be restricted to nodes that were in parent projection and were + * accepted by the passed filter. If any of the checks fails an exception will be thrown. + * + * @param filter Filter that will select nodes for projection. If {@code null}, + * then no filter would be applied to nodes in projection. + * @param balancer Balancer that will select balanced node in resulting projection. If {@code null}, + * then balancer which was specified while projection construction will be used. + * @return Resulting projection (static or dynamic, depending in parent projection type). + * @throws GridClientException If resulting projection is empty. + */ + public GridClientCompute projection(GridClientPredicate<? super GridClientNode> filter, + GridClientLoadBalancer balancer) throws GridClientException; + + /** + * Creates a projection that will communicate only with specified remote nodes. For any particular call + * a node to communicate will be selected with passed balancer.. + * <p> + * If current projection is dynamic projection, then this method will check is passed nodes are in topology. + * If any filters were specified in current topology, this method will check if passed nodes are accepted by + * the filter. If current projection was restricted to any subset of nodes, this method will check if + * passed nodes are in that subset (i.e. calculate the intersection of two collections). + * If any of the checks fails an exception will be thrown. + * + * @param nodes Collection of nodes to which this projection will be restricted. If {@code null}, + * then no filter would be applied to nodes in projection. + * @param balancer Balancer that will select nodes in resulting projection. If {@code null}, + * then balancer which was specified while projection construction will be used. + * @return Resulting static projection that is bound to a given nodes. + * @throws GridClientException If resulting projection is empty. + */ + public GridClientCompute projection(Collection<GridClientNode> nodes, GridClientLoadBalancer balancer) + throws GridClientException; + + /** + * Gets load balancer used by this projection. By default, the balancer specified + * in {@link GridClientConfiguration#getBalancer()} property is used. User can + * provide custom balancers for different projections via + * {@link #projection(GridClientPredicate, GridClientLoadBalancer)} method. + * + * @return Instance of {@link GridClientLoadBalancer} used by this projection. + */ + public GridClientLoadBalancer balancer(); + + /** + * Executes task on remote grid. Only nodes included into this projection will + * be contacted. Note that task must be deployed on remote grid prior to the + * execution. + * + * @param taskName Task name or task class name. + * @param taskArg Optional task argument. + * @return Task execution result. + * @throws GridClientException In case of error. + * @throws GridServerUnreachableException If none of the servers can be reached. + * @throws GridClientClosedException If client was closed manually. + */ + public <R> R execute(String taskName, Object taskArg) throws GridClientException; + + /** + * Asynchronously executes task on remote grid. Only nodes included into this projection will + * be contacted. Note that task must be deployed on remote grid prior to the + * execution. + * + * @param taskName Task name or task class name. + * @param taskArg Optional task argument. + * @return Future for remote execution. + */ + public <R> GridClientFuture<R> executeAsync(String taskName, Object taskArg); + + /** + * Executes task using cache affinity key for routing. This way the task will start executing + * exactly on the node where this affinity key is cached hence allowing for + * collocation of computations and data. + * + * @param taskName Task name or task class name. + * @param cacheName Name of the cache on which affinity should be calculated. If {@code null}, + * then default cache will be used. + * @param affKey Affinity key. + * @param taskArg Optional task argument. + * @return Task execution result. + * @throws GridClientException In case of error. + * @throws GridServerUnreachableException If none of the servers can be reached. + * @throws GridClientClosedException If client was closed manually. + */ + public <R> R affinityExecute(String taskName, String cacheName, Object affKey, Object taskArg) + throws GridClientException; + + /** + * Asynchronously executes task using cache affinity key for routing. This way + * the task will start executing exactly on the node where this affinity key is cached + * hence allowing for collocation of computations and data. + * + * @param taskName Task name or task class name. + * @param cacheName Name of the cache on which affinity should be calculated. If {@code null}, + * then balancer which was specified while projection construction will be used. + * @param affKey Affinity key. + * @param taskArg Optional task argument. + * @return Future for the remote execution. + */ + public <R> GridClientFuture<R> affinityExecuteAsync(String taskName, String cacheName, Object affKey, + Object taskArg); + + /** + * Gets most recently refreshed topology (only non-daemon nodes included). + * If this compute instance is a projection, then only nodes that + * satisfy projection criteria will be returned. + * + * @return Most recently refreshed topology. + * @throws GridClientException If client doesn't have an actual topology version. + */ + public Collection<GridClientNode> nodes() throws GridClientException; + + /** + * Gets cached node with given id from most recently refreshed topology. + * + * @param id Node ID. + * @return Node for given ID or {@code null} if node with given id was not found. + * @throws GridClientException If client doesn't have an actual topology version. + */ + public GridClientNode node(UUID id) throws GridClientException; + + /** + * Gets cached nodes for the given IDs based on most recently refreshed topology. + * If this compute instance is a projection, then only nodes that passes projection + * criteria will be returned. + * + * @param ids Node IDs. + * @return Collection of nodes for provided IDs. + * @throws GridClientException If client doesn't have an actual topology version. + */ + public Collection<GridClientNode> nodes(Collection<UUID> ids) throws GridClientException; + + /** + * Gets all cached nodes that pass the filter. If this compute instance is a projection, then only + * nodes that passes projection criteria will be passed to the filter. + * + * @param filter Node filter. + * @return Collection of nodes that satisfy provided filter. + * @throws GridClientException If client doesn't have an actual topology version. + */ + public Collection<GridClientNode> nodes(GridClientPredicate<GridClientNode> filter) + throws GridClientException; + + /** + * Gets most recently refreshed set of daemon nodes. If this compute instance is a projection, + * then only nodes that satisfy projection criteria will be returned. + * + * @return Daemon nodes in most recently refreshed topology. + * @throws GridClientException If client doesn't have an actual topology version. + */ + public Collection<GridClientNode> daemonNodes() throws GridClientException; + + /** + * Refreshes and returns node by its ID from remote grid. Use {@code includeAttrs} and + * {@code includeMetrics} parameters to automatically fetch remote node attributes and + * metrics. + * <p> + * Note that fetched attributes and metrics may or may note be cached in {@link GridClientNode} + * based on {@link GridClientConfiguration#isEnableMetricsCache()} and + * {@link GridClientConfiguration#isEnableAttributesCache()} parameters. Even though topology + * is refreshed automatically every {@link GridClientConfiguration#getTopologyRefreshFrequency()} + * interval, node metrics and attributes will be fetched in background only if + * {@link GridClientConfiguration#isAutoFetchMetrics()} or + * {@link GridClientConfiguration#isAutoFetchAttributes()} set to true. + * <p> + * Also note that node attributes are static and, if cached, there is no need + * to refresh them again. + * + * @param id Node ID. + * @param includeAttrs Whether to include node attributes. + * @param includeMetrics Whether to include node metrics. + * @return Node descriptor or {@code null} if node doesn't exist. + * @throws GridClientException In case request failed. + * @throws GridServerUnreachableException If none of the servers can be reached. + * @throws GridClientClosedException If client was closed manually. + */ + public GridClientNode refreshNode(UUID id, boolean includeAttrs, boolean includeMetrics) throws GridClientException; + + /** + * Asynchronously refreshes and returns node by its ID from remote grid. Use {@code includeAttrs} and + * {@code includeMetrics} parameters to automatically fetch remote node attributes and + * metrics. + * <p> + * Note that fetched attributes and metrics may or may note be cached in {@link GridClientNode} + * based on {@link GridClientConfiguration#isEnableMetricsCache()} and + * {@link GridClientConfiguration#isEnableAttributesCache()} parameters. Even though topology + * is refreshed automatically every {@link GridClientConfiguration#getTopologyRefreshFrequency()} + * interval, node metrics and attributes will be fetched in background only if + * {@link GridClientConfiguration#isAutoFetchMetrics()} or + * {@link GridClientConfiguration#isAutoFetchAttributes()} set to true. + * <p> + * Also note that node attributes are static and, if cached, there is no need + * to refresh them again. + * + * @param id Node ID. + * @param includeAttrs Whether to include node attributes. + * @param includeMetrics Whether to include node metrics. + * @return Future for the refresh + */ + public GridClientFuture<GridClientNode> refreshNodeAsync(UUID id, boolean includeAttrs, boolean includeMetrics); + + /** + * Refreshes and returns node by its IP address from remote grid. All possible IP addresses + * of a node will be checked. If there is more than one node for given IP address, then + * first found node will be refreshed. Use {@code includeAttrs} and + * {@code includeMetrics} parameters to automatically fetch remote node attributes and + * metrics. + * <p> + * Note that fetched attributes and metrics may or may note be cached in {@link GridClientNode} + * based on {@link GridClientConfiguration#isEnableMetricsCache()} and + * {@link GridClientConfiguration#isEnableAttributesCache()} parameters. Even though topology + * is refreshed automatically every {@link GridClientConfiguration#getTopologyRefreshFrequency()} + * interval, node metrics and attributes will be fetched in background only if + * {@link GridClientConfiguration#isAutoFetchMetrics()} or + * {@link GridClientConfiguration#isAutoFetchAttributes()} set to true. + * <p> + * Also note that node attributes are static and, if cached, there is no need + * to refresh them again. + * + * @param ip IP address. + * @param includeAttrs Whether to include node attributes. + * @param includeMetrics Whether to include node metrics. + * @return Node descriptor or {@code null} if node doesn't exist. + * @throws GridClientException In case of error. + * @throws GridServerUnreachableException If none of the servers can be reached. + * @throws GridClientClosedException If client was closed manually. + */ + @Nullable public GridClientNode refreshNode(String ip, boolean includeAttrs, boolean includeMetrics) + throws GridClientException; + + /** + * Asynchronously refreshes and returns node by its IP address from remote grid. All possible IP addresses + * of a node will be checked. If there is more than one node for given IP address, then + * first found node will be refreshed. Use {@code includeAttrs} and + * {@code includeMetrics} parameters to automatically fetch remote node attributes and + * metrics. + * <p> + * Note that fetched attributes and metrics may or may note be cached in {@link GridClientNode} + * based on {@link GridClientConfiguration#isEnableMetricsCache()} and + * {@link GridClientConfiguration#isEnableAttributesCache()} parameters. Even though topology + * is refreshed automatically every {@link GridClientConfiguration#getTopologyRefreshFrequency()} + * interval, node metrics and attributes will be fetched in background only if + * {@link GridClientConfiguration#isAutoFetchMetrics()} or + * {@link GridClientConfiguration#isAutoFetchAttributes()} set to true. + * <p> + * Also note that node attributes are static and, if cached, there is no need + * to refresh them again. + * + * @param ip IP address. + * @param includeAttrs Whether to include node attributes. + * @param includeMetrics Whether to include node metrics. + * @return Future for the refresh operation. + */ + public GridClientFuture<GridClientNode> refreshNodeAsync(String ip, boolean includeAttrs, boolean includeMetrics); + + /** + * Refreshes and returns all nodes within topology. Use {@code includeAttrs} and + * {@code includeMetrics} parameters to automatically fetch remote node attributes and + * metrics. + * <p> + * Note that fetched attributes and metrics may or may note be cached in {@link GridClientNode} + * based on {@link GridClientConfiguration#isEnableMetricsCache()} and + * {@link GridClientConfiguration#isEnableAttributesCache()} parameters. Even though topology + * is refreshed automatically every {@link GridClientConfiguration#getTopologyRefreshFrequency()} + * interval, node metrics and attributes will be fetched in background only if + * {@link GridClientConfiguration#isAutoFetchMetrics()} or + * {@link GridClientConfiguration#isAutoFetchAttributes()} set to {@code true}. + * <p> + * Also note that node attributes are static and, if cached, there is no need + * to refresh them again. + * + * @param includeAttrs Whether to include node attributes. + * @param includeMetrics Whether to include node metrics. + * @return Node descriptors. + * @throws GridClientException In case of error. + * @throws GridServerUnreachableException If none of the servers can be reached. + * @throws GridClientClosedException If client was closed manually. + */ + public List<GridClientNode> refreshTopology(boolean includeAttrs, boolean includeMetrics) + throws GridClientException; + + /** + * Asynchronously refreshes and returns all nodes within topology. Use {@code includeAttrs} and + * {@code includeMetrics} parameters to automatically fetch remote node attributes and + * metrics. + * <p> + * Note that fetched attributes and metrics may or may note be cached in {@link GridClientNode} + * based on {@link GridClientConfiguration#isEnableMetricsCache()} and + * {@link GridClientConfiguration#isEnableAttributesCache()}parameters. Even though topology + * is refreshed automatically every {@link GridClientConfiguration#getTopologyRefreshFrequency()} + * interval, node metrics and attributes will be fetched in background only if + * {@link GridClientConfiguration#isAutoFetchMetrics()} or + * {@link GridClientConfiguration#isAutoFetchAttributes()} set to {@code true}. + * <p> + * Also note that node attributes are static and, if cached, there is no need + * to refresh them again. + * + * @param includeAttrs Whether to include node attributes. + * @param includeMetrics Whether to include node metrics. + * @return Future. + */ + public GridClientFuture<List<GridClientNode>> refreshTopologyAsync(boolean includeAttrs, boolean includeMetrics); + + /** ++ * Gets contents of default log file ({@code IGNITE_HOME/work/log/gridgain.log}). ++ * Note that backward reading (with negative line indexes) supported for only 8-bit character encodings. ++ * ++ * @param lineFrom Index of line from which log is get, inclusive. Negative values mean line numbers ++ * from the end of the file. ++ * @param lineTo Index of line to which log is get, inclusive. Negative values mean line numbers ++ * from the end of the file. ++ * @return Log contents. ++ * @throws GridClientException In case of error. ++ * @throws GridServerUnreachableException If none of the servers can be reached. ++ * @throws GridClientClosedException If client was closed manually. ++ */ ++ public List<String> log(int lineFrom, int lineTo) throws GridClientException; ++ ++ /** ++ * Asynchronously gets contents of default log file ++ * ({@code IGNITE_HOME/work/log/gridgain.log}). ++ * Note that backward reading (with negative line indexes) supported for only 8-bit character encodings. ++ * ++ * @param lineFrom Index of line from which log is get, inclusive. Negative values mean line numbers ++ * from the end of the file. ++ * @param lineTo Index of line to which log is get, inclusive. Negative values mean line numbers ++ * from the end of the file. ++ * @return Future for this operation. ++ */ ++ public GridClientFuture<List<String>> logAsync(int lineFrom, int lineTo); ++ ++ /** ++ * Gets contents of custom log file, i.e. log file in a non-default location. ++ * Note that backward reading (with negative line indexes) supported for only 8-bit character encodings. ++ * ++ * @param path Log file path. Can be absolute or relative to IGNITE_HOME. ++ * @param lineFrom Index of line from which log is get, inclusive. Negative values mean line numbers ++ * from the end of the file. ++ * @param lineTo Index of line to which log is get, inclusive. Negative values mean line numbers ++ * from the end of the file. ++ * @return Log contents. ++ * @throws GridClientException In case of error. ++ * @throws GridServerUnreachableException If none of the servers can be reached. ++ * @throws GridClientClosedException If client was closed manually. ++ */ ++ public List<String> log(String path, int lineFrom, int lineTo) throws GridClientException; ++ ++ /** ++ * Asynchronously gets contents of custom log file. ++ * Note that backward reading (with negative line indexes) supported for only 8-bit character encodings. ++ * ++ * @param path Log file path. Can be absolute or relative to IGNITE_HOME. ++ * @param lineFrom Index of line from which log is get, inclusive. Negative values mean line numbers ++ * from the end of the file. ++ * @param lineTo Index of line to which log is get, inclusive. Negative values mean line numbers ++ * from the end of the file. ++ * @return Future. ++ */ ++ public GridClientFuture<List<String>> logAsync(String path, int lineFrom, int lineTo); ++ ++ /** + * Sets keep portables flag for the next task execution in the current thread. + */ + public GridClientCompute withKeepPortables(); +}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/0a1b1b7a/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientConfiguration.java ---------------------------------------------------------------------- diff --cc modules/core/src/main/java/org/apache/ignite/internal/client/GridClientConfiguration.java index 330fca8,0000000..55b1f3a mode 100644,000000..100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientConfiguration.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientConfiguration.java @@@ -1,867 -1,0 +1,846 @@@ +/* + * 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.internal.client; + +import org.apache.ignite.internal.client.balancer.*; +import org.apache.ignite.internal.client.marshaller.*; +import org.apache.ignite.internal.client.marshaller.optimized.*; +import org.apache.ignite.internal.client.ssl.*; +import org.apache.ignite.portables.*; +import org.apache.ignite.plugin.security.*; +import org.apache.ignite.internal.util.typedef.*; +import org.apache.ignite.internal.util.typedef.internal.*; ++import org.apache.ignite.plugin.security.*; +import org.jetbrains.annotations.*; + +import java.net.*; +import java.util.*; +import java.util.concurrent.*; + +/** + * Java client configuration. + */ +public class GridClientConfiguration { + /** Default client protocol. */ + public static final GridClientProtocol DFLT_CLIENT_PROTOCOL = GridClientProtocol.TCP; + + /** Default topology refresh frequency is 2 sec. */ + public static final int DFLT_TOP_REFRESH_FREQ = 2000; + + /** Default maximum time connection can be idle. */ + public static final long DFLT_MAX_CONN_IDLE_TIME = 30000; + + /** Default ping interval in milliseconds. */ + public static final long DFLT_PING_INTERVAL = 5000; + + /** Default ping timeout in milliseconds. */ + public static final long DFLT_PING_TIMEOUT = 7000; + + /** Default connect timeout in milliseconds. */ + public static final int DFLT_CONNECT_TIMEOUT = 10000; + + /** Default flag setting for TCP_NODELAY option. */ + public static final boolean DFLT_TCP_NODELAY = true; + + /** List of servers to connect to. */ + private Collection<String> srvs = Collections.emptySet(); + + /** List of routers to connect to. */ + private Collection<String> routers = Collections.emptySet(); + + /** Client protocol. */ + private GridClientProtocol proto = DFLT_CLIENT_PROTOCOL; + + /** Socket connect timeout. */ + private int connectTimeout = DFLT_CONNECT_TIMEOUT; + + /** TCP_NODELAY flag. */ + private boolean tcpNoDelay = DFLT_TCP_NODELAY; + + /** SSL context factory */ + private GridSslContextFactory sslCtxFactory; + + /** Flag indicating whether metrics cache is enabled. */ + private boolean enableMetricsCache = true; + + /** Flag indicating whether attributes cache is enabled. */ + private boolean enableAttrsCache = true; + + /** Flag indicating whether metrics should be automatically fetched. */ + private boolean autoFetchMetrics = true; + + /** Flag indicating whether attributes should be automatically fetched. */ + private boolean autoFetchAttrs = true; + + /** Topology refresh frequency. */ + private long topRefreshFreq = DFLT_TOP_REFRESH_FREQ; + + /** Max time of connection idleness. */ + private long maxConnIdleTime = DFLT_MAX_CONN_IDLE_TIME; + + /** Ping interval. */ + private long pingInterval = DFLT_PING_INTERVAL; + + /** Ping timeout. */ + private long pingTimeout = DFLT_PING_TIMEOUT; + + /** Default balancer. */ + private GridClientLoadBalancer balancer = new GridClientRandomBalancer(); + + /** Collection of data configurations. */ + private Map<String, GridClientDataConfiguration> dataCfgs = Collections.emptyMap(); + + /** Credentials. */ + private GridSecurityCredentialsProvider credProvider; + + /** Executor. */ + private ExecutorService executor; + + /** Marshaller. */ + private GridClientMarshaller marshaller = new GridClientOptimizedMarshaller(); + + /** Daemon flag. */ + private boolean daemon; + - /** Portable configuration. */ - private PortableConfiguration portableCfg; - + /** + * Creates default configuration. + */ + public GridClientConfiguration() { + // No-op. + } + + /** + * Copy constructor. + * + * @param cfg Configuration to be copied. + */ + public GridClientConfiguration(GridClientConfiguration cfg) { + // Preserve alphabetical order for maintenance; + autoFetchAttrs = cfg.isAutoFetchAttributes(); + autoFetchMetrics = cfg.isAutoFetchMetrics(); + balancer = cfg.getBalancer(); + connectTimeout = cfg.getConnectTimeout(); + credProvider = cfg.getSecurityCredentialsProvider(); + enableAttrsCache = cfg.isEnableAttributesCache(); + enableMetricsCache = cfg.isEnableMetricsCache(); + executor = cfg.getExecutorService(); + marshaller = cfg.getMarshaller(); + maxConnIdleTime = cfg.getMaxConnectionIdleTime(); + pingInterval = cfg.getPingInterval(); + pingTimeout = cfg.getPingTimeout(); + proto = cfg.getProtocol(); + routers = cfg.getRouters(); + srvs = cfg.getServers(); + sslCtxFactory = cfg.getSslContextFactory(); + tcpNoDelay = cfg.isTcpNoDelay(); + topRefreshFreq = cfg.getTopologyRefreshFrequency(); + daemon = cfg.isDaemon(); + marshaller = cfg.getMarshaller(); - portableCfg = cfg.getPortableConfiguration(); + + setDataConfigurations(cfg.getDataConfigurations()); + } + + /** + * Creates properties-based configuration based on passed in properties. + * + * @param in Client configuration in properties format. + * @throws GridClientException If parsing configuration failed. + */ + public GridClientConfiguration(Properties in) throws GridClientException { + this("gg.client", in); + } + + /** + * Creates properties-based configuration. + * + * @param prefix Prefix for the client properties. + * @param in Properties map to load configuration from. + * @throws GridClientException If parsing configuration failed. + */ + public GridClientConfiguration(String prefix, Properties in) throws GridClientException { + load(prefix, in); + } + + /** + * Collection of {@code 'host:port'} pairs representing + * remote grid servers used to establish initial connection to - * the grid. Once connection is established, GridGain will get ++ * the grid. Once connection is established, Ignite will get + * a full view on grid topology and will be able to connect to + * any available remote node. + * <p> + * Note that only these addresses are used to perform + * topology updates in background and to detect Grid connectivity + * status. + * + * @return Collection of {@code 'host:port'} pairs representing remote + * grid servers. + * @see GridClient#connected() + */ + public Collection<String> getServers() { + return Collections.unmodifiableCollection(srvs); + } + + /** + * Collection of {@code 'host:port'} pairs representing + * grid routers used to establish connection to the grid. + * <p> + * Addresses here could be owned by Routers as well as + * by individual Grid nodes. No additional connections + * will be made even if other Grid nodes are available. + * <p> + * This configuration mode is designated for cases when + * some Grid nodes are unavailable (due to security restrictions + * for example). So only few nodes acting as routers or + * dedicated router components used to access entire Grid. + * <p> + * This configuration parameter will not be used and direct + * connections to all grid nodes will be established if + * {@link #getServers()} return non-empty collection value. + * <p> + * Note that only these addresses are used to perform + * topology updates in background and to detect Grid connectivity + * status. + * + * @return Collection of {@code 'host:port'} pairs + * representing routers. + * @see GridClient#connected() + */ + public Collection<String> getRouters() { + return routers; + } + + /** + * Sets list of servers this client should connect to. + * + * @param srvs List of servers. + */ + public void setServers(Collection<String> srvs) { + this.srvs = srvs != null ? srvs : Collections.<String>emptySet(); + } + + /** + * Sets list of routers this client should connect to. + * + * @param routers List of routers. + */ + public void setRouters(Collection<String> routers) { + this.routers = routers != null ? routers : Collections.<String>emptySet(); + } + + /** + * Gets protocol for communication between client and remote grid. + * Default is defined by {@link #DFLT_CLIENT_PROTOCOL} constant. + * + * @return Protocol for communication between client and remote grid. + */ + public GridClientProtocol getProtocol() { + return proto; + } + + /** + * Sets protocol type that should be used in communication. Protocol type cannot be changed after + * client is created. + * + * @param proto Protocol type. + * @see GridClientProtocol + */ + public void setProtocol(GridClientProtocol proto) { + this.proto = proto; + } + + /** + * Gets timeout for socket connect operation in milliseconds. If {@code 0} - + * then wait infinitely. Default is defined by {@link #DFLT_CONNECT_TIMEOUT} constant. + * + * @return Connect timeout in milliseconds. + */ + public int getConnectTimeout() { + return connectTimeout; + } + + /** + * Gets flag indicating whether {@code TCP_NODELAY} flag should be enabled for outgoing connections. + * This flag reduces communication latency and in the majority of cases should be set to true. For more + * information, see {@link Socket#setTcpNoDelay(boolean)} + * <p> + * If not set, default value is {@link #DFLT_TCP_NODELAY} + * + * @return If {@code TCP_NODELAY} should be set on underlying sockets. + */ + public boolean isTcpNoDelay() { + return tcpNoDelay; + } + + /** + * Sets whether {@code TCP_NODELAY} flag should be set on underlying socket connections. + * + * @param tcpNoDelay {@code True} if flag should be set. + */ + public void setTcpNoDelay(boolean tcpNoDelay) { + this.tcpNoDelay = tcpNoDelay; + } + + /** + * Sets timeout for socket connect operation. + * + * @param connectTimeout Connect timeout in milliseconds. + */ + public void setConnectTimeout(int connectTimeout) { + this.connectTimeout = connectTimeout; + } + + /** + * Gets a factory that should be used for SSL context creation. + * If it returns {@code null} then SSL is considered disabled. + * + * @return Factory instance. + * @see GridSslContextFactory + */ + public GridSslContextFactory getSslContextFactory() { + return sslCtxFactory; + } + + /** + * Sets SSL context factory that will be used for creation of secure connections. + * + * @param sslCtxFactory Context factory. + */ + public void setSslContextFactory(GridSslContextFactory sslCtxFactory) { + this.sslCtxFactory = sslCtxFactory; + } + + /** + * Default balancer to be used for computational client. It can be overridden + * for different compute instances. By default {@link GridClientRandomBalancer} + * is used. + * + * @return Default balancer to be used for computational client. + */ + public GridClientLoadBalancer getBalancer() { + return balancer; + } + + /** + * Sets default compute balancer. + * + * @param balancer Balancer to use. + */ + public void setBalancer(GridClientLoadBalancer balancer) { + this.balancer = balancer; + } + + /** + * Gets client credentials provider to authenticate with. + * + * @return Credentials provider. + */ + public GridSecurityCredentialsProvider getSecurityCredentialsProvider() { + return credProvider; + } + + /** + * Sets client credentials provider used in authentication process. + * + * @param credProvider Client credentials provider. + */ + public void setSecurityCredentialsProvider(GridSecurityCredentialsProvider credProvider) { + this.credProvider = credProvider; + } + + /** + * Gets a collection of data configurations specified by user. + * + * @return Collection of data configurations (possibly empty). + */ + public Collection<GridClientDataConfiguration> getDataConfigurations() { + return dataCfgs.values(); + } + + /** + * Sets data configurations. + * + * @param dataCfgs Data configurations. + */ + public void setDataConfigurations(Collection<? extends GridClientDataConfiguration> dataCfgs) { + this.dataCfgs = U.newHashMap(dataCfgs.size()); + + for (GridClientDataConfiguration dataCfg : dataCfgs) + this.dataCfgs.put(dataCfg.getName(), new GridClientDataConfiguration(dataCfg)); + } + + /** + * Gets data configuration for a cache with specified name. + * + * @param name Name of grid cache. + * @return Configuration or {@code null} if there is not configuration for specified name. + */ + public GridClientDataConfiguration getDataConfiguration(@Nullable String name) { + return dataCfgs.get(name); + } + + /** + * Sets flag indicating whether node and cache metrics should be cached by client. + * + * @param enableMetricsCache {@code True} if cache should be enabled. + */ + public void setEnableMetricsCache(boolean enableMetricsCache) { + this.enableMetricsCache = enableMetricsCache; + } + + /** + * Enables client to cache per-node and per-cache metrics internally. In memory + * sensitive environments, such as mobile platforms, caching metrics + * may be expensive and, hence, this parameter should be set to {@code false}. + * <p> + * Note that topology is refreshed automatically every {@link #getTopologyRefreshFrequency()} + * interval, and if {@link #isAutoFetchMetrics()} enabled then metrics will be updated + * with that frequency. + * <p> + * By default this value is {@code true} which means that metrics will be cached + * on the client side. + * + * @return {@code True} if metrics cache is enabled, {@code false} otherwise. + */ + public boolean isEnableMetricsCache() { + return enableMetricsCache; + } + + /** + * Sets flag indicating whether node attributes should be cached by client. + * + * @param enableAttrsCache {@code True} if cache should be enabled. + */ + public void setEnableAttributesCache(boolean enableAttrsCache) { + this.enableAttrsCache = enableAttrsCache; + } + + /** + * Enables client to cache per-node attributes internally. In memory + * sensitive environments, such as mobile platforms, caching node attributes + * may be expensive and, hence, this parameter should be set to {@code false}. + * <p> + * Note that node attributes are static and, if cached, there is no need + * to refresh them again. If {@link #isAutoFetchAttributes()} is enabled then + * attributes will be cached during client initialization. + * <p> + * By default this value is {@code true} which means that node attributes + * will be cached on the client side. + * + * @return {@code True} if attributes cache is enabled, {@code false} otherwise. + */ + public boolean isEnableAttributesCache() { + return enableAttrsCache; + } + + /** + * Sets flag indicating whether node metrics should be fetched by client automatically. + * + * @param autoFetchMetrics {@code True} if metrics should be fetched. + */ + public void setAutoFetchMetrics(boolean autoFetchMetrics) { + this.autoFetchMetrics = autoFetchMetrics; + } + + /** + * Allows client to fetch node metrics automatically with background topology refresh. + * <p> + * Note that this parameter will only affect auto-fetching of node metrics. + * Cache metrics still need to be fetched explicitly via + * {@link GridClientData#metrics()} or {@link GridClientData#metricsAsync()} methods. + * <p> + * By default this value is {@code true} which means that metrics will be fetched + * automatically. + * + * @return {@code true} if client should fetch metrics on topology refresh, + * {@code false} otherwise. + */ + public boolean isAutoFetchMetrics() { + return autoFetchMetrics; + } + + /** + * Sets flag indicating whether node attributes should be fetched by client automatically. + * + * @param autoFetchAttrs {@code True} if attributes should be fetched. + */ + public void setAutoFetchAttributes(boolean autoFetchAttrs) { + this.autoFetchAttrs = autoFetchAttrs; + } + + /** + * Allows client to fetch node attributes automatically with background topology refresh. + * <p> + * By default this value is {@code true} which means that attributes will be fetched + * automatically. + * + * @return {@code True} if client should fetch attributes once on topology refresh, + * {@code false} otherwise. + */ + public boolean isAutoFetchAttributes() { + return autoFetchAttrs; + } + + /** + * Gets topology refresh frequency. Default is defined by {@link #DFLT_TOP_REFRESH_FREQ} + * constant. + * + * @return Topology refresh frequency. + */ + public long getTopologyRefreshFrequency() { + return topRefreshFreq; + } + + /** + * Sets topology refresh frequency. If topology cache is enabled, grid topology + * will be refreshed every {@code topRefreshFreq} milliseconds. + * + * @param topRefreshFreq Topology refresh frequency in milliseconds. + */ + public void setTopologyRefreshFrequency(long topRefreshFreq) { + this.topRefreshFreq = topRefreshFreq; + } + + /** + * Gets maximum amount of time that client connection can be idle before it is closed. + * Default is defined by {@link #DFLT_MAX_CONN_IDLE_TIME} constant. + * + * @return Maximum idle time in milliseconds. + */ + public long getMaxConnectionIdleTime() { + return maxConnIdleTime; + } + + /** + * Sets maximum time in milliseconds which connection can be idle before it is closed by client. + * + * @param maxConnIdleTime Maximum time of connection idleness in milliseconds. + */ + public void setMaxConnectionIdleTime(long maxConnIdleTime) { + this.maxConnIdleTime = maxConnIdleTime; + } + + /** + * Gets time interval in milliseconds between ping requests. Default is defined + * by {@link #DFLT_PING_INTERVAL} constant. + * <p> + * Ping requests used by {@link GridClientProtocol#TCP} protocol + * to detect network failures and half-opened sockets. + * + * @return Ping interval. + */ + public long getPingInterval() { + return pingInterval; + } + + /** + * Sets ping interval in milliseconds. + * + * @param pingInterval Ping interval in milliseconds. + */ + public void setPingInterval(long pingInterval) { + this.pingInterval = pingInterval; + } + + /** + * Gets ping timeout. Default is defined by {@link #DFLT_PING_TIMEOUT} constant. + * <p> + * Ping requests used by {@link GridClientProtocol#TCP} protocol + * to detect network failures and half-opened sockets. + * If no response received in period equal to this timeout than connection + * considered broken and closed. + * + * @return Ping timeout. + */ + public long getPingTimeout() { + return pingTimeout; + } + + /** + * Sets ping timeout in milliseconds. + * + * @param pingTimeout Ping interval in milliseconds. + */ + public void setPingTimeout(long pingTimeout) { + this.pingTimeout = pingTimeout; + } + + /** + * Gets {@link ExecutorService} where client could run asynchronous operations. + * <p> + * When using {@link GridClientProtocol#TCP} this executor should be able to serve at least + * {@code Runtime.getRuntime().availableProcessors()} parallel tasks. + * <p> + * Note that this executor will be automatically shut down when client get closed. + * + * @return {@link ExecutorService} instance to use. + */ + public ExecutorService getExecutorService() { + return executor; + } + + /** + * Sets executor service. + * + * @param executor Executor service to use in client. + */ + public void setExecutorService(ExecutorService executor) { + this.executor = executor; + } + + /** + * Gets the marshaller, that is used to communicate between client and server. + * <p> + * Options, that can be used out-of-the-box: + * <ul> - * <li>{@link GridClientOptimizedMarshaller} (default) - GridGain's optimized marshaller.</li> ++ * <li>{@link GridClientOptimizedMarshaller} (default) - Ignite's optimized marshaller.</li> + * <li>{@code GridClientPortableMarshaller} - Marshaller that supports portable objects.</li> + * <li>{@link org.apache.ignite.internal.client.marshaller.jdk.GridClientJdkMarshaller} - JDK marshaller (not recommended).</li> + * </ul> + * + * @return A marshaller to use. + */ + public GridClientMarshaller getMarshaller() { + return marshaller; + } + + /** + * Sets the marshaller to use for communication. + * + * @param marshaller A marshaller to use. + */ + public void setMarshaller(GridClientMarshaller marshaller) { + this.marshaller = marshaller; + } + + /** - * Gets portable configuration. - * - * @return Portable configuration. - */ - public PortableConfiguration getPortableConfiguration() { - return portableCfg; - } - - /** - * Sets portable configuration. - * - * @param portableCfg Portable configuration. - */ - public void setPortableConfiguration(@Nullable PortableConfiguration portableCfg) { - this.portableCfg = portableCfg; - } - - /** + * Load client configuration from the properties map. + * + * @param prefix Prefix for the client properties. + * @param in Properties map to load configuration from. + * @throws GridClientException If parsing configuration failed. + */ + public void load(String prefix, Properties in) throws GridClientException { + while (prefix.endsWith(".")) + prefix = prefix.substring(0, prefix.length() - 1); + + if (!prefix.isEmpty()) + prefix += "."; + + String balancer = in.getProperty(prefix + "balancer"); + String connectTimeout = in.getProperty(prefix + "connectTimeout"); + String cred = in.getProperty(prefix + "credentials"); + String autoFetchMetrics = in.getProperty(prefix + "autoFetchMetrics"); + String autoFetchAttrs = in.getProperty(prefix + "autoFetchAttributes"); + String maxConnIdleTime = in.getProperty(prefix + "idleTimeout"); + String proto = in.getProperty(prefix + "protocol"); + String srvrs = in.getProperty(prefix + "servers"); + String tcpNoDelay = in.getProperty(prefix + "tcp.noDelay"); + String topRefreshFreq = in.getProperty(prefix + "topology.refresh"); + + String sslEnabled = in.getProperty(prefix + "ssl.enabled"); + + String sslProto = in.getProperty(prefix + "ssl.protocol", "TLS"); + String sslKeyAlg = in.getProperty(prefix + "ssl.key.algorithm", "SunX509"); + + String keyStorePath = in.getProperty(prefix + "ssl.keystore.location"); + String keyStorePwd = in.getProperty(prefix + "ssl.keystore.password"); + String keyStoreType = in.getProperty(prefix + "ssl.keystore.type"); + + String trustStorePath = in.getProperty(prefix + "ssl.truststore.location"); + String trustStorePwd = in.getProperty(prefix + "ssl.truststore.password"); + String trustStoreType = in.getProperty(prefix + "ssl.truststore.type"); + + String dataCfgs = in.getProperty(prefix + "data.configurations"); + + setBalancer(resolveBalancer(balancer)); + + if (!F.isEmpty(connectTimeout)) + setConnectTimeout(Integer.parseInt(connectTimeout)); + + if (!F.isEmpty(cred)) { + int idx = cred.indexOf(':'); + + if (idx >= 0 && idx < cred.length() - 1) { + setSecurityCredentialsProvider(new GridSecurityCredentialsBasicProvider( + new GridSecurityCredentials(cred.substring(0, idx), cred.substring(idx + 1)))); + } + else { + setSecurityCredentialsProvider(new GridSecurityCredentialsBasicProvider( + new GridSecurityCredentials(null, null, cred))); + } + } + + if (!F.isEmpty(autoFetchMetrics)) + setAutoFetchMetrics(Boolean.parseBoolean(autoFetchMetrics)); + + if (!F.isEmpty(autoFetchAttrs)) + setAutoFetchAttributes(Boolean.parseBoolean(autoFetchAttrs)); + + if (!F.isEmpty(maxConnIdleTime)) + setMaxConnectionIdleTime(Integer.parseInt(maxConnIdleTime)); + + if (!F.isEmpty(proto)) + setProtocol(GridClientProtocol.valueOf(proto)); + + if (!F.isEmpty(srvrs)) + setServers(Arrays.asList(srvrs.replaceAll("\\s+", "").split(","))); + + if (!F.isEmpty(tcpNoDelay)) + setTcpNoDelay(Boolean.parseBoolean(tcpNoDelay)); + + if (!F.isEmpty(topRefreshFreq)) + setTopologyRefreshFrequency(Long.parseLong(topRefreshFreq)); + + // + // SSL configuration section + // + + if (!F.isEmpty(sslEnabled) && Boolean.parseBoolean(sslEnabled)) { + GridSslBasicContextFactory factory = new GridSslBasicContextFactory(); + + factory.setProtocol(F.isEmpty(sslProto) ? "TLS" : sslProto); + factory.setKeyAlgorithm(F.isEmpty(sslKeyAlg) ? "SunX509" : sslKeyAlg); + + if (F.isEmpty(keyStorePath)) + throw new IllegalArgumentException("SSL key store location is not specified."); + + factory.setKeyStoreFilePath(keyStorePath); + + if (keyStorePwd != null) + factory.setKeyStorePassword(keyStorePwd.toCharArray()); + + factory.setKeyStoreType(F.isEmpty(keyStoreType) ? "jks" : keyStoreType); + + if (F.isEmpty(trustStorePath)) + factory.setTrustManagers(GridSslBasicContextFactory.getDisabledTrustManager()); + else { + factory.setTrustStoreFilePath(trustStorePath); + + if (trustStorePwd != null) + factory.setTrustStorePassword(trustStorePwd.toCharArray()); + + factory.setTrustStoreType(F.isEmpty(trustStoreType) ? "jks" : trustStoreType); + } + + setSslContextFactory(factory); + } + + // + // Data configuration section + // + + if (!F.isEmpty(dataCfgs)) { + String[] names = dataCfgs.replaceAll("\\s+", "").split(","); + Collection<GridClientDataConfiguration> list = new ArrayList<>(); + + for (String cfgName : names) { + if (F.isEmpty(cfgName)) + continue; + + String name = in.getProperty(prefix + "data." + cfgName + ".name"); + String bal = in.getProperty(prefix + "data." + cfgName + ".balancer"); + String aff = in.getProperty(prefix + "data." + cfgName + ".affinity"); + + GridClientDataConfiguration dataCfg = new GridClientDataConfiguration(); + + dataCfg.setName(F.isEmpty(name) ? null : name); + dataCfg.setBalancer(resolveBalancer(bal)); + dataCfg.setAffinity(resolveAffinity(aff)); + + list.add(dataCfg); + } + + setDataConfigurations(list); + } + } + + /** + * Resolve load balancer from string definition. + * + * @param balancer Load balancer string definition. + * @return Resolved load balancer. + * @throws GridClientException If loading failed. + */ + private static GridClientLoadBalancer resolveBalancer(String balancer) throws GridClientException { + if (F.isEmpty(balancer) || "random".equals(balancer)) + return new GridClientRandomBalancer(); + + if ("roundrobin".equals(balancer)) + return new GridClientRoundRobinBalancer(); + + return newInstance(GridClientLoadBalancer.class, balancer); + } + + /** + * Resolve data affinity from string definition. + * + * @param affinity Data affinity string definition. + * @return Resolved data affinity. + * @throws GridClientException If loading failed. + */ + private static GridClientDataAffinity resolveAffinity(String affinity) throws GridClientException { + if (F.isEmpty(affinity)) + return null; + + if ("partitioned".equals(affinity)) + return new GridClientPartitionAffinity(); + + return newInstance(GridClientDataAffinity.class, affinity); + } + + /** + * Constructs new instance of the specified class. + * + * @param exp Expected class for the new instance. + * @param clsName Class name to create new instance for. + * @param <T> Expected class type for the new instance. + * @return New instance of specified class. + * @throws GridClientException If loading failed. + */ + private static <T> T newInstance(Class<T> exp, String clsName) throws GridClientException { + Object obj; + + try { + obj = Class.forName(clsName).newInstance(); + } + // Catch all for convenience. + catch (Exception e) { + throw new GridClientException("Failed to create class instance: " + clsName, e); + } + + return exp.cast(obj); + } + + /** + * Set the daemon flag value. Communication threads will be created as daemons if this flag is set. + * + * @param daemon Daemon flag. + */ + public void setDaemon(boolean daemon) { + this.daemon = daemon; + } + + /** + * Get the daemon flag. + * + * @return Daemon flag. + */ + public boolean isDaemon() { + return daemon; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/0a1b1b7a/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientData.java ---------------------------------------------------------------------- diff --cc modules/core/src/main/java/org/apache/ignite/internal/client/GridClientData.java index 79d5c5c,0000000..73fa06f mode 100644,000000..100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientData.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientData.java @@@ -1,443 -1,0 +1,443 @@@ +/* + * 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.internal.client; + +import java.util.*; + +/** + * A data projection of grid client. Contains various methods for cache operations and metrics retrieval. + * An instance of data projection over some remote cache is provided via + * {@link GridClient#data(String)} method. + * <h1 class="header">Affinity Awareness</h1> - * One of the unique properties of the GridGain remote clients is that they are ++ * One of the unique properties of the Ignite remote clients is that they are + * affinity aware. In other words, both compute and data APIs will optionally + * contact exactly the node where the data is cached based on some affinity key. + * This allows for collocation of computations and data and avoids extra network + * hops that would be necessary if non-affinity nodes were contacted. By default + * all operations on {@code GridClientData} API will be affinity-aware unless + * such behavior is overridden by pinning one or more remote nodes + * (see {@link #pinNodes(GridClientNode, GridClientNode...)} for more information). + */ +public interface GridClientData { + /** + * Gets name of the remote cache. The cache name for this projection was specified + * via {@link GridClient#data(String)} method at the time of creation. + * + * @return Name of the remote cache. + */ + public String cacheName(); + + /** + * Gets client data projection which will only contact specified remote grid node. By default, remote + * node is determined based on {@link GridClientDataAffinity} provided - this method allows + * to override default behavior and use only specified server for all cache operations. + * <p> + * Use this method when there are other than {@code key-affinity} reasons why a certain + * node should be contacted. + * + * @param node Node to be contacted (optional). + * @param nodes Additional nodes (optional). + * @return Client data which will only contact server with given node ID. + * @throws GridClientException If resulting projection is empty. + */ + public GridClientData pinNodes(GridClientNode node, GridClientNode... nodes) throws GridClientException; + + /** + * Gets pinned node or {@code null} if no nodes were pinned. + * + * @return Pinned node. + */ + public Collection<GridClientNode> pinnedNodes(); + + /** + * Puts value to cache on remote grid. + * <p> + * Note that this operation is affinity-aware and will immediately contact + * exactly the remote node on which this key is supposed to be cached (unless + * some nodes were {@code pinned}). + * + * @param key Key to put in cache. + * @param val Value to put in cache. + * @return Whether value was actually put to cache. + * @throws GridClientException In case of error. + * @throws GridServerUnreachableException If none of the servers can be reached. + * @throws GridClientClosedException If client was closed manually. + */ + public <K, V> boolean put(K key, V val) throws GridClientException; + + /** + * Asynchronously puts value to cache on remote node. + * <p> + * Note that this operation is affinity-aware and will immediately contact + * exactly the remote node on which this key is supposed to be cached (unless + * some nodes were {@code pinned}). + * + * @param key Key to put in cache. + * @param val Value to put in cache. + * @return Future whether value was actually put to cache. + */ + public <K, V> GridClientFuture<Boolean> putAsync(K key, V val); + + /** + * Puts entries to cache on remote grid. + * <p> + * Note that this operation is affinity-aware and will immediately contact + * exactly the remote nodes on which these keys are supposed to be cached (unless + * some nodes were {@code pinned}). If entries do not map to one node, then the node + * which has most mapped entries will be contacted. + * + * @param entries Entries to put in cache. + * @throws GridClientException In case of error. + * @throws GridServerUnreachableException If none of the servers can be reached. + * @throws GridClientClosedException If client was closed manually. + */ + public <K, V> void putAll(Map<K, V> entries) throws GridClientException; + + /** + * Asynchronously puts entries to cache on remote grid. + * <p> + * Note that this operation is affinity-aware and will immediately contact + * exactly the remote nodes on which these keys are supposed to be cached (unless + * some nodes were {@code pinned}). If entries do not map to one node, then the node + * which has most mapped entries will be contacted. + * + * @param entries Entries to put in cache. + * @return Future whether this operation completes. + */ + public <K, V> GridClientFuture<?> putAllAsync(Map<K, V> entries); + + /** + * Gets value from cache on remote node. + * <p> + * Note that this operation is affinity-aware and will immediately contact + * exactly the remote node on which this key is supposed to be cached (unless + * some nodes were {@code pinned}). + * + * @param key Key to get from cache. + * @return Value for given key or {@code null} if no value was cached. + * @throws GridClientException In case of error. + * @throws GridServerUnreachableException If none of the servers can be reached. + * @throws GridClientClosedException If client was closed manually. + */ + public <K, V> V get(K key) throws GridClientException; + + /** + * Asynchronously gets value from cache on remote grid. + * <p> + * Note that this operation is affinity-aware and will immediately contact + * exactly the remote node on which this key is supposed to be cached (unless + * some nodes were {@code pinned}). + * + * @param key Key to get from cache. + * @return Future with value for given key or with {@code null} if no value was cached. + */ + public <K, V> GridClientFuture<V> getAsync(K key); + + /** + * Gets entries from cache on remote grid. + * <p> + * Note that this operation is affinity-aware and will immediately contact + * exactly the remote nodes on which these keys are supposed to be cached (unless + * some nodes were {@code pinned}). If entries do not map to one node, then the node + * which has most mapped entries will be contacted. + * + * @param keys Keys to get. + * @throws GridClientException In case of error. + * @return Entries retrieved from remote cache nodes. + * @throws GridServerUnreachableException If none of the servers can be reached. + * @throws GridClientClosedException If client was closed manually. + */ + public <K, V> Map<K, V> getAll(Collection<K> keys) throws GridClientException; + + /** + * Asynchronously gets entries from cache on remote grid. + * <p> + * Note that this operation is affinity-aware and will immediately contact + * exactly the remote nodes on which these keys are supposed to be cached (unless + * some nodes were {@code pinned}). If entries do not map to one node, then the node + * which has most mapped entries will be contacted. + * + * @param keys Keys to get. + * @return Future with entries retrieved from remote cache nodes. + */ + public <K, V> GridClientFuture<Map<K, V>> getAllAsync(Collection<K> keys); + + /** + * Removes value from cache on remote node. + * <p> + * Note that this operation is affinity-aware and will immediately contact + * exactly the remote node on which this key is supposed to be cached (unless + * some nodes were {@code pinned}). + * + * @param key Key to remove. + * @return Whether value was actually removed. + * @throws GridClientException In case of error. + * @throws GridServerUnreachableException If none of the servers can be reached. + * @throws GridClientClosedException If client was closed manually. + */ + public <K> boolean remove(K key) throws GridClientException; + + /** + * Asynchronously removes value from cache on remote grid. + * <p> + * Note that this operation is affinity-aware and will immediately contact + * exactly the remote node on which this key is supposed to be cached (unless + * some nodes were {@code pinned}). + * + * @param key Key to remove. + * @return Future whether value was actually removed. + */ + public <K> GridClientFuture<Boolean> removeAsync(K key); + + /** + * Removes entries from cache on remote node. + * <p> + * Note that this operation is affinity-aware and will immediately contact + * exactly the remote nodes on which these keys are supposed to be cached (unless + * some nodes were {@code pinned}). If entries do not map to one node, then the node + * which has most mapped entries will be contacted. + * + * @param keys Keys to remove. + * @throws GridClientException In case of error. + * @throws GridServerUnreachableException If none of the servers can be reached. + * @throws GridClientClosedException If client was closed manually. + */ + public <K> void removeAll(Collection<K> keys) throws GridClientException; + + /** + * Asynchronously removes entries from cache on remote grid. + * <p> + * Note that this operation is affinity-aware and will immediately contact + * exactly the remote nodes on which these keys are supposed to be cached (unless + * some nodes were {@code pinned}). If entries do not map to one node, then the node + * which has most mapped entries will be contacted. + * + * @param keys Keys to remove. + * @return Future whether operation finishes. + */ + public <K> GridClientFuture<?> removeAllAsync(Collection<K> keys); + + /** + * Replaces value in cache on remote grid only if there was a {@code non-null} + * value associated with this key. + * <p> + * Note that this operation is affinity-aware and will immediately contact + * exactly the remote node on which this key is supposed to be cached (unless + * some nodes were {@code pinned}). + * + * @param key Key to replace. + * @param val Value to replace. + * @return Whether value was actually replaced. + * @throws GridClientException In case of error. + * @throws GridServerUnreachableException If none of the servers can be reached. + * @throws GridClientClosedException If client was closed manually. + */ + public <K, V> boolean replace(K key, V val) throws GridClientException; + + /** + * Asynchronously replaces value in cache on remote grid only if there was a {@code non-null} + * value associated with this key. + * <p> + * Note that this operation is affinity-aware and will immediately contact + * exactly the remote node on which this key is supposed to be cached (unless + * some nodes were {@code pinned}). + * + * @param key Key to replace. + * @param val Value to replace. + * @return Future whether value was actually replaced. + */ + public <K, V> GridClientFuture<Boolean> replaceAsync(K key, V val); + + /** + * Sets entry value to {@code val1} if current value is {@code val2} with + * following conditions: + * <ul> + * <li> + * If {@code val1} is {@code null} and {@code val2} is equal to current value, + * entry is removed from cache. + * </li> + * <li> + * If {@code val2} is {@code null}, entry is created if it doesn't exist. + * </li> + * <li> + * If both {@code val1} and {@code val2} are {@code null}, entry is removed. + * </li> + * </ul> + * Note that this operation is affinity-aware and will immediately contact + * exactly the remote node on which this key is supposed to be cached (unless + * some nodes were {@code pinned}). + * + * @param key Key to set. + * @param val1 Value to set. + * @param val2 Check value. + * @return Whether value of entry was changed. + * @throws GridClientException In case of error. + * @throws GridServerUnreachableException If none of the servers can be reached. + * @throws GridClientClosedException If client was closed manually. + */ + public <K, V> boolean cas(K key, V val1, V val2) throws GridClientException; + + /** + * Asynchronously sets entry value to {@code val1} if current value is {@code val2} + * with following conditions: + * <ul> + * <li> + * If {@code val1} is {@code null} and {@code val2} is equal to current value, + * entry is removed from cache. + * </li> + * <li> + * If {@code val2} is {@code null}, entry is created if it doesn't exist. + * </li> + * <li> + * If both {@code val1} and {@code val2} are {@code null}, entry is removed. + * </li> + * </ul> + * Note that this operation is affinity-aware and will immediately contact + * exactly the remote node on which this key is supposed to be cached (unless + * some nodes were {@code pinned}). + * + * @param key Key to set. + * @param val1 Value to set. + * @param val2 Check value. + * @return Future whether value of entry was changed. + */ + public <K, V> GridClientFuture<Boolean> casAsync(K key, V val1, V val2); + + /** + * Gets affinity node ID for provided key. This method will return {@code null} if no + * affinity was configured for the given cache for this client or there are no nodes in topology with + * cache enabled. + * + * @param key Key. + * @return Node ID. + * @throws GridClientException In case of error. + */ + public <K> UUID affinity(K key) throws GridClientException; + + /** + * Fetches metrics for cache from remote grid. + * + * @return Cache metrics. + * @throws GridClientException In case of error. + * @throws GridServerUnreachableException If none of the servers can be reached. + * @throws GridClientClosedException If client was closed manually. + */ + public GridClientDataMetrics metrics() throws GridClientException; + + /** + * Asynchronously fetches metrics for cache from remote grid. + * + * @return Future with cache metrics. + */ + public GridClientFuture<GridClientDataMetrics> metricsAsync(); + + /** + * Tries to get metrics from local cache. + * <p> + * Local cache is updated on every {@link #metrics()} or {@link #metricsAsync()} call + * if {@link GridClientConfiguration#isEnableMetricsCache()} is enabled. If it is + * disabled then this method will always return {@code null}. + * + * @return Cached metrics or {@code null} if no cached metrics available. + * @throws GridClientException In case of error. + * @throws GridServerUnreachableException If none of the servers can be reached. + * @throws GridClientClosedException If client was closed manually. + */ + public GridClientDataMetrics cachedMetrics() throws GridClientException; + + /** + * Append requested value to already cached one. This method supports work with strings, lists and maps. + * <p> + * Note that this operation is affinity-aware and will immediately contact + * exactly the remote node on which this key is supposed to be cached (unless + * some nodes were {@code pinned}). + * + * @param key Key to manipulate cache value for. + * @param val Value to append to the cached one. + * @return Whether value of entry was changed. + * @throws GridClientException In case of error. + */ + public <K, V> boolean append(K key, V val) throws GridClientException; + + /** + * Append requested value to already cached one. This method supports work with strings, lists and maps. + * <p> + * Note that this operation is affinity-aware and will immediately contact + * exactly the remote node on which this key is supposed to be cached (unless + * some nodes were {@code pinned}). + * + * @param key Key to manipulate cache value for. + * @param val Value to append to the cached one. + * @return Future whether value of entry was changed. + * @throws GridClientException In case of error. + */ + public <K, V> GridClientFuture<Boolean> appendAsync(K key, V val) throws GridClientException; + + /** + * Prepend requested value to already cached one. This method supports work with strings, lists and maps. + * <p> + * Note that this operation is affinity-aware and will immediately contact + * exactly the remote node on which this key is supposed to be cached (unless + * some nodes were {@code pinned}). + * + * @param key Key to manipulate cache value for. + * @param val Value to prepend to the cached one. + * @return Whether value of entry was changed. + * @throws GridClientException In case of error. + */ + public <K, V> boolean prepend(K key, V val) throws GridClientException; + + /** + * Prepend requested value to already cached one. This method supports work with strings, lists and maps. + * <p> + * Note that this operation is affinity-aware and will immediately contact + * exactly the remote node on which this key is supposed to be cached (unless + * some nodes were {@code pinned}). + * + * @param key Key to manipulate cache value for. + * @param val Value to prepend to the cached one. + * @return Future whether value of entry was changed. + * @throws GridClientException In case of error. + */ + public <K, V> GridClientFuture<Boolean> prependAsync(K key, V val) throws GridClientException; + + /** + * Gets cache flags enabled on this data projection. + * + * @return Flags for this data projection (empty set if no flags have been set). + */ + public Set<GridClientCacheFlag> flags(); + + /** + * Creates new client data object with enabled cache flags. + * + * @param flags Optional cache flags to be enabled. + * @return New client data object. + * @throws GridClientException In case of error. + */ + public GridClientData flagsOn(GridClientCacheFlag... flags) throws GridClientException; + + /** + * Creates new client data object with disabled cache flags. + * + * @param flags Cache flags to be disabled. + * @return New client data object. + * @throws GridClientException In case of error. + */ + public GridClientData flagsOff(GridClientCacheFlag... flags) throws GridClientException; +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/0a1b1b7a/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientFactory.java ---------------------------------------------------------------------- diff --cc modules/core/src/main/java/org/apache/ignite/internal/client/GridClientFactory.java index 0160159,0000000..1616d0a mode 100644,000000..100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientFactory.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientFactory.java @@@ -1,138 -1,0 +1,138 @@@ +/* + * 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.internal.client; + +import org.apache.ignite.internal.client.impl.*; + +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.locks.*; + +/** + * Client factory opens and closes clients. It also tracks all currently opened clients as well. + */ +public class GridClientFactory { + /** Map that contain all opened clients. */ + private static ConcurrentMap<UUID, GridClientImpl> openClients = new ConcurrentHashMap<>(); + + /** Lock to prevent concurrent adding of clients while stopAll is working. */ + private static ReadWriteLock busyLock = new ReentrantReadWriteLock(); + + /** + * Ensure singleton. + */ + private GridClientFactory() { + // No-op. + } + + /** + * Starts a client with given configuration. Starting client will be assigned a randomly generated + * UUID which can be obtained by {@link GridClient#id()} method. + * + * @param cfg Client configuration. + * @return Started client. + * @throws GridClientException If client could not be created. + */ + public static GridClient start(GridClientConfiguration cfg) throws GridClientException { + busyLock.readLock().lock(); + + try { + UUID clientId = UUID.randomUUID(); + - GridClientImpl client = new GridClientImpl(clientId, cfg); ++ GridClientImpl client = new GridClientImpl(clientId, cfg, false); + + GridClientImpl old = openClients.putIfAbsent(clientId, client); + + assert old == null : "Random unique UUID generation failed."; + + return client; + } + finally { + busyLock.readLock().unlock(); + } + } + + /** + * Waits for all open clients to finish their operations and stops them, This method + * is equivalent to {@code stopAll(true)} method invocation. + * + * @see #stopAll(boolean) + */ + public static void stopAll() { + stopAll(true); + } + + /** + * Stops all currently open clients. + * + * @param wait If {@code true} then each client will wait to finish all ongoing requests before + * closing (however, no new requests will be accepted). If {@code false}, clients will be + * closed immediately and all ongoing requests will be failed. + */ + @SuppressWarnings("TooBroadScope") + public static void stopAll(boolean wait) { + ConcurrentMap<UUID, GridClientImpl> old; + + busyLock.writeLock().lock(); + + try { + old = openClients; + + openClients = new ConcurrentHashMap<>(); + } + finally { + busyLock.writeLock().unlock(); + } + + for (GridClientImpl client : old.values()) + client.stop(wait); + } + + /** + * Waits for all pending requests for a particular client to be completed (no new requests will be + * accepted) and then closes the client. This method is equivalent to {@code stop(clientId, true)}. + * + * @param clientId Identifier of client to close. + * @see #stop(UUID, boolean) + */ + public static void stop(UUID clientId) { + stop(clientId, true); + } + + /** + * Stops particular client. + * + * @param clientId Client identifier to close. + * @param wait If {@code true} then client will wait to finish all ongoing requests before + * closing (however, no new requests will be accepted). If {@code false}, client will be + * closed immediately and all ongoing requests will be failed. + */ + public static void stop(UUID clientId, boolean wait) { + busyLock.readLock().lock(); + + try { + GridClientImpl client = openClients.remove(clientId); + + if (client != null) + client.stop(wait); + } + finally { + busyLock.readLock().unlock(); + } + } +}