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
.tmf
.event
.TmfTimeRange
;
28 * <b><u>LttngTraceState</u></b>
36 public class LttngTraceState
implements Cloneable
{
37 // ========================================================================
39 // =======================================================================
41 private Long save_interval
= null;
43 private Long max_time_state_recomputed_in_seek
= null;
44 private boolean has_precomputed_states
= false;
46 private HashMap
<ProcessStateKey
, LttngProcessState
> processes
= new HashMap
<ProcessStateKey
, LttngProcessState
>();
49 private Map
<Long
, LttngProcessState
> running_process
= new HashMap
<Long
, LttngProcessState
>();
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
>();
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
>();
65 private int nb_events
= 0;
67 // reference to input data provider
68 ILttngStateInputRef inputDataRef
= null;
71 // ========================================================================
73 // =======================================================================
76 StateStrings strings
= StateStrings
.getInstance();
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()]);
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()]);
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()]);
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()]);
103 // =======================================================================
105 // =======================================================================
107 public LttngTraceState
clone() {
108 LttngTraceState newState
= null;
111 newState
= (LttngTraceState
) super.clone();
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
;
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
;
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
;
133 // This reference should never need to be updated, should it?
134 newState
.inputDataRef
= this.inputDataRef
;
136 // *** We need loop on each ArrayList and HashMap, as java implement
137 // nothing that's remotely near deep copying.
139 // In the future, implement something better here... serialization
140 // perhaps? Or copy the array chunk of memory in C?
142 Iterator
<Long
> iteratorL
= null;
143 Iterator
<ProcessStateKey
> iteratorP
= null;
145 ProcessStateKey processKey
= null;
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());
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());
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
)
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
)
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(
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
)
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
)
201 } catch (CloneNotSupportedException e
) {
202 System
.out
.println("Cloning failed with : " + e
.getMessage());
208 public void init(ILttngStateInputRef inputReference
)
209 throws LttngStateException
{
210 if (inputReference
== null) {
211 StringBuilder sb
= new StringBuilder(
212 "The input provider reference must not be null");
213 throw new LttngStateException(sb
.toString());
216 // Save the input data reference
217 inputDataRef
= inputReference
;
220 traceId
= inputDataRef
.getTraceId();
223 max_time_state_recomputed_in_seek
= 0L;
228 // Obtain the total num of available CPUs and initialize the map
229 // to the corresponding size
230 int numCpus
= inputDataRef
.getNumberOfCpus();
231 for (Long i
= 0L; i
< numCpus
; i
++) {
232 cpu_states
.put(i
, new LTTngCPUState());
237 for (Long i
= 0L; i
< irq_names
.size(); i
++) {
238 irq_states
.put(i
, new LttngIRQState());
242 soft_irq_states
.clear();
243 for (Long i
= 0L; i
< soft_irq_names
.size(); i
++) {
244 soft_irq_states
.put(i
, new LttngSoftIRQState());
249 for (Long i
= 0L; i
< trap_names
.size(); i
++) {
250 trap_states
.put(i
, new LttngTrapState(0L));
259 TmfTimeRange timeWin
= inputDataRef
.getTraceTimeWindow();
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
);
266 * We are not sure is it's a kernel thread or normal thread, put the
267 * bottom stack state to unknown
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
274 es
.setProc_status(ProcessStatus
.LTTV_STATE_UNNAMED
);
276 // Reduce from default to only one execution state in the stack
277 process
.popFromExecutionStack();
280 // no associated user trace yet
281 process
.setUserTrace("");
282 // processes.put(i, process);
283 running_process
.put(i
, process
);
285 LTTngCPUState cpuState
= cpu_states
.get(i
);
287 // Add the new process to the list
288 processes
.put(new ProcessStateKey(process
), process
);
292 for (Long key
: irq_states
.keySet()) {
293 LttngIRQState irqState
= irq_states
.get(key
);
294 irqState
.clearAndSetBaseToIrqStack(IRQMode
.LTTV_IRQ_UNKNOWN
);
297 // reset soft_irq_states
298 for (Long key
: soft_irq_states
.keySet()) {
299 LttngSoftIRQState softIrqState
= soft_irq_states
.get(key
);
300 softIrqState
.reset();
304 for (Long key
: trap_states
.keySet()) {
305 LttngTrapState trapState
= trap_states
.get(key
);
306 trapState
.setRunning(0L);
310 for (Long key
: bdev_states
.keySet()) {
311 LttngBdevState bdevState
= bdev_states
.get(key
);
312 bdevState
.clearBdevStack();
317 public Long
getSave_interval() {
318 return save_interval
;
321 public void setSave_interval(Long saveInterval
) {
322 save_interval
= saveInterval
;
326 * @return total number of CPUs registered as read from the Trace
328 public int getNumberOfCPUs() {
329 return inputDataRef
.getNumberOfCpus();
333 * Provide access to input data not necessarily at Trace level
337 public ILttngStateInputRef
getInputDataRef() {
341 public Long
getMax_time_state_recomputed_in_seek() {
342 return max_time_state_recomputed_in_seek
;
345 public void setMax_time_state_recomputed_in_seek(
346 Long maxTimeStateRecomputedInSeek
) {
347 max_time_state_recomputed_in_seek
= maxTimeStateRecomputedInSeek
;
350 public boolean isHas_precomputed_states() {
351 return has_precomputed_states
;
354 public void setHas_precomputed_states(boolean hasPrecomputedStates
) {
355 has_precomputed_states
= hasPrecomputedStates
;
358 public Map
<Long
, LttngProcessState
> getRunning_process() {
359 return running_process
;
362 public Map
<Long
, String
> getSyscall_names() {
363 return syscall_names
;
366 public Map
<Long
, String
> getTrap_names() {
370 public Map
<Long
, String
> getIrq_names() {
374 public Map
<Long
, String
> getSoft_irq_names() {
375 return soft_irq_names
;
378 public Map
<Long
, LTTngCPUState
> getCpu_states() {
382 public Map
<Long
, LttngIRQState
> getIrq_states() {
386 public Map
<Long
, LttngSoftIRQState
> getSoft_irq_states() {
387 return soft_irq_states
;
390 public Map
<Long
, LttngTrapState
> getTrap_states() {
394 public Map
<Long
, LttngBdevState
> getBdev_states() {
398 public Map
<Long
, String
> getKprobe_table() {
403 * @return the traceId
405 public String
getTraceId() {
410 * Return an array of Processes
412 * @return LttngProcessState
414 public LttngProcessState
[] getProcesses() {
415 return processes
.values().toArray(new LttngProcessState
[processes
.size()]);
419 * Clear all process state items e.g. when a new experiment is selected
421 public void clearProcessState() {
426 * Interface to add process state.
428 * @param newProcessState
430 public void addProcessState(LttngProcessState newProcessState
) {
431 if (newProcessState
!= null) {
432 processes
.put( new ProcessStateKey(newProcessState
), newProcessState
);
437 * Interface to remove process state.
439 * @param oldProcessState
441 public void removeProcessState(LttngProcessState oldProcessState
) {
442 if (oldProcessState
!= null) {
443 processes
.remove(new ProcessStateKey(oldProcessState
));
448 * Search by keys (pid, cpuId and traceId)<p>
450 * A match is returned if the three arguments received match an entry
451 * Otherwise null is returned
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
457 * @return LttngProcessState
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
) );
469 class ProcessStateKey
{
470 private LttngProcessState valueRef
= null;
472 private Long pid
= null;
473 private Long cpuId
= null;
474 private String traceId
= null;
476 @SuppressWarnings("unused")
477 private ProcessStateKey() { }
479 public ProcessStateKey(LttngProcessState newRef
) {
483 public ProcessStateKey(Long newPid
, Long newCpuId
, String newTraceId
) {
486 traceId
= newTraceId
;
490 public boolean equals(Object obj
) {
491 boolean isSame
= false;
493 if ( obj
instanceof ProcessStateKey
) {
494 ProcessStateKey procKey
= (ProcessStateKey
) obj
;
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())) ) )
505 if ( (procKey
.getPid().equals(this.pid
) ) &&
506 (procKey
.getTraceId().equals(this.traceId
) ) &&
507 ( (procKey
.getCpuId().longValue() == 0L ) || (procKey
.getCpuId().equals(this.cpuId
)) ) )
515 .debug("ERROR : The received Key is not of the type ProcessStateKey! but "
516 + obj
.getClass().toString());
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();
533 public Long
getCpuId() {
534 if ( valueRef
!= null ) {
535 return valueRef
.getCpu();
542 public String
getTraceId() {
543 if ( valueRef
!= null ) {
544 return valueRef
.getTrace_id();
552 public int hashCode() {
553 return this.toString().hashCode();
558 public String
toString() {
559 if ( valueRef
!= null ) {
560 return (valueRef
.getPid().toString() + ":" + valueRef
.getCpu().toString() + ":" + valueRef
.getTrace_id().toString() );
563 return (pid
.toString() + ":" + cpuId
.toString() + ":" + traceId
.toString());