private Object authenticate( ClientConnection connection, Credentials credentials, ClientPrincipal principal, boolean firstConnection) throws IOException { final SerializationService ss = getSerializationService(); AuthenticationRequest auth = new AuthenticationRequest(credentials, principal); connection.init(); auth.setOwnerConnection(firstConnection); // contains remoteAddress and principal SerializableCollection collectionWrapper; try { collectionWrapper = (SerializableCollection) sendAndReceive(auth, connection); } catch (Exception e) { throw new RetryableIOException(e); } final Iterator<Data> iter = collectionWrapper.iterator(); if (iter.hasNext()) { final Data addressData = iter.next(); final Address address = ss.toObject(addressData); connection.setRemoteEndpoint(address); if (iter.hasNext()) { final Data principalData = iter.next(); return ss.toObject(principalData); } } throw new AuthenticationException(); }
void shutdown() { interrupt(); final ClientConnection c = conn; if (c != null) { c.close(); } }
@Override public void onConnectionClose(ClientConnection clientConnection) { Address endpoint = clientConnection.getRemoteEndpoint(); if (endpoint != null) { connections.remove(clientConnection.getRemoteEndpoint()); ownerConnectionFuture.closeIfAddressMatches(endpoint); } }
private void closeIfAddressMatches(Address address) { final ClientConnection currentOwnerConnection = ownerConnection; if (currentOwnerConnection == null || !currentOwnerConnection.live()) { return; } if (address.equals(currentOwnerConnection.getRemoteEndpoint())) { close(); } }
private void process(ClientPacket packet) { final ClientConnection conn = packet.getClientConnection(); try { handleClientMessage(packet.getClientMessage()); } catch (Exception e) { logger.severe("Failed to process task: " + packet + " on responseThread :" + getName(), e); } finally { conn.decrementPacketCount(); } }
@Override public boolean removeEventHandler(Integer callId) { if (callId != null) { for (ClientConnection clientConnection : connections.values()) { if (clientConnection.deRegisterEventHandler(callId) != null) { return true; } } } return false; }
@Override public void handlePacket(Packet packet) { final ClientConnection conn = (ClientConnection) packet.getConn(); conn.incrementPacketCount(); if (packet.isHeaderSet(Packet.HEADER_EVENT)) { final ClientListenerServiceImpl listenerService = (ClientListenerServiceImpl) client.getListenerService(); listenerService.handleEventPacket(packet); } else { invocationService.handlePacket(packet); } }
@Override public ClientConnection call() throws Exception { if (!live) { throw new HazelcastException("ConnectionManager is not active!!!"); } SocketChannel socketChannel = null; try { socketChannel = SocketChannel.open(); Socket socket = socketChannel.socket(); socket.setKeepAlive(socketOptions.isKeepAlive()); socket.setTcpNoDelay(socketOptions.isTcpNoDelay()); socket.setReuseAddress(socketOptions.isReuseAddress()); if (socketOptions.getLingerSeconds() > 0) { socket.setSoLinger(true, socketOptions.getLingerSeconds()); } int bufferSize = socketOptions.getBufferSize() * KILO_BYTE; if (bufferSize < 0) { bufferSize = DEFAULT_BUFFER_SIZE_BYTE; } socket.setSendBufferSize(bufferSize); socket.setReceiveBufferSize(bufferSize); socketChannel.socket().connect(address.getInetSocketAddress(), connectionTimeout); SocketChannelWrapper socketChannelWrapper = socketChannelWrapperFactory.wrapSocketChannel(socketChannel, true); final ClientConnection clientConnection = new ClientConnection( ClientConnectionManagerImpl.this, inSelector, outSelector, connectionIdGen.incrementAndGet(), socketChannelWrapper, executionService, invocationService, client.getSerializationService()); socketChannel.configureBlocking(true); if (socketInterceptor != null) { socketInterceptor.onConnect(socket); } authenticator.auth(clientConnection); socketChannel.configureBlocking(isBlock); socket.setSoTimeout(0); if (!isBlock) { clientConnection.getReadHandler().register(); } return clientConnection; } catch (Exception e) { if (socketChannel != null) { socketChannel.close(); } throw ExceptionUtil.rethrow(e); } }
@Override public synchronized void shutdown() { if (!live) { return; } live = false; for (ClientConnection connection : connections.values()) { connection.close(); } inSelector.shutdown(); outSelector.shutdown(); connectionLockMap.clear(); }
@Override public Object sendAndReceive(ClientRequest request, ClientConnection connection) throws Exception { final SerializationService ss = client.getSerializationService(); connection.write(ss.toData(request)); final Data data = connection.read(); ClientResponse clientResponse = ss.toObject(data); Object response = ss.toObject(clientResponse.getResponse()); if (response instanceof Throwable) { Throwable t = (Throwable) response; ExceptionUtil.fixRemoteStackTrace(t, Thread.currentThread().getStackTrace()); throw new Exception(t); } return response; }
public void run() { if (!live) { return; } final long now = Clock.currentTimeMillis(); for (ClientConnection connection : connections.values()) { if (now - connection.lastReadTime() > heartBeatTimeout) { connection.heartBeatingFailed(); } if (now - connection.lastReadTime() > heartBeatInterval) { final ClientPingRequest request = new ClientPingRequest(); invocationService.send(request, connection); } else { connection.heartBeatingSucceed(); } } }
private void waitForPacketsProcessed() { final long begin = System.currentTimeMillis(); int count = connection.getPacketCount(); while (count != 0) { try { Thread.sleep(WAIT_TIME_FOR_PACKETS_TO_BE_CONSUMED); } catch (InterruptedException e) { logger.warning(e); break; } long elapsed = System.currentTimeMillis() - begin; if (elapsed > WAIT_TIME_FOR_PACKETS_TO_BE_CONSUMED_THRESHOLD) { logger.warning("There are packets which are not processed " + count); break; } count = connection.getPacketCount(); } }
boolean isConnectionHealthy(long elapsed) { if (elapsed >= heartBeatInterval) { if (sendConnection != null) { return sendConnection.isHeartBeating(); } else { return true; } } return true; }
public void cleanResources( ConstructorFunction<Object, Throwable> responseCtor, ClientConnection connection) { final Iterator<Map.Entry<Integer, ClientInvocation>> iter = callIdMap.entrySet().iterator(); while (iter.hasNext()) { final Map.Entry<Integer, ClientInvocation> entry = iter.next(); final ClientInvocation invocation = entry.getValue(); if (connection.equals(invocation.getSendConnection())) { iter.remove(); invocation.notifyException(responseCtor.createNew(null)); eventHandlerMap.remove(entry.getKey()); } } final Iterator<ClientListenerInvocation> iterator = eventHandlerMap.values().iterator(); while (iterator.hasNext()) { final ClientInvocation invocation = iterator.next(); if (connection.equals(invocation.getSendConnection())) { iterator.remove(); invocation.notifyException(responseCtor.createNew(null)); } } }
private ClientConnection getOrConnect(Address target, Authenticator authenticator) throws Exception { if (!smartRouting) { target = ownerConnectionFuture.getOrWaitForCreation().getEndPoint(); } Address address = addressTranslator.translate(target); if (address == null) { throw new IOException("Address is required!"); } ClientConnection clientConnection = connections.get(address); if (clientConnection == null) { final Object lock = getLock(address); synchronized (lock) { clientConnection = connections.get(address); if (clientConnection == null) { final ConnectionProcessor connectionProcessor = new ConnectionProcessor(address, authenticator, false); final ICompletableFuture<ClientConnection> future = executionService.submitInternal(connectionProcessor); try { clientConnection = future.get(connectionTimeout, TimeUnit.MILLISECONDS); } catch (Exception e) { future.cancel(true); throw new RetryableIOException(e); } ClientConnection current = connections.putIfAbsent(address, clientConnection); if (current != null) { clientConnection.close(); clientConnection = current; } } } } return clientConnection; }
private void listenMembershipEvents() throws IOException { final SerializationService serializationService = clusterService.getSerializationService(); while (!Thread.currentThread().isInterrupted()) { final Data clientResponseData = conn.read(); final ClientResponse clientResponse = serializationService.toObject(clientResponseData); final Object eventObject = serializationService.toObject(clientResponse.getResponse()); final ClientMembershipEvent event = (ClientMembershipEvent) eventObject; final MemberImpl member = (MemberImpl) event.getMember(); boolean membersUpdated = false; if (event.getEventType() == MembershipEvent.MEMBER_ADDED) { members.add(member); membersUpdated = true; } else if (event.getEventType() == ClientMembershipEvent.MEMBER_REMOVED) { members.remove(member); membersUpdated = true; // getConnectionManager().removeConnectionPool(member.getAddress()); // //TODO } else if (event.getEventType() == ClientMembershipEvent.MEMBER_ATTRIBUTE_CHANGED) { MemberAttributeChange memberAttributeChange = event.getMemberAttributeChange(); Map<Address, MemberImpl> memberMap = clusterService.getMembersRef(); if (memberMap != null) { for (MemberImpl target : memberMap.values()) { if (target.getUuid().equals(memberAttributeChange.getUuid())) { final MemberAttributeOperationType operationType = memberAttributeChange.getOperationType(); final String key = memberAttributeChange.getKey(); final Object value = memberAttributeChange.getValue(); target.updateAttribute(operationType, key, value); MemberAttributeEvent memberAttributeEvent = new MemberAttributeEvent(client.getCluster(), target, operationType, key, value); clusterService.fireMemberAttributeEvent(memberAttributeEvent); break; } } } } if (membersUpdated) { ((ClientPartitionServiceImpl) client.getClientPartitionService()).refreshPartitions(); updateMembersRef(); LOGGER.info(clusterService.membersString()); clusterService.fireMembershipEvent( new MembershipEvent( client.getCluster(), member, event.getEventType(), Collections.unmodifiableSet(new LinkedHashSet<Member>(members)))); } } }
@Override public void onDetectingUnresponsiveConnection(ClientConnection connection) { if (smartRouting) { // closing the owner connection if unresponsive so that it can be switched to a healthy one. ownerConnectionFuture.closeIfAddressMatches(connection.getEndPoint()); // we do not close connection itself since we will continue to send heartbeat ping to this // connection. // IOUtil.closeResource(connection); return; } // close both owner and operation connection ownerConnectionFuture.close(); IOUtil.closeResource(connection); }
protected void send(ClientInvocation invocation, ClientConnection connection) throws IOException { if (isShutdown) { throw new HazelcastClientNotActiveException("Client is shut down"); } registerInvocation(invocation); ClientMessage clientMessage = invocation.getClientMessage(); if (!isAllowedToSendRequest(connection, invocation) || !writeToConnection(connection, clientMessage)) { final int callId = clientMessage.getCorrelationId(); deRegisterCallId(callId); deRegisterEventHandler(callId); throw new IOException("Packet not send to " + connection.getRemoteEndpoint()); } invocation.setSendConnection(connection); }
@Override public void run() { try { int correlationId = clientMessage.getCorrelationId(); final EventHandler eventHandler = eventHandlerMap.get(correlationId); if (eventHandler == null) { logger.warning( "No eventHandler for callId: " + correlationId + ", event: " + clientMessage); return; } eventHandler.handle(clientMessage); } finally { connection.decrementPendingPacketCount(); } }
private boolean isAllowedToSendRequest(ClientConnection connection, ClientInvocation invocation) { if (!connection.isHeartBeating()) { if (invocation.shouldBypassHeartbeatCheck()) { // ping and removeAllListeners should be send even though heart is not beating return true; } if (logger.isFinestEnabled()) { logger.warning( "Connection is not heart-beating, won't write client message -> " + invocation.getClientMessage()); } return false; } return true; }
protected void send(ClientInvocation invocation, ClientConnection connection) throws IOException { if (isShutdown) { throw new HazelcastClientNotActiveException("Client is shut down"); } registerInvocation(invocation); ClientMessage clientMessage = invocation.getClientMessage(); if (!isAllowedToSendRequest(connection, invocation) || !writeToConnection(connection, clientMessage)) { final int callId = clientMessage.getCorrelationId(); ClientInvocation clientInvocation = deRegisterCallId(callId); deRegisterEventHandler(callId); if (clientInvocation != null) { throw new IOException("Packet not send to " + connection.getRemoteEndpoint()); } else { if (logger.isFinestEnabled()) { logger.finest("Invocation not found to deregister for call id " + callId); } } } invocation.setSendConnection(connection); }
public void removeEndpoint(Address address) { final ClientConnection clientConnection = connections.get(address); if (clientConnection != null) { clientConnection.close(); } }
private boolean writeToConnection(ClientConnection connection, ClientMessage clientMessage) { clientMessage.addFlag(ClientMessage.BEGIN_AND_END_FLAGS); return connection.write(clientMessage); }