X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=statesystem%2Forg.eclipse.tracecompass.statesystem.core%2Fsrc%2Forg%2Feclipse%2Ftracecompass%2Finternal%2Fstatesystem%2Fcore%2Fbackend%2Fhistorytree%2FHistoryTreeBackend.java;h=2aaa1e390c6ed9e271ef8a9566daaac781f50a76;hb=f4baf640acb2940d56ade46f42d7e5cbad0a598f;hp=ae8bf0d850cdac8e9a25c48fc6bee912c8ec7911;hpb=e8aa33258a6f3cf94b4e72edb8d9c69b00ee245f;p=deliverable%2Ftracecompass.git diff --git a/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HistoryTreeBackend.java b/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HistoryTreeBackend.java index ae8bf0d850..2aaa1e390c 100644 --- a/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HistoryTreeBackend.java +++ b/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HistoryTreeBackend.java @@ -18,8 +18,9 @@ package org.eclipse.tracecompass.internal.statesystem.core.backend.historytree; import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.io.PrintWriter; import java.nio.channels.ClosedChannelException; +import java.util.Deque; +import java.util.LinkedList; import java.util.List; import org.eclipse.jdt.annotation.NonNull; @@ -31,6 +32,8 @@ import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval; import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue; import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue; +import com.google.common.annotations.VisibleForTesting; + /** * History Tree backend for storing a state history. This is the basic version * that runs in the same thread as the class creating it. @@ -44,7 +47,7 @@ public class HistoryTreeBackend implements IStateHistoryBackend { /** * The history tree that sits underneath. */ - private final HistoryTree fSht; + private final @NonNull IHistoryTree fSht; /** Indicates if the history tree construction is done */ private volatile boolean fFinishedBuilding = false; @@ -100,7 +103,7 @@ public class HistoryTreeBackend implements IStateHistoryBackend { fSsid = ssid; final HTConfig conf = new HTConfig(newStateFile, blockSize, maxChildren, providerVersion, startTime); - fSht = new HistoryTree(conf); + fSht = initializeSHT(conf); } /** @@ -142,19 +145,55 @@ public class HistoryTreeBackend implements IStateHistoryBackend { * recognized, or if the version of the file does not match the * expected providerVersion. */ - public HistoryTreeBackend(@NonNull String ssid, File existingStateFile, int providerVersion) + public HistoryTreeBackend(@NonNull String ssid, @NonNull File existingStateFile, int providerVersion) throws IOException { fSsid = ssid; - fSht = new HistoryTree(existingStateFile, providerVersion); + fSht = initializeSHT(existingStateFile, providerVersion); fFinishedBuilding = true; } + /** + * New-tree initializer for the History Tree wrapped by this backend. Can be + * overriden to use different implementations. + * + * @param conf + * The HTConfig configuration object + * @return The new history tree + * @throws IOException + * If there was a problem during creation + */ + @VisibleForTesting + protected @NonNull IHistoryTree initializeSHT(@NonNull HTConfig conf) throws IOException { + return HistoryTreeFactory.createHistoryTree(conf); + } + + /** + * Existing-tree initializer for the History Tree wrapped by this backend. + * Can be overriden to use different implementations. + * + * @param existingStateFile + * The file to open + * @param providerVersion + * The expected state provider version + * @return The history tree opened from the given file + * @throws IOException + * If there was a problem during creation + */ + @VisibleForTesting + protected @NonNull IHistoryTree initializeSHT(@NonNull File existingStateFile, int providerVersion) throws IOException { + return HistoryTreeFactory.createFromFile(existingStateFile.toPath(), providerVersion); + } + /** * Get the History Tree built by this backend. * + * Note: Do not override this method. If you want to extend the class to use + * a different History Tree implementation, override both variants of + * {@link #initializeSHT} instead. + * * @return The history tree */ - protected HistoryTree getSHT() { + protected final @NonNull IHistoryTree getSHT() { return fSht; } @@ -165,12 +204,12 @@ public class HistoryTreeBackend implements IStateHistoryBackend { @Override public long getStartTime() { - return fSht.getTreeStart(); + return getSHT().getTreeStart(); } @Override public long getEndTime() { - return fSht.getTreeEnd(); + return getSHT().getTreeEnd(); } @Override @@ -180,46 +219,46 @@ public class HistoryTreeBackend implements IStateHistoryBackend { quark, (TmfStateValue) value); /* Start insertions at the "latest leaf" */ - fSht.insertInterval(interval); + getSHT().insertInterval(interval); } @Override public void finishedBuilding(long endTime) { - fSht.closeTree(endTime); + getSHT().closeTree(endTime); fFinishedBuilding = true; } @Override public FileInputStream supplyAttributeTreeReader() { - return fSht.supplyATReader(); + return getSHT().supplyATReader(); } @Override public File supplyAttributeTreeWriterFile() { - return fSht.supplyATWriterFile(); + return getSHT().supplyATWriterFile(); } @Override public long supplyAttributeTreeWriterFilePosition() { - return fSht.supplyATWriterFilePos(); + return getSHT().supplyATWriterFilePos(); } @Override public void removeFiles() { - fSht.deleteFile(); + getSHT().deleteFile(); } @Override public void dispose() { if (fFinishedBuilding) { - fSht.closeFile(); + getSHT().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) */ - fSht.deleteFile(); + getSHT().deleteFile(); } } @@ -228,14 +267,20 @@ public class HistoryTreeBackend implements IStateHistoryBackend { throws TimeRangeException, StateSystemDisposedException { checkValidTime(t); + /* Queue is a stack of nodes containing nodes intersecting t */ + Deque queue = new LinkedList<>(); + /* We start by reading the information in the root node */ - HTNode currentNode = fSht.getRootNode(); - currentNode.writeInfoFromNode(stateInfo, t); + queue.add(getSHT().getRootNode()); - /* Then we follow the branch down in the relevant children */ + /* Then we follow the down in the relevant children */ try { - while (currentNode.getNodeType() == HTNode.NodeType.CORE) { - currentNode = fSht.selectNextChild((CoreNode) currentNode, t); + while (!queue.isEmpty()) { + HTNode currentNode = queue.pop(); + if (currentNode.getNodeType() == HTNode.NodeType.CORE) { + /*Here we add the relevant children nodes for BFS*/ + queue.addAll(getSHT().selectNextChildren((ParentNode) currentNode, t)); + } currentNode.writeInfoFromNode(stateInfo, t); } } catch (ClosedChannelException e) { @@ -251,7 +296,11 @@ public class HistoryTreeBackend implements IStateHistoryBackend { @Override public ITmfStateInterval doSingularQuery(long t, int attributeQuark) throws TimeRangeException, StateSystemDisposedException { - return getRelevantInterval(t, attributeQuark); + try { + return getRelevantInterval(t, attributeQuark); + } catch (ClosedChannelException e) { + throw new StateSystemDisposedException(e); + } } private void checkValidTime(long t) { @@ -266,25 +315,20 @@ public class HistoryTreeBackend implements IStateHistoryBackend { /** * Inner method to find the interval in the tree containing the requested * key/timestamp pair, wherever in which node it is. - * - * @param t - * @param key - * @return The node containing the information we want */ private HTInterval getRelevantInterval(long t, int key) - throws TimeRangeException, StateSystemDisposedException { + throws TimeRangeException, ClosedChannelException { checkValidTime(t); - HTNode currentNode = fSht.getRootNode(); - HTInterval interval = currentNode.getRelevantInterval(key, t); - - try { - while (interval == null && currentNode.getNodeType() == HTNode.NodeType.CORE) { - currentNode = fSht.selectNextChild((CoreNode) currentNode, t); - interval = currentNode.getRelevantInterval(key, t); + Deque queue = new LinkedList<>(); + queue.add(getSHT().getRootNode()); + HTInterval interval = null; + while (interval == null && !queue.isEmpty()) { + HTNode currentNode = queue.pop(); + if (currentNode.getNodeType() == HTNode.NodeType.CORE) { + queue.addAll(getSHT().selectNextChildren((ParentNode) currentNode, t)); } - } catch (ClosedChannelException e) { - throw new StateSystemDisposedException(e); + interval = currentNode.getRelevantInterval(key, t); } return interval; } @@ -295,7 +339,7 @@ public class HistoryTreeBackend implements IStateHistoryBackend { * @return The current size of the history file in bytes */ public long getFileSize() { - return fSht.getFileSize(); + return getSHT().getFileSize(); } /** @@ -309,15 +353,15 @@ public class HistoryTreeBackend implements IStateHistoryBackend { long ret; try { - for (int seq = 0; seq < fSht.getNodeCount(); seq++) { - node = fSht.readNode(seq); + for (int seq = 0; seq < getSHT().getNodeCount(); seq++) { + node = getSHT().readNode(seq); total += node.getNodeUsagePercent(); } } catch (ClosedChannelException e) { Activator.getDefault().logError(e.getMessage(), e); } - ret = total / fSht.getNodeCount(); + ret = total / getSHT().getNodeCount(); /* The return value should be a percentage */ if (ret < 0 || ret > 100) { throw new IllegalStateException("Average node usage is not a percentage: " + ret); //$NON-NLS-1$ @@ -325,32 +369,4 @@ public class HistoryTreeBackend implements IStateHistoryBackend { return (int) ret; } - @Override - public void debugPrint(PrintWriter writer) { - /* By default don't print out all the intervals */ - debugPrint(writer, false); - } - - /** - * The basic debugPrint method will print the tree structure, but not their - * contents. - * - * This method here print the contents (the intervals) as well. - * - * @param writer - * The PrintWriter to which the debug info will be written - * @param printIntervals - * Should we also print every contained interval individually? - */ - public void debugPrint(PrintWriter writer, boolean printIntervals) { - /* Only used for debugging, shouldn't be externalized */ - writer.println("------------------------------"); //$NON-NLS-1$ - writer.println("State History Tree:\n"); //$NON-NLS-1$ - writer.println(fSht.toString()); - writer.println("Average node utilization: " //$NON-NLS-1$ - + getAverageNodeUsage()); - writer.println(""); //$NON-NLS-1$ - - fSht.debugPrintFullTree(writer, printIntervals); - } }