From 3a081e85a42e35059bc45c53ad914eeb61af6f1f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Genevi=C3=A8ve=20Bastien?= Date: Sun, 10 Jul 2016 21:51:30 -0400 Subject: [PATCH] ss: Extract an history tree interface MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This is a second step towards supporting multiple types of SHTs Change-Id: I294ae4991207fac30700ef803f529f3f14e4417b Signed-off-by: Geneviève Bastien Signed-off-by: Alexandre Montplaisir Reviewed-on: https://git.eclipse.org/r/77007 Reviewed-by: Hudson CI --- .../backend/historytree/HistoryTreeTest.java | 24 +-- .../HistoryTreeWithBackendTest.java | 37 +++- .../stubs/backend/HistoryTreeBackendStub.java | 51 ++++- ...eStub.java => HistoryTreeClassicStub.java} | 14 +- .../core/backend/historytree/HTConfig.java | 2 +- .../core/backend/historytree/HT_IO.java | 2 +- .../historytree/HistoryTreeBackend.java | 8 +- ...storyTree.java => HistoryTreeClassic.java} | 137 ++----------- .../historytree/HistoryTreeFactory.java | 11 +- .../backend/historytree/IHistoryTree.java | 184 ++++++++++++++++++ 10 files changed, 313 insertions(+), 157 deletions(-) rename statesystem/org.eclipse.tracecompass.statesystem.core.tests/stubs/org/eclipse/tracecompass/statesystem/core/tests/stubs/backend/{HistoryTreeStub.java => HistoryTreeClassicStub.java} (92%) rename statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/{HistoryTree.java => HistoryTreeClassic.java} (86%) create mode 100644 statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/IHistoryTree.java diff --git a/statesystem/org.eclipse.tracecompass.statesystem.core.tests/src/org/eclipse/tracecompass/statesystem/core/tests/backend/historytree/HistoryTreeTest.java b/statesystem/org.eclipse.tracecompass.statesystem.core.tests/src/org/eclipse/tracecompass/statesystem/core/tests/backend/historytree/HistoryTreeTest.java index c90f7142a1..13b759c353 100644 --- a/statesystem/org.eclipse.tracecompass.statesystem.core.tests/src/org/eclipse/tracecompass/statesystem/core/tests/backend/historytree/HistoryTreeTest.java +++ b/statesystem/org.eclipse.tracecompass.statesystem.core.tests/src/org/eclipse/tracecompass/statesystem/core/tests/backend/historytree/HistoryTreeTest.java @@ -22,9 +22,9 @@ import org.eclipse.jdt.annotation.Nullable; 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.backend.historytree.IHistoryTree; import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue; -import org.eclipse.tracecompass.statesystem.core.tests.stubs.backend.HistoryTreeStub; +import org.eclipse.tracecompass.statesystem.core.tests.stubs.backend.HistoryTreeClassicStub; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -38,7 +38,7 @@ public class HistoryTreeTest { /* Minimal allowed blocksize */ - private static final int BLOCK_SIZE = HistoryTree.TREE_HEADER_SIZE; + private static final int BLOCK_SIZE = HistoryTreeClassicStub.MINIMUM_BLOCK_SIZE; private static final HTInterval NULL_INTERVAL = new HTInterval(10, 20, 1, TmfStateValue.nullValue()); @@ -84,8 +84,8 @@ public class HistoryTreeTest { * The max number of children per node in the tree (tree config * option) */ - private HistoryTreeStub setupSmallTree(int maxChildren) { - HistoryTreeStub ht = null; + private HistoryTreeClassicStub setupSmallTree(int maxChildren) { + HistoryTreeClassicStub ht = null; try { File newFile = fTempFile; assertNotNull(newFile); @@ -94,7 +94,7 @@ public class HistoryTreeTest { maxChildren, /* Number of children */ 1, /* Provider version */ 1); /* Start time */ - ht = new HistoryTreeStub(config); + ht = new HistoryTreeClassicStub(config); } catch (IOException e) { fail(e.getMessage()); @@ -107,11 +107,11 @@ public class HistoryTreeTest { /** * Setup a history tree with config MAX_CHILDREN = 3. */ - private HistoryTreeStub setupSmallTree() { + private HistoryTreeClassicStub setupSmallTree() { return setupSmallTree(3); } - private static long fillValues(HistoryTree ht, TmfStateValue value, int nbValues, long start) { + private static long fillValues(IHistoryTree ht, TmfStateValue value, int nbValues, long start) { for (int i = 0; i < nbValues; i++) { ht.insertInterval(new HTInterval(start + i, start + i + 1, 1, value)); } @@ -130,7 +130,7 @@ public class HistoryTreeTest { * greater than or equal to this to make sure the intervals go in * the leaf node. */ - private static long fillNextLeafNode(HistoryTreeStub ht, long leafNodeStart) { + private static long fillNextLeafNode(HistoryTreeClassicStub ht, long leafNodeStart) { int prevCount = ht.getNodeCount(); int prevDepth = ht.getDepth(); @@ -156,7 +156,7 @@ public class HistoryTreeTest { */ @Test public void testSequentialFill() { - HistoryTreeStub ht = setupSmallTree(); + HistoryTreeClassicStub ht = setupSmallTree(); HTNode node = ht.getLatestLeaf(); assertEquals(0, node.getNodeUsagePercent()); @@ -197,7 +197,7 @@ public class HistoryTreeTest { */ @Test public void testDepth() { - HistoryTreeStub ht = setupSmallTree(); + HistoryTreeClassicStub ht = setupSmallTree(); /* Fill a first node */ HTNode node = ht.getLatestLeaf(); @@ -266,7 +266,7 @@ public class HistoryTreeTest { /* Represents the start time of the current leaf node */ long start = 1; - HistoryTreeStub ht = setupSmallTree(2); + HistoryTreeClassicStub ht = setupSmallTree(2); start = fillNextLeafNode(ht, start); List branch = ht.getLatestBranch(); diff --git a/statesystem/org.eclipse.tracecompass.statesystem.core.tests/src/org/eclipse/tracecompass/statesystem/core/tests/backend/historytree/HistoryTreeWithBackendTest.java b/statesystem/org.eclipse.tracecompass.statesystem.core.tests/src/org/eclipse/tracecompass/statesystem/core/tests/backend/historytree/HistoryTreeWithBackendTest.java index 27f57ff9e5..85ca8dcf7d 100644 --- a/statesystem/org.eclipse.tracecompass.statesystem.core.tests/src/org/eclipse/tracecompass/statesystem/core/tests/backend/historytree/HistoryTreeWithBackendTest.java +++ b/statesystem/org.eclipse.tracecompass.statesystem.core.tests/src/org/eclipse/tracecompass/statesystem/core/tests/backend/historytree/HistoryTreeWithBackendTest.java @@ -13,22 +13,28 @@ import static org.junit.Assert.fail; import java.io.File; import java.io.IOException; +import java.util.Arrays; import org.eclipse.tracecompass.common.core.NonNullUtils; 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.backend.historytree.HistoryTreeBackend; +import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.IHistoryTree; import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue; import org.eclipse.tracecompass.statesystem.core.tests.stubs.backend.HistoryTreeBackendStub; +import org.eclipse.tracecompass.statesystem.core.tests.stubs.backend.HistoryTreeBackendStub.HistoryTreeType; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; /** * Test the {@link HistoryTreeBackend}-specific behavior and its interactions - * with the {@link HistoryTree} class + * with the {@link IHistoryTree} classes. * * @author Geneviève Bastien */ +@RunWith(Parameterized.class) public class HistoryTreeWithBackendTest { /** State system ID */ @@ -41,6 +47,28 @@ public class HistoryTreeWithBackendTest { /** Default block size */ private static final int BLOCK_SIZE = 4096; + private final HistoryTreeType fHtType; + + /** + * @return The arrays of parameters + */ + @Parameters(name = "{0}") + public static Iterable getParameters() { + return Arrays.asList(new Object[][] { + { HistoryTreeType.CLASSIC } + }); + } + + /** + * Constructor + * + * @param htType + * The type of history tree to use + */ + public HistoryTreeWithBackendTest(HistoryTreeType htType) { + fHtType = htType; + } + /** * Test the behavior of the history tree after at least a depth of 3 */ @@ -53,6 +81,7 @@ public class HistoryTreeWithBackendTest { long startTime = 1; File historyTreeFile = NonNullUtils.checkNotNull(File.createTempFile("HistoryTreeBackendTest", ".ht")); + HistoryTreeBackendStub.setTreeType(fHtType); HistoryTreeBackendStub backend = new HistoryTreeBackendStub(SSID, historyTreeFile, PROVIDER_VERSION, startTime, BLOCK_SIZE, MAX_CHILDREN); int duration = nbAttr; @@ -64,8 +93,8 @@ public class HistoryTreeWithBackendTest { backend.insertPastState(interval.getStartTime(), interval.getEndTime(), interval.getAttribute(), interval.getStateValue()); /* - * insert cascading intervals to fill 2 levels of history - * tree, so that we start another branch + * insert cascading intervals to fill 2 levels of history tree, so + * that we start another branch */ while (backend.getHistoryTree().getDepth() < depthToRead) { backend.insertPastState( diff --git a/statesystem/org.eclipse.tracecompass.statesystem.core.tests/stubs/org/eclipse/tracecompass/statesystem/core/tests/stubs/backend/HistoryTreeBackendStub.java b/statesystem/org.eclipse.tracecompass.statesystem.core.tests/stubs/org/eclipse/tracecompass/statesystem/core/tests/stubs/backend/HistoryTreeBackendStub.java index 4405a55e29..0aa13f6a5b 100644 --- a/statesystem/org.eclipse.tracecompass.statesystem.core.tests/stubs/org/eclipse/tracecompass/statesystem/core/tests/stubs/backend/HistoryTreeBackendStub.java +++ b/statesystem/org.eclipse.tracecompass.statesystem.core.tests/stubs/org/eclipse/tracecompass/statesystem/core/tests/stubs/backend/HistoryTreeBackendStub.java @@ -13,17 +13,42 @@ import java.io.File; import java.io.IOException; import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.HTConfig; -import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.HistoryTree; import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.HistoryTreeBackend; +import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.IHistoryTree; /** * Stub class for the {@link HistoryTreeBackend}. It creates a - * {@link HistoryTreeStub} to grant access to some protected methods. + * {@link HistoryTreeClassicStub} to grant access to some protected methods. * * @author Geneviève Bastien */ public class HistoryTreeBackendStub extends HistoryTreeBackend { + private static HistoryTreeType HT_TYPE = HistoryTreeType.CLASSIC; + + /** + * Sets the type of tree to build. Since the history tree is initialized in + * the parent's constructor, this stub class needs to know the type of tree + * to build. + * + * @param htType + * The type of history tree to build for this backend + */ + public static void setTreeType(HistoryTreeType htType) { + HT_TYPE = htType; + } + + /** + * Enumeration of all history tree types implemented. This will be used to + * create the right type of history tree + */ + public enum HistoryTreeType { + /** + * The classic history tree + */ + CLASSIC + } + /** * Constructor for new history files. Use this when creating a new history * from scratch. @@ -76,13 +101,23 @@ public class HistoryTreeBackendStub extends HistoryTreeBackend { } @Override - protected HistoryTree initializeSHT(HTConfig conf) throws IOException { - return new HistoryTreeStub(conf); + protected IHistoryTree initializeSHT(HTConfig conf) throws IOException { + switch (HT_TYPE) { + case CLASSIC: + return new HistoryTreeClassicStub(conf); + default: + return new HistoryTreeClassicStub(conf); + } } @Override - protected HistoryTree initializeSHT(File existingStateFile, int providerVersion) throws IOException { - return new HistoryTreeStub(existingStateFile, providerVersion); + protected IHistoryTree initializeSHT(File existingStateFile, int providerVersion) throws IOException { + switch (HT_TYPE) { + case CLASSIC: + return new HistoryTreeClassicStub(existingStateFile, providerVersion); + default: + return new HistoryTreeClassicStub(existingStateFile, providerVersion); + } } /** @@ -90,8 +125,8 @@ public class HistoryTreeBackendStub extends HistoryTreeBackend { * * @return The history tree */ - public HistoryTreeStub getHistoryTree() { - return (HistoryTreeStub) super.getSHT(); + public HistoryTreeClassicStub getHistoryTree() { + return (HistoryTreeClassicStub) super.getSHT(); } } diff --git a/statesystem/org.eclipse.tracecompass.statesystem.core.tests/stubs/org/eclipse/tracecompass/statesystem/core/tests/stubs/backend/HistoryTreeStub.java b/statesystem/org.eclipse.tracecompass.statesystem.core.tests/stubs/org/eclipse/tracecompass/statesystem/core/tests/stubs/backend/HistoryTreeClassicStub.java similarity index 92% rename from statesystem/org.eclipse.tracecompass.statesystem.core.tests/stubs/org/eclipse/tracecompass/statesystem/core/tests/stubs/backend/HistoryTreeStub.java rename to statesystem/org.eclipse.tracecompass.statesystem.core.tests/stubs/org/eclipse/tracecompass/statesystem/core/tests/stubs/backend/HistoryTreeClassicStub.java index 9c5937af68..b46894d478 100644 --- a/statesystem/org.eclipse.tracecompass.statesystem.core.tests/stubs/org/eclipse/tracecompass/statesystem/core/tests/stubs/backend/HistoryTreeStub.java +++ b/statesystem/org.eclipse.tracecompass.statesystem.core.tests/stubs/org/eclipse/tracecompass/statesystem/core/tests/stubs/backend/HistoryTreeClassicStub.java @@ -22,7 +22,8 @@ import java.util.List; 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.HTNode; -import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.HistoryTree; +import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.HistoryTreeClassic; +import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.IHistoryTree; import com.google.common.collect.Iterables; @@ -35,7 +36,12 @@ import com.google.common.collect.Iterables; * * @author Geneviève Bastien */ -public class HistoryTreeStub extends HistoryTree { +public class HistoryTreeClassicStub extends HistoryTreeClassic { + + /** + * Minimum size a block of this tree should have + */ + public static final int MINIMUM_BLOCK_SIZE = IHistoryTree.TREE_HEADER_SIZE; /** * Constructor for this history tree stub @@ -46,7 +52,7 @@ public class HistoryTreeStub extends HistoryTree { * If an error happens trying to open/write to the file * specified in the config */ - public HistoryTreeStub(HTConfig conf) throws IOException { + public HistoryTreeClassicStub(HTConfig conf) throws IOException { super(conf); } @@ -61,7 +67,7 @@ public class HistoryTreeStub extends HistoryTree { * @throws IOException * If an error happens reading the file */ - public HistoryTreeStub(File existingStateFile, int expProviderVersion) throws IOException { + public HistoryTreeClassicStub(File existingStateFile, int expProviderVersion) throws IOException { super(existingStateFile, expProviderVersion); } diff --git a/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HTConfig.java b/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HTConfig.java index 3340254b82..597df81238 100644 --- a/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HTConfig.java +++ b/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HTConfig.java @@ -15,7 +15,7 @@ package org.eclipse.tracecompass.internal.statesystem.core.backend.historytree; import java.io.File; /** - * Configuration object for the {@link HistoryTree}. + * Configuration object for the {@link IHistoryTree}. * * @author Alexandre Montplaisir */ diff --git a/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HT_IO.java b/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HT_IO.java index ef04a424e4..c69c51b6e1 100644 --- a/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HT_IO.java +++ b/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HT_IO.java @@ -270,7 +270,7 @@ class HT_IO { * Cast to (long) is needed to make sure the result is a long too and * doesn't get truncated */ - fc.position(HistoryTree.TREE_HEADER_SIZE + fc.position(IHistoryTree.TREE_HEADER_SIZE + ((long) seqNumber) * fConfig.getBlockSize()); } 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 75cea1a518..344c3b0f11 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 @@ -46,7 +46,7 @@ public class HistoryTreeBackend implements IStateHistoryBackend { /** * The history tree that sits underneath. */ - private final @NonNull HistoryTree fSht; + private final @NonNull IHistoryTree fSht; /** Indicates if the history tree construction is done */ private volatile boolean fFinishedBuilding = false; @@ -162,7 +162,7 @@ public class HistoryTreeBackend implements IStateHistoryBackend { * If there was a problem during creation */ @VisibleForTesting - protected @NonNull HistoryTree initializeSHT(@NonNull HTConfig conf) throws IOException { + protected @NonNull IHistoryTree initializeSHT(@NonNull HTConfig conf) throws IOException { return HistoryTreeFactory.createHistoryTree(conf); } @@ -179,7 +179,7 @@ public class HistoryTreeBackend implements IStateHistoryBackend { * If there was a problem during creation */ @VisibleForTesting - protected @NonNull HistoryTree initializeSHT(@NonNull File existingStateFile, int providerVersion) throws IOException { + protected @NonNull IHistoryTree initializeSHT(@NonNull File existingStateFile, int providerVersion) throws IOException { return HistoryTreeFactory.createFromFile(existingStateFile.toPath(), providerVersion); } @@ -192,7 +192,7 @@ public class HistoryTreeBackend implements IStateHistoryBackend { * * @return The history tree */ - protected final @NonNull HistoryTree getSHT() { + protected final @NonNull IHistoryTree getSHT() { return fSht; } diff --git a/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HistoryTree.java b/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HistoryTreeClassic.java similarity index 86% rename from statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HistoryTree.java rename to statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HistoryTreeClassic.java index d675866e07..8bf229dccd 100644 --- a/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HistoryTree.java +++ b/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HistoryTreeClassic.java @@ -40,14 +40,7 @@ import com.google.common.collect.ImmutableList; * * @author Alexandre Montplaisir */ -public class HistoryTree { - - /** - * Size of the "tree header" in the tree-file The nodes will use this offset - * to know where they should be in the file. This should always be a - * multiple of 4K. - */ - public static final int TREE_HEADER_SIZE = 4096; +public class HistoryTreeClassic implements IHistoryTree { /** * The magic number for this file format. Package-private for the factory @@ -95,7 +88,7 @@ public class HistoryTree { * If an error happens trying to open/write to the file * specified in the config */ - public HistoryTree(HTConfig conf) throws IOException { + public HistoryTreeClassic(HTConfig conf) throws IOException { /* * Simple check to make sure we have enough place in the 0th block for * the tree configuration @@ -128,7 +121,7 @@ public class HistoryTree { * @throws IOException * If an error happens reading the file */ - public HistoryTree(File existingStateFile, int expProviderVersion) throws IOException { + public HistoryTreeClassic(File existingStateFile, int expProviderVersion) throws IOException { /* * Open the file ourselves, get the tree header information we need, * then pass on the descriptor to the TreeIO object. @@ -236,15 +229,7 @@ public class HistoryTree { return Collections.synchronizedList(list); } - /** - * "Save" the tree to disk. This method will cause the treeIO object to - * commit all nodes to disk and then return the RandomAccessFile descriptor - * so the Tree object can save its configuration into the header of the - * file. - * - * @param requestedEndTime - * The greatest timestamp present in the history tree - */ + @Override public void closeTree(long requestedEndTime) { /* This is an important operation, queries can wait */ synchronized (fLatestBranch) { @@ -307,38 +292,22 @@ public class HistoryTree { // Accessors // ------------------------------------------------------------------------ - /** - * Get the start time of this tree. - * - * @return The start time - */ + @Override public long getTreeStart() { return fConfig.getTreeStart(); } - /** - * Get the current end time of this tree. - * - * @return The end time - */ + @Override public long getTreeEnd() { return fTreeEnd; } - /** - * Get the number of nodes in this tree. - * - * @return The number of nodes - */ + @Override public int getNodeCount() { return fNodeCount; } - /** - * Get the current root node of this tree - * - * @return The root node - */ + @Override public HTNode getRootNode() { return fLatestBranch.get(0); } @@ -378,46 +347,23 @@ public class HistoryTree { // HT_IO interface // ------------------------------------------------------------------------ - /** - * Return the FileInputStream reader with which we will read an attribute - * tree (it will be sought to the correct position). - * - * @return The FileInputStream indicating the file and position from which - * the attribute tree can be read. - */ + @Override public FileInputStream supplyATReader() { return fTreeIO.supplyATReader(getNodeCount()); } - /** - * Return the file to which we will write the attribute tree. - * - * @return The file to which we will write the attribute tree - */ + @Override public File supplyATWriterFile() { return fConfig.getStateFile(); } - /** - * Return the position in the file (given by {@link #supplyATWriterFile}) - * where to start writing the attribute tree. - * - * @return The position in the file where to start writing - */ + @Override public long supplyATWriterFilePos() { - return HistoryTree.TREE_HEADER_SIZE + return IHistoryTree.TREE_HEADER_SIZE + ((long) getNodeCount() * fConfig.getBlockSize()); } - /** - * Read a node from the tree. - * - * @param seqNumber - * The sequence number of the node to read - * @return The node - * @throws ClosedChannelException - * If the tree IO is unavailable - */ + @Override public HTNode readNode(int seqNumber) throws ClosedChannelException { /* Try to read the node from memory */ synchronized (fLatestBranch) { @@ -432,26 +378,17 @@ public class HistoryTree { return fTreeIO.readNode(seqNumber); } - /** - * Write a node object to the history file. - * - * @param node - * The node to write to disk - */ + @Override public void writeNode(HTNode node) { fTreeIO.writeNode(node); } - /** - * Close the history file. - */ + @Override public void closeFile() { fTreeIO.closeFile(); } - /** - * Delete the history file. - */ + @Override public void deleteFile() { fTreeIO.deleteFile(); } @@ -460,14 +397,7 @@ public class HistoryTree { // Operations // ------------------------------------------------------------------------ - /** - * Insert an interval in the tree. - * - * @param interval - * The interval to be inserted - * @throws TimeRangeException - * If the start of end time of the interval are invalid - */ + @Override public void insertInterval(HTInterval interval) throws TimeRangeException { if (interval.getStartTime() < fConfig.getTreeStart()) { throw new TimeRangeException("Interval Start:" + interval.getStartTime() + ", Config Start:" + fConfig.getTreeStart()); //$NON-NLS-1$ //$NON-NLS-2$ @@ -650,19 +580,7 @@ public class HistoryTree { return newNode; } - /** - * Inner method to select the next child of the current node intersecting - * the given timestamp. Useful for moving down the tree following one - * branch. - * - * @param currentNode - * The node on which the request is made - * @param t - * The timestamp to choose which child is the next one - * @return The child node intersecting t - * @throws ClosedChannelException - * If the file channel was closed while we were reading the tree - */ + @Override public HTNode selectNextChild(CoreNode currentNode, long t) throws ClosedChannelException { assert (currentNode.getNbChildren() > 0); int potentialNextSeqNb = currentNode.getSequenceNumber(); @@ -694,11 +612,7 @@ public class HistoryTree { return readNode(potentialNextSeqNb); } - /** - * Get the current size of the history file. - * - * @return The history file size - */ + @Override public long getFileSize() { return fConfig.getStateFile().length(); } @@ -774,18 +688,7 @@ public class HistoryTree { } } - /** - * Print out the full tree for debugging purposes - * - * @param writer - * PrintWriter in which to write the output - * @param printIntervals - * Flag to enable full output of the interval information - * @param ts - * The timestamp that nodes have to intersect for intervals to be - * printed. A negative value will print intervals for all nodes. - * The timestamp only applies if printIntervals is true. - */ + @Override public void debugPrintFullTree(PrintWriter writer, boolean printIntervals, long ts) { /* Only used for debugging, shouldn't be externalized */ diff --git a/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HistoryTreeFactory.java b/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HistoryTreeFactory.java index bdf9bde3c4..61aae2307c 100644 --- a/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HistoryTreeFactory.java +++ b/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HistoryTreeFactory.java @@ -41,8 +41,8 @@ public final class HistoryTreeFactory { * If an error happens trying to open/write to the file * specified in the config */ - public static HistoryTree createHistoryTree(HTConfig conf) throws IOException { - return new HistoryTree(conf); + public static IHistoryTree createHistoryTree(HTConfig conf) throws IOException { + return new HistoryTreeClassic(conf); } /** @@ -57,8 +57,7 @@ public final class HistoryTreeFactory { * @throws IOException * If an error happens reading the file */ - public static HistoryTree createFromFile(Path existingStateFile, int expectedProviderVersion) throws IOException { - + public static IHistoryTree createFromFile(Path existingStateFile, int expectedProviderVersion) throws IOException { /* * Check the file exists and has a positive length. These verifications * will also be done in the HT's constructor. @@ -84,8 +83,8 @@ public final class HistoryTreeFactory { */ int magicNumber = buffer.getInt(); switch (magicNumber) { - case HistoryTree.HISTORY_FILE_MAGIC_NUMBER: - return new HistoryTree(existingStateFile.toFile(), expectedProviderVersion); + case HistoryTreeClassic.HISTORY_FILE_MAGIC_NUMBER: + return new HistoryTreeClassic(existingStateFile.toFile(), expectedProviderVersion); default: throw new IOException("Not a known history tree file"); //$NON-NLS-1$ } diff --git a/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/IHistoryTree.java b/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/IHistoryTree.java new file mode 100644 index 0000000000..f58d9ae912 --- /dev/null +++ b/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/IHistoryTree.java @@ -0,0 +1,184 @@ +/******************************************************************************* + * Copyright (c) 2010, 2016 Ericsson, École Polytechnique de Montréal, and others + * + * 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.tracecompass.internal.statesystem.core.backend.historytree; + +import java.io.File; +import java.io.FileInputStream; +import java.io.PrintWriter; +import java.nio.channels.ClosedChannelException; + +import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException; + +/** + * Meta-container for the History Tree. This structure contains all the + * high-level data relevant to the tree. + * + * @author Alexandre Montplaisir + */ +public interface IHistoryTree { + + /** + * Size of the "tree header" in the tree-file The nodes will use this offset + * to know where they should be in the file. This should always be a + * multiple of 4K. + */ + int TREE_HEADER_SIZE = 4096; + + /** + * "Save" the tree to disk. This method will cause the treeIO object to + * commit all nodes to disk and then return the RandomAccessFile descriptor + * so the Tree object can save its configuration into the header of the + * file. + * + * @param requestedEndTime + * The greatest timestamp present in the history tree + */ + void closeTree(long requestedEndTime); + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * Get the start time of this tree. + * + * @return The start time + */ + long getTreeStart(); + + /** + * Get the current end time of this tree. + * + * @return The end time + */ + long getTreeEnd(); + + /** + * Get the number of nodes in this tree. + * + * @return The number of nodes + */ + int getNodeCount(); + + /** + * Get the current root node of this tree + * + * @return The root node + */ + HTNode getRootNode(); + + // ------------------------------------------------------------------------ + // HT_IO interface + // ------------------------------------------------------------------------ + + /** + * Return the FileInputStream reader with which we will read an attribute + * tree (it will be sought to the correct position). + * + * @return The FileInputStream indicating the file and position from which + * the attribute tree can be read. + */ + FileInputStream supplyATReader(); + + /** + * Return the file to which we will write the attribute tree. + * + * @return The file to which we will write the attribute tree + */ + File supplyATWriterFile(); + + /** + * Return the position in the file (given by {@link #supplyATWriterFile}) + * where to start writing the attribute tree. + * + * @return The position in the file where to start writing + */ + long supplyATWriterFilePos(); + + /** + * Read a node from the tree. + * + * @param seqNumber + * The sequence number of the node to read + * @return The node + * @throws ClosedChannelException + * If the tree IO is unavailable + */ + HTNode readNode(int seqNumber) throws ClosedChannelException; + + /** + * Write a node object to the history file. + * + * @param node + * The node to write to disk + */ + void writeNode(HTNode node); + + /** + * Close the history file. + */ + void closeFile(); + + /** + * Delete the history file. + */ + void deleteFile(); + + // ------------------------------------------------------------------------ + // Operations + // ------------------------------------------------------------------------ + + /** + * Insert an interval in the tree. + * + * @param interval + * The interval to be inserted + * @throws TimeRangeException + * If the start of end time of the interval are invalid + */ + void insertInterval(HTInterval interval) throws TimeRangeException; + + /** + * Inner method to select the next child of the current node intersecting + * the given timestamp. Useful for moving down the tree following one + * branch. + * + * @param currentNode + * The node on which the request is made + * @param t + * The timestamp to choose which child is the next one + * @return The child node intersecting t + * @throws ClosedChannelException + * If the file channel was closed while we were reading the tree + */ + HTNode selectNextChild(CoreNode currentNode, long t) throws ClosedChannelException; + + /** + * Get the current size of the history file. + * + * @return The history file size + */ + long getFileSize(); + + /** + * Print out the full tree for debugging purposes + * + * @param writer + * PrintWriter in which to write the output + * @param printIntervals + * Flag to enable full output of the interval information + * @param ts + * The timestamp that nodes have to intersect for intervals to be + * printed. A negative value will print intervals for all nodes. + * The timestamp only applies if printIntervals is true. + */ + void debugPrintFullTree(PrintWriter writer, boolean printIntervals, long ts); + +} -- 2.34.1