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); } }
/** * 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(); } }
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(); } }
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()); }
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); } }
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); } }
/** 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); } }