/* * ************************************************************************************* * Copyright (C) 2008 EsperTech, Inc. All rights reserved. * * http://esper.codehaus.org * * http://www.espertech.com * * ---------------------------------------------------------------------------------- * * The software in this package is published under the terms of the GPL license * * a copy of which has been included with this distribution in the license.txt file. * * ************************************************************************************* */ package com.espertech.esper.dataflow.util; import com.espertech.esper.client.dataflow.EPDataFlowSignal; import com.espertech.esper.dataflow.annotations.DataFlowOperator; import com.espertech.esper.dataflow.interfaces.EPDataFlowSignalHandler; import java.util.ArrayList; import java.util.List; import java.util.concurrent.*; @DataFlowOperator public class DefaultSupportCaptureOp<T> implements EPDataFlowSignalHandler, Future<Object[]> { private List<List<T>> received = new ArrayList<List<T>>(); private List<T> current = new ArrayList<T>(); private CountDownLatch numRowLatch; public DefaultSupportCaptureOp() { this(0); } public DefaultSupportCaptureOp(int latchedNumRows) { this.numRowLatch = new CountDownLatch(latchedNumRows); } public synchronized void onInput(T event) { current.add(event); if (numRowLatch != null) { numRowLatch.countDown(); } } public void onSignal(EPDataFlowSignal signal) { received.add(current); current = new ArrayList<T>(); } public synchronized List<List<T>> getAndReset() { List<List<T>> resultEvents = received; received = new ArrayList<List<T>>(); current.clear(); return resultEvents; } public synchronized Object[] getCurrent() { return current.toArray(); } public synchronized Object[] getCurrentAndReset() { Object[] currentArray = current.toArray(); current.clear(); return currentArray; } public boolean cancel(boolean mayInterruptIfRunning) { throw new UnsupportedOperationException(); } public boolean isCancelled() { throw new UnsupportedOperationException(); } public boolean isDone() { return numRowLatch.getCount() <= 0; } public Object[] get() throws InterruptedException, ExecutionException { try { return get(Long.MAX_VALUE, TimeUnit.DAYS); } catch (TimeoutException e) { } return null; } public Object[] get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { boolean result = numRowLatch.await(timeout, unit); if (!result) { throw new TimeoutException("latch timed out"); } return getCurrent(); } public Object[] getPunctuated() throws InterruptedException, ExecutionException, TimeoutException { boolean result = numRowLatch.await(1, TimeUnit.SECONDS); if (!result) { throw new TimeoutException("latch timed out"); } return received.get(0).toArray(); } /** * Wait for the listener invocation for up to the given number of milliseconds. * @param msecWait to wait * @param numberOfNewEvents in any number of separate invocations required before returning * @throws RuntimeException when no results or insufficient number of events were received */ public void waitForInvocation(long msecWait, int numberOfNewEvents) { long startTime = System.currentTimeMillis(); while(true) { synchronized (this) { if ((System.currentTimeMillis() - startTime) > msecWait) { throw new RuntimeException("No events or less then the number of expected events received, expected " + numberOfNewEvents + " received " + current.size()); } if (current.size() >= numberOfNewEvents) { return; } } try { Thread.sleep(50); } catch (InterruptedException e) { return; } } } }