From 7e0b2b56022c992c499d8abbe41385344db5cae8 Mon Sep 17 00:00:00 2001 From: Alexandre Montplaisir Date: Fri, 27 Apr 2012 11:45:08 -0400 Subject: [PATCH] tmf: Enforce existing sv types when reusing attributes Once we assign an Integer or String statevalue to an attribute, make sure every subsequent modification keeps using statevalues of the same type. This is a new restriction that was not there before, but it makes sense to add it to the design. It also helps to isolate problems in the state provider. Fixes Eclipse bug #375878 Signed-off-by: Alexandre Montplaisir --- .../tmf/core/statesystem/StateSystem.java | 18 ++++++-- .../tmf/core/statesystem/TransientState.java | 42 ++++++++++++++----- 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statesystem/StateSystem.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statesystem/StateSystem.java index 48764b96d3..3e8d060bf1 100644 --- a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statesystem/StateSystem.java +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statesystem/StateSystem.java @@ -281,9 +281,13 @@ public class StateSystem { * If the requested time is outside of the trace's range * @throws AttributeNotFoundException * If the requested attribute quark is invalid + * @throws StateValueTypeException + * If the inserted state value's type does not match what is + * already assigned to this attribute. */ public void modifyAttribute(long t, ITmfStateValue value, int attributeQuark) - throws TimeRangeException, AttributeNotFoundException { + throws TimeRangeException, AttributeNotFoundException, + StateValueTypeException { transState.processStateChange(t, value, attributeQuark); } @@ -468,8 +472,16 @@ public class StateSystem { removeAttribute(t, childNodeQuark); } /* Nullify ourselves */ - transState.processStateChange(t, TmfStateValue.nullValue(), - attributeQuark); + try { + transState.processStateChange(t, TmfStateValue.nullValue(), + attributeQuark); + } catch (StateValueTypeException e) { + /* + * Will not happen since we're inserting null values only, but + * poor compiler has no way of knowing this... + */ + e.printStackTrace(); + } } /** diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statesystem/TransientState.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statesystem/TransientState.java index d0a0a7eb10..4b2027cda5 100644 --- a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statesystem/TransientState.java +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statesystem/TransientState.java @@ -20,10 +20,11 @@ import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval; import org.eclipse.linuxtools.tmf.core.interval.TmfStateInterval; import org.eclipse.linuxtools.tmf.core.statesystem.helpers.IStateHistoryBackend; import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue; +import org.eclipse.linuxtools.tmf.core.statevalue.StateValueTypeException; import org.eclipse.linuxtools.tmf.core.statevalue.TmfStateValue; /** - * The Transient State is used to build intervals from puntual state changse. 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. * @@ -44,13 +45,15 @@ class TransientState { private long latestTime; private ArrayList ongoingStateInfo; - private ArrayList ongoingStateStartTimes; + private final ArrayList ongoingStateStartTimes; + private final ArrayList stateValueTypes; TransientState(IStateHistoryBackend backend) { this.backend = backend; isActive = true; ongoingStateInfo = new ArrayList(); ongoingStateStartTimes = new ArrayList(); + stateValueTypes = new ArrayList(); if (backend != null) { latestTime = backend.getStartTime(); @@ -129,6 +132,7 @@ class TransientState { * change. */ ongoingStateInfo.add(TmfStateValue.nullValue()); + stateValueTypes.add((byte) -1); if (backend == null) { ongoingStateStartTimes.add(0L); @@ -168,13 +172,35 @@ class TransientState { * The timestamp associated with this state change * @throws TimeRangeException * @throws AttributeNotFoundException + * @throws StateValueTypeException */ synchronized void processStateChange(long eventTime, ITmfStateValue value, int index) throws TimeRangeException, - AttributeNotFoundException { + AttributeNotFoundException, StateValueTypeException { assert (this.isActive); + + byte expectedSvType = stateValueTypes.get(index); checkValidAttribute(index); + + /* + * Make sure the state value type we're inserting is the same as the + * one registered for this attribute. + */ + if (expectedSvType == -1) { + /* + * 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)) { + /* + * We authorize inserting null values in any type of attribute, + * but for every other types, it needs to match our expectations! + */ + throw new StateValueTypeException(); + } + /* Update the Transient State's lastestTime, if needed */ if (latestTime < eventTime) { latestTime = eventTime; } @@ -193,10 +219,7 @@ class TransientState { * These two conditions are necessary to create an interval and * update ongoingStateInfo. */ - backend.insertPastState(ongoingStateStartTimes.get(index), /* - * Start - * Time - */ + backend.insertPastState(ongoingStateStartTimes.get(index), eventTime - 1, /* End Time */ index, /* attribute quark */ ongoingStateInfo.get(index)); /* StateValue */ @@ -254,10 +277,7 @@ class TransientState { continue; } try { - backend.insertPastState(ongoingStateStartTimes.get(i), /* - * Start - * Time - */ + backend.insertPastState(ongoingStateStartTimes.get(i), endTime, /* End Time */ i, /* attribute quark */ ongoingStateInfo.get(i)); /* StateValue */ -- 2.34.1