use of io.pravega.common.util.ReusableLatch in project pravega by pravega.
the class StreamSegmentContainerRegistryTests method testContainerFailureOnStartup.
/**
* Tests the ability to detect a container failure and unregister the container in case the container fails on startup.
*/
@Test
public void testContainerFailureOnStartup() throws Exception {
final int containerId = 123;
// We insert a ReusableLatch that will allow us to manually delay the TestContainer's shutdown/closing process
// so that we have enough time to verify that calling getContainer() on a currently shutting down container will
// throw the appropriate exception.
ReusableLatch closeReleaseSignal = new ReusableLatch();
TestContainerFactory factory = new TestContainerFactory(new IntentionalException(), closeReleaseSignal);
@Cleanup StreamSegmentContainerRegistry registry = new StreamSegmentContainerRegistry(factory, executorService());
AssertExtensions.assertThrows("Unexpected exception thrown upon failed container startup.", registry.startContainer(containerId, TIMEOUT)::join, ex -> ex instanceof IntentionalException || (ex instanceof IllegalStateException && ex.getCause() instanceof IntentionalException));
AssertExtensions.assertThrows("Container is registered even if it failed to start (and is currently shut down).", () -> registry.getContainer(containerId), ex -> ex instanceof ContainerNotFoundException);
// Unblock container closing, which will, in turn, unblock its de-registration.
closeReleaseSignal.release();
AssertExtensions.assertThrows("Container is registered even if it failed to start (and has been unregistered).", () -> registry.getContainer(containerId), ex -> ex instanceof ContainerNotFoundException);
}
use of io.pravega.common.util.ReusableLatch in project pravega by pravega.
the class AsyncStorageWrapperTests method testConcurrencySameSegment.
/**
* Tests basic same-segment concurrency for simple operations. Since all operations use the same sequencing mechanism
* it suffices to test using two arbitrary operations instead of every possible pair.
*/
@Test
public void testConcurrencySameSegment() throws Exception {
final String segmentName = "Segment";
final String op1 = TestStorage.CREATE;
final String op2 = TestStorage.DELETE;
// Create a set of latches that can be used to detect when an operation was invoked and when to release it.
val invoked = new HashMap<String, ReusableLatch>();
val waitOn = new HashMap<String, ReusableLatch>();
invoked.put(op1, new ReusableLatch());
invoked.put(op2, new ReusableLatch());
waitOn.put(op1, new ReusableLatch());
waitOn.put(op2, new ReusableLatch());
val innerStorage = new TestStorage((operation, segment) -> {
invoked.get(operation).release();
Exceptions.handleInterrupted(() -> waitOn.get(operation).await());
return null;
});
@Cleanup val s = new AsyncStorageWrapper(innerStorage, executorService());
// Begin executing one operation (Create) and wait for it properly "acquire" the lock.
val futures = new ArrayList<CompletableFuture<?>>();
futures.add(s.create(segmentName, TIMEOUT));
invoked.get(op1).await(LOCK_TIMEOUT_MILLIS);
Assert.assertEquals("Unexpected number of active segments.", 1, s.getSegmentWithOngoingOperationsCount());
// Begin executing a second operation (Delete) and verify that it hasn't started within a reasonable amount of time.
futures.add(s.delete(InMemoryStorage.newHandle(segmentName, false), TIMEOUT));
AssertExtensions.assertThrows("Second operation was invoked while the first one was still running.", () -> invoked.get(op2).await(LOCK_TIMEOUT_MILLIS), ex -> ex instanceof TimeoutException);
// Complete the first operation and await the second operation to begin executing, then release it too.
waitOn.get(op1).release();
invoked.get(op2).await(LOCK_TIMEOUT_MILLIS);
Assert.assertEquals("Unexpected number of active segments.", 1, s.getSegmentWithOngoingOperationsCount());
waitOn.get(op2).release();
// Wait for both operations to complete. This will re-throw any exceptions that may have occurred.
allOf(futures).get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
Assert.assertEquals("Unexpected final number of active segments.", 0, s.getSegmentWithOngoingOperationsCount());
}
use of io.pravega.common.util.ReusableLatch in project pravega by pravega.
the class EndOfDataNotifierTest method endOfStreamNotifierTest.
@Test
public void endOfStreamNotifierTest() throws Exception {
AtomicBoolean listenerInvoked = new AtomicBoolean();
ReusableLatch latch = new ReusableLatch();
when(state.isEndOfData()).thenReturn(false).thenReturn(true);
when(sync.getState()).thenReturn(state);
Listener<EndOfDataNotification> listener1 = notification -> {
log.info("listener 1 invoked");
listenerInvoked.set(true);
latch.release();
};
Listener<EndOfDataNotification> listener2 = notification -> {
};
EndOfDataNotifier notifier = new EndOfDataNotifier(system, sync, executor);
notifier.registerListener(listener1);
verify(executor, times(1)).scheduleAtFixedRate(any(Runnable.class), anyLong(), anyLong(), any(TimeUnit.class));
latch.await();
verify(state, times(2)).isEndOfData();
assertTrue(listenerInvoked.get());
notifier.registerListener(listener2);
verify(executor, times(1)).scheduleAtFixedRate(any(Runnable.class), anyLong(), anyLong(), any(TimeUnit.class));
notifier.unregisterAllListeners();
verify(system, times(1)).removeListeners(EndOfDataNotification.class.getSimpleName());
}
Aggregations