1 /*******************************************************************************
2 * Copyright (c) 2010, 2016 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 * Patrick Tasse - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.tracecompass
.tmf
.ui
.views
.timechart
;
15 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
17 import java
.util
.Iterator
;
18 import java
.util
.List
;
19 import java
.util
.NoSuchElementException
;
20 import java
.util
.Vector
;
21 import java
.util
.regex
.Pattern
;
23 import org
.eclipse
.jdt
.annotation
.NonNull
;
24 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
25 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ITimeEvent
;
26 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ITimeGraphEntry
;
29 * An entry (row) in the time chart analysis view
32 * @author Patrick Tasse
34 public class TimeChartAnalysisEntry
implements ITimeGraphEntry
{
36 private final ITmfTrace fTrace
;
37 private final Vector
<TimeChartEvent
> fTraceEvents
;
38 private int fPower
= 0; // 2^fPower nanoseconds per vector position
39 private long fReferenceTime
= -1; // time corresponding to beginning of index 0
40 private long fStartTime
= -1; // time of first event
41 private long fStopTime
= -1; // time of last event
42 private long fLastRank
= -1; // rank of last processed trace event
44 TimeChartAnalysisEntry(ITmfTrace trace
, int modelSize
) {
46 fTraceEvents
= new Vector
<>(modelSize
);
50 public List
<@NonNull ITimeGraphEntry
> getChildren() {
55 public ITimeGraphEntry
getParent() {
60 public boolean hasChildren() {
65 public String
getName() {
66 return fTrace
.getName();
70 public long getStartTime() {
75 public long getEndTime() {
80 public boolean hasTimeEvents() {
85 public Iterator
<@NonNull ITimeEvent
> getTimeEventsIterator() {
86 return new EntryIterator(0, Long
.MAX_VALUE
, 0);
90 public Iterator
<@NonNull ITimeEvent
> getTimeEventsIterator(long startTime
, long stopTime
, long maxDuration
) {
91 return new EntryIterator(startTime
, stopTime
, maxDuration
);
94 private class EntryIterator
implements Iterator
<@NonNull ITimeEvent
> {
95 private final long fIteratorStartTime
;
96 private final long fIteratorStopTime
;
97 private final long fIteratorMaxDuration
;
98 private long lastTime
= -1;
99 private TimeChartEvent next
= null;
100 private Iterator
<ITimeEvent
> nestedIterator
= null;
102 public EntryIterator(long startTime
, long stopTime
, long maxDuration
) {
103 fIteratorStartTime
= startTime
;
104 fIteratorStopTime
= stopTime
;
105 fIteratorMaxDuration
= maxDuration
;
109 public boolean hasNext() {
110 synchronized (fTraceEvents
) {
114 if (nestedIterator
!= null) {
115 if (nestedIterator
.hasNext()) {
118 nestedIterator
= null;
120 long time
= (lastTime
== -1) ? fStartTime
: lastTime
;
121 int index
= (fReferenceTime
== -1) ?
0 : (int) ((time
- fReferenceTime
) >> fPower
);
122 while (index
< fTraceEvents
.size()) {
123 TimeChartEvent event
= fTraceEvents
.get(index
++);
124 if (event
!= null && (lastTime
== -1 || event
.getTime() > time
)) {
125 if (event
.getTime() + event
.getDuration() >= fIteratorStartTime
&& event
.getTime() <= fIteratorStopTime
) {
126 if (event
.getItemizedEntry() == null || event
.getDuration() <= fIteratorMaxDuration
) {
127 lastTime
= event
.getTime() + event
.getDuration();
131 nestedIterator
= event
.getItemizedEntry().getTimeEventsIterator(fIteratorStartTime
, fIteratorStopTime
, fIteratorMaxDuration
);
132 return nestedIterator
.hasNext();
141 public TimeChartEvent
next() {
142 synchronized (fTraceEvents
) {
143 if (nestedIterator
!= null) {
144 TimeChartEvent event
= (TimeChartEvent
) nestedIterator
.next();
145 lastTime
= event
.getTime() + event
.getDuration();
149 TimeChartEvent event
= checkNotNull(next
);
153 throw new NoSuchElementException();
158 public void remove() {
159 throw new UnsupportedOperationException();
165 * Add a time event to the time chart entry
170 public void addTraceEvent(ITimeEvent timeEvent
) {
171 long time
= timeEvent
.getTime();
172 synchronized (fTraceEvents
) {
173 long index
= (fReferenceTime
== -1) ?
0 : (time
- fReferenceTime
) >> fPower
;
175 if (fTraceEvents
.capacity() - fTraceEvents
.size() < -index
) {
176 int powershift
= (-index
+ fTraceEvents
.size() <= 2 * fTraceEvents
.capacity()) ?
1 :
177 (int) Math
.ceil(Math
.log((double) (-index
+ fTraceEvents
.size()) / fTraceEvents
.capacity()) / Math
.log(2));
179 index
= (int) ((time
- fReferenceTime
) >> fPower
);
183 fTraceEvents
.set(0, (TimeChartEvent
) timeEvent
);
184 } else if (index
< fTraceEvents
.capacity()) {
185 if (index
>= fTraceEvents
.size()) {
186 fTraceEvents
.setSize((int) index
+ 1);
189 int powershift
= (index
< 2 * fTraceEvents
.capacity()) ?
1 :
190 (int) Math
.ceil(Math
.log((double) (index
+ 1) / fTraceEvents
.capacity()) / Math
.log(2));
192 index
= (int) ((time
- fReferenceTime
) >> fPower
);
193 fTraceEvents
.setSize((int) index
+ 1);
195 TimeChartEvent event
= fTraceEvents
.get((int) index
);
197 fTraceEvents
.set((int) index
, (TimeChartEvent
) timeEvent
);
199 if (event
.getItemizedEntry() == null) {
200 event
.merge((TimeChartEvent
) timeEvent
);
202 event
.mergeDecorations((TimeChartEvent
) timeEvent
);
203 event
.getItemizedEntry().addTraceEvent(timeEvent
);
206 if (fReferenceTime
== -1 || time
< fReferenceTime
) {
207 fReferenceTime
= (time
>> fPower
) << fPower
;
209 if (fStartTime
== -1 || time
< fStartTime
) {
212 if (fStopTime
== -1 || time
> fStopTime
) {
218 private void merge(int powershift
) {
219 fPower
+= powershift
;
220 fReferenceTime
= (fReferenceTime
>> fPower
) << fPower
;
222 for (int i
= 0; i
< fTraceEvents
.size(); i
++) {
223 TimeChartEvent event
= fTraceEvents
.get(i
);
225 index
= (int) ((event
.getTime() - fReferenceTime
) >> fPower
);
226 TimeChartEvent mergedEvent
= fTraceEvents
.get(index
);
227 if (mergedEvent
== null) {
228 fTraceEvents
.set(index
, event
);
230 mergedEvent
.merge(event
);
233 fTraceEvents
.set(i
, null);
237 fTraceEvents
.setSize(index
+ 1);
240 private void shift(int indexshift
) {
241 int oldSize
= fTraceEvents
.size();
242 fTraceEvents
.setSize(oldSize
+ indexshift
);
243 for (int i
= oldSize
- 1; i
>= 0; i
--) {
244 fTraceEvents
.set(i
+ indexshift
, fTraceEvents
.get(i
));
246 for (int i
= 0; i
< indexshift
; i
++) {
247 fTraceEvents
.set(i
, null);
252 * Retrieve the trace associated with this entry
254 * @return The trace object
256 public ITmfTrace
getTrace() {
261 * Set the last rank of the entry
266 public void setLastRank(long rank
) {
271 * Retrieve the last rank of the entry
273 * @return The last rank
275 public long getLastRank() {
283 public boolean matches(@NonNull Pattern pattern
) {
284 return getName() != null ? pattern
.matcher(getName()).find() : false;