/** Invokes the "onBlockFetchFailure" callback for every listed block id. */ private void failRemainingBlocks(String[] failedBlockIds, Throwable e) { for (String blockId : failedBlockIds) { try { listener.onBlockFetchFailure(blockId, e); } catch (Exception e2) { logger.error("Error in block fetch failure callback", e2); } } }
@Override public void onSuccess(int chunkIndex, ManagedBuffer buffer) { // On receipt of a chunk, pass it upwards as a block. listener.onBlockFetchSuccess(blockIds[chunkIndex], buffer); }
@Test public void testFailure() { LinkedHashMap<String, ManagedBuffer> blocks = Maps.newLinkedHashMap(); blocks.put("b0", new NioManagedBuffer(ByteBuffer.wrap(new byte[12]))); blocks.put("b1", null); blocks.put("b2", null); BlockFetchingListener listener = fetchBlocks(blocks); // Each failure will cause a failure to be invoked in all remaining block fetches. verify(listener, times(1)).onBlockFetchSuccess("b0", blocks.get("b0")); verify(listener, times(1)).onBlockFetchFailure(eq("b1"), any()); verify(listener, times(2)).onBlockFetchFailure(eq("b2"), any()); }
@Test public void testFailure() { LinkedHashMap<String, ManagedBuffer> blocks = Maps.newLinkedHashMap(); blocks.put("b0", new NioManagedBuffer(ByteBuffer.wrap(new byte[12]))); blocks.put("b1", null); blocks.put("b2", null); BlockFetchingListener listener = fetchBlocks(blocks); // Each failure will cause a failure to be invoked in all remaining block fetches. verify(listener, times(1)).onBlockFetchSuccess("b0", blocks.get("b0")); verify(listener, times(1)).onBlockFetchFailure(eq("b1"), any()); verify(listener, times(2)).onBlockFetchFailure(eq("b2"), any()); }
@Test public void testFailure() { LinkedHashMap<String, ManagedBuffer> blocks = Maps.newLinkedHashMap(); blocks.put("b0", new NioManagedBuffer(ByteBuffer.wrap(new byte[12]))); blocks.put("b1", null); blocks.put("b2", null); BlockFetchingListener listener = fetchBlocks(blocks); // Each failure will cause a failure to be invoked in all remaining block fetches. verify(listener, times(1)).onBlockFetchSuccess("b0", blocks.get("b0")); verify(listener, times(1)).onBlockFetchFailure(eq("b1"), any()); verify(listener, times(2)).onBlockFetchFailure(eq("b2"), any()); }
@Override public void onSuccess(int chunkIndex, ManagedBuffer buffer) { // On receipt of a chunk, pass it upwards as a block. listener.onBlockFetchSuccess(blockIds[chunkIndex], buffer); }
/** Invokes the "onBlockFetchFailure" callback for every listed block id. */ private void failRemainingBlocks(String[] failedBlockIds, Throwable e) { for (String blockId : failedBlockIds) { try { listener.onBlockFetchFailure(blockId, e); } catch (Exception e2) { logger.error("Error in block fetch failure callback", e2); } } }
@Test public void testFailureAndSuccess() { LinkedHashMap<String, ManagedBuffer> blocks = Maps.newLinkedHashMap(); blocks.put("b0", new NioManagedBuffer(ByteBuffer.wrap(new byte[12]))); blocks.put("b1", null); blocks.put("b2", new NioManagedBuffer(ByteBuffer.wrap(new byte[21]))); BlockFetchingListener listener = fetchBlocks(blocks); // We may call both success and failure for the same block. verify(listener, times(1)).onBlockFetchSuccess("b0", blocks.get("b0")); verify(listener, times(1)).onBlockFetchFailure(eq("b1"), any()); verify(listener, times(1)).onBlockFetchSuccess("b2", blocks.get("b2")); verify(listener, times(1)).onBlockFetchFailure(eq("b2"), any()); }
@Override public void onSuccess(int chunkIndex, ManagedBuffer buffer) { // On receipt of a chunk, pass it upwards as a block. listener.onBlockFetchSuccess(blockIds[chunkIndex], buffer); }
/** Invokes the "onBlockFetchFailure" callback for every listed block id. */ private void failRemainingBlocks(String[] failedBlockIds, Throwable e) { for (String blockId : failedBlockIds) { try { listener.onBlockFetchFailure(blockId, e); } catch (Exception e2) { logger.error("Error in block fetch failure callback", e2); } } }
@Test public void testFailureAndSuccess() { LinkedHashMap<String, ManagedBuffer> blocks = Maps.newLinkedHashMap(); blocks.put("b0", new NioManagedBuffer(ByteBuffer.wrap(new byte[12]))); blocks.put("b1", null); blocks.put("b2", new NioManagedBuffer(ByteBuffer.wrap(new byte[21]))); BlockFetchingListener listener = fetchBlocks(blocks); // We may call both success and failure for the same block. verify(listener, times(1)).onBlockFetchSuccess("b0", blocks.get("b0")); verify(listener, times(1)).onBlockFetchFailure(eq("b1"), any()); verify(listener, times(1)).onBlockFetchSuccess("b2", blocks.get("b2")); verify(listener, times(1)).onBlockFetchFailure(eq("b2"), any()); }
@Override public void onBlockFetchSuccess(String blockId, ManagedBuffer data) { // We will only forward this success message to our parent listener if this block request is // outstanding and we are still the active listener. boolean shouldForwardSuccess = false; synchronized (RetryingBlockFetcher.this) { if (this == currentListener && outstandingBlocksIds.contains(blockId)) { outstandingBlocksIds.remove(blockId); shouldForwardSuccess = true; } } // Now actually invoke the parent listener, outside of the synchronized block. if (shouldForwardSuccess) { listener.onBlockFetchSuccess(blockId, data); } }
@Override public void onBlockFetchFailure(String blockId, Throwable exception) { // We will only forward this failure to our parent listener if this block request is // outstanding, we are still the active listener, AND we cannot retry the fetch. boolean shouldForwardFailure = false; synchronized (RetryingBlockFetcher.this) { if (this == currentListener && outstandingBlocksIds.contains(blockId)) { if (shouldRetry(exception)) { initiateRetry(); } else { logger.error(String.format("Failed to fetch block %s, and will not retry (%s retries)", blockId, retryCount), exception); outstandingBlocksIds.remove(blockId); shouldForwardFailure = true; } } } // Now actually invoke the parent listener, outside of the synchronized block. if (shouldForwardFailure) { listener.onBlockFetchFailure(blockId, exception); } } }
@Test public void testFailureAndSuccess() { LinkedHashMap<String, ManagedBuffer> blocks = Maps.newLinkedHashMap(); blocks.put("b0", new NioManagedBuffer(ByteBuffer.wrap(new byte[12]))); blocks.put("b1", null); blocks.put("b2", new NioManagedBuffer(ByteBuffer.wrap(new byte[21]))); BlockFetchingListener listener = fetchBlocks(blocks); // We may call both success and failure for the same block. verify(listener, times(1)).onBlockFetchSuccess("b0", blocks.get("b0")); verify(listener, times(1)).onBlockFetchFailure(eq("b1"), any()); verify(listener, times(1)).onBlockFetchSuccess("b2", blocks.get("b2")); verify(listener, times(1)).onBlockFetchFailure(eq("b2"), any()); }
@Override public void onBlockFetchSuccess(String blockId, ManagedBuffer data) { // We will only forward this success message to our parent listener if this block request is // outstanding and we are still the active listener. boolean shouldForwardSuccess = false; synchronized (RetryingBlockFetcher.this) { if (this == currentListener && outstandingBlocksIds.contains(blockId)) { outstandingBlocksIds.remove(blockId); shouldForwardSuccess = true; } } // Now actually invoke the parent listener, outside of the synchronized block. if (shouldForwardSuccess) { listener.onBlockFetchSuccess(blockId, data); } }
@Override public void onBlockFetchFailure(String blockId, Throwable exception) { // We will only forward this failure to our parent listener if this block request is // outstanding, we are still the active listener, AND we cannot retry the fetch. boolean shouldForwardFailure = false; synchronized (RetryingBlockFetcher.this) { if (this == currentListener && outstandingBlocksIds.contains(blockId)) { if (shouldRetry(exception)) { initiateRetry(); } else { logger.error(String.format("Failed to fetch block %s, and will not retry (%s retries)", blockId, retryCount), exception); outstandingBlocksIds.remove(blockId); shouldForwardFailure = true; } } } // Now actually invoke the parent listener, outside of the synchronized block. if (shouldForwardFailure) { listener.onBlockFetchFailure(blockId, exception); } } }
@Test public void testUnrecoverableFailure() throws IOException, InterruptedException { BlockFetchingListener listener = mock(BlockFetchingListener.class); List<? extends Map<String, Object>> interactions = Arrays.asList( // b0 throws a non-IOException error, so it will be failed without retry. ImmutableMap.<String, Object>builder() .put("b0", new RuntimeException("Ouch!")) .put("b1", block1) .build() ); performInteractions(interactions, listener); verify(listener).onBlockFetchFailure(eq("b0"), any()); verify(listener).onBlockFetchSuccess("b1", block1); verifyNoMoreInteractions(listener); }
@Override public void onBlockFetchSuccess(String blockId, ManagedBuffer data) { // We will only forward this success message to our parent listener if this block request is // outstanding and we are still the active listener. boolean shouldForwardSuccess = false; synchronized (RetryingBlockFetcher.this) { if (this == currentListener && outstandingBlocksIds.contains(blockId)) { outstandingBlocksIds.remove(blockId); shouldForwardSuccess = true; } } // Now actually invoke the parent listener, outside of the synchronized block. if (shouldForwardSuccess) { listener.onBlockFetchSuccess(blockId, data); } }
@Override public void onBlockFetchFailure(String blockId, Throwable exception) { // We will only forward this failure to our parent listener if this block request is // outstanding, we are still the active listener, AND we cannot retry the fetch. boolean shouldForwardFailure = false; synchronized (RetryingBlockFetcher.this) { if (this == currentListener && outstandingBlocksIds.contains(blockId)) { if (shouldRetry(exception)) { initiateRetry(); } else { logger.error(String.format("Failed to fetch block %s, and will not retry (%s retries)", blockId, retryCount), exception); outstandingBlocksIds.remove(blockId); shouldForwardFailure = true; } } } // Now actually invoke the parent listener, outside of the synchronized block. if (shouldForwardFailure) { listener.onBlockFetchFailure(blockId, exception); } } }
@Test public void testUnrecoverableFailure() throws IOException, InterruptedException { BlockFetchingListener listener = mock(BlockFetchingListener.class); List<? extends Map<String, Object>> interactions = Arrays.asList( // b0 throws a non-IOException error, so it will be failed without retry. ImmutableMap.<String, Object>builder() .put("b0", new RuntimeException("Ouch!")) .put("b1", block1) .build() ); performInteractions(interactions, listener); verify(listener).onBlockFetchFailure(eq("b0"), any()); verify(listener).onBlockFetchSuccess("b1", block1); verifyNoMoreInteractions(listener); }