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 32dd8fb211545f591615e6bfaade76d168fe6dc9..c37bb1173a367b2462561c04297906862da01161 100644 (file)
  *
  * Contributors:
  *   Francois Chouinard - Initial API and implementation
- *   Alexandre Montplaisir - Consolidated constructors
+ *   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;
 
     // ------------------------------------------------------------------------
-    // Constructor
+    // Constructors
     // ------------------------------------------------------------------------
 
     /**
-     * Request 'n' events of a given type for the given time range (given
-     * priority). Events are returned in blocks of the given size.
+     * Request 'n' events of a given type, for the *whole* trace, at the given
+     * priority.
+     *
+     * @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,
+            long index,
+            int nbRequested,
+            ExecutionType priority) {
+        this(dataType, TmfTimeRange.ETERNITY, index, nbRequested, priority);
+    }
+
+    /**
+     * Request 'n' events of a given type, for the given time range, at the
+     * given priority.
      *
      * @param dataType
      *            The requested data type.
@@ -54,22 +147,33 @@ public abstract class TmfEventRequest extends TmfDataRequest implements ITmfEven
      *            events in the time range.
      * @param priority
      *            The requested execution priority.
-     * @since 3.0
      */
     public TmfEventRequest(Class<? extends ITmfEvent> dataType,
             TmfTimeRange range,
             long index,
             int nbRequested,
             ExecutionType priority) {
-        super(dataType, index, nbRequested, 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() == ITmfDataRequest.ExecutionType.BACKGROUND ? "(BG)" : "(FG)")
+                    + (getExecType() == ExecutionType.BACKGROUND ? "(BG)" : "(FG)")
                     + " Type=" + type + " Index=" + getIndex() + " NbReq=" + getNbRequested()
                     + " Range=" + getRange()
                     + " DataType=" + getDataType().getSimpleName();
@@ -77,14 +181,70 @@ public abstract class TmfEventRequest extends TmfDataRequest implements ITmfEven
         }
     }
 
+    /**
+     * Resets the request counter (used for testing)
+     */
+    public static void reset() {
+        fRequestNumber = 0;
+    }
+
     // ------------------------------------------------------------------------
     // Accessors
     // ------------------------------------------------------------------------
 
+    @Override
+    public int getRequestId() {
+        return fRequestId;
+    }
+
+    @Override
+    public long getIndex() {
+        return fIndex;
+    }
+
     /**
-     * @return the requested time range
-     * @since 2.0
+     * @since 3.0
      */
+    @Override
+    public ExecutionType getExecType() {
+        return fExecType;
+    }
+
+    @Override
+    public int getNbRequested() {
+        return fNbRequested;
+    }
+
+    @Override
+    public synchronized int getNbRead() {
+        return fNbRead;
+    }
+
+    @Override
+    public synchronized boolean isRunning() {
+        return fRequestRunning;
+    }
+
+    @Override
+    public synchronized boolean isCompleted() {
+        return fRequestCompleted;
+    }
+
+    @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;
@@ -95,17 +255,140 @@ public abstract class TmfEventRequest extends TmfDataRequest implements ITmfEven
     // ------------------------------------------------------------------------
 
     /**
-     * this method is called by the event provider to set the index
-     * corresponding to the time range start time once it is known
+     * This method is called by the event provider to set the index
+     * corresponding to the time range start time
      *
      * @param index
-     *            the start index
+     *            The start time index
      */
+    protected void setIndex(int index) {
+        fIndex = index;
+    }
+
     @Override
     public void setStartIndex(int index) {
         setIndex(index);
     }
 
+    // ------------------------------------------------------------------------
+    // 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$
+        }
+    }
+
+    /**
+     * To suspend the client thread until the request starts (or is canceled).
+     *
+     * @throws InterruptedException
+     *             If the thread was interrupted while waiting
+     */
+    public void waitForStart() throws InterruptedException {
+        while (!fRequestRunning) {
+            startedLatch.await();
+        }
+    }
+
+    @Override
+    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();
+    }
+
     // ------------------------------------------------------------------------
     // Object
     // ------------------------------------------------------------------------
@@ -120,21 +403,24 @@ public abstract class TmfEventRequest extends TmfDataRequest implements ITmfEven
     public boolean equals(Object other) {
         if (other instanceof TmfEventRequest) {
             TmfEventRequest request = (TmfEventRequest) other;
-            return super.equals(other) && request.fRange.equals(fRange);
+            return request.fDataType == fDataType
+                    && request.fIndex == fIndex
+                    && request.fNbRequested == fNbRequested
+                    && request.fRange.equals(fRange);
         }
         return false;
     }
 
     @Override
-    @SuppressWarnings("nls")
     public String toString() {
         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() + ")]";
+        return '[' + name + '(' + getRequestId() + ',' + getDataType().getSimpleName() +
+                ',' + getExecType() + ',' + getRange() + ',' + getIndex() +
+                ',' + getNbRequested() + ")]"; //$NON-NLS-1$
     }
 
 }
This page took 0.036494 seconds and 5 git commands to generate.