Commit | Line | Data |
---|---|---|
5d10d135 ASL |
1 | /******************************************************************************* |
2 | * Copyright (c) 2009 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 | * | |
9 | * Contributors: | |
10 | * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation | |
11 | *******************************************************************************/ | |
6c13869b | 12 | package org.eclipse.linuxtools.lttng.core.state.model; |
5d10d135 ASL |
13 | |
14 | import java.util.HashMap; | |
15 | import java.util.Iterator; | |
16 | import java.util.Map; | |
17 | ||
6c13869b FC |
18 | import org.eclipse.linuxtools.lttng.core.LttngConstants; |
19 | import org.eclipse.linuxtools.lttng.core.TraceDebug; | |
20 | import org.eclipse.linuxtools.lttng.core.state.LttngStateException; | |
21 | import org.eclipse.linuxtools.lttng.core.state.StateStrings; | |
22 | import org.eclipse.linuxtools.lttng.core.state.StateStrings.ExecutionMode; | |
23 | import org.eclipse.linuxtools.lttng.core.state.StateStrings.ExecutionSubMode; | |
24 | import org.eclipse.linuxtools.lttng.core.state.StateStrings.IRQMode; | |
25 | import org.eclipse.linuxtools.lttng.core.state.StateStrings.ProcessStatus; | |
26 | import org.eclipse.linuxtools.lttng.core.state.resource.ILttngStateContext; | |
27 | import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange; | |
5d10d135 ASL |
28 | |
29 | /** | |
30 | * <b><u>LttngTraceState</u></b> | |
31 | * <p> | |
32 | * | |
33 | */ | |
34 | /** | |
35 | * @author alvaro | |
36 | * | |
37 | */ | |
38 | public class LttngTraceState implements Cloneable { | |
39 | // ======================================================================== | |
40 | // Data | |
41 | // ======================================================================= | |
42 | ||
43 | private Long save_interval = null; | |
44 | ||
28b94d61 | 45 | private Long max_time_state_recomputed_in_seek = null; |
5d10d135 ASL |
46 | private boolean has_precomputed_states = false; |
47 | ||
2211df66 | 48 | private HashMap<ProcessStateKey, LttngProcessState> processes = new HashMap<ProcessStateKey, LttngProcessState>(); |
5d10d135 ASL |
49 | |
50 | // by cpu | |
51 | private Map<Long, LttngProcessState> running_process = new HashMap<Long, LttngProcessState>(); | |
52 | ||
53 | // Get state tables | |
54 | private Map<Long, LTTngCPUState> cpu_states = new HashMap<Long, LTTngCPUState>(); | |
55 | private Map<Long, LttngIRQState> irq_states = new HashMap<Long, LttngIRQState>(); | |
56 | private Map<Long, LttngSoftIRQState> soft_irq_states = new HashMap<Long, LttngSoftIRQState>(); | |
57 | private Map<Long, LttngTrapState> trap_states = new HashMap<Long, LttngTrapState>(); | |
58 | private Map<Long, LttngBdevState> bdev_states = new HashMap<Long, LttngBdevState>(); | |
59 | ||
60 | // Get name tables | |
61 | private Map<Long, String> syscall_names = new HashMap<Long, String>(); | |
62 | private Map<Long, String> kprobe_table = new HashMap<Long, String>(); | |
63 | private Map<Long, String> soft_irq_names = new HashMap<Long, String>(); | |
64 | private Map<Long, String> trap_names = new HashMap<Long, String>(); | |
65 | private Map<Long, String> irq_names = new HashMap<Long, String>(); | |
66 | ||
67 | private int nb_events = 0; | |
68 | ||
69 | // reference to input data provider | |
8827c197 | 70 | ILttngStateContext fContext = null; |
9c4eb5f7 | 71 | String traceId = ""; //$NON-NLS-1$ |
5d10d135 ASL |
72 | |
73 | // ======================================================================== | |
74 | // Constructor | |
75 | // ======================================================================= | |
76 | LttngTraceState() { | |
77 | // Get name tables | |
78 | StateStrings strings = StateStrings.getInstance(); | |
79 | ||
80 | // initialize sycall_names | |
81 | String[] ref_name_table = strings.getSyscallNames(); | |
82 | for (Long i = 0L; i < ref_name_table.length; i++) { | |
83 | syscall_names.put(i, ref_name_table[i.intValue()]); | |
84 | } | |
85 | ||
86 | // trap names | |
87 | ref_name_table = strings.getTrapNames(); | |
88 | for (Long i = 0L; i < ref_name_table.length; i++) { | |
89 | trap_names.put(i, ref_name_table[i.intValue()]); | |
90 | } | |
91 | ||
92 | // irq names | |
93 | ref_name_table = strings.getIrqNames(); | |
94 | for (Long i = 0L; i < ref_name_table.length; i++) { | |
95 | irq_names.put(i, ref_name_table[i.intValue()]); | |
96 | } | |
97 | ||
98 | // softirq names | |
99 | ref_name_table = strings.getSoftIrqNames(); | |
100 | for (Long i = 0L; i < ref_name_table.length; i++) { | |
101 | soft_irq_names.put(i, ref_name_table[i.intValue()]); | |
102 | } | |
103 | } | |
104 | ||
105 | // ======================================================================= | |
106 | // Methods | |
107 | // ======================================================================= | |
cc6eec3e | 108 | @Override |
5d10d135 ASL |
109 | public LttngTraceState clone() { |
110 | LttngTraceState newState = null; | |
111 | ||
112 | try { | |
113 | newState = (LttngTraceState) super.clone(); | |
114 | ||
115 | // *** IMPORTANT *** | |
116 | // Basic type in java are immutable! | |
117 | // Thus, using assignment ("=") on basic type is CORRECT, | |
118 | // but we should ALWAYS use "new" or "clone()" on "non basic" type | |
119 | newState.save_interval = this.save_interval; | |
120 | newState.traceId = this.traceId; | |
121 | ||
122 | // Basic value only need to be assigned while cloning | |
123 | newState.has_precomputed_states = this.has_precomputed_states; | |
124 | newState.nb_events = this.nb_events; | |
28b94d61 | 125 | newState.max_time_state_recomputed_in_seek = this.max_time_state_recomputed_in_seek; |
5d10d135 ASL |
126 | |
127 | // Clone should work correctly for all stack object that contain | |
128 | // basic java object (String, Long, etc...) | |
129 | newState.syscall_names = this.syscall_names; | |
130 | newState.kprobe_table = this.kprobe_table; | |
131 | newState.soft_irq_names = this.soft_irq_names; | |
132 | newState.trap_names = this.trap_names; | |
133 | newState.irq_names = this.irq_names; | |
134 | ||
135 | // This reference should never need to be updated, should it? | |
8827c197 | 136 | newState.fContext = this.fContext; |
5d10d135 ASL |
137 | |
138 | // *** We need loop on each ArrayList and HashMap, as java implement | |
139 | // nothing that's remotely near deep copying. | |
140 | // *** TODO *** | |
141 | // In the future, implement something better here... serialization | |
142 | // perhaps? Or copy the array chunk of memory in C? | |
2211df66 FC |
143 | |
144 | Iterator<Long> iteratorL = null; | |
145 | Iterator<ProcessStateKey> iteratorP = null; | |
58c60db3 | 146 | Long mapKey = null; |
2211df66 FC |
147 | ProcessStateKey processKey = null; |
148 | ||
149 | newState.processes = new HashMap<ProcessStateKey, LttngProcessState>(); | |
150 | iteratorP = this.processes.keySet().iterator(); | |
151 | while (iteratorP.hasNext()) { | |
152 | processKey = iteratorP.next(); | |
153 | newState.processes.put(processKey, this.processes.get(processKey).clone()); | |
154 | } | |
58c60db3 | 155 | |
5d10d135 | 156 | newState.running_process = new HashMap<Long, LttngProcessState>(); |
2211df66 FC |
157 | iteratorL = this.running_process.keySet().iterator(); |
158 | while (iteratorL.hasNext()) { | |
159 | mapKey = iteratorL.next(); | |
160 | newState.running_process.put(mapKey, this.running_process.get(mapKey).clone()); | |
5d10d135 ASL |
161 | } |
162 | ||
163 | newState.cpu_states = new HashMap<Long, LTTngCPUState>(); | |
2211df66 FC |
164 | iteratorL = this.cpu_states.keySet().iterator(); |
165 | while (iteratorL.hasNext()) { | |
166 | mapKey = iteratorL.next(); | |
5d10d135 ASL |
167 | newState.cpu_states.put(mapKey, this.cpu_states.get(mapKey) |
168 | .clone()); | |
169 | } | |
170 | ||
171 | newState.irq_states = new HashMap<Long, LttngIRQState>(); | |
2211df66 FC |
172 | iteratorL = this.irq_states.keySet().iterator(); |
173 | while (iteratorL.hasNext()) { | |
174 | mapKey = iteratorL.next(); | |
5d10d135 ASL |
175 | newState.irq_states.put(mapKey, this.irq_states.get(mapKey) |
176 | .clone()); | |
177 | } | |
178 | ||
179 | newState.soft_irq_states = new HashMap<Long, LttngSoftIRQState>(); | |
2211df66 FC |
180 | iteratorL = this.soft_irq_states.keySet().iterator(); |
181 | while (iteratorL.hasNext()) { | |
182 | mapKey = iteratorL.next(); | |
5d10d135 ASL |
183 | newState.soft_irq_states.put(mapKey, this.soft_irq_states.get( |
184 | mapKey).clone()); | |
185 | } | |
186 | ||
187 | newState.trap_states = new HashMap<Long, LttngTrapState>(); | |
2211df66 FC |
188 | iteratorL = this.trap_states.keySet().iterator(); |
189 | while (iteratorL.hasNext()) { | |
190 | mapKey = iteratorL.next(); | |
5d10d135 ASL |
191 | newState.trap_states.put(mapKey, this.trap_states.get(mapKey) |
192 | .clone()); | |
193 | } | |
194 | ||
195 | newState.bdev_states = new HashMap<Long, LttngBdevState>(); | |
2211df66 FC |
196 | iteratorL = this.bdev_states.keySet().iterator(); |
197 | while (iteratorL.hasNext()) { | |
198 | mapKey = iteratorL.next(); | |
5d10d135 ASL |
199 | newState.bdev_states.put(mapKey, this.bdev_states.get(mapKey) |
200 | .clone()); | |
201 | } | |
202 | ||
203 | } catch (CloneNotSupportedException e) { | |
9c4eb5f7 | 204 | System.out.println("Cloning failed with : " + e.getMessage()); //$NON-NLS-1$ |
5d10d135 ASL |
205 | } |
206 | ||
207 | return newState; | |
208 | } | |
209 | ||
8827c197 | 210 | public void init(ILttngStateContext context) |
5d10d135 | 211 | throws LttngStateException { |
8827c197 | 212 | if (context == null) { |
5d10d135 | 213 | StringBuilder sb = new StringBuilder( |
9c4eb5f7 | 214 | "The input provider reference must not be null"); //$NON-NLS-1$ |
5d10d135 ASL |
215 | throw new LttngStateException(sb.toString()); |
216 | } | |
217 | ||
218 | // Save the input data reference | |
8827c197 | 219 | fContext = context; |
5d10d135 ASL |
220 | |
221 | // Save traceid | |
8827c197 | 222 | traceId = fContext.getTraceId(); |
5d10d135 ASL |
223 | |
224 | // max time | |
28b94d61 | 225 | max_time_state_recomputed_in_seek = 0L; |
5d10d135 ASL |
226 | |
227 | // reset cpu_states | |
228 | cpu_states.clear(); | |
229 | ||
230 | // Obtain the total num of available CPUs and initialize the map | |
231 | // to the corresponding size | |
8827c197 | 232 | int numCpus = fContext.getNumberOfCpus(); |
5d10d135 ASL |
233 | for (Long i = 0L; i < numCpus; i++) { |
234 | cpu_states.put(i, new LTTngCPUState()); | |
235 | } | |
236 | ||
237 | // irq states | |
238 | irq_states.clear(); | |
239 | for (Long i = 0L; i < irq_names.size(); i++) { | |
240 | irq_states.put(i, new LttngIRQState()); | |
241 | } | |
242 | ||
243 | // soft irqs | |
244 | soft_irq_states.clear(); | |
245 | for (Long i = 0L; i < soft_irq_names.size(); i++) { | |
246 | soft_irq_states.put(i, new LttngSoftIRQState()); | |
247 | } | |
248 | ||
249 | // traps | |
250 | trap_states.clear(); | |
251 | for (Long i = 0L; i < trap_names.size(); i++) { | |
252 | trap_states.put(i, new LttngTrapState(0L)); | |
253 | } | |
254 | ||
255 | // bdev states | |
256 | bdev_states.clear(); | |
28b94d61 | 257 | |
5d10d135 ASL |
258 | processes.clear(); |
259 | ||
260 | nb_events = 0; | |
8827c197 | 261 | TmfTimeRange timeWin = fContext.getTraceTimeWindow(); |
5d10d135 ASL |
262 | |
263 | /* Put the per cpu running_process to beginning state : process 0. */ | |
264 | for (Long i = 0L; i < numCpus; i++) { | |
28b94d61 | 265 | LttngProcessState process = new LttngProcessState(timeWin.getStartTime().getValue(), traceId ); |
5d10d135 ASL |
266 | |
267 | /* | |
268 | * We are not sure is it's a kernel thread or normal thread, put the | |
269 | * bottom stack state to unknown | |
270 | */ | |
271 | LttngExecutionState es = process.getFirstElementFromExecutionStack(); | |
272 | process.setState(es); | |
273 | es.setExec_mode(ExecutionMode.LTTV_STATE_MODE_UNKNOWN); | |
b12f4544 FC |
274 | es.setExec_submode(ExecutionSubMode.LTTV_STATE_SUBMODE_NONE.getInName()); |
275 | // Note: For statistics performance improvement a integer representation of the submode is used | |
276 | // as well as a bit mask is applied! | |
277 | es.setExec_submode_id(StateStrings.ExecutionSubMode.LTTV_STATE_SUBMODE_NONE.ordinal() | LttngConstants.STATS_NONE_ID); | |
5d10d135 ASL |
278 | es.setProc_status(ProcessStatus.LTTV_STATE_UNNAMED); |
279 | ||
280 | // Reduce from default to only one execution state in the stack | |
281 | process.popFromExecutionStack(); | |
282 | ||
283 | process.setCpu(i); | |
284 | // no associated user trace yet | |
9c4eb5f7 | 285 | process.setUserTrace(""); //$NON-NLS-1$ |
5d10d135 ASL |
286 | // processes.put(i, process); |
287 | running_process.put(i, process); | |
288 | // reset cpu states | |
289 | LTTngCPUState cpuState = cpu_states.get(i); | |
290 | cpuState.reset(); | |
291 | // Add the new process to the list | |
2211df66 | 292 | processes.put(new ProcessStateKey(process), process); |
5d10d135 ASL |
293 | } |
294 | ||
295 | // reset irq_states | |
296 | for (Long key : irq_states.keySet()) { | |
297 | LttngIRQState irqState = irq_states.get(key); | |
298 | irqState.clearAndSetBaseToIrqStack(IRQMode.LTTV_IRQ_UNKNOWN); | |
299 | } | |
300 | ||
301 | // reset soft_irq_states | |
302 | for (Long key : soft_irq_states.keySet()) { | |
303 | LttngSoftIRQState softIrqState = soft_irq_states.get(key); | |
304 | softIrqState.reset(); | |
305 | } | |
306 | ||
307 | // reset trap_states | |
308 | for (Long key : trap_states.keySet()) { | |
309 | LttngTrapState trapState = trap_states.get(key); | |
310 | trapState.setRunning(0L); | |
311 | } | |
312 | ||
313 | // reset bdev_states | |
314 | for (Long key : bdev_states.keySet()) { | |
315 | LttngBdevState bdevState = bdev_states.get(key); | |
316 | bdevState.clearBdevStack(); | |
317 | } | |
318 | ||
319 | } | |
320 | ||
321 | public Long getSave_interval() { | |
322 | return save_interval; | |
323 | } | |
324 | ||
325 | public void setSave_interval(Long saveInterval) { | |
326 | save_interval = saveInterval; | |
327 | } | |
328 | ||
329 | /** | |
330 | * @return total number of CPUs registered as read from the Trace | |
331 | */ | |
332 | public int getNumberOfCPUs() { | |
8827c197 | 333 | return fContext.getNumberOfCpus(); |
5d10d135 ASL |
334 | } |
335 | ||
336 | /** | |
337 | * Provide access to input data not necessarily at Trace level | |
338 | * | |
339 | * @return | |
340 | */ | |
8827c197 FC |
341 | public ILttngStateContext getContext() { |
342 | return fContext; | |
5d10d135 ASL |
343 | } |
344 | ||
28b94d61 | 345 | public Long getMax_time_state_recomputed_in_seek() { |
5d10d135 ASL |
346 | return max_time_state_recomputed_in_seek; |
347 | } | |
348 | ||
349 | public void setMax_time_state_recomputed_in_seek( | |
28b94d61 | 350 | Long maxTimeStateRecomputedInSeek) { |
5d10d135 ASL |
351 | max_time_state_recomputed_in_seek = maxTimeStateRecomputedInSeek; |
352 | } | |
353 | ||
354 | public boolean isHas_precomputed_states() { | |
355 | return has_precomputed_states; | |
356 | } | |
357 | ||
358 | public void setHas_precomputed_states(boolean hasPrecomputedStates) { | |
359 | has_precomputed_states = hasPrecomputedStates; | |
360 | } | |
361 | ||
362 | public Map<Long, LttngProcessState> getRunning_process() { | |
363 | return running_process; | |
364 | } | |
365 | ||
366 | public Map<Long, String> getSyscall_names() { | |
367 | return syscall_names; | |
368 | } | |
369 | ||
370 | public Map<Long, String> getTrap_names() { | |
371 | return trap_names; | |
372 | } | |
373 | ||
374 | public Map<Long, String> getIrq_names() { | |
375 | return irq_names; | |
376 | } | |
377 | ||
378 | public Map<Long, String> getSoft_irq_names() { | |
379 | return soft_irq_names; | |
380 | } | |
381 | ||
382 | public Map<Long, LTTngCPUState> getCpu_states() { | |
383 | return cpu_states; | |
384 | } | |
385 | ||
386 | public Map<Long, LttngIRQState> getIrq_states() { | |
387 | return irq_states; | |
388 | } | |
389 | ||
390 | public Map<Long, LttngSoftIRQState> getSoft_irq_states() { | |
391 | return soft_irq_states; | |
392 | } | |
393 | ||
394 | public Map<Long, LttngTrapState> getTrap_states() { | |
395 | return trap_states; | |
396 | } | |
397 | ||
398 | public Map<Long, LttngBdevState> getBdev_states() { | |
399 | return bdev_states; | |
400 | } | |
401 | ||
402 | public Map<Long, String> getKprobe_table() { | |
403 | return kprobe_table; | |
404 | } | |
405 | ||
406 | /** | |
407 | * @return the traceId | |
408 | */ | |
409 | public String getTraceId() { | |
410 | return traceId; | |
411 | } | |
2211df66 FC |
412 | |
413 | /** | |
414 | * Return an array of Processes | |
415 | * | |
416 | * @return LttngProcessState | |
417 | */ | |
418 | public LttngProcessState[] getProcesses() { | |
419 | return processes.values().toArray(new LttngProcessState[processes.size()]); | |
420 | } | |
421 | ||
422 | /** | |
423 | * Clear all process state items e.g. when a new experiment is selected | |
424 | */ | |
425 | public void clearProcessState() { | |
426 | processes.clear(); | |
427 | } | |
428 | ||
429 | /** | |
430 | * Interface to add process state. | |
431 | * | |
432 | * @param newProcessState | |
433 | */ | |
434 | public void addProcessState(LttngProcessState newProcessState) { | |
435 | if (newProcessState != null) { | |
436 | processes.put( new ProcessStateKey(newProcessState), newProcessState); | |
437 | } | |
438 | } | |
439 | ||
440 | /** | |
441 | * Interface to remove process state. | |
442 | * | |
443 | * @param oldProcessState | |
444 | */ | |
445 | public void removeProcessState(LttngProcessState oldProcessState) { | |
446 | if (oldProcessState != null) { | |
447 | processes.remove(new ProcessStateKey(oldProcessState)); | |
448 | } | |
449 | } | |
450 | ||
451 | /** | |
452 | * Search by keys (pid, cpuId and traceId)<p> | |
453 | * | |
454 | * A match is returned if the three arguments received match an entry | |
455 | * Otherwise null is returned | |
456 | * | |
457 | * @param searchedPid The processId (Pid) we are looking for | |
458 | * @param searchedCpuId The cpu Id we are looking for | |
459 | * @param searchedTraceID The traceId (trace name?) we are looking for | |
460 | * | |
461 | * @return LttngProcessState | |
462 | */ | |
463 | public LttngProcessState findProcessState(Long searchedPid, Long searchedCpuId, String searchedTraceID) { | |
464 | // Get the TimeRangeEventProcess associated to a key we create here | |
465 | LttngProcessState foundProcess = processes.get( new ProcessStateKey(searchedPid, searchedCpuId, searchedTraceID) ); | |
466 | ||
467 | return foundProcess; | |
468 | } | |
2211df66 | 469 | } |
5d10d135 | 470 | |
b12f4544 FC |
471 | final class ProcessStateKey { |
472 | ||
473 | private long pid; | |
474 | private long cpuId; | |
475 | private String traceId; | |
2211df66 | 476 | |
2211df66 FC |
477 | |
478 | @SuppressWarnings("unused") | |
479 | private ProcessStateKey() { } | |
480 | ||
481 | public ProcessStateKey(LttngProcessState newRef) { | |
b12f4544 FC |
482 | pid = newRef.getPid().longValue(); |
483 | cpuId = newRef.getCpu().longValue(); | |
484 | traceId = newRef.getTrace_id(); | |
2211df66 FC |
485 | } |
486 | ||
487 | public ProcessStateKey(Long newPid, Long newCpuId, String newTraceId) { | |
488 | pid = newPid; | |
489 | cpuId = newCpuId; | |
490 | traceId = newTraceId; | |
491 | } | |
492 | ||
493 | @Override | |
494 | public boolean equals(Object obj) { | |
550d787e FC |
495 | |
496 | if (obj == null) return false; | |
ba1bc132 | 497 | boolean isSame = true; |
550d787e | 498 | |
2211df66 FC |
499 | if ( obj instanceof ProcessStateKey ) { |
500 | ProcessStateKey procKey = (ProcessStateKey) obj; | |
501 | ||
b12f4544 FC |
502 | if (procKey.pid != this.pid) { |
503 | return false; | |
504 | } | |
505 | ||
506 | if (!(procKey.traceId.equals(this.traceId))) { | |
507 | return false; | |
508 | } | |
509 | ||
510 | if (((procKey.pid == 0L) && (procKey.cpuId != this.cpuId))) { | |
511 | return false; | |
512 | } | |
513 | ||
ba1bc132 | 514 | } |
2211df66 FC |
515 | else { |
516 | TraceDebug | |
9c4eb5f7 | 517 | .debug("ERROR : The received Key is not of the type ProcessStateKey! but " //$NON-NLS-1$ |
2211df66 | 518 | + obj.getClass().toString()); |
550d787e | 519 | return false; |
2211df66 FC |
520 | } |
521 | ||
522 | return isSame; | |
523 | } | |
524 | ||
2211df66 FC |
525 | @Override |
526 | public int hashCode() { | |
b12f4544 | 527 | return (1 ^ (int)(pid ^ (pid >>> 32)) ^ traceId.hashCode()); |
2211df66 FC |
528 | } |
529 | ||
530 | ||
531 | @Override | |
3b38ea61 | 532 | @SuppressWarnings("nls") |
2211df66 | 533 | public String toString() { |
b12f4544 | 534 | return (String.valueOf(pid) + ":" + traceId); |
2211df66 | 535 | } |
5d10d135 | 536 | } |