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=6f0148e4f7c229700f662ef6d82955301cf3c436;hpb=c84075b477a08d280c80c3122b22309086535330;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 6f0148e4f7..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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2015 Ericsson + * Copyright (c) 2012, 2016 Ericsson * Copyright (c) 2010, 2011 École Polytechnique de Montréal * Copyright (c) 2010, 2011 Alexandre Montplaisir * @@ -18,16 +18,13 @@ 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; -import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.CoreNode; -import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.HTConfig; -import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.HTInterval; -import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.HTNode; -import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.HistoryTree; +import org.eclipse.tracecompass.internal.statesystem.core.Activator; import org.eclipse.tracecompass.statesystem.core.backend.IStateHistoryBackend; import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException; import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException; @@ -35,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. @@ -43,12 +42,12 @@ import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue; */ public class HistoryTreeBackend implements IStateHistoryBackend { - private final @NonNull String ssid; + private final @NonNull String fSsid; /** * The history tree that sits underneath. */ - private final HistoryTree sht; + private final @NonNull IHistoryTree fSht; /** Indicates if the history tree construction is done */ private volatile boolean fFinishedBuilding = false; @@ -69,7 +68,7 @@ public class HistoryTreeBackend implements IStateHistoryBackend { * is the history tree finished building */ protected void setFinishedBuilding(boolean isFinishedBuilding) { - this.fFinishedBuilding = isFinishedBuilding; + fFinishedBuilding = isFinishedBuilding; } /** @@ -101,10 +100,10 @@ public class HistoryTreeBackend implements IStateHistoryBackend { long startTime, int blockSize, int maxChildren) throws IOException { - this.ssid = ssid; + fSsid = ssid; final HTConfig conf = new HTConfig(newStateFile, blockSize, maxChildren, providerVersion, startTime); - sht = new HistoryTree(conf); + fSht = initializeSHT(conf); } /** @@ -146,35 +145,71 @@ 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 { - this.ssid = ssid; - sht = new HistoryTree(existingStateFile, providerVersion); + fSsid = ssid; + 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() { - return sht; + protected final @NonNull IHistoryTree getSHT() { + return fSht; } @Override public String getSSID() { - return ssid; + return fSsid; } @Override public long getStartTime() { - return sht.getTreeStart(); + return getSHT().getTreeStart(); } @Override public long getEndTime() { - return sht.getTreeEnd(); + return getSHT().getTreeEnd(); } @Override @@ -184,46 +219,46 @@ public class HistoryTreeBackend implements IStateHistoryBackend { quark, (TmfStateValue) value); /* Start insertions at the "latest leaf" */ - sht.insertInterval(interval); + getSHT().insertInterval(interval); } @Override public void finishedBuilding(long endTime) { - sht.closeTree(endTime); + getSHT().closeTree(endTime); fFinishedBuilding = true; } @Override public FileInputStream supplyAttributeTreeReader() { - return sht.supplyATReader(); + return getSHT().supplyATReader(); } @Override public File supplyAttributeTreeWriterFile() { - return sht.supplyATWriterFile(); + return getSHT().supplyATWriterFile(); } @Override public long supplyAttributeTreeWriterFilePosition() { - return sht.supplyATWriterFilePos(); + return getSHT().supplyATWriterFilePos(); } @Override public void removeFiles() { - sht.deleteFile(); + getSHT().deleteFile(); } @Override public void dispose() { if (fFinishedBuilding) { - sht.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) */ - sht.deleteFile(); + getSHT().deleteFile(); } } @@ -232,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 = sht.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 = sht.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) { @@ -250,45 +291,44 @@ public class HistoryTreeBackend implements IStateHistoryBackend { * The stateInfo should now be filled with everything needed, we pass * the control back to the State System. */ - return; } @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) { - long treeStart = sht.getTreeStart(); - long treeEnd = sht.getTreeEnd(); - if (t < treeStart || t > treeEnd) { - throw new TimeRangeException(ssid + " Time:" + t + ", Start:" + treeStart + ", End:" + treeEnd); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + long startTime = getStartTime(); + long endTime = getEndTime(); + if (t < startTime || t > endTime) { + throw new TimeRangeException(String.format("%s Time:%d, Start:%d, End:%d", //$NON-NLS-1$ + fSsid, t, startTime, endTime)); } } /** * 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 = sht.getRootNode(); - HTInterval interval = currentNode.getRelevantInterval(key, t); - - try { - while (interval == null && currentNode.getNodeType() == HTNode.NodeType.CORE) { - currentNode = sht.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; } @@ -299,7 +339,7 @@ public class HistoryTreeBackend implements IStateHistoryBackend { * @return The current size of the history file in bytes */ public long getFileSize() { - return sht.getFileSize(); + return getSHT().getFileSize(); } /** @@ -313,45 +353,20 @@ public class HistoryTreeBackend implements IStateHistoryBackend { long ret; try { - for (int seq = 0; seq < sht.getNodeCount(); seq++) { - node = sht.readNode(seq); + for (int seq = 0; seq < getSHT().getNodeCount(); seq++) { + node = getSHT().readNode(seq); total += node.getNodeUsagePercent(); } } catch (ClosedChannelException e) { - e.printStackTrace(); + Activator.getDefault().logError(e.getMessage(), e); } - ret = total / sht.getNodeCount(); - assert (ret >= 0 && ret <= 100); + 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$ + } return (int) ret; } - @Override - public void debugPrint(PrintWriter writer) { - /* By default don't print out all the intervals */ - this.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(sht.toString()); - writer.println("Average node utilization: " //$NON-NLS-1$ - + this.getAverageNodeUsage()); - writer.println(""); //$NON-NLS-1$ - - sht.debugPrintFullTree(writer, printIntervals); - } }