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;
  }
Example #2
0
  public void close() {
    if (closed) {
      return;
    }

    if (!connection.isDestroyed() && !connection.removeChannel(id)) {
      throw HornetQClientMessageBundle.BUNDLE.noChannelToClose(id);
    }

    if (failingOver) {
      unlock();
    }
    closed = true;
  }
Example #3
0
  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);
      }
    }
  }
Example #4
0
  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;
    }
  }
Example #5
0
  public boolean supports(final byte packetType) {
    int version = connection.getClientVersion();

    switch (packetType) {
      case PacketImpl.CLUSTER_TOPOLOGY_V2:
        return version >= 122;
      default:
        return true;
    }
  }
Example #6
0
  // 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;
  }
Example #8
0
  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;
    }
  }
Example #9
0
  private void doWrite(final Packet packet) {
    final HornetQBuffer buffer = packet.encode(connection);

    connection.getTransportConnection().write(buffer, false, false);
  }
Example #10
0
  /**
   * 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));
        }
      }
    }
Example #12
0
 /** @param liveConnection */
 public void addAsFailureListenerOf(CoreRemotingConnection liveConnection) {
   this.connection = liveConnection;
   connection.addFailureListener(this);
   // connection.addCloseListener(this);
 }
Example #13
0
 private void removeListener() {
   if (connection == null) return;
   connection.removeFailureListener(this);
 }
Example #14
0
 /** @param remotingConnection */
 public ReplicationManager(
     CoreRemotingConnection remotingConnection, final ExecutorFactory executorFactory) {
   this.executorFactory = executorFactory;
   this.replicatingChannel = remotingConnection.getChannel(CHANNEL_ID.REPLICATION.id, -1);
   this.remotingConnection = remotingConnection;
 }