-/*******************************************************************************\r
- * Copyright (c) 2010 Ericsson\r
- *\r
- * All rights reserved. This program and the accompanying materials are\r
- * made available under the terms of the Eclipse Public License v1.0 which\r
- * accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * Patrick Tasse - Initial API and implementation\r
- *******************************************************************************/\r
-\r
-package org.eclipse.linuxtools.tmf.ui.views.timechart;\r
-\r
-import java.util.Iterator;\r
-import java.util.NoSuchElementException;\r
-import java.util.Vector;\r
-\r
-import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;\r
-\r
-/**\r
- * An entry (row) in the time chart analysis view\r
- *\r
- * @version 1.0\r
- * @author Patrick Tasse\r
- */\r
-public class TimeChartAnalysisEntry implements ITimeGraphEntry {\r
-\r
- private final ITmfTrace fTrace;\r
- private final Vector<TimeChartEvent> fTraceEvents;\r
- private int fPower = 0; // 2^fPower nanoseconds per vector position\r
- private long fReferenceTime = -1; // time corresponding to beginning of index 0\r
- private long fStartTime = -1; // time of first event\r
- private long fStopTime = -1; // time of last event\r
- private long fLastRank = -1; // rank of last processed trace event\r
-\r
- TimeChartAnalysisEntry(ITmfTrace trace, int modelSize) {\r
- fTrace = trace;\r
- fTraceEvents = new Vector<TimeChartEvent>(modelSize);\r
- }\r
-\r
- @Override\r
- public ITimeGraphEntry[] getChildren() {\r
- return null;\r
- }\r
-\r
- @Override\r
- public ITimeGraphEntry getParent() {\r
- return null;\r
- }\r
-\r
- @Override\r
- public boolean hasChildren() {\r
- return false;\r
- }\r
-\r
- @Override\r
- public String getName() {\r
- return fTrace.getName();\r
- }\r
-\r
- @Override\r
- public long getStartTime() {\r
- return fStartTime;\r
- }\r
-\r
- @Override\r
- public long getEndTime() {\r
- return fStopTime;\r
- }\r
-\r
- @Override\r
- public boolean hasTimeEvents() {\r
- return true;\r
- }\r
-\r
- @Override\r
- public Iterator<ITimeEvent> getTimeEventsIterator() {\r
- return new EntryIterator(0, Long.MAX_VALUE, 0);\r
- }\r
-\r
- @Override\r
- public Iterator<ITimeEvent> getTimeEventsIterator(long startTime, long stopTime, long maxDuration) {\r
- return new EntryIterator(startTime, stopTime, maxDuration);\r
- }\r
-\r
- private class EntryIterator implements Iterator<ITimeEvent> {\r
- private final long fIteratorStartTime;\r
- private final long fIteratorStopTime;\r
- private final long fIteratorMaxDuration;\r
- private long lastTime = -1;\r
- private TimeChartEvent next = null;\r
- private Iterator<ITimeEvent> nestedIterator = null;\r
-\r
- public EntryIterator(long startTime, long stopTime, long maxDuration) {\r
- fIteratorStartTime = startTime;\r
- fIteratorStopTime = stopTime;\r
- fIteratorMaxDuration = maxDuration;\r
- }\r
-\r
- @Override\r
- public boolean hasNext() {\r
- synchronized (fTraceEvents) {\r
- if (next != null) {\r
- return true;\r
- }\r
- if (nestedIterator != null) {\r
- if (nestedIterator.hasNext()) {\r
- return true;\r
- }\r
- nestedIterator = null;\r
- }\r
- long time = (lastTime == -1) ? fStartTime : lastTime;\r
- int index = (fReferenceTime == -1) ? 0 : (int) ((time - fReferenceTime) >> fPower);\r
- while (index < fTraceEvents.size()) {\r
- TimeChartEvent event = fTraceEvents.get(index++);\r
- if (event != null && (lastTime == -1 || event.getTime() > time)) {\r
- if (event.getTime() + event.getDuration() >= fIteratorStartTime && event.getTime() <= fIteratorStopTime) {\r
- if (event.getItemizedEntry() == null || event.getDuration() <= fIteratorMaxDuration) {\r
- lastTime = event.getTime() + event.getDuration();\r
- next = event;\r
- return true;\r
- }\r
- nestedIterator = event.getItemizedEntry().getTimeEventsIterator(fIteratorStartTime, fIteratorStopTime, fIteratorMaxDuration);\r
- return nestedIterator.hasNext();\r
- }\r
- }\r
- }\r
- return false;\r
- }\r
- }\r
-\r
- @Override\r
- public TimeChartEvent next() {\r
- synchronized (fTraceEvents) {\r
- if (nestedIterator != null) {\r
- TimeChartEvent event = (TimeChartEvent) nestedIterator.next();\r
- lastTime = event.getTime() + event.getDuration();\r
- return event;\r
- }\r
- if (hasNext()) {\r
- TimeChartEvent event = next;\r
- next = null;\r
- return event;\r
- }\r
- throw new NoSuchElementException();\r
- }\r
- }\r
-\r
- @Override\r
- public void remove() {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- }\r
-\r
- /**\r
- * Add a time event to the time chart entry\r
- *\r
- * @param timeEvent\r
- * The event to add\r
- */\r
- public void addTraceEvent(ITimeEvent timeEvent) {\r
- long time = timeEvent.getTime();\r
- synchronized (fTraceEvents) {\r
- long index = (fReferenceTime == -1) ? 0 : (time - fReferenceTime) >> fPower;\r
- if (index < 0) {\r
- if (fTraceEvents.capacity() - fTraceEvents.size() < -index) {\r
- int powershift = (-index + fTraceEvents.size() <= 2 * fTraceEvents.capacity()) ? 1 :\r
- (int) Math.ceil(Math.log((double) (-index + fTraceEvents.size()) / fTraceEvents.capacity()) / Math.log(2));\r
- merge(powershift);\r
- index = (int) ((time - fReferenceTime) >> fPower);\r
- }\r
- shift((int) -index);\r
- index = 0;\r
- fTraceEvents.set(0, (TimeChartEvent) timeEvent);\r
- } else if (index < fTraceEvents.capacity()) {\r
- if (index >= fTraceEvents.size()) {\r
- fTraceEvents.setSize((int) index + 1);\r
- }\r
- } else {\r
- int powershift = (index < 2 * fTraceEvents.capacity()) ? 1 :\r
- (int) Math.ceil(Math.log((double) (index + 1) / fTraceEvents.capacity()) / Math.log(2));\r
- merge(powershift);\r
- index = (int) ((time - fReferenceTime) >> fPower);\r
- fTraceEvents.setSize((int) index + 1);\r
- }\r
- TimeChartEvent event = fTraceEvents.get((int) index);\r
- if (event == null) {\r
- fTraceEvents.set((int) index, (TimeChartEvent) timeEvent);\r
- } else {\r
- if (event.getItemizedEntry() == null) {\r
- event.merge((TimeChartEvent) timeEvent);\r
- } else {\r
- event.mergeDecorations((TimeChartEvent) timeEvent);\r
- event.getItemizedEntry().addTraceEvent(timeEvent);\r
- }\r
- }\r
- if (fReferenceTime == -1 || time < fReferenceTime) {\r
- fReferenceTime = (time >> fPower) << fPower;\r
- }\r
- if (fStartTime == -1 || time < fStartTime) {\r
- fStartTime = time;\r
- }\r
- if (fStopTime == -1 || time > fStopTime) {\r
- fStopTime = time;\r
- }\r
- }\r
- }\r
-\r
- private void merge(int powershift) {\r
- fPower += powershift;\r
- fReferenceTime = (fReferenceTime >> fPower) << fPower;\r
- int index = 0;\r
- for (int i = 0; i < fTraceEvents.size(); i++) {\r
- TimeChartEvent event = fTraceEvents.get(i);\r
- if (event != null) {\r
- index = (int) ((event.getTime() - fReferenceTime) >> fPower);\r
- TimeChartEvent mergedEvent = fTraceEvents.get(index);\r
- if (mergedEvent == null) {\r
- fTraceEvents.set(index, event);\r
- } else {\r
- mergedEvent.merge(event);\r
- }\r
- if (i != index) {\r
- fTraceEvents.set(i, null);\r
- }\r
- }\r
- }\r
- fTraceEvents.setSize(index + 1);\r
- }\r
-\r
- private void shift(int indexshift) {\r
- int oldSize = fTraceEvents.size();\r
- fTraceEvents.setSize(oldSize + indexshift);\r
- for (int i = oldSize - 1; i >= 0; i--) {\r
- fTraceEvents.set(i + indexshift, fTraceEvents.get(i));\r
- }\r
- for (int i = 0; i < indexshift; i++) {\r
- fTraceEvents.set(i, null);\r
- }\r
- }\r
-\r
- /**\r
- * Retrieve the trace associated with this entry\r
- *\r
- * @return The trace object\r
- */\r
- public ITmfTrace getTrace() {\r
- return fTrace;\r
- }\r
-\r
- /**\r
- * Set the last rank of the entry\r
- *\r
- * @param rank\r
- * The rank to set\r
- */\r
- public void setLastRank(long rank) {\r
- fLastRank = rank;\r
- }\r
-\r
- /**\r
- * Retrieve the last rank of the entry\r
- *\r
- * @return The last rank\r
- */\r
- public long getLastRank() {\r
- return fLastRank;\r
- }\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Patrick Tasse - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.tmf.ui.views.timechart;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Vector;
+
+import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
+
+/**
+ * An entry (row) in the time chart analysis view
+ *
+ * @version 1.0
+ * @author Patrick Tasse
+ */
+public class TimeChartAnalysisEntry implements ITimeGraphEntry {
+
+ private final ITmfTrace fTrace;
+ private final Vector<TimeChartEvent> fTraceEvents;
+ private int fPower = 0; // 2^fPower nanoseconds per vector position
+ private long fReferenceTime = -1; // time corresponding to beginning of index 0
+ private long fStartTime = -1; // time of first event
+ private long fStopTime = -1; // time of last event
+ private long fLastRank = -1; // rank of last processed trace event
+
+ TimeChartAnalysisEntry(ITmfTrace trace, int modelSize) {
+ fTrace = trace;
+ fTraceEvents = new Vector<TimeChartEvent>(modelSize);
+ }
+
+ @Override
+ public ITimeGraphEntry[] getChildren() {
+ return null;
+ }
+
+ @Override
+ public ITimeGraphEntry getParent() {
+ return null;
+ }
+
+ @Override
+ public boolean hasChildren() {
+ return false;
+ }
+
+ @Override
+ public String getName() {
+ return fTrace.getName();
+ }
+
+ @Override
+ public long getStartTime() {
+ return fStartTime;
+ }
+
+ @Override
+ public long getEndTime() {
+ return fStopTime;
+ }
+
+ @Override
+ public boolean hasTimeEvents() {
+ return true;
+ }
+
+ @Override
+ public Iterator<ITimeEvent> getTimeEventsIterator() {
+ return new EntryIterator(0, Long.MAX_VALUE, 0);
+ }
+
+ @Override
+ public Iterator<ITimeEvent> getTimeEventsIterator(long startTime, long stopTime, long maxDuration) {
+ return new EntryIterator(startTime, stopTime, maxDuration);
+ }
+
+ private class EntryIterator implements Iterator<ITimeEvent> {
+ private final long fIteratorStartTime;
+ private final long fIteratorStopTime;
+ private final long fIteratorMaxDuration;
+ private long lastTime = -1;
+ private TimeChartEvent next = null;
+ private Iterator<ITimeEvent> nestedIterator = null;
+
+ public EntryIterator(long startTime, long stopTime, long maxDuration) {
+ fIteratorStartTime = startTime;
+ fIteratorStopTime = stopTime;
+ fIteratorMaxDuration = maxDuration;
+ }
+
+ @Override
+ public boolean hasNext() {
+ synchronized (fTraceEvents) {
+ if (next != null) {
+ return true;
+ }
+ if (nestedIterator != null) {
+ if (nestedIterator.hasNext()) {
+ return true;
+ }
+ nestedIterator = null;
+ }
+ long time = (lastTime == -1) ? fStartTime : lastTime;
+ int index = (fReferenceTime == -1) ? 0 : (int) ((time - fReferenceTime) >> fPower);
+ while (index < fTraceEvents.size()) {
+ TimeChartEvent event = fTraceEvents.get(index++);
+ if (event != null && (lastTime == -1 || event.getTime() > time)) {
+ if (event.getTime() + event.getDuration() >= fIteratorStartTime && event.getTime() <= fIteratorStopTime) {
+ if (event.getItemizedEntry() == null || event.getDuration() <= fIteratorMaxDuration) {
+ lastTime = event.getTime() + event.getDuration();
+ next = event;
+ return true;
+ }
+ nestedIterator = event.getItemizedEntry().getTimeEventsIterator(fIteratorStartTime, fIteratorStopTime, fIteratorMaxDuration);
+ return nestedIterator.hasNext();
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+ @Override
+ public TimeChartEvent next() {
+ synchronized (fTraceEvents) {
+ if (nestedIterator != null) {
+ TimeChartEvent event = (TimeChartEvent) nestedIterator.next();
+ lastTime = event.getTime() + event.getDuration();
+ return event;
+ }
+ if (hasNext()) {
+ TimeChartEvent event = next;
+ next = null;
+ return event;
+ }
+ throw new NoSuchElementException();
+ }
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+
+ /**
+ * Add a time event to the time chart entry
+ *
+ * @param timeEvent
+ * The event to add
+ */
+ public void addTraceEvent(ITimeEvent timeEvent) {
+ long time = timeEvent.getTime();
+ synchronized (fTraceEvents) {
+ long index = (fReferenceTime == -1) ? 0 : (time - fReferenceTime) >> fPower;
+ if (index < 0) {
+ if (fTraceEvents.capacity() - fTraceEvents.size() < -index) {
+ int powershift = (-index + fTraceEvents.size() <= 2 * fTraceEvents.capacity()) ? 1 :
+ (int) Math.ceil(Math.log((double) (-index + fTraceEvents.size()) / fTraceEvents.capacity()) / Math.log(2));
+ merge(powershift);
+ index = (int) ((time - fReferenceTime) >> fPower);
+ }
+ shift((int) -index);
+ index = 0;
+ fTraceEvents.set(0, (TimeChartEvent) timeEvent);
+ } else if (index < fTraceEvents.capacity()) {
+ if (index >= fTraceEvents.size()) {
+ fTraceEvents.setSize((int) index + 1);
+ }
+ } else {
+ int powershift = (index < 2 * fTraceEvents.capacity()) ? 1 :
+ (int) Math.ceil(Math.log((double) (index + 1) / fTraceEvents.capacity()) / Math.log(2));
+ merge(powershift);
+ index = (int) ((time - fReferenceTime) >> fPower);
+ fTraceEvents.setSize((int) index + 1);
+ }
+ TimeChartEvent event = fTraceEvents.get((int) index);
+ if (event == null) {
+ fTraceEvents.set((int) index, (TimeChartEvent) timeEvent);
+ } else {
+ if (event.getItemizedEntry() == null) {
+ event.merge((TimeChartEvent) timeEvent);
+ } else {
+ event.mergeDecorations((TimeChartEvent) timeEvent);
+ event.getItemizedEntry().addTraceEvent(timeEvent);
+ }
+ }
+ if (fReferenceTime == -1 || time < fReferenceTime) {
+ fReferenceTime = (time >> fPower) << fPower;
+ }
+ if (fStartTime == -1 || time < fStartTime) {
+ fStartTime = time;
+ }
+ if (fStopTime == -1 || time > fStopTime) {
+ fStopTime = time;
+ }
+ }
+ }
+
+ private void merge(int powershift) {
+ fPower += powershift;
+ fReferenceTime = (fReferenceTime >> fPower) << fPower;
+ int index = 0;
+ for (int i = 0; i < fTraceEvents.size(); i++) {
+ TimeChartEvent event = fTraceEvents.get(i);
+ if (event != null) {
+ index = (int) ((event.getTime() - fReferenceTime) >> fPower);
+ TimeChartEvent mergedEvent = fTraceEvents.get(index);
+ if (mergedEvent == null) {
+ fTraceEvents.set(index, event);
+ } else {
+ mergedEvent.merge(event);
+ }
+ if (i != index) {
+ fTraceEvents.set(i, null);
+ }
+ }
+ }
+ fTraceEvents.setSize(index + 1);
+ }
+
+ private void shift(int indexshift) {
+ int oldSize = fTraceEvents.size();
+ fTraceEvents.setSize(oldSize + indexshift);
+ for (int i = oldSize - 1; i >= 0; i--) {
+ fTraceEvents.set(i + indexshift, fTraceEvents.get(i));
+ }
+ for (int i = 0; i < indexshift; i++) {
+ fTraceEvents.set(i, null);
+ }
+ }
+
+ /**
+ * Retrieve the trace associated with this entry
+ *
+ * @return The trace object
+ */
+ public ITmfTrace getTrace() {
+ return fTrace;
+ }
+
+ /**
+ * Set the last rank of the entry
+ *
+ * @param rank
+ * The rank to set
+ */
+ public void setLastRank(long rank) {
+ fLastRank = rank;
+ }
+
+ /**
+ * Retrieve the last rank of the entry
+ *
+ * @return The last rank
+ */
+ public long getLastRank() {
+ return fLastRank;
+ }
+}