Beispiel #1
0
        /**
         * <summary>
         * This method executes request to a communication layer and handles connection error, if it occurs. Server
         * is picked up according to the projection affinity and key given. Connection will be made with the node
         * on which key is cached. In case of communication exception client instance is notified and new instance
         * of client is created. If none of servers can be reached, an exception is thrown.</summary>
         *
         * <param name="c">Closure to be executed.</param>
         * <param name="cacheName">Cache name for which mapped node will be calculated.</param>
         * <param name="affKey">Affinity key.</param>
         * <returns>Closure result.</returns>
         */
        protected IGridClientFuture <TRes> WithReconnectHandling <TRes>(Func <IGridClientConnection, Guid, IGridClientFuture <TRes> > c, String cacheName, Object affKey)
        {
            IGridClientDataAffinity affinity = cfg.Affinity(cacheName);

            // If pinned (fixed-nodes) or no affinity provided use balancer.
            if (_nodes != null || affinity == null)
            {
                return(WithReconnectHandling(c));
            }

            try {
                IList <N> prjNodes = ProjectionNodes();

                if (prjNodes.Count == 0)
                {
                    throw new GridClientServerUnreachableException("Failed to get affinity node" +
                                                                   " (no nodes in topology were accepted by the filter): " + _filter);
                }

                N node = affinity.Node(affKey, prjNodes);

                GridClientConnectionManager connMgr = cfg.ConnectionManager;

                for (int i = 0; i < RetryCount; i++)
                {
                    IGridClientConnection conn = null;

                    try {
                        conn = connMgr.connection(node);

                        return(c(conn, node.Id));
                    }
                    catch (GridClientConnectionIdleClosedException e) {
                        connMgr.onFacadeFailed(node, conn, e);
                    }
                    catch (GridClientConnectionResetException e) {
                        connMgr.onFacadeFailed(node, conn, e);

                        if (!CheckNodeAlive(node.Id))
                        {
                            throw new GridClientServerUnreachableException("Failed to communicate with mapped grid node" +
                                                                           " for given affinity key (node left the grid)" +
                                                                           " [nodeId=" + node.Id + ", affKey=" + affKey + ']');
                        }
                    }
                }

                throw new GridClientServerUnreachableException("Failed to communicate with mapped grid node for given affinity " +
                                                               "key (did node left the grid?) [nodeId=" + node.Id + ", affKey=" + affKey + ']');
            }
            catch (GridClientException e) {
                return(new GridClientFinishedFuture <TRes>(() => {
                    throw e;
                }));
            }
        }
Beispiel #2
0
        /**
         * <summary>
         * Tries to refresh node on every possible connection in topology.</summary>
         *
         * <param name="nodeId">Node id to check.</param>
         * <returns><c>True</c> if response was received, <c>null</c> if either <c>null</c> response received
         * or no nodes can be contacted at all.</returns>
         * <exception cref="GridClientClosedException">If client was closed manually.</exception>
         */
        protected bool CheckNodeAlive(Guid nodeId)
        {
            GridClientConnectionManager connMgr = cfg.ConnectionManager;
            GridClientTopology          top     = cfg.Topology;

            // Try to get node information on any of the connections possible.
            foreach (N node in top.Nodes())
            {
                try {
                    // Do not try to connect to the same node.
                    if (node.Id.Equals(nodeId))
                    {
                        continue;
                    }

                    // Get connection to node DIFFER from the requested nodeId.
                    IGridClientConnection conn = connMgr.connection(node);

                    try {
                        // Get node via DIFFERENT grid node to ensure the grid knows about node with nodeId (it is alive).
                        N target = conn.Node(nodeId, false, false, node.Id).Result;

                        // If requested node not found...
                        if (target == null)
                        {
                            top.NodeFailed(nodeId);
                        }

                        return(target != null);
                    }
                    catch (GridClientConnectionResetException e) {
                        connMgr.onFacadeFailed(node, conn, e);
                    }
                    catch (GridClientClosedException) {
                        throw;
                    }
                    catch (GridClientException e) {
                        // Future failed, so connection exception have already been handled.
                        Dbg.WriteLine("Could not receive node by its id [nodeId={0}, e={1}]", nodeId, e);
                    }
                }
                catch (GridClientServerUnreachableException e) {
                    // Try next node.
                    Dbg.WriteLine("Could not receive node by its id [nodeId={0}, e={1}]", nodeId, e);
                }
            }

            return(false);
        }
Beispiel #3
0
        /**
         * <summary>
         * This method executes request to a communication layer and handles connection error, if it occurs.
         * In case of communication exception client instance is notified and new instance of client is created.
         * If none of the grid servers can be reached, an exception is thrown.</summary>
         *
         * <param name="c">Closure to be executed.</param>
         * <returns>Closure result.</returns>
         */
        protected IGridClientFuture <TRes> WithReconnectHandling <TRes>(Func <IGridClientConnection, Guid, IGridClientFuture <TRes> > c)
        {
            try {
                N node = null;

                bool changeNode = false;

                GridClientConnectionManager connMgr = cfg.ConnectionManager;

                for (int i = 0; i < RetryCount; i++)
                {
                    if (node == null || changeNode)
                    {
                        node = BalancedNode();
                    }

                    IGridClientConnection conn = null;

                    try {
                        conn = connMgr.connection(node);

                        return(c(conn, node.Id));
                    }
                    catch (GridClientConnectionIdleClosedException e) {
                        connMgr.onFacadeFailed(node, conn, e);

                        // It's ok, just reconnect to the same node.
                        changeNode = false;
                    }
                    catch (GridClientConnectionResetException e) {
                        connMgr.onFacadeFailed(node, conn, e);

                        changeNode = true;
                    }
                }

                throw new GridClientServerUnreachableException("Failed to communicate with grid nodes " +
                                                               "(maximum count of retries reached).");
            }
            catch (GridClientException e) {
                return(new GridClientFinishedFuture <TRes>(() => {
                    throw e;
                }));
            }
        }
Beispiel #4
0
        /**
         * <summary>
         * Creates a new client based on a given configuration.</summary>
         *
         * <param name="id">Client identifier.</param>
         * <param name="cfg0">Client configuration.</param>
         * <exception cref="GridClientException">If client configuration is incorrect.</exception>
         * <exception cref="GridClientServerUnreachableException">If none of the servers specified in configuration can be reached.</exception>
         */
        public GridClientImpl(Guid id, IGridClientConfiguration cfg0)
        {
            Id = id;

            cfg = new GridClientConfiguration(cfg0);

            ICollection <IPEndPoint> srvs    = ParseServers(cfg.Servers);
            ICollection <IPEndPoint> routers = ParseServers(cfg.Routers);

            top = new GridClientTopology(id, cfg.IsTopologyCacheEnabled);

            Action <Object> addTopLsnr = o => {
                var lsnr = o as IGridClientTopologyListener;

                if (lsnr != null)
                {
                    top.AddTopologyListener(lsnr);
                }
            };

            // Add to topology as listeners.
            foreach (IGridClientDataConfiguration dataCfg in cfg.DataConfigurations)
            {
                addTopLsnr(dataCfg.Affinity);
            }

            addTopLsnr(cfg.Balancer);
            addTopLsnr(topUpdateBalancer);

            if (srvs.Count == 0)
            {
                // Use routers for initial connection.
                srvs = routers;
            }
            else
            {
                // Disable routers for connection manager.
                routers = new HashSet <IPEndPoint>();
            }

            connMgr = new GridClientConnectionManager(Id, top, routers, cfg.Credentials, cfg.Protocol, cfg.SslContext, cfg.ConnectTimeout);

            int retries = 3;

            while (true)
            {
                IGridClientConnection conn = null;

                try {
                    // Create connection to a server from the list of endpoints.
                    conn = connMgr.connection(srvs);

                    // Request topology at start to determine which node we connected to.
                    // Also this request validates TCP connection is alive.
                    conn.Topology(false, false, Guid.Empty).WaitDone();

                    break;
                }
                catch (GridClientAuthenticationException) {
                    if (conn != null)
                    {
                        conn.Close(false);
                    }

                    top.Dispose();

                    throw;
                }
                catch (GridClientException e) {
                    if (conn != null)
                    {
                        conn.Close(false);
                    }

                    if (retries-- <= 0)
                    {
                        top.Dispose();

                        throw new GridClientException("Failed to update grid topology.", e);
                    }
                }
            }

            IDictionary <String, GridClientCacheMode> overallCaches = new GridClientNullDictionary <String, GridClientCacheMode>();

            // Topology is now updated, so we can identify current connection.
            foreach (GridClientNodeImpl node in top.Nodes())
            {
                foreach (KeyValuePair <String, GridClientCacheMode> pair in node.Caches)
                {
                    overallCaches[pair.Key] = pair.Value;
                }
            }

            foreach (KeyValuePair <String, GridClientCacheMode> entry in overallCaches)
            {
                if (Affinity(entry.Key) is GridClientPartitionAffinity && entry.Value != GridClientCacheMode.Partitioned)
                {
                    Dbg.WriteLine(typeof(GridClientPartitionAffinity) + " is used for a cache configured " +
                                  "for non-partitioned mode [cacheName=" + entry.Key + ", cacheMode=" + entry.Value + ']');
                }
            }

            idleCheckThread = new Thread(checkIdle);

            idleCheckThread.Name = "grid-check-idle-worker--client#" + id;

            idleCheckThread.Start();

            topUpdateThread = new Thread(updateTopology);

            topUpdateThread.Name = "grid-topology-update-worker--client#" + id;

            topUpdateThread.Start();

            _compute = new GridClientComputeImpl(this, null, null, cfg.Balancer);

            Dbg.WriteLine("Client started. Id: " + Id);
        }