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