/*******************************************************************************
- * Copyright (c) 2012 Ericsson
+ * Copyright (c) 2012, 2013 Ericsson
* Copyright (c) 2010, 2011 École Polytechnique de Montréal
* Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
*
import java.util.ArrayList;
import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.IStateHistoryBackend;
import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;
import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;
import org.eclipse.linuxtools.tmf.core.interval.TmfStateInterval;
import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue;
+import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue.Type;
import org.eclipse.linuxtools.tmf.core.statevalue.TmfStateValue;
/**
- * 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;
+ @NonNull private final IStateHistoryBackend backend;
private boolean isActive;
private long latestTime;
- private ArrayList<ITmfStateValue> ongoingStateInfo;
- private final ArrayList<Long> ongoingStateStartTimes;
- private final ArrayList<Byte> stateValueTypes;
+ private List<ITmfStateValue> ongoingStateInfo;
+ private List<Long> ongoingStateStartTimes;
+ private List<Type> stateValueTypes;
- TransientState(IStateHistoryBackend backend) {
+ /**
+ * Constructor
+ *
+ * @param backend
+ * The back-end in which to insert the generated state intervals
+ */
+ public TransientState(@NonNull IStateHistoryBackend backend) {
this.backend = backend;
isActive = true;
- ongoingStateInfo = new ArrayList<ITmfStateValue>();
- ongoingStateStartTimes = new ArrayList<Long>();
- stateValueTypes = new ArrayList<Byte>();
-
- if (backend != null) {
- latestTime = backend.getStartTime();
- } else {
- latestTime = 0;
- }
+ ongoingStateInfo = new ArrayList<>();
+ ongoingStateStartTimes = new ArrayList<>();
+ stateValueTypes = new ArrayList<>();
+
+ latestTime = backend.getStartTime();
}
- 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);
}
- void changeOngoingStateValue(int index, ITmfStateValue newValue)
- throws AttributeNotFoundException {
-
- checkValidAttribute(index);
- ongoingStateInfo.set(index, newValue);
+ /**
+ * 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);
}
/**
- * 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).
+ * 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
*/
- ITmfStateInterval getOngoingInterval(int quark)
+ public void changeOngoingStateValue(int quark, ITmfStateValue newValue)
throws AttributeNotFoundException {
-
checkValidAttribute(quark);
- return new TmfStateInterval(ongoingStateStartTimes.get(quark), -1, quark,
- ongoingStateInfo.get(quark));
+ ongoingStateInfo.set(quark, newValue);
}
- private void checkValidAttribute(int quark)
- throws AttributeNotFoundException {
+ /**
+ * Convenience method to return the "ongoing" value for a given attribute as
+ * a dummy interval whose end time = the current latest time.
+ *
+ * @param quark
+ * The quark of the attribute
+ * @return An interval representing the current state (but whose end time is
+ * the current one, and probably not the "final" one)
+ * @throws AttributeNotFoundException
+ * If the quark is invalid
+ */
+ public ITmfStateInterval getOngoingInterval(int quark) throws AttributeNotFoundException {
+ checkValidAttribute(quark);
+ return new TmfStateInterval(ongoingStateStartTimes.get(quark), latestTime,
+ quark, ongoingStateInfo.get(quark));
+ }
+ private void checkValidAttribute(int quark) throws AttributeNotFoundException {
if (quark > ongoingStateInfo.size() - 1 || quark < 0) {
throw new AttributeNotFoundException();
}
}
/**
- * Batch method of changeOngoingStateValue(), updates the complete
- * ongoingStateInfo in one go. BE VERY CAREFUL WITH THIS! Especially with
- * the sizes of both arrays.
+ * More advanced version of {@link #changeOngoingStateValue}. Replaces the
+ * complete ongoingStateInfo in one go, and updates the
+ * ongoingStateStartTimes and #stateValuesTypes accordingly. BE VERY CAREFUL
+ * WITH THIS!
*
- * Note that the new ongoingStateInfo will be a shallow copy of
- * newStateInfo, so that last one must be already instantiated and all.
- *
- * @param newStateInfo
- * The List of StateValues to replace the old ongoingStateInfo
- * one.
+ * @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.
*/
- void changeOngoingStateInfo(ArrayList<ITmfStateValue> newStateInfo) {
- this.ongoingStateInfo = newStateInfo;
+ public synchronized void replaceOngoingState(List<ITmfStateInterval> newStateIntervals) {
+ int size = newStateIntervals.size();
+ ongoingStateInfo = new ArrayList<>(size);
+ ongoingStateStartTimes = new ArrayList<>(size);
+ stateValueTypes = new ArrayList<>(size);
+
+ for (ITmfStateInterval interval : newStateIntervals) {
+ ongoingStateInfo.add(interval.getStateValue());
+ ongoingStateStartTimes.add(interval.getStartTime());
+ stateValueTypes.add(interval.getStateValue().getType());
+ }
}
/**
* 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
* change.
*/
ongoingStateInfo.add(TmfStateValue.nullValue());
- stateValueTypes.add((byte) -1);
+ stateValueTypes.add(Type.NULL);
- if (backend == null) {
- ongoingStateStartTimes.add(0L);
- } else {
- ongoingStateStartTimes.add(backend.getStartTime());
- }
+ ongoingStateStartTimes.add(backend.getStartTime());
}
/**
* @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);
- byte 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
* one registered for this attribute.
*/
- if (expectedSvType == -1) {
+ if (expectedSvType == Type.NULL) {
/*
* 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());
- } else if ((value.getType() != -1) && (value.getType() != expectedSvType)) {
+ stateValueTypes.set(quark, value.getType());
+ } else if ((value.getType() != Type.NULL) && (value.getType() != expectedSvType)) {
/*
* We authorize inserting null values in any type of attribute,
* but for every other types, it needs to match our expectations!
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
return;
}
- if (backend != null && ongoingStateStartTimes.get(index) < eventTime) {
+ if (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;
}
* @param t
* The requested timestamp
*/
- void doQuery(List<ITmfStateInterval> stateInfo, long t) {
+ public void doQuery(List<ITmfStateInterval> stateInfo, long t) {
ITmfStateInterval interval;
if (!this.isActive) {
}
/**
- * 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++) {
if (ongoingStateStartTimes.get(i) > endTime) {
/*
- * Handle the cases where trace end >= timetamp of last state
+ * Handle the cases where trace end > timestamp of last state
* change. This can happen when inserting "future" changes.
*/
continue;
* This shouldn't happen, since we control where the interval's
* start time comes from
*/
- e.printStackTrace();
+ throw new IllegalStateException(e);
}
}
/**
* 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$
return;
}
-}
\ No newline at end of file
+}