*/
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
*/
/* Latch tracking if the state history is done building or not */
private final CountDownLatch finishedLatch = new CountDownLatch(1);
+ private boolean buildCancelled = false;
+
/**
* General constructor
*
}
@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();
}
//--------------------------------------------------------------------------
+ ((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 */
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.
public HistoryTreeBackend(File existingStateFile) throws IOException {
sht = new HistoryTree(existingStateFile);
treeIO = sht.getTreeIO();
+ isFinishedBuilding = true;
}
@Override
@Override
public void finishedBuilding(long endTime) {
sht.closeTree(endTime);
+ isFinishedBuilding = true;
}
@Override
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 {
* 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;
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;
/**
* 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;
*/
/**
* 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"
/**
* 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"
* 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??
*/
@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
* 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) {
} catch (InterruptedException e) {
e.printStackTrace();
}
- return;
}
@Override
* 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
*/
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();
}
this.trace = trace;
}
+ @Override
+ public void dispose() {
+ cancelOngoingRequests();
+ }
+
@Override
public void updateStats(final boolean isGlobal, ITmfTimestamp start,
ITmfTimestamp end) {
// ITmfStatistics
// ------------------------------------------------------------------------
+ @Override
+ public void dispose() {
+ stats.dispose();
+ }
+
@Override
public void updateStats(final boolean isGlobal, final ITmfTimestamp start,
final ITmfTimestamp end) {
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);
*/
@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();
}