Beispiel #1
0
  public void testFlushWithCrashedParticipants() throws Exception {
    JChannel c1 = null;
    JChannel c2 = null;
    JChannel c3 = null;

    try {
      c1 = createChannel(true, 3, "C1");
      changeProps(c1);
      c1.connect("testFlushWithCrashedFlushCoordinator");

      c2 = createChannel(c1, "C2");
      changeProps(c2);
      c2.connect("testFlushWithCrashedFlushCoordinator");

      c3 = createChannel(c1, "C3");
      changeProps(c3);
      c3.connect("testFlushWithCrashedFlushCoordinator");

      // and then kill members other than flush coordinator
      Util.shutdown(c3);
      Util.shutdown(c1);

      // start flush
      Util.startFlush(c2);

      c2.stopFlush();
      Util.waitUntilAllChannelsHaveSameSize(10000, 500, c2);

      // cluster should not hang and one remaining member should have a correct view
      assertTrue("correct view size", c2.getView().size() == 1);
    } finally {
      Util.close(c3, c2, c1);
    }
  }
Beispiel #2
0
  /**
   * Connects this channel to a group and gets a state from a specified state provider.
   *
   * <p>This method invokes {@code connect()} and then {@code getState}.
   *
   * <p>If the FLUSH protocol is in the channel's stack definition, only one flush round is executed
   * for both connecting and fetching the state rather than two flushes if we invoke {@code connect}
   * and {@code getState} in succession.
   *
   * <p>If the channel is already connected, an error message will be printed to the error log. If
   * the channel is closed a ChannelClosed exception will be thrown.
   *
   * @param cluster_name The cluster name to connect to. Cannot be null.
   * @param target The state provider. If null, the state will be fetched from the coordinator,
   *     unless this channel is the coordinator.
   * @param timeout The timeout for the state transfer.
   * @exception Exception The protocol stack cannot be started, or the JOIN failed
   * @exception IllegalStateException The channel is closed or disconnected
   * @exception StateTransferException State transfer was not successful
   */
  public synchronized void connect(
      String cluster_name, Address target, long timeout, boolean useFlushIfPresent)
      throws Exception {
    if (!_preConnect(cluster_name)) return;

    if (cluster_name == null) { // only connect if we are not a unicast channel
      state = State.CONNECTED;
      return;
    }

    boolean canFetchState = false;
    try {
      Event connect_event =
          useFlushIfPresent
              ? new Event(Event.CONNECT_WITH_STATE_TRANSFER_USE_FLUSH, cluster_name)
              : new Event(Event.CONNECT_WITH_STATE_TRANSFER, cluster_name);
      _connect(connect_event);
      state = State.CONNECTED;
      notifyChannelConnected(this);
      canFetchState = getView() != null && getView().size() > 1;

      // if I am not the only member in cluster then
      if (canFetchState) getState(target, timeout, false); // fetch state from target
    } finally {
      // stopFlush if we fetched the state or failed to connect...
      if ((flushSupported() && useFlushIfPresent) && (canFetchState || state != State.CONNECTED))
        stopFlush();
    }
  }
Beispiel #3
0
  public void startFlush(boolean automatic_resume) throws Exception {
    if (!flushSupported())
      throw new IllegalStateException(
          "Flush is not supported, add pbcast.FLUSH protocol to your configuration");

    try {
      down(new Event(Event.SUSPEND));
    } catch (Exception e) {
      throw new Exception("Flush failed", e.getCause());
    } finally {
      if (automatic_resume) stopFlush();
    }
  }
Beispiel #4
0
  protected void getState(Address target, long timeout, Callable<Boolean> flushInvoker)
      throws Exception {
    checkClosedOrNotConnected();
    if (!state_transfer_supported)
      throw new IllegalStateException(
          "fetching state will fail as state transfer is not supported. "
              + "Add one of the state transfer protocols to your configuration");

    if (target == null) target = determineCoordinator();
    if (target != null && local_addr != null && target.equals(local_addr)) {
      log.trace(
          local_addr
              + ": cannot get state from myself ("
              + target
              + "): probably the first member");
      return;
    }

    boolean initiateFlush = flushSupported() && flushInvoker != null;

    if (initiateFlush) {
      boolean successfulFlush = false;
      try {
        successfulFlush = flushInvoker.call();
      } catch (Throwable e) {
        successfulFlush = false; // http://jira.jboss.com/jira/browse/JGRP-759
      }
      if (!successfulFlush)
        throw new IllegalStateException(
            "Node " + local_addr + " could not flush the cluster for state retrieval");
    }

    state_promise.reset();
    StateTransferInfo state_info = new StateTransferInfo(target, timeout);
    long start = System.currentTimeMillis();
    down(new Event(Event.GET_STATE, state_info));
    StateTransferResult result = state_promise.getResult(state_info.timeout);

    if (initiateFlush) stopFlush();

    if (result == null)
      throw new StateTransferException(
          "timeout during state transfer (" + (System.currentTimeMillis() - start) + "ms)");
    if (result.hasException())
      throw new StateTransferException("state transfer failed", result.getException());
  }
Beispiel #5
0
 public void startFlush(List<Address> flushParticipants, boolean automatic_resume)
     throws Exception {
   if (!flushSupported())
     throw new IllegalStateException(
         "Flush is not supported, add pbcast.FLUSH protocol to your configuration");
   View v = getView();
   boolean validParticipants = v != null && v.getMembers().containsAll(flushParticipants);
   if (!validParticipants)
     throw new IllegalArgumentException(
         "Current view " + v + " does not contain all flush participants " + flushParticipants);
   try {
     down(new Event(Event.SUSPEND, flushParticipants));
   } catch (Exception e) {
     throw new Exception("Flush failed", e.getCause());
   } finally {
     if (automatic_resume) stopFlush(flushParticipants);
   }
 }
Beispiel #6
0
  public void testFlushWithCrashedParticipant() throws Exception {
    JChannel c1 = null;
    JChannel c2 = null;
    JChannel c3 = null;

    try {
      c1 = createChannel(true, 3, "C1");
      changeProps(c1);
      c1.connect("testFlushWithCrashedParticipant");

      c2 = createChannel(c1, "C2");
      changeProps(c2);
      c2.connect("testFlushWithCrashedParticipant");

      c3 = createChannel(c1, "C3");
      changeProps(c3);
      c3.connect("testFlushWithCrashedParticipant");

      System.out.println("shutting down C3");
      Util.shutdown(c3); // kill a flush participant

      System.out.println("C2: starting flush");
      boolean rc = Util.startFlush(c2);
      System.out.println("flush " + (rc ? " was successful" : "failed"));
      assert rc;

      System.out.println("stopping flush");
      c2.stopFlush();

      System.out.println("waiting for view to contain C1 and C2");
      Util.waitUntilAllChannelsHaveSameSize(10000, 500, c1, c2);

      // cluster should not hang and two remaining members should have a correct view
      System.out.println("C1: view=" + c1.getView() + "\nC2: view=" + c2.getView());
      assertTrue("correct view size", c1.getView().size() == 2);
      assertTrue("correct view size", c2.getView().size() == 2);
    } finally {
      Util.close(c3, c2, c1);
    }
  }
Beispiel #7
0
  /** Tests http://jira.jboss.com/jira/browse/JGRP-661 */
  public void testPartialFlush() throws Exception {
    JChannel c1 = null;
    JChannel c2 = null;
    try {
      c1 = createChannel(true, 2);
      c1.setReceiver(new SimpleReplier(c1, true));
      c1.connect("testPartialFlush");

      c2 = createChannel(c1);
      c2.setReceiver(new SimpleReplier(c2, false));
      c2.connect("testPartialFlush");

      List<Address> members = new ArrayList<Address>();
      members.add(c2.getAddress());
      boolean flushedOk = Util.startFlush(c2, members);

      assertTrue("Partial flush worked", flushedOk);

      c2.stopFlush(members);
    } finally {
      Util.close(c2, c1);
    }
  }