/**
   * @throws Exception
   * @throws URISyntaxException
   */
  private void startClient() throws Exception, URISyntaxException {
    clientTransport =
        TransportFactory.connect(
            new URI(
                "tcp://localhost:"
                    + serverPort
                    + "?trace=true&wireFormat.maxInactivityDuration=1000"));
    clientTransport.setTransportListener(
        new TransportListener() {
          public void onCommand(Object command) {
            clientReceiveCount.incrementAndGet();
            if (clientRunOnCommand != null) {
              clientRunOnCommand.run();
            }
          }

          public void onException(IOException error) {
            if (!ignoreClientError.get()) {
              LOG.info("Client transport error:");
              error.printStackTrace();
              clientErrorCount.incrementAndGet();
            }
          }

          public void transportInterupted() {}

          public void transportResumed() {}
        });
    clientTransport.start();
  }
  public void onAccept(Transport transport) {
    try {
      LOG.info("[" + getName() + "] Server Accepted a Connection");
      serverTransport = transport;
      serverTransport.setTransportListener(
          new TransportListener() {
            public void onCommand(Object command) {
              serverReceiveCount.incrementAndGet();
              if (serverRunOnCommand != null) {
                serverRunOnCommand.run();
              }
            }

            public void onException(IOException error) {
              if (!ignoreClientError.get()) {
                LOG.info("Server transport error:", error);
                serverErrorCount.incrementAndGet();
              }
            }

            public void transportInterupted() {}

            public void transportResumed() {}
          });
      serverTransport.start();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  protected Transport createTransport() throws Exception {
    Transport transport =
        TransportFactory.connect(
            new URI("failover://(tcp://localhost:1234?transport.connectTimeout=10000)"));
    transport.setTransportListener(
        new TransportListener() {

          @Override
          public void onCommand(Object command) {}

          @Override
          public void onException(IOException error) {}

          @Override
          public void transportInterupted() {}

          @Override
          public void transportResumed() {}
        });
    transport.start();

    this.failoverTransport = transport.narrow(FailoverTransport.class);

    return transport;
  }
  @Test
  public void testLocalhostPortSyntax() throws Exception {
    transport =
        TransportFactory.connect(new URI("failover://(tcp://localhost:1111/localhost:2111)"));

    transport.setTransportListener(
        new TransportListener() {

          @Override
          public void onCommand(Object command) {}

          @Override
          public void onException(IOException error) {}

          @Override
          public void transportInterupted() {}

          @Override
          public void transportResumed() {}
        });

    failoverTransport = transport.narrow(FailoverTransport.class);

    transport.start();
  }
  public void testClientHang() throws Exception {

    //
    // Manually create a client transport so that it does not send KeepAlive
    // packets.
    // this should simulate a client hang.
    clientTransport =
        new TcpTransport(
            new OpenWireFormat(),
            SocketFactory.getDefault(),
            new URI("tcp://localhost:" + serverPort),
            null);
    clientTransport.setTransportListener(
        new TransportListener() {
          public void onCommand(Object command) {
            clientReceiveCount.incrementAndGet();
            if (clientRunOnCommand != null) {
              clientRunOnCommand.run();
            }
          }

          public void onException(IOException error) {
            if (!ignoreClientError.get()) {
              LOG.info("Client transport error:");
              error.printStackTrace();
              clientErrorCount.incrementAndGet();
            }
          }

          public void transportInterupted() {}

          public void transportResumed() {}
        });
    clientTransport.start();
    WireFormatInfo info = new WireFormatInfo();
    info.setVersion(OpenWireFormat.DEFAULT_VERSION);
    info.setMaxInactivityDuration(1000);
    clientTransport.oneway(info);

    assertEquals(0, serverErrorCount.get());
    assertEquals(0, clientErrorCount.get());

    // Server should consider the client timed out right away since the
    // client is not hart beating fast enough.
    Thread.sleep(6000);

    assertEquals(0, clientErrorCount.get());
    assertTrue(serverErrorCount.get() > 0);
  }
    @Override
    public void onException(IOException error) {
      try {
        synchronized (reconnectMutex) {
          if (transport == null || !transport.isConnected()) {
            return;
          }

          LOG.debug("Transport failed, starting up reconnect task", error);

          ServiceSupport.dispose(transport);
          transport = null;
          connectedCount--;
          if (primary == this) {
            primary = null;
          }
          reconnectTask.wakeup();
        }
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        if (transportListener != null) {
          transportListener.onException(new InterruptedIOException());
        }
      }
    }
 protected void tearDown() throws Exception {
   ignoreClientError.set(true);
   ignoreServerError.set(true);
   try {
     if (clientTransport != null) {
       clientTransport.stop();
     }
     if (serverTransport != null) {
       serverTransport.stop();
     }
     if (server != null) {
       server.stop();
     }
   } catch (Throwable e) {
     e.printStackTrace();
   }
   super.tearDown();
 }
  @Test(timeout = 30000)
  @Ignore("Test fails on windows")
  public void testReconnectUnlimited() throws Exception {

    Transport transport =
        TransportFactory.connect(
            new URI(
                "failover://(tcp://0.0.0.0:61616)?useExponentialBackOff=false&reconnectDelay=0&initialReconnectDelay=0"));

    transport.setTransportListener(
        new TransportListener() {

          @Override
          public void onCommand(Object command) {}

          @Override
          public void onException(IOException error) {}

          @Override
          public void transportInterupted() {}

          @Override
          public void transportResumed() {}
        });
    transport.start();

    this.failoverTransport = transport.narrow(FailoverTransport.class);

    assertTrue(
        "no implicit limit of 1000",
        Wait.waitFor(
            new Wait.Condition() {
              @Override
              public boolean isSatisified() throws Exception {
                return failoverTransport.getConnectFailures() > 1002;
              }
            }));
  }
  @Override
  protected void doStart() throws Exception {
    input.setTransportListener(
        new DefaultTransportListener() {
          @Override
          public void onCommand(Object command) {
            try {
              process((Command) command);
            } catch (Throwable error) {
              onFailure(error);
            }
          }

          @Override
          public void onException(IOException error) {
            onFailure(error);
          }
        });

    this.input.start();
  }
 protected void doStop(ServiceStopper serviceStopper) throws Exception {
   input.stop();
 }
 public void oneway(Object message) throws IOException {
   input.oneway(message);
 }
 @Override
 public int getReceiveCounter() {
   return input.getReceiveCounter();
 }
 @Override
 public String getRemoteAddress() {
   return input.getRemoteAddress();
 }
 @After
 public void tearDown() throws Exception {
   if (transport != null) {
     transport.stop();
   }
 }
  /** @return */
  private boolean doConnect() {
    long closestReconnectDate = 0;
    synchronized (reconnectMutex) {
      if (disposed || connectionFailure != null) {
        reconnectMutex.notifyAll();
      }

      if (transports.size() == connectedCount || disposed || connectionFailure != null) {
        return false;
      } else {

        if (transports.isEmpty()) {
          // connectionFailure = new IOException("No uris available to
          // connect to.");
        } else {

          // Try to connect them up.
          Iterator<FanoutTransportHandler> iter = transports.iterator();
          for (int i = 0; iter.hasNext() && !disposed; i++) {

            long now = System.currentTimeMillis();

            FanoutTransportHandler fanoutHandler = iter.next();
            if (fanoutHandler.transport != null) {
              continue;
            }

            // Are we waiting a little to try to reconnect this one?
            if (fanoutHandler.reconnectDate != 0 && fanoutHandler.reconnectDate > now) {
              if (closestReconnectDate == 0 || fanoutHandler.reconnectDate < closestReconnectDate) {
                closestReconnectDate = fanoutHandler.reconnectDate;
              }
              continue;
            }

            URI uri = fanoutHandler.uri;
            try {
              LOG.debug("Stopped: " + this);
              LOG.debug("Attempting connect to: " + uri);
              Transport t = TransportFactory.compositeConnect(uri);
              fanoutHandler.transport = t;
              t.setTransportListener(fanoutHandler);
              if (started) {
                restoreTransport(fanoutHandler);
              }
              LOG.debug("Connection established");
              fanoutHandler.reconnectDelay = initialReconnectDelay;
              fanoutHandler.connectFailures = 0;
              if (primary == null) {
                primary = fanoutHandler;
              }
              connectedCount++;
            } catch (Exception e) {
              LOG.debug("Connect fail to: " + uri + ", reason: " + e);

              if (fanoutHandler.transport != null) {
                ServiceSupport.dispose(fanoutHandler.transport);
                fanoutHandler.transport = null;
              }

              if (maxReconnectAttempts > 0
                  && ++fanoutHandler.connectFailures >= maxReconnectAttempts) {
                LOG.error(
                    "Failed to connect to transport after: "
                        + fanoutHandler.connectFailures
                        + " attempt(s)");
                connectionFailure = e;
                reconnectMutex.notifyAll();
                return false;
              } else {

                if (useExponentialBackOff) {
                  // Exponential increment of reconnect delay.
                  fanoutHandler.reconnectDelay *= backOffMultiplier;
                  if (fanoutHandler.reconnectDelay > maxReconnectDelay) {
                    fanoutHandler.reconnectDelay = maxReconnectDelay;
                  }
                }

                fanoutHandler.reconnectDate = now + fanoutHandler.reconnectDelay;

                if (closestReconnectDate == 0
                    || fanoutHandler.reconnectDate < closestReconnectDate) {
                  closestReconnectDate = fanoutHandler.reconnectDate;
                }
              }
            }
          }
          if (transports.size() == connectedCount || disposed) {
            reconnectMutex.notifyAll();
            return false;
          }
        }
      }
    }

    try {
      long reconnectDelay = closestReconnectDate - System.currentTimeMillis();
      if (reconnectDelay > 0) {
        LOG.debug("Waiting " + reconnectDelay + " ms before attempting connection. ");
        Thread.sleep(reconnectDelay);
      }
    } catch (InterruptedException e1) {
      Thread.currentThread().interrupt();
    }
    return true;
  }