tmf: Provide a way to get the number of attributes in a system
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng2.kernel.core / src / org / eclipse / linuxtools / internal / lttng2 / kernel / core / stateprovider / CtfKernelHandler.java
CommitLineData
efc403bb
AM
1/*******************************************************************************
2 * Copyright (c) 2012 Ericsson
3 * Copyright (c) 2010, 2011 École Polytechnique de Montréal
4 * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
5 *
6 * All rights reserved. This program and the accompanying materials are
7 * made available under the terms of the Eclipse Public License v1.0 which
8 * accompanies this distribution, and is available at
9 * http://www.eclipse.org/legal/epl-v10.html
10 *
11 *******************************************************************************/
12
13package org.eclipse.linuxtools.internal.lttng2.kernel.core.stateprovider;
14
15import java.util.HashMap;
16import java.util.Vector;
17import java.util.concurrent.BlockingQueue;
18
ee8e0dc9
AM
19import org.eclipse.linuxtools.lttng2.kernel.core.trace.Attributes;
20import org.eclipse.linuxtools.lttng2.kernel.core.trace.LttngStrings;
efc403bb
AM
21import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfEvent;
22import org.eclipse.linuxtools.tmf.core.event.ITmfEventField;
6d08acca
AM
23import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
24import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;
25import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
18ab1d18 26import org.eclipse.linuxtools.tmf.core.statesystem.IStateSystemBuilder;
efc403bb 27import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue;
efc403bb
AM
28import org.eclipse.linuxtools.tmf.core.statevalue.TmfStateValue;
29
30/**
31 * This is the reference "state provider" for LTTng 2.0 kernel traces.
32 *
33 * @author alexmont
34 *
35 */
dc0f7bfe 36class CtfKernelHandler implements Runnable {
efc403bb
AM
37
38 private final BlockingQueue<CtfTmfEvent> inQueue;
d26f90fd 39 private IStateSystemBuilder ss;
efc403bb
AM
40
41 private CtfTmfEvent currentEvent;
42
43 /*
44 * We can keep handles to some Attribute Nodes so these don't need to be
45 * re-found (re-hashed Strings etc.) every new event
46 */
47 Vector<Integer> currentCPUNodes;
48 Vector<Integer> currentThreadNodes;
49
50 /* Event names HashMap. TODO: This can be discarded once we move to Java 7 */
51 private final HashMap<String, Integer> knownEventNames;
52
562bfcd2
AM
53 /* Common locations in the attribute tree */
54 private int cpusNode = -1;
55 private int threadsNode = -1;
06552532
AM
56 private int irqsNode = -1;
57 private int softIrqsNode = -1;
562bfcd2 58
dc0f7bfe 59 CtfKernelHandler(BlockingQueue<CtfTmfEvent> eventsQueue) {
efc403bb
AM
60 assert (eventsQueue != null);
61 this.inQueue = eventsQueue;
62 currentCPUNodes = new Vector<Integer>();
63 currentThreadNodes = new Vector<Integer>();
64
65 knownEventNames = fillEventNames();
66 }
67
d26f90fd 68 void assignStateSystem(IStateSystemBuilder targetSS) {
efc403bb
AM
69 this.ss = targetSS;
70 }
71
efc403bb
AM
72 @Override
73 public void run() {
74 if (ss == null) {
75 System.err.println("Cannot run event manager without assigning a target state system first!"); //$NON-NLS-1$
76 return;
77 }
78 CtfTmfEvent event;
562bfcd2 79 setupCommonLocations();
efc403bb
AM
80
81 try {
82 event = inQueue.take();
f13dfe18 83 while (event.getTimestampValue() != -1) {
efc403bb
AM
84 processEvent(event);
85 event = inQueue.take();
86 }
87 /* We've received the last event, clean up */
88 closeStateSystem();
89 return;
90 } catch (InterruptedException e) {
91 /* We've been interrupted abnormally */
92 System.out.println("Event handler interrupted!"); //$NON-NLS-1$
93 e.printStackTrace();
94 }
95 }
96
97 private void closeStateSystem() {
98 /* Close the History system, if there is one */
d26f90fd
AM
99 try {
100 ss.closeHistory(currentEvent.getTimestamp().getValue());
101 } catch (TimeRangeException e) {
102 /*
103 * Since we're using currentEvent.getTimestamp, this shouldn't
104 * cause any problem
105 */
106 e.printStackTrace();
efc403bb
AM
107 }
108 }
109
efc403bb
AM
110 private void processEvent(CtfTmfEvent event) {
111 currentEvent = event;
112 ITmfEventField content = event.getContent();
2130a4fb 113 String eventName = event.getEventName();
efc403bb
AM
114
115 long ts = event.getTimestamp().getValue();
116 int quark;
117 ITmfStateValue value;
118 Integer eventCpu = event.getCPU();
119 Integer currentCPUNode, currentThreadNode, tidNode;
120
121 /* Adjust the current nodes Vectors if we see a new CPU in an event */
122 if (eventCpu >= currentCPUNodes.size()) {
123 /* We need to add this node to the vector */
124 for (Integer i = currentCPUNodes.size(); i < eventCpu + 1; i++) {
562bfcd2 125 quark = ss.getQuarkRelativeAndAdd(cpusNode, i.toString());
efc403bb
AM
126 currentCPUNodes.add(quark);
127
562bfcd2 128 quark = ss.getQuarkRelativeAndAdd(threadsNode, Attributes.UNKNOWN);
efc403bb
AM
129 currentThreadNodes.add(quark);
130 }
131 }
132
133 currentCPUNode = currentCPUNodes.get(eventCpu);
134 currentThreadNode = currentThreadNodes.get(eventCpu);
135 assert (currentCPUNode != null);
136 assert (currentThreadNode != null);
137
138 try {
139 /*
140 * Feed event to the history system if it's known to cause a state
06552532 141 * transition.
efc403bb
AM
142 */
143 switch (getEventIndex(eventName)) {
144
145 case 1: // "exit_syscall":
a23c6969
AM
146 /* Fields: int64 ret */
147 {
efc403bb 148 /* Pop "syscall" from the Exec_mode_stack */
ee8e0dc9 149 quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.EXEC_MODE_STACK);
efc403bb
AM
150 try {
151 ss.popAttribute(ts, quark);
152 } catch (AttributeNotFoundException e1) {
153 /*
154 * meh, can happen if we're missing events, we'll just
155 * silently ignore it.
156 */
157 System.err.println(event.getTimestamp()
158 + " Popping empty attribute: " + e1.getMessage()); //$NON-NLS-1$
159 }
a23c6969 160 }
efc403bb
AM
161 break;
162
163 case 2: // "irq_handler_entry":
a23c6969
AM
164 /* Fields: int32 irq, string name */
165 {
ee8e0dc9 166 Integer irqId = ((Long) content.getField(LttngStrings.IRQ).getValue()).intValue();
efc403bb 167
06552532
AM
168 /* Mark this IRQ as active in the resource tree.
169 * The state value = the CPU on which this IRQ is sitting */
170 quark = ss.getQuarkRelativeAndAdd(irqsNode, irqId.toString());
171 value = TmfStateValue.newValueInt(event.getCPU());
172 ss.modifyAttribute(ts, value, quark);
efc403bb
AM
173
174 /* Change the status of the running process to interrupted */
ee8e0dc9 175 quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS);
06552532 176 value = TmfStateValue.newValueInt(Attributes.STATUS_INTERRUPTED);
efc403bb 177 ss.modifyAttribute(ts, value, quark);
a23c6969 178 }
efc403bb
AM
179 break;
180
181 case 3: // "irq_handler_exit":
a23c6969
AM
182 /* Fields: int32 irq, int32 ret */
183 {
06552532 184 Integer irqId = ((Long) content.getField(LttngStrings.IRQ).getValue()).intValue();
efc403bb 185
06552532
AM
186 /* Put this IRQ back to inactive in the resource tree */
187 quark = ss.getQuarkRelativeAndAdd(irqsNode, irqId.toString());
188 value = TmfStateValue.nullValue();
189 ss.modifyAttribute(ts, value, quark);
efc403bb 190
06552532
AM
191 /* Set the previous process back to running */
192 quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS);
193 value = TmfStateValue.newValueInt(Attributes.STATUS_RUN);
194 ss.modifyAttribute(ts, value, quark);
a23c6969 195 }
efc403bb
AM
196 break;
197
198 case 4: // "softirq_entry":
a23c6969 199 /* Fields: int32 vec */
06552532
AM
200 {
201 Integer softIrqId = ((Long) content.getField(LttngStrings.VEC).getValue()).intValue();
202
203 /* Mark this SoftIRQ as active in the resource tree.
204 * The state value = the CPU on which this SoftIRQ is processed */
205 quark = ss.getQuarkRelativeAndAdd(softIrqsNode, softIrqId.toString());
206 value = TmfStateValue.newValueInt(event.getCPU());
207 ss.modifyAttribute(ts, value, quark);
208
209 /* Change the status of the running process to interrupted */
210 quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS);
211 value = TmfStateValue.newValueInt(Attributes.STATUS_INTERRUPTED);
212 ss.modifyAttribute(ts, value, quark);
213 }
efc403bb
AM
214 break;
215
216 case 5: // "softirq_exit":
a23c6969 217 /* Fields: int32 vec */
06552532
AM
218 {
219 Integer softIrqId = ((Long) content.getField(LttngStrings.VEC).getValue()).intValue();
220
221 /* Put this SoftIRQ back to inactive (= -1) in the resource tree */
222 quark = ss.getQuarkRelativeAndAdd(softIrqsNode, softIrqId.toString());
223 value = TmfStateValue.nullValue();
224 ss.modifyAttribute(ts, value, quark);
225
226 /* Set the previous process back to running */
227 quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS);
228 value = TmfStateValue.newValueInt(Attributes.STATUS_RUN);
229 ss.modifyAttribute(ts, value, quark);
230 }
efc403bb
AM
231 break;
232
233 case 6: // "softirq_raise":
06552532
AM
234 /* Fields: int32 vec */
235 {
236 Integer softIrqId = ((Long) content.getField(LttngStrings.VEC).getValue()).intValue();
237
238 /* Mark this SoftIRQ as *raised* in the resource tree.
239 * State value = -2 */
240 quark = ss.getQuarkRelativeAndAdd(softIrqsNode, softIrqId.toString());
241 value = TmfStateValue.newValueInt(-2);
242 ss.modifyAttribute(ts, value, quark);
243 }
efc403bb
AM
244 break;
245
246 case 7: // "sched_switch":
a23c6969
AM
247 /*
248 * Fields: string prev_comm, int32 prev_tid, int32 prev_prio, int64 prev_state,
249 * string next_comm, int32 next_tid, int32 next_prio
250 */
251 {
efc403bb 252
ee8e0dc9
AM
253 Integer prevTid = ((Long) content.getField(LttngStrings.PREV_TID).getValue()).intValue();
254 Long prevState = (Long) content.getField(LttngStrings.PREV_STATE).getValue();
efc403bb 255
ee8e0dc9
AM
256 String nextProcessName = (String) content.getField(LttngStrings.NEXT_COMM).getValue();
257 Integer nextTid = ((Long) content.getField(LttngStrings.NEXT_TID).getValue()).intValue();
efc403bb 258
efc403bb 259 /* Update the currentThreadNodes pointer */
562bfcd2 260 Integer newCurrentThreadNode = ss.getQuarkRelativeAndAdd(threadsNode, nextTid.toString());
1ba498e5 261 initThreadNode(newCurrentThreadNode);
efc403bb
AM
262 currentThreadNodes.set(eventCpu, newCurrentThreadNode);
263
264 /* Set the status of the new scheduled process */
1ba498e5 265 quark = ss.getQuarkRelative(newCurrentThreadNode, Attributes.STATUS);
ee8e0dc9 266 value = TmfStateValue.newValueInt(Attributes.STATUS_RUN);
efc403bb
AM
267 ss.modifyAttribute(ts, value, quark);
268
269 /* Set the exec name of the new process */
1ba498e5 270 quark = ss.getQuarkRelative(newCurrentThreadNode, Attributes.EXEC_NAME);
efc403bb
AM
271 value = TmfStateValue.newValueString(nextProcessName);
272 ss.modifyAttribute(ts, value, quark);
273
274 /* Set the status of the process that got scheduled out */
562bfcd2 275 quark = ss.getQuarkRelativeAndAdd(threadsNode, prevTid.toString(), Attributes.STATUS);
efc403bb
AM
276 value = TmfStateValue.newValueInt(prevState.intValue());
277 ss.modifyAttribute(ts, value, quark);
278
279 /* Set the current scheduled process on the relevant CPU */
ee8e0dc9 280 quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.CURRENT_THREAD);
efc403bb
AM
281 value = TmfStateValue.newValueInt(nextTid);
282 ss.modifyAttribute(ts, value, quark);
a23c6969 283 }
efc403bb
AM
284 break;
285
286 case 8: // "sched_process_fork":
a23c6969
AM
287 /* Fields: string parent_comm, int32 parent_tid,
288 * string child_comm, int32 child_tid */
289 {
efc403bb
AM
290 // String parentProcessName = (String)
291 // event.getFieldValue("parent_comm");
634c67e6 292 String childProcessName;
ee8e0dc9 293 childProcessName = (String) content.getField(LttngStrings.CHILD_COMM).getValue();
efc403bb
AM
294 // assert ( parentProcessName.equals(childProcessName) );
295
ee8e0dc9
AM
296 Integer parentTid = ((Long) content.getField(LttngStrings.PARENT_TID).getValue()).intValue();
297 Integer childTid = ((Long) content.getField(LttngStrings.CHILD_TID).getValue()).intValue();
efc403bb 298
562bfcd2 299 tidNode = ss.getQuarkRelativeAndAdd(threadsNode, childTid.toString());
1ba498e5 300 initThreadNode(tidNode);
efc403bb
AM
301
302 /*
303 * Add the new process with its known TID, PPID, and initial
304 * Exec_name
305 */
1ba498e5 306 quark = ss.getQuarkRelative(tidNode, Attributes.PPID);
efc403bb
AM
307 value = TmfStateValue.newValueInt(parentTid);
308 ss.modifyAttribute(ts, value, quark);
309
310 /* Set the new process' exec_name */
1ba498e5 311 quark = ss.getQuarkRelative(tidNode, Attributes.EXEC_NAME);
efc403bb
AM
312 value = TmfStateValue.newValueString(childProcessName);
313 ss.modifyAttribute(ts, value, quark);
a23c6969 314 }
efc403bb
AM
315 break;
316
317 case 9: // "sched_process_exit":
a23c6969
AM
318 /* Fields: string comm, int32 tid, int32 prio */
319 {
ee8e0dc9
AM
320 String processName = (String) content.getField(LttngStrings.COMM).getValue();
321 Integer tid = ((Long) content.getField(LttngStrings.TID).getValue()).intValue();
efc403bb
AM
322
323 /* Update the process' name, if we don't have it */
562bfcd2 324 quark = ss.getQuarkRelativeAndAdd(threadsNode, tid.toString(), Attributes.EXEC_NAME);
efc403bb
AM
325 value = TmfStateValue.newValueString(processName);
326 ss.updateOngoingState(value, quark);
327
328 /*
329 * Remove the process and all its sub-attributes from the
330 * current state
331 */
562bfcd2 332 quark = ss.getQuarkRelativeAndAdd(threadsNode, tid.toString());
efc403bb 333 ss.removeAttribute(ts, quark);
a23c6969 334 }
efc403bb
AM
335 break;
336
337 case 10: // "sched_process_free":
a23c6969 338 /* Fields: string comm, int32 tid, int32 prio */
efc403bb
AM
339 break;
340
ee8e0dc9 341 // FIXME In CTF it's as "syscall_exec". Will have to be adapted.
efc403bb
AM
342 // case LTT_EVENT_EXEC:
343 // filename = new String((byte[]) event.getField(0));
344 //
345 // /* Change the Exec_name of the process */
346 // quark = ss.getQuarkRelativePath(true, currentThreadNode,
347 // "Exec_name");
348 // ss.modifyAttribute(ts, filename, quark);
349 // break;
350
351 default:
a23c6969
AM
352 /* Other event types not covered by the main switch */
353 {
ee8e0dc9
AM
354 if (eventName.startsWith(LttngStrings.SYSCALL_PREFIX)
355 || eventName.startsWith(LttngStrings.COMPAT_SYSCALL_PREFIX)) {
efc403bb
AM
356 /*
357 * This is a replacement for the old sys_enter event. Now
358 * syscall names are listed into the event type
359 */
360
361 /*
362 * Push the syscall name on the Exec_mode_stack of the
363 * relevant PID
364 */
ee8e0dc9 365 quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.EXEC_MODE_STACK);
efc403bb
AM
366 value = TmfStateValue.newValueString(eventName);
367 ss.pushAttribute(ts, value, quark);
368 }
a23c6969 369 }
efc403bb 370 break;
a23c6969 371 } // End of big switch
efc403bb
AM
372
373 /*
374 * Statistics
375 */
376
634c67e6 377 /* Number of events of each type, globally */
ee8e0dc9
AM
378// quark = ss.getQuarkAbsoluteAndAdd(Attributes.STATISTICS,
379// Attributes.EVENT_TYPES, eventName);
380// ss.incrementAttribute(ts, quark);
634c67e6 381
ee8e0dc9
AM
382 /* Number of events per CPU */
383// quark = ss.getQuarkRelativeAndAdd(currentCPUNode,
384// Attributes.STATISTICS, Attributes.EVENT_TYPES, eventName);
385// ss.incrementAttribute(ts, quark);
634c67e6 386
ee8e0dc9
AM
387 /* Number of events per process */
388// quark = ss.getQuarkRelativeAndAdd(currentThreadNode,
389// Attributes.STATISTICS, Attributes.EVENT_TYPES, eventName);
390// ss.incrementAttribute(ts, quark);
efc403bb 391
efc403bb
AM
392 } catch (AttributeNotFoundException ae) {
393 /*
394 * This would indicate a problem with the logic of the manager here,
395 * so it shouldn't happen.
396 */
397 ae.printStackTrace();
398
399 } catch (TimeRangeException tre) {
400 /*
401 * This would happen if the events in the trace aren't ordered
402 * chronologically, which should never be the case ...
403 */
ee8e0dc9
AM
404 System.err.println("TimeRangeExcpetion caught in the state system's event manager."); //$NON-NLS-1$
405 System.err.println("Are the events in the trace correctly ordered?"); //$NON-NLS-1$
efc403bb
AM
406 tre.printStackTrace();
407
408 } catch (StateValueTypeException sve) {
409 /*
410 * This would happen if we were trying to push/pop attributes not of
411 * type integer. Which, once again, should never happen.
412 */
413 sve.printStackTrace();
414 }
1ba498e5 415 }
efc403bb 416
1ba498e5
AM
417 /**
418 * Ensure we always have some sub-attributes available for every "TID" node.
419 */
420 private void initThreadNode(int currentThreadNode) {
421 ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.PPID);
422 ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.EXEC_NAME);
423 ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.EXEC_MODE_STACK);
424 ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS);
efc403bb
AM
425 }
426
562bfcd2
AM
427 private void setupCommonLocations() {
428 cpusNode = ss.getQuarkAbsoluteAndAdd(Attributes.CPUS);
429 threadsNode = ss.getQuarkAbsoluteAndAdd(Attributes.THREADS);
06552532
AM
430 irqsNode = ss.getQuarkAbsoluteAndAdd(Attributes.RESOURCES, Attributes.IRQS);
431 softIrqsNode = ss.getQuarkAbsoluteAndAdd(Attributes.RESOURCES, Attributes.SOFT_IRQS);
562bfcd2
AM
432 }
433
efc403bb
AM
434 private static HashMap<String, Integer> fillEventNames() {
435 /*
436 * TODO Replace with straight strings in the switch/case once we move to
437 * Java 7
438 */
efc403bb
AM
439 HashMap<String, Integer> map = new HashMap<String, Integer>();
440
ee8e0dc9
AM
441 map.put(LttngStrings.EXIT_SYSCALL, 1);
442 map.put(LttngStrings.IRQ_HANDLER_ENTRY, 2);
443 map.put(LttngStrings.IRQ_HANDLER_EXIT, 3);
444 map.put(LttngStrings.SOFTIRQ_ENTRY, 4);
445 map.put(LttngStrings.SOFTIRQ_EXIT, 5);
446 map.put(LttngStrings.SOFTIRQ_RAISE, 6);
447 map.put(LttngStrings.SCHED_SWITCH, 7);
448 map.put(LttngStrings.SCHED_PROCESS_FORK, 8);
449 map.put(LttngStrings.SCHED_PROCESS_EXIT, 9);
450 map.put(LttngStrings.SCHED_PROCESS_FREE, 10);
efc403bb
AM
451
452 return map;
453 }
454
455 private int getEventIndex(String eventName) {
456 Integer ret = knownEventNames.get(eventName);
457 return (ret != null) ? ret : -1;
458 }
efc403bb 459}
This page took 0.048122 seconds and 5 git commands to generate.