tmf: Add a method to query an ongoing state's start time
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / internal / tmf / core / statesystem / StateSystem.java
index c783eb40554089919ab72893f0ffb92faeb1032c..cd82f921198913a07891bc704d6c6458d1203808 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012 Ericsson
+ * Copyright (c) 2012, 2013 Ericsson
  * Copyright (c) 2010, 2011 École Polytechnique de Montréal
  * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
  *
@@ -18,16 +18,19 @@ import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.linuxtools.internal.tmf.core.Tracer;
+import org.eclipse.linuxtools.internal.tmf.core.Activator;
+import org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.IStateHistoryBackend;
 import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
+import org.eclipse.linuxtools.tmf.core.exceptions.StateSystemDisposedException;
 import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;
 import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
 import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;
 import org.eclipse.linuxtools.tmf.core.interval.TmfStateInterval;
-import org.eclipse.linuxtools.tmf.core.statesystem.IStateSystemBuilder;
+import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystemBuilder;
 import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue;
 import org.eclipse.linuxtools.tmf.core.statevalue.TmfStateValue;
 
@@ -44,18 +47,37 @@ import org.eclipse.linuxtools.tmf.core.statevalue.TmfStateValue;
  * @author alexmont
  *
  */
-public class StateSystem implements IStateSystemBuilder {
+public class StateSystem implements ITmfStateSystemBuilder {
 
     /* References to the inner structures */
     private final AttributeTree attributeTree;
     private final TransientState transState;
     private final IStateHistoryBackend backend;
 
+    /* Latch tracking if the state history is done building or not */
+    private final CountDownLatch finishedLatch = new CountDownLatch(1);
+
+    private boolean buildCancelled = false;
+    private boolean isDisposed = false;
+
+    /**
+     * New-file constructor. For when you build a state system with a new file,
+     * or if the back-end does not require a file on disk.
+     *
+     * @param backend
+     *            Back-end plugin to use
+     */
+    public StateSystem(IStateHistoryBackend backend) {
+        this.backend = backend;
+        this.transState = new TransientState(backend);
+        this.attributeTree = new AttributeTree(this);
+    }
+
     /**
      * General constructor
      *
      * @param backend
-     *            The "state history storage" backend to use.
+     *            The "state history storage" back-end to use.
      * @param newFile
      *            Put true if this is a new history started from scratch. It is
      *            used to tell the state system where to get its attribute tree.
@@ -73,7 +95,28 @@ public class StateSystem implements IStateSystemBuilder {
             /* We're opening an existing file */
             this.attributeTree = new AttributeTree(this, backend.supplyAttributeTreeReader());
             transState.setInactive();
+            finishedLatch.countDown(); /* The history is already built */
+        }
+    }
+
+    @Override
+    public boolean waitUntilBuilt() {
+        try {
+            finishedLatch.await();
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        return !buildCancelled;
+    }
+
+    @Override
+    public synchronized void dispose() {
+        isDisposed = true;
+        if (transState.isActive()) {
+            transState.setInactive();
+            buildCancelled = true;
         }
+        backend.dispose();
     }
 
     //--------------------------------------------------------------------------
@@ -147,6 +190,7 @@ public class StateSystem implements IStateSystemBuilder {
              */
             attributeTree.writeSelf(attributeTreeFile, attributeTreeFilePos);
         }
+        finishedLatch.countDown(); /* Mark the history as finished building */
     }
 
     //--------------------------------------------------------------------------
@@ -321,27 +365,29 @@ public class StateSystem implements IStateSystemBuilder {
         }
 
         stackDepth++;
-        subAttributeQuark = getQuarkRelativeAndAdd(attributeQuark,
-                stackDepth.toString());
+        subAttributeQuark = getQuarkRelativeAndAdd(attributeQuark, stackDepth.toString());
 
-        modifyAttribute(t, TmfStateValue.newValueInt(stackDepth),
-                attributeQuark);
+        modifyAttribute(t, TmfStateValue.newValueInt(stackDepth), attributeQuark);
         modifyAttribute(t, value, subAttributeQuark);
     }
 
     @Override
-    public void popAttribute(long t, int attributeQuark)
+    public ITmfStateValue popAttribute(long t, int attributeQuark)
             throws AttributeNotFoundException, TimeRangeException,
             StateValueTypeException {
-        Integer stackDepth;
-        int subAttributeQuark;
-        ITmfStateValue previousSV = transState.getOngoingStateValue(attributeQuark);
+        /* These are the state values of the stack-attribute itself */
+        ITmfStateValue previousSV = queryOngoingState(attributeQuark);
 
         if (previousSV.isNull()) {
-            /* Same as if stackDepth == 0, see below */
-            return;
+            /*
+             * Trying to pop an empty stack. This often happens at the start of
+             * traces, for example when we see a syscall_exit, without having
+             * the corresponding syscall_entry in the trace. Just ignore
+             * silently.
+             */
+            return null;
         }
-        if (previousSV.getType() != 0) {
+        if (previousSV.getType() != ITmfStateValue.TYPE_INTEGER) {
             /*
              * The existing value was a string, this doesn't look like a valid
              * stack attribute.
@@ -349,33 +395,34 @@ public class StateSystem implements IStateSystemBuilder {
             throw new StateValueTypeException();
         }
 
-        stackDepth = previousSV.unboxInt();
-
-        if (stackDepth == 0) {
-            /*
-             * Trying to pop an empty stack. This often happens at the start of
-             * traces, for example when we see a syscall_exit, without having
-             * the corresponding syscall_entry in the trace. Just ignore
-             * silently.
-             */
-            return;
-        }
+        Integer stackDepth = previousSV.unboxInt();
 
-        if (stackDepth < 0) {
+        if (stackDepth <= 0) {
             /* This on the other hand should not happen... */
-            String message = "A top-level stack attribute " + //$NON-NLS-1$
-                    "cannot have a negative integer value."; //$NON-NLS-1$
+            /* the case where == -1 was handled previously by .isNull() */
+            String message = "A top-level stack attribute cannot " + //$NON-NLS-1$
+                    "have a value of 0 or less (except -1/null)."; //$NON-NLS-1$
             throw new StateValueTypeException(message);
         }
 
-        /* The attribute should already exist... */
-        subAttributeQuark = getQuarkRelative(attributeQuark,
-                stackDepth.toString());
+        /* The attribute should already exist at this point */
+        int subAttributeQuark = getQuarkRelative(attributeQuark, stackDepth.toString());
+        ITmfStateValue poppedValue = queryOngoingState(subAttributeQuark);
 
-        stackDepth--;
-        modifyAttribute(t, TmfStateValue.newValueInt(stackDepth),
-                attributeQuark);
+        /* Update the state value of the stack-attribute */
+        ITmfStateValue nextSV;
+        if (--stackDepth == 0 ) {
+            /* Jump over "0" and store -1 (a null state value) */
+            nextSV = TmfStateValue.nullValue();
+        } else {
+            nextSV = TmfStateValue.newValueInt(stackDepth);
+        }
+        modifyAttribute(t, nextSV, attributeQuark);
+
+        /* Delete the sub-attribute that contained the user's state value */
         removeAttribute(t, subAttributeQuark);
+
+        return poppedValue;
     }
 
     @Override
@@ -416,21 +463,29 @@ public class StateSystem implements IStateSystemBuilder {
         return transState.getOngoingStateValue(attributeQuark);
     }
 
+    @Override
+    public long getOngoingStartTime(int attribute)
+            throws AttributeNotFoundException {
+        return transState.getOngoingStartTime(attribute);
+    }
+
     @Override
     public void updateOngoingState(ITmfStateValue newValue, int attributeQuark)
             throws AttributeNotFoundException {
         transState.changeOngoingStateValue(attributeQuark, newValue);
     }
 
-
-
     //--------------------------------------------------------------------------
     //        Regular query methods (sent to the back-end)
     //--------------------------------------------------------------------------
 
     @Override
     public synchronized List<ITmfStateInterval> queryFullState(long t)
-            throws TimeRangeException {
+            throws TimeRangeException, StateSystemDisposedException {
+        if (isDisposed) {
+            throw new StateSystemDisposedException();
+        }
+
         List<ITmfStateInterval> stateInfo = new ArrayList<ITmfStateInterval>(
                 attributeTree.getNbAttributes());
 
@@ -466,9 +521,13 @@ public class StateSystem implements IStateSystemBuilder {
 
     @Override
     public ITmfStateInterval querySingleState(long t, int attributeQuark)
-            throws AttributeNotFoundException, TimeRangeException {
-        ITmfStateInterval ret;
+            throws AttributeNotFoundException, TimeRangeException,
+            StateSystemDisposedException {
+        if (isDisposed) {
+            throw new StateSystemDisposedException();
+        }
 
+        ITmfStateInterval ret;
         if (transState.hasInfoAboutStateOf(t, attributeQuark)) {
             ret = transState.getOngoingInterval(attributeQuark);
         } else {
@@ -487,10 +546,36 @@ public class StateSystem implements IStateSystemBuilder {
         return ret;
     }
 
+    @Override
+    public ITmfStateInterval querySingleStackTop(long t, int stackAttributeQuark)
+            throws StateValueTypeException, AttributeNotFoundException,
+            TimeRangeException, StateSystemDisposedException {
+        Integer curStackDepth = querySingleState(t, stackAttributeQuark).getStateValue().unboxInt();
+
+        if (curStackDepth == -1) {
+            /* There is nothing stored in this stack at this moment */
+            return null;
+        } else if (curStackDepth < -1 || curStackDepth == 0) {
+            /*
+             * This attribute is an integer attribute, but it doesn't seem like
+             * it's used as a stack-attribute...
+             */
+            throw new StateValueTypeException();
+        }
+
+        int subAttribQuark = getQuarkRelative(stackAttributeQuark, curStackDepth.toString());
+        ITmfStateInterval ret = querySingleState(t, subAttribQuark);
+        return ret;
+    }
+
     @Override
     public List<ITmfStateInterval> queryHistoryRange(int attributeQuark,
             long t1, long t2) throws TimeRangeException,
-            AttributeNotFoundException {
+            AttributeNotFoundException, StateSystemDisposedException {
+        if (isDisposed) {
+            throw new StateSystemDisposedException();
+        }
+
         List<ITmfStateInterval> intervals;
         ITmfStateInterval currentInterval;
         long ts, tEnd;
@@ -526,13 +611,19 @@ public class StateSystem implements IStateSystemBuilder {
     @Override
     public List<ITmfStateInterval> queryHistoryRange(int attributeQuark,
             long t1, long t2, long resolution, IProgressMonitor monitor)
-            throws TimeRangeException, AttributeNotFoundException {
+            throws TimeRangeException, AttributeNotFoundException,
+            StateSystemDisposedException {
+        if (isDisposed) {
+            throw new StateSystemDisposedException();
+        }
+
         List<ITmfStateInterval> intervals;
         ITmfStateInterval currentInterval;
         long ts, tEnd;
 
-        if (monitor == null) {
-            monitor = new NullProgressMonitor();
+        IProgressMonitor mon = monitor;
+        if (mon == null) {
+            mon = new NullProgressMonitor();
         }
 
         /* Make sure the time range makes sense */
@@ -558,7 +649,7 @@ public class StateSystem implements IStateSystemBuilder {
          */
         for (ts = t1; (currentInterval.getEndTime() != -1) && (ts < tEnd);
                 ts += resolution) {
-            if (monitor.isCanceled()) {
+            if (mon.isCanceled()) {
                 return intervals;
             }
             if (ts <= currentInterval.getEndTime()) {
@@ -581,7 +672,7 @@ public class StateSystem implements IStateSystemBuilder {
     //--------------------------------------------------------------------------
 
     static void logMissingInterval(int attribute, long timestamp) {
-        Tracer.traceInfo("No data found in history for attribute " + //$NON-NLS-1$
+        Activator.logInfo("No data found in history for attribute " + //$NON-NLS-1$
                 attribute + " at time " + timestamp + //$NON-NLS-1$
                 ", returning dummy interval"); //$NON-NLS-1$
     }
This page took 0.028059 seconds and 5 git commands to generate.