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.Stack; | |
15 | ||
16 | import org.eclipse.linuxtools.lttng.TraceDebug; | |
17 | import org.eclipse.linuxtools.lttng.state.StateStrings; | |
18 | import org.eclipse.linuxtools.lttng.state.StateStrings.ExecutionMode; | |
19 | import org.eclipse.linuxtools.lttng.state.StateStrings.ExecutionSubMode; | |
20 | import org.eclipse.linuxtools.lttng.state.StateStrings.ProcessStatus; | |
58c60db3 | 21 | import org.eclipse.linuxtools.tmf.event.TmfTimestamp; |
5d10d135 ASL |
22 | |
23 | /** | |
24 | * <b>LttngProcessState</b> | |
25 | * | |
26 | * @author alvaro | |
27 | * | |
28 | */ | |
29 | public class LttngProcessState implements Cloneable { | |
30 | // ======================================================================== | |
31 | // Data | |
32 | // ======================================================================= | |
33 | private Long cpu = null; | |
34 | private Long pid = null; | |
35 | private Long tgid = null; | |
36 | private String name = null; | |
58c60db3 | 37 | private TmfTimestamp creation_time = null; |
5d10d135 ASL |
38 | private String brand = null; |
39 | private StateStrings.ProcessType type = null; | |
40 | private Long current_function = null; | |
41 | private Long ppid = null; | |
58c60db3 | 42 | private TmfTimestamp insertion_time = null; |
5d10d135 ASL |
43 | private String pid_time = null; |
44 | private Long free_events = null; | |
45 | private LttngExecutionState state = null; // top of stack | |
46 | private Stack<LttngExecutionState> execution_stack = new Stack<LttngExecutionState>(); | |
47 | private Stack<Long> user_stack = new Stack<Long>(); // user space | |
48 | ||
49 | private String userTrace = null; /* Associated file trace */ | |
50 | private Long target_pid = null; /* target PID of the current event. */ | |
58c60db3 | 51 | |
5d10d135 ASL |
52 | // ======================================================================== |
53 | // Constructor | |
54 | // ======================================================================= | |
58c60db3 | 55 | public LttngProcessState(TmfTimestamp startTime) { |
5d10d135 ASL |
56 | this.cpu = 0L; |
57 | this.pid = 0L; | |
58 | this.tgid = 0L; | |
59 | this.name = StateStrings.ProcessStatus.LTTV_STATE_UNNAMED.getInName(); | |
60 | this.insertion_time = startTime; | |
5d10d135 ASL |
61 | init(); |
62 | } | |
63 | ||
64 | public LttngProcessState(Long cpu, Long pid, Long tgid, | |
58c60db3 | 65 | String name, TmfTimestamp startTime) { |
5d10d135 ASL |
66 | this.cpu = cpu; |
67 | this.pid = pid; | |
68 | this.tgid = tgid; | |
69 | this.name = name; | |
70 | this.insertion_time = startTime; | |
5d10d135 ASL |
71 | init(); |
72 | } | |
73 | ||
74 | // ======================================================================== | |
75 | // Methods | |
76 | // ======================================================================= | |
77 | private void init() { | |
78 | this.brand = StateStrings.LTTV_STATE_UNBRANDED; | |
79 | this.type = StateStrings.ProcessType.LTTV_STATE_USER_THREAD; | |
80 | this.current_function = 0L; | |
81 | this.ppid = 0L; | |
58c60db3 FC |
82 | // creation time defined when parent pid is known |
83 | // calling the setCreation_time method adjust the pid_time string | |
84 | setCreation_time(new TmfTimestamp()); | |
5d10d135 ASL |
85 | this.free_events = 0L; |
86 | ||
63eecb47 | 87 | // Initialise stack |
5d10d135 | 88 | LttngExecutionState es = new LttngExecutionState(); |
63eecb47 | 89 | es.setExec_mode(ExecutionMode.LTTV_STATE_USER_MODE); |
5d10d135 ASL |
90 | es.setExec_submode(ExecutionSubMode.LTTV_STATE_SUBMODE_NONE.getInName()); |
91 | es.setEntry_Time(this.insertion_time); | |
92 | es.setChange_Time(this.insertion_time); | |
93 | es.setCum_cpu_time(0L); | |
94 | es.setProc_status(ProcessStatus.LTTV_STATE_RUN); | |
95 | this.execution_stack.push(es); | |
63eecb47 FC |
96 | |
97 | //This second entry is needed when processes are created via a Fork event. | |
98 | es = new LttngExecutionState(); | |
99 | es.setExec_mode(ExecutionMode.LTTV_STATE_SYSCALL); | |
100 | es | |
101 | .setExec_submode(ExecutionSubMode.LTTV_STATE_SUBMODE_NONE | |
102 | .getInName()); | |
103 | es.setEntry_Time(this.insertion_time); | |
104 | es.setChange_Time(this.insertion_time); | |
105 | es.setCum_cpu_time(0L); | |
106 | es.setProc_status(ProcessStatus.LTTV_STATE_WAIT_FORK); | |
107 | this.execution_stack.push(es); | |
5d10d135 ASL |
108 | |
109 | // point state to the top of the stack | |
110 | this.state = es; | |
111 | } | |
112 | ||
cc6eec3e | 113 | @Override |
5d10d135 ASL |
114 | @SuppressWarnings("unchecked") |
115 | public LttngProcessState clone() { | |
116 | LttngProcessState newState = null; | |
117 | ||
118 | try { | |
119 | newState = (LttngProcessState)super.clone(); | |
120 | ||
121 | // *** IMPORTANT *** | |
122 | // Basic type in java are immutable! | |
123 | // Thus, using assignment ("=") on basic type is CORRECT, | |
124 | // but we should ALWAYS use "new" or "clone()" on "non basic" type | |
125 | newState.cpu = this.cpu; | |
126 | newState.pid = this.pid; | |
127 | newState.tgid = this.tgid; | |
128 | newState.name = this.name; | |
129 | newState.brand = this.brand; | |
130 | newState.type = this.type; | |
131 | newState.current_function = this.current_function; | |
132 | newState.ppid = this.ppid; | |
133 | newState.pid_time= this.pid_time; | |
134 | newState.free_events = this.free_events; | |
135 | newState.userTrace = this.userTrace; | |
136 | newState.target_pid = this.target_pid; | |
58c60db3 FC |
137 | |
138 | // No clonable implemented in TMF, we will use copy constructor | |
139 | // NOTE : we GOT to check for null to avoid crashing on null pointer here! | |
140 | if ( this.creation_time != null ) { | |
141 | newState.creation_time = new TmfTimestamp(this.creation_time); | |
142 | } | |
143 | ||
144 | if ( this.creation_time != null ) { | |
145 | newState.insertion_time = new TmfTimestamp(this.insertion_time); | |
146 | } | |
5d10d135 ASL |
147 | |
148 | // Call clone on our own object is safe as Long it implements Clonable | |
149 | newState.state = (LttngExecutionState)this.state.clone(); | |
150 | ||
151 | // Clone should work correctly for all stack object that contain basic java object (String, Long, etc...) | |
152 | newState.user_stack = (Stack<Long>)this.user_stack.clone(); | |
153 | ||
154 | ||
155 | // This is worst case : Stack that contain user defined object. We have to unstack it and clone every object in a new stack! | |
156 | // Why does java does not call clone() for every object in the stack it clone? It would probably be too useful... | |
157 | newState.execution_stack = new Stack<LttngExecutionState>(); | |
158 | ||
159 | // Work stack we will use to "pop" item | |
160 | Stack<LttngExecutionState> tmpStack = new Stack<LttngExecutionState>(); | |
161 | ||
162 | // First, we pop every ExecutionState, and insert a CLONED copy into our new cloned stack | |
163 | while ( this.execution_stack.empty() == false ) { | |
164 | // Save a copy of the original reference | |
165 | tmpStack.push(this.execution_stack.peek()); | |
166 | // Push a CLONED copy into the new stack while poping it from the original stack | |
167 | newState.execution_stack.push( this.execution_stack.pop().clone() ); | |
168 | } | |
169 | ||
170 | // Second, we reinsert back our content into the original stack | |
171 | while ( tmpStack.empty() == false ) { | |
172 | // Pop the cloned copy and push it back into the original stack | |
173 | this.execution_stack.push( tmpStack.pop() ); | |
174 | } | |
175 | } | |
176 | catch ( CloneNotSupportedException e ) { | |
177 | System.out.println("Cloning failed with : " + e.getMessage() ); | |
178 | } | |
179 | ||
180 | return newState; | |
181 | } | |
182 | ||
183 | ||
184 | // ======================================================================== | |
185 | // Methods | |
186 | // ======================================================================= | |
187 | /** | |
188 | * @return the pid | |
189 | */ | |
190 | public Long getPid() { | |
191 | return pid; | |
192 | } | |
193 | ||
194 | /** | |
195 | * @param pid | |
196 | * the pid to set | |
197 | */ | |
198 | public void setPid(Long pid) { | |
199 | this.pid = pid; | |
200 | } | |
201 | ||
202 | /** | |
203 | * @return the tgid | |
204 | */ | |
205 | public Long getTgid() { | |
206 | return tgid; | |
207 | } | |
208 | ||
209 | /** | |
210 | * @param tgid | |
211 | * the tgid to set | |
212 | */ | |
213 | public void setTgid(Long tgid) { | |
214 | this.tgid = tgid; | |
215 | } | |
216 | ||
217 | /** | |
218 | * @return the ppid | |
219 | */ | |
220 | public Long getPpid() { | |
221 | return ppid; | |
222 | } | |
223 | ||
224 | /** | |
225 | * @param ppid | |
226 | * the ppid to set | |
227 | */ | |
228 | public void setPpid(Long ppid) { | |
229 | this.ppid = ppid; | |
230 | } | |
231 | ||
232 | /** | |
233 | * <p> | |
234 | * When the parent pid is known, the creation time is also known and | |
235 | * requires update | |
236 | * </p> | |
237 | * | |
238 | * @param ppid | |
239 | * the ppid to set | |
240 | */ | |
58c60db3 | 241 | public void setPpid(Long ppid, TmfTimestamp creationTime) { |
5d10d135 ASL |
242 | if (ppid != null) { |
243 | this.ppid = ppid; | |
244 | } | |
245 | ||
246 | if (creationTime != null) { | |
247 | setCreation_time(creationTime); | |
248 | } | |
249 | } | |
250 | ||
251 | /** | |
252 | * @return the creation_time | |
253 | */ | |
58c60db3 | 254 | public TmfTimestamp getCreation_time() { |
5d10d135 ASL |
255 | return creation_time; |
256 | } | |
257 | ||
258 | /** | |
259 | * @param creationTime | |
260 | * the creation_time to set | |
261 | */ | |
58c60db3 | 262 | public void setCreation_time(TmfTimestamp creationTime) { |
5d10d135 ASL |
263 | if ( (creationTime != null) && (pid != null) ) { |
264 | creation_time = creationTime; | |
265 | StringBuilder sb = new StringBuilder(this.pid.toString() + "-" | |
266 | + creationTime.toString()); | |
267 | this.pid_time = sb.toString(); | |
268 | } | |
269 | } | |
270 | ||
271 | /** | |
272 | * @return the insertion_time | |
273 | */ | |
58c60db3 | 274 | public TmfTimestamp getInsertion_time() { |
5d10d135 ASL |
275 | return insertion_time; |
276 | } | |
277 | ||
278 | /** | |
279 | * @param insertionTime | |
280 | * the insertion_time to set | |
281 | */ | |
58c60db3 | 282 | public void setInsertion_time(TmfTimestamp insertionTime) { |
5d10d135 ASL |
283 | insertion_time = insertionTime; |
284 | } | |
285 | ||
286 | /** | |
287 | * @return the name | |
288 | */ | |
289 | public String getName() { | |
290 | return name; | |
291 | } | |
292 | ||
293 | /** | |
294 | * @param name | |
295 | * the name to set | |
296 | */ | |
297 | public void setName(String name) { | |
298 | this.name = name; | |
299 | } | |
300 | ||
301 | /** | |
302 | * @return the brand | |
303 | */ | |
304 | public String getBrand() { | |
305 | return brand; | |
306 | } | |
307 | ||
308 | /** | |
309 | * @param brand | |
310 | * the brand to set | |
311 | */ | |
312 | public void setBrand(String brand) { | |
313 | this.brand = brand; | |
314 | } | |
315 | ||
316 | /** | |
317 | * @return the prid_time | |
318 | */ | |
319 | public String getPid_time() { | |
320 | return pid_time; | |
321 | } | |
322 | ||
323 | /** | |
324 | * @return the cpu | |
325 | */ | |
326 | public Long getCpu() { | |
327 | return cpu; | |
328 | } | |
329 | ||
330 | /** | |
331 | * @param cpu | |
332 | * the cpu to set | |
333 | */ | |
334 | public void setCpu(Long cpu) { | |
335 | this.cpu = cpu; | |
336 | } | |
337 | ||
338 | /** | |
339 | * @return the current_function | |
340 | */ | |
341 | public Long getCurrent_function() { | |
342 | return current_function; | |
343 | } | |
344 | ||
345 | /** | |
346 | * @param currentFunction | |
347 | * the current_function to set | |
348 | */ | |
349 | public void setCurrent_function(Long currentFunction) { | |
350 | current_function = currentFunction; | |
351 | } | |
352 | ||
353 | /** | |
354 | * @return the target_pid | |
355 | */ | |
356 | public Long getTarget_pid() { | |
357 | return target_pid; | |
358 | } | |
359 | ||
360 | /** | |
361 | * @param targetPid | |
362 | * the target_pid to set | |
363 | */ | |
364 | public void setTarget_pid(Long targetPid) { | |
365 | target_pid = targetPid; | |
366 | } | |
5d10d135 | 367 | |
5d10d135 ASL |
368 | /** |
369 | * @return the free_events | |
370 | */ | |
371 | public Long getFree_events() { | |
372 | return free_events; | |
373 | } | |
374 | ||
375 | /** | |
376 | * @param freeEvents | |
377 | * the free_events to set | |
378 | */ | |
379 | public void setFree_events(Long freeEvents) { | |
380 | free_events = freeEvents; | |
381 | } | |
382 | ||
383 | /** | |
384 | * increment the nuber of free events | |
385 | */ | |
386 | public void incrementFree_events() { | |
387 | ++free_events; | |
388 | } | |
389 | ||
390 | /** | |
391 | * @return the state | |
392 | */ | |
393 | public LttngExecutionState getState() { | |
394 | return state; | |
395 | } | |
396 | ||
397 | /** | |
398 | * @param state | |
399 | * the state to set | |
400 | */ | |
401 | public void setState(LttngExecutionState state) { | |
402 | this.state = state; | |
403 | } | |
404 | ||
405 | /** | |
406 | * @return the type | |
407 | */ | |
408 | public StateStrings.ProcessType getType() { | |
409 | return type; | |
410 | } | |
411 | ||
412 | /** | |
413 | * @param type | |
414 | * the type to set | |
415 | */ | |
416 | public void setType(StateStrings.ProcessType type) { | |
417 | this.type = type; | |
418 | } | |
419 | ||
420 | /** | |
421 | * @return the userTrace | |
422 | */ | |
423 | public String getUserTrace() { | |
424 | return userTrace; | |
425 | } | |
426 | ||
427 | /** | |
428 | * @param userTrace | |
429 | * the userTrace to set | |
430 | */ | |
431 | public void setUserTrace(String userTrace) { | |
432 | this.userTrace = userTrace; | |
433 | } | |
434 | ||
435 | ||
436 | public void clearUserStack() { | |
437 | user_stack.clear(); | |
438 | } | |
439 | ||
440 | public void pushToUserStack(Long newState) { | |
441 | user_stack.push(newState); | |
442 | } | |
443 | ||
444 | public Long popFromUserStack() { | |
445 | if (user_stack.size() <= 1) { | |
446 | TraceDebug.debug("Removing last item from user stack is not allowed! (popFromUserStack)"); | |
447 | return null; | |
448 | } | |
449 | else { | |
450 | return user_stack.pop(); | |
451 | } | |
452 | } | |
453 | ||
454 | public Long peekFromUserStack() { | |
455 | return user_stack.peek(); | |
456 | } | |
457 | ||
458 | ||
459 | ||
460 | public void clearExecutionStack() { | |
461 | execution_stack.clear(); | |
462 | } | |
463 | ||
464 | public void pushToExecutionStack(LttngExecutionState newState) { | |
465 | execution_stack.push(newState); | |
63eecb47 | 466 | setState(newState); |
5d10d135 ASL |
467 | } |
468 | ||
469 | public LttngExecutionState popFromExecutionStack() { | |
470 | if (execution_stack.size() <= 1) { | |
58c60db3 | 471 | TraceDebug.debug("Removing last item from execution stack is not allowed! (popFromExecutionStack)"); |
5d10d135 ASL |
472 | return null; |
473 | } | |
474 | else { | |
63eecb47 FC |
475 | LttngExecutionState popedState = execution_stack.pop(); |
476 | // adjust current state to the new top | |
477 | setState(peekFromExecutionStack()); | |
478 | return popedState; | |
5d10d135 ASL |
479 | } |
480 | } | |
481 | ||
482 | public LttngExecutionState peekFromExecutionStack() { | |
483 | return execution_stack.peek(); | |
484 | } | |
485 | ||
486 | public LttngExecutionState getFirstElementFromExecutionStack() { | |
487 | return execution_stack.firstElement(); | |
488 | } | |
58c60db3 FC |
489 | |
490 | /* | |
491 | * MAIN : For testing only! | |
492 | */ | |
493 | public static void main(String[] args) { | |
494 | ||
495 | // !!! TESTING CLONE HERE !!! | |
496 | ||
497 | // *** New object with some args set to "123" | |
498 | LttngProcessState joie = new LttngProcessState(new TmfTimestamp(123L, (byte) -9)); | |
499 | ||
500 | // Stack not empty by default?? | |
501 | System.out.println("Emptying stack... Trashing empty instance of : " + joie.popFromExecutionStack() ); | |
502 | ||
503 | joie.setCpu(123L); | |
504 | joie.setName("123"); | |
505 | ||
506 | LttngExecutionState testEx1 = new LttngExecutionState(); | |
507 | testEx1.setCum_cpu_time(123L); | |
508 | testEx1.setChange_Time(new TmfTimestamp(123L, (byte) -9)); | |
509 | testEx1.setEntry_Time(new TmfTimestamp(123L, (byte) -9)); | |
510 | ||
511 | // Print testEx1 reference | |
512 | System.out.println("testEx1 reference : " + testEx1); | |
513 | ||
514 | joie.pushToExecutionStack(testEx1); | |
515 | joie.pushToUserStack(123L); | |
516 | ||
517 | ||
518 | ||
519 | // *** New object cloned from the first one | |
520 | LttngProcessState joie2 = (LttngProcessState)joie.clone(); | |
521 | ||
522 | ||
523 | // *** Modification of the FIRST object : Everything to "456" | |
524 | joie.setCpu(456L); | |
525 | joie.setName("456"); | |
526 | testEx1.setCum_cpu_time(456L); | |
527 | testEx1.setChange_Time(new TmfTimestamp(456L, (byte) -9)); | |
528 | testEx1.setEntry_Time(new TmfTimestamp(456L, (byte) -9)); | |
529 | ||
530 | // Push new object on stack of the FIRST object | |
531 | LttngExecutionState testEx2 = new LttngExecutionState(); | |
532 | testEx2.setCum_cpu_time(456L); | |
533 | joie.pushToExecutionStack(testEx2); | |
534 | joie.pushToUserStack(456L); | |
535 | ||
536 | ||
537 | // *** TEST : Everything should be "123L" stil | |
538 | System.out.println("123 == " + joie2.getCpu() ); | |
539 | System.out.println("123 == " + joie2.getName() ); | |
540 | ||
541 | LttngExecutionState newtestEx1 = joie2.popFromExecutionStack(); | |
542 | // Print newtestEx1 reference | |
543 | System.out.println("testEx1 reference : " + newtestEx1); | |
544 | ||
545 | System.out.println("123 == " + newtestEx1.getCum_cpu_time() ); | |
546 | System.out.println("123 == " + joie2.popFromUserStack() ); | |
547 | ||
548 | // *** LAST TEST : The joie2 stack should be empty, only joie1 stack contains more than 1 object | |
549 | try { | |
550 | System.out.println("123 == " + joie2.popFromExecutionStack().getCum_cpu_time() ); | |
551 | } | |
552 | catch ( Exception e) { | |
553 | System.out.println("All fine"); | |
554 | } | |
555 | } | |
556 | ||
5d10d135 | 557 | } |