/** * Closes all opened connections. * * @param waitCompletion If {@code true} waits for all pending requests to be proceeded. */ @SuppressWarnings("TooBroadScope") @Override public void stop(boolean waitCompletion) { Collection<GridClientConnection> closeConns; if (closed) return; // Mark manager as closed. closed = true; // Remove all connections from cache. closeConns = new ArrayList<>(conns.values()); conns.clear(); nodeConns.clear(); // Close old connection outside the writer lock. for (GridClientConnection conn : closeConns) conn.close(CLIENT_CLOSED, waitCompletion); if (pingExecutor != null) GridClientUtils.shutdownNow(GridClientConnectionManager.class, pingExecutor, log); GridClientUtils.shutdownNow(GridClientConnectionManager.class, executor, log); if (srv != null) srv.stop(); }
/** * Returns connection to one of the given addresses. * * @param nodeId {@code UUID} of node for mapping with connection. {@code null} if no need of * mapping. * @param srvs Collection of addresses to connect to. * @return Connection to use for operations, targeted for the given node. * @throws GridServerUnreachableException If connection can't be established. * @throws GridClientClosedException If connections manager has been closed already. * @throws InterruptedException If connection was interrupted. */ public GridClientConnection connection(@Nullable UUID nodeId, Collection<InetSocketAddress> srvs) throws GridServerUnreachableException, GridClientClosedException, InterruptedException { if (srvs == null || srvs.isEmpty()) throw new GridServerUnreachableException( "Failed to establish connection to the grid" + " (address list is empty)."); checkClosed(); // Search for existent connection. for (InetSocketAddress endPoint : srvs) { assert endPoint != null; GridClientConnection conn = conns.get(endPoint); if (conn == null) continue; // Ignore closed connections. if (conn.closeIfIdle(cfg.getMaxConnectionIdleTime())) { closeIdle(); continue; } if (nodeId != null) nodeConns.put(nodeId, conn); return conn; } return connect(nodeId, srvs); }
/** {@inheritDoc} */ @Override public void terminateConnection(GridClientConnection conn, GridClientNode node, Throwable e) { if (log.isLoggable(Level.FINE)) log.fine( "Connection with remote node was terminated [node=" + node + ", srvAddr=" + conn.serverAddress() + ", errMsg=" + e.getMessage() + ']'); closeIdle(); conn.close(FAILED, false); }
/** * Gets active communication facade. * * @param node Remote node to which connection should be established. * @throws GridServerUnreachableException If none of the servers can be reached after the * exception. * @throws GridClientClosedException If client was closed manually. * @throws InterruptedException If connection was interrupted. */ @Override public GridClientConnection connection(GridClientNode node) throws GridClientClosedException, GridServerUnreachableException, InterruptedException { assert node != null; // Use router's connections if defined. if (!routers.isEmpty()) return connection(null, routers); GridClientConnection conn = nodeConns.get(node.nodeId()); if (conn != null) { // Ignore closed connections. if (conn.closeIfIdle(cfg.getMaxConnectionIdleTime())) closeIdle(); else return conn; } // Use node's connection, if node is available over rest. Collection<InetSocketAddress> endpoints = node.availableAddresses(cfg.getProtocol(), true); List<InetSocketAddress> resolvedEndpoints = new ArrayList<>(endpoints.size()); for (InetSocketAddress endpoint : endpoints) if (!endpoint.isUnresolved()) resolvedEndpoints.add(endpoint); if (resolvedEndpoints.isEmpty()) { throw new GridServerUnreachableException( "No available endpoints to connect " + "(is rest enabled for this node?): " + node); } boolean sameHost = node.attributes().isEmpty() || F.containsAny(U.allLocalMACs(), node.attribute(ATTR_MACS).toString().split(", ")); Collection<InetSocketAddress> srvs = new LinkedHashSet<>(); if (sameHost) { Collections.sort(resolvedEndpoints, U.inetAddressesComparator(true)); srvs.addAll(resolvedEndpoints); } else { for (InetSocketAddress endpoint : resolvedEndpoints) if (!endpoint.getAddress().isLoopbackAddress()) srvs.add(endpoint); } return connection(node.nodeId(), srvs); }
/** {@inheritDoc} */ @SuppressWarnings("BusyWait") @Override public void init(Collection<InetSocketAddress> srvs) throws GridClientException, InterruptedException { init0(); GridClientException firstEx = null; for (int i = 0; i < INIT_RETRY_CNT; i++) { Collection<InetSocketAddress> srvsCp = new ArrayList<>(srvs); while (!srvsCp.isEmpty()) { GridClientConnection conn = null; try { conn = connect(null, srvsCp); conn.topology(cfg.isAutoFetchAttributes(), cfg.isAutoFetchMetrics(), null).get(); return; } catch (GridServerUnreachableException e) { // No connection could be opened to any of initial addresses - exit to retry loop. assert conn == null : "GridClientConnectionResetException was thrown from GridClientConnection#topology"; if (firstEx == null) firstEx = e; break; } catch (GridClientConnectionResetException e) { // Connection was established but topology update failed - // trying other initial addresses if any. assert conn != null : "GridClientConnectionResetException was thrown from connect()"; if (firstEx == null) firstEx = e; if (!srvsCp.remove(conn.serverAddress())) // We have misbehaving collection or equals - just exit to avoid infinite loop. break; } } Thread.sleep(INIT_RETRY_INTERVAL); } for (GridClientConnection c : conns.values()) { conns.remove(c.serverAddress(), c); c.close(FAILED, false); } throw firstEx; }
/** * Close all connections idling for more then {@link * GridClientConfiguration#getMaxConnectionIdleTime()} milliseconds. */ @SuppressWarnings("ForLoopReplaceableByForEach") private void closeIdle() { for (Iterator<Map.Entry<UUID, GridClientConnection>> it = nodeConns.entrySet().iterator(); it.hasNext(); ) { Map.Entry<UUID, GridClientConnection> entry = it.next(); GridClientConnection conn = entry.getValue(); if (conn.closeIfIdle(cfg.getMaxConnectionIdleTime())) { conns.remove(conn.serverAddress(), conn); nodeConns.remove(entry.getKey(), conn); } } for (GridClientConnection conn : conns.values()) if (conn.closeIfIdle(cfg.getMaxConnectionIdleTime())) conns.remove(conn.serverAddress(), conn); }
/** * Create new connection to specified server. * * @param nodeId {@code UUID} of node for mapping with connection. {@code null} if no need of * mapping. * @param addr Remote socket to connect. * @return Established connection. * @throws IOException If connection failed. * @throws GridClientException If protocol error happened. * @throws InterruptedException If thread was interrupted before connection was established. */ protected GridClientConnection connect(@Nullable UUID nodeId, InetSocketAddress addr) throws IOException, GridClientException, InterruptedException { endpointStripedLock.lock(addr); try { GridClientConnection old = conns.get(addr); if (old != null) { if (old.isClosed()) { conns.remove(addr, old); if (nodeId != null) nodeConns.remove(nodeId, old); } else { if (nodeId != null) nodeConns.put(nodeId, old); return old; } } SecurityCredentials cred = null; try { if (cfg.getSecurityCredentialsProvider() != null) cred = cfg.getSecurityCredentialsProvider().credentials(); } catch (IgniteCheckedException e) { throw new GridClientException("Failed to obtain client credentials.", e); } GridClientConnection conn; if (cfg.getProtocol() == GridClientProtocol.TCP) { conn = new GridClientNioTcpConnection( srv, clientId, addr, sslCtx, pingExecutor, cfg.getConnectTimeout(), cfg.getPingInterval(), cfg.getPingTimeout(), cfg.isTcpNoDelay(), cfg.getMarshaller(), marshId, top, cred, keepPortablesThreadLocal()); } else throw new GridServerUnreachableException( "Failed to create client (protocol is not supported): " + cfg.getProtocol()); old = conns.putIfAbsent(addr, conn); assert old == null; if (nodeId != null) nodeConns.put(nodeId, conn); return conn; } finally { endpointStripedLock.unlock(addr); } }