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
.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
.statesystem
.core
.ITmfStateSystemBuilder
;
18 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
19 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateSystemDisposedException
;
20 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateValueTypeException
;
21 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.ITmfStateInterval
;
22 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
23 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.TmfStateValue
;
24 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.module
.IXmlStateSystemContainer
;
25 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.stateprovider
.TmfXmlStrings
;
26 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
27 import org
.eclipse
.tracecompass
.tmf
.core
.statesystem
.TmfAttributePool
;
29 import com
.google
.common
.collect
.BiMap
;
30 import com
.google
.common
.collect
.ImmutableBiMap
;
33 * This class is responsible for creating scenarios, updating their status and
34 * data, and saving the scenario data to the state system
38 public class TmfXmlScenarioHistoryBuilder
{
40 /** The string 'status' */
41 public static final String STATUS
= "status"; //$NON-NLS-1$
42 /** The string for "nbScenarios" */
43 public static final String SCENARIO_COUNT
= "nbScenarios"; //$NON-NLS-1$
45 /** The string for start time */
46 private static final String START_TIME
= "startTime"; //$NON-NLS-1$
48 private static final String ERROR_MESSAGE
= "The state system is null"; //$NON-NLS-1$
50 private final Map
<String
, TmfAttributePool
> fFsmPools
= new HashMap
<>();
53 * All possible types of status for a scenario
55 public enum ScenarioStatusType
{
57 * scenario pending for start point
61 * scenario in progress
69 * scenario match with the pattern
75 * Cache the available status in a map
77 protected static final BiMap
<ScenarioStatusType
, ITmfStateValue
> STATUS_MAP
= NonNullUtils
.checkNotNull(ImmutableBiMap
.of(
78 ScenarioStatusType
.PENDING
, TmfStateValue
.newValueInt(0),
79 ScenarioStatusType
.IN_PROGRESS
, TmfStateValue
.newValueInt(1),
80 ScenarioStatusType
.MATCHED
, TmfStateValue
.newValueInt(2),
81 ScenarioStatusType
.ABANDONED
, TmfStateValue
.newValueInt(3)));
84 * Get the scenario matched process start time
87 * The state system container this class use
89 * The scenario details
93 * @return The start time of the matching process for the specified scenario
95 public long getStartTime(final IXmlStateSystemContainer container
, final TmfXmlScenarioInfo info
, final ITmfEvent event
) {
96 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
97 long ts
= getTimestamp(event
, ss
);
99 int attributeQuark
= getQuarkRelativeAndAdd(ss
, info
.getQuark(), START_TIME
);
100 ITmfStateInterval state
= ss
.querySingleState(ts
, attributeQuark
);
101 return state
.getStartTime();
102 } catch (AttributeNotFoundException
| StateSystemDisposedException e
) {
103 Activator
.logError("failed to get the start time of the scenario", e
); //$NON-NLS-1$
109 * Save the stored fields
112 * The state system container this class use
113 * @param attributeName
114 * The name of the attribute to save
116 * The value of the attribute to save
118 * The scenario details
122 public void updateStoredFields(final IXmlStateSystemContainer container
, final String attributeName
, final ITmfStateValue value
, final TmfXmlScenarioInfo info
, final ITmfEvent event
) {
123 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
124 long ts
= getTimestamp(event
, ss
);
126 int attributeQuark
= getQuarkRelativeAndAdd(ss
, info
.getQuark(), TmfXmlStrings
.STORED_FIELDS
, attributeName
);
127 ss
.modifyAttribute(ts
, value
, attributeQuark
);
128 } catch (StateValueTypeException
| AttributeNotFoundException e
) {
129 Activator
.logError("failed to save the stored field " + attributeName
, e
); //$NON-NLS-1$
134 * Clear the special fields
137 * The state system container this class use
138 * @param attributeName
139 * The name of the attribute to save
141 * The scenario details
145 public void resetStoredFields(final IXmlStateSystemContainer container
, final String attributeName
, final TmfXmlScenarioInfo info
, final ITmfEvent event
) {
146 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
147 long ts
= getTimestamp(event
, ss
);
148 ITmfStateValue value
= TmfStateValue
.nullValue();
150 int attributeQuark
= getQuarkRelativeAndAdd(ss
, info
.getQuark(), TmfXmlStrings
.STORED_FIELDS
, attributeName
);
151 ss
.modifyAttribute(ts
, value
, attributeQuark
);
152 } catch (StateValueTypeException
| AttributeNotFoundException e
) {
153 Activator
.logError("failed to clear the stored fields", e
); //$NON-NLS-1$
158 * Get the value of a special field in the state system
161 * The state system container this class use
162 * @param attributeName
163 * The attribute name of the special field
165 * The scenario details
169 * @return The value of a special field saved into the state system
171 public ITmfStateValue
getStoredFieldValue(IXmlStateSystemContainer container
, String attributeName
, final TmfXmlScenarioInfo info
, ITmfEvent event
) {
172 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
173 long ts
= event
.getTimestamp().toNanos();
174 ITmfStateInterval state
= null;
176 int attributeQuark
= getQuarkRelativeAndAdd(ss
, info
.getQuark(), TmfXmlStrings
.STORED_FIELDS
, attributeName
);
177 state
= ss
.querySingleState(ts
, attributeQuark
);
178 } catch (AttributeNotFoundException
| StateSystemDisposedException e
) {
179 Activator
.logError("failed to get the value of the stored field " + attributeName
, e
); //$NON-NLS-1$
181 return (state
!= null) ? NonNullUtils
.checkNotNull(state
.getStateValue()) : TmfStateValue
.nullValue();
185 * Get the attribute pool for this fsm
188 * The state system container
191 * @return The attribute pool associated with this FSM
193 protected TmfAttributePool
getPoolFor(IXmlStateSystemContainer container
, String fsmId
) {
194 TmfAttributePool pool
= fFsmPools
.get(fsmId
);
198 ITmfStateSystemBuilder ss
= NonNullUtils
.checkNotNull((ITmfStateSystemBuilder
) container
.getStateSystem());
199 String
[] fsmPath
= new String
[] { TmfXmlStrings
.SCENARIOS
, fsmId
};
200 int quark
= getQuarkAbsoluteAndAdd(ss
, fsmPath
);
201 pool
= new TmfAttributePool(ss
, quark
);
202 fFsmPools
.put(fsmId
, pool
);
207 * Get the scenario quark
210 * The state system container this class use
212 * Id of the fsm this scenario is associated to
213 * @return The scenario quark
215 public int assignScenarioQuark(IXmlStateSystemContainer container
, String fsmId
) {
216 TmfAttributePool pool
= getPoolFor(container
, fsmId
);
217 return pool
.getAvailable();
221 * Get the scenario status quark
224 * The state system container this class use
225 * @param scenarioQuark
227 * @return The scenario quark
229 public int getScenarioStatusQuark(IXmlStateSystemContainer container
, int scenarioQuark
) {
230 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
231 return getQuarkRelativeAndAdd(ss
, scenarioQuark
, STATUS
);
235 * Get the start time of a specific state of the scenario
238 * The state system container this class use
240 * The name of the current state of the scenario
242 * The scenario details
246 * @return The start time for the specified state
248 public long getSpecificStateStartTime(final IXmlStateSystemContainer container
, final String stateName
, final TmfXmlScenarioInfo info
, final ITmfEvent event
) {
249 long ts
= event
.getTimestamp().getValue();
250 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
252 int attributeQuark
= getQuarkRelativeAndAdd(ss
, info
.getQuark(), TmfXmlStrings
.STATE
, stateName
, START_TIME
);
253 ITmfStateInterval state
= ss
.querySingleState(ts
, attributeQuark
);
254 return state
.getStartTime();
255 } catch (AttributeNotFoundException
| StateSystemDisposedException e
) {
256 Activator
.logError("failed the start time of the state " + stateName
, e
); //$NON-NLS-1$
262 * Basic quark-retrieving method. Pass an attribute in parameter as an array
263 * of strings, the matching quark will be returned. If the attribute does
264 * not exist, it will add the quark to the state system if the context
267 * See {@link ITmfStateSystemBuilder#getQuarkAbsoluteAndAdd(String...)}
270 * The state system the attribute belongs to
272 * Full path to the attribute
273 * @return The quark for this attribute
275 private static int getQuarkAbsoluteAndAdd(@Nullable ITmfStateSystemBuilder ss
, String
... path
) {
277 throw new NullPointerException(ERROR_MESSAGE
);
279 return ss
.getQuarkAbsoluteAndAdd(path
);
283 * Quark-retrieving method, but the attribute is queried starting from the
284 * startNodeQuark. If the attribute does not exist, it will add it to the
285 * state system if the context allows it.
287 * See {@link ITmfStateSystemBuilder#getQuarkRelativeAndAdd(int, String...)}
290 * The state system the attribute belongs to
291 * @param startNodeQuark
292 * The quark of the attribute from which 'path' originates.
294 * Relative path to the attribute
295 * @return The quark for this attribute
297 private static int getQuarkRelativeAndAdd(@Nullable ITmfStateSystemBuilder ss
, int startNodeQuark
, String
... path
) {
299 throw new NullPointerException(ERROR_MESSAGE
);
301 return ss
.getQuarkRelativeAndAdd(startNodeQuark
, path
);
305 * Update the scenario internal data
308 * The state system container this class use
310 * The scenario details
314 public void update(final IXmlStateSystemContainer container
, final TmfXmlScenarioInfo info
, final @Nullable ITmfEvent event
) {
315 updateScenarioSpecificStateStartTime(event
, container
, info
);
316 updateScenarioState(event
, container
, info
);
317 updateScenarioStatus(event
, container
, info
);
320 private static void updateScenarioStatus(@Nullable ITmfEvent event
, IXmlStateSystemContainer container
, final TmfXmlScenarioInfo info
) {
321 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
322 long ts
= getTimestamp(event
, ss
);
323 ITmfStateValue value
;
326 switch (info
.getStatus()) {
328 value
= STATUS_MAP
.get(ScenarioStatusType
.IN_PROGRESS
);
331 value
= STATUS_MAP
.get(ScenarioStatusType
.ABANDONED
);
334 value
= STATUS_MAP
.get(ScenarioStatusType
.MATCHED
);
337 value
= STATUS_MAP
.get(ScenarioStatusType
.PENDING
);
340 value
= TmfStateValue
.nullValue();
343 ss
.modifyAttribute(ts
, value
, info
.getStatusQuark());
344 } catch (StateValueTypeException
| AttributeNotFoundException e
) {
345 Activator
.logError("failed to update scenario status"); //$NON-NLS-1$
349 private static long getTimestamp(@Nullable ITmfEvent event
, @Nullable ITmfStateSystemBuilder ss
) {
351 return event
.getTimestamp().toNanos();
354 return ss
.getCurrentEndTime();
356 throw new IllegalArgumentException("Event and state system cannot be null at the same time."); //$NON-NLS-1$
359 private static void updateScenarioState(final @Nullable ITmfEvent event
, final IXmlStateSystemContainer container
, final TmfXmlScenarioInfo info
) {
360 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
361 long ts
= getTimestamp(event
, ss
);
364 ITmfStateValue value
= TmfStateValue
.newValueString(info
.getActiveState());
365 int attributeQuark
= ss
.getQuarkRelativeAndAdd(info
.getQuark(), TmfXmlStrings
.STATE
);
366 ss
.modifyAttribute(ts
, value
, attributeQuark
);
367 } catch (StateValueTypeException
| AttributeNotFoundException e
) {
368 Activator
.logError("failed to update scenario state"); //$NON-NLS-1$
373 * Update the start time of specified state
378 * The state system container this class use
380 * The scenario details
382 private static void updateScenarioSpecificStateStartTime(final @Nullable ITmfEvent event
, final IXmlStateSystemContainer container
, final TmfXmlScenarioInfo info
) {
383 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
384 long ts
= getTimestamp(event
, ss
);
386 int stateQuark
= ss
.getQuarkRelativeAndAdd(info
.getQuark(), TmfXmlStrings
.STATE
);
387 String activeState
= ss
.queryOngoingState(stateQuark
).unboxStr();
388 if (activeState
.compareTo(info
.getActiveState()) != 0) {
389 int attributeQuark
= ss
.getQuarkRelativeAndAdd(stateQuark
, info
.getActiveState(), START_TIME
);
390 ITmfStateValue value
= TmfStateValue
.newValueLong(ts
);
391 ss
.modifyAttribute(ts
, value
, attributeQuark
);
393 } catch (StateValueTypeException
| AttributeNotFoundException e
) {
394 Activator
.logError("failed to update the start time of the state"); //$NON-NLS-1$
399 * Start the scenario, sets the start time for the time of the event
402 * The state system container this class use
404 * The scenario details. The value should be null if there is no
409 public void startScenario(final IXmlStateSystemContainer container
, final TmfXmlScenarioInfo info
, final ITmfEvent event
) {
410 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
411 long ts
= getTimestamp(event
, ss
);
414 ITmfStateValue value
= TmfStateValue
.newValueLong(ts
);
415 int attributeQuark
= ss
.getQuarkRelativeAndAdd(info
.getQuark(), START_TIME
);
416 ss
.modifyAttribute(ts
, value
, attributeQuark
);
417 } catch (StateValueTypeException
| AttributeNotFoundException e
) {
418 Activator
.logError("failed to update the start time of the scenario"); //$NON-NLS-1$
423 * Set the end time of the scenario to the time of the event, or current
424 * state system end time if null, and recycle the attribute quark
427 * The state system container this class use
429 * The scenario details. The value should be null if there is no
434 public void completeScenario(final IXmlStateSystemContainer container
, final TmfXmlScenarioInfo info
, final @Nullable ITmfEvent event
) {
435 ITmfStateSystemBuilder ss
= (ITmfStateSystemBuilder
) container
.getStateSystem();
436 long ts
= getTimestamp(event
, ss
);
437 TmfAttributePool pool
= getPoolFor(container
, info
.getFsmId());
438 pool
.recycle(info
.getQuark(), ts
);