1 /*******************************************************************************
2 * Copyright (c) 2016 Ecole Polytechnique de Montreal, Ericsson
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 ******************************************************************************/
9 package org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.core
.model
;
11 import java
.util
.HashMap
;
14 import org
.eclipse
.jdt
.annotation
.Nullable
;
15 import org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
;
16 import org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.core
.Activator
;
17 import org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.core
.module
.IXmlStateSystemContainer
;
18 import org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.core
.stateprovider
.TmfXmlStrings
;
19 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystemBuilder
;
20 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateSystemDisposedException
;
21 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateValueTypeException
;
22 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.ITmfStateInterval
;
23 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
24 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.TmfStateValue
;
25 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
26 import org
.eclipse
.tracecompass
.tmf
.core
.statesystem
.TmfAttributePool
;
28 import com
.google
.common
.collect
.BiMap
;
29 import com
.google
.common
.collect
.ImmutableBiMap
;
32 * This class is responsible for creating scenarios, updating their status and
33 * data, and saving the scenario data to the state system
35 public class TmfXmlScenarioHistoryBuilder
{
37 /** The string 'status' */
38 public static final String STATUS
= "status"; //$NON-NLS-1$
39 /** The string for "nbScenarios" */
40 public static final String SCENARIO_COUNT
= "nbScenarios"; //$NON-NLS-1$
42 /** The string for start time */
43 private static final String START_TIME
= "startTime"; //$NON-NLS-1$
45 private static final String ERROR_MESSAGE
= "The state system is null"; //$NON-NLS-1$
47 private final Map
<String
, TmfAttributePool
> fFsmPools
= new HashMap
<>();
50 * All possible types of status for a scenario
52 public enum ScenarioStatusType
{
54 * scenario pending for start point
58 * scenario in progress
66 * scenario match with the pattern
72 * Cache the available status in a map
74 protected static final BiMap
<ScenarioStatusType
, ITmfStateValue
> STATUS_MAP
= NonNullUtils
.checkNotNull(ImmutableBiMap
.of(
75 ScenarioStatusType
.PENDING
, TmfStateValue
.newValueInt(0),
76 ScenarioStatusType
.IN_PROGRESS
, TmfStateValue
.newValueInt(1),
77 ScenarioStatusType
.MATCHED
, TmfStateValue
.newValueInt(2),
78 ScenarioStatusType
.ABANDONED
, TmfStateValue
.newValueInt(3)));
81 * Get the scenario matched process start time
84 * The state system container this class use
86 * The scenario details
90 * @return The start time of the matching process for the specified scenario
92 public long getStartTime(final IXmlStateSystemContainer container
, final TmfXmlScenarioInfo info
, final ITmfEvent event
) {
93 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
94 long ts
= getTimestamp(event
, ss
);
96 int attributeQuark
= getQuarkRelativeAndAdd(ss
, info
.getQuark(), START_TIME
);
97 ITmfStateInterval state
= ss
.querySingleState(ts
, attributeQuark
);
98 return state
.getStartTime();
99 } catch (StateSystemDisposedException e
) {
100 Activator
.logError("failed to get the start time of the scenario", e
); //$NON-NLS-1$
106 * Save the stored fields
109 * The state system container this class use
110 * @param attributeName
111 * The name of the attribute to save
113 * The value of the attribute to save
115 * The scenario details
119 public void updateStoredFields(final IXmlStateSystemContainer container
, final String attributeName
, final ITmfStateValue value
, final TmfXmlScenarioInfo info
, final ITmfEvent event
) {
120 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
121 long ts
= getTimestamp(event
, ss
);
123 int attributeQuark
= getQuarkRelativeAndAdd(ss
, info
.getQuark(), TmfXmlStrings
.STORED_FIELDS
, attributeName
);
124 ss
.modifyAttribute(ts
, value
, attributeQuark
);
125 } catch (StateValueTypeException e
) {
126 Activator
.logError("failed to save the stored field " + attributeName
, e
); //$NON-NLS-1$
131 * Clear the special fields
134 * The state system container this class use
135 * @param attributeName
136 * The name of the attribute to save
138 * The scenario details
142 public void resetStoredFields(final IXmlStateSystemContainer container
, final String attributeName
, final TmfXmlScenarioInfo info
, final ITmfEvent event
) {
143 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
144 long ts
= getTimestamp(event
, ss
);
145 ITmfStateValue value
= TmfStateValue
.nullValue();
147 int attributeQuark
= getQuarkRelativeAndAdd(ss
, info
.getQuark(), TmfXmlStrings
.STORED_FIELDS
, attributeName
);
148 ss
.modifyAttribute(ts
, value
, attributeQuark
);
149 } catch (StateValueTypeException e
) {
150 Activator
.logError("failed to clear the stored fields", e
); //$NON-NLS-1$
155 * Get the value of a special field in the state system
158 * The state system container this class use
159 * @param attributeName
160 * The attribute name of the special field
162 * The scenario details
166 * @return The value of a special field saved into the state system
168 public ITmfStateValue
getStoredFieldValue(IXmlStateSystemContainer container
, String attributeName
, final TmfXmlScenarioInfo info
, ITmfEvent event
) {
169 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
170 long ts
= event
.getTimestamp().toNanos();
171 ITmfStateInterval state
= null;
173 int attributeQuark
= getQuarkRelativeAndAdd(ss
, info
.getQuark(), TmfXmlStrings
.STORED_FIELDS
, attributeName
);
174 state
= ss
.querySingleState(ts
, attributeQuark
);
175 } catch (StateSystemDisposedException e
) {
176 Activator
.logError("failed to get the value of the stored field " + attributeName
, e
); //$NON-NLS-1$
178 return (state
!= null) ? NonNullUtils
.checkNotNull(state
.getStateValue()) : TmfStateValue
.nullValue();
182 * Get the attribute pool for this fsm
185 * The state system container
188 * @return The attribute pool associated with this FSM
190 protected TmfAttributePool
getPoolFor(IXmlStateSystemContainer container
, String fsmId
) {
191 TmfAttributePool pool
= fFsmPools
.get(fsmId
);
195 ITmfStateSystemBuilder ss
= NonNullUtils
.checkNotNull((ITmfStateSystemBuilder
) container
.getStateSystem());
196 String
[] fsmPath
= new String
[] { TmfXmlStrings
.SCENARIOS
, fsmId
};
197 int quark
= getQuarkAbsoluteAndAdd(ss
, fsmPath
);
198 pool
= new TmfAttributePool(ss
, quark
);
199 fFsmPools
.put(fsmId
, pool
);
204 * Get the scenario quark
207 * The state system container this class use
209 * Id of the fsm this scenario is associated to
210 * @return The scenario quark
212 public int assignScenarioQuark(IXmlStateSystemContainer container
, String fsmId
) {
213 TmfAttributePool pool
= getPoolFor(container
, fsmId
);
214 return pool
.getAvailable();
218 * Get the scenario status quark
221 * The state system container this class use
222 * @param scenarioQuark
224 * @return The scenario quark
226 public int getScenarioStatusQuark(IXmlStateSystemContainer container
, int scenarioQuark
) {
227 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
228 return getQuarkRelativeAndAdd(ss
, scenarioQuark
, STATUS
);
232 * Get the start time of a specific state of the scenario
235 * The state system container this class use
237 * The name of the current state of the scenario
239 * The scenario details
243 * @return The start time for the specified state
245 public long getSpecificStateStartTime(final IXmlStateSystemContainer container
, final String stateName
, final TmfXmlScenarioInfo info
, final ITmfEvent event
) {
246 long ts
= event
.getTimestamp().getValue();
247 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
249 int attributeQuark
= getQuarkRelativeAndAdd(ss
, info
.getQuark(), TmfXmlStrings
.STATE
, stateName
, START_TIME
);
250 ITmfStateInterval state
= ss
.querySingleState(ts
, attributeQuark
);
251 return state
.getStartTime();
252 } catch (StateSystemDisposedException e
) {
253 Activator
.logError("failed the start time of the state " + stateName
, e
); //$NON-NLS-1$
259 * Basic quark-retrieving method. Pass an attribute in parameter as an array
260 * of strings, the matching quark will be returned. If the attribute does
261 * not exist, it will add the quark to the state system if the context
264 * See {@link ITmfStateSystemBuilder#getQuarkAbsoluteAndAdd(String...)}
267 * The state system the attribute belongs to
269 * Full path to the attribute
270 * @return The quark for this attribute
272 private static int getQuarkAbsoluteAndAdd(@Nullable ITmfStateSystemBuilder ss
, String
... path
) {
274 throw new NullPointerException(ERROR_MESSAGE
);
276 return ss
.getQuarkAbsoluteAndAdd(path
);
280 * Quark-retrieving method, but the attribute is queried starting from the
281 * startNodeQuark. If the attribute does not exist, it will add it to the
282 * state system if the context allows it.
284 * See {@link ITmfStateSystemBuilder#getQuarkRelativeAndAdd(int, String...)}
287 * The state system the attribute belongs to
288 * @param startNodeQuark
289 * The quark of the attribute from which 'path' originates.
291 * Relative path to the attribute
292 * @return The quark for this attribute
294 private static int getQuarkRelativeAndAdd(@Nullable ITmfStateSystemBuilder ss
, int startNodeQuark
, String
... path
) {
296 throw new NullPointerException(ERROR_MESSAGE
);
298 return ss
.getQuarkRelativeAndAdd(startNodeQuark
, path
);
302 * Update the scenario internal data
305 * The state system container this class use
307 * The scenario details
311 public void update(final IXmlStateSystemContainer container
, final TmfXmlScenarioInfo info
, final @Nullable ITmfEvent event
) {
312 updateScenarioSpecificStateStartTime(event
, container
, info
);
313 updateScenarioState(event
, container
, info
);
314 updateScenarioStatus(event
, container
, info
);
317 private static void updateScenarioStatus(@Nullable ITmfEvent event
, IXmlStateSystemContainer container
, final TmfXmlScenarioInfo info
) {
318 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
319 long ts
= getTimestamp(event
, ss
);
320 ITmfStateValue value
;
323 switch (info
.getStatus()) {
325 value
= STATUS_MAP
.get(ScenarioStatusType
.IN_PROGRESS
);
328 value
= STATUS_MAP
.get(ScenarioStatusType
.ABANDONED
);
331 value
= STATUS_MAP
.get(ScenarioStatusType
.MATCHED
);
334 value
= STATUS_MAP
.get(ScenarioStatusType
.PENDING
);
337 value
= TmfStateValue
.nullValue();
340 ss
.modifyAttribute(ts
, value
, info
.getStatusQuark());
341 } catch (StateValueTypeException e
) {
342 Activator
.logError("failed to update scenario status"); //$NON-NLS-1$
346 private static long getTimestamp(@Nullable ITmfEvent event
, @Nullable ITmfStateSystemBuilder ss
) {
348 return event
.getTimestamp().toNanos();
351 return ss
.getCurrentEndTime();
353 throw new IllegalArgumentException("Event and state system cannot be null at the same time."); //$NON-NLS-1$
356 private static void updateScenarioState(final @Nullable ITmfEvent event
, final IXmlStateSystemContainer container
, final TmfXmlScenarioInfo info
) {
357 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
358 long ts
= getTimestamp(event
, ss
);
361 ITmfStateValue value
= TmfStateValue
.newValueString(info
.getActiveState());
362 int attributeQuark
= ss
.getQuarkRelativeAndAdd(info
.getQuark(), TmfXmlStrings
.STATE
);
363 ss
.modifyAttribute(ts
, value
, attributeQuark
);
364 } catch (StateValueTypeException e
) {
365 Activator
.logError("failed to update scenario state"); //$NON-NLS-1$
370 * Update the start time of specified state
375 * The state system container this class use
377 * The scenario details
379 private static void updateScenarioSpecificStateStartTime(final @Nullable ITmfEvent event
, final IXmlStateSystemContainer container
, final TmfXmlScenarioInfo info
) {
380 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
381 long ts
= getTimestamp(event
, ss
);
383 int stateQuark
= ss
.getQuarkRelativeAndAdd(info
.getQuark(), TmfXmlStrings
.STATE
);
384 String activeState
= ss
.queryOngoingState(stateQuark
).unboxStr();
385 if (activeState
.compareTo(info
.getActiveState()) != 0) {
386 int attributeQuark
= ss
.getQuarkRelativeAndAdd(stateQuark
, info
.getActiveState(), START_TIME
);
387 ITmfStateValue value
= TmfStateValue
.newValueLong(ts
);
388 ss
.modifyAttribute(ts
, value
, attributeQuark
);
390 } catch (StateValueTypeException e
) {
391 Activator
.logError("failed to update the start time of the state"); //$NON-NLS-1$
396 * Start the scenario, sets the start time for the time of the event
399 * The state system container this class use
401 * The scenario details. The value should be null if there is no
406 public void startScenario(final IXmlStateSystemContainer container
, final TmfXmlScenarioInfo info
, final ITmfEvent event
) {
407 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
408 long ts
= getTimestamp(event
, ss
);
411 ITmfStateValue value
= TmfStateValue
.newValueLong(ts
);
412 int attributeQuark
= ss
.getQuarkRelativeAndAdd(info
.getQuark(), START_TIME
);
413 ss
.modifyAttribute(ts
, value
, attributeQuark
);
414 } catch (StateValueTypeException e
) {
415 Activator
.logError("failed to update the start time of the scenario"); //$NON-NLS-1$
420 * Set the end time of the scenario to the time of the event, or current
421 * state system end time if null, and recycle the attribute quark
424 * The state system container this class use
426 * The scenario details. The value should be null if there is no
431 public void completeScenario(final IXmlStateSystemContainer container
, final TmfXmlScenarioInfo info
, final @Nullable ITmfEvent event
) {
432 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
433 long ts
= getTimestamp(event
, ss
);
434 TmfAttributePool pool
= getPoolFor(container
, info
.getFsmId());
435 pool
.recycle(info
.getQuark(), ts
);