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
.LttngConstants
;
19 import org
.eclipse
.linuxtools
.lttng
.TraceDebug
;
20 import org
.eclipse
.linuxtools
.lttng
.state
.LttngStateException
;
21 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
;
22 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.ExecutionMode
;
23 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.ExecutionSubMode
;
24 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.IRQMode
;
25 import org
.eclipse
.linuxtools
.lttng
.state
.StateStrings
.ProcessStatus
;
26 import org
.eclipse
.linuxtools
.lttng
.state
.resource
.ILttngStateContext
;
27 import org
.eclipse
.linuxtools
.tmf
.event
.TmfTimeRange
;
30 * <b><u>LttngTraceState</u></b>
38 public class LttngTraceState
implements Cloneable
{
39 // ========================================================================
41 // =======================================================================
43 private Long save_interval
= null;
45 private Long max_time_state_recomputed_in_seek
= null;
46 private boolean has_precomputed_states
= false;
48 private HashMap
<ProcessStateKey
, LttngProcessState
> processes
= new HashMap
<ProcessStateKey
, LttngProcessState
>();
51 private Map
<Long
, LttngProcessState
> running_process
= new HashMap
<Long
, LttngProcessState
>();
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
>();
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
>();
67 private int nb_events
= 0;
69 // reference to input data provider
70 ILttngStateContext fContext
= null;
71 String traceId
= ""; //$NON-NLS-1$
73 // ========================================================================
75 // =======================================================================
78 StateStrings strings
= StateStrings
.getInstance();
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()]);
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()]);
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()]);
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()]);
105 // =======================================================================
107 // =======================================================================
109 public LttngTraceState
clone() {
110 LttngTraceState newState
= null;
113 newState
= (LttngTraceState
) super.clone();
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
;
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
;
125 newState
.max_time_state_recomputed_in_seek
= this.max_time_state_recomputed_in_seek
;
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
;
135 // This reference should never need to be updated, should it?
136 newState
.fContext
= this.fContext
;
138 // *** We need loop on each ArrayList and HashMap, as java implement
139 // nothing that's remotely near deep copying.
141 // In the future, implement something better here... serialization
142 // perhaps? Or copy the array chunk of memory in C?
144 Iterator
<Long
> iteratorL
= null;
145 Iterator
<ProcessStateKey
> iteratorP
= null;
147 ProcessStateKey processKey
= null;
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());
156 newState
.running_process
= new HashMap
<Long
, LttngProcessState
>();
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());
163 newState
.cpu_states
= new HashMap
<Long
, LTTngCPUState
>();
164 iteratorL
= this.cpu_states
.keySet().iterator();
165 while (iteratorL
.hasNext()) {
166 mapKey
= iteratorL
.next();
167 newState
.cpu_states
.put(mapKey
, this.cpu_states
.get(mapKey
)
171 newState
.irq_states
= new HashMap
<Long
, LttngIRQState
>();
172 iteratorL
= this.irq_states
.keySet().iterator();
173 while (iteratorL
.hasNext()) {
174 mapKey
= iteratorL
.next();
175 newState
.irq_states
.put(mapKey
, this.irq_states
.get(mapKey
)
179 newState
.soft_irq_states
= new HashMap
<Long
, LttngSoftIRQState
>();
180 iteratorL
= this.soft_irq_states
.keySet().iterator();
181 while (iteratorL
.hasNext()) {
182 mapKey
= iteratorL
.next();
183 newState
.soft_irq_states
.put(mapKey
, this.soft_irq_states
.get(
187 newState
.trap_states
= new HashMap
<Long
, LttngTrapState
>();
188 iteratorL
= this.trap_states
.keySet().iterator();
189 while (iteratorL
.hasNext()) {
190 mapKey
= iteratorL
.next();
191 newState
.trap_states
.put(mapKey
, this.trap_states
.get(mapKey
)
195 newState
.bdev_states
= new HashMap
<Long
, LttngBdevState
>();
196 iteratorL
= this.bdev_states
.keySet().iterator();
197 while (iteratorL
.hasNext()) {
198 mapKey
= iteratorL
.next();
199 newState
.bdev_states
.put(mapKey
, this.bdev_states
.get(mapKey
)
203 } catch (CloneNotSupportedException e
) {
204 System
.out
.println("Cloning failed with : " + e
.getMessage()); //$NON-NLS-1$
210 public void init(ILttngStateContext context
)
211 throws LttngStateException
{
212 if (context
== null) {
213 StringBuilder sb
= new StringBuilder(
214 "The input provider reference must not be null"); //$NON-NLS-1$
215 throw new LttngStateException(sb
.toString());
218 // Save the input data reference
222 traceId
= fContext
.getTraceId();
225 max_time_state_recomputed_in_seek
= 0L;
230 // Obtain the total num of available CPUs and initialize the map
231 // to the corresponding size
232 int numCpus
= fContext
.getNumberOfCpus();
233 for (Long i
= 0L; i
< numCpus
; i
++) {
234 cpu_states
.put(i
, new LTTngCPUState());
239 for (Long i
= 0L; i
< irq_names
.size(); i
++) {
240 irq_states
.put(i
, new LttngIRQState());
244 soft_irq_states
.clear();
245 for (Long i
= 0L; i
< soft_irq_names
.size(); i
++) {
246 soft_irq_states
.put(i
, new LttngSoftIRQState());
251 for (Long i
= 0L; i
< trap_names
.size(); i
++) {
252 trap_states
.put(i
, new LttngTrapState(0L));
261 TmfTimeRange timeWin
= fContext
.getTraceTimeWindow();
263 /* Put the per cpu running_process to beginning state : process 0. */
264 for (Long i
= 0L; i
< numCpus
; i
++) {
265 LttngProcessState process
= new LttngProcessState(timeWin
.getStartTime().getValue(), traceId
);
268 * We are not sure is it's a kernel thread or normal thread, put the
269 * bottom stack state to unknown
271 LttngExecutionState es
= process
.getFirstElementFromExecutionStack();
272 process
.setState(es
);
273 es
.setExec_mode(ExecutionMode
.LTTV_STATE_MODE_UNKNOWN
);
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
);
278 es
.setProc_status(ProcessStatus
.LTTV_STATE_UNNAMED
);
280 // Reduce from default to only one execution state in the stack
281 process
.popFromExecutionStack();
284 // no associated user trace yet
285 process
.setUserTrace(""); //$NON-NLS-1$
286 // processes.put(i, process);
287 running_process
.put(i
, process
);
289 LTTngCPUState cpuState
= cpu_states
.get(i
);
291 // Add the new process to the list
292 processes
.put(new ProcessStateKey(process
), process
);
296 for (Long key
: irq_states
.keySet()) {
297 LttngIRQState irqState
= irq_states
.get(key
);
298 irqState
.clearAndSetBaseToIrqStack(IRQMode
.LTTV_IRQ_UNKNOWN
);
301 // reset soft_irq_states
302 for (Long key
: soft_irq_states
.keySet()) {
303 LttngSoftIRQState softIrqState
= soft_irq_states
.get(key
);
304 softIrqState
.reset();
308 for (Long key
: trap_states
.keySet()) {
309 LttngTrapState trapState
= trap_states
.get(key
);
310 trapState
.setRunning(0L);
314 for (Long key
: bdev_states
.keySet()) {
315 LttngBdevState bdevState
= bdev_states
.get(key
);
316 bdevState
.clearBdevStack();
321 public Long
getSave_interval() {
322 return save_interval
;
325 public void setSave_interval(Long saveInterval
) {
326 save_interval
= saveInterval
;
330 * @return total number of CPUs registered as read from the Trace
332 public int getNumberOfCPUs() {
333 return fContext
.getNumberOfCpus();
337 * Provide access to input data not necessarily at Trace level
341 public ILttngStateContext
getContext() {
345 public Long
getMax_time_state_recomputed_in_seek() {
346 return max_time_state_recomputed_in_seek
;
349 public void setMax_time_state_recomputed_in_seek(
350 Long maxTimeStateRecomputedInSeek
) {
351 max_time_state_recomputed_in_seek
= maxTimeStateRecomputedInSeek
;
354 public boolean isHas_precomputed_states() {
355 return has_precomputed_states
;
358 public void setHas_precomputed_states(boolean hasPrecomputedStates
) {
359 has_precomputed_states
= hasPrecomputedStates
;
362 public Map
<Long
, LttngProcessState
> getRunning_process() {
363 return running_process
;
366 public Map
<Long
, String
> getSyscall_names() {
367 return syscall_names
;
370 public Map
<Long
, String
> getTrap_names() {
374 public Map
<Long
, String
> getIrq_names() {
378 public Map
<Long
, String
> getSoft_irq_names() {
379 return soft_irq_names
;
382 public Map
<Long
, LTTngCPUState
> getCpu_states() {
386 public Map
<Long
, LttngIRQState
> getIrq_states() {
390 public Map
<Long
, LttngSoftIRQState
> getSoft_irq_states() {
391 return soft_irq_states
;
394 public Map
<Long
, LttngTrapState
> getTrap_states() {
398 public Map
<Long
, LttngBdevState
> getBdev_states() {
402 public Map
<Long
, String
> getKprobe_table() {
407 * @return the traceId
409 public String
getTraceId() {
414 * Return an array of Processes
416 * @return LttngProcessState
418 public LttngProcessState
[] getProcesses() {
419 return processes
.values().toArray(new LttngProcessState
[processes
.size()]);
423 * Clear all process state items e.g. when a new experiment is selected
425 public void clearProcessState() {
430 * Interface to add process state.
432 * @param newProcessState
434 public void addProcessState(LttngProcessState newProcessState
) {
435 if (newProcessState
!= null) {
436 processes
.put( new ProcessStateKey(newProcessState
), newProcessState
);
441 * Interface to remove process state.
443 * @param oldProcessState
445 public void removeProcessState(LttngProcessState oldProcessState
) {
446 if (oldProcessState
!= null) {
447 processes
.remove(new ProcessStateKey(oldProcessState
));
452 * Search by keys (pid, cpuId and traceId)<p>
454 * A match is returned if the three arguments received match an entry
455 * Otherwise null is returned
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
461 * @return LttngProcessState
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
) );
471 final class ProcessStateKey
{
475 private String traceId
;
478 @SuppressWarnings("unused")
479 private ProcessStateKey() { }
481 public ProcessStateKey(LttngProcessState newRef
) {
482 pid
= newRef
.getPid().longValue();
483 cpuId
= newRef
.getCpu().longValue();
484 traceId
= newRef
.getTrace_id();
487 public ProcessStateKey(Long newPid
, Long newCpuId
, String newTraceId
) {
490 traceId
= newTraceId
;
494 public boolean equals(Object obj
) {
496 if (obj
== null) return false;
497 boolean isSame
= true;
499 if ( obj
instanceof ProcessStateKey
) {
500 ProcessStateKey procKey
= (ProcessStateKey
) obj
;
502 if (procKey
.pid
!= this.pid
) {
506 if (!(procKey
.traceId
.equals(this.traceId
))) {
510 if (((procKey
.pid
== 0L) && (procKey
.cpuId
!= this.cpuId
))) {
517 .debug("ERROR : The received Key is not of the type ProcessStateKey! but " //$NON-NLS-1$
518 + obj
.getClass().toString());
526 public int hashCode() {
527 return (1 ^
(int)(pid ^
(pid
>>> 32)) ^ traceId
.hashCode());
532 @SuppressWarnings("nls")
533 public String
toString() {
534 return (String
.valueOf(pid
) + ":" + traceId
);