/** * Create a dependency barrier for the processors in this group. * This allows custom event processors to have dependencies on * {@link com.lmax.disruptor.BatchEventProcessor}s created by the disruptor. * * @return a {@link SequenceBarrier} including all the processors in this group. */ public SequenceBarrier asSequenceBarrier() { return disruptor.getRingBuffer().newBarrier(sequences); } }
private Future<List<StubEvent>> getMessages(final long initial, final long toWaitFor) throws InterruptedException, BrokenBarrierException { final CyclicBarrier cyclicBarrier = new CyclicBarrier(2); final SequenceBarrier sequenceBarrier = ringBuffer.newBarrier(); final Future<List<StubEvent>> f = executor.submit( new TestWaiter( cyclicBarrier, sequenceBarrier, ringBuffer, initial, toWaitFor)); cyclicBarrier.await(); return f; }
EventHandlerGroup<T> createWorkerPool( final Sequence[] barrierSequences, final WorkHandler<? super T>[] workHandlers) { final SequenceBarrier sequenceBarrier = ringBuffer.newBarrier(barrierSequences); final WorkerPool<T> workerPool = new WorkerPool<>(ringBuffer, sequenceBarrier, exceptionHandler, workHandlers); consumerRepository.add(workerPool, sequenceBarrier); final Sequence[] workerSequences = workerPool.getWorkerSequences(); updateGatingSequencesForNextInChain(barrierSequences, workerSequences); return new EventHandlerGroup<>(this, consumerRepository, workerSequences); }
/** * Construct a work pool with an internal {@link RingBuffer} for convenience. * <p> * This option does not require {@link RingBuffer#addGatingSequences(Sequence...)} to be called before the work pool is started. * * @param eventFactory for filling the {@link RingBuffer} * @param exceptionHandler to callback when an error occurs which is not handled by the {@link WorkHandler}s. * @param workHandlers to distribute the work load across. */ @SafeVarargs public WorkerPool( final EventFactory<T> eventFactory, final ExceptionHandler<? super T> exceptionHandler, final WorkHandler<? super T>... workHandlers) { ringBuffer = RingBuffer.createMultiProducer(eventFactory, 1024, new BlockingWaitStrategy()); final SequenceBarrier barrier = ringBuffer.newBarrier(); final int numWorkers = workHandlers.length; workProcessors = new WorkProcessor[numWorkers]; for (int i = 0; i < numWorkers; i++) { workProcessors[i] = new WorkProcessor<>( ringBuffer, barrier, workHandlers[i], exceptionHandler, workSequence); } ringBuffer.addGatingSequences(getWorkerSequences()); }
public DisruptorQueueImpl(String queueName, ProducerType producerType, int bufferSize, WaitStrategy wait, boolean isBatch, int batchSize, long flushMs) { _queueName = PREFIX + queueName; _buffer = RingBuffer.create(producerType, new ObjectEventFactory(), bufferSize, wait); _consumer = new Sequence(); _barrier = _buffer.newBarrier(); _buffer.addGatingSequences(_consumer); _isBatch = isBatch; _cache = new ArrayList<>(); _inputBatchSize = batchSize; if (_isBatch) { _batcher = new ThreadLocalBatch(); _flusher = new DisruptorFlusher(Math.max(flushMs, 1)); _flusher.start(); } else { _batcher = null; } }
@Override public EventProcessor createEventProcessor( final RingBuffer<TestEvent> ringBuffer, final Sequence[] barrierSequences) { assertSame("Should have had a barrier sequence", 1, barrierSequences.length); return new BatchEventProcessor<TestEvent>( disruptor.getRingBuffer(), ringBuffer.newBarrier( barrierSequences), eventHandler); } });
@Override public EventProcessor createEventProcessor( final RingBuffer<TestEvent> ringBuffer, final Sequence[] barrierSequences) { assertEquals("Should not have had any barrier sequences", 0, barrierSequences.length); return new BatchEventProcessor<TestEvent>( disruptor.getRingBuffer(), ringBuffer.newBarrier( barrierSequences), eventHandler); } });
@Override public EventProcessor createEventProcessor( RingBuffer<TestEvent> ringBuffer, Sequence[] barrierSequences) { return new BatchEventProcessor<TestEvent>( ringBuffer, ringBuffer.newBarrier(barrierSequences), new SleepingEventHandler()); } };
final AtomicBoolean publisherComplete = new AtomicBoolean(false); final RingBuffer<StubEvent> buffer2 = createMultiProducer(StubEvent.EVENT_FACTORY, ringBufferSize); final TestEventProcessor processor = new TestEventProcessor(buffer2.newBarrier()); buffer2.addGatingSequences(processor.getSequence());
EventHandlerGroup<T> createEventProcessors( final Sequence[] barrierSequences, final EventHandler<? super T>[] eventHandlers) { checkNotStarted(); final Sequence[] processorSequences = new Sequence[eventHandlers.length]; final SequenceBarrier barrier = ringBuffer.newBarrier(barrierSequences); for (int i = 0, eventHandlersLength = eventHandlers.length; i < eventHandlersLength; i++) { final EventHandler<? super T> eventHandler = eventHandlers[i]; final BatchEventProcessor<T> batchEventProcessor = new BatchEventProcessor<>(ringBuffer, barrier, eventHandler); if (exceptionHandler != null) { batchEventProcessor.setExceptionHandler(exceptionHandler); } consumerRepository.add(batchEventProcessor, eventHandler, barrier); processorSequences[i] = batchEventProcessor.getSequence(); } updateGatingSequencesForNextInChain(barrierSequences, processorSequences); return new EventHandlerGroup<>(this, consumerRepository, processorSequences); }
ringBuffer.newBarrier(sequence1, sequence2, sequence3);
@Test public void shouldWaitForWorkCompleteWhereCompleteWorkThresholdIsBehind() throws Exception { long expectedNumberMessages = 10; fillRingBuffer(expectedNumberMessages); final DummyEventProcessor[] eventProcessors = new DummyEventProcessor[3]; for (int i = 0, size = eventProcessors.length; i < size; i++) { eventProcessors[i] = new DummyEventProcessor(); eventProcessors[i].setSequence(expectedNumberMessages - 2); } final SequenceBarrier sequenceBarrier = ringBuffer.newBarrier(Util.getSequencesFor(eventProcessors)); Runnable runnable = new Runnable() { public void run() { for (DummyEventProcessor stubWorker : eventProcessors) { stubWorker.setSequence(stubWorker.getSequence().get() + 1L); } } }; Thread thread = new Thread(runnable); thread.start(); thread.join(); long expectedWorkSequence = expectedNumberMessages - 1; long completedWorkSequence = sequenceBarrier.waitFor(expectedWorkSequence); assertTrue(completedWorkSequence >= expectedWorkSequence); }
@Test public void shouldSupportCustomProcessorsAsDependencies() throws Exception { RingBuffer<TestEvent> ringBuffer = disruptor.getRingBuffer(); final DelayedEventHandler delayedEventHandler = createDelayedEventHandler(); CountDownLatch countDownLatch = new CountDownLatch(2); EventHandler<TestEvent> handlerWithBarrier = new EventHandlerStub<TestEvent>(countDownLatch); final BatchEventProcessor<TestEvent> processor = new BatchEventProcessor<TestEvent>(ringBuffer, ringBuffer.newBarrier(), delayedEventHandler); disruptor.handleEventsWith(processor).then(handlerWithBarrier); ensureTwoEventsProcessedAccordingToDependencies(countDownLatch, delayedEventHandler); }
final SequenceBarrier sequenceBarrier = ringBuffer.newBarrier(Util.getSequencesFor(workers));
new BatchEventProcessor<StubEvent>(ringBuffer, ringBuffer.newBarrier(), handler1); new BatchEventProcessor<StubEvent>(ringBuffer, ringBuffer.newBarrier(processor1.getSequence()), handler2);
@Test public void shouldReportProgressByUpdatingSequenceViaCallback() throws Exception { final RingBuffer<StubEvent> ringBuffer = createMultiProducer(StubEvent.EVENT_FACTORY, 16); final SequenceBarrier sequenceBarrier = ringBuffer.newBarrier(); final SequenceReportingEventHandler<StubEvent> handler = new TestSequenceReportingEventHandler(); final BatchEventProcessor<StubEvent> batchEventProcessor = new BatchEventProcessor<StubEvent>( ringBuffer, sequenceBarrier, handler); ringBuffer.addGatingSequences(batchEventProcessor.getSequence()); Thread thread = new Thread(batchEventProcessor); thread.setDaemon(true); thread.start(); assertEquals(-1L, batchEventProcessor.getSequence().get()); ringBuffer.publish(ringBuffer.next()); callbackLatch.await(); assertEquals(0L, batchEventProcessor.getSequence().get()); onEndOfBatchLatch.countDown(); assertEquals(0L, batchEventProcessor.getSequence().get()); batchEventProcessor.halt(); thread.join(); }
@Test public void shouldWaitForWorkCompleteWhereCompleteWorkThresholdIsAhead() throws Exception { final long expectedNumberMessages = 10; final long expectedWorkSequence = 9; fillRingBuffer(expectedNumberMessages); final Sequence sequence1 = new Sequence(expectedNumberMessages); final Sequence sequence2 = new Sequence(expectedWorkSequence); final Sequence sequence3 = new Sequence(expectedNumberMessages); final SequenceBarrier sequenceBarrier = ringBuffer.newBarrier(sequence1, sequence2, sequence3); long completedWorkSequence = sequenceBarrier.waitFor(expectedWorkSequence); assertTrue(completedWorkSequence >= expectedWorkSequence); }
@Test public void shouldSetAndClearAlertStatus() { SequenceBarrier sequenceBarrier = ringBuffer.newBarrier(); assertFalse(sequenceBarrier.isAlerted()); sequenceBarrier.alert(); assertTrue(sequenceBarrier.isAlerted()); sequenceBarrier.clearAlert(); assertFalse(sequenceBarrier.isAlerted()); }
@Test public void shouldAddEventProcessorsAfterPublishing() throws Exception { RingBuffer<TestEvent> rb = disruptor.getRingBuffer(); BatchEventProcessor<TestEvent> b1 = new BatchEventProcessor<TestEvent>( rb, rb.newBarrier(), new SleepingEventHandler()); BatchEventProcessor<TestEvent> b2 = new BatchEventProcessor<TestEvent>( rb, rb.newBarrier(b1.getSequence()), new SleepingEventHandler()); BatchEventProcessor<TestEvent> b3 = new BatchEventProcessor<TestEvent>( rb, rb.newBarrier(b2.getSequence()), new SleepingEventHandler()); assertThat(b1.getSequence().get(), is(-1L)); assertThat(b2.getSequence().get(), is(-1L)); assertThat(b3.getSequence().get(), is(-1L)); rb.publish(rb.next()); rb.publish(rb.next()); rb.publish(rb.next()); rb.publish(rb.next()); rb.publish(rb.next()); rb.publish(rb.next()); disruptor.handleEventsWith(b1, b2, b3); assertThat(b1.getSequence().get(), is(5L)); assertThat(b2.getSequence().get(), is(5L)); assertThat(b3.getSequence().get(), is(5L)); }
@Test public void should() throws Exception { RingBuffer<TestEvent> rb = disruptor.getRingBuffer(); BatchEventProcessor<TestEvent> b1 = new BatchEventProcessor<TestEvent>( rb, rb.newBarrier(), new SleepingEventHandler()); EventProcessorFactory<TestEvent> b2 = new EventProcessorFactory<TestEvent>() { @Override public EventProcessor createEventProcessor( RingBuffer<TestEvent> ringBuffer, Sequence[] barrierSequences) { return new BatchEventProcessor<TestEvent>( ringBuffer, ringBuffer.newBarrier(barrierSequences), new SleepingEventHandler()); } }; disruptor.handleEventsWith(b1).then(b2); disruptor.start(); }