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