1 /*******************************************************************************
2 * Copyright (c) 2009 Ericsson
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
10 * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
11 *******************************************************************************/
12 package org
.eclipse
.linuxtools
.lttng
.state
.model
;
14 import java
.util
.HashMap
;
15 import java
.util
.Iterator
;
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
;
25 import org
.eclipse
.linuxtools
.lttng
.state
.resource
.ILttngStateContext
;
26 import org
.eclipse
.linuxtools
.tmf
.event
.TmfTimeRange
;
29 * <b><u>LttngTraceState</u></b>
37 public class LttngTraceState
implements Cloneable
{
38 // ========================================================================
40 // =======================================================================
42 private Long save_interval
= null;
44 private Long max_time_state_recomputed_in_seek
= null;
45 private boolean has_precomputed_states
= false;
47 private HashMap
<ProcessStateKey
, LttngProcessState
> processes
= new HashMap
<ProcessStateKey
, LttngProcessState
>();
50 private Map
<Long
, LttngProcessState
> running_process
= new HashMap
<Long
, LttngProcessState
>();
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
>();
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
>();
66 private int nb_events
= 0;
68 // reference to input data provider
69 ILttngStateContext fContext
= null;
72 // ========================================================================
74 // =======================================================================
77 StateStrings strings
= StateStrings
.getInstance();
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()]);
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()]);
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()]);
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()]);
104 // =======================================================================
106 // =======================================================================
108 public LttngTraceState
clone() {
109 LttngTraceState newState
= null;
112 newState
= (LttngTraceState
) super.clone();
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
;
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
;
124 newState
.max_time_state_recomputed_in_seek
= this.max_time_state_recomputed_in_seek
;
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
;
134 // This reference should never need to be updated, should it?
135 newState
.fContext
= this.fContext
;
137 // *** We need loop on each ArrayList and HashMap, as java implement
138 // nothing that's remotely near deep copying.
140 // In the future, implement something better here... serialization
141 // perhaps? Or copy the array chunk of memory in C?
143 Iterator
<Long
> iteratorL
= null;
144 Iterator
<ProcessStateKey
> iteratorP
= null;
146 ProcessStateKey processKey
= null;
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());
155 newState
.running_process
= new HashMap
<Long
, LttngProcessState
>();
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());
162 newState
.cpu_states
= new HashMap
<Long
, LTTngCPUState
>();
163 iteratorL
= this.cpu_states
.keySet().iterator();
164 while (iteratorL
.hasNext()) {
165 mapKey
= iteratorL
.next();
166 newState
.cpu_states
.put(mapKey
, this.cpu_states
.get(mapKey
)
170 newState
.irq_states
= new HashMap
<Long
, LttngIRQState
>();
171 iteratorL
= this.irq_states
.keySet().iterator();
172 while (iteratorL
.hasNext()) {
173 mapKey
= iteratorL
.next();
174 newState
.irq_states
.put(mapKey
, this.irq_states
.get(mapKey
)
178 newState
.soft_irq_states
= new HashMap
<Long
, LttngSoftIRQState
>();
179 iteratorL
= this.soft_irq_states
.keySet().iterator();
180 while (iteratorL
.hasNext()) {
181 mapKey
= iteratorL
.next();
182 newState
.soft_irq_states
.put(mapKey
, this.soft_irq_states
.get(
186 newState
.trap_states
= new HashMap
<Long
, LttngTrapState
>();
187 iteratorL
= this.trap_states
.keySet().iterator();
188 while (iteratorL
.hasNext()) {
189 mapKey
= iteratorL
.next();
190 newState
.trap_states
.put(mapKey
, this.trap_states
.get(mapKey
)
194 newState
.bdev_states
= new HashMap
<Long
, LttngBdevState
>();
195 iteratorL
= this.bdev_states
.keySet().iterator();
196 while (iteratorL
.hasNext()) {
197 mapKey
= iteratorL
.next();
198 newState
.bdev_states
.put(mapKey
, this.bdev_states
.get(mapKey
)
202 } catch (CloneNotSupportedException e
) {
203 System
.out
.println("Cloning failed with : " + e
.getMessage());
209 public void init(ILttngStateContext context
)
210 throws LttngStateException
{
211 if (context
== null) {
212 StringBuilder sb
= new StringBuilder(
213 "The input provider reference must not be null");
214 throw new LttngStateException(sb
.toString());
217 // Save the input data reference
221 traceId
= fContext
.getTraceId();
224 max_time_state_recomputed_in_seek
= 0L;
229 // Obtain the total num of available CPUs and initialize the map
230 // to the corresponding size
231 int numCpus
= fContext
.getNumberOfCpus();
232 for (Long i
= 0L; i
< numCpus
; i
++) {
233 cpu_states
.put(i
, new LTTngCPUState());
238 for (Long i
= 0L; i
< irq_names
.size(); i
++) {
239 irq_states
.put(i
, new LttngIRQState());
243 soft_irq_states
.clear();
244 for (Long i
= 0L; i
< soft_irq_names
.size(); i
++) {
245 soft_irq_states
.put(i
, new LttngSoftIRQState());
250 for (Long i
= 0L; i
< trap_names
.size(); i
++) {
251 trap_states
.put(i
, new LttngTrapState(0L));
260 TmfTimeRange timeWin
= fContext
.getTraceTimeWindow();
262 /* Put the per cpu running_process to beginning state : process 0. */
263 for (Long i
= 0L; i
< numCpus
; i
++) {
264 LttngProcessState process
= new LttngProcessState(timeWin
.getStartTime().getValue(), traceId
);
267 * We are not sure is it's a kernel thread or normal thread, put the
268 * bottom stack state to unknown
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
275 es
.setProc_status(ProcessStatus
.LTTV_STATE_UNNAMED
);
277 // Reduce from default to only one execution state in the stack
278 process
.popFromExecutionStack();
281 // no associated user trace yet
282 process
.setUserTrace("");
283 // processes.put(i, process);
284 running_process
.put(i
, process
);
286 LTTngCPUState cpuState
= cpu_states
.get(i
);
288 // Add the new process to the list
289 processes
.put(new ProcessStateKey(process
), process
);
293 for (Long key
: irq_states
.keySet()) {
294 LttngIRQState irqState
= irq_states
.get(key
);
295 irqState
.clearAndSetBaseToIrqStack(IRQMode
.LTTV_IRQ_UNKNOWN
);
298 // reset soft_irq_states
299 for (Long key
: soft_irq_states
.keySet()) {
300 LttngSoftIRQState softIrqState
= soft_irq_states
.get(key
);
301 softIrqState
.reset();
305 for (Long key
: trap_states
.keySet()) {
306 LttngTrapState trapState
= trap_states
.get(key
);
307 trapState
.setRunning(0L);
311 for (Long key
: bdev_states
.keySet()) {
312 LttngBdevState bdevState
= bdev_states
.get(key
);
313 bdevState
.clearBdevStack();
318 public Long
getSave_interval() {
319 return save_interval
;
322 public void setSave_interval(Long saveInterval
) {
323 save_interval
= saveInterval
;
327 * @return total number of CPUs registered as read from the Trace
329 public int getNumberOfCPUs() {
330 return fContext
.getNumberOfCpus();
334 * Provide access to input data not necessarily at Trace level
338 public ILttngStateContext
getContext() {
342 public Long
getMax_time_state_recomputed_in_seek() {
343 return max_time_state_recomputed_in_seek
;
346 public void setMax_time_state_recomputed_in_seek(
347 Long maxTimeStateRecomputedInSeek
) {
348 max_time_state_recomputed_in_seek
= maxTimeStateRecomputedInSeek
;
351 public boolean isHas_precomputed_states() {
352 return has_precomputed_states
;
355 public void setHas_precomputed_states(boolean hasPrecomputedStates
) {
356 has_precomputed_states
= hasPrecomputedStates
;
359 public Map
<Long
, LttngProcessState
> getRunning_process() {
360 return running_process
;
363 public Map
<Long
, String
> getSyscall_names() {
364 return syscall_names
;
367 public Map
<Long
, String
> getTrap_names() {
371 public Map
<Long
, String
> getIrq_names() {
375 public Map
<Long
, String
> getSoft_irq_names() {
376 return soft_irq_names
;
379 public Map
<Long
, LTTngCPUState
> getCpu_states() {
383 public Map
<Long
, LttngIRQState
> getIrq_states() {
387 public Map
<Long
, LttngSoftIRQState
> getSoft_irq_states() {
388 return soft_irq_states
;
391 public Map
<Long
, LttngTrapState
> getTrap_states() {
395 public Map
<Long
, LttngBdevState
> getBdev_states() {
399 public Map
<Long
, String
> getKprobe_table() {
404 * @return the traceId
406 public String
getTraceId() {
411 * Return an array of Processes
413 * @return LttngProcessState
415 public LttngProcessState
[] getProcesses() {
416 return processes
.values().toArray(new LttngProcessState
[processes
.size()]);
420 * Clear all process state items e.g. when a new experiment is selected
422 public void clearProcessState() {
427 * Interface to add process state.
429 * @param newProcessState
431 public void addProcessState(LttngProcessState newProcessState
) {
432 if (newProcessState
!= null) {
433 processes
.put( new ProcessStateKey(newProcessState
), newProcessState
);
438 * Interface to remove process state.
440 * @param oldProcessState
442 public void removeProcessState(LttngProcessState oldProcessState
) {
443 if (oldProcessState
!= null) {
444 processes
.remove(new ProcessStateKey(oldProcessState
));
449 * Search by keys (pid, cpuId and traceId)<p>
451 * A match is returned if the three arguments received match an entry
452 * Otherwise null is returned
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
458 * @return LttngProcessState
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
) );
470 class ProcessStateKey
{
471 private LttngProcessState valueRef
= null;
473 private Long pid
= null;
474 private Long cpuId
= null;
475 private String traceId
= null;
477 @SuppressWarnings("unused")
478 private ProcessStateKey() { }
480 public ProcessStateKey(LttngProcessState newRef
) {
484 public ProcessStateKey(Long newPid
, Long newCpuId
, String newTraceId
) {
487 traceId
= newTraceId
;
491 public boolean equals(Object obj
) {
492 boolean isSame
= false;
494 if ( obj
instanceof ProcessStateKey
) {
495 ProcessStateKey procKey
= (ProcessStateKey
) obj
;
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())) ) )
506 if ( (procKey
.getPid().equals(this.pid
) ) &&
507 (procKey
.getTraceId().equals(this.traceId
) ) &&
508 ( (procKey
.getCpuId().longValue() == 0L ) || (procKey
.getCpuId().equals(this.cpuId
)) ) )
516 .debug("ERROR : The received Key is not of the type ProcessStateKey! but "
517 + obj
.getClass().toString());
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();
534 public Long
getCpuId() {
535 if ( valueRef
!= null ) {
536 return valueRef
.getCpu();
543 public String
getTraceId() {
544 if ( valueRef
!= null ) {
545 return valueRef
.getTrace_id();
553 public int hashCode() {
554 return this.toString().hashCode();
559 public String
toString() {
560 if ( valueRef
!= null ) {
561 return (valueRef
.getPid().toString() + ":" + valueRef
.getCpu().toString() + ":" + valueRef
.getTrace_id().toString() );
564 return (pid
.toString() + ":" + cpuId
.toString() + ":" + traceId
.toString());