From a691727699da9157e3f3f7b1b51be6580b613562 Mon Sep 17 00:00:00 2001 From: Alexandre Montplaisir Date: Fri, 13 Dec 2013 17:01:09 -0500 Subject: [PATCH] tmf: Add proper public methods to internal.tmf.core.statesystem Those are already in internal packages, so they will not be API methods, but by making them public, it makes it possible to access them directly for unit testing. Change-Id: I320317302ed6d6ccfc414d3666d2b657c1cd3207 Signed-off-by: Alexandre Montplaisir Reviewed-on: https://git.eclipse.org/r/19884 Tested-by: Hudson CI Reviewed-by: Matthew Khouzam IP-Clean: Matthew Khouzam --- .../tmf/core/statesystem/Attribute.java | 95 +++++++--- .../tmf/core/statesystem/AttributeTree.java | 99 ++++++---- .../tmf/core/statesystem/TransientState.java | 172 ++++++++++++------ 3 files changed, 252 insertions(+), 114 deletions(-) diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/Attribute.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/Attribute.java index fec8dc4c1f..1f9859f23f 100644 --- a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/Attribute.java +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/Attribute.java @@ -30,43 +30,65 @@ import java.util.Map; * @author alexmont * */ -abstract class Attribute { +public abstract class Attribute { private final Attribute parent; private final String name; private final int quark; + + /** The list of sub-attributes */ protected final List subAttributes; /** * Constructor + * + * @param parent + * The parent attribute of this one. Can be 'null' to represent + * this attribute is the root node of the tree. + * @param name + * Base name of this attribute + * @param quark + * The integer representation of this attribute */ - Attribute(Attribute parent, String name, int quark) { + public Attribute(Attribute parent, String name, int quark) { this.parent = parent; this.quark = quark; this.name = name; this.subAttributes = new ArrayList<>(); } + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + /** - * @name Accessors + * Get the quark (integer representation) of this attribute. + * + * @return The quark of this attribute */ - - int getQuark() { + public int getQuark() { return quark; } - Attribute getParent() { - return parent; + /** + * Get the name of this attribute. + * + * @return The name of this attribute + */ + public String getName() { + return name; } - List getSubAttributes() { + /** + * Get the list of child attributes below this one. This is a read-only + * view. + * + * @return The list of child attributes. + */ + public List getSubAttributes() { return Collections.unmodifiableList(subAttributes); } - String getName() { - return name; - } - /** * Get the matching quark for a given path-of-strings * @@ -74,7 +96,7 @@ abstract class Attribute { * The path we are looking for, *relative to this node*. * @return The matching quark, or -1 if that attribute does not exist. */ - int getSubAttributeQuark(String... path) { + public int getSubAttributeQuark(String... path) { return this.getSubAttributeQuark(path, 0); } @@ -89,7 +111,7 @@ abstract class Attribute { * @return The Node object matching the last element in the path, or "null" * if that attribute does not exist. */ - Attribute getSubAttributeNode(String... path) { + public Attribute getSubAttributeNode(String... path) { return this.getSubAttributeNode(path, 0); } @@ -108,8 +130,25 @@ abstract class Attribute { } /* The methods how to access children are left to derived classes */ - abstract void addSubAttribute(Attribute newSubAttribute); - abstract Attribute getSubAttributeNode(String[] path, int index); + + /** + * Add a sub-attribute to this attribute + * + * @param newSubAttribute The new attribute to add + */ + protected abstract void addSubAttribute(Attribute newSubAttribute); + + /** + * Get a sub-attribute from this node's sub-attributes + * + * @param path + * The *full* path to the attribute + * @param index + * The index in 'path' where this attribute is located + * (indicating where to start searching). + * @return The requested attribute + */ + protected abstract Attribute getSubAttributeNode(String[] path, int index); /** * Return a String array composed of the full (absolute) path representing @@ -117,14 +156,14 @@ abstract class Attribute { * * @return */ - String[] getFullAttribute() { + private String[] getFullAttribute() { LinkedList list = new LinkedList<>(); Attribute curNode = this; /* Add recursive parents to the list, but stop at the root node */ - while (curNode.getParent() != null) { + while (curNode.parent != null) { list.addFirst(curNode.getName()); - curNode = curNode.getParent(); + curNode = curNode.parent; } return list.toArray(new String[0]); @@ -134,9 +173,9 @@ abstract class Attribute { * Return the absolute path of this attribute, as a single slash-separated * String. * - * @return + * @return The full name of this attribute */ - String getFullAttributeName() { + public String getFullAttributeName() { String[] array = this.getFullAttribute(); StringBuffer buf = new StringBuffer(); @@ -176,7 +215,13 @@ abstract class Attribute { return; } - void debugPrint(PrintWriter writer) { + /** + * Debugging method to print the contents of this attribute + * + * @param writer + * PrintWriter where to write the information + */ + public void debugPrint(PrintWriter writer) { /* Only used for debugging, shouldn't be externalized */ writer.println("------------------------------"); //$NON-NLS-1$ writer.println("Attribute tree: (quark)\n"); //$NON-NLS-1$ @@ -196,15 +241,15 @@ abstract class Attribute { */ final class AlphaNumAttribute extends Attribute { - private Map subAttributesMap; + private final Map subAttributesMap; - AlphaNumAttribute(Attribute parent, String name, int quark) { + public AlphaNumAttribute(Attribute parent, String name, int quark) { super(parent, name, quark); this.subAttributesMap = new HashMap<>(); } @Override - synchronized void addSubAttribute(Attribute newSubAttribute) { + protected synchronized void addSubAttribute(Attribute newSubAttribute) { assert (newSubAttribute != null); assert (newSubAttribute.getName() != null); /* This should catch buggy state changing statements */ diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/AttributeTree.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/AttributeTree.java index 73ced1eec2..05142f74c6 100644 --- a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/AttributeTree.java +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/AttributeTree.java @@ -46,7 +46,7 @@ public final class AttributeTree { * @param ss * The StateSystem to which this AT is attached */ - AttributeTree(StateSystem ss) { + public AttributeTree(StateSystem ss) { this.ss = ss; this.attributeList = Collections.synchronizedList(new ArrayList()); this.attributeTreeRoot = new AlphaNumAttribute(null, "root", -1); //$NON-NLS-1$ @@ -62,8 +62,9 @@ public final class AttributeTree { * File stream where to read the AT information. Make sure it's * sought at the right place! * @throws IOException + * If there is a problem reading from the file stream */ - AttributeTree(StateSystem ss, FileInputStream fis) throws IOException { + public AttributeTree(StateSystem ss, FileInputStream fis) throws IOException { this(ss); DataInputStream in = new DataInputStream(new BufferedInputStream(fis)); @@ -134,15 +135,15 @@ public final class AttributeTree { } /** - * Tell the Attribute Tree to write itself somewhere. The passed - * FileOutputStream defines where (which file/position). + * Tell the Attribute Tree to write itself somewhere in a file. * - * @param fos - * Where to write. Make sure it's sought at the right position - * you want. + * @param file + * The file to write to + * @param pos + * The position (in bytes) in the file where to write * @return The total number of bytes written. */ - int writeSelf(File file, long pos) { + public int writeSelf(File file, long pos) { int total = 0; byte[] curByteArray; @@ -193,24 +194,26 @@ public final class AttributeTree { * this also equals the integer value (quark) the next added attribute will * have. * - * @return + * @return The current number of attributes in the tree */ - int getNbAttributes() { + public int getNbAttributes() { return attributeList.size(); } /** - * This is the version to specifically add missing attributes. - * - * If 'numericalNode' is true, all the new attributes created will be of - * type 'NumericalNode' instead of 'AlphaNumNode'. Be careful with this, if - * you do not want ALL added attributes to be numerical, call this function - * first with 'false' to create the parent nodes, then call it again to make - * sure only the final node is numerical. + * Get the quark for a given attribute path. No new attribute will be + * created : if the specified path does not exist, throw an error. * + * @param startingNodeQuark + * The quark of the attribute from which relative queries will + * start. Use '-1' to start at the root node. + * @param subPath + * The path to the attribute, relative to the starting node. + * @return The quark of the specified attribute * @throws AttributeNotFoundException + * If the specified path was not found */ - int getQuarkDontAdd(int startingNodeQuark, String... subPath) + public int getQuarkDontAdd(int startingNodeQuark, String... subPath) throws AttributeNotFoundException { assert (startingNodeQuark >= -1); @@ -243,9 +246,21 @@ public final class AttributeTree { return knownQuark; } - // FIXME synchronized here is probably quite costly... maybe only locking - // the "for" would be enough? - synchronized int getQuarkAndAdd(int startingNodeQuark, String... subPath) { + /** + * Get the quark of a given attribute path. If that specified path does not + * exist, it will be created (and the quark that was just created will be + * returned). + * + * @param startingNodeQuark + * The quark of the attribute from which relative queries will + * start. Use '-1' to start at the root node. + * @param subPath + * The path to the attribute, relative to the starting node. + * @return The quark of the attribute represented by the path + */ + public synchronized int getQuarkAndAdd(int startingNodeQuark, String... subPath) { + // FIXME synchronized here is probably quite costly... maybe only locking + // the "for" would be enough? assert (subPath != null && subPath.length > 0); assert (startingNodeQuark >= -1); @@ -305,19 +320,21 @@ public final class AttributeTree { return knownQuark; } - int getSubAttributesCount(int quark) { - return attributeList.get(quark).getSubAttributes().size(); - } - /** * Returns the sub-attributes of the quark passed in parameter * * @param attributeQuark + * The quark of the attribute to print the sub-attributes of. * @param recursive - * @return + * Should the query be recursive or not? If false, only children + * one level deep will be returned. If true, all descendants will + * be returned (depth-first search) + * @return The list of quarks representing the children attributes * @throws AttributeNotFoundException + * If 'attributeQuark' is invalid, or if there is no attrbiute + * associated to it. */ - List getSubAttributes(int attributeQuark, boolean recursive) + public List getSubAttributes(int attributeQuark, boolean recursive) throws AttributeNotFoundException { List listOfChildren = new ArrayList<>(); Attribute startingAttribute; @@ -350,19 +367,39 @@ public final class AttributeTree { } } - String getAttributeName(int quark) { + /** + * Get then base name of an attribute specified by a quark. + * + * @param quark + * The quark of the attribute + * @return The (base) name of the attribute + */ + public String getAttributeName(int quark) { return attributeList.get(quark).getName(); } - String getFullAttributeName(int quark) { + /** + * Get the full path name of an attribute specified by a quark. + * + * @param quark + * The quark of the attribute + * @return The full path name of the attribute + */ + public String getFullAttributeName(int quark) { if (quark >= attributeList.size() || quark < 0) { return null; } return attributeList.get(quark).getFullAttributeName(); } - void debugPrint(PrintWriter writer) { + /** + * Debug-print all the attributes in the tree. + * + * @param writer + * The writer where to print the output + */ + public void debugPrint(PrintWriter writer) { attributeTreeRoot.debugPrint(writer); } -} \ No newline at end of file +} diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/TransientState.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/TransientState.java index 84bfb24747..ff08a7c20e 100644 --- a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/TransientState.java +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/TransientState.java @@ -27,19 +27,18 @@ import org.eclipse.linuxtools.tmf.core.statevalue.TmfStateValue; import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue.Type; /** - * The Transient State is used to build intervals from punctual state changes. It - * contains a "state info" vector similar to the "current state", except here we - * also record the start time of every state stored in it. + * The Transient State is used to build intervals from punctual state changes. + * It contains a "state info" vector similar to the "current state", except here + * we also record the start time of every state stored in it. * - * We can then build StateInterval's, to be inserted in the State History when - * we detect state changes : the "start time" of the interval will be the - * recorded time we have here, and the "end time" will be the timestamp of the - * new state-changing event we just read. - * - * @author alexmont + * We can then build {@link ITmfStateInterval}'s, to be inserted in a + * {@link IStateHistoryBackend} when we detect state changes : the "start time" + * of the interval will be the recorded time we have here, and the "end time" + * will be the timestamp of the new state-changing event we just read. * + * @author Alexandre Montplaisir */ -class TransientState { +public class TransientState { /* Indicates where to insert state changes that we generate */ private final IStateHistoryBackend backend; @@ -51,7 +50,13 @@ class TransientState { private List ongoingStateStartTimes; private List stateValueTypes; - TransientState(IStateHistoryBackend backend) { + /** + * Constructor + * + * @param backend + * The back-end in which to insert the generated state intervals + */ + public TransientState(IStateHistoryBackend backend) { this.backend = backend; isActive = true; ongoingStateInfo = new ArrayList<>(); @@ -65,34 +70,73 @@ class TransientState { } } - long getLatestTime() { + /** + * Get the latest time we have seen so far. + * + * @return The latest time seen in the transient state + */ + public long getLatestTime() { return latestTime; } - ITmfStateValue getOngoingStateValue(int index) throws AttributeNotFoundException { - checkValidAttribute(index); - return ongoingStateInfo.get(index); + /** + * Retrieve the ongoing state value for a given index (attribute quark). + * + * @param quark + * The quark of the attribute to look for + * @return The corresponding state value + * @throws AttributeNotFoundException + * If the quark is invalid + */ + public ITmfStateValue getOngoingStateValue(int quark) throws AttributeNotFoundException { + checkValidAttribute(quark); + return ongoingStateInfo.get(quark); } - long getOngoingStartTime(int index) throws AttributeNotFoundException { - checkValidAttribute(index); - return ongoingStateStartTimes.get(index); + /** + * Retrieve the start time of the state in which the given attribute is in. + * + * @param quark + * The quark of the attribute to look for + * @return The start time of the current state for this attribute + * @throws AttributeNotFoundException + * If the quark is invalid + */ + public long getOngoingStartTime(int quark) throws AttributeNotFoundException { + checkValidAttribute(quark); + return ongoingStateStartTimes.get(quark); } - void changeOngoingStateValue(int index, ITmfStateValue newValue) + /** + * Modify the current state for a given attribute. This will not update the + * "ongoing state start time" in any way, so be careful when using this. + * + * @param quark + * The quark of the attribute to modify + * @param newValue + * The state value the attribute should have + * @throws AttributeNotFoundException + * If the quark is invalid + */ + public void changeOngoingStateValue(int quark, ITmfStateValue newValue) throws AttributeNotFoundException { - checkValidAttribute(index); - ongoingStateInfo.set(index, newValue); + checkValidAttribute(quark); + ongoingStateInfo.set(quark, newValue); } /** - * Return the "ongoing" value for a given attribute as a dummy interval - * whose end time = -1 (since we don't know its real end time yet). + * Convenience method to return the "ongoing" value for a given attribute as + * a dummy interval whose end time = -1 (since we don't know its real end + * time yet). * * @param quark + * The quark of the attribute + * @return An interval representing the current state (but whose end time is + * meaningless) * @throws AttributeNotFoundException + * If the quark is invalid */ - ITmfStateInterval getOngoingInterval(int quark) throws AttributeNotFoundException { + public ITmfStateInterval getOngoingInterval(int quark) throws AttributeNotFoundException { checkValidAttribute(quark); return new TmfStateInterval(ongoingStateStartTimes.get(quark), -1, quark, ongoingStateInfo.get(quark)); @@ -106,16 +150,16 @@ class TransientState { /** * More advanced version of {@link #changeOngoingStateValue}. Replaces the - * complete {@link #ongoingStateInfo} in one go, and updates the - * {@link #ongoingStateStartTimes} and {@link #stateValuesTypes} - * accordingly. BE VERY CAREFUL WITH THIS! + * complete ongoingStateInfo in one go, and updates the + * ongoingStateStartTimes and #stateValuesTypes accordingly. BE VERY CAREFUL + * WITH THIS! * * @param newStateIntervals * The List of intervals that will represent the new * "ongoing state". Their end times don't matter, we will only * check their value and start times. */ - synchronized void replaceOngoingState(List newStateIntervals) { + public synchronized void replaceOngoingState(List newStateIntervals) { int size = newStateIntervals.size(); ongoingStateInfo = new ArrayList<>(size); ongoingStateStartTimes = new ArrayList<>(size); @@ -133,7 +177,7 @@ class TransientState { * Ongoing... tables can stay in sync with the number of attributes in the * attribute tree, namely when we add sub-path attributes. */ - synchronized void addEmptyEntry() { + public synchronized void addEmptyEntry() { /* * Since this is a new attribute, we suppose it was in the "null state" * since the beginning (so we can have intervals covering for all @@ -165,31 +209,34 @@ class TransientState { * @return True if the value is present in the Transient State at this * moment in time, false if it's not */ - boolean hasInfoAboutStateOf(long time, int quark) { + public boolean hasInfoAboutStateOf(long time, int quark) { return (this.isActive() && time >= ongoingStateStartTimes.get(quark)); } /** - * This is the lower-level method that will be called by the - * StateHistorySystem (with already-built StateValues and timestamps) + * Process a state change to be inserted in the history. * - * @param index - * The index in the vectors (== the quark of the attribute) - * @param value - * The new StateValue associated to this attribute * @param eventTime * The timestamp associated with this state change + * @param value + * The new StateValue associated to this attribute + * @param quark + * The quark of the attribute that is being modified * @throws TimeRangeException + * If 'eventTime' is invalid * @throws AttributeNotFoundException + * IF 'quark' does not represent an existing attribute * @throws StateValueTypeException + * If the state value to be inserted is of a different type of + * what was inserted so far for this attribute. */ - synchronized void processStateChange(long eventTime, - ITmfStateValue value, int index) throws TimeRangeException, + public synchronized void processStateChange(long eventTime, + ITmfStateValue value, int quark) throws TimeRangeException, AttributeNotFoundException, StateValueTypeException { assert (this.isActive); - Type expectedSvType = stateValueTypes.get(index); - checkValidAttribute(index); + Type expectedSvType = stateValueTypes.get(quark); + checkValidAttribute(quark); /* * Make sure the state value type we're inserting is the same as the @@ -200,7 +247,7 @@ class TransientState { * The value hasn't been used yet, set it to the value * we're currently inserting (which might be null/-1 again). */ - stateValueTypes.set(index, value.getType()); + stateValueTypes.set(quark, value.getType()); } else if ((value.getType() != Type.NULL) && (value.getType() != expectedSvType)) { /* * We authorize inserting null values in any type of attribute, @@ -214,7 +261,7 @@ class TransientState { latestTime = eventTime; } - if (ongoingStateInfo.get(index).equals(value)) { + if (ongoingStateInfo.get(quark).equals(value)) { /* * This is the case where the new value and the one already present * in the Builder are the same. We do not need to create an @@ -223,19 +270,19 @@ class TransientState { return; } - if (backend != null && ongoingStateStartTimes.get(index) < eventTime) { + if (backend != null && ongoingStateStartTimes.get(quark) < eventTime) { /* * These two conditions are necessary to create an interval and * update ongoingStateInfo. */ - backend.insertPastState(ongoingStateStartTimes.get(index), + backend.insertPastState(ongoingStateStartTimes.get(quark), eventTime - 1, /* End Time */ - index, /* attribute quark */ - ongoingStateInfo.get(index)); /* StateValue */ + quark, /* attribute quark */ + ongoingStateInfo.get(quark)); /* StateValue */ - ongoingStateStartTimes.set(index, eventTime); + ongoingStateStartTimes.set(quark, eventTime); } - ongoingStateInfo.set(index, value); + ongoingStateInfo.set(quark, value); return; } @@ -248,7 +295,7 @@ class TransientState { * @param t * The requested timestamp */ - void doQuery(List stateInfo, long t) { + public void doQuery(List stateInfo, long t) { ITmfStateInterval interval; if (!this.isActive) { @@ -270,11 +317,16 @@ class TransientState { } /** - * Close off the Transient State, used for example when we are done reading a - * static trace file. All the information currently contained in it will be - * converted to intervals and "flushed" to the State History. + * Close off the Transient State, used for example when we are done reading + * a static trace file. All the information currently contained in it will + * be converted to intervals and "flushed" to the state history. + * + * @param endTime + * The timestamp to use as end time for the state history (since + * it may be different than the timestamp of the last state + * change) */ - void closeTransientState(long endTime) { + public void closeTransientState(long endTime) { assert (this.isActive); for (int i = 0; i < ongoingStateInfo.size(); i++) { @@ -309,22 +361,26 @@ class TransientState { /** * Simply returns if this Transient State is currently being used or not * - * @return + * @return True if this transient state is active */ - boolean isActive() { + public boolean isActive() { return this.isActive; } - void setInactive() { + /** + * Mark this transient state as inactive + */ + public void setInactive() { isActive = false; } /** - * Debugging method that prints the contents of both 'ongoing...' vectors + * Debugging method that prints the contents of the transient state * * @param writer + * The writer to which the output should be written */ - void debugPrint(PrintWriter writer) { + public void debugPrint(PrintWriter writer) { /* Only used for debugging, shouldn't be externalized */ writer.println("------------------------------"); //$NON-NLS-1$ writer.println("Info stored in the Builder:"); //$NON-NLS-1$ -- 2.34.1