tmf: Add dispose methods to the state and stats backends
authorAlexandre Montplaisir <alexmonthy@voxpopuli.im>
Thu, 1 Nov 2012 21:15:03 +0000 (17:15 -0400)
committerAlexandre Montplaisir <alexmonthy@voxpopuli.im>
Fri, 2 Nov 2012 17:52:31 +0000 (13:52 -0400)
When a trace/experiment is closed while a state history is
being built (either for storing kernel states or statistics),
the build should be cancelled as part of the trace's dispose().
This means the threads should be stopped cleanly, the files
should be closed, and any ongoing requests should be cancelled.

Change-Id: I0313ed37a927330a46b68024d1926922ddcaefb8
Signed-off-by: Alexandre Montplaisir <alexmonthy@voxpopuli.im>
Reviewed-on: https://git.eclipse.org/r/8491
Reviewed-by: Patrick Tasse <patrick.tasse@gmail.com>
IP-Clean: Patrick Tasse <patrick.tasse@gmail.com>
Tested-by: Hudson CI
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/IStateHistoryBackend.java
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/StateSystem.java
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/historytree/HT_IO.java
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/historytree/HistoryTreeBackend.java
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/historytree/ThreadedHistoryTreeBackend.java
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statesystem/ITmfStateSystem.java
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statistics/ITmfStatistics.java
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statistics/TmfEventsStatistics.java
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statistics/TmfStateStatistics.java
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/trace/TmfTrace.java

index 60de334a5008d5879b6efc9d0cc07e0c8e521a56..13c512b9c7e5412faee4f8642f16e1ef731fc779 100644 (file)
@@ -125,6 +125,12 @@ public interface IStateHistoryBackend {
      */
     public void removeFiles();
 
+    /**
+     * Notify the state history back-end that the trace is being closed, so it
+     * should release its file descriptors, close its connections, etc.
+     */
+    public void dispose();
+
     /**
      * @name Query methods
      */
index b302e49d568efc239ab281388c409864a1052aa7..527f7eee64f222f6aa384c81fd72b8caad122688 100644 (file)
@@ -55,6 +55,8 @@ public class StateSystem implements ITmfStateSystemBuilder {
     /* Latch tracking if the state history is done building or not */
     private final CountDownLatch finishedLatch = new CountDownLatch(1);
 
+    private boolean buildCancelled = false;
+
     /**
      * General constructor
      *
@@ -82,12 +84,22 @@ public class StateSystem implements ITmfStateSystemBuilder {
     }
 
     @Override
-    public void waitUntilBuilt() {
+    public boolean waitUntilBuilt() {
         try {
             finishedLatch.await();
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
+        return !buildCancelled;
+    }
+
+    @Override
+    public synchronized void dispose() {
+        if (transState.isActive()) {
+            transState.setInactive();
+            buildCancelled = true;
+        }
+        backend.dispose();
     }
 
     //--------------------------------------------------------------------------
index b3aaa7129e6eff40034144c3e305ef7a818ef243..6eb1ed5bc3953d375be0dfabab1a526c106c8007 100644 (file)
@@ -156,13 +156,17 @@ class HT_IO {
                 + ((long) tree.getNodeCount() * tree.config.blockSize);
     }
 
-    synchronized void deleteFile() {
+    synchronized void closeFile() {
         try {
             fis.close();
             fos.close();
         } catch (IOException e) {
             e.printStackTrace();
         }
+    }
+
+    synchronized void deleteFile() {
+        closeFile();
 
         if(!historyTreeFile.delete()) {
             /* We didn't succeed in deleting the file */
index 0e119a95c70cf85fc03808d5989ade07d5f44240..d13598022ffa00f75dfa24b7d2503f552c26e2f0 100644 (file)
@@ -36,6 +36,9 @@ public class HistoryTreeBackend implements IStateHistoryBackend {
     protected final HistoryTree sht;
     private final HT_IO treeIO;
 
+    /** Indicates if the history tree construction is done */
+    protected boolean isFinishedBuilding = false;
+
     /**
      * Construtor for new history files. Use this when creating a new history
      * from scratch.
@@ -89,6 +92,7 @@ public class HistoryTreeBackend implements IStateHistoryBackend {
     public HistoryTreeBackend(File existingStateFile) throws IOException {
         sht = new HistoryTree(existingStateFile);
         treeIO = sht.getTreeIO();
+        isFinishedBuilding = true;
     }
 
     @Override
@@ -114,6 +118,7 @@ public class HistoryTreeBackend implements IStateHistoryBackend {
     @Override
     public void finishedBuilding(long endTime) {
         sht.closeTree(endTime);
+        isFinishedBuilding = true;
     }
 
     @Override
@@ -136,6 +141,20 @@ public class HistoryTreeBackend implements IStateHistoryBackend {
         treeIO.deleteFile();
     }
 
+    @Override
+    public void dispose() {
+        if (isFinishedBuilding) {
+            treeIO.closeFile();
+        } else {
+            /*
+             * The build is being interrupted, delete the file we partially
+             * built since it won't be complete, so shouldn't be re-used in the
+             * future (.deleteFile() will close the file first)
+             */
+            treeIO.deleteFile();
+        }
+    }
+
     @Override
     public void doQuery(List<ITmfStateInterval> stateInfo, long t)
             throws TimeRangeException {
index 1874e7bfe8449cb7a05dc2a829bdfacfbbd7bd83..820a44a93368500760e17a7263eaf44cb30dece4 100644 (file)
@@ -2,12 +2,12 @@
  * Copyright (c) 2012 Ericsson
  * Copyright (c) 2010, 2011 École Polytechnique de Montréal
  * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
- * 
+ *
  * All rights reserved. This program and the accompanying materials are
  * made available under the terms of the Eclipse Public License v1.0 which
  * accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
- * 
+ *
  *******************************************************************************/
 
 package org.eclipse.linuxtools.internal.tmf.core.statesystem.historytree;
@@ -17,6 +17,7 @@ import java.io.IOException;
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.BlockingQueue;
 
+import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp;
 import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
 import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue;
 import org.eclipse.linuxtools.tmf.core.statevalue.TmfStateValue;
@@ -24,16 +25,16 @@ import org.eclipse.linuxtools.tmf.core.statevalue.TmfStateValue;
 /**
  * Variant of the HistoryTreeBackend which runs all the interval-insertion logic
  * in a separate thread.
- * 
+ *
  * @author alexmont
- * 
+ *
  */
 public final class ThreadedHistoryTreeBackend extends HistoryTreeBackend
         implements Runnable {
 
     /*
      * From superclass:
-     * 
+     *
      * protected final StateHistoryTree sht;
      */
 
@@ -42,10 +43,10 @@ public final class ThreadedHistoryTreeBackend extends HistoryTreeBackend
 
     /**
      * New state history constructor
-     * 
+     *
      * Note that it usually doesn't make sense to use a Threaded HT if you're
      * opening an existing state-file, but you know what you're doing...
-     * 
+     *
      * @param newStateFile
      *            The name of the history file that will be created. Should end
      *            in ".ht"
@@ -73,7 +74,7 @@ public final class ThreadedHistoryTreeBackend extends HistoryTreeBackend
     /**
      * New State History constructor. This version provides default values for
      * blockSize and maxChildren.
-     * 
+     *
      * @param newStateFile
      *            The name of the history file that will be created. Should end
      *            in ".ht"
@@ -98,7 +99,7 @@ public final class ThreadedHistoryTreeBackend extends HistoryTreeBackend
      * The Threaded version does not specify an "existing file" constructor,
      * since the history is already built (and we only use the other thread
      * during building). Just use a plain HistoryTreeProvider in this case.
-     * 
+     *
      * TODO but what about streaming??
      */
 
@@ -123,7 +124,6 @@ public final class ThreadedHistoryTreeBackend extends HistoryTreeBackend
 
     @Override
     public void finishedBuilding(long endTime) {
-        HTInterval pill;
         /*
          * We need to commit everything in the History Tree and stop the
          * standalone thread before returning to the StateHistorySystem. (SHS
@@ -131,13 +131,34 @@ public final class ThreadedHistoryTreeBackend extends HistoryTreeBackend
          * at the same time we are writing the last nodes!)
          */
 
+        stopRunningThread(endTime);
+        isFinishedBuilding = true;
+        return;
+    }
+
+    @Override
+    public void dispose() {
+        if (!isFinishedBuilding) {
+            stopRunningThread(TmfTimestamp.PROJECT_IS_CANNED.getValue());
+        }
         /*
-         * Send the "poison pill" in the queue, then wait for the HT to finish
+         * isFinishedBuilding remains false, so the superclass will ask the
+         * back-end to delete the file.
+         */
+        super.dispose();
+    }
+
+    private void stopRunningThread(long endTime) {
+        if (!shtThread.isAlive()) {
+            return;
+        }
+
+        /*
+         * Send a "poison pill" in the queue, then wait for the HT to finish
          * its closeTree()
          */
-        
         try {
-            pill = new HTInterval(-1, endTime, -1, TmfStateValue.nullValue());
+            HTInterval pill = new HTInterval(-1, endTime, -1, TmfStateValue.nullValue());
             intervalQueue.put(pill);
             shtThread.join();
         } catch (TimeRangeException e) {
@@ -145,7 +166,6 @@ public final class ThreadedHistoryTreeBackend extends HistoryTreeBackend
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
-        return;
     }
 
     @Override
index 91601d48c4c9b572823f69dbbb33b79c6e515d61..0c659591c1bb540bf9d747be74a09d1ead1ccd1a 100644 (file)
@@ -56,8 +56,19 @@ public interface ITmfStateSystem {
      * should return immediately. It's an alternative to listening to the
      * {@link org.eclipse.linuxtools.tmf.core.signal.TmfStateSystemBuildCompleted}
      * signal.
+     *
+     * @return If the build was successful. If false is returned, this either
+     *         means there was a problem during the build, or it got cancelled
+     *         before it could finished. In that case, no queries should be run
+     *         afterwards.
+     */
+    public boolean waitUntilBuilt();
+
+    /**
+     * Notify the state system that the trace is being closed, so it should
+     * clean up, close its files, etc.
      */
-    public void waitUntilBuilt();
+    public void dispose();
 
     /**
      * Return the current total amount of attributes in the system. This is also
index 7c1c078957f45553b3ef09ab63f968d3ba8278af..f3547ab6ad31b8ef820e70df7187af963bcee0c0 100644 (file)
@@ -87,4 +87,10 @@ public interface ITmfStatistics {
      */
     public Map<String, Long> getEventTypesInRange(ITmfTimestamp start,
             ITmfTimestamp end);
+
+    /**
+     * Notify the statistics back-end that the trace is being closed, so it
+     * should dispose itself as appropriate (release file descriptors, etc.)
+     */
+    public void dispose();
 }
index 39abdd368e22d2d8c534c24c83127ac75cc7fc8b..25253def782a92f936e8b1e5db758fffeef38262 100644 (file)
@@ -55,6 +55,11 @@ public class TmfEventsStatistics implements ITmfStatistics {
         this.trace = trace;
     }
 
+    @Override
+    public void dispose() {
+        cancelOngoingRequests();
+    }
+
     @Override
     public void updateStats(final boolean isGlobal, ITmfTimestamp start,
             ITmfTimestamp end) {
index a7f2d2a5ed6b7e095355511f3daef745abc67901..0d2e3db87ba5bbaa444c4a419d5adf520f79f286 100644 (file)
@@ -121,6 +121,11 @@ public class TmfStateStatistics implements ITmfStatistics {
     // ITmfStatistics
     // ------------------------------------------------------------------------
 
+    @Override
+    public void dispose() {
+        stats.dispose();
+    }
+
     @Override
     public void updateStats(final boolean isGlobal, final ITmfTimestamp start,
             final ITmfTimestamp end) {
@@ -137,7 +142,9 @@ public class TmfStateStatistics implements ITmfStatistics {
                 Map<String, Long> map;
 
                 /* Wait until the history building completed */
-                stats.waitUntilBuilt();
+                if (!stats.waitUntilBuilt()) {
+                    return;
+                }
 
                 /* Range should be valid for both global and time range queries */
                 total = getEventsInRange(start, end);
index 11290be95f33682723e0c49cc17a71cd47bceb67..d8b347cb451859613b7932a7232d483174f1d4a3 100644 (file)
@@ -270,10 +270,15 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
      */
     @Override
     public synchronized void dispose() {
-        // Clean up the index if applicable
+        /* Clean up the index if applicable */
         if (getIndexer() != null) {
             getIndexer().dispose();
         }
+
+        /* Clean up the statistics */
+        if (fStatistics != null) {
+            fStatistics.dispose();
+        }
         super.dispose();
     }
 
This page took 0.068167 seconds and 5 git commands to generate.