@Override public synchronized void receive(ForeignException e) { // if we already have an exception, then ignore it if (exception != null) return; LOG.debug(name + " accepting received exception" , e); // mark that we got the error if (e != null) { exception = e; } else { exception = new ForeignException(name, ""); } // notify all the listeners dispatch(e); }
} catch (InterruptedException e) { if (aborted) { throw new ForeignException("Interrupted and found to be aborted while waiting for tasks!", e); throw (ForeignException) e.getCause(); throw new ForeignException(name, e.getCause()); } finally {
@Override public synchronized void rethrowException() throws ForeignException { if (exception != null) { // This gets the stack where this is caused, (instead of where it was deserialized). // This is much more useful for debugging throw new ForeignException(exception.getSource(), exception.getCause()); } }
/** * The connection to the rest of the procedure group (members and coordinator) has been * broken/lost/failed. This should fail any interested procedures, but not attempt to notify other * members since we cannot reach them anymore. * @param message description of the error * @param cause the actual cause of the failure */ void rpcConnectionFailure(final String message, final IOException cause) { Collection<Procedure> toNotify = procedures.values(); boolean isTraceEnabled = LOG.isTraceEnabled(); LOG.debug("received connection failure: " + message, cause); for (Procedure proc : toNotify) { if (proc == null) { continue; } // notify the elements, if they aren't null if (isTraceEnabled) { LOG.trace("connection failure - notify procedure: " + proc.getName()); } proc.receive(new ForeignException(proc.getName(), cause)); } }
@Override public void cancel(String why) { if (finished) return; this.finished = true; LOG.info("Stop taking snapshot=" + ClientSnapshotDescriptionUtils.toString(snapshot) + " because: " + why); CancellationException ce = new CancellationException(why); monitor.receive(new ForeignException(master.getServerName().toString(), ce)); }
/** * Method to cancel the Subprocedure by injecting an exception from and external source. * @param cause */ public void cancel(String msg, Throwable cause) { LOG.error(msg, cause); complete = true; if (cause instanceof ForeignException) { monitor.receive((ForeignException) cause); } else { monitor.receive(new ForeignException(getMemberName(), cause)); } }
@Override public void run() { // ensure we don't run this task multiple times synchronized (this) { // quick exit if we already marked the task complete if (TimeoutExceptionInjector.this.complete) return; // mark the task is run, to avoid repeats TimeoutExceptionInjector.this.complete = true; } long end = EnvironmentEdgeManager.currentTime(); TimeoutException tee = new TimeoutException( "Timeout caused Foreign Exception", start, end, maxTime); String source = "timer-" + timer; listener.receive(new ForeignException(source, tee)); } };
if (aborted) throw new ForeignException( "Interrupted and found to be aborted while waiting for tasks!", e); Thread.currentThread().interrupt(); throw (ForeignException) e.getCause(); throw new ForeignException(name, e.getCause()); } finally {
LOG.error(msg); ee = new ForeignException(getMemberName(), new IllegalArgumentException(msg)); } else { data = Arrays.copyOfRange(data, ProtobufUtil.lengthOfPBMagic(), data.length); + " but we can't read the information. Killing the procedure."); ee = new ForeignException(getMemberName(), e);
private void flushRegions() throws ForeignException { if (regions.isEmpty()) { // No regions on this RS, we are basically done. return; } monitor.rethrowException(); // assert that the taskManager is empty. if (taskManager.hasTasks()) { throw new IllegalStateException("Attempting to flush " + table + " but we currently have outstanding tasks"); } // Add all hfiles already existing in region. for (HRegion region : regions) { // submit one task per region for parallelize by region. taskManager.submitTask(new RegionFlushTask(region)); monitor.rethrowException(); } // wait for everything to complete. LOG.debug("Flush region tasks submitted for " + regions.size() + " regions"); try { taskManager.waitForOutstandingTasks(); } catch (InterruptedException e) { throw new ForeignException(getMemberName(), e); } }
/** * Sends a message to Members to create a new {@link Subprocedure} for this Procedure and execute * the {@link Subprocedure#acquireBarrier} step. * @throws ForeignException */ public void sendGlobalBarrierStart() throws ForeignException { // start the procedure LOG.debug("Starting procedure '" + procName + "', kicking off acquire phase on members."); try { // send procedure barrier start to specified list of members. cloning the list to avoid // concurrent modification from the controller setting the prepared nodes coord.getRpcs().sendGlobalBarrierAcquire(this, args, Lists.newArrayList(this.acquiringMembers)); } catch (IOException e) { coord.rpcConnectionFailure("Can't reach controller.", e); } catch (IllegalArgumentException e) { throw new ForeignException(getName(), e); } }
private void flushSnapshot() throws ForeignException { if (regions.isEmpty()) { // No regions on this RS, we are basically done. return; } monitor.rethrowException(); // assert that the taskManager is empty. if (taskManager.hasTasks()) { throw new IllegalStateException("Attempting to take snapshot " + ClientSnapshotDescriptionUtils.toString(snapshot) + " but we currently have outstanding tasks"); } // Add all hfiles already existing in region. for (HRegion region : regions) { // submit one task per region for parallelize by region. taskManager.submitTask(new RegionSnapshotTask(region, snapshot, snapshotSkipFlush, monitor)); monitor.rethrowException(); } // wait for everything to complete. LOG.debug("Flush Snapshot Tasks submitted for " + regions.size() + " regions"); try { taskManager.waitForOutstandingTasks(); } catch (InterruptedException e) { LOG.error("got interrupted exception for " + getMemberName()); throw new ForeignException(getMemberName(), e); } }
@Test public void testErrorPropagation() throws Exception { List<String> members = new ArrayList<>(); members.add("member"); Procedure proc = new Procedure(coord, new ForeignExceptionDispatcher(), 100, Integer.MAX_VALUE, "op", null, members); final Procedure procspy = spy(proc); ForeignException cause = new ForeignException("SRC", "External Exception"); proc.receive(cause); // start the barrier procedure Thread t = new Thread() { @Override public void run() { procspy.call(); } }; t.start(); t.join(); verify(procspy, never()).sendGlobalBarrierStart(); verify(procspy, never()).sendGlobalBarrierReached(); verify(procspy).sendGlobalBarrierComplete(); }
@Test public void testBarrieredErrorPropagation() throws Exception { List<String> members = new ArrayList<>(); members.add("member"); LatchedProcedure proc = new LatchedProcedure(coord, new ForeignExceptionDispatcher(), 100, Integer.MAX_VALUE, "op", null, members); final LatchedProcedure procspy = spy(proc); // start the barrier procedure Thread t = new Thread() { @Override public void run() { procspy.call(); } }; t.start(); // now test that we can put an error in before the commit phase runs procspy.startedAcquireBarrier.await(); ForeignException cause = new ForeignException("SRC", "External Exception"); procspy.receive(cause); procspy.barrierAcquiredByMember(members.get(0)); t.join(); // verify state of all the object verify(procspy).sendGlobalBarrierStart(); verify(procspy).sendGlobalBarrierComplete(); verify(procspy, never()).sendGlobalBarrierReached(); } }
/** * Takes a series of bytes and tries to generate an ForeignException instance for it. * @param bytes * @return the ForeignExcpetion instance * @throws InvalidProtocolBufferException if there was deserialization problem this is thrown. * @throws org.apache.hbase.thirdparty.com.google.protobuf.InvalidProtocolBufferException */ public static ForeignException deserialize(byte[] bytes) throws IOException { // figure out the data we need to pass ForeignExceptionMessage eem = ForeignExceptionMessage.parseFrom(bytes); GenericExceptionMessage gem = eem.getGenericException(); StackTraceElement [] trace = ForeignException.toStackTrace(gem.getTraceList()); ProxyThrowable dfe = new ProxyThrowable(gem.getMessage(), trace); ForeignException e = new ForeignException(eem.getSource(), dfe); return e; }
doThrow(new ForeignException("SRC", "prepare exception")).when(spy).acquireBarrier();
/** * Verify that we get back similar stack trace information before an after serialization. */ @Test public void testSimpleException() throws IOException { String data = "some bytes"; ForeignException in = new ForeignException("SRC", new IllegalArgumentException(data)); // check that we get the data back out ForeignException e = ForeignException.deserialize(ForeignException.serialize(srcName, in)); assertNotNull(e); // now check that we get the right stack trace StackTraceElement elem = new StackTraceElement(this.getClass().toString(), "method", "file", 1); in.setStackTrace(new StackTraceElement[] { elem }); e = ForeignException.deserialize(ForeignException.serialize(srcName, in)); assertNotNull(e); assertEquals("Stack trace got corrupted", elem, e.getCause().getStackTrace()[0]); assertEquals("Got an unexpectedly long stack trace", 1, e.getCause().getStackTrace().length); }
@Override public Void answer(InvocationOnMock invocation) throws Throwable { int index = elem[0]; if (index == memberErrorIndex) { LOG.debug("Sending error to coordinator"); ForeignException remoteCause = new ForeignException("TIMER", new TimeoutException("subprocTimeout" , 1, 2, 0)); Subprocedure r = ((Subprocedure) invocation.getMock()); LOG.error("Remote commit failure, not propagating error:" + remoteCause); comms.receiveAbortProcedure(r.getName(), remoteCause); assertTrue(r.isComplete()); // don't complete the error phase until the coordinator has gotten the error // notification (which ensures that we never progress past prepare) try { Procedure.waitForLatch(coordinatorReceivedErrorLatch, new ForeignExceptionDispatcher(), WAKE_FREQUENCY, "coordinator received error"); } catch (InterruptedException e) { LOG.debug("Wait for latch interrupted, done:" + (coordinatorReceivedErrorLatch.getCount() == 0)); // reset the interrupt status on the thread Thread.currentThread().interrupt(); } } elem[0] = ++index; return null; } }).when(commit).acquireBarrier();
} catch (InterruptedException e) { ForeignException ee = new ForeignException("Interrupted while waiting for procdure to finish", e); monitor.receive(ee); Thread.currentThread().interrupt();
LOG.error(msg, e); monitorException.receive( new ForeignException(env.getMasterServices().getServerName().toString(), e)); throw new IOException(msg, e);