os.linux: Rewrite a CPU usage test in a less insane way
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.analysis.xml.core / src / org / eclipse / tracecompass / tmf / analysis / xml / core / model / TmfXmlStateAttribute.java
CommitLineData
0f7276b6 1/*******************************************************************************
ed902a2b 2 * Copyright (c) 2014, 2015 Ecole Polytechnique de Montreal
0f7276b6
GB
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 *
9 * Contributors:
10 * Florian Wininger - Initial API and implementation
11 ******************************************************************************/
12
2bdf0193 13package org.eclipse.tracecompass.tmf.analysis.xml.core.model;
0f7276b6 14
1d7e62f9 15import java.util.LinkedList;
0f7276b6
GB
16import java.util.List;
17
1d7e62f9 18import org.eclipse.jdt.annotation.Nullable;
2bdf0193 19import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.Activator;
e894a508
AM
20import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
21import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
22import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
23import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
24import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
25import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
2bdf0193
AM
26import org.eclipse.tracecompass.tmf.analysis.xml.core.module.IXmlStateSystemContainer;
27import org.eclipse.tracecompass.tmf.analysis.xml.core.module.XmlUtils;
28import org.eclipse.tracecompass.tmf.analysis.xml.core.stateprovider.TmfXmlStrings;
29import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
30import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
35f39420
AM
31import org.eclipse.tracecompass.tmf.core.event.aspect.TmfCpuAspect;
32import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
0f7276b6
GB
33import org.w3c.dom.Element;
34
35/**
1d7e62f9
GB
36 * This Class implements a single attribute value in the XML-defined state
37 * system.
0f7276b6
GB
38 *
39 * <pre>
40 * Examples:
41 * <stateAttribute type="constant" value="Threads" />
42 * <stateAttribute type="query" />
43 * <stateAttribute type="constant" value="CPUs" />
44 * <stateAttribute type="eventField" value="cpu" />
45 * <stateAttribute type="constant" value="Current_thread" />
46 * </attribute>
47 * </pre>
48 *
49 * @author Florian Wininger
50 */
1d7e62f9 51public abstract class TmfXmlStateAttribute implements ITmfXmlStateAttribute {
0f7276b6
GB
52
53 private enum StateAttributeType {
54 NONE,
55 CONSTANT,
56 EVENTFIELD,
57 QUERY,
1d7e62f9 58 LOCATION,
597168fc
NE
59 SELF,
60 EVENTNAME
0f7276b6
GB
61 }
62
63 /** Type of attribute */
64 private final StateAttributeType fType;
65
66 /** Attribute's name */
12685851 67 private final @Nullable String fName;
0f7276b6
GB
68
69 /** List of attributes for a query */
1d7e62f9 70 private final List<ITmfXmlStateAttribute> fQueryList = new LinkedList<>();
0f7276b6 71
1d7e62f9 72 private final IXmlStateSystemContainer fContainer;
0f7276b6
GB
73
74 /**
75 * Constructor
76 *
1d7e62f9
GB
77 * @param modelFactory
78 * The factory used to create XML model elements
0f7276b6
GB
79 * @param attribute
80 * XML element of the attribute
1d7e62f9
GB
81 * @param container
82 * The state system container this state attribute belongs to
0f7276b6 83 */
1d7e62f9
GB
84 protected TmfXmlStateAttribute(ITmfXmlModelFactory modelFactory, Element attribute, IXmlStateSystemContainer container) {
85 fContainer = container;
0f7276b6
GB
86
87 switch (attribute.getAttribute(TmfXmlStrings.TYPE)) {
88 case TmfXmlStrings.TYPE_CONSTANT:
89 fType = StateAttributeType.CONSTANT;
1d7e62f9 90 fName = fContainer.getAttributeValue(attribute.getAttribute(TmfXmlStrings.VALUE));
0f7276b6
GB
91 break;
92 case TmfXmlStrings.EVENT_FIELD:
93 fType = StateAttributeType.EVENTFIELD;
1d7e62f9 94 fName = fContainer.getAttributeValue(attribute.getAttribute(TmfXmlStrings.VALUE));
0f7276b6
GB
95 break;
96 case TmfXmlStrings.TYPE_LOCATION:
97 fType = StateAttributeType.LOCATION;
1d7e62f9 98 fName = fContainer.getAttributeValue(attribute.getAttribute(TmfXmlStrings.VALUE));
0f7276b6
GB
99 break;
100 case TmfXmlStrings.TYPE_QUERY:
101 List<Element> childElements = XmlUtils.getChildElements(attribute);
102 for (Element subAttributeNode : childElements) {
12685851
GB
103 if (subAttributeNode == null) {
104 continue;
105 }
1d7e62f9 106 ITmfXmlStateAttribute subAttribute = modelFactory.createStateAttribute(subAttributeNode, fContainer);
0f7276b6
GB
107 fQueryList.add(subAttribute);
108 }
109 fType = StateAttributeType.QUERY;
110 fName = null;
111 break;
597168fc
NE
112 case TmfXmlStrings.TYPE_EVENT_NAME:
113 fType = StateAttributeType.EVENTNAME;
114 fName = fContainer.getAttributeValue(attribute.getAttribute(TmfXmlStrings.VALUE));
115 break;
0f7276b6
GB
116 case TmfXmlStrings.NULL:
117 fType = StateAttributeType.NONE;
118 fName = null;
119 break;
1d7e62f9
GB
120 case TmfXmlStrings.TYPE_SELF:
121 fType = StateAttributeType.SELF;
122 fName = null;
123 break;
0f7276b6
GB
124 default:
125 throw new IllegalArgumentException("TmfXmlStateAttribute constructor: The XML element is not of the right type"); //$NON-NLS-1$
126 }
127 }
128
129 /**
130 * This method gets the quark for this state attribute in the State System.
0f7276b6
GB
131 *
132 * Unless this attribute is a location, in which case the quark must exist,
1d7e62f9
GB
133 * the quark will be added to the state system if the state system is in
134 * builder mode.
0f7276b6 135 *
0f7276b6 136 * @param startQuark
1d7e62f9
GB
137 * root quark, use {@link IXmlStateSystemContainer#ROOT_QUARK} to
138 * search the full attribute tree
0f7276b6 139 * @return the quark described by attribute or
1d7e62f9
GB
140 * {@link IXmlStateSystemContainer#ERROR_QUARK} if quark cannot be
141 * found
142 */
143 @Override
144 public int getAttributeQuark(int startQuark) {
145 return getAttributeQuark(null, startQuark);
146 }
147
148 /**
149 * Basic quark-retrieving method. Pass an attribute in parameter as an array
150 * of strings, the matching quark will be returned. If the attribute does
151 * not exist, it will add the quark to the state system if the context
152 * allows it.
153 *
154 * See {@link ITmfStateSystemBuilder#getQuarkAbsoluteAndAdd(String...)}
155 *
156 * @param path
157 * Full path to the attribute
158 * @return The quark for this attribute
159 * @throws AttributeNotFoundException
160 * The attribute does not exist and cannot be added
161 */
162 protected abstract int getQuarkAbsoluteAndAdd(String... path) throws AttributeNotFoundException;
163
164 /**
165 * Quark-retrieving method, but the attribute is queried starting from the
166 * startNodeQuark. If the attribute does not exist, it will add it to the
167 * state system if the context allows it.
168 *
169 * See {@link ITmfStateSystemBuilder#getQuarkRelativeAndAdd(int, String...)}
170 *
171 * @param startNodeQuark
172 * The quark of the attribute from which 'path' originates.
173 * @param path
174 * Relative path to the attribute
175 * @return The quark for this attribute
176 * @throws AttributeNotFoundException
177 * The attribute does not exist and cannot be added
178 */
179 protected abstract int getQuarkRelativeAndAdd(int startNodeQuark, String... path) throws AttributeNotFoundException;
180
181 /**
182 * Get the state system associated with this attribute's container
183 *
184 * @return The state system associated with this state attribute
0f7276b6 185 */
12685851 186 protected @Nullable ITmfStateSystem getStateSystem() {
1d7e62f9
GB
187 return fContainer.getStateSystem();
188 }
0f7276b6 189
1d7e62f9
GB
190 /**
191 * This method gets the quark for this state attribute in the State System.
192 *
193 * Unless this attribute is a location, in which case the quark must exist,
194 * the quark will be added to the state system if the state system is in
195 * builder mode.
196 *
197 * @param event
198 * The current event being handled, or <code>null</code> if no
199 * event available in the context
200 * @param startQuark
201 * root quark, use {@link IXmlStateSystemContainer#ROOT_QUARK} to
202 * search the full attribute tree
203 * @return the quark described by attribute or
204 * {@link IXmlStateSystemContainer#ERROR_QUARK} if quark cannot be
205 * found
206 */
207 @Override
208 public int getAttributeQuark(@Nullable ITmfEvent event, int startQuark) {
209 ITmfStateSystem ss = getStateSystem();
12685851
GB
210 if (ss == null) {
211 throw new IllegalStateException("The state system hasn't been initialized yet"); //$NON-NLS-1$
212 }
0f7276b6
GB
213
214 try {
215 switch (fType) {
216 case CONSTANT: {
217 int quark;
1d7e62f9
GB
218 if (startQuark == IXmlStateSystemContainer.ROOT_QUARK) {
219 quark = getQuarkAbsoluteAndAdd(fName);
0f7276b6 220 } else {
1d7e62f9 221 quark = getQuarkRelativeAndAdd(startQuark, fName);
0f7276b6
GB
222 }
223 return quark;
224 }
225 case EVENTFIELD: {
1d7e62f9
GB
226 int quark = IXmlStateSystemContainer.ERROR_QUARK;
227 if (event == null) {
228 Activator.logWarning("XML State attribute: looking for an event field, but event is null"); //$NON-NLS-1$
229 return quark;
230 }
0f7276b6 231 /* special case if field is CPU which is not in the field */
12685851
GB
232 String name = fName;
233 if (name == null) {
234 throw new IllegalStateException();
235 }
236 if (name.equals(TmfXmlStrings.CPU)) {
35f39420
AM
237 /* See if the event advertises a CPU aspect */
238 Iterable<TmfCpuAspect> cpuAspects = TmfTraceUtils.getEventAspectsOfClass(
239 event.getTrace(), TmfCpuAspect.class);
240 for (TmfCpuAspect aspect : cpuAspects) {
52293ccd 241 Integer cpu = aspect.resolve(event);
2a28075c 242 if (cpu != null) {
52293ccd 243 quark = getQuarkRelativeAndAdd(startQuark, cpu.toString());
35f39420
AM
244 break;
245 }
246 }
247 } else {
1d7e62f9 248 final ITmfEventField content = event.getContent();
0f7276b6
GB
249 /* stop if the event field doesn't exist */
250 if (content.getField(fName) == null) {
1d7e62f9 251 return IXmlStateSystemContainer.ERROR_QUARK;
0f7276b6
GB
252 }
253
254 Object field = content.getField(fName).getValue();
255
256 if (field instanceof String) {
257 String fieldString = (String) field;
1d7e62f9 258 quark = getQuarkRelativeAndAdd(startQuark, fieldString);
0f7276b6
GB
259 } else if (field instanceof Long) {
260 Long fieldLong = (Long) field;
1d7e62f9 261 quark = getQuarkRelativeAndAdd(startQuark, fieldLong.toString());
0f7276b6
GB
262 } else if (field instanceof Integer) {
263 Integer fieldInterger = (Integer) field;
1d7e62f9 264 quark = getQuarkRelativeAndAdd(startQuark, fieldInterger.toString());
0f7276b6 265 }
35f39420 266 }
0f7276b6
GB
267 return quark;
268 }
269 case QUERY: {
270 int quark;
271 ITmfStateValue value = TmfStateValue.nullValue();
1d7e62f9 272 int quarkQuery = IXmlStateSystemContainer.ROOT_QUARK;
0f7276b6 273
1d7e62f9 274 for (ITmfXmlStateAttribute attrib : fQueryList) {
0f7276b6 275 quarkQuery = attrib.getAttributeQuark(event, quarkQuery);
1d7e62f9 276 if (quarkQuery == IXmlStateSystemContainer.ERROR_QUARK) {
0f7276b6
GB
277 break;
278 }
279 }
280
281 // the query may fail: for example CurrentThread if there
282 // has not been a sched_switch event
1d7e62f9 283 if (quarkQuery != IXmlStateSystemContainer.ERROR_QUARK) {
0f7276b6
GB
284 value = ss.queryOngoingState(quarkQuery);
285 }
286
287 switch (value.getType()) {
288 case INTEGER: {
289 int result = value.unboxInt();
1d7e62f9 290 quark = getQuarkRelativeAndAdd(startQuark, String.valueOf(result));
0f7276b6
GB
291 break;
292 }
293 case LONG: {
294 long result = value.unboxLong();
1d7e62f9 295 quark = getQuarkRelativeAndAdd(startQuark, String.valueOf(result));
0f7276b6
GB
296 break;
297 }
298 case STRING: {
299 String result = value.unboxStr();
1d7e62f9 300 quark = getQuarkRelativeAndAdd(startQuark, result);
0f7276b6
GB
301 break;
302 }
303 case DOUBLE:
304 case NULL:
305 default:
1d7e62f9 306 quark = IXmlStateSystemContainer.ERROR_QUARK; // error
0f7276b6
GB
307 break;
308 }
309 return quark;
310 }
311 case LOCATION: {
312 int quark = startQuark;
313 String idLocation = fName;
314
1d7e62f9
GB
315 /* TODO: Add a fContainer.getLocation(id) method */
316 for (TmfXmlLocation location : fContainer.getLocations()) {
0f7276b6
GB
317 if (location.getId().equals(idLocation)) {
318 quark = location.getLocationQuark(event, quark);
1d7e62f9 319 if (quark == IXmlStateSystemContainer.ERROR_QUARK) {
0f7276b6
GB
320 break;
321 }
322 }
323 }
324 return quark;
325 }
597168fc
NE
326 case EVENTNAME: {
327 int quark = IXmlStateSystemContainer.ERROR_QUARK;
328 if (event == null) {
329 Activator.logWarning("XML State attribute: looking for an eventname, but event is null"); //$NON-NLS-1$
330 return quark;
331 }
332 quark = getQuarkRelativeAndAdd(startQuark, event.getType().getName());
333 return quark;
334 }
1d7e62f9
GB
335 case SELF:
336 return startQuark;
0f7276b6
GB
337 case NONE:
338 default:
339 return startQuark;
340 }
341 } catch (AttributeNotFoundException ae) {
342 /*
343 * This can be happen before the creation of the node for a query in
344 * the state system. Example : current thread before a sched_switch
345 */
1d7e62f9 346 return IXmlStateSystemContainer.ERROR_QUARK;
0f7276b6
GB
347 } catch (StateValueTypeException e) {
348 /*
349 * This would happen if we were trying to push/pop attributes not of
350 * type integer. Which, once again, should never happen.
351 */
352 Activator.logError("StateValueTypeException", e); //$NON-NLS-1$
1d7e62f9 353 return IXmlStateSystemContainer.ERROR_QUARK;
0f7276b6
GB
354 }
355 }
356
446598f9
GB
357 @Override
358 public String toString() {
359 return "TmfXmlStateAttribute " + fType + ": " + fName; //$NON-NLS-1$ //$NON-NLS-2$
360 }
361
52293ccd 362}
This page took 0.06644 seconds and 5 git commands to generate.