public ConnectionEntry createConnectionEntry( final Acceptor acceptorUsed, final Connection connection) { final Configuration config = server.getConfiguration(); Executor connectionExecutor = server.getExecutorFactory().getExecutor(); final CoreRemotingConnection rc = new RemotingConnectionImpl( connection, interceptors, config.isAsyncConnectionExecutionEnabled() ? connectionExecutor : null, server.getNodeID()); Channel channel1 = rc.getChannel(CHANNEL_ID.SESSION.id, -1); ChannelHandler handler = new HornetQPacketHandler(this, server, channel1, rc); channel1.setHandler(handler); long ttl = HornetQClient.DEFAULT_CONNECTION_TTL; if (config.getConnectionTTLOverride() != -1) { ttl = config.getConnectionTTLOverride(); } final ConnectionEntry entry = new ConnectionEntry(rc, connectionExecutor, System.currentTimeMillis(), ttl); final Channel channel0 = rc.getChannel(0, -1); channel0.setHandler(new LocalChannelHandler(config, entry, channel0, acceptorUsed, rc)); return entry; }
public void close() { if (closed) { return; } if (!connection.isDestroyed() && !connection.removeChannel(id)) { throw HornetQClientMessageBundle.BUNDLE.noChannelToClose(id); } if (failingOver) { unlock(); } closed = true; }
public void handlePacket(final Packet packet) { if (packet.getType() == PacketImpl.PACKETS_CONFIRMED) { if (resendCache != null) { final PacketsConfirmedMessage msg = (PacketsConfirmedMessage) packet; clearUpTo(msg.getCommandID()); } if (!connection.isClient()) { handler.handlePacket(packet); } return; } else { if (packet.isResponse()) { confirm(packet); lock.lock(); try { response = packet; sendCondition.signal(); } finally { lock.unlock(); } } else if (handler != null) { handler.handlePacket(packet); } } }
public void transferConnection(final CoreRemotingConnection newConnection) { // Needs to synchronize on the connection to make sure no packets from // the old connection get processed after transfer has occurred synchronized (connection.getTransferLock()) { connection.removeChannel(id); // And switch it final CoreRemotingConnection rnewConnection = newConnection; rnewConnection.putChannel(id, this); connection = rnewConnection; transferring = true; } }
public boolean supports(final byte packetType) { int version = connection.getClientVersion(); switch (packetType) { case PacketImpl.CLUSTER_TOPOLOGY_V2: return version >= 122; default: return true; } }
// This must never called by more than one thread concurrently public boolean send(final Packet packet, final boolean flush, final boolean batch) { if (invokeInterceptors(packet, interceptors, connection) != null) { return false; } synchronized (sendLock) { packet.setChannelID(id); if (isTrace) { HornetQClientLogger.LOGGER.trace( "Sending packet nonblocking " + packet + " on channeID=" + id); } HornetQBuffer buffer = packet.encode(connection); lock.lock(); try { if (failingOver) { // TODO - don't hardcode this timeout try { failoverCondition.await(10000, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { throw new HornetQInterruptedException(e); } } // Sanity check if (transferring) { throw new IllegalStateException("Cannot send a packet while channel is doing failover"); } if (resendCache != null && packet.isRequiresConfirmations()) { resendCache.add(packet); } } finally { lock.unlock(); } if (isTrace) { HornetQClientLogger.LOGGER.trace("Writing buffer for channelID=" + id); } // The actual send must be outside the lock, or with OIO transport, the write can block if the // tcp // buffer is full, preventing any incoming buffers being handled and blocking failover connection.getTransportConnection().write(buffer, flush, batch); return true; } }
@Override public synchronized void start() throws HornetQException { if (started) { throw new IllegalStateException("ReplicationManager is already started"); } replicatingChannel.setHandler(responseHandler); failureListener = new ReplicatedSessionFailureListener(); remotingConnection.addFailureListener(failureListener); started = true; enabled = true; }
public boolean supports(final byte packetType) { int version = connection.getClientVersion(); switch (packetType) { case PacketImpl.CLUSTER_TOPOLOGY_V2: return version >= 122; case PacketImpl.DISCONNECT_CONSUMER: return version >= 124; case PacketImpl.CLUSTER_TOPOLOGY_V3: return version >= 125; case PacketImpl.NODE_ANNOUNCE_V2: return version >= 125; case PacketImpl.DISCONNECT_V2: return version >= 125; default: return true; } }
private void doWrite(final Packet packet) { final HornetQBuffer buffer = packet.encode(connection); connection.getTransportConnection().write(buffer, false, false); }
/** * Due to networking issues or server issues the server may take longer to answer than expected.. * the client may timeout the call throwing an exception and the client could eventually retry * another call, but the server could then answer a previous command issuing a * class-cast-exception. The expectedPacket will be used to filter out undesirable packets that * would belong to previous calls. */ public Packet sendBlocking(final Packet packet, byte expectedPacket) throws HornetQException { String interceptionResult = invokeInterceptors(packet, interceptors, connection); if (interceptionResult != null) { // if we don't throw an exception here the client might not unblock throw HornetQClientMessageBundle.BUNDLE.interceptorRejectedPacket(interceptionResult); } if (closed) { throw HornetQClientMessageBundle.BUNDLE.connectionDestroyed(); } if (connection.getBlockingCallTimeout() == -1) { throw new IllegalStateException( "Cannot do a blocking call timeout on a server side connection"); } // Synchronized since can't be called concurrently by more than one thread and this can occur // E.g. blocking acknowledge() from inside a message handler at some time as other operation on // main thread synchronized (sendBlockingLock) { packet.setChannelID(id); final HornetQBuffer buffer = packet.encode(connection); lock.lock(); try { if (failingOver) { try { if (connection.getBlockingCallFailoverTimeout() < 0) { while (failingOver) { failoverCondition.await(); } } else { if (!failoverCondition.await( connection.getBlockingCallFailoverTimeout(), TimeUnit.MILLISECONDS)) { HornetQClientLogger.LOGGER.debug("timed-out waiting for failover condition"); } } } catch (InterruptedException e) { throw new HornetQInterruptedException(e); } } response = null; if (resendCache != null && packet.isRequiresConfirmations()) { resendCache.add(packet); } connection.getTransportConnection().write(buffer, false, false); long toWait = connection.getBlockingCallTimeout(); long start = System.currentTimeMillis(); while (!closed && (response == null || (response.getType() != PacketImpl.EXCEPTION && response.getType() != expectedPacket)) && toWait > 0) { try { sendCondition.await(toWait, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { throw new HornetQInterruptedException(e); } if (response != null && response.getType() != PacketImpl.EXCEPTION && response.getType() != expectedPacket) { HornetQClientLogger.LOGGER.packetOutOfOrder(response, new Exception("trace")); } if (closed) { break; } final long now = System.currentTimeMillis(); toWait -= now - start; start = now; } if (response == null) { throw HornetQClientMessageBundle.BUNDLE.timedOutSendingPacket(packet.getType()); } if (response.getType() == PacketImpl.EXCEPTION) { final HornetQExceptionMessage mem = (HornetQExceptionMessage) response; HornetQException e = mem.getException(); e.fillInStackTrace(); throw e; } } finally { lock.unlock(); } return response; } }
public void handlePacket(final Packet packet) { if (packet.getType() == PacketImpl.PING) { Ping ping = (Ping) packet; if (config.getConnectionTTLOverride() == -1) { // Allow clients to specify connection ttl entry.ttl = ping.getConnectionTTL(); } // Just send a ping back channel0.send(packet); } else if (packet.getType() == PacketImpl.SUBSCRIBE_TOPOLOGY || packet.getType() == PacketImpl.SUBSCRIBE_TOPOLOGY_V2) { SubscribeClusterTopologyUpdatesMessage msg = (SubscribeClusterTopologyUpdatesMessage) packet; if (packet.getType() == PacketImpl.SUBSCRIBE_TOPOLOGY_V2) { channel0 .getConnection() .setClientVersion( ((SubscribeClusterTopologyUpdatesMessageV2) msg).getClientVersion()); } final ClusterTopologyListener listener = new ClusterTopologyListener() { public void nodeUP( final long uniqueEventID, final String nodeID, final Pair<TransportConfiguration, TransportConfiguration> connectorPair, final boolean last) { // Using an executor as most of the notifications on the Topology // may come from a channel itself // What could cause deadlocks entry.connectionExecutor.execute( new Runnable() { public void run() { if (channel0.supports(PacketImpl.CLUSTER_TOPOLOGY_V2)) { channel0.send( new ClusterTopologyChangeMessage_V2( uniqueEventID, nodeID, connectorPair, last)); } else { channel0.send( new ClusterTopologyChangeMessage(nodeID, connectorPair, last)); } } }); } public void nodeDown(final long uniqueEventID, final String nodeID) { // Using an executor as most of the notifications on the Topology // may come from a channel itself // What could cause deadlocks entry.connectionExecutor.execute( new Runnable() { public void run() { if (channel0.supports(PacketImpl.CLUSTER_TOPOLOGY_V2)) { channel0.send(new ClusterTopologyChangeMessage_V2(uniqueEventID, nodeID)); } else { channel0.send(new ClusterTopologyChangeMessage(nodeID)); } } }); } @Override public String toString() { return "Remote Proxy on channel " + Integer.toHexString(System.identityHashCode(this)); } }; if (acceptorUsed.getClusterConnection() != null) { acceptorUsed.getClusterConnection().addClusterTopologyListener(listener); rc.addCloseListener( new CloseListener() { public void connectionClosed() { acceptorUsed.getClusterConnection().removeClusterTopologyListener(listener); } }); } else { // if not clustered, we send a single notification to the client containing the node-id // where the server is connected to // This is done this way so Recovery discovery could also use the node-id for // non-clustered setups entry.connectionExecutor.execute( new Runnable() { public void run() { String nodeId = server.getNodeID().toString(); Pair<TransportConfiguration, TransportConfiguration> emptyConfig = new Pair<TransportConfiguration, TransportConfiguration>(null, null); if (channel0.supports(PacketImpl.CLUSTER_TOPOLOGY_V2)) { channel0.send( new ClusterTopologyChangeMessage_V2( System.currentTimeMillis(), nodeId, emptyConfig, true)); } else { channel0.send(new ClusterTopologyChangeMessage(nodeId, emptyConfig, true)); } } }); } } else if (packet.getType() == PacketImpl.NODE_ANNOUNCE) { NodeAnnounceMessage msg = (NodeAnnounceMessage) packet; Pair<TransportConfiguration, TransportConfiguration> pair; if (msg.isBackup()) { pair = new Pair<TransportConfiguration, TransportConfiguration>(null, msg.getConnector()); } else { pair = new Pair<TransportConfiguration, TransportConfiguration>( msg.getConnector(), msg.getBackupConnector()); } if (isTrace) { HornetQLogger.LOGGER.trace( "Server " + server + " receiving nodeUp from NodeID=" + msg.getNodeID() + ", pair=" + pair); } if (acceptorUsed != null) { ClusterConnection clusterConn = acceptorUsed.getClusterConnection(); if (clusterConn != null) { clusterConn.nodeAnnounced( msg.getCurrentEventID(), msg.getNodeID(), pair, msg.isBackup()); } else { HornetQLogger.LOGGER.debug("Cluster connection is null on acceptor = " + acceptorUsed); } } else { HornetQLogger.LOGGER.debug( "there is no acceptor used configured at the CoreProtocolManager " + this); } } else if (packet.getType() == PacketImpl.BACKUP_REGISTRATION) { BackupRegistrationMessage msg = (BackupRegistrationMessage) packet; ClusterConnection clusterConnection = acceptorUsed.getClusterConnection(); if (clusterConnection.verify(msg.getClusterUser(), msg.getClusterPassword())) { try { server.startReplication( rc, clusterConnection, getPair(msg.getConnector(), true), msg.isFailBackRequest()); } catch (HornetQException e) { channel0.send(new BackupRegistrationFailedMessage(e)); } } else { channel0.send(new BackupRegistrationFailedMessage(null)); } } }
/** @param liveConnection */ public void addAsFailureListenerOf(CoreRemotingConnection liveConnection) { this.connection = liveConnection; connection.addFailureListener(this); // connection.addCloseListener(this); }
private void removeListener() { if (connection == null) return; connection.removeFailureListener(this); }
/** @param remotingConnection */ public ReplicationManager( CoreRemotingConnection remotingConnection, final ExecutorFactory executorFactory) { this.executorFactory = executorFactory; this.replicatingChannel = remotingConnection.getChannel(CHANNEL_ID.REPLICATION.id, -1); this.remotingConnection = remotingConnection; }