Commit | Line | Data |
---|---|---|
3a5f73a1 JCK |
1 | /******************************************************************************* |
2 | * Copyright (c) 2016 Ecole Polytechnique de Montreal, Ericsson | |
3 | * | |
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 | ******************************************************************************/ | |
6eca054d | 9 | package org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model; |
3a5f73a1 JCK |
10 | |
11 | import java.util.HashMap; | |
12 | import java.util.Map; | |
13 | ||
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; | |
6eca054d GB |
17 | import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.IXmlStateSystemContainer; |
18 | import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.stateprovider.TmfXmlStrings; | |
3a5f73a1 | 19 | import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder; |
3a5f73a1 JCK |
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; | |
3a5f73a1 JCK |
25 | import org.eclipse.tracecompass.tmf.core.event.ITmfEvent; |
26 | import org.eclipse.tracecompass.tmf.core.statesystem.TmfAttributePool; | |
27 | ||
28 | import com.google.common.collect.BiMap; | |
29 | import com.google.common.collect.ImmutableBiMap; | |
30 | ||
31 | /** | |
32 | * This class is responsible for creating scenarios, updating their status and | |
33 | * data, and saving the scenario data to the state system | |
3a5f73a1 JCK |
34 | */ |
35 | public class TmfXmlScenarioHistoryBuilder { | |
36 | ||
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$ | |
41 | ||
42 | /** The string for start time */ | |
43 | private static final String START_TIME = "startTime"; //$NON-NLS-1$ | |
44 | /** Error message */ | |
45 | private static final String ERROR_MESSAGE = "The state system is null"; //$NON-NLS-1$ | |
46 | ||
47 | private final Map<String, TmfAttributePool> fFsmPools = new HashMap<>(); | |
48 | ||
49 | /** | |
50 | * All possible types of status for a scenario | |
51 | */ | |
52 | public enum ScenarioStatusType { | |
53 | /** | |
54 | * scenario pending for start point | |
55 | */ | |
56 | PENDING, | |
57 | /** | |
58 | * scenario in progress | |
59 | */ | |
60 | IN_PROGRESS, | |
61 | /** | |
62 | * scenario abandoned | |
63 | */ | |
64 | ABANDONED, | |
65 | /** | |
66 | * scenario match with the pattern | |
67 | */ | |
68 | MATCHED | |
69 | } | |
70 | ||
71 | /** | |
72 | * Cache the available status in a map | |
73 | */ | |
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))); | |
79 | ||
80 | /** | |
81 | * Get the scenario matched process start time | |
82 | * | |
83 | * @param container | |
84 | * The state system container this class use | |
85 | * @param info | |
86 | * The scenario details | |
87 | * @param event | |
88 | * The current event | |
89 | * | |
90 | * @return The start time of the matching process for the specified scenario | |
91 | */ | |
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); | |
95 | try { | |
96 | int attributeQuark = getQuarkRelativeAndAdd(ss, info.getQuark(), START_TIME); | |
97 | ITmfStateInterval state = ss.querySingleState(ts, attributeQuark); | |
98 | return state.getStartTime(); | |
ed48dc75 | 99 | } catch (StateSystemDisposedException e) { |
3a5f73a1 JCK |
100 | Activator.logError("failed to get the start time of the scenario", e); //$NON-NLS-1$ |
101 | } | |
102 | return -1L; | |
103 | } | |
104 | ||
105 | /** | |
106 | * Save the stored fields | |
107 | * | |
108 | * @param container | |
109 | * The state system container this class use | |
110 | * @param attributeName | |
111 | * The name of the attribute to save | |
112 | * @param value | |
113 | * The value of the attribute to save | |
114 | * @param info | |
115 | * The scenario details | |
116 | * @param event | |
117 | * The current event | |
118 | */ | |
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); | |
122 | try { | |
123 | int attributeQuark = getQuarkRelativeAndAdd(ss, info.getQuark(), TmfXmlStrings.STORED_FIELDS, attributeName); | |
124 | ss.modifyAttribute(ts, value, attributeQuark); | |
ed48dc75 | 125 | } catch (StateValueTypeException e) { |
3a5f73a1 JCK |
126 | Activator.logError("failed to save the stored field " + attributeName, e); //$NON-NLS-1$ |
127 | } | |
128 | } | |
129 | ||
130 | /** | |
131 | * Clear the special fields | |
132 | * | |
133 | * @param container | |
134 | * The state system container this class use | |
135 | * @param attributeName | |
136 | * The name of the attribute to save | |
137 | * @param info | |
138 | * The scenario details | |
139 | * @param event | |
140 | * The current event | |
141 | */ | |
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(); | |
146 | try { | |
147 | int attributeQuark = getQuarkRelativeAndAdd(ss, info.getQuark(), TmfXmlStrings.STORED_FIELDS, attributeName); | |
148 | ss.modifyAttribute(ts, value, attributeQuark); | |
ed48dc75 | 149 | } catch (StateValueTypeException e) { |
3a5f73a1 JCK |
150 | Activator.logError("failed to clear the stored fields", e); //$NON-NLS-1$ |
151 | } | |
152 | } | |
153 | ||
154 | /** | |
155 | * Get the value of a special field in the state system | |
156 | * | |
157 | * @param container | |
158 | * The state system container this class use | |
159 | * @param attributeName | |
160 | * The attribute name of the special field | |
161 | * @param info | |
162 | * The scenario details | |
163 | * @param event | |
164 | * The current event | |
165 | * | |
166 | * @return The value of a special field saved into the state system | |
167 | */ | |
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; | |
172 | try { | |
173 | int attributeQuark = getQuarkRelativeAndAdd(ss, info.getQuark(), TmfXmlStrings.STORED_FIELDS, attributeName); | |
174 | state = ss.querySingleState(ts, attributeQuark); | |
ed48dc75 | 175 | } catch (StateSystemDisposedException e) { |
3a5f73a1 JCK |
176 | Activator.logError("failed to get the value of the stored field " + attributeName, e); //$NON-NLS-1$ |
177 | } | |
178 | return (state != null) ? NonNullUtils.checkNotNull(state.getStateValue()) : TmfStateValue.nullValue(); | |
179 | } | |
180 | ||
181 | /** | |
182 | * Get the attribute pool for this fsm | |
183 | * | |
184 | * @param container | |
185 | * The state system container | |
186 | * @param fsmId | |
187 | * The ID of the FSM | |
188 | * @return The attribute pool associated with this FSM | |
189 | */ | |
190 | protected TmfAttributePool getPoolFor(IXmlStateSystemContainer container, String fsmId) { | |
191 | TmfAttributePool pool = fFsmPools.get(fsmId); | |
192 | if (pool != null) { | |
193 | return pool; | |
194 | } | |
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); | |
200 | return pool; | |
201 | } | |
202 | ||
203 | /** | |
204 | * Get the scenario quark | |
205 | * | |
206 | * @param container | |
207 | * The state system container this class use | |
208 | * @param fsmId | |
209 | * Id of the fsm this scenario is associated to | |
210 | * @return The scenario quark | |
211 | */ | |
212 | public int assignScenarioQuark(IXmlStateSystemContainer container, String fsmId) { | |
213 | TmfAttributePool pool = getPoolFor(container, fsmId); | |
214 | return pool.getAvailable(); | |
215 | } | |
216 | ||
217 | /** | |
218 | * Get the scenario status quark | |
219 | * | |
220 | * @param container | |
221 | * The state system container this class use | |
222 | * @param scenarioQuark | |
223 | * The scenario quark | |
224 | * @return The scenario quark | |
225 | */ | |
226 | public int getScenarioStatusQuark(IXmlStateSystemContainer container, int scenarioQuark) { | |
227 | ITmfStateSystemBuilder ss = (ITmfStateSystemBuilder) container.getStateSystem(); | |
228 | return getQuarkRelativeAndAdd(ss, scenarioQuark, STATUS); | |
229 | } | |
230 | ||
231 | /** | |
232 | * Get the start time of a specific state of the scenario | |
233 | * | |
234 | * @param container | |
235 | * The state system container this class use | |
236 | * @param stateName | |
237 | * The name of the current state of the scenario | |
238 | * @param info | |
239 | * The scenario details | |
240 | * @param event | |
241 | * The current event | |
242 | * | |
243 | * @return The start time for the specified state | |
244 | */ | |
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(); | |
248 | try { | |
249 | int attributeQuark = getQuarkRelativeAndAdd(ss, info.getQuark(), TmfXmlStrings.STATE, stateName, START_TIME); | |
250 | ITmfStateInterval state = ss.querySingleState(ts, attributeQuark); | |
251 | return state.getStartTime(); | |
ed48dc75 | 252 | } catch (StateSystemDisposedException e) { |
3a5f73a1 JCK |
253 | Activator.logError("failed the start time of the state " + stateName, e); //$NON-NLS-1$ |
254 | } | |
255 | return -1l; | |
256 | } | |
257 | ||
258 | /** | |
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 | |
262 | * allows it. | |
263 | * | |
264 | * See {@link ITmfStateSystemBuilder#getQuarkAbsoluteAndAdd(String...)} | |
265 | * | |
266 | * @param ss | |
267 | * The state system the attribute belongs to | |
268 | * @param path | |
269 | * Full path to the attribute | |
270 | * @return The quark for this attribute | |
271 | */ | |
272 | private static int getQuarkAbsoluteAndAdd(@Nullable ITmfStateSystemBuilder ss, String... path) { | |
273 | if (ss == null) { | |
274 | throw new NullPointerException(ERROR_MESSAGE); | |
275 | } | |
276 | return ss.getQuarkAbsoluteAndAdd(path); | |
277 | } | |
278 | ||
279 | /** | |
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. | |
283 | * | |
284 | * See {@link ITmfStateSystemBuilder#getQuarkRelativeAndAdd(int, String...)} | |
285 | * | |
286 | ** @param ss | |
287 | * The state system the attribute belongs to | |
288 | * @param startNodeQuark | |
289 | * The quark of the attribute from which 'path' originates. | |
290 | * @param path | |
291 | * Relative path to the attribute | |
292 | * @return The quark for this attribute | |
293 | */ | |
294 | private static int getQuarkRelativeAndAdd(@Nullable ITmfStateSystemBuilder ss, int startNodeQuark, String... path) { | |
295 | if (ss == null) { | |
296 | throw new NullPointerException(ERROR_MESSAGE); | |
297 | } | |
298 | return ss.getQuarkRelativeAndAdd(startNodeQuark, path); | |
299 | } | |
300 | ||
301 | /** | |
302 | * Update the scenario internal data | |
303 | * | |
304 | * @param container | |
305 | * The state system container this class use | |
306 | * @param info | |
307 | * The scenario details | |
308 | * @param event | |
309 | * The current event | |
310 | */ | |
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); | |
315 | } | |
316 | ||
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; | |
321 | try { | |
322 | // save the status | |
323 | switch (info.getStatus()) { | |
324 | case IN_PROGRESS: | |
325 | value = STATUS_MAP.get(ScenarioStatusType.IN_PROGRESS); | |
326 | break; | |
327 | case ABANDONED: | |
328 | value = STATUS_MAP.get(ScenarioStatusType.ABANDONED); | |
329 | break; | |
330 | case MATCHED: | |
331 | value = STATUS_MAP.get(ScenarioStatusType.MATCHED); | |
332 | break; | |
333 | case PENDING: | |
334 | value = STATUS_MAP.get(ScenarioStatusType.PENDING); | |
335 | break; | |
336 | default: | |
337 | value = TmfStateValue.nullValue(); | |
338 | break; | |
339 | } | |
340 | ss.modifyAttribute(ts, value, info.getStatusQuark()); | |
ed48dc75 | 341 | } catch (StateValueTypeException e) { |
3a5f73a1 JCK |
342 | Activator.logError("failed to update scenario status"); //$NON-NLS-1$ |
343 | } | |
344 | } | |
345 | ||
346 | private static long getTimestamp(@Nullable ITmfEvent event, @Nullable ITmfStateSystemBuilder ss) { | |
347 | if (event != null) { | |
348 | return event.getTimestamp().toNanos(); | |
349 | } | |
350 | if (ss != null) { | |
351 | return ss.getCurrentEndTime(); | |
352 | } | |
353 | throw new IllegalArgumentException("Event and state system cannot be null at the same time."); //$NON-NLS-1$ | |
354 | } | |
355 | ||
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); | |
359 | try { | |
360 | // save the status | |
361 | ITmfStateValue value = TmfStateValue.newValueString(info.getActiveState()); | |
362 | int attributeQuark = ss.getQuarkRelativeAndAdd(info.getQuark(), TmfXmlStrings.STATE); | |
363 | ss.modifyAttribute(ts, value, attributeQuark); | |
ed48dc75 | 364 | } catch (StateValueTypeException e) { |
3a5f73a1 JCK |
365 | Activator.logError("failed to update scenario state"); //$NON-NLS-1$ |
366 | } | |
367 | } | |
368 | ||
369 | /** | |
370 | * Update the start time of specified state | |
371 | * | |
372 | * @param event | |
373 | * The current event | |
374 | * @param container | |
375 | * The state system container this class use | |
376 | * @param info | |
377 | * The scenario details | |
378 | */ | |
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); | |
382 | try { | |
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); | |
389 | } | |
ed48dc75 | 390 | } catch (StateValueTypeException e) { |
3a5f73a1 JCK |
391 | Activator.logError("failed to update the start time of the state"); //$NON-NLS-1$ |
392 | } | |
393 | } | |
394 | ||
395 | /** | |
396 | * Start the scenario, sets the start time for the time of the event | |
397 | * | |
398 | * @param container | |
399 | * The state system container this class use | |
400 | * @param info | |
401 | * The scenario details. The value should be null if there is no | |
402 | * scenario | |
403 | * @param event | |
404 | * The active event | |
405 | */ | |
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); | |
409 | try { | |
410 | // save the status | |
411 | ITmfStateValue value = TmfStateValue.newValueLong(ts); | |
412 | int attributeQuark = ss.getQuarkRelativeAndAdd(info.getQuark(), START_TIME); | |
413 | ss.modifyAttribute(ts, value, attributeQuark); | |
ed48dc75 | 414 | } catch (StateValueTypeException e) { |
3a5f73a1 JCK |
415 | Activator.logError("failed to update the start time of the scenario"); //$NON-NLS-1$ |
416 | } | |
417 | } | |
418 | ||
419 | /** | |
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 | |
422 | * | |
423 | * @param container | |
424 | * The state system container this class use | |
425 | * @param info | |
426 | * The scenario details. The value should be null if there is no | |
427 | * scenario | |
428 | * @param event | |
429 | * The active event | |
430 | */ | |
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); | |
436 | } | |
437 | } |