ss: Move plugins to Trace Compass namespace
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / request / TmfEventRequest.java
index 4b97e97658ab4201c12f8d3cbd7155a945256a43..c37bb1173a367b2462561c04297906862da01161 100644 (file)
  *
  * Contributors:
  *   Francois Chouinard - Initial API and implementation
+ *   Alexandre Montplaisir - Consolidate constructors, merge with TmfDataRequest
  *******************************************************************************/
 
 package org.eclipse.linuxtools.tmf.core.request;
 
+import java.util.concurrent.CountDownLatch;
+
 import org.eclipse.linuxtools.internal.tmf.core.TmfCoreTracer;
 import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange;
 
 /**
- * An extension of TmfDataRequest for timestamped events.
+ * TmfEventRequest's are used to obtain series of events from an event provider.
+ * Open ranges can be used, especially for continuous streaming.
+ * <p>
+ * The request is processed asynchronously by a TmfEventProvider and, as events
+ * become available, handleData() is invoked synchronously for each one.
+ * <p>
+ * The TmfEventProvider indicates that the request is completed by calling
+ * done(). The request can be cancelled at any time with cancel().
+ * <p>
+ * Typical usage:
+ *
+ * <pre><code>
+ * TmfEventRequest request = new TmfEventRequest(DataType.class, range, startIndex, nbEvents, priority) {
+ *
+ *     public void handleData(ITmfEvent event) {
+ *         // do something with the event
+ *     }
+ *
+ *     public void handleSuccess() {
+ *         // callback for when the request completes successfully
+ *     }
+ *
+ *     public void handleFailure() {
+ *         // callback for when the request fails due to an error
+ *     }
+ *
+ *     public void handleCancel() {
+ *         // callback for when the request is cancelled via .cancel()
+ *     }
+ *
+ * };
+ *
+ * eventProvider.sendRequest(request);
+ * </code></pre>
+ *
+ *
+ * TODO: Implement request failures (codes, etc...)
  *
- * @version 1.0
  * @author Francois Chouinard
+ * @since 3.0
  */
-public abstract class TmfEventRequest extends TmfDataRequest implements ITmfEventRequest {
+public abstract class TmfEventRequest implements ITmfEventRequest {
+
+    // ------------------------------------------------------------------------
+    // Constants
+    // ------------------------------------------------------------------------
+
+    private static int fRequestNumber = 0;
 
     // ------------------------------------------------------------------------
     // Attributes
     // ------------------------------------------------------------------------
 
-    private final TmfTimeRange fRange; // The requested events time range
+    private final Class<? extends ITmfEvent> fDataType;
+    private final ExecutionType fExecType;
+
+    /** A unique request ID */
+    private final int fRequestId;
+
+    /** The requested events time range */
+    private final TmfTimeRange fRange;
+
+    /** The index (rank) of the requested event
+     * @since 3.0*/
+    protected long fIndex;
+
+    /** The number of requested events (ALL_DATA for all)
+     * @since 3.0*/
+    protected int fNbRequested;
+
+    /** The number of reads so far */
+    private int fNbRead;
+
+    private final CountDownLatch startedLatch = new CountDownLatch(1);
+    private final CountDownLatch completedLatch = new CountDownLatch(1);
+
+    private boolean fRequestRunning;
+    private boolean fRequestCompleted;
+    private boolean fRequestFailed;
+    private boolean fRequestCanceled;
 
     // ------------------------------------------------------------------------
     // Constructors
     // ------------------------------------------------------------------------
 
     /**
-     * Request all the events of a given type (high priority)
-     * Events are returned in blocks of the default size (DEFAULT_BLOCK_SIZE).
+     * Request 'n' events of a given type, for the *whole* trace, at the given
+     * priority.
      *
-     * @param dataType the requested data type
+     * @param dataType
+     *            The requested data type.
+     * @param index
+     *            The index of the first event to retrieve. You can use '0' to
+     *            start at the beginning of the trace.
+     * @param nbRequested
+     *            The number of events requested. You can use
+     *            {@link TmfEventRequest#ALL_DATA} to indicate you want all
+     *            events in the trace.
+     * @param priority
+     *            The requested execution priority.
      */
-    public TmfEventRequest(Class<? extends ITmfEvent> dataType) {
-        this(dataType, TmfTimeRange.ETERNITY, 0, ALL_DATA, DEFAULT_BLOCK_SIZE, ExecutionType.FOREGROUND);
+    public TmfEventRequest(Class<? extends ITmfEvent> dataType,
+            long index,
+            int nbRequested,
+            ExecutionType priority) {
+        this(dataType, TmfTimeRange.ETERNITY, index, nbRequested, priority);
     }
 
     /**
-     * Request all the events of a given type (given priority)
-     * Events are returned in blocks of the default size (DEFAULT_BLOCK_SIZE).
+     * Request 'n' events of a given type, for the given time range, at the
+     * given priority.
      *
-     * @param dataType the requested data type
-     * @param priority the requested execution priority
+     * @param dataType
+     *            The requested data type.
+     * @param range
+     *            The time range of the requested events. You can use
+     *            {@link TmfTimeRange#ETERNITY} to indicate you want to cover
+     *            the whole trace.
+     * @param index
+     *            The index of the first event to retrieve. You can use '0' to
+     *            start at the beginning of the trace.
+     * @param nbRequested
+     *            The number of events requested. You can use
+     *            {@link TmfEventRequest#ALL_DATA} to indicate you want all
+     *            events in the time range.
+     * @param priority
+     *            The requested execution priority.
      */
-    public TmfEventRequest(Class<? extends ITmfEvent> dataType, ExecutionType priority) {
-        this(dataType, TmfTimeRange.ETERNITY, 0, ALL_DATA, DEFAULT_BLOCK_SIZE, priority);
+    public TmfEventRequest(Class<? extends ITmfEvent> dataType,
+            TmfTimeRange range,
+            long index,
+            int nbRequested,
+            ExecutionType priority) {
+
+        fRequestId = fRequestNumber++;
+        fDataType = dataType;
+        fIndex = index;
+        fNbRequested = nbRequested;
+        fExecType = priority;
+        fRange = range;
+        fNbRead = 0;
+
+        fRequestRunning = false;
+        fRequestCompleted = false;
+        fRequestFailed = false;
+        fRequestCanceled = false;
+
+        /* Setup the request tracing if it's enabled */
+        if (TmfCoreTracer.isRequestTraced()) {
+            String type = getClass().getName();
+            type = type.substring(type.lastIndexOf('.') + 1);
+            @SuppressWarnings("nls")
+            String message = "CREATED "
+                    + (getExecType() == ExecutionType.BACKGROUND ? "(BG)" : "(FG)")
+                    + " Type=" + type + " Index=" + getIndex() + " NbReq=" + getNbRequested()
+                    + " Range=" + getRange()
+                    + " DataType=" + getDataType().getSimpleName();
+            TmfCoreTracer.traceRequest(this, message);
+        }
     }
 
     /**
-     * Request all the events of a given type for the given time range (high priority)
-     * Events are returned in blocks of the default size (DEFAULT_BLOCK_SIZE).
-     *
-     * @param dataType the requested data type
-     * @param range the time range of the requested events
+     * Resets the request counter (used for testing)
      */
-    public TmfEventRequest(Class<? extends ITmfEvent> dataType, TmfTimeRange range) {
-        this(dataType, range, 0, ALL_DATA, DEFAULT_BLOCK_SIZE, ExecutionType.FOREGROUND);
+    public static void reset() {
+        fRequestNumber = 0;
     }
 
-    /**
-     * Request all the events of a given type for the given time range (given priority)
-     * Events are returned in blocks of the default size (DEFAULT_BLOCK_SIZE).
-     *
-     * @param dataType the requested data type
-     * @param range the time range of the requested events
-     * @param priority the requested execution priority
-     */
-    public TmfEventRequest(Class<? extends ITmfEvent> dataType, TmfTimeRange range, ExecutionType priority) {
-        this(dataType, range, 0, ALL_DATA, DEFAULT_BLOCK_SIZE, priority);
+    // ------------------------------------------------------------------------
+    // Accessors
+    // ------------------------------------------------------------------------
+
+    @Override
+    public int getRequestId() {
+        return fRequestId;
     }
 
-    /**
-     * Request 'n' events of a given type from the given time range (high priority)
-     * Events are returned in blocks of the default size (DEFAULT_BLOCK_SIZE).
-     *
-     * @param dataType the requested data type
-     * @param range the time range of the requested events
-     * @param nbRequested the number of events requested
-     */
-    public TmfEventRequest(Class<? extends ITmfEvent> dataType, TmfTimeRange range, int nbRequested) {
-        this(dataType, range, 0, nbRequested, DEFAULT_BLOCK_SIZE, ExecutionType.FOREGROUND);
+    @Override
+    public long getIndex() {
+        return fIndex;
     }
 
     /**
-     * Request 'n' events of a given type for the given time range (given priority)
-     * Events are returned in blocks of the default size (DEFAULT_BLOCK_SIZE).
-     *
-     * @param dataType the requested data type
-     * @param range the time range of the requested events
-     * @param nbRequested the number of events requested
-     * @param priority the requested execution priority
+     * @since 3.0
      */
-    public TmfEventRequest(Class<? extends ITmfEvent> dataType, TmfTimeRange range, int nbRequested, ExecutionType priority) {
-        this(dataType, range, 0, nbRequested, DEFAULT_BLOCK_SIZE, priority);
+    @Override
+    public ExecutionType getExecType() {
+        return fExecType;
     }
 
-    /**
-     * Request 'n' events of a given type for the given time range (high priority).
-     * Events are returned in blocks of the given size.
-     *
-     * @param dataType the requested data type
-     * @param range the time range of the requested events
-     * @param nbRequested the number of events requested
-     * @param blockSize the number of events per block
-     */
-    public TmfEventRequest(Class<? extends ITmfEvent> dataType, TmfTimeRange range, int nbRequested, int blockSize) {
-       this(dataType, range, 0, nbRequested, blockSize, ExecutionType.FOREGROUND);
+    @Override
+    public int getNbRequested() {
+        return fNbRequested;
     }
 
-    /**
-     * Request 'n' events of a given type for the given time range (high priority).
-     * Events are returned in blocks of the given size.
-     *
-     * @param dataType the requested data type
-     * @param range the time range of the requested events
-     * @param index the index of the first event to retrieve
-     * @param nbRequested the number of events requested
-     * @param blockSize the number of events per block
-     */
-    public TmfEventRequest(Class<? extends ITmfEvent> dataType, TmfTimeRange range, long index, int nbRequested, int blockSize) {
-        this(dataType, range, index, nbRequested, blockSize, ExecutionType.FOREGROUND);
+    @Override
+    public synchronized int getNbRead() {
+        return fNbRead;
     }
 
-    /**
-     * Request 'n' events of a given type for the given time range (given priority).
-     * Events are returned in blocks of the given size.
-     *
-     * @param dataType the requested data type
-     * @param range the time range of the requested events
-     * @param nbRequested the number of events requested
-     * @param blockSize the number of events per block
-     * @param priority the requested execution priority
-     */
-    public TmfEventRequest(Class<? extends ITmfEvent> dataType, TmfTimeRange range, int nbRequested, int blockSize, ExecutionType priority) {
-       this(dataType, range, 0, nbRequested, blockSize, priority);
+    @Override
+    public synchronized boolean isRunning() {
+        return fRequestRunning;
     }
 
-    /**
-     * Request 'n' events of a given type for the given time range (given priority).
-     * Events are returned in blocks of the given size.
-     *
-     * @param dataType the requested data type
-     * @param range the time range of the requested events
-     * @param index the index of the first event to retrieve
-     * @param nbRequested the number of events requested
-     * @param blockSize the number of events per block
-     * @param priority the requested execution priority
-     */
-    public TmfEventRequest(Class<? extends ITmfEvent> dataType, TmfTimeRange range, long index, int nbRequested, int blockSize, ExecutionType priority) {
-       super(dataType, index, nbRequested, blockSize, priority);
-       fRange = range;
+    @Override
+    public synchronized boolean isCompleted() {
+        return fRequestCompleted;
+    }
 
-        if (TmfCoreTracer.isRequestTraced()) {
-            String type = getClass().getName();
-            type = type.substring(type.lastIndexOf('.') + 1);
-            @SuppressWarnings("nls")
-            String message = "CREATED "
-                    + (getExecType() == ITmfDataRequest.ExecutionType.BACKGROUND ? "(BG)" : "(FG)")
-                    + " Type=" + type + " Index=" + getIndex() + " NbReq=" + getNbRequested()
-                    + " Range=" + getRange()
-                    + " DataType=" + getDataType().getSimpleName();
-            TmfCoreTracer.traceRequest(this, message);
-        }
+    @Override
+    public synchronized boolean isFailed() {
+        return fRequestFailed;
+    }
+
+    @Override
+    public synchronized boolean isCancelled() {
+        return fRequestCanceled;
+    }
+
+    @Override
+    public Class<? extends ITmfEvent> getDataType() {
+        return fDataType;
+    }
+
+    @Override
+    public TmfTimeRange getRange() {
+        return fRange;
     }
 
     // ------------------------------------------------------------------------
-    // Accessors
+    // Setters
     // ------------------------------------------------------------------------
 
     /**
-     * @return the requested time range
-     * @since 2.0
+     * This method is called by the event provider to set the index
+     * corresponding to the time range start time
+     *
+     * @param index
+     *            The start time index
      */
+    protected void setIndex(int index) {
+        fIndex = index;
+    }
+
     @Override
-       public TmfTimeRange getRange() {
-        return fRange;
+    public void setStartIndex(int index) {
+        setIndex(index);
     }
 
     // ------------------------------------------------------------------------
-    // Setters
+    // Operators
     // ------------------------------------------------------------------------
 
+    @Override
+    public void handleData(ITmfEvent event) {
+        fNbRead++;
+    }
+
+    @Override
+    public void handleStarted() {
+        if (TmfCoreTracer.isRequestTraced()) {
+            TmfCoreTracer.traceRequest(this, "STARTED"); //$NON-NLS-1$
+        }
+    }
+
+    @Override
+    public void handleCompleted() {
+        boolean requestFailed = false;
+        boolean requestCanceled = false;
+        synchronized (this) {
+            requestFailed = fRequestFailed;
+            requestCanceled = fRequestCanceled;
+        }
+
+        if (requestFailed) {
+            handleFailure();
+        } else if (requestCanceled) {
+            handleCancel();
+        } else {
+            handleSuccess();
+        }
+        if (TmfCoreTracer.isRequestTraced()) {
+            TmfCoreTracer.traceRequest(this, "COMPLETED (" + fNbRead + " events read)"); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+    }
+
+    @Override
+    public void handleSuccess() {
+        if (TmfCoreTracer.isRequestTraced()) {
+            TmfCoreTracer.traceRequest(this, "SUCCEEDED"); //$NON-NLS-1$
+        }
+    }
+
+    @Override
+    public void handleFailure() {
+        if (TmfCoreTracer.isRequestTraced()) {
+            TmfCoreTracer.traceRequest(this, "FAILED"); //$NON-NLS-1$
+        }
+    }
+
+    @Override
+    public void handleCancel() {
+        if (TmfCoreTracer.isRequestTraced()) {
+            TmfCoreTracer.traceRequest(this, "CANCELLED"); //$NON-NLS-1$
+        }
+    }
+
     /**
-     * this method is called by the event provider to set the index corresponding
-     * to the time range start time once it is known
+     * To suspend the client thread until the request starts (or is canceled).
      *
-     * @param index the start index
+     * @throws InterruptedException
+     *             If the thread was interrupted while waiting
      */
+    public void waitForStart() throws InterruptedException {
+        while (!fRequestRunning) {
+            startedLatch.await();
+        }
+    }
+
     @Override
-       public void setStartIndex(int index) {
-       setIndex(index);
+    public void waitForCompletion() throws InterruptedException {
+        while (!fRequestCompleted) {
+            completedLatch.await();
+        }
+    }
+
+    @Override
+    public void start() {
+        synchronized (this) {
+            fRequestRunning = true;
+        }
+        handleStarted();
+        startedLatch.countDown();
+    }
+
+    @Override
+    public void done() {
+        synchronized (this) {
+            if (!fRequestCompleted) {
+                fRequestRunning = false;
+                fRequestCompleted = true;
+            } else {
+                return;
+            }
+        }
+        try {
+            handleCompleted();
+        } finally {
+            completedLatch.countDown();
+        }
+    }
+
+    @Override
+    public void fail() {
+        synchronized (this) {
+            fRequestFailed = true;
+        }
+        done();
+    }
+
+    @Override
+    public void cancel() {
+        synchronized (this) {
+            fRequestCanceled = true;
+        }
+        done();
     }
 
     // ------------------------------------------------------------------------
@@ -207,23 +396,31 @@ public abstract class TmfEventRequest extends TmfDataRequest implements ITmfEven
     @Override
     // All requests have a unique id
     public int hashCode() {
-       return getRequestId();
+        return getRequestId();
     }
 
     @Override
     public boolean equals(Object other) {
-       if (other instanceof TmfEventRequest) {
-               TmfEventRequest request = (TmfEventRequest) other;
-               return super.equals(other) && request.fRange.equals(fRange);
-       }
-       return false;
+        if (other instanceof TmfEventRequest) {
+            TmfEventRequest request = (TmfEventRequest) other;
+            return request.fDataType == fDataType
+                    && request.fIndex == fIndex
+                    && request.fNbRequested == fNbRequested
+                    && request.fRange.equals(fRange);
+        }
+        return false;
     }
 
     @Override
-    @SuppressWarnings("nls")
     public String toString() {
-               return "[TmfEventRequest(" + getRequestId() + "," + getDataType().getSimpleName()
-                       + "," + getRange() + "," + getIndex() + "," + getNbRequested() + "," + getBlockSize() + ")]";
+        String name = getClass().getName();
+        int dot = name.lastIndexOf('.');
+        if (dot >= 0) {
+            name = name.substring(dot + 1);
+        }
+        return '[' + name + '(' + getRequestId() + ',' + getDataType().getSimpleName() +
+                ',' + getExecType() + ',' + getRange() + ',' + getIndex() +
+                ',' + getNbRequested() + ")]"; //$NON-NLS-1$
     }
 
 }
This page took 0.031116 seconds and 5 git commands to generate.