From 88144d4adebd89a3e86eec2ccd8492ed7ebcc02e Mon Sep 17 00:00:00 2001 From: Alvaro Sanchez-Leon Date: Thu, 11 Feb 2010 16:48:17 +0000 Subject: [PATCH] temporary re-factoring project --- .../META-INF/MANIFEST.MF | 10 +- .../plugin.properties | 2 +- .../linuxtools/lttng/LTTngCorePlugin.java | 2 +- .../eclipse/linuxtools/lttng/TraceDebug.java | 5 +- .../linuxtools/lttng/event/LttngEvent.java | 73 +- .../lttng/event/LttngEventContent.java | 83 +- .../linuxtools/lttng/jni/JniEvent.java | 478 +++++++++++ .../linuxtools/lttng/jni/JniException.java | 169 ++++ .../linuxtools/lttng/jni/JniMarker.java | 235 ++++++ .../linuxtools/lttng/jni/JniMarkerField.java | 158 ++++ .../linuxtools/lttng/jni/JniParser.java | 304 +++++++ .../eclipse/linuxtools/lttng/jni/JniTime.java | 178 ++++ .../linuxtools/lttng/jni/JniTrace.java | 785 ++++++++++++++++++ .../linuxtools/lttng/jni/JniTracefile.java | 465 +++++++++++ .../linuxtools/lttng/jni/Jni_C_Common.java | 75 ++ .../linuxtools/lttng/jni/Jni_C_Pointer.java | 94 +++ .../state/IStateDataRequestListener.java | 38 + .../lttng/state/LttngStateInputRef.java | 105 +++ .../lttng/state/RequestCompletedSignal.java | 18 + .../lttng/state/RequestStartedSignal.java | 18 + .../lttng/state/StateDataRequest.java | 350 ++++---- .../linuxtools/lttng/state/StateManager.java | 587 +++++++++++++ .../lttng/state/StateStacksHandler.java | 199 +++++ .../evProcessor/AbsEventProcessorFactory.java | 51 ++ .../evProcessor/EventProcessorProxy.java | 12 +- .../state/evProcessor/IEventProcessing.java | 29 + .../evProcessor/state/AbsStateUpdate.java | 7 +- .../evProcessor/state/StateUpdateFactory.java | 186 +++++ .../state/StateUpdateHandlers.java | 259 ++++-- .../experiment/StateExperimentManager.java | 466 +++-------- .../state/experiment/StateManagerFactory.java | 112 +-- .../state/model/ILttngStateInputRef.java | 33 + .../lttng/state/model/LttngTraceState.java | 23 +- .../lttng/state/model/LttngTrapState.java | 13 +- .../lttng/state/model/StateModelFactory.java | 3 +- .../lttng/trace/LTTngTextTrace.java | 304 +++++-- .../linuxtools/lttng/trace/LTTngTrace.java | 753 +++-------------- 37 files changed, 5147 insertions(+), 1535 deletions(-) create mode 100644 org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniEvent.java create mode 100644 org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniException.java create mode 100644 org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniMarker.java create mode 100644 org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniMarkerField.java create mode 100644 org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniParser.java create mode 100644 org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniTime.java create mode 100644 org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniTrace.java create mode 100644 org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniTracefile.java create mode 100644 org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/Jni_C_Common.java create mode 100644 org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/Jni_C_Pointer.java create mode 100644 org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/IStateDataRequestListener.java create mode 100644 org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/LttngStateInputRef.java create mode 100644 org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/RequestCompletedSignal.java create mode 100644 org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/RequestStartedSignal.java create mode 100644 org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/StateManager.java create mode 100644 org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/StateStacksHandler.java create mode 100644 org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/AbsEventProcessorFactory.java create mode 100644 org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/IEventProcessing.java create mode 100644 org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/state/StateUpdateFactory.java create mode 100644 org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/model/ILttngStateInputRef.java diff --git a/org.eclipse.linuxtools.lttng/META-INF/MANIFEST.MF b/org.eclipse.linuxtools.lttng/META-INF/MANIFEST.MF index 326bd6e351..515753605b 100644 --- a/org.eclipse.linuxtools.lttng/META-INF/MANIFEST.MF +++ b/org.eclipse.linuxtools.lttng/META-INF/MANIFEST.MF @@ -6,22 +6,16 @@ Bundle-Version: 0.2.0.qualifier Bundle-Activator: org.eclipse.linuxtools.lttng.LTTngCorePlugin Bundle-Vendor: %Bundle-Vendor Require-Bundle: org.eclipse.core.runtime, - org.eclipse.linuxtools.tmf;bundle-version="0.2.0", - org.eclipse.linuxtools.lttng.jni;bundle-version="0.2.0" + org.eclipse.linuxtools.tmf;bundle-version="0.2.0" Bundle-RequiredExecutionEnvironment: J2SE-1.5 Bundle-ActivationPolicy: lazy Export-Package: org.eclipse.linuxtools.lttng, - org.eclipse.linuxtools.lttng.control, org.eclipse.linuxtools.lttng.event, - org.eclipse.linuxtools.lttng.model, - org.eclipse.linuxtools.lttng.request, - org.eclipse.linuxtools.lttng.signal, + org.eclipse.linuxtools.lttng.jni, org.eclipse.linuxtools.lttng.state, org.eclipse.linuxtools.lttng.state.evProcessor, org.eclipse.linuxtools.lttng.state.evProcessor.state, org.eclipse.linuxtools.lttng.state.experiment, org.eclipse.linuxtools.lttng.state.model, - org.eclipse.linuxtools.lttng.state.resource, - org.eclipse.linuxtools.lttng.state.trace, org.eclipse.linuxtools.lttng.trace Bundle-Localization: plugin diff --git a/org.eclipse.linuxtools.lttng/plugin.properties b/org.eclipse.linuxtools.lttng/plugin.properties index 9415eb3102..da1d0fbac8 100644 --- a/org.eclipse.linuxtools.lttng/plugin.properties +++ b/org.eclipse.linuxtools.lttng/plugin.properties @@ -1,3 +1,3 @@ #Properties file for org.eclipse.linuxtools.lttng -Bundle-Vendor = Eclipse Linux Tools +Bundle-Vendor = Eclipse Bundle-Name = LTTng - Linux Tracing Toolkit (Incubation) \ No newline at end of file diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/LTTngCorePlugin.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/LTTngCorePlugin.java index 533f53704e..779ae5e9f8 100644 --- a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/LTTngCorePlugin.java +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/LTTngCorePlugin.java @@ -67,7 +67,7 @@ public class LTTngCorePlugin extends Plugin { public void start(BundleContext context) throws Exception { super.start(context); plugin = this; - LttngFactory.init(); + TraceDebug.init(); } /* diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/TraceDebug.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/TraceDebug.java index c2cd34637d..96eb50dd49 100644 --- a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/TraceDebug.java +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/TraceDebug.java @@ -95,8 +95,6 @@ public class TraceDebug { int earliestRequested = numOfStackLines > 0 ? stackCalledFromIdx + numOfStackLines : stackCalledFromIdx; StringBuilder sb = new StringBuilder(); - int max = Thread.currentThread().getStackTrace().length - 1; - earliestRequested = earliestRequested > max ? max : earliestRequested; for (int i = earliestRequested; i >= stackCalledFromIdx; i--) { sb.append(trace(Thread.currentThread().getStackTrace(), i) + "\n"); } @@ -104,8 +102,7 @@ public class TraceDebug { } private static String trace(StackTraceElement e[], int level) { - if (e != null) { - level = level >= e.length ? e.length - 1 : level; + if (e != null && e.length >= level) { StackTraceElement s = e[level]; if (s != null) { String simpleClassName = s.getClassName(); diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/event/LttngEvent.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/event/LttngEvent.java index ea4a01025b..81a6f2f32b 100644 --- a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/event/LttngEvent.java +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/event/LttngEvent.java @@ -3,7 +3,6 @@ package org.eclipse.linuxtools.lttng.event; import org.eclipse.linuxtools.lttng.jni.JniEvent; import org.eclipse.linuxtools.tmf.event.TmfEvent; import org.eclipse.linuxtools.tmf.event.TmfEventSource; -import org.eclipse.linuxtools.tmf.trace.TmfTrace; /** * LttngEvent

@@ -17,10 +16,7 @@ public class LttngEvent extends TmfEvent { // Reference to the JNI JniEvent. Should only be used INTERNALLY private JniEvent jniEventReference = null; - - // Reference to the parent trace that own this event - private TmfTrace parentTrace = null; - + /** * Constructor with parameters.

* @@ -38,12 +34,11 @@ public class LttngEvent extends TmfEvent { * @see org.eclipse.linuxtools.lttng.event.LttngEventReference * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniEvent */ - public LttngEvent(TmfTrace parent, LttngTimestamp timestamp, TmfEventSource source, LttngEventType type, LttngEventContent content, LttngEventReference reference, JniEvent lttEvent) { + public LttngEvent(LttngTimestamp timestamp, TmfEventSource source, LttngEventType type, LttngEventContent content, LttngEventReference reference, JniEvent lttEvent) { super(timestamp, source, type, reference); fContent = content; jniEventReference = lttEvent; - setParentTrace(parent); } /** @@ -52,9 +47,7 @@ public class LttngEvent extends TmfEvent { * @param oldEvent Event we want to copy from. */ public LttngEvent(LttngEvent oldEvent) { - this( - oldEvent.getParentTrace(), - (LttngTimestamp)oldEvent.getTimestamp(), + this( (LttngTimestamp)oldEvent.getTimestamp(), (TmfEventSource)oldEvent.getSource(), (LttngEventType)oldEvent.getType(), (LttngEventContent)oldEvent.getContent(), @@ -65,25 +58,6 @@ public class LttngEvent extends TmfEvent { /** - * Return the parent trace asoociated with this event - * - * @return Parent trace - */ - public TmfTrace getParentTrace() { - return parentTrace; - } - - /** - * Set a new parent trace for this event - * - * @param parentTrace The new parent - */ - public void setParentTrace(TmfTrace parentTrace) { - this.parentTrace = parentTrace; - } - - - /** * Return the channel name of this event.

* * @return Channel (tracefile) for this event @@ -110,6 +84,19 @@ public class LttngEvent extends TmfEvent { return ( (LttngEventType)this.getType() ).getMarkerName(); } + /** + * Set a new JniReference for this event.

+ * + * Note : Reference is used to get back to the Jni during event parsing and need to be consistent. + * + * @param newJniEventReference New reference + * + * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniEvent + */ + public void updateJniEventReference(JniEvent newJniEventReference) { + this.jniEventReference = newJniEventReference; + } + @Override public LttngEventContent getContent() { return (LttngEventContent)fContent; @@ -128,18 +115,6 @@ public class LttngEvent extends TmfEvent { fType = newType; } - /** - * Set a new JniReference for this event.

- * - * Note : Reference is used to get back to the Jni during event parsing and need to be consistent. - * - * @param newJniEventReference New reference - * - * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniEvent - */ - public synchronized void updateJniEventReference(JniEvent newJniEventReference) { - this.jniEventReference = newJniEventReference; - } /** * Convert this event into a Jni JniEvent.

@@ -151,7 +126,7 @@ public class LttngEvent extends TmfEvent { * * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniEvent */ - public synchronized JniEvent convertEventTmfToJni() { + public JniEvent convertEventTmfToJni() { JniEvent tmpEvent = null; // ***TODO*** @@ -170,13 +145,13 @@ public class LttngEvent extends TmfEvent { @Override public String toString() { - StringBuffer result= new StringBuffer("[LttngEvent("); - result.append("Timestamp:" + getTimestamp().getValue()); - result.append(",Channel:" + getChannelName()); - result.append(",CPU:" + getCpuId()); - result.append(",Marker:" + getMarkerName()); - result.append(",Content:" + getContent() + ")]"); + String returnedData=""; + + returnedData += "Event timestamp:" + this.getTimestamp().getValue() + " "; + returnedData += "Channel:" + getChannelName() + " "; + returnedData += "CPU:" + getCpuId() + " "; + returnedData += "Marker:" + getMarkerName() + " "; - return result.toString(); + return returnedData; } } diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/event/LttngEventContent.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/event/LttngEventContent.java index c8b6d45408..92ee00dc3c 100644 --- a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/event/LttngEventContent.java +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/event/LttngEventContent.java @@ -14,9 +14,7 @@ package org.eclipse.linuxtools.lttng.event; import java.util.HashMap; -import org.eclipse.linuxtools.lttng.jni.JniEvent; import org.eclipse.linuxtools.tmf.event.TmfEventContent; -import org.eclipse.linuxtools.tmf.event.TmfNoSuchFieldException; /** * LttngEventContent

@@ -87,9 +85,11 @@ public class LttngEventContent extends TmfEventContent { @Override public LttngEventType getType() { return (LttngEventType)fParentEvent.getType(); +// return (LttngEventType)fEventType; } public void setType(LttngEventType newType) { ((LttngEvent)fParentEvent).setType(newType); +// fEventType = newType; } @@ -100,7 +100,7 @@ public class LttngEventContent extends TmfEventContent { } // ***VERIFY*** - // A bit weird to return the _currently_parsed fields (unlike all fields like getFields() ) + // A bit weird to return the _currently_parsed fields (unlike all like getFields() ) // Should we keep this? /** * Return currently parsed fields in an object array format.

@@ -154,30 +154,17 @@ public class LttngEventContent extends TmfEventContent { * @see @see org.eclipse.linuxtools.lttng.event.LttngEventField */ @Override - public synchronized LttngEventField[] getFields() { - if ( fFieldsMap.size() < fParentEvent.getType().getNbFields() ) { - LttngEventField tmpField = null; - LttngEventType tmpType = (LttngEventType)fParentEvent.getType(); - - for ( int pos=0; posJniEvent

+ * + * A JniEvent has the actual content that got traced by Lttng.
+ * Provides access to the LttEvent C structure in java.

+ * + * Most important fields in the JniEvent are : + *

+ * Note that the JniEvent content is not directly accessibe and should be obtained + * using the parseAllFields() or parseFieldBy...() methods. + */ +public final class JniEvent extends Jni_C_Common implements Comparable { + // Variables to detect if the event have been filled at least once + // this make possible the detection of "uninitialized" struct in Ltt + // Can be "EOK", "ERANGE" or "EPERM" (defined in Jaf_C_Common) + private int eventState = EPERM; // Start with EPERM to ensure sanity + + // Internal C pointer of the JniEvent used in LTT + private Jni_C_Pointer thisEventPtr = new Jni_C_Pointer(); + + // Reference to the parent tracefile + private JniTracefile parentTracefile = null; + + // This map hold marker relative to the parent tracefile of this event + // They are "our" marker in this event + private HashMap markersMap = null; + + // Data we should populate from ltt + // Note that all type have been scaled up as there is no "unsigned" in java + // This might be a problem about "unsigned long" as there is no equivalent + // in java + private Jni_C_Pointer tracefilePtr = new Jni_C_Pointer(); + private JniTime eventTime = null; + + // These methods need a tracefile pointer, instead of a event pointer + private native int ltt_readNextEvent(long tracefilePtr); + private native int ltt_seekEvent(long tracefilePtr, JniTime givenTime); + private native int ltt_positionToFirstEvent(long tracefilePtr); + + // Native access functions + private native long ltt_getTracefilePtr(long eventPtr); + @SuppressWarnings("unused") + private native long ltt_getBlock(long eventPtr); + @SuppressWarnings("unused") + private native long ltt_getOffset(long eventPtr); + @SuppressWarnings("unused") + private native long ltt_getCurrentTimestampCounter(long eventPtr); + @SuppressWarnings("unused") + private native long ltt_getTimestamp(long eventPtr); + private native int ltt_getEventMarkerId(long eventPtr); + private native long ltt_getNanosencondsTime(long eventPtr); + @SuppressWarnings("unused") + private native void ltt_feedEventTime(long eventPtr, JniTime eventTime); + private native long ltt_getEventDataSize(long eventPtr); + @SuppressWarnings("unused") + private native long ltt_getEventSize(long eventPtr); + @SuppressWarnings("unused") + private native int ltt_getCount(long eventPtr); + @SuppressWarnings("unused") + private native long ltt_getOverflowNanoSeconds(long eventPtr); + + // This method an event pointer + private native void ltt_getDataContent(long eventPtr, long dataSize, byte[] returnedContent); + + // Debug native function, ask LTT to print event structure + private native void ltt_printEvent(long eventPtr); + + static { + System.loadLibrary("lttvtraceread"); + } + + + /** + * Default constructor is forbidden + */ + @SuppressWarnings("unused") + private JniEvent() { + }; + + /** + * Copy constructor.

+ * + * @param oldEvent Reference to the JniEvent you want to copy. + */ + public JniEvent(JniEvent oldEvent) { + thisEventPtr = oldEvent.thisEventPtr; + markersMap = oldEvent.markersMap; + parentTracefile = oldEvent.parentTracefile; + eventState = oldEvent.eventState; + + tracefilePtr = oldEvent.tracefilePtr; + eventTime = oldEvent.eventTime; + } + + /** + * Constructor with parameters

+ * + * This constructor could throw. It will happen if an event can not be populated on first read.
+ * In that case, the parent tracefile is probably useless and should be deleted. + * + * @param newEventPtr C pointer (converted in long) of the LttEvent C structure. + * @param newMarkersMap Reference an already populated HashMap of JniMarker objects + * @param newParentTracefile Reference to the parent JniTracefile of this JniEvent + * + * @exception JniException + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Pointer + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniMarker + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniTracefile + */ + public JniEvent(Jni_C_Pointer newEventPtr, HashMap newMarkersMap, JniTracefile newParentTracefile) throws JniException { + + // Basic test to make sure we didn't get null/empty value + if ((newEventPtr.getPointer() == NULL) + || (newMarkersMap == null) + || (newMarkersMap.size() == 0) + || (newParentTracefile == null)) { + throw new JniEventException("Null or empty value passed to constructor, object is invalid! (JniEvent)"); + } + + thisEventPtr = newEventPtr; + tracefilePtr = newParentTracefile.getTracefilePtr(); + markersMap = newMarkersMap; + parentTracefile = newParentTracefile; + + eventTime = new JniTime(); + + // Try to move to the first event + // If the event is Out of Range (ERANGE) at the first read, + // this event type will never be usable. + // In that case, throw JniNoSuchEventException to warn the tracefile. + eventState = positionToFirstEvent(); + if (eventState != EOK) { + throw new JniNoSuchEventException("Object not populated, unusable. There is probably no event of that type in the trace. (JniEvent)"); + } + else { + populateEventInformation(); + } + } + + /** + * Move to the next event and populate the java object with LttEvent structure.

+ * + * If the move fails, the event will not get populated and the last event data will still be available. + * + * @return LTT read status, as defined in Jni_C_Common. + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Common + */ + public int readNextEvent() { + // Ask Ltt to read the next event for this particular tracefile + eventState = ltt_readNextEvent( tracefilePtr.getPointer() ); + // If the event state is sane populate it + if (eventState == EOK) { + populateEventInformation(); + } + + return eventState; + } + + /** + * Seek to a certain time.

+ * + * Seek to a certain time and read event at this exact time or the next one if there is no event there.

+ * + * Note that this function can seek in an invalid position if the timestamp is after the last event.
+ * In that case, a seek back would be required to get back to a consistent state.

+ * + * If the seek fails, the event will not get populated and the last event data will still be available.

+ * + * @return LTT read status, as defined in Jni_C_Common + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Common + */ + public int seekToTime(JniTime seekTime) { + // Ask Ltt to read the next event for this particular tracefile + eventState = ltt_seekEvent(tracefilePtr.getPointer(), seekTime); + + // If the event state is sane populate it + if (eventState == EOK) { + populateEventInformation(); + } + + return eventState; + } + + /** + * Try to seek to a certain time and seek back if it failed.

+ * + * Seek to a certain time and read event at this exact time or the next one if there is no event there.

+ * + * If the seek fails, we will seek back to the previous position, so the event will stay in a consistent state.

+ * + * @return LTT read status, as defined in Jni_C_Common + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Common + */ + public int seekOrFallBack(JniTime seekTime) { + // Save the old time + JniTime oldTime = new JniTime(eventTime); + + // Call seek to move ahead + // Save the state for the return (eventState will be modified if we seek back) + int returnState = seekToTime(seekTime); + + // If the event state is sane populate it + if (returnState == EOK) { + populateEventInformation(); + } + else { + seekToTime(oldTime); + } + + return returnState; + } + + /** + * Position on the first event in the tracefile.

+ * + * The function return the read status after the first event.

+ * + * A status different of EOK probably means there is no event associated to this tracefile. + * + * @return LTT read status, as defined in Jni_C_Common + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Common + */ + public int positionToFirstEvent() { + eventState = ltt_positionToFirstEvent(tracefilePtr.getPointer()); + + return eventState; + } + + /** + * Obtain a marker associated with this tracefile's event. + * + * @return Reference to the marker for this tracefile's event or null if none. + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniMarker + */ + public JniMarker requestEventMarker() { + return markersMap.get(getEventMarkerId()); + } + + /** + * Obtain the raw data of a LttEvent object.

+ * + * The data will be in raw C bytes, not java bytes.
+ * Note : This function is mostly untested and provided "as is". + * + * @return Bytes array of raw data (contain raw C bytes). + */ + public byte[] requestEventContent() { + byte dataContent[] = new byte[(int) getEventDataSize()]; + + ltt_getDataContent(thisEventPtr.getPointer(), getEventDataSize(), dataContent); + + return dataContent; + } + + /** + * Obtain an event source.

+ * + * This is not implemented yet and will always return "Kernel core" for now. + * + * @return Reference to the JniMarker object for this event or null if none. + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniMarker + */ + public String requestEventSource() { + // *** TODO *** + // No "Source" of event exists in Ltt so far + // It would be a good addition to have a way to detect where an event come + // from, like "kernel" or "userspace" + // + return "Kernel Core"; + } + + /** + * Parse a particular field in the event payload, identified by its id (position).

+ * + * Note : Position are relative to an event marker (i.e. requestEventMarker().getMarkerFieldsArrayList() ) + * + * @param fieldId Position of the field to parse. + * + * @return Object that contain the parsed payload + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniParser + */ + public Object parseFieldById(int fieldId) { + return JniParser.parseField(this, fieldId); + } + + /** + * Parse a particular field in the event payload, identified by its name.

+ * + * Note : Name are relative to an event marker (i.e. requestEventMarker().getMarkerFieldsHashMap() ) + * + * @param fieldName Position of the field to parse. + * + * @return Object that contain the parsed payload + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniParser + */ + public Object parseFieldByName(String fieldName) { + return JniParser.parseField(this, fieldName); + } + + /** + * Method to parse all the event payload.

+ * + * @return HashMap which is the parsedContent objects and their name as key. + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniParser + */ + public HashMap parseAllFields() { + return JniParser.parseAllFields(this); + } + + /* + * This function populates the event data with data from LTT + * + * NOTE : To get better performance, we copy very few data into memory here + * + */ + private void populateEventInformation() { + // We need to save the time, as it is not a primitive (can't be dynamically called in getter) + eventTime.setTime(ltt_getNanosencondsTime(thisEventPtr.getPointer() )); + } + + public JniTime getEventTime() { + return eventTime; + } + + // *** To get better performance, all getter belows call LTT directly **** + // That way, we can avoid copying data into memory + public int getEventMarkerId() { + return ltt_getEventMarkerId(thisEventPtr.getPointer()); + } + + public long getEventDataSize() { + return ltt_getEventDataSize(thisEventPtr.getPointer()); + } + + public HashMap getMarkersMap() { + return markersMap; + } + + /** + * Pointer to the parent LTTTracefile C structure.
+ *
+ * The pointer should only be used INTERNALY, do not use unless you + * know what you are doing. + * + * @return The actual (long converted) pointer or NULL. + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Pointer + */ + public Jni_C_Pointer getTracefilePtr() { + return new Jni_C_Pointer( ltt_getTracefilePtr(thisEventPtr.getPointer()) ); + } + + /** + * Pointer to the LttEvent C structure.
+ *
+ * The pointer should only be used INTERNALY, do not use unless you + * know what you are doing. + * + * @return The actual (long converted) pointer or NULL. + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Pointer + */ + public Jni_C_Pointer getEventPtr() { + return thisEventPtr; + } + + public int getEventState() { + return eventState; + } + + /** + * Getter to the parent tracefile for this event. + * + * @return The parent tracefile + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniTracefile + */ + public JniTracefile getParentTracefile() { + return parentTracefile; + } + + /** + * Compare fonction for JNIEvent.

+ *

+ * This will compare the current JNIEvent with a passed one by timestamp AND tracefile ("type").
+ * If both are equal but type differs, current event is considered to be older (-1 returned). + * + * @return -1 if given event happens before, 0 if equal, 1 if passed event happens after. + */ + public int compareTo(JniEvent rightEvent ){ + + // Note : this = left hand operand + + // By default, we consider the current event to be older. + int eventComparaison = -1; + + // Test against null before performing anything + if ( rightEvent != null ) { + // Compare the timestamp first + eventComparaison = this.getEventTime().compareTo( rightEvent.getEventTime() ); + + // If timestamp is equal, compare the parent tracefile ("event type") + if ( (eventComparaison == 0) && ( !this.parentTracefile.equals(rightEvent.parentTracefile)) ) { + eventComparaison = 1; + } + } + return eventComparaison; + } + + /** + * Print information for this event. + * Intended to debug
+ * + * This function will call Ltt to print, so information printed will be + * the one from the C structure, not the one populated in java.

+ * + * This function will not throw but will complain loudly if pointer is NULL. + */ + public void printEventInformation() { + + // If null pointer, print a warning! + if (thisEventPtr.getPointer() == NULL) { + printlnC("Pointer is NULL, cannot print. (printEventInformation)"); + } + else { + ltt_printEvent(thisEventPtr.getPointer()); + } + } + + /** + * toString() method. + * Intended to debug.

+ * + * @return Attributes of the object concatenated in String + */ + @Override + public String toString() { + String returnData = ""; + + returnData += "tracefilePtr : " + tracefilePtr + "\n"; + returnData += "eventMarkerId : " + getEventMarkerId() + "\n"; + returnData += "eventTime : " + eventTime.getReferenceToString() + "\n"; + returnData += " seconds : " + eventTime.getSeconds() + "\n"; + returnData += " nanoSeconds : " + eventTime.getNanoSeconds() + "\n"; + returnData += "eventDataSize : " + getEventDataSize() + "\n"; + returnData += "markersMap : " + markersMap.keySet() + "\n"; // Hack to avoid ending up with markersMap.toString() + + return returnData; + } +} diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniException.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniException.java new file mode 100644 index 0000000000..7f8adf6e0d --- /dev/null +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniException.java @@ -0,0 +1,169 @@ +package org.eclipse.linuxtools.lttng.jni; +/******************************************************************************* + * Copyright (c) 2009 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: + * William Bourque (wbourque@gmail.com) - Initial API and implementation + *******************************************************************************/ + + +/** + * JniException + *

+ * Super class for JNI exception. + */ +public class JniException extends Exception { + private static final long serialVersionUID = -6620784221853154537L; + + JniException(String errMsg) { + super(errMsg); + } +} + +/** + * JniTraceException + *

+ * Basic exception class for the JniTrace class + */ +class JniTraceException extends JniException { + private static final long serialVersionUID = -6873007333085268143L; + + JniTraceException(String errMsg) { + super(errMsg); + } +} + +/** + * JniOpenTraceFailedException + *

+ * Sub-exception class type for JniTraceException + * This type will get thrown when a trace fail to open + * Most likely to be caused by a bad tracepath + */ +class JniOpenTraceFailedException extends JniTraceException { + private static final long serialVersionUID = 877769692366394895L; + + JniOpenTraceFailedException(String errMsg) { + super(errMsg); + } +} + +/** + * JniNoNextEventInTraceException + *

+ * Sub-exception class type for JniTraceException + * This type will get thrown when we can't find any "next" event + * This should usually mean there is no more event in the trace + + */ +class JniNoNextEventInTraceException extends JniTraceException { + private static final long serialVersionUID = -2887528566100063849L; + + JniNoNextEventInTraceException(String errMsg) { + super(errMsg); + } +} + +// +/** + * JniTracefileException + *

+ * Basic exception class for the JniTracefile class + */ +class JniTracefileException extends JniException { + private static final long serialVersionUID = 5081317864491800084L; + + JniTracefileException(String errMsg) { + super(errMsg); + } +} + +/** + * JniTracefileWithoutEventException + *

+ * Sub-exception class type for JniTracefileException + * This type will get thrown when a trace file contain no readable events + * The proper course of action would usually be to ignore this useless trace file + */ +class JniTracefileWithoutEventException extends JniTracefileException { + private static final long serialVersionUID = -8183967479236071261L; + + JniTracefileWithoutEventException(String errMsg) { + super(errMsg); + } +} + +/** + * JniEventException + *

+ * Basic exception class for the JniEvent class + */ +class JniEventException extends JniException { + private static final long serialVersionUID = -5891749130387304519L; + + JniEventException(String errMsg) { + super(errMsg); + } +} + +/** + * JniNoSuchEventException + *

+ * Sub-exception type for the JniEventException type + * This exception type will get thrown when an event is unavailable + * This might happen at construction because some events type are not present in + * the trace + */ +class JniNoSuchEventException extends JniEventException { + private static final long serialVersionUID = -4379712949891538051L; + + JniNoSuchEventException(String errMsg) { + super(errMsg); + } +} + +/** + * JniEventOutOfRangeException + *

+ * Sub-exception type for the JniEventException type + * This exception type will get thrown when there is no more event of this type + * available + */ +class JniEventOutOfRangeException extends JniEventException { + private static final long serialVersionUID = -4645877232795324541L; + + JniEventOutOfRangeException(String errMsg) { + super(errMsg); + } +} + +/** + * JniMarkerException + *

+ * Basic Exception class for the JniMarker class + */ +class JniMarkerException extends JniException { + private static final long serialVersionUID = -4694173610721983794L; + + JniMarkerException(String errMsg) { + super(errMsg); + } +} + +/** + * JniMarkerFieldException + *

+ * Basic Exception class for the JniMarkerField class + */ +class JniMarkerFieldException extends JniException { + private static final long serialVersionUID = 6066381741374806879L; + + JniMarkerFieldException(String errMsg) { + super(errMsg); + } +} diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniMarker.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniMarker.java new file mode 100644 index 0000000000..3990bfc15c --- /dev/null +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniMarker.java @@ -0,0 +1,235 @@ +package org.eclipse.linuxtools.lttng.jni; +/******************************************************************************* + * Copyright (c) 2009 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: + * William Bourque (wbourque@gmail.com) - Initial API and implementation + *******************************************************************************/ + + +import java.util.ArrayList; +import java.util.HashMap; + +/** + * JniMarker

+ * + * A JniMarker contain information how to interpret the unparsed content (payload) of an event.
+ * Each JniMarker contains several MarkerFields for each fields in the event's payload. + * + * Provides access to the marker_info C structure (from LTT) in java. + * + * Most important fields in the JniMarker are : + *

    + *
  • the name of the marker in String + *
  • an overview of the marker format (in C style printf format) + *
  • a reference to an ArrayList that contains MarkerFields object of this JniMarker + *
+ */ +public final class JniMarker extends Jni_C_Common +{ + // Internal C pointer of the JniEvent used in LTT + private Jni_C_Pointer thisMarkerPtr = new Jni_C_Pointer(); + + private String name = ""; + private String formatOverview = ""; + + // These two contains hold references to the same MarkerField object + // The ArrayList can be used to efficiently find a field by its position + // The HashMap can be used to find a field by its name + private HashMap markerFieldsHashMap = null; + private ArrayList markerFieldsArrayList = null; + + // Native access method + private native String ltt_getName(long markerPtr); + private native String ltt_getFormatOverview(long markerPtr); + @SuppressWarnings("unused") + private native long ltt_getSize(long markerPtr); + @SuppressWarnings("unused") + private native short ltt_getLargestAlign(long markerPtr); + @SuppressWarnings("unused") + private native short ltt_getIntSize(long markerPtr); + @SuppressWarnings("unused") + private native short ltt_getLongSize(long markerPtr); + @SuppressWarnings("unused") + private native short ltt_getPointerSize(long markerPtr); + @SuppressWarnings("unused") + private native short ltt_getSize_tSize(long markerPtr); + private native void ltt_getAllMarkerFields(long tracePtr); + @SuppressWarnings("unused") + private native short ltt_getAlignement(long markerPtr); + @SuppressWarnings("unused") + private native long ltt_getNextMarkerPtr(long markerPtr); + + // Debug native function, ask LTT to print marker structure + private native void ltt_printMarker(long markerPtr); + + static { + System.loadLibrary("lttvtraceread"); + } + + /* + * Default constructor is forbidden + */ + @SuppressWarnings("unused") + private JniMarker() { + } + + /** + * Copy constructor.

+ * + * @param oldMarker Reference to the JniMarker you want to copy. + */ + public JniMarker(JniMarker oldMarker) { + thisMarkerPtr = oldMarker.thisMarkerPtr; + name = oldMarker.name; + formatOverview = oldMarker.formatOverview; + markerFieldsHashMap = oldMarker.markerFieldsHashMap; + markerFieldsArrayList = oldMarker.markerFieldsArrayList; + + } + + /** + * Constructor, using pointer.

+ * + * @param newMarkerPtr Pointer to a C marker_info structure + * + * @exception JniException + */ + public JniMarker(Jni_C_Pointer newMarkerPtr) throws JniException { + thisMarkerPtr = newMarkerPtr; + markerFieldsArrayList = new ArrayList(); + markerFieldsHashMap = new HashMap(); + + // Populate the marker + populateMarkerInformation(); + } + + + /* + * This function populates the marker data with data from LTT + * + */ + private void populateMarkerInformation() throws JniException { + if (thisMarkerPtr.getPointer() == NULL) { + throw new JniMarkerException("Pointer is NULL, trace closed? (populateMarkerInformatOverviewion)"); + } else { + name = ltt_getName( thisMarkerPtr.getPointer() ); + formatOverview = ltt_getFormatOverview( thisMarkerPtr.getPointer() ); + // To fill the markerFieldArray is a bit different + ltt_getAllMarkerFields( thisMarkerPtr.getPointer() ); + } + } + + /* + * Fills a map of all the JniMarkerField associated with this JniMarker. + * + * Note: This function is called from C and there is no way to propagate + * exception back to the caller without crashing JNI. Therefore, it MUST + * catch all exceptions. + * + * @param markerName Name of the parent marker + * @param markerFieldPtr C Pointer (converted in long) to marker_field C Structure + */ + @SuppressWarnings("unused") + private void addMarkerFieldFromC(String markerFieldName, long markerFieldPtr) { + // Create a new Jaf_markerField object and insert it in the map + // the maker field fill itself with LTT data while being constructed + try { + JniMarkerField newMarkerField = new JniMarkerField( new Jni_C_Pointer(markerFieldPtr) ); + markerFieldsArrayList.add(newMarkerField); + markerFieldsHashMap.put(markerFieldName, newMarkerField); + + } catch (JniException e) { + printlnC("Failed to add marker field " + markerFieldName + " to marker fields list!(addMarkerFieldFromC)\n\tException raised : " + e.toString() ); + } + } + + // Access to class variable. Most of them doesn't have setter + public String getName() { + return name; + } + + public String getFormatOverview() { + return formatOverview; + } + + public HashMap getMarkerFieldsHashMap() { + return markerFieldsHashMap; + } + + public ArrayList getMarkerFieldsArrayList() { + return markerFieldsArrayList; + } + + /** + * Pointer to the marker_info C structure.

+ * + * The pointer should only be used INTERNALY, do not use unless you + * know what you are doing.

+ * + * @return The actual (long converted) pointer or NULL + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Pointer + */ + public Jni_C_Pointer getMarkerPtr() { + return thisMarkerPtr; + } + + + /** + * Print information for this JniMarker. + * Intended to debug
+ * + * This function will call Ltt to print, so information printed will be the one from + * the C structure, not the one populated in java.

+ * + * This function will not throw but will complain loudly if pointer is NULL + */ + public void printMarkerInformation() { + + // If null pointer, print a warning! + if (thisMarkerPtr.getPointer() == NULL) { + printlnC("Pointer is NULL, cannot print. (printMarkerInformation)"); + } else { + ltt_printMarker(thisMarkerPtr.getPointer()); + } + } + + /** + * Print information for ALL marker fields for this marker. + * Intended to debug
+ * + * This function will call Ltt to print, so information printed will be the one from + * the C structure, not the one populated in java. + */ + public void printAllMarkerFieldsInformation() { + Object[] allMarkersField = markerFieldsArrayList.toArray(); + + for (int pos = 0; pos < allMarkersField.length; pos++) { + printlnC(allMarkersField[pos].toString()); + } + } + + /** + * toString() method. + * Intended to debug
+ * + * @return Attributes of the object concatenated in String + */ + @Override + public String toString() { + String returnData = ""; + + returnData += "name : " + name + "\n"; + returnData += "formatOverview : " + formatOverview + "\n"; + returnData += "markerFieldArrayList : " + markerFieldsArrayList.toArray() + "\n"; + + return returnData; + } + +} diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniMarkerField.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniMarkerField.java new file mode 100644 index 0000000000..de2422f2ab --- /dev/null +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniMarkerField.java @@ -0,0 +1,158 @@ +package org.eclipse.linuxtools.lttng.jni; +/******************************************************************************* + * Copyright (c) 2009 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: + * William Bourque (wbourque@gmail.com) - Initial API and implementation + *******************************************************************************/ + + +/** + * JniMarkerField

+ * A JniMarkerField is one of the field of the unparsed content (payload) of an event.

+ * + * Provides access to the marker_field C structure (from LTT) in java.

+ * + * Most important attributes in the JniMarkerField are : + *

    + *
  • the name (field) of in String + *
  • the marker field format (in C style printf format) + *
+ */ +public final class JniMarkerField extends Jni_C_Common +{ + // Internal C pointer of the JniEvent used in LTT + private Jni_C_Pointer thisMarkerFieldPtr = new Jni_C_Pointer(); + + private String field = ""; + private String format = ""; + + // Native access method + private native String ltt_getField(long markerFieldPtr); + @SuppressWarnings("unused") + private native int ltt_getType(long markerFieldPtr); + @SuppressWarnings("unused") + private native long ltt_getOffset(long markerFieldPtr); + @SuppressWarnings("unused") + private native long ltt_getSize(long markerFieldPtr); + @SuppressWarnings("unused") + private native long ltt_getAlignment(long markerFieldPtr); + @SuppressWarnings("unused") + private native long ltt_getAttributes(long markerFieldPtr); + @SuppressWarnings("unused") + private native int ltt_getStatic_offset(long markerFieldPtr); + private native String ltt_getFormat(long markerFieldPtr); + + // Debug native function, ask LTT to print marker structure + private native void ltt_printMarkerField(long markerFieldPtr); + + static { + System.loadLibrary("lttvtraceread"); + } + + /* + * Default constructor is forbidden + */ + @SuppressWarnings("unused") + private JniMarkerField() { + } + + /** + * Copy constructor.

+ * + * @param oldMarkerField Reference to the JniMarkerField you want to copy. + */ + public JniMarkerField(JniMarkerField oldMarkerField) { + thisMarkerFieldPtr = oldMarkerField.getMarkerFieldPtr(); + field = oldMarkerField.getField(); + format = oldMarkerField.getFormat(); + } + + /** + * Constructor, using pointer.

+ * + * @param newMarkerFieldPtr Pointer to a C marker_field structure + * + * @exception JniException + */ + public JniMarkerField(Jni_C_Pointer newMarkerFieldPtr) throws JniException { + thisMarkerFieldPtr = newMarkerFieldPtr; + + // Populate the marker field + populateMarkerFieldInformation(); + } + + /* + * This function populates the marker field data with data from LTT + * + */ + private void populateMarkerFieldInformation() throws JniException { + if (thisMarkerFieldPtr.getPointer() == NULL) { + throw new JniMarkerFieldException( + "Pointer is NULL, trace closed? (populateMarkerInformation)"); + } else { + field = ltt_getField(thisMarkerFieldPtr.getPointer()); + format = ltt_getFormat(thisMarkerFieldPtr.getPointer()); + } + } + + public String getField() { + return field; + } + + public String getFormat() { + return format; + } + + /** + * Pointer to the marker_field C structure.

+ * + * The pointer should only be used INTERNALY, do not use these unless you + * know what you are doing.

+ * + * @return The actual (long converted) pointer or NULL + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Pointer + */ + public Jni_C_Pointer getMarkerFieldPtr() { + return thisMarkerFieldPtr; + } + + /** + * Print information for this event. Intended to debug
+ * + * This function will call Ltt to print, so information printed will be the one from + * the C structure, not the one populated in java.

+ * + * This function will not throw but will complain loudly if pointer is NULL + */ + public void printMarkerFieldInformation() { + + // If null pointer, print a warning! + if (thisMarkerFieldPtr.getPointer() == NULL) { + printlnC("Pointer is NULL, cannot print. (printMarkerFieldInformation)"); + } else { + ltt_printMarkerField(thisMarkerFieldPtr.getPointer()); + } + } + + /** + * toString() method. + * Intended to debug
+ * + * @return Attributes of the object concatenated in String + */ + @Override + public String toString() { + String returnData = ""; + returnData += "field : " + field + "\n"; + returnData += "format : " + format + "\n"; + + return returnData; + } +} diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniParser.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniParser.java new file mode 100644 index 0000000000..4f1ee63f23 --- /dev/null +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniParser.java @@ -0,0 +1,304 @@ +package org.eclipse.linuxtools.lttng.jni; +/******************************************************************************* + * Copyright (c) 2009 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: + * William Bourque (wbourque@gmail.com) - Initial API and implementation + *******************************************************************************/ + + +import java.util.HashMap; +import java.util.Iterator; + +/** + * JniParser

+ * + * JniParser is used to parse an event payload into something usable.

+ * + * All methods are static, the parser shouldn't be instantiated. + */ +public class JniParser extends Jni_C_Common +{ + private static native void ltt_getParsedData(ParsedObjectContent parseddata, long eventPtr, long markerFieldPtr); + + static { + System.loadLibrary("lttvtraceread"); + } + + // *** HACK *** + // We cannot use "Object" directly as java does not support swapping primitive value + // We either need to create a new object type or to use a "non-primitive" type that have "Setter()" functions + // Another (ugly) hack would be to pass an array to modify the reference's reference. + // *** + private static ParsedObjectContent parsedData = new ParsedObjectContent(); + + /* + * Default constructor is forbidden + */ + private JniParser() { + } + + + /** + * Method to parse a single field identified by its id.

+ * + * All parsing will be done on C side as we need LTT functions. + * + * @param eventToParse The jni event we want to parse. + * @param fieldPosition The position (or id) of the field we want to parse + * + * @return An Object that contain the JniEvent payload parsed by the C, or null, if if was impossible to parse (i.e., wrong position) + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniEvent + */ + static public Object parseField(JniEvent eventToParse, int fieldPosition) { + + // Sanity check + if ( (fieldPosition < 0) || ( fieldPosition >= eventToParse.requestEventMarker().getMarkerFieldsArrayList().size() ) ){ + return null; + } + + JniMarkerField tmpField = eventToParse.requestEventMarker().getMarkerFieldsArrayList().get(fieldPosition); + + // Call the parsing function in C. The result will be put in parsedData object + ltt_getParsedData(parsedData, eventToParse.getEventPtr().getPointer(), tmpField.getMarkerFieldPtr().getPointer() ); + + return parsedData.getData(); + } + + + /** + * Method to parse a single field identified by its name.

+ * + * All parsing will be done on C side as we need LTT functions. + * + * @param eventToParse The jni event we want to parse. + * @param fieldName The name of the field we want to parse. + * + * @return An Object that contain the JniEvent payload parsed by the C, or null, if if was impossible to parse (i.e., wrong position) + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniEvent + */ + static public Object parseField(JniEvent eventToParse, String fieldName) { + + JniMarkerField tmpField = eventToParse.requestEventMarker().getMarkerFieldsHashMap().get(fieldName); + + // return immediately if there is no field by that name + if ( tmpField == null ) { + return null; + } + + ltt_getParsedData(parsedData, eventToParse.getEventPtr().getPointer(), tmpField.getMarkerFieldPtr().getPointer() ); + + return parsedData.getData(); + } + + + + /** + * Method to parse all fields at once.

+ * + * All parsing will be done on C side as we need LTT functions. + * + * @param eventToParse The jni event we want to parse. + * @return An HashMap of Object that contain the is the JniEvent's payload parsed by the C + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniEvent + */ + static public HashMap parseAllFields(JniEvent eventToParse) { + HashMap markerFieldData = eventToParse.requestEventMarker().getMarkerFieldsHashMap(); + + // This hashmap will contain the parsed content. + // ParsedContent is a local class defined at the end of this file + + // *** HACK *** + // We want (need?) the map that contain the parsed data to be in the same order as markerField map + // The "instinctive way" would be to use : + // HashMap parsedDataMap = new HashMap(nbMarkerField); + // + // However, we cannot ensure that the newly created hashmap will use the same order. + // The hard way would be to override the default hash function for both hashmap + // However, this is way easier to abuse the fact that both hashmap are of type + // Therefore we can abuse the java-cast with clone() : + // HashMap parsedDataMap = (HashMap)markerFieldData.clone(); + // Or even safer, use HashMap constructor to do so : + HashMap parsedDataMap = new HashMap(markerFieldData); + + String newKey = null; + JniMarkerField newMarkerField = null; + Iterator iterator = markerFieldData.keySet().iterator(); + + while ( iterator.hasNext() ) { + newKey = iterator.next(); + newMarkerField = markerFieldData.get(newKey); + // Call the C to parse the data + ltt_getParsedData(parsedData, eventToParse.getEventPtr().getPointer(), newMarkerField.getMarkerFieldPtr().getPointer() ); + // Save the result into the HashMap + parsedDataMap.put(newMarkerField.getField(), parsedData.getData() ); + } + + return parsedDataMap; + } + + + /* + * Add a parsed String value to the Array
+ *
+ * Note : this function will be called from the C side. + * Note2: contentHolder is of type "Object" instead of "ParsedObjectContent" to be able to use the most generic function signature on the C side. + * its goal is to give a generic interface to people that would like to use the JNI library + * + * @param parsedArray Array where to store the value + * @param fieldName The name of the parsed field + * @param stringToAdd The parsed data to add + * @param formatToAdd The format of the raw data + */ + @SuppressWarnings("unused") + static private void addStringToParsingFromC(Object contentHolder, String stringToAdd) { + ((ParsedObjectContent)contentHolder).setData( stringToAdd); + } + + /* + * Add a parsed 64 bits Pointer value to the Array
+ *
+ * Note : this function will be called from the C side. + * Note2: contentHolder is of type "Object" instead of "ParsedObjectContent" to be able to use the most generic function signature on the C side. + * its goal is to give a generic interface to people that would like to use the JNI library + * + * @param contentHolder Object where to store the parsed value + * @param fieldName The name of the parsed field + * @param pointerToAdd The parsed data to add (in 64 bits long!) + * @param formatToAdd The format of the raw data + */ + @SuppressWarnings("unused") + static private void addLongPointerToParsingFromC(Object contentHolder, long pointerToAdd) { + ((ParsedObjectContent)contentHolder).setData( new Jni_C_Pointer((long) pointerToAdd)); + } + + /* + * Add a parsed 32 bits Pointer value to the Array
+ *
+ * Note : this function will be called from the C side. + * Note2: contentHolder is of type "Object" instead of "ParsedObjectContent" to be able to use the most generic function signature on the C side. + * its goal is to give a generic interface to people that would like to use the JNI library + * + * @param contentHolder Object where to store the parsed value + * @param fieldName The name of the parsed field + * @param pointerToAdd The parsed data to add (converted in 64 bits long!) + * @param formatToAdd The format of the raw data + */ + @SuppressWarnings("unused") + static private void addIntPointerToParsingFromC(Object contentHolder, long pointerToAdd) { + ((ParsedObjectContent)contentHolder).setData( new Jni_C_Pointer((int) pointerToAdd)); + } + + /* + * Add a parsed short value to the Array
+ *
+ * Note : this function will be called from the C side. + * Note2: contentHolder is of type "Object" instead of "ParsedObjectContent" to be able to use the most generic function signature on the C side. + * its goal is to give a generic interface to people that would like to use the JNI library + * + * @param contentHolder Object where to store the parsed value + * @param fieldName The name of the parsed field + * @param shortToAdd The parsed data to add + * @param formatToAdd The format of the raw data + */ + @SuppressWarnings("unused") + static private void addShortToParsingFromC(Object contentHolder, short shortToAdd) { + ((ParsedObjectContent)contentHolder).setData( new Short(shortToAdd)); + } + + /* + * Add a parsed integer value to the Array
+ *
+ * Note : this function will be called from the C side. + * Note2: contentHolder is of type "Object" instead of "ParsedObjectContent" to be able to use the most generic function signature on the C side. + * its goal is to give a generic interface to people that would like to use the JNI library + * + * @param contentHolder Object where to store the parsed value + * @param fieldName The name of the parsed field + * @param intToAdd The parsed data to add + * @param formatToAdd The format of the raw data + */ + @SuppressWarnings("unused") + static private void addIntegerToParsingFromC(Object contentHolder, int intToAdd) { + ((ParsedObjectContent)contentHolder).setData( new Integer(intToAdd)); + } + + /* + * Add a parsed long value to the Array
+ *
+ * Note : this function will be called from the C side. + * Note2: contentHolder is of type "Object" instead of "ParsedObjectContent" to be able to use the most generic function signature on the C side. + * its goal is to give a generic interface to people that would like to use the JNI library + * + * @param contentHolder Object where to store the parsed value + * @param fieldName The name of the parsed field + * @param longToAdd The parsed data to add + * @param formatToAdd The format of the raw data + */ + @SuppressWarnings("unused") + static private void addLongToParsingFromC(Object contentHolder, long longToAdd) { + ((ParsedObjectContent)contentHolder).setData( new Long(longToAdd)); + } + + /* + * Add a parsed float value to the Array
+ *
+ * Note : this function will be called from the C side. + * Note2: contentHolder is of type "Object" instead of "ParsedObjectContent" to be able to use the most generic function signature on the C side. + * its goal is to give a generic interface to people that would like to use the JNI library + * + * @param contentHolder Object where to store the parsed value + * @param fieldName The name of the parsed field + * @param floatToAdd The parsed data to add + * @param formatToAdd The format of the raw data + */ + @SuppressWarnings("unused") + static private void addFloatToParsingFromC(Object contentHolder, float floatToAdd) { + ((ParsedObjectContent)contentHolder).setData( new Float(floatToAdd)); + } + + /* + * Add a parsed double value to the Array
+ *
+ * Note : this function will be called from the C side. + * Note2: contentHolder is of type "Object" instead of "ParsedObjectContent" to be able to use the most generic function signature on the C side. + * its goal is to give a generic interface to people that would like to use the JNI library + * + * + * @param contentHolder Object where to store the parsed value + * @param fieldName The name of the parsed field + * @param doubleToAdd The parsed data to add + * @param formatToAdd The format of the raw data + */ + @SuppressWarnings("unused") + static private void addDoubleToParsingFromC(Object contentHolder, double doubleToAdd) { + ((ParsedObjectContent)contentHolder).setData( new Double(doubleToAdd)); + } + +} + +/** + * ParsedObjectContent

+ * + * ParsedObjectContent class. + * Only be used locally in this object to parse event data more efficiently in the C. + */ +class ParsedObjectContent { + private Object parsedData = null; + + public Object getData() { + return parsedData; + } + + public void setData(Object newData) { + parsedData = newData; + } +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniTime.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniTime.java new file mode 100644 index 0000000000..e6d64de9af --- /dev/null +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniTime.java @@ -0,0 +1,178 @@ +package org.eclipse.linuxtools.lttng.jni; +/******************************************************************************* + * Copyright (c) 2009 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: + * William Bourque (wbourque@gmail.com) - Initial API and implementation + *******************************************************************************/ + + +/** + * JniTime + *

+ * Used to store (event, trace, tracefile, ...) timestamp. + * + * Mimic the behavior of the LttTime C structure. + */ +public final class JniTime extends Jni_C_Common implements Comparable +{ + private long time = 0; + + /** + * Default constructor.

+ * + * Note : Time will be set to 0. + * + */ + public JniTime() { + time = 0; + } + + /** + * Copy constructor. + * + * @param oldTime Reference to the JniTime you want to copy. + */ + public JniTime(JniTime oldTime) { + time = oldTime.getTime(); + } + + /** + * Constructor with parameters.

+ * + * "LTT style" constructor with Seconds et Nanoseconds + * + * @param newSec Seconds of the JniTime + * @param newNanoSec Nanoseconds of the JniTime + */ + public JniTime(long newSec, long newNanoSec) { + time = (newSec * NANO) + newNanoSec; + } + + /** + * Constructor with parameters.

+ * + * Usual "nanosecond only" constructor. + * + * @param newNanoSecTime Time in nanoseconds + */ + public JniTime(long newNanoSecTime) { + time = newNanoSecTime; + } + + /** + * Second of the time.

+ * + * Returns seconds, i.e. multiple of 1 000 000, of the stored nanoseconds time. + * + * @return Second of this time. + */ + public long getSeconds() { + return (time / NANO); + } + + /** + * Getter for the nanosecond of the time.

+ * + * Returns nanoseconds part, i.e. modulo of 1 000 000, of the stored nanoseconds time. + * + * @return Nanoseconds of this time + */ + public long getNanoSeconds() { + return time % NANO; + } + + /** + * Full time, in nanoseconds.

+ * + * @return Complete time in nanoseconds + */ + public long getTime() { + return time; + } + + /** + * Changes the current time for this object

+ * + * @param newTime New time to set, in nanoseconds. + */ + public void setTime(long newTime) { + time = newTime; + } + + /* + * Populate this time object + * + * Note: This function is called from C side. + * + * @param newTime The time we want to populate + */ + @SuppressWarnings("unused") + private void setTimeFromC(long newTime) { + time = newTime; + } + + /** + * Comparaison operator smaller or equal than "<=" .

+ * + * @param comparedTime The time we want to compare with this one + * + * @return true if compared time is smaller or equal, false otherwise + */ + public boolean isSmallerOrEqual(JniTime comparedTime) { + + // NOTE : We check <= instead of just < + // This mean the LEFT OPERAND (comparedTime) always prevails + if (this.getTime() <= comparedTime.getTime() ) { + return true; + } + else { + return false; + } + } + + /** + * compareTo operator.

+ * + * @param right The time we want to compare with this one + * + * @return int of value -1, 0 or 1, as the pased argument is bigger, equal or smaller than this time + */ + public int compareTo(JniTime right) { + long leftTime = this.getTime(); + long rightTime = right.getTime(); + + if ( leftTime < rightTime ) { + return -1; + } + else if ( leftTime > rightTime ) { + return 1; + } + else { + return 0; + } + } + + /** + * toString() method. + * Intended to debug

+ * + * NOTE : We output the time in the same format as LTT (seconds and nanosecond separatly) + * + * @return String Attributes of the object concatenated in String + */ + @Override + public String toString() { + String returnData = ""; + + returnData += "seconds : " + this.getSeconds() + "\n"; + returnData += "nanoSeconds : " + this.getNanoSeconds() + "\n"; + + return returnData; + } +} diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniTrace.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniTrace.java new file mode 100644 index 0000000000..113c04168f --- /dev/null +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniTrace.java @@ -0,0 +1,785 @@ +package org.eclipse.linuxtools.lttng.jni; +/******************************************************************************* + * Copyright (c) 2009 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: + * William Bourque (wbourque@gmail.com) - Initial API and implementation + *******************************************************************************/ + + +import java.util.HashMap; +import java.util.Iterator; +import java.util.PriorityQueue; + +/** + * JniTrace + *

+ * This is the top level class in the JNI. It provides access to the + * LttTrace C structure in java. + *

+ * Most important fields in the JniTrace are : + *

    + *
  • a JniTrace path (a trace directory) + *
  • a HashMap of tracefiles that exists in this trace + *
+ */ +public class JniTrace extends Jni_C_Common { + + private final static boolean DEFAULT_LTT_DEBUG = false; + + // Internal C pointer of the JniTrace used in LTT + private Jni_C_Pointer thisTracePtr = new Jni_C_Pointer(); + + // Data we should populate from LTT + // Note that all type have been scaled up as there is no "unsigned" in java + // This might be a problem about "unsigned long" as there is no equivalent + // in java + + private String tracepath = ""; // Path of the trace. Should be a directory (like : /tmp/traceX) + private int cpuNumber = 0; + private long archType = 0; + private long archVariant = 0; + private short archSize = 0; + private short lttMajorVersion = 0; + private short lttMinorVersion = 0; + private short flightRecorder = 0; + private long freqScale = 0; + private long startFreq = 0; + private long startTimestampCurrentCounter = 0; + private long startMonotonic = 0; + private JniTime startTimeNoAdjustement = null; + private JniTime startTime = null; + private JniTime endTime = null; + + // This Map holds a reference to the tracefiles owned by this trace + private HashMap tracefilesMap = null; + // The priority queue (similar to heap) hold events + private PriorityQueue eventsHeap = null; + + // This variable will hold the content of the "last" event we read + private JniEvent currentEvent = null; + + // Should we print debug in the C library or not? + private boolean printLttDebug = DEFAULT_LTT_DEBUG; + + // Open/close native functions + private native long ltt_openTrace(String pathname, boolean printDebug); + private native void ltt_closeTrace(long tracePtr); + + // Native access functions + private native String ltt_getTracepath(long tracePtr); + private native int ltt_getCpuNumber(long tracePtr); + private native long ltt_getArchType(long tracePtr); + private native long ltt_getArchVariant(long tracePtr); + private native short ltt_getArchSize(long tracePtr); + private native short ltt_getLttMajorVersion(long tracePtr); + private native short ltt_getLttMinorVersion(long tracePtr); + private native short ltt_getFlightRecorder(long tracePtr); + private native long ltt_getFreqScale(long tracePtr); + private native long ltt_getStartFreq(long tracePtr); + private native long ltt_getStartTimestampCurrentCounter(long tracePtr); + private native long ltt_getStartMonotonic(long tracePtr); + + // Native function to fill out startTime + private native void ltt_feedStartTime(long tracePtr, JniTime startTime); + + // Native function to fill out startTimeFromTimestampCurrentCounter + private native void ltt_feedStartTimeFromTimestampCurrentCounter(long tracePtr, JniTime startTime); + + // Native function to fill out tracefilesMap + private native void ltt_feedAllTracefiles(long tracePtr); + + // Native function to fill out the start and end time of the trace + private native void ltt_feedTracefileTimeRange(long tracePtr, JniTime startTime, JniTime endTime); + + // Debug native function, ask LTT to print trace structure + private native void ltt_printTrace(long tracePtr); + + static { + System.loadLibrary("lttvtraceread"); + } + + /* + * Default constructor is forbidden + */ + @SuppressWarnings("unused") + private JniTrace() { + } + + /** + * Constructor that takes a tracepath parameter.

+ * + * This constructor also opens the trace. + * + * @param newpath The directory of the trace to be opened + * @param newPrintDebug Should the debug information be printed in the LTT C library + * + * @exception JniException + */ + public JniTrace(String newpath, boolean newPrintDebug) throws JniException { + tracepath = newpath; + thisTracePtr = new Jni_C_Pointer(); + printLttDebug = newPrintDebug; + + openTrace(newpath); + } + + /** + * Copy constructor. + * + * @param oldTrace A reference to the JniTrace to copy. + */ + public JniTrace(JniTrace oldTrace) { + thisTracePtr = oldTrace.thisTracePtr; + + tracepath = oldTrace.tracepath; + cpuNumber = oldTrace.cpuNumber; + archType = oldTrace.archType; + archVariant = oldTrace.archVariant; + archSize = oldTrace.archSize; + lttMajorVersion = oldTrace.lttMajorVersion; + lttMinorVersion = oldTrace.lttMinorVersion; + flightRecorder = oldTrace.flightRecorder; + freqScale = oldTrace.freqScale; + startFreq = oldTrace.startFreq; + startTimestampCurrentCounter = oldTrace.startTimestampCurrentCounter; + startMonotonic = oldTrace.startMonotonic; + startTimeNoAdjustement = oldTrace.startTimeNoAdjustement; + startTime = oldTrace.startTime; + endTime = oldTrace.endTime; + + tracefilesMap = new HashMap(oldTrace.tracefilesMap.size()); + tracefilesMap = oldTrace.tracefilesMap; + + eventsHeap = new PriorityQueue( oldTrace.eventsHeap.size()); + eventsHeap = oldTrace.eventsHeap; + + printLttDebug = oldTrace.printLttDebug; + } + + /** + * Constructor, using C pointer.

+ * + * @param newPtr The pointer to an already opened LttTrace C structure. + * @param newPrintDebug Should the debug information be printed in the LTT C library + * + * @exception JniException + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Pointer + */ + public JniTrace(Jni_C_Pointer newPtr, boolean newPrintDebug) throws JniException { + thisTracePtr = newPtr; + printLttDebug = newPrintDebug; + + // Populate our trace + populateTraceInformation(); + } + + /** + * Open an existing trace.

+ * + * The tracepath is a directory and needs to exist, otherwise + * a JafOpenTraceFailedException is throwed. + * + * @param newPath The directory of the trace to be opened + * + * @exception JniOpenTraceFailedException Thrown if the open failed + */ + public void openTrace(String newPath) throws JniException { + // If open is called while a trace is already opened, we will try to close it first + if (thisTracePtr.getPointer() != NULL) { + closeTrace(); + } + + // Set the tracepath and open it + tracepath = newPath; + openTrace(); + } + + /** + * Open an existing trace.

+ * + * The tracepath should have been set already, + * + * @exception JniOpenTraceFailedException Thrown if the open failed + */ + public void openTrace() throws JniException { + + // Raise an exception if the tracepath is empty, otherwise open the trace + if (tracepath == "") { + throw new JniTraceException("Tracepath is not set. (openTrace)"); + } + + // If the file is already opened, close it first + if (thisTracePtr.getPointer() != NULL) { + closeTrace(); + } + + // Call the LTT to open the trace + long newPtr = ltt_openTrace(tracepath, printLttDebug); + if (newPtr == NULL) { + throw new JniOpenTraceFailedException("Error while opening trace. Is the tracepath correct? (openTrace)"); + } + + // This is OUR pointer + thisTracePtr = new Jni_C_Pointer(newPtr); + + // Populate the trace with LTT information + populateTraceInformation(); + } + + /** + * Close a trace.

+ * + * If the trace is already closed, will silently do nothing. + */ + public void closeTrace() { + if (thisTracePtr.getPointer() != NULL) { + ltt_closeTrace(thisTracePtr.getPointer()); + thisTracePtr = new Jni_C_Pointer(NULL); + + // Clear the tracefile map + tracefilesMap.clear(); + tracefilesMap = null; + + // Clear the eventsHeap and make it points to null + eventsHeap.clear(); + eventsHeap = null; + + // Ask the garbage collector to make a little pass here, as we could + // be left with 100's of unreferenced objects + System.gc(); + } + } + + /* + * This function populates the trace data with data from LTT + * + * @throws JniException + */ + private void populateTraceInformation() throws JniException { + if (thisTracePtr.getPointer() == NULL) { + throw new JniTraceException("Pointer is NULL, trace not opened/already closed? (populateTraceInformation)"); + } + + // Populate from the LTT library + tracepath = ltt_getTracepath( thisTracePtr.getPointer() ); + cpuNumber = ltt_getCpuNumber( thisTracePtr.getPointer() ); + archType = ltt_getArchType( thisTracePtr.getPointer() ); + archVariant = ltt_getArchVariant( thisTracePtr.getPointer() ); + archSize = ltt_getArchSize( thisTracePtr.getPointer() ); + lttMajorVersion = ltt_getLttMajorVersion( thisTracePtr.getPointer() ); + lttMinorVersion = ltt_getLttMinorVersion( thisTracePtr.getPointer() ); + flightRecorder = ltt_getFlightRecorder( thisTracePtr.getPointer() ); + freqScale = ltt_getFreqScale( thisTracePtr.getPointer() ); + startFreq = ltt_getStartFreq( thisTracePtr.getPointer() ); + startTimestampCurrentCounter = ltt_getStartTimestampCurrentCounter( thisTracePtr.getPointer() ); + startMonotonic = ltt_getStartMonotonic( thisTracePtr.getPointer() ); + + // Creation of time is a bit different, we need to pass the object reference to C + // + // *** NOTE : LTTv consider "raw startTime" (time without any frequency adjustement) to be default startTime + // So "startTimeNoAdjustement" is obtain throught "ltt_feedStartTime()" and + // "startTime" is obtained from ltt_feedStartTimeFromTimestampCurrentCounter() + startTimeNoAdjustement = new JniTime(); + ltt_feedStartTime( thisTracePtr.getPointer(), startTimeNoAdjustement ); + + startTime = new JniTime(); + ltt_feedStartTimeFromTimestampCurrentCounter( thisTracePtr.getPointer(), startTime ); + + // Call the fill up function for the tracefiles map + if ( tracefilesMap== null ) { + tracefilesMap = new HashMap(); + } + ltt_feedAllTracefiles( thisTracePtr.getPointer() ); + + // Now, obtain the trace "endTime" + // Note that we discard "startTime" right away, as we already have it + endTime = new JniTime(); + ltt_feedTracefileTimeRange(thisTracePtr.getPointer(), new JniTime(), endTime); + + if (eventsHeap == null) { + eventsHeap = new PriorityQueue(tracefilesMap.size()); + } + + // Populate the heap with events + populateEventHeap(); + } + + /* + * This function populates the event heap with one event from each tracefile + * It should be called after each seek or when the object is constructed + */ + private void populateEventHeap() { + currentEvent = null; + eventsHeap.clear(); + + Object new_key = null; + JniTracefile tmpTracefile = null; + + Iterator iterator = tracefilesMap.keySet().iterator(); + while( iterator.hasNext() ) { + new_key = iterator.next(); + + tmpTracefile = tracefilesMap.get(new_key); + if ( tmpTracefile.getCurrentEvent().getEventState() == EOK ) { + eventsHeap.add( tmpTracefile.getCurrentEvent() ); + } + } + } + + /* + * Fills a map of all the trace files. + * + * Note: This function is called from C and there is no way to propagate + * exception back to the caller without crashing JNI. Therefore, it MUST + * catch all exceptions. + * + * @param tracefileName + * @param tracefilePtr + */ + @SuppressWarnings("unused") + private void addTracefileFromC(String tracefileName, long tracefilePtr) { + + JniTracefile newTracefile = null; + + // Create a new tracefile object and insert it in the map + // the tracefile fill itself with LTT data while being constructed + try { + newTracefile = new JniTracefile( new Jni_C_Pointer(tracefilePtr), this ); + tracefilesMap.put( (tracefileName + newTracefile.getCpuNumber()), newTracefile); + } + catch(JniTracefileWithoutEventException e) { + printlnC("JniTracefile " + tracefileName + " has no event (addTracefileFromC). Ignoring."); + } + catch(Exception e) { + printlnC("Failed to add tracefile " + tracefileName + " to tracefilesMap!(addTracefileFromC)\n\tException raised : " + e.toString() ); + } + } + + /** + * Return the top event in the events stack, determined by timestamp, in the trace (all the tracefiles).

+ * + * Note : If the events were read before, the top event and the event currently loaded (currentEvent) are most likely the same. + * + * @return The top event in the stack or null if no event is available. + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniEvent + */ + public JniEvent findNextEvent() { + return eventsHeap.peek(); + } + + /** + * Return the next event in the events stack, determined by timestamp, in the trace (all the tracefiles).

+ * + * @return The next event in the trace or null if no event is available. + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniEvent + */ + public JniEvent readNextEvent() { + // Get the "next" event on the top of the heap but DO NOT remove it + JniEvent tmpEvent = eventsHeap.peek(); + + // If the event is null, it was the last one in the trace we can leave the function + if (tmpEvent == null) { + return null; + } + + // Otherwise, we need to make sure the timestamp of the event we got is not the same as the last "NextEvent" we requested + // NOTE : JniEvent.compareTo() compare by timestamp AND type, as 2 events of different type could have the same timestamp. + if ( tmpEvent.compareTo(currentEvent) == 0 ) { + // Remove the event on top as it is the same currentEventTimestamp + eventsHeap.poll(); + + // Read the next event for this particular event type + tmpEvent.readNextEvent(); + + // If the event state is sane (not Out of Range), put it back in the heap + if ( tmpEvent.getEventState() == EOK ) { + eventsHeap.add(tmpEvent); + } + + // Pick the top event again + tmpEvent = eventsHeap.peek(); + + // Save the event we just read as the "current event" + currentEvent = tmpEvent; + } + // If the event on top has different timestamp than the currentTimestamp, just save this timestamp as current + else { + currentEvent = tmpEvent; + } + + return tmpEvent; + } + + /** + * Read the next event on a certain tracefile.

+ * + * By calling this function make sure the "global" readNextEvent() stay synchronised. + * Calling readNextEvent() after this function will consider this tracefile moved and is then consistent. + * + * @param targetTracefile The tracefile object to read from + * + * @return The next event in the tracefile or null if no event is available. + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniTracefile + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniEvent + */ + public JniEvent readNextEvent(JniTracefile targetTracefile) { + JniEvent returnedEvent = null; + + // There is 2 special cases where we should read the CURRENT event, not the next one + // 1- The currentEvent is null --> We never read or we just seeked + // 2- The currentEvent is of another type --> We last read on a DIFFERENT tracefile + if ( (currentEvent == null) || + (currentEvent.getParentTracefile().equals(targetTracefile) == false) + ) { + returnedEvent = targetTracefile.getCurrentEvent(); + // Save the event we read + currentEvent = returnedEvent; + } + else { + // Remove from the event related to this tracefile from the event heap, if it exists. + // WARNING : This only safe as long getCurrentEvent() never return "null" in any case. + eventsHeap.remove(targetTracefile.getCurrentEvent() ); + + // If status EOK, we can return the event, otherwise something wrong happen (out of range, read error, etc...) + if ( targetTracefile.readNextEvent() == EOK) { + returnedEvent = targetTracefile.getCurrentEvent(); + // Add back to the heap the read event + eventsHeap.add(returnedEvent); + } + // Save the event we read... + // Note : might be null if the read failed and it's ok + currentEvent = targetTracefile.getCurrentEvent(); + } + + return returnedEvent; + } + + /** + * Seek to a certain time but do not read the next event.

+ * + * This only position the trace, it will not return anything.

+ * + * @param seekTime The time where we want to seek to + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniTime + */ + public void seekToTime(JniTime seekTime) { + + // Invalidate the last read event + currentEvent = null; + + Object tracefile_name = null; + Iterator iterator = tracefilesMap.keySet().iterator(); + + while (iterator.hasNext() ) { + // We seek to the given event for ALL tracefiles + tracefile_name = iterator.next(); + seekToTime(seekTime, tracefilesMap.get(tracefile_name)); + } + + populateEventHeap(); + } + + /** + * Seek to a certain time on a certain tracefile but do not read the next event.

+ * + * This only position the trace, it will not return anything.

+ * + * @param targetTracefile The tracefile object to read from + * @param seekTime The time where we want to seek to + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniTracefile + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniTime + */ + public void seekToTime(JniTime seekTime, JniTracefile targetTracefile) { + // Invalidate the current read event + currentEvent = null; + + // Remove from the event related to this tracefile from the event heap, if it exists. + // WARNING : This is only safe as long getCurrentEvent() never return "null" in any case. + eventsHeap.remove(targetTracefile.getCurrentEvent() ); + + // Perform the actual seek on the tracefile + // Add the event to the heap if it succeed + if ( targetTracefile.seekToTime(seekTime) == EOK) { + // Add back to the heap the read event + eventsHeap.add(targetTracefile.getCurrentEvent()); + } + } + + /** + * Seek to a certain timestamp and read the next event. + *

+ * If no more events are available or an error happen, null will be returned. + * + * @param seekTime The time where we want to seek to. + * + * @return The event just after the seeked time or null if none available. + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniEvent + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniTime + */ + public JniEvent seekAndRead(JniTime seekTime) { + JniEvent returnedEvent = null; + seekToTime(seekTime); + + // The trace should be correctly positionned, let's get the event + returnedEvent = readNextEvent(); + + return returnedEvent; + } + + /** + * Seek to a certain timestamp on a certain tracefile and read the next event.

+ * + * If no more events are available or an error happen, null will be returned. + * + * Calling readNextEvent() after this function will consider this tracefile moved and is then consistent.
+ * + * @param tracefileName The tracefile object to read from + * @param seekTime The time where we want to seek to + * + * @return The event just after the seeked time or null if none available. + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniTracefile + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniTime + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniEvent + */ + public JniEvent seekAndRead(JniTime seekTime, JniTracefile targetTracefile) { + seekToTime(seekTime, targetTracefile); + return readNextEvent(targetTracefile); + } + + /** + * Get a certain tracefile from its given name.

+ * + * @param tracefileName The name of the tracefile. + * + * @return The tracefile found or null if none. + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniTracefile + */ + public JniTracefile requestTracefileByName(String tracefileName) { + return tracefilesMap.get(tracefileName); + } + + /** + * Get a certain event associated to a tracefile from the tracefile name.

+ * + * @param tracefileName The name of the trace file. + * + * @return Event of the tracefile or null if none found. + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniEvent + */ + public JniEvent requestEventByName(String tracefileName) { + JniEvent returnValue = null; + + JniTracefile tmpTracefile = tracefilesMap.get(tracefileName); + + // If the tracefile is found, return the current event + // There should always be an event linked to a tracefile + if (tmpTracefile != null) { + returnValue = tmpTracefile.getCurrentEvent(); + } + + return returnValue; + } + + // Access to class variable. Most of them doesn't have setter + public String getTracepath() { + return tracepath; + } + + public int getCpuNumber() { + return cpuNumber; + } + + public long getArchType() { + return archType; + } + + public long getArchVariant() { + return archVariant; + } + + public short getArchSize() { + return archSize; + } + + public short getLttMajorVersion() { + return lttMajorVersion; + } + + public short getLttMinorVersion() { + return lttMinorVersion; + } + + public short getFlightRecorder() { + return flightRecorder; + } + + public long getFreqScale() { + return freqScale; + } + + public long getStartFreq() { + return startFreq; + } + + public long getStartTimestampCurrentCounter() { + return startTimestampCurrentCounter; + } + + public long getStartMonotonic() { + return startMonotonic; + } + + public JniTime getStartTime() { + return startTime; + } + + public JniTime getEndTime() { + return endTime; + } + + public JniTime getStartTimeNoAdjustement() { + return startTimeNoAdjustement; + } + + public HashMap getTracefilesMap() { + return tracefilesMap; + } + + /** + * The timestamp of the last read event.

+ * + * Note : If no event is available, Long.MAX_VALUE is returned. + * + * @return Time of the last event read + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniTime + */ + public JniTime getCurrentEventTimestamp() { + JniTime returnedTime = null; + + // If no event were read or we reach the last event in the trace, + // currentEvent will be null + if ( currentEvent != null ) { + returnedTime = currentEvent.getEventTime(); + } + else { + returnedTime = new JniTime(Long.MAX_VALUE); + } + return returnedTime; + } + + /** + * Pointer to the LttTrace C structure.

+ * + * The pointer should only be used INTERNALY, do not use unless you + * know what you are doing. + * + * @return The actual (long converted) pointer or NULL. + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Pointer + */ + public Jni_C_Pointer getTracePtr() { + return thisTracePtr; + } + + /** + * Return boolean value saying if the debug is enabled in LTT or not.

+ * + * Note : this need to be set at construction. + * + * @return If the debug is set or not + */ + public boolean isPrintingLttDebug() { + return printLttDebug; + } + + /** + * Print information for all the tracefiles associated with this trace. + * Intended to debug

+ * + * This function will call Ltt to print, so information printed will be the + * one from the C structure, not the one populated in java. + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniTracefile + */ + public void printAllTracefilesInformation() { + JniTracefile tracefile = null; + + Iterator iterator = tracefilesMap.keySet().iterator(); + while (iterator.hasNext()) { + tracefile = tracefilesMap.get(iterator.next()); + tracefile.printTracefileInformation(); + } + } + + /** + * Print information for this trace. + * Intended to debug

+ * + * This function will call Ltt to print, so information printed will be the + * one from the C structure, not the one populated in java.

+ *
+ * This function will not throw but will complain loudly if pointer is NULL + */ + public void printTraceInformation() { + + // If null pointer, print a warning! + if (thisTracePtr.getPointer() == NULL) { + printlnC("Pointer is NULL, cannot print. (printTraceInformation)"); + } + else { + ltt_printTrace( thisTracePtr.getPointer() ); + } + } + + /** + * toString() method. + * Intended to debug
+ * + * @return Attributes of the object concatenated in String + */ + @Override + public String toString() { + String returnData = ""; + returnData += "tracepath : " + tracepath + "\n"; + returnData += "cpuNumber : " + cpuNumber + "\n"; + returnData += "archType : " + archType + "\n"; + returnData += "archVariant : " + archVariant + "\n"; + returnData += "archSize : " + archSize + "\n"; + returnData += "lttMajorVersion : " + lttMajorVersion + "\n"; + returnData += "lttMinorVersion : " + lttMinorVersion + "\n"; + returnData += "flightRecorder : " + flightRecorder + "\n"; + returnData += "freqScale : " + freqScale + "\n"; + returnData += "startFreq : " + startFreq + "\n"; + returnData += "startTimestampCurrentCounter : " + startTimestampCurrentCounter + "\n"; + returnData += "startMonotonic : " + startMonotonic + "\n"; + returnData += "startTimeNoAdjustement : " + startTimeNoAdjustement.getReferenceToString() + "\n"; + returnData += " seconds : " + startTimeNoAdjustement.getSeconds() + "\n"; + returnData += " nanoSeconds : " + startTimeNoAdjustement.getNanoSeconds() + "\n"; + returnData += "startTime : " + startTime.getReferenceToString() + "\n"; + returnData += " seconds : " + startTime.getSeconds() + "\n"; + returnData += " nanoSeconds : " + startTime.getNanoSeconds() + "\n"; + returnData += "endTime : " + endTime.getReferenceToString() + "\n"; + returnData += " seconds : " + endTime.getSeconds() + "\n"; + returnData += " nanoSeconds : " + endTime.getNanoSeconds() + "\n"; + returnData += "tracefilesMap : " + tracefilesMap.keySet() + "\n"; // Hack to avoid ending up with tracefilesMap.toString() + + return returnData; + } +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniTracefile.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniTracefile.java new file mode 100644 index 0000000000..e3a4927cd0 --- /dev/null +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/JniTracefile.java @@ -0,0 +1,465 @@ +package org.eclipse.linuxtools.lttng.jni; +/******************************************************************************* + * Copyright (c) 2009 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: + * William Bourque (wbourque@gmail.com) - Initial API and implementation + *******************************************************************************/ + + +import java.util.HashMap; + +/** + * JniTracefile + *

+ * A tracefile own an event of a certain type.
+ * Provides access to the LttTracefile C structure in java. + *

+ * Most important fields in the JniTracefile are : + *

    + *
  • a JniTracefile path (a tracefile file within a JniTrace directory) + *
  • a name (basically the name without the directory part) + *
  • a reference to a single event object + *
  • a HashMap of marker associated with this tracefile + *
+ */ +public final class JniTracefile extends Jni_C_Common { + + // Internal C pointer of the JniTracefile used in LTT + private Jni_C_Pointer thisTracefilePtr = new Jni_C_Pointer(); + + // Reference to the parent trace + private JniTrace parentTrace = null; + + // Data we should populate from LTT + // Note that all type have been scaled up as there is no "unsigned" in java + // This might be a problem about "unsigned long" as there is no equivalent in java + private boolean isCpuOnline = false; + private String tracefilePath = ""; + private String tracefileName = ""; + private long cpuNumber = 0; + private long tid = 0; + private long pgid = 0; + private long creation = 0; + + // Internal C pointer for trace and marker + private Jni_C_Pointer tracePtr = null; + private Jni_C_Pointer markerDataPtr = null; + + private int CFileDescriptor = 0; + private long fileSize = 0; + private long blocksNumber = 0; + private boolean isBytesOrderReversed = false; + private boolean isFloatWordOrdered = false; + private long alignement = 0; + private long bufferHeaderSize = 0; + private int bitsOfCurrentTimestampCounter = 0; + private int bitsOfEvent = 0; + private long currentTimestampCounterMask = 0; + private long currentTimestampCounterMaskNextBit = 0; + private long eventsLost = 0; + private long subBufferCorrupt = 0; + private JniEvent currentEvent = null; + + // Internal C pointer for trace and marker + private Jni_C_Pointer bufferPtr = null; + + private long bufferSize = 0; + + // This map will hold markers_info owned by this tracefile + private HashMap tracefileMarkersMap = null; + + // Native access functions + private native boolean ltt_getIsCpuOnline(long tracefilePtr); + private native String ltt_getTracefilepath(long tracefilePtr); + private native String ltt_getTracefilename(long tracefilePtr); + private native long ltt_getCpuNumber(long tracefilePtr); + private native long ltt_getTid(long tracefilePtr); + private native long ltt_getPgid(long tracefilePtr); + private native long ltt_getCreation(long tracefilePtr); + private native long ltt_getTracePtr(long tracefilePtr); + private native long ltt_getMarkerDataPtr(long tracefilePtr); + private native int ltt_getCFileDescriptor(long tracefilePtr); + private native long ltt_getFileSize(long tracefilePtr); + private native long ltt_getBlockNumber(long tracefilePtr); + private native boolean ltt_getIsBytesOrderReversed(long tracefilePtr); + private native boolean ltt_getIsFloatWordOrdered(long tracefilePtr); + private native long ltt_getAlignement(long tracefilePtr); + private native long ltt_getBufferHeaderSize(long tracefilePtr); + private native int ltt_getBitsOfCurrentTimestampCounter(long tracefilePtr); + private native int ltt_getBitsOfEvent(long tracefilePtr); + private native long ltt_getCurrentTimestampCounterMask(long tracefilePtr); + private native long ltt_getCurrentTimestampCounterMaskNextBit(long tracefilePtr); + private native long ltt_getEventsLost(long tracefilePtr); + private native long ltt_getSubBufferCorrupt(long tracefilePtr); + private native long ltt_getEventPtr(long tracefilePtr); + private native long ltt_getBufferPtr(long tracefilePtr); + private native long ltt_getBufferSize(long tracefilePtr); + + // Method to fill a map with marker object + private native void ltt_feedAllMarkers(long tracefilePtr); + + // Debug native function, ask LTT to print tracefile structure + private native void ltt_printTracefile(long tracefilePtr); + + static { + System.loadLibrary("lttvtraceread"); + } + + /* + * Default constructor is forbidden + */ + @SuppressWarnings("unused") + private JniTracefile() { + }; + + /** + * Copy constructor.

+ * + * @param oldTracefile Reference to the JniTracefile you want to copy. + */ + public JniTracefile(JniTracefile oldTracefile) { + thisTracefilePtr = oldTracefile.thisTracefilePtr; + parentTrace = oldTracefile.parentTrace; + tracefileMarkersMap = oldTracefile.tracefileMarkersMap; + isCpuOnline = oldTracefile.isCpuOnline; + tracefilePath = oldTracefile.tracefilePath; + tracefileName = oldTracefile.tracefileName; + cpuNumber = oldTracefile.cpuNumber; + tid = oldTracefile.tid; + pgid = oldTracefile.pgid; + creation = oldTracefile.creation; + tracePtr = oldTracefile.tracePtr; + markerDataPtr = oldTracefile.markerDataPtr; + CFileDescriptor = oldTracefile.CFileDescriptor; + fileSize = oldTracefile.fileSize; + blocksNumber = oldTracefile.blocksNumber; + isBytesOrderReversed = oldTracefile.isBytesOrderReversed; + isFloatWordOrdered = oldTracefile.isFloatWordOrdered; + alignement = oldTracefile.alignement; + bufferHeaderSize = oldTracefile.bufferHeaderSize; + bitsOfCurrentTimestampCounter = oldTracefile.bitsOfCurrentTimestampCounter; + bitsOfEvent = oldTracefile.bitsOfEvent; + currentTimestampCounterMask = oldTracefile.currentTimestampCounterMask; + currentTimestampCounterMaskNextBit = oldTracefile.currentTimestampCounterMaskNextBit; + eventsLost = oldTracefile.eventsLost; + subBufferCorrupt = oldTracefile.subBufferCorrupt; + currentEvent = oldTracefile.currentEvent; + bufferPtr = oldTracefile.bufferPtr; + bufferSize = oldTracefile.bufferSize; + } + + /** + * Constructor, using C pointer.

+ * + * @param newPtr The pointer of an already opened LttTracefile C Structure + * + * @exception JniException + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniTrace + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Pointer + */ + public JniTracefile(Jni_C_Pointer newPtr, JniTrace newParentTrace) throws JniException { + thisTracefilePtr = newPtr; + parentTrace = newParentTrace; + tracefileMarkersMap = new HashMap(); + + // Retrieve the trace file information and load the first event. + try { + populateTracefileInformation(); + } catch (JniNoSuchEventException e) { + throw new JniTracefileWithoutEventException( + "JniEvent constructor reported that no event of this type are usable. (Jaf_Tracefile)"); + } + } + + /** + * Read the next event of this tracefile.

+ * + * Note : If the read succeed, the event will be populated.

+ * + * @return LTT read status, as defined in Jni_C_Common + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Common + */ + public int readNextEvent() { + return currentEvent.readNextEvent(); + } + + /** + * Seek to the given time.

+ * + * Note : If the seek succeed, the event will be populated. + * + * @param seekTime The timestamp where to seek. + * + * @return LTT read status, as defined in Jni_C_Common + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Common + */ + public int seekToTime(JniTime seekTime) { + return currentEvent.seekToTime(seekTime); + } + + /* + * This function populates the tracefile data with data from LTT + * + * @throws JniException + */ + private void populateTracefileInformation() throws JniException { + if (thisTracefilePtr.getPointer() == NULL) { + throw new JniTracefileException( + "Pointer is NULL, trace closed? (populateTracefileInformation)"); + } + + isCpuOnline = ltt_getIsCpuOnline( thisTracefilePtr.getPointer() ); + tracefilePath = ltt_getTracefilepath( thisTracefilePtr.getPointer() ); + tracefileName = ltt_getTracefilename( thisTracefilePtr.getPointer() ); + cpuNumber = ltt_getCpuNumber( thisTracefilePtr.getPointer() ); + tid = ltt_getTid( thisTracefilePtr.getPointer() ); + pgid = ltt_getPgid( thisTracefilePtr.getPointer() ); + creation = ltt_getCreation( thisTracefilePtr.getPointer() ); + tracePtr = new Jni_C_Pointer(ltt_getTracePtr( thisTracefilePtr.getPointer()) ); + markerDataPtr = new Jni_C_Pointer(ltt_getMarkerDataPtr( thisTracefilePtr.getPointer()) ); + CFileDescriptor = ltt_getCFileDescriptor( thisTracefilePtr.getPointer() ); + fileSize = ltt_getFileSize( thisTracefilePtr.getPointer() ); + blocksNumber = ltt_getBlockNumber( thisTracefilePtr.getPointer() ); + isBytesOrderReversed = ltt_getIsBytesOrderReversed( thisTracefilePtr.getPointer() ); + isFloatWordOrdered = ltt_getIsFloatWordOrdered( thisTracefilePtr.getPointer() ); + alignement = ltt_getAlignement( thisTracefilePtr.getPointer() ); + bufferHeaderSize = ltt_getBufferHeaderSize( thisTracefilePtr.getPointer() ); + bitsOfCurrentTimestampCounter = ltt_getBitsOfCurrentTimestampCounter( thisTracefilePtr.getPointer() ); + bitsOfEvent = ltt_getBitsOfEvent( thisTracefilePtr.getPointer() ); + currentTimestampCounterMask = ltt_getCurrentTimestampCounterMask( thisTracefilePtr.getPointer() ); + currentTimestampCounterMaskNextBit = ltt_getCurrentTimestampCounterMaskNextBit( thisTracefilePtr.getPointer() ); + eventsLost = ltt_getEventsLost( thisTracefilePtr.getPointer() ); + subBufferCorrupt = ltt_getSubBufferCorrupt( thisTracefilePtr.getPointer() ); + bufferPtr = new Jni_C_Pointer(ltt_getBufferPtr( thisTracefilePtr.getPointer()) ); + bufferSize = ltt_getBufferSize( thisTracefilePtr.getPointer() ); + + // To fill the map is a bit different + ltt_feedAllMarkers( thisTracefilePtr.getPointer() ); + + Jni_C_Pointer tmpEventPointer = new Jni_C_Pointer(ltt_getEventPtr(thisTracefilePtr.getPointer())); + currentEvent = new JniEvent(tmpEventPointer , tracefileMarkersMap, this); + } + + /* + * Fills a map of all the markers associated with this tracefile. + * + * Note: This function is called from C and there is no way to propagate + * exception back to the caller without crashing JNI. Therefore, it MUST + * catch all exceptions. + * + * @param markerId Id of the marker (int) + * @param markerInfoPtr C Pointer to a marker_info C structure + */ + @SuppressWarnings("unused") + private void addMarkersFromC(int markerId, long markerInfoPtr) { + // Create a new tracefile object and insert it in the map + // the tracefile fill itself with LTT data while being constructed + try { + JniMarker newMarker = new JniMarker( new Jni_C_Pointer(markerInfoPtr) ); + + tracefileMarkersMap.put(markerId, newMarker); + } catch (Exception e) { + printlnC("Failed to add marker to tracefileMarkersMap!(addMarkersFromC)\n\tException raised : " + e.toString()); + } + } + + // Access to class variable. Most of them doesn't have setter + public boolean getIsCpuOnline() { + return isCpuOnline; + } + + public String getTracefilePath() { + return tracefilePath; + } + + public String getTracefileName() { + return tracefileName; + } + + public long getCpuNumber() { + return cpuNumber; + } + + public long getTid() { + return tid; + } + + public long getPgid() { + return pgid; + } + + public long getCreation() { + return creation; + } + + public Jni_C_Pointer getTracePtr() { + return tracePtr; + } + + public Jni_C_Pointer getMarkerDataPtr() { + return markerDataPtr; + } + + public int getCFileDescriptor() { + return CFileDescriptor; + } + + public long getFileSize() { + return fileSize; + } + + public long getBlocksNumber() { + return blocksNumber; + } + + public boolean getIsBytesOrderReversed() { + return isBytesOrderReversed; + } + + public boolean getIsFloatWordOrdered() { + return isFloatWordOrdered; + } + + public long getAlignement() { + return alignement; + } + + public long getBufferHeaderSize() { + return bufferHeaderSize; + } + + public int getBitsOfCurrentTimestampCounter() { + return bitsOfCurrentTimestampCounter; + } + + public int getBitsOfEvent() { + return bitsOfEvent; + } + + public long getCurrentTimestampCounterMask() { + return currentTimestampCounterMask; + } + + public long getCurrentTimestampCounterMaskNextBit() { + return currentTimestampCounterMaskNextBit; + } + + public long getEventsLost() { + return eventsLost; + } + + public long getSubBufferCorrupt() { + return subBufferCorrupt; + } + + public JniEvent getCurrentEvent() { + return currentEvent; + } + + public Jni_C_Pointer getBufferPtr() { + return bufferPtr; + } + + public long getBufferSize() { + return bufferSize; + } + + public HashMap getTracefileMarkersMap() { + return tracefileMarkersMap; + } + + /** + * Parent trace of this tracefile.

+ * + * @return The parent trace + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniTrace + */ + public JniTrace getParentTrace() { + return parentTrace; + } + + /** + * Pointer to the LttTracefile C structure

+ * + * The pointer should only be used INTERNALY, do not use unless you + * know what you are doing.

+ * + * @return The actual (long converted) pointer or NULL. + * + * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Pointer + */ + public Jni_C_Pointer getTracefilePtr() { + return thisTracefilePtr; + } + + /** + * Print information for this tracefile. + * Intended to debug

+ * + * This function will call Ltt to print, so information printed will be the + * one from the C structure, not the one populated in java.

+ * + * This function will not throw but will complain loudly if pointer is NULL. + */ + public void printTracefileInformation() { + + // If null pointer, print a warning! + if (thisTracefilePtr.getPointer() == NULL) { + printlnC("Pointer is NULL, cannot print. (printTracefileInformation)"); + } + else { + ltt_printTracefile( thisTracefilePtr.getPointer() ); + } + } + + /** + * toString() method. + * Intended to debug

+ * + * @return Attributes of the object concatenated in String + */ + @Override + public String toString() { + String returnData = ""; + + returnData += "isCpuOnline : " + isCpuOnline + "\n"; + returnData += "tracefilePath : " + tracefilePath + "\n"; + returnData += "tracefileName : " + tracefileName + "\n"; + returnData += "cpuNumber : " + cpuNumber + "\n"; + returnData += "tid : " + tid + "\n"; + returnData += "pgid : " + pgid + "\n"; + returnData += "creation : " + creation + "\n"; + returnData += "tracePtr : " + tracePtr + "\n"; + returnData += "markerDataPtr : " + markerDataPtr + "\n"; + returnData += "CFileDescriptor : " + CFileDescriptor + "\n"; + returnData += "fileSize : " + fileSize + "\n"; + returnData += "blocksNumber : " + blocksNumber + "\n"; + returnData += "isBytesOrderReversed : " + isBytesOrderReversed + "\n"; + returnData += "isFloatWordOrdered : " + isFloatWordOrdered + "\n"; + returnData += "alignement : " + alignement + "\n"; + returnData += "bufferHeaderSize : " + bufferHeaderSize + "\n"; + returnData += "bitsOfCurrentTimestampCounter : " + bitsOfCurrentTimestampCounter + "\n"; + returnData += "bitsOfEvent : " + bitsOfEvent + "\n"; + returnData += "currentTimestampCounterMask : " + currentTimestampCounterMask + "\n"; + returnData += "currentTimestampCounterMaskNextBit : " + currentTimestampCounterMaskNextBit + "\n"; + returnData += "eventsLost : " + eventsLost + "\n"; + returnData += "subBufferCorrupt : " + subBufferCorrupt + "\n"; + returnData += "currentEvent : " + currentEvent.getReferenceToString() + "\n"; // Hack to avoid ending up with event.toString() + returnData += "bufferPtr : " + bufferPtr + "\n"; + returnData += "bufferSize : " + bufferSize + "\n"; + returnData += "tracefileMarkersMap : " + tracefileMarkersMap.keySet() + "\n"; // Hack to avoid ending up with tracefileMarkersMap.toString() + + return returnData; + } +} + diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/Jni_C_Common.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/Jni_C_Common.java new file mode 100644 index 0000000000..23904606db --- /dev/null +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/Jni_C_Common.java @@ -0,0 +1,75 @@ +package org.eclipse.linuxtools.lttng.jni; +/******************************************************************************* + * Copyright (c) 2009 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: + * William Bourque (wbourque@gmail.com) - Initial API and implementation + *******************************************************************************/ + + +/** + * Jni_C_Common + *

+ * Common constants and methods that should be shared between JNI objects + */ +public abstract class Jni_C_Common { + + // Needed for native types + public static final int NULL = 0; + + // C errno correspondance. Used to interpret LTT return value + public static final int EOK = 0; + public static final int EPERM = 1; + public static final int ERANGE = 34; + + // Timestamps are in nanoseconds, this const ease up the math + public static final long NANO = 1000000000; + + // Native console printing function + private native void ltt_printC(String string_to_print); + + // Load LTTV library (order is important) + static { + System.loadLibrary("lttvtraceread"); + } + + /** + * Java-side console printing function.

+ * + * Call the C printing function to make sure all printing happen on the same side. + * + * @param msg The string to print in C. + */ + public void printC(String msg) { + // Need to escape "%" for C printf + msg = msg.replaceAll("%", "%%"); + ltt_printC(msg); + } + + /** + * Java-side console printing function that add carriage return.

+ * + * Call the C printing function to make sure all printing happen on the same side. + * + * @param msg The string to print in C. + */ + public void printlnC(String msg) { + printC(msg + "\n"); + } + + /** + * "Alternate" .toString()

+ * + * Simulates the way Java Object implements "toString()" + * + * @return The Java hashed UID of the object (i.e. : NAME@HASH) + */ + public String getReferenceToString() { + return this.getClass().getName() + "@" + Integer.toHexString(this.hashCode()); + } +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/Jni_C_Pointer.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/Jni_C_Pointer.java new file mode 100644 index 0000000000..7cfec13078 --- /dev/null +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/jni/Jni_C_Pointer.java @@ -0,0 +1,94 @@ +package org.eclipse.linuxtools.lttng.jni; + + +/** + * Jni_C_Pointer + *

+ * Class pointer to handle properly "C pointer"

+ * + * Can transparently handle pointer of 32 or 64 bits. + */ +public class Jni_C_Pointer extends Jni_C_Common { + + private long ptr = NULL; + private boolean isLong = true; + + /** + * Default constructor.

+ * + * Note : Pointer will be set to a 64bits "NULL". + */ + public Jni_C_Pointer() { + ptr = NULL; + } + + /** + * Constructor with parameters for 64bits pointers. + * + * @param newPtr long-converted (64 bits) C pointer. + */ + public Jni_C_Pointer(long newPtr) { + ptr = newPtr; + isLong = true; + } + + /** + * Constructor with parameters for 32bits pointers. + * + * @param newPtr int-converted (32 bits) C pointer. + */ + public Jni_C_Pointer(int newPtr) { + ptr = (long)newPtr; + isLong = false; + } + + /** + * Get the current pointer. + * + * @return The current pointer, in long. + */ + public long getPointer() { + return ptr; + } + + /** + * Set the pointer, as a 64bits pointer. + * + * @param newPtr long-converted (64 bits) C pointer. + */ + public void setPointer(long newPtr) { + ptr = newPtr; + isLong = true; + } + + /** + * Set the pointer, as a 64bits pointer. + * + * @param newPtr int-converted (32 bits) C pointer. + */ + public void setPointer(int newPtr) { + ptr = newPtr; + isLong = false; + } + + /** + * toString() method.

+ * + * Convert the pointer to a nice looking int/long hexadecimal format. + * + * @return Attributes of the object concatenated in String + */ + @Override + public String toString() { + String returnData = "0x"; + + if (isLong == true) { + returnData += Long.toHexString(ptr); + } + else { + returnData += Integer.toHexString((int) ptr); + } + + return returnData; + } +} diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/IStateDataRequestListener.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/IStateDataRequestListener.java new file mode 100644 index 0000000000..5cfe500bd2 --- /dev/null +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/IStateDataRequestListener.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2009 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: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.state; + + +/** + * Interface to be used to receive notification of Processing start and + * completed + * + * @author alvaro + * + */ +public interface IStateDataRequestListener { + // ======================================================================== + // Methods + // ======================================================================== + + /** + * + * @param request + * @return + */ + public void processingStarted(RequestStartedSignal request); + + /** + * @param signal + */ + public void processingCompleted(RequestCompletedSignal signal); +} diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/LttngStateInputRef.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/LttngStateInputRef.java new file mode 100644 index 0000000000..2bb7bcea7c --- /dev/null +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/LttngStateInputRef.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2009 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: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.state; + +import org.eclipse.linuxtools.lttng.state.model.ILttngStateInputRef; +import org.eclipse.linuxtools.lttng.trace.LTTngTextTrace; +import org.eclipse.linuxtools.lttng.trace.LTTngTrace; +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; +import org.eclipse.linuxtools.tmf.trace.TmfTrace; + +/** + * Interface data provider to the state.model package + * + * @author alvaro + * + */ +public class LttngStateInputRef implements ILttngStateInputRef { + + private int cpuNumber = -1; + + // ======================================================================== + // Table data + // ======================================================================= + TmfTrace log = null; + + // ======================================================================== + // Constructor + // ======================================================================== + LttngStateInputRef(TmfTrace log) { + this.log = log; + + if ( log instanceof LTTngTrace) { + cpuNumber = ((LTTngTrace)log).getCpuNumber(); + } + else if ( log instanceof LTTngTextTrace) { + cpuNumber = ((LTTngTextTrace)log).getCpuNumber(); + } + } + + // ======================================================================== + // Methods + // ======================================================================= + /* + * (non-Javadoc) + * + * @seeorg.eclipse.linuxtools.lttng.ui.state.model.ILttngStateInputRef# + * getNumberOfCpus() + */ + // @Override + public int getNumberOfCpus() { + return cpuNumber; + } + + /* + * (non-Javadoc) + * + * @seeorg.eclipse.linuxtools.lttng.ui.state.model.ILttngStateInputRef# + * getTraceTimeWindow() + */ + // @Override + public TmfTimeRange getTraceTimeWindow() { + if (log != null) { + return log.getTimeRange(); + + } + return null; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.linuxtools.lttng.state.model.ILttngStateInputRef#getTraceId() + */ + public String getTraceId() { + if (log != null) { + return log.getName(); + } + return null; + } + + /* + * (non-Javadoc) + * + * @seeorg.eclipse.linuxtools.lttng.state.model.ILttngStateInputRef# + * getExperimentTimeWindow() + */ + public TmfTimeRange getExperimentTimeWindow() { + // TODO Using the Trace time window temporarily, we need to replace with + // the Experiment level + if (log != null) { + return log.getTimeRange(); + } + return null; + } +} diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/RequestCompletedSignal.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/RequestCompletedSignal.java new file mode 100644 index 0000000000..c270b00797 --- /dev/null +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/RequestCompletedSignal.java @@ -0,0 +1,18 @@ +package org.eclipse.linuxtools.lttng.state; + +import org.eclipse.linuxtools.tmf.signal.TmfSignal; + +public class RequestCompletedSignal extends TmfSignal { + + StateDataRequest request; + + public RequestCompletedSignal(StateDataRequest request) { + super(request); + this.request = request; + } + + public StateDataRequest getRequest() { + return request; + } + +} diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/RequestStartedSignal.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/RequestStartedSignal.java new file mode 100644 index 0000000000..1372f092e2 --- /dev/null +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/RequestStartedSignal.java @@ -0,0 +1,18 @@ +package org.eclipse.linuxtools.lttng.state; + +import org.eclipse.linuxtools.tmf.signal.TmfSignal; + +public class RequestStartedSignal extends TmfSignal { + + StateDataRequest request; + + public RequestStartedSignal(StateDataRequest request) { + super(request); + this.request = request; + } + + public StateDataRequest getRequest() { + return request; + } + +} diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/StateDataRequest.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/StateDataRequest.java index 667426ef31..62eb5be5bf 100644 --- a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/StateDataRequest.java +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/StateDataRequest.java @@ -11,6 +11,13 @@ *******************************************************************************/ package org.eclipse.linuxtools.lttng.state; +import java.util.Vector; + +import org.eclipse.linuxtools.tmf.event.TmfEvent; +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; +import org.eclipse.linuxtools.tmf.request.TmfDataRequest; +import org.eclipse.linuxtools.tmf.signal.TmfSignalManager; +import org.eclipse.linuxtools.tmf.trace.TmfExperiment; /** * This class is an extension of Data Request which includes specific references @@ -19,202 +26,163 @@ package org.eclipse.linuxtools.lttng.state; * @author alvaro * */ -public class StateDataRequest { - // // +public class StateDataRequest extends TmfDataRequest { // ======================================================================== - // // Data - // // + // Data // ======================================================================= - // private Vector listeners = new - // Vector(); - // private String transactionId = ""; /* optional user's attribute */ - // private StateManager manager = null; - // private long numOfEvents = 0; - // private boolean broadcast = false; - // private boolean clearDataInd = false; - // // + private Vector listeners = new Vector(); + private String transactionId = ""; /* optional user's attribute */ + private StateManager manager = null; + private long numOfEvents = 0; + private boolean broadcast = false; + private boolean clearDataInd = false; // ======================================================================== - // // Constructors - // // + // Constructors // ======================================================================= - // /** - // * @param range - // * @param offset - // * @param nbEvents - // * @param maxBlockSize - // * @param listener - // */ - // public StateDataRequest(TmfTimeRange range, long offset, int nbEvents, - // int maxBlockSize, IStateDataRequestListener listener, - // StateManager manager) { - // - // super(range, nbEvents, maxBlockSize); - // //super(0, nbEvents, maxBlockSize); - // this.manager = manager; - // if (listener != null && !listeners.contains(listener)) { - // listeners.add(listener); - // } - // } - // - // /** - // * @param range - // * @param offset - // * @param nbEvents - // * @param maxBlockSize - // * @param listener - // * @param transactionID - // * optional use by user application - // */ - // public StateDataRequest(TmfTimeRange range, long offset, int nbEvents, - // int maxBlockSize, IStateDataRequestListener listener, - // String transactionID, StateManager manager) { - // - // this(range, offset, nbEvents, maxBlockSize, listener, manager); - // this.transactionId = transactionID; - // } - // - // // + /** + * @param range + * @param offset + * @param nbEvents + * @param maxBlockSize + * @param listener + */ + public StateDataRequest(TmfTimeRange range, long offset, int nbEvents, + int maxBlockSize, IStateDataRequestListener listener, + StateManager manager) { + + super(range, nbEvents, maxBlockSize); + //super(0, nbEvents, maxBlockSize); + this.manager = manager; + if (listener != null && !listeners.contains(listener)) { + listeners.add(listener); + } + } + + /** + * @param range + * @param offset + * @param nbEvents + * @param maxBlockSize + * @param listener + * @param transactionID + * optional use by user application + */ + public StateDataRequest(TmfTimeRange range, long offset, int nbEvents, + int maxBlockSize, IStateDataRequestListener listener, + String transactionID, StateManager manager) { + + this(range, offset, nbEvents, maxBlockSize, listener, manager); + this.transactionId = transactionID; + } + // ======================================================================== - // // Methods - // // + // Methods // ======================================================================= - // - // /** - // * Trigger the start to process this request right after the notification - // to - // * the interested listeners - // * - // * @param experiment - // * @param broadcast - // * true: All views, false: only to registered listeners - // */ - // public void startRequestInd(TmfExperiment experiment, boolean broadcast, - // boolean waitForCompletion) { - // if (broadcast) { - // // Notify all state views. - // this.broadcast = broadcast; - // // TmfSignalManager.dispatchSignal(new RequestStartedSignal(this)); - // } - // // else { - // // // Notify specific state views - // // for (IStateDataRequestListener listener : listeners) { - // // listener.processingStarted(new RequestStartedSignal(this)); - // // } - // // } - // - // // trigger the start to process this request - // experiment.processRequest(this, waitForCompletion); - // } - // - // /** - // * to be called by the handleCompletion in superclass method, notifies the - // * interested listeners. i.e. if the request start indicated broadcast, - // the - // * completion will also be broadcasted otherwise only registered listeners - // * will be notified. - // */ - // public void notifyCompletion() { - // if (broadcast) { - // // Notify all state views. - // TraceDebug.debug("request completed" + this.toString()); - // TmfSignalManager.dispatchSignal(new RequestCompletedSignal(this)); - // } else { - // // Notify specific state views - // for (IStateDataRequestListener listener : listeners) { - // listener.processingCompleted(new RequestCompletedSignal(this)); - // } - // } - // } - // - // public void notifyStarting() { - // if (broadcast) { - // // Notify all state views. - // TraceDebug.debug("request started" + this.toString()); - // TmfSignalManager.dispatchSignal(new RequestStartedSignal(this)); - // } else { - // for (IStateDataRequestListener listener : listeners) { - // listener.processingStarted(new RequestStartedSignal(this)); - // } - // } - // } - // - // public String getTransactionId() { - // return transactionId; - // } - // - // public StateManager getStateManager() { - // return this.manager; - // } - // - // // public IStateDataRequestListener getListener() { - // // return listener; - // // } - // - // public void addListener(IStateDataRequestListener listener) { - // if (!listeners.contains(listener)) { - // listeners.add(listener); - // } - // } - // - // public void removeListener(IStateDataRequestListener listener) { - // if (listener != null) { - // listeners.remove(listener); - // } - // } - // - // /** - // * @param numOfEvents - // * the numOfEvents to set - // */ - // public void setNumOfEvents(long numOfEvents) { - // this.numOfEvents = numOfEvents; - // } - // - // /** - // * @return the numOfEvents - // */ - // public long getNumOfEvents() { - // return numOfEvents; - // } - // - // /** - // * @param clearAllData - // * indicates the need to clear all previous data e.g. a new - // * experiment selection - // */ - // public void setclearDataInd(boolean clearAllData) { - // this.clearDataInd = clearAllData; - // } - // - // /** - // * Returns indication - clearing of all existing data model is required - // e.g - // * from the selection of a new experiment - // * - // * @return - // */ - // public boolean isclearDataInd() { - // return clearDataInd; - // } - // - // /** - // * Compare the time range with a Data Request. - // * - // * @param trange - // * @return - // */ - // public boolean equalTime(StateDataRequest otherRequest) { - // TmfTimeRange trange = otherRequest.getRange(); - // TmfTimeRange myTimeRange = getRange(); - // TmfTimestamp myStartTime = myTimeRange.getStartTime(); - // TmfTimestamp myEndTime = myTimeRange.getEndTime(); - // - // if (myStartTime.equals(trange.getStartTime())) { - // if (myEndTime.equals(trange.getEndTime())) { - // return true; - // } - // } - // - // return false; + + /** + * Trigger the start to process this request right after the notification to + * the interested listeners + * + * @param experiment + * @param broadcast + * true: All views, false: only to registered listeners + */ + public void startRequestInd(TmfExperiment experiment, boolean broadcast, + boolean waitForCompletion) { + if (broadcast) { + // Notify all state views. + this.broadcast = broadcast; + TmfSignalManager.dispatchSignal(new RequestStartedSignal(this)); + } else { + // Notify specific state views + for (IStateDataRequestListener listener : listeners) { + listener.processingStarted(new RequestStartedSignal(this)); + } + } + + // trigger the start to process this request + experiment.processRequest(this, waitForCompletion); + } + + /** + * to be called by the handleCompletion in superclass method, notifies the + * interested listeners. i.e. if the request start indicated broadcast, the + * completion will also be broadcasted otherwise only registered listeners + * will be notified. + */ + public void notifyCompletion() { + if (broadcast) { + // Notify all state views. + TmfSignalManager.dispatchSignal(new RequestCompletedSignal(this)); + } else { + // Notify specific state views + for (IStateDataRequestListener listener : listeners) { + listener.processingCompleted(new RequestCompletedSignal(this)); + } + } + } + + public void notifyStarting() { + for (IStateDataRequestListener listener : listeners) { + listener.processingStarted(new RequestStartedSignal(this)); + } + } + + public String getTransactionId() { + return transactionId; + } + + public StateManager getStateManager() { + return this.manager; + } + + // public IStateDataRequestListener getListener() { + // return listener; // } + + public void addListener(IStateDataRequestListener listener) { + if (!listeners.contains(listener)) { + listeners.add(listener); + } + } + + public void removeListener(IStateDataRequestListener listener) { + if (listener != null) { + listeners.remove(listener); + } + } + + /** + * @param numOfEvents + * the numOfEvents to set + */ + public void setNumOfEvents(long numOfEvents) { + this.numOfEvents = numOfEvents; + } + + /** + * @return the numOfEvents + */ + public long getNumOfEvents() { + return numOfEvents; + } + + /** + * @param clearAllData + * indicates the need to clear all previous data e.g. a new + * experiment selection + */ + public void setclearDataInd(boolean clearAllData) { + this.clearDataInd = clearAllData; + } + + /** + * Returns indication - clearing of all existing data model is required e.g + * from the selection of a new experiment + * + * @return + */ + public boolean isclearDataInd() { + return clearDataInd; + } } diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/StateManager.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/StateManager.java new file mode 100644 index 0000000000..bfa4bf25e8 --- /dev/null +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/StateManager.java @@ -0,0 +1,587 @@ +/******************************************************************************* + * Copyright (c) 2009 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: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.state; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Observable; +import java.util.Set; +import java.util.Vector; + +import org.eclipse.linuxtools.lttng.TraceDebug; +import org.eclipse.linuxtools.lttng.event.LttngTimestamp; +import org.eclipse.linuxtools.lttng.state.evProcessor.AbsEventProcessorFactory; +import org.eclipse.linuxtools.lttng.state.evProcessor.EventProcessorProxy; +import org.eclipse.linuxtools.lttng.state.evProcessor.IEventProcessing; +import org.eclipse.linuxtools.lttng.state.model.ILttngStateInputRef; +import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; +import org.eclipse.linuxtools.lttng.state.model.StateModelFactory; +import org.eclipse.linuxtools.tmf.event.TmfEvent; +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; +import org.eclipse.linuxtools.tmf.event.TmfTimestamp; +import org.eclipse.linuxtools.tmf.request.TmfDataRequest; +import org.eclipse.linuxtools.tmf.trace.TmfExperiment; +import org.eclipse.linuxtools.tmf.trace.TmfTrace; +import org.eclipse.linuxtools.tmf.trace.TmfTraceCheckpoint; + +/** + * + * @author alvaro + * + */ +public class StateManager extends Observable { + + private static final long LTTNG_STATE_SAVE_INTERVAL = 5000000L; + + // These are used in the building of the data request. + private static final long DEFAULT_OFFSET = 0L; + private static final int DEFAULT_CHUNK = 1; + + // ======================================================================== + // Data + // ======================================================================= + private TmfExperiment fExperiment = null; + private TmfTrace fEventLog = null; + private StateStacksHandler stateIn = null; + private Long eventCount = 0L; + + private HashMap stateCheckpointsList = new HashMap(); + private Vector timestampCheckpointsList = new Vector(); + + // ======================================================================== + // Constructor + // ======================================================================= + + // /** + // * Default constructor + // *

+ // * Instanciate its own StateStacksHandler. + // * + // */ + // public StateManager() { + // this.stateIn = new StateStacksHandler(); + // } + + /** + * Constructor with parameter + *

+ * + * @param stateInputHandler + * A valid StateStacksHandler + * + */ + public StateManager(StateStacksHandler stateInputHandler) { + this.stateIn = stateInputHandler; + } + + // /** + // * Copy constructor + // *

+ // * + // * @param oldStateManager + // * the StateManager we want to copy + // * + // */ + // public StateManager(StateManager oldStateManager) { + // fEventLog = oldStateManager.fEventLog; + // stateIn = oldStateManager.stateIn; + // trace = oldStateManager.trace; + // eventCount = oldStateManager.eventCount; + // + // stateCheckpointsList = oldStateManager.stateCheckpointsList; + // timestampCheckpointsList = oldStateManager.timestampCheckpointsList; + // } + + // ======================================================================== + // Methods + // ======================================================================= + /** + * A new Experiment or trace selected + * @param experiment + * @param clearPreviousData + */ + public void setTraceSelection(TmfExperiment experiment, + boolean clearPreviousData) { + // New log in use, read all events and build state transition stack + if (experiment != null) { + if (fExperiment != null && fExperiment != experiment) { + this.fExperiment.dispose(); + } + + this.fExperiment = experiment; + + // if (fEventLog != null) { + // this.fEventLog.dispose(); + // } + + this.fEventLog = (TmfTrace)experiment.getTraces()[0]; + try { + stateIn.init(fEventLog); + } catch (LttngStateException e) { + e.printStackTrace(); + } + + // Restart count and collections + eventCount = 0L; + stateCheckpointsList.clear(); + timestampCheckpointsList.clear(); + + // Obtain a dataRequest to pass to the processRequest function + TmfTimeRange allTraceWindow = fEventLog.getTimeRange(); + StateDataRequest request = getDataRequestStateSave(allTraceWindow, + null); + request.setclearDataInd(clearPreviousData); + + // Wait for completion + request.startRequestInd(fExperiment, true, true); + + if (TraceDebug.isDEBUG()) { + StringBuilder sb = new StringBuilder( + "Total number of processes in the State provider: " + + stateIn.getTraceStateModel().getProcesses().length); + + TmfTimeRange logTimes = fEventLog.getTimeRange(); + sb.append("\n\tLog file times " + + new LttngTimestamp(logTimes.getStartTime())); + sb.append(" - " + new LttngTimestamp(logTimes.getEndTime())); + + sb.append("\n\tCheckPoints available at: "); + for (TmfTraceCheckpoint cpoint : timestampCheckpointsList) { + sb.append("\n\t" + cpoint.getTimestamp()); + } + TraceDebug.debug(sb.toString()); + } + } + + } + + /** + * TODO: Not ready for threading + *

+ * Read events within specific time window + *

+ * + * @param trange + * @param obs + * @param transactionID + */ + public void executeDataRequest(TmfTimeRange trange, String transactionID, + IStateDataRequestListener listener) { + TmfTimestamp restoredStartTime = restoreCheckPointByTimestamp(trange + .getStartTime()); + // Adjust the time range to consider rewinding to the start time + trange = new TmfTimeRange(restoredStartTime, trange.getEndTime()); + // Get a data request for the time range we want (nearest checkpoint + // to timestamp wanted) + eventCount = 0L; + + // Process request to that point + StateDataRequest request = getDataRequestByTimeRange(trange, listener); + // don't wait for completion i.e. allow cancellations + request.startRequestInd(fExperiment, false, false); + + if (TraceDebug.isDEBUG()) { + TraceDebug + .debug(" Time Window requested, (start adjusted to checkpoint): " + + trange.getStartTime() + + "-" + trange.getEndTime() + + " Total number of processes in the State provider: " + + stateIn.getTraceStateModel().getProcesses().length + " Completed"); + } + } + + /** + * Current value of event counter + * + * @return Long The number of events, if it is known + */ + public Long getEventCount() { + return eventCount; + } + + /** + * used to obtain details on the log associated with this manager e.g. + * logid. + * + * @return + */ + public TmfTrace getEventLog() { + return fEventLog; + } + + /** + * Used for troubleshooting when debug mode is on + * + * @return Set Set of event that were not handled + */ + public Set getEventsNotHandled() { + return stateIn.getEventsNotHandled(); + } + + /** + * Needed for verification purposes + * + * @param listener + * The IEventProcessing we want to register + */ + void registerListener(IEventProcessing listener) { + stateIn.registerListener(listener); + } + + /** + * Needed for verification purposes + * + * @param listener + * The IEventProcessing we want to unregister + */ + void deregisterListener(IEventProcessing listener) { + stateIn.deregisterListener(listener); + } + + /** + * Save a checkpoint if it is needed at that point + *

+ * The function will use "eventCount" internally to determine if a save was + * needed + * + * @param eventCounter + * The event "count" or event "id" so far + * @param eventTime + * The timestamp of this event + * + * @return boolean True if a checkpoint was saved, false otherwise + */ + private boolean saveCheckPointIfNeeded(Long eventCounter, + TmfTimestamp eventTime) { + boolean saveHappened = false; + // Crate new location to store checkpoint reference + Long location = new Long(eventCounter.longValue()); + // Save a checkpoint every LTTNG_STATE_SAVE_INTERVAL event + if ((location % LTTNG_STATE_SAVE_INTERVAL) == 0) { + // Save the checkpoint + stateCheckpointsList.put(location, stateIn.traceStateModel.clone()); + // Save correlation between timestamp and checkpoint index + + timestampCheckpointsList.add(new TmfTraceCheckpoint(eventTime, + location)); + + saveHappened = true; + } + + return saveHappened; + } + + /** + * Restore to the closest checkpoint from TmfTimestamp + *

+ * Note : it is heavier to restore by timestamp than by event position, + * restore by event position whichever possible. + * + * @param eventTime + * The timestamp of the event to restore to + * + * @return TmfTimestamp indicates the nearest time used to restore the + * state, null sent if input is invalid + */ + public TmfTimestamp restoreCheckPointByTimestamp(TmfTimestamp eventTime) { + TmfTimeRange logRange = fExperiment.getTimeRange(); + TmfTimestamp nearestTimeStamp = logRange.getStartTime(); + + // The GUI can have time limits higher than this log, since GUI can + // handle multiple logs + if ((eventTime.getValue() < 0) + || (eventTime.getValue() > logRange.getEndTime().getValue())) { + return null; + } + + // The GUI can have time limits lower than this log, since GUI can + // handle multiple logs + if ((eventTime.getValue() < logRange.getStartTime().getValue())) { + eventTime = logRange.getStartTime(); + } + + // Sort the checkpoints, required before the binary search + Collections.sort(timestampCheckpointsList); + // Initiate the compare with a checkpoint containing the target time + // stamp to find + int index = Collections.binarySearch(timestampCheckpointsList, + new TmfTraceCheckpoint(eventTime, 0)); + // adjust index to round down to earlier checkpoint when exact match not + // found + index = getPrevIndex(index); + + LttngTraceState traceState; + Long location = 0L; + if (index == 0) { + // No checkpoint restore is needed, start with a brand new + // TraceState + ILttngStateInputRef inputDataRef = new LttngStateInputRef(fEventLog); + traceState = StateModelFactory.getStateEntryInstance(inputDataRef); + } else { + // Useful CheckPoint found + TmfTraceCheckpoint checkpoint = timestampCheckpointsList.get(index); + nearestTimeStamp = checkpoint.getTimestamp(); + // get the location associated with the checkpoint + location = (Long) (checkpoint.getLocation()); + // reference a new copy of the checkpoint template + traceState = stateCheckpointsList.get(location).clone(); + } + + // Make sure eventCount stay consistent! + eventCount = new Long(location); + + // Restore the stored traceState + stateIn.setTraceStateModel(traceState); + + return nearestTimeStamp; + } + + /** + * Adjust the result from a binary search to the round down position + * + * @param position + * if Negative is: (-(insertion point) -1) + * @return position or if no match found, earlier than insertion point + */ + private int getPrevIndex(int position) { + int roundDownPosition = position; + if (position < 0) { + roundDownPosition = -(position + 2); + } + + roundDownPosition = roundDownPosition < 0 ? 0 : roundDownPosition; + return roundDownPosition; + } + + // /** + // * Restore to the closest checkpoint from position + // *

+ // * + // * @param position + // * The position of the event to restore to + // * + // * @return boolean True if a checkpoint was restored, false otherwise + // */ + // private boolean restoreCheckPointByPosition(long position) { + // long nearestCheckPoint = (position - (position % + // LTTNG_STATE_SAVE_INTERVAL)); + // + // // Some sanity check : + // // Not under 0 + // // Not over eventCount + // // A checkpoint exist + // if ((nearestCheckPoint < 0) || (nearestCheckPoint > eventCount) + // || (stateCheckpointsList.get(nearestCheckPoint) == null)) { + // return false; + // } else { + // // Restore the stored traceState + // stateIn.setTraceStateModel(stateCheckpointsList + // .get(nearestCheckPoint)); + // + // // Make sure eventCount stay consistent! + // eventCount = new Long(nearestCheckPoint); + // + // // * Rewind to the correct position + // // To do so, we need a request to the correct window + // // We will seek to nearestCheckPoint and read next events until + // // position + // TmfDataRequest request = getDataRequestByPosition( + // (int) nearestCheckPoint, (int) position); + // + // // Process request to that point + // fExperiment.processRequest(request, true); + // + // return true; + // } + // } + + /** + * Get a Tmf data request for the current eventlog + *

+ * + * @param TmfTimeRange + * The time range we want events from. + * + * @return TmfDataRequest The request made + */ + StateDataRequest getDataRequestByTimeRange(TmfTimeRange timeWindow, + IStateDataRequestListener listener) { + + final TmfEvent[] evt = new TmfEvent[1]; + + // ***TODO*** + // The override of handlePartialResult is similar to the one in + // getDataRequestByPosition() + // *** + + // Create the new request and override the handlePartialResult function + StateDataRequest request = new StateDataRequest(timeWindow, + DEFAULT_OFFSET, TmfDataRequest.ALL_EVENTS, DEFAULT_CHUNK, + listener, this) { + @Override + public void handleData() { + TmfEvent[] result = getData(); + + evt[0] = (result.length > 0) ? result[0] : null; + // Dispatch information for Event processing + stateIn.processEvent(evt[0]); + + // increment internal and external number of events + setNumOfEvents(getNumOfEvents() + 1); + eventCount++; + } + + @Override + public void handleCompleted() { + if (isCancelled() || isFailed()) { + // No notification to end request handlers + } else { + // notify the associated end request handlers + requestCompleted(); + } + + // notify listeners + notifyCompletion(); + } + }; + + return request; + } + + private StateDataRequest getDataRequestStateSave(TmfTimeRange timeWindow, + IStateDataRequestListener requestListener) { + + final TmfEvent[] evt = new TmfEvent[1]; + + // ***TODO*** + // The override of handlePartialResult is similar to the one in + // getDataRequestByPosition() + // *** + + // Create the new request and override the handlePartialResult function + StateDataRequest request = new StateDataRequest(timeWindow, + DEFAULT_OFFSET, TmfDataRequest.ALL_EVENTS, DEFAULT_CHUNK, + requestListener, this) { + + @Override + public void handleData() { + TmfEvent[] result = getData(); + + evt[0] = (result.length > 0) ? result[0] : null; + // Dispatch information for Event processing + stateIn.processEvent(evt[0]); + + // Call the function that will save a checkpoint if needed at + // that point + // Note : We call this function before incrementing eventCount + // to avoid skipping the "0th" event + if (evt[0] != null) { + saveCheckPointIfNeeded(getNumOfEvents(), evt[0] + .getTimestamp()); + } + + // increment internal and external counters + setNumOfEvents(getNumOfEvents() + 1); + eventCount++; + } + + @Override + public void handleCompleted() { + if (isCancelled() || isFailed()) { + // No notification to end request handlers + } else { + // notify the associated end request handlers + requestCompleted(); + } + + // notify listeners + notifyCompletion(); + TraceDebug.debug("number of events processed on file opening" + + getNumOfEvents()); + } + }; + + return request; + } + + // /** + // * Get a Tmf data request for the current eventlog + // *

+ // * + // * @param startPosition + // * The position to start the get request from + // * @param endPosition + // * The position to ed the get request at + // * + // * @return TmfDataRequest The request made + // */ + // private TmfDataRequest getDataRequestByPosition( + // long startPosition, long endPosition) { + // final TmfEvent[] evt = new TmfEvent[1]; + // + // // ***FIXME*** + // // The override of handlePartialResult is exactly the same as the one in + // // getDataRequestByPosition() + // // However, there is no way to override it in only one place to avoid + // // code duplication! + // // *** + // + // // Create the new request and override the handlePartialResult function + // TmfDataRequest request = new TmfDataRequest( + // (int) startPosition, DEFAULT_OFFSET, + // (int) (endPosition - startPosition), DEFAULT_CHUNK) { + // //@Override + // public void handlePartialResult() { + // TmfEvent[] result = getData(); + // + // evt[0] = (result.length > 0) ? result[0] : null; + // // Dispatch information for Event processing + // stateIn.processEvent(evt[0]); + // } + // }; + // + // return request; + // } + + /** + * @return + */ + public TmfTimeRange getExperimentTimeWindow() { + if (fExperiment != null) { + return fExperiment.getTimeRange(); + } + return null; + } + + /** + * This method has to be called once all events of the associated Trace have + * been processed, this method then triggers the drawing of the final state + * which is necessary e.g when zooming. + */ + public synchronized void requestCompleted() { + Set handlerRegister = EventProcessorProxy + .getInstance().getProcessingFactories(); + // Notify the FINISH handlers + for (Iterator iterator = handlerRegister + .iterator(); iterator.hasNext();) { + AbsEventProcessorFactory handlerRegistry = (AbsEventProcessorFactory) iterator + .next(); + IEventProcessing handler = handlerRegistry.getfinishProcessor(); + if (handler != null) { + // process State Update + handler.process(null, stateIn.traceStateModel); + } + } + } +} diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/StateStacksHandler.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/StateStacksHandler.java new file mode 100644 index 0000000000..81ad12f298 --- /dev/null +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/StateStacksHandler.java @@ -0,0 +1,199 @@ +/******************************************************************************* + * Copyright (c) 2009 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: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.state; + +import java.util.Iterator; +import java.util.Set; +import java.util.Vector; + +import org.eclipse.linuxtools.lttng.TraceDebug; +import org.eclipse.linuxtools.lttng.event.LttngEvent; +import org.eclipse.linuxtools.lttng.state.evProcessor.AbsEventProcessorFactory; +import org.eclipse.linuxtools.lttng.state.evProcessor.EventProcessorProxy; +import org.eclipse.linuxtools.lttng.state.evProcessor.IEventProcessing; +import org.eclipse.linuxtools.lttng.state.model.ILttngStateInputRef; +import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; +import org.eclipse.linuxtools.tmf.event.TmfEvent; +import org.eclipse.linuxtools.tmf.trace.TmfTrace; + +/** + * @author Alvaro + * + */ +public class StateStacksHandler { + // ======================================================================== + // Table data + // ======================================================================= + protected LttngTraceState traceStateModel = null; + protected Set eventsNotHandled = null; + protected Vector listeners = new Vector(); + + // ======================================================================== + // Constructors + // ======================================================================== + public StateStacksHandler(LttngTraceState model) { + // It's assumed to have one instance of this class per Trace + this.traceStateModel = model; + } + + // ======================================================================== + // Methods + // ======================================================================= + /** + * Initialised by manager, any time a JniTrace selection is updated + * + * @param trace + * @param log + * + */ + void init(TmfTrace log) throws LttngStateException { + if (log == null) { + throw new LttngStateException("No TmfTrace object available!"); + } + + // this.trace = trace; + ILttngStateInputRef ref = new LttngStateInputRef(log); + this.traceStateModel.init(ref); + } + + + protected void processEvent(TmfEvent tmfEvent) /* throws LttngStateException */{ + if (tmfEvent == null) { + return; + } + + if (!(tmfEvent instanceof LttngEvent)) { + TraceDebug + .debug("The event received is not an instance of LttngEvent and can not be processed"); + } + + LttngEvent trcEvent = (LttngEvent) tmfEvent; +// LttngEventField[] fields = ((LttngEventContent)trcEvent.getContent()).getFields(); + + if (trcEvent != null) { + String inEventName = trcEvent.getMarkerName(); + // String inChannel = trcEvent.getChannelName(); + // TraceDebug.debug("Event: " + inEventName); + + // Check if the received event is a transition state event + // TODO: Remove temporarily to allow other events to go to the + // statistics view. + // Needs restructuring. + // Events eventStruct = StateStrings.getInstance() + // .getStateTransEventMap().get(inEventName); + // if (eventStruct != null) { + // String expectedChannel = eventStruct.getParent().getInName(); + // check that received channel is the expected channel in the + // structure + // if (inChannel.equals(expectedChannel)) { + // Notify the before Handlers + Set handlerRegister = EventProcessorProxy + .getInstance().getProcessingFactories(); + + // Notify the state BEFORE update handlers + for (Iterator iterator = handlerRegister + .iterator(); iterator.hasNext();) { + AbsEventProcessorFactory handlerRegistry = (AbsEventProcessorFactory) iterator + .next(); + IEventProcessing handler = handlerRegistry + .getBeforeProcessor(inEventName); + if (handler != null) { + // process State Update + handler.process(trcEvent, traceStateModel); + } + + } + + // Notify the STATE UPDATE handlers + // Only one state update expected + for (Iterator iterator = handlerRegister + .iterator(); iterator.hasNext();) { + AbsEventProcessorFactory handlerRegistry = (AbsEventProcessorFactory) iterator + .next(); + IEventProcessing handler = handlerRegistry + .getStateUpdaterProcessor(inEventName); + if (handler != null) { + // process State Update + handler.process(trcEvent, traceStateModel); + } + + } + + // Notify the AFTER update handlers + for (Iterator iterator = handlerRegister + .iterator(); iterator.hasNext();) { + AbsEventProcessorFactory handlerRegistry = (AbsEventProcessorFactory) iterator + .next(); + IEventProcessing handler = handlerRegistry + .getAfterProcessor(inEventName); + if (handler != null) { + // process State Update + handler.process(trcEvent, traceStateModel); + } + } + + // } else { + // StringBuilder sb = new StringBuilder( + // "Unexpected channel received for: " + inEventName + // + ", channel rec: " + inChannel + // + " chanel expected: " + expectedChannel); + // TraceDebug.debug(sb.toString()); + // } + // } + } + } + + /** + * Used for troubleshooting when debug mode is on + * + * @return + */ + Set getEventsNotHandled() { + return eventsNotHandled; + } + + /** + * Needed for checkpoint + * + * @param LttngTraceState + */ + public LttngTraceState getTraceStateModel() { + return traceStateModel; + } + + /** + * Needed for checkpoint + * + * @param LttngTraceState + */ + public void setTraceStateModel(LttngTraceState newTraceState) { + traceStateModel = newTraceState; + } + + /** + * Needed for verification purposes + * + * @param listener + */ + void registerListener(IEventProcessing listener) { + this.listeners.add(listener); + } + + /** + * Needed for verification purposes + * + * @param listener + */ + void deregisterListener(IEventProcessing listener) { + this.listeners.remove(listener); + } +} diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/AbsEventProcessorFactory.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/AbsEventProcessorFactory.java new file mode 100644 index 0000000000..c0a414ddff --- /dev/null +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/AbsEventProcessorFactory.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2009 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: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.state.evProcessor; + +/** + * @author alvaro + * + */ +public abstract class AbsEventProcessorFactory { + /** + * + * @return The Event Handler for received event before the State data model + * is updated. + */ + public abstract IEventProcessing getBeforeProcessor(String eventType); + + /** + * + * @return The Event Handler for received event after the State data model + * is updated. + */ + public abstract IEventProcessing getAfterProcessor(String eventType); + + /** + * + * @return The Event Handler after the complete read request is completed, + * needed e.g. to draw the last state + */ + public abstract IEventProcessing getfinishProcessor(); + + /** + * + * @return The Event Handler for received event in charge to update the + * state. Only one handler is expected so other factories must not + * override this method. + */ + public IEventProcessing getStateUpdaterProcessor(String eventType) { + return null; + } + +} diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/EventProcessorProxy.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/EventProcessorProxy.java index 272c5725f7..cb92caaf53 100644 --- a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/EventProcessorProxy.java +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/EventProcessorProxy.java @@ -16,7 +16,7 @@ import java.util.HashSet; import java.util.Set; import org.eclipse.linuxtools.lttng.TraceDebug; -import org.eclipse.linuxtools.lttng.state.evProcessor.state.StateEventToHandlerFactory; +import org.eclipse.linuxtools.lttng.state.evProcessor.state.StateUpdateFactory; /** * @author alvaro @@ -27,7 +27,7 @@ public class EventProcessorProxy { // Data // ======================================================================= private static EventProcessorProxy instance = null; - private final Set processingFactories = new HashSet(); + private final Set processingFactories = new HashSet(); // ======================================================================== @@ -35,7 +35,7 @@ public class EventProcessorProxy { // ======================================================================= public EventProcessorProxy() { // Manual creation of State update factory - addEventProcessorFactory(StateEventToHandlerFactory.getInstance()); + addEventProcessorFactory(StateUpdateFactory.getInstance()); } // ======================================================================== @@ -44,7 +44,7 @@ public class EventProcessorProxy { /** * @return the processingFactories */ - public Set getProcessingFactories() { + public Set getProcessingFactories() { return processingFactories; } @@ -68,7 +68,7 @@ public class EventProcessorProxy { * @param handlersFactory */ public void addEventProcessorFactory( - AbsEventToHandlerResolver handlersFactory) { + AbsEventProcessorFactory handlersFactory) { if (handlersFactory != null) { //only add the listener if not already included if (!processingFactories.contains(handlersFactory)) { @@ -86,7 +86,7 @@ public class EventProcessorProxy { * @param handlersFactory */ public void removeEventProcessorFactory( - IEventToHandlerResolver handlersFactory) { + AbsEventProcessorFactory handlersFactory) { if (handlersFactory != null) { processingFactories.remove(handlersFactory); } diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/IEventProcessing.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/IEventProcessing.java new file mode 100644 index 0000000000..d69827b491 --- /dev/null +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/IEventProcessing.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2009 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: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.state.evProcessor; + +import org.eclipse.linuxtools.lttng.event.LttngEvent; +import org.eclipse.linuxtools.lttng.state.StateStrings; +import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; + +/** + * @author alvaro + * + */ +public interface IEventProcessing { + + // ======================================================================== + // Abstract methods + // ======================================================================= + public abstract boolean process(LttngEvent trcEvent, LttngTraceState traceSt); + public abstract StateStrings.Events getEventHandleType(); +} diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/state/AbsStateUpdate.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/state/AbsStateUpdate.java index 26fbc4cfce..bf82ff2e75 100644 --- a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/state/AbsStateUpdate.java +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/state/AbsStateUpdate.java @@ -18,7 +18,7 @@ import org.eclipse.linuxtools.lttng.state.StateStrings; import org.eclipse.linuxtools.lttng.state.StateStrings.ExecutionMode; import org.eclipse.linuxtools.lttng.state.StateStrings.IRQMode; import org.eclipse.linuxtools.lttng.state.StateStrings.ProcessStatus; -import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor; +import org.eclipse.linuxtools.lttng.state.evProcessor.IEventProcessing; import org.eclipse.linuxtools.lttng.state.model.LTTngCPUState; import org.eclipse.linuxtools.lttng.state.model.LttngBdevState; import org.eclipse.linuxtools.lttng.state.model.LttngExecutionState; @@ -28,7 +28,7 @@ import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; import org.eclipse.linuxtools.tmf.event.TmfTimestamp; public abstract class AbsStateUpdate extends AbsStateProcessing implements - ILttngEventProcessor { + IEventProcessing { // ======================================================================== // Data @@ -48,8 +48,7 @@ public abstract class AbsStateUpdate extends AbsStateProcessing implements exe_state.setEntry_Time(eventTime.getValue()); exe_state.setChange_Time(eventTime.getValue()); exe_state.setCum_cpu_time(0L); -// if (process != null) - exe_state.setProc_status(process.getState().getProc_status()); + exe_state.setProc_status(process.getState().getProc_status()); process.pushToExecutionStack(exe_state); } diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/state/StateUpdateFactory.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/state/StateUpdateFactory.java new file mode 100644 index 0000000000..977a672d1b --- /dev/null +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/state/StateUpdateFactory.java @@ -0,0 +1,186 @@ +/******************************************************************************* + * Copyright (c) 2009 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: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.state.evProcessor.state; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.linuxtools.lttng.state.StateStrings; +import org.eclipse.linuxtools.lttng.state.evProcessor.AbsEventProcessorFactory; +import org.eclipse.linuxtools.lttng.state.evProcessor.IEventProcessing; + +/** + * Builds a Map from string event name to a processing handler object, the + * processors implement the same interface to facilitate transparent methods + * call, + * + * The map key STring is the entry point of the raw events, using a hash speeds + * up the resolution of the appropriate processor + * + * @author alvaro + * + */ +public class StateUpdateFactory extends AbsEventProcessorFactory { + // ======================================================================== + // Data + // ======================================================================= + private final Map eventNametoProcessor = new HashMap(); + private static StateUpdateFactory instance = new StateUpdateFactory(); + private StateUpdateHandlers instantiateHandler = new StateUpdateHandlers(); + + // ======================================================================== + // Constructors + // ======================================================================= + private StateUpdateFactory() { + //create one instance of each individual event handler and add the instance to the map + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_SYSCALL_ENTRY + .getInName(), instantiateHandler.getSyscallEntryHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_SYSCALL_EXIT + .getInName(), instantiateHandler.getsySyscallExitHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_TRAP_ENTRY + .getInName(), instantiateHandler.getTrapEntryHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_TRAP_EXIT + .getInName(), instantiateHandler.getTrapExitHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_PAGE_FAULT_ENTRY + .getInName(), instantiateHandler.getTrapEntryHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_PAGE_FAULT_EXIT + .getInName(), instantiateHandler.getTrapExitHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY + .getInName(), instantiateHandler.getTrapEntryHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_PAGE_FAULT_NOSEM_EXIT + .getInName(), instantiateHandler.getTrapExitHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_IRQ_ENTRY + .getInName(), instantiateHandler.getIrqEntryHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_IRQ_EXIT + .getInName(), instantiateHandler.getIrqExitHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_SOFT_IRQ_RAISE + .getInName(), instantiateHandler.getSoftIrqRaiseHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_SOFT_IRQ_ENTRY + .getInName(), instantiateHandler.getSoftIrqEntryHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_SOFT_IRQ_EXIT + .getInName(), instantiateHandler.getSoftIrqExitHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_LIST_INTERRUPT + .getInName(), instantiateHandler.getEnumInterruptHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_REQUEST_ISSUE + .getInName(), instantiateHandler.getBdevRequestIssueHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_REQUEST_COMPLETE + .getInName(), instantiateHandler.getBdevRequestCompleteHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_FUNCTION_ENTRY + .getInName(), instantiateHandler.getFunctionEntryHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_FUNCTION_EXIT + .getInName(), instantiateHandler.getFunctionExitHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_SYS_CALL_TABLE + .getInName(), instantiateHandler.getDumpSyscallHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_KPROBE_TABLE + .getInName(), instantiateHandler.getDumpKprobeHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_SOFTIRQ_VEC + .getInName(), instantiateHandler.getDumpSoftIrqHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_SCHED_SCHEDULE + .getInName(), instantiateHandler.getSchedChangeHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_PROCESS_FORK + .getInName(), instantiateHandler.getProcessForkHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_KTHREAD_CREATE + .getInName(), instantiateHandler.getProcessKernelThreadHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_PROCESS_EXIT + .getInName(), instantiateHandler.getProcessExitHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_PROCESS_FREE + .getInName(), instantiateHandler.getProcessFreeHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_EXEC + .getInName(), instantiateHandler.getProcessExecHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_THREAD_BRAND + .getInName(), instantiateHandler.GetThreadBrandHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_STATEDUMP_END + .getInName(), instantiateHandler.getStateDumpEndHandler()); + + eventNametoProcessor.put(StateStrings.Events.LTT_EVENT_PROCESS_STATE + .getInName(), instantiateHandler.getEnumProcessStateHandler()); + + + } + + // ======================================================================== + // Public methods + // ======================================================================= + /** + * The event processors are common to all traces an multiple instances will + * use more memory unnecessarily + * + * @return + */ + public static AbsEventProcessorFactory getInstance() { + if (instance == null) { + instance = new StateUpdateFactory(); + } + return instance; + } + + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.lttng.state.evProcessor.AbsEventProcessorFactory#getAfterProcessor(java.lang.String) + */ + @Override + public IEventProcessing getAfterProcessor(String eventType) { + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.lttng.state.evProcessor.AbsEventProcessorFactory#getBeforeProcessor(java.lang.String) + */ + @Override + public IEventProcessing getBeforeProcessor(String eventType) { + return null; + } + + /** + * This is the only event handler to update the State provider + * @return + * + */ + @Override + public IEventProcessing getStateUpdaterProcessor(String eventType) { + return eventNametoProcessor.get(eventType); + } + + @Override + public IEventProcessing getfinishProcessor() { + // No finishing processor used + return null; + } +} diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/state/StateUpdateHandlers.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/state/StateUpdateHandlers.java index d15b200831..48292b86b6 100644 --- a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/state/StateUpdateHandlers.java +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/evProcessor/state/StateUpdateHandlers.java @@ -25,7 +25,7 @@ import org.eclipse.linuxtools.lttng.state.StateStrings.Fields; import org.eclipse.linuxtools.lttng.state.StateStrings.IRQMode; import org.eclipse.linuxtools.lttng.state.StateStrings.ProcessStatus; import org.eclipse.linuxtools.lttng.state.StateStrings.ProcessType; -import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor; +import org.eclipse.linuxtools.lttng.state.evProcessor.IEventProcessing; import org.eclipse.linuxtools.lttng.state.model.LTTngCPUState; import org.eclipse.linuxtools.lttng.state.model.LttngBdevState; import org.eclipse.linuxtools.lttng.state.model.LttngExecutionState; @@ -45,9 +45,11 @@ import org.eclipse.linuxtools.tmf.event.TmfTimestamp; */ class StateUpdateHandlers { - final ILttngEventProcessor getSyscallEntryHandler() { + final IEventProcessing getSyscallEntryHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_SYSCALL_ENTRY; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { @@ -83,13 +85,20 @@ class StateUpdateHandlers { submode, trcEvent.getTimestamp(), traceSt); return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } - final ILttngEventProcessor getsySyscallExitHandler() { + final IEventProcessing getsySyscallExitHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_SYSCALL_EXIT; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { @@ -108,6 +117,11 @@ class StateUpdateHandlers { return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -117,9 +131,11 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getTrapEntryHandler() { + final IEventProcessing getTrapEntryHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_TRAP_ENTRY; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { Long cpu = trcEvent.getCpuId(); @@ -149,25 +165,19 @@ class StateUpdateHandlers { LTTngCPUState cpust = traceSt.getCpu_states().get(cpu); cpu_push_mode(cpust, StateStrings.CpuMode.LTTV_CPU_TRAP); cpust.pushToTrapStack(trap); /* update trap status */ - + // update Trap State - LttngTrapState trap_state = null; - trap_state = traceSt.getTrap_states().get(trap); - - // If the trape_state exists, just increment it's counter, - // otherwise, create it - if ( trap_state == null ) { - trap_state = new LttngTrapState(); - trap_state.incrementRunning(); - traceSt.getTrap_states().put(trap, trap_state); - } - else { - trap_state.incrementRunning(); - } - + LttngTrapState trap_state = traceSt.getTrap_states().get(trap); + trap_state.incrementRunning(); + return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -176,9 +186,11 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getTrapExitHandler() { + final IEventProcessing getTrapExitHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_TRAP_EXIT; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { @@ -203,6 +215,11 @@ class StateUpdateHandlers { return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -211,9 +228,11 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getIrqEntryHandler() { + final IEventProcessing getIrqEntryHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_IRQ_ENTRY; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { @@ -221,10 +240,7 @@ class StateUpdateHandlers { Long irq = getAFieldLong(trcEvent, traceSt, Fields.LTT_FIELD_IRQ_ID); - if (irq == null || traceSt.getIrq_states().get(irq) == null) { - if (irq != null) { - System.out.println("Invalid irq (" + irq + "), ts = " + trcEvent.getOriginalTimestamp()); - } + if (irq == null) { return true; } @@ -254,6 +270,10 @@ class StateUpdateHandlers { return false; } + + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -262,9 +282,11 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getSoftIrqExitHandler() { + final IEventProcessing getSoftIrqExitHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_SOFT_IRQ_EXIT; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { @@ -280,9 +302,7 @@ class StateUpdateHandlers { if (softirq != -1) { LttngSoftIRQState softIrqstate = traceSt .getSoft_irq_states().get(softirq); - if (softIrqstate != null) { - softIrqstate.decrementRunning(); - } + softIrqstate.decrementRunning(); } /* update cpu status */ @@ -290,6 +310,11 @@ class StateUpdateHandlers { return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -298,9 +323,11 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getIrqExitHandler() { + final IEventProcessing getIrqExitHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_IRQ_EXIT; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { @@ -325,6 +352,11 @@ class StateUpdateHandlers { return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -333,7 +365,7 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getSoftIrqRaiseHandler() { + final IEventProcessing getSoftIrqRaiseHandler() { AbsStateUpdate handler = new AbsStateUpdate() { private Events eventType = Events.LTT_EVENT_SOFT_IRQ_RAISE; @@ -376,6 +408,11 @@ class StateUpdateHandlers { return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -384,9 +421,11 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getSoftIrqEntryHandler() { + final IEventProcessing getSoftIrqEntryHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_SOFT_IRQ_ENTRY; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { @@ -434,6 +473,11 @@ class StateUpdateHandlers { return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -443,7 +487,7 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getEnumInterruptHandler() { + final IEventProcessing getEnumInterruptHandler() { AbsStateUpdate handler = new AbsStateUpdate() { private Events eventType = Events.LTT_EVENT_LIST_INTERRUPT; @@ -475,6 +519,11 @@ class StateUpdateHandlers { return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -484,9 +533,11 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getBdevRequestIssueHandler() { + final IEventProcessing getBdevRequestIssueHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_REQUEST_ISSUE; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { @@ -531,6 +582,11 @@ class StateUpdateHandlers { return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -545,9 +601,11 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getBdevRequestCompleteHandler() { + final IEventProcessing getBdevRequestCompleteHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_REQUEST_COMPLETE; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { @@ -586,6 +644,11 @@ class StateUpdateHandlers { return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -600,9 +663,11 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getFunctionEntryHandler() { + final IEventProcessing getFunctionEntryHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_FUNCTION_ENTRY; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { Long cpu = trcEvent.getCpuId(); @@ -613,6 +678,11 @@ class StateUpdateHandlers { return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -621,9 +691,11 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getFunctionExitHandler() { + final IEventProcessing getFunctionExitHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_FUNCTION_EXIT; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { @@ -634,6 +706,11 @@ class StateUpdateHandlers { return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -648,9 +725,11 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getDumpSyscallHandler() { + final IEventProcessing getDumpSyscallHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_SYS_CALL_TABLE; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { // obtain the syscall id @@ -668,6 +747,11 @@ class StateUpdateHandlers { return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -682,9 +766,11 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getDumpKprobeHandler() { + final IEventProcessing getDumpKprobeHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_KPROBE_TABLE; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { @@ -697,6 +783,11 @@ class StateUpdateHandlers { return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -711,9 +802,11 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getDumpSoftIrqHandler() { + final IEventProcessing getDumpSoftIrqHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_SOFTIRQ_VEC; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { @@ -734,6 +827,11 @@ class StateUpdateHandlers { return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -748,9 +846,11 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getSchedChangeHandler() { + final IEventProcessing getSchedChangeHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_SCHED_SCHEDULE; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { @@ -878,6 +978,11 @@ class StateUpdateHandlers { return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -893,9 +998,11 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getProcessForkHandler() { + final IEventProcessing getProcessForkHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_PROCESS_FORK; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { @@ -1007,6 +1114,11 @@ class StateUpdateHandlers { return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -1021,9 +1133,11 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getProcessKernelThreadHandler() { + final IEventProcessing getProcessKernelThreadHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_KTHREAD_CREATE; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { /* @@ -1058,6 +1172,11 @@ class StateUpdateHandlers { return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -1072,9 +1191,11 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getProcessExitHandler() { + final IEventProcessing getProcessExitHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_PROCESS_EXIT; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { @@ -1095,6 +1216,11 @@ class StateUpdateHandlers { return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -1109,9 +1235,11 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getProcessFreeHandler() { + final IEventProcessing getProcessFreeHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_PROCESS_FREE; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { @@ -1171,6 +1299,11 @@ class StateUpdateHandlers { // return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -1185,9 +1318,11 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getProcessExecHandler() { + final IEventProcessing getProcessExecHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_EXEC; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { @@ -1218,6 +1353,11 @@ class StateUpdateHandlers { return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -1232,9 +1372,11 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor GetThreadBrandHandler() { + final IEventProcessing GetThreadBrandHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_THREAD_BRAND; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { @@ -1248,6 +1390,11 @@ class StateUpdateHandlers { return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } @@ -1255,9 +1402,11 @@ class StateUpdateHandlers { /** * @return */ - final ILttngEventProcessor getStateDumpEndHandler() { + final IEventProcessing getStateDumpEndHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_STATEDUMP_END; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { @@ -1278,6 +1427,11 @@ class StateUpdateHandlers { } + // @Override + public Events getEventHandleType() { + return eventType; + } + /** * Private method used to establish the first execution state in the * stack for a given process @@ -1367,9 +1521,11 @@ class StateUpdateHandlers { * * @return */ - final ILttngEventProcessor getEnumProcessStateHandler() { + final IEventProcessing getEnumProcessStateHandler() { AbsStateUpdate handler = new AbsStateUpdate() { + private Events eventType = Events.LTT_EVENT_PROCESS_STATE; + // @Override public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { @@ -1536,6 +1692,11 @@ class StateUpdateHandlers { return false; } + + // @Override + public Events getEventHandleType() { + return eventType; + } }; return handler; } diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/experiment/StateExperimentManager.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/experiment/StateExperimentManager.java index b00fd22a0f..716e22449d 100644 --- a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/experiment/StateExperimentManager.java +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/experiment/StateExperimentManager.java @@ -1,5 +1,5 @@ /******************************************************************************* -+ * Copyright (c) 2009, 2010 Ericsson + * Copyright (c) 2009 Ericsson * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which @@ -14,420 +14,144 @@ package org.eclipse.linuxtools.lttng.state.experiment; import java.util.HashMap; import java.util.Map; -import org.eclipse.linuxtools.lttng.TraceDebug; -import org.eclipse.linuxtools.lttng.control.LttngCoreProviderFactory; -import org.eclipse.linuxtools.lttng.control.LttngSyntheticEventProvider; -import org.eclipse.linuxtools.lttng.event.LttngEvent; -import org.eclipse.linuxtools.lttng.event.LttngSyntheticEvent; -import org.eclipse.linuxtools.lttng.event.LttngSyntheticEvent.SequenceInd; -import org.eclipse.linuxtools.lttng.model.LTTngTreeNode; -import org.eclipse.linuxtools.lttng.signal.ILttExperimentSelectedListener; -import org.eclipse.linuxtools.lttng.signal.StateExperimentListener; -import org.eclipse.linuxtools.lttng.state.trace.IStateTraceManager; -import org.eclipse.linuxtools.tmf.event.TmfEvent; +import org.eclipse.linuxtools.lttng.state.IStateDataRequestListener; +import org.eclipse.linuxtools.lttng.state.StateManager; +import org.eclipse.linuxtools.tmf.component.TmfComponent; import org.eclipse.linuxtools.tmf.event.TmfTimeRange; -import org.eclipse.linuxtools.tmf.experiment.TmfExperiment; -import org.eclipse.linuxtools.tmf.request.ITmfEventRequest; -import org.eclipse.linuxtools.tmf.request.TmfDataRequest; -import org.eclipse.linuxtools.tmf.request.TmfEventRequest; -import org.eclipse.linuxtools.tmf.signal.TmfExperimentUpdatedSignal; -import org.eclipse.linuxtools.tmf.trace.ITmfTrace; +import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler; +import org.eclipse.linuxtools.tmf.trace.TmfExperiment; +import org.eclipse.linuxtools.tmf.trace.TmfExperimentSelectedSignal; /** * @author alvaro * */ -public class StateExperimentManager extends LTTngTreeNode implements - ILttExperimentSelectedListener, IStateExperimentManager { +public class StateExperimentManager extends TmfComponent { // ======================================================================== // Data // ======================================================================= - private LTTngTreeNode fSelectedExperiment = null; // one selected experiment - // supported - private final StateExperimentListener fexperimentListener; - private boolean fwaitForCompletion = false; - /** - * Used to route incoming events to proper trace manager, during check point - * building - */ - private final Map ftraceToManagerMap = new HashMap(); - private LttngSyntheticEvent syntheticEvent = null; - private ITmfEventRequest fStateCheckPointRequest = null; - + + private final Map managersByID = new HashMap(); + private TmfExperiment fExperiment = null; // one experiment supported // ======================================================================== // Constructors // ======================================================================= - public StateExperimentManager(Long id, String name) { - super(id, null, name, null); - fexperimentListener = new StateExperimentListener("Experiment Manager", - this); - } + /** + * package level constructor, creation from factory + */ + StateExperimentManager() { + super(); + } // ======================================================================== // Methods // ======================================================================= -// /* (non-Javadoc) -// * @see org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager#readExperimentTimeWindow(org.eclipse.linuxtools.tmf.event.TmfTimeRange, java.lang.String, org.eclipse.linuxtools.lttng.state.IStateDataRequestListener) -// */ -// public ILttngSyntEventRequest readExperimentTimeWindow(TmfTimeRange trange, -// Object source, IRequestStatusListener listener, -// ITransEventProcessor processor) { -// -// ILttngSyntEventRequest request = null; -// -// // validate -// if (fSelectedExperiment != null) { -// // Get all trace manager nodes -// LTTngTreeNode[] traceMgrs = fSelectedExperiment.getChildren(); -// -// if (traceMgrs != null && traceMgrs.length > 0) { -// IStateTraceManager traceManager; -// // Trigger one request per trace -// for (LTTngTreeNode traceNode : traceMgrs) { -// traceManager = (IStateTraceManager) traceNode; -// request = traceManager.executeDataRequest(trange, source, -// listener, -// processor); -// } -// } -// } else { -// if (fSelectedExperiment == null) { -// TraceDebug.debug("No experiment selected"); -// } -// } -// -// return request; -// } - -// /* (non-Javadoc) -// * @see org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager#readExperiment(java.lang.String, org.eclipse.linuxtools.lttng.state.IStateDataRequestListener) -// */ -// @SuppressWarnings("unchecked") -// public void readExperiment(Object source, IRequestStatusListener listener, -// ITransEventProcessor processor) { -// // validate -// if (fSelectedExperiment != null) { -// TmfExperiment experiment = (TmfExperiment) fSelectedExperiment -// .getValue(); -// TmfTimeRange trange = experiment.getTimeRange(); -// readExperimentTimeWindow(trange, source, listener, processor); -// } else { -// TraceDebug.debug("No selected experiment available"); -// } -// } - - - - /* - * (non-Javadoc) + /** + * Return the Map of unique id to Manager instance * - * @see - * org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager - * #experimentSelected_prep - * (org.eclipse.linuxtools.tmf.experiment.TmfExperiment) + * @return */ - public void experimentSelected_prep(TmfExperiment experiment) { - LTTngTreeNode experimentNode = null; - if (experiment != null) { - experimentNode = getChildByName(experiment.getName()); - // keep experiment if already loaded with the same value - if (experimentNode != null - && experimentNode.getValue() != experiment) { - // rebuild the experiment nodes from scratch - removeChild(experimentNode); - experimentNode = null; - } - - // Make sure all traces involved have a corresponding state manager - // and - // state system to request its initial data - if (experimentNode == null) { - // Create the new experiment tree node - experimentNode = new LTTngTreeNode(getNextUniqueId(), this, - experiment.getName(), experiment); - // add the new experiment to this children list - addChild(experimentNode); - } - - // Make sure the traces exists in the tree - ITmfTrace[] rtraces = experiment.getTraces(); - String traceName; - LTTngTreeNode traceStateManagerNode; - // StateStacksHandler - for (ITmfTrace rtrace : rtraces) { - traceName = rtrace.getName(); - traceStateManagerNode = experimentNode.getChildByName(traceName); - // Node does not exist for this experiment, so needs to be - // created - if (traceStateManagerNode == null) { - traceStateManagerNode = StateManagerFactory.getManager( - rtrace, experimentNode); - experimentNode.addChild(traceStateManagerNode); - } - } - - // Reset event provider to handle requests for the new experiment - LttngSyntheticEventProvider synEventProvider = LttngCoreProviderFactory - .getEventProvider(); - synEventProvider.reset(experimentNode); - - // preserve the selected experiment - fSelectedExperiment = experimentNode; - } + public Map getManagersByID() { + return managersByID; } - /* - * (non-Javadoc) + /** + * Read all available traces from the nearest checkpoint from start position + * to the end of a specified time range * - * @see org.eclipse.linuxtools.lttng.signal.ILttExperimentSelectedListener# - * experimentSelected(java.lang.Object, - * org.eclipse.linuxtools.tmf.experiment.TmfExperiment) + * @param trange + * @param obs + * @param transactionID + * @param display */ - public void experimentSelected(Object source, - TmfExperiment experiment) { - // validate - if (experiment == null) { - TraceDebug.debug("Received expriment is null"); - return; + public void readExperimentTimeWindow(TmfTimeRange trange, + String transactionID, IStateDataRequestListener listener) { + if (fExperiment != null) { + String id = fExperiment.getExperimentId(); + StateManager manager = managersByID.get(id); + if (manager != null) { + // TODO: A loop to request data for each trace needs to be used + // here when multiple traces are supported. + manager.executeDataRequest(trange, transactionID, listener); + } } + } - // If previous request is ongoing, cancel it before requesting a new - // one. - if (fStateCheckPointRequest != null && !fStateCheckPointRequest.isCompleted()) { - fStateCheckPointRequest.cancel(); + public void readExperiment(String transactionID, + IStateDataRequestListener listener) { + // Need someone to listen to the updates as well as an fExperiment + // loaded. + if (listener != null && fExperiment != null) { + TmfTimeRange trange = fExperiment.getTimeRange(); + String experimentId = fExperiment.getExperimentId(); + + // FIXME: there should be an id field available at the trace level + // to be fixed with the support of multiple files. + // We also need to iterate over the traces in the Experiment and + // execute a data Request on each of them + // This is also on hold till the request can be performed at a trace + // level. + // ITmfTrace[] fTraces = fExperiment.getTraces(); + // for (int i=0; i < fTraces.length; i++) { + StateManager manager = StateManagerFactory.getManager(experimentId); + manager.executeDataRequest(trange, transactionID, listener); + // } } - - // trigger data request to build the state system check points - fStateCheckPointRequest = buildCheckPoints(experiment); - -// LTTngTreeNode experimentNode = getChildByName(experiment.getName()); -// if (experimentNode != null) { -// // get the trace manager nodes -// LTTngTreeNode[] traceNodes = experimentNode.getChildren(); -// for (LTTngTreeNode traceStateManagerNode : traceNodes) { -// // The trace node needs to perform its first data request -// // for this experiment with the main goal of building its -// // checkpoints -// if (traceStateManagerNode instanceof ILttExperimentSelectedListener) { -// // no need to provide the trace to the trace manager -// ((ILttExperimentSelectedListener) traceStateManagerNode).experimentUpdated( -// new TmfExperimentUpdatedSignal(source, experiment, null), fwaitForCompletion); -// } -// } -// } } - + /* * (non-Javadoc) * - * @see org.eclipse.linuxtools.lttng.signal.ILttExperimentSelectedListener# - * experimentUpdated - * (org.eclipse.linuxtools.tmf.signal.TmfExperimentUpdatedSignal, boolean) + * @see + * org.eclipse.linuxtools.tmf.eventlog.ITmfEventLogEventListener#handleEvent + * (org.eclipse.linuxtools.tmf.eventlog.ITmfEventLogEvent) */ - public void experimentUpdated(TmfExperimentUpdatedSignal signal, boolean wait) { - // NOTE: This represents the end of TMF indexing for a trace, however - // the node was already existing and the state system check points are - // already requested and built upon selection. - // No action for the time being + @TmfSignalHandler + public void experimentSelected(TmfExperimentSelectedSignal signal) { + // TmfExperiment experiment = signal.getExperiment(); + // ITmfTrace[] traces = experiment.getTraces(); + // for (ITmfTrace trace : traces) { + // + // } + if (signal != null) { + fExperiment = signal.getExperiment(); + traceSelected(fExperiment); + } } - /** - * @return the SelectedExperiment tree node + * A new Experiment selected, notification received from the framework + * Notify the new log selection to the state handling managers + * + * @param experiment */ - public LTTngTreeNode getSelectedExperiment() { - return fSelectedExperiment; + private void traceSelected(TmfExperiment experiment) { + // TODO: Re-factor when multiple traces are supported + // traceId, as well as when the request can be specified at the trace + // level + // For the moment it does work for only one trace per experiment. + String experimentId = experiment.getExperimentId(); + StateManager manager = StateManagerFactory.getManager(experimentId); + // TODO: clearAllData shall not be applied to all manager calls below + // since that would clean all data loaded within previous iterations in + // the future loop. i.e. It can be applied to first manager in the loop. + boolean clearAllData = true; + manager.setTraceSelection(experiment, clearAllData); } - /* (non-Javadoc) - * @see org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager#getExperimentTimeRange() + /** + * @return */ - @SuppressWarnings("unchecked") public TmfTimeRange getExperimentTimeRange() { TmfTimeRange timeRangeResult = null; - if (fSelectedExperiment != null) { - timeRangeResult = ((TmfExperiment) fSelectedExperiment - .getValue()).getTimeRange(); + if (fExperiment != null) { + timeRangeResult = fExperiment.getTimeRange(); } return timeRangeResult; } - /* - * (non-Javadoc) - * - * @see java.lang.Object#finalize() - */ - @Override - protected void finalize() { - fexperimentListener.dispose(); - } - - - /* - * (non-Javadoc) - * - * @see - * org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager - * #waitForComplete(boolean) - */ - public void waitForCompletion(boolean wait) { - fwaitForCompletion = wait; - } - - private ITmfEventRequest buildCheckPoints(TmfExperiment experiment) { - // validate - if (experiment == null) { - TraceDebug.debug("Received expriment is null"); - return null; - } - - LTTngTreeNode experimentNode = getChildByName(experiment.getName()); - if (experimentNode == null) { - TraceDebug.debug("Expriment Node " + experiment.getName() + " does not exist"); - return null; - } - - // get the trace manager nodes associated to the experiment - LTTngTreeNode[] traceNodes = experimentNode.getChildren(); - synchronized (ftraceToManagerMap) { - ftraceToManagerMap.clear(); - } - - for (LTTngTreeNode traceStateManagerNode : traceNodes) { - IStateTraceManager traceManager; - try { - traceManager = (IStateTraceManager) traceStateManagerNode; - } catch (ClassCastException e) { - System.out.println(e.getStackTrace().toString()); - return null; - } - - // Clear all previously created check points as preparation to - // re-build - traceManager.clearCheckPoints(); - - // build the trace to manager mapping for event dispatching - synchronized (ftraceToManagerMap) { - ftraceToManagerMap.put(traceManager.getTrace(), traceManager); - } - } - - // if no trace mapping - if (ftraceToManagerMap.size() < 1) { - TraceDebug.debug("No traces associated to experiment " + experiment.getName()); - return null; - } - - // Prepare event data request to build state model - ITmfEventRequest request = new TmfEventRequest( - LttngEvent.class, TmfTimeRange.Eternity, - TmfDataRequest.ALL_DATA, 1) { - - Long nbEvents = 0L; - - /* - * (non-Javadoc) - * - * @see - * org.eclipse.linuxtools.tmf.request.TmfDataRequest#handleData() - */ - @Override - public void handleData() { - TmfEvent[] events = getData(); - if (events.length > 0) { - nbEvents++; - - LttngEvent event = (LttngEvent) events[0]; - ITmfTrace trace = event.getParentTrace(); - IStateTraceManager traceManager = ftraceToManagerMap - .get(trace); - if (traceManager != null) { - // obtain synthetic event - LttngSyntheticEvent synEvent = updateSynEvent(event, - traceManager); - // update state system, and save check points as needed - traceManager.handleEvent(synEvent, nbEvents); - } else { - TraceDebug - .debug("StateTraceManager not found for trace" - + trace.getName()); - } - } - } - - /* - * (non-Javadoc) - * - * @see - * org.eclipse.linuxtools.tmf.request.TmfDataRequest#handleFailure() - */ - public void handleFailure() { - printCompletedMessage(); - } - - /* - * (non-Javadoc) - * - * @see - * org.eclipse.linuxtools.tmf.request.TmfDataRequest#handleCancel() - */ - public void handleCancel() { - printCompletedMessage(); - } - - /* - * (non-Javadoc) - * - * @see - * org.eclipse.linuxtools.tmf.request.TmfDataRequest#handleSuccess() - */ - public void handleSuccess() { - printCompletedMessage(); - } - - /** - * @param header - */ - private void printCompletedMessage() { - // super.handleCompleted(); - if (TraceDebug.isDEBUG()) { - TraceDebug.debug("Trace check point building completed, number of events handled: " + nbEvents - + "\n\t\t"); - for (IStateTraceManager traceMgr : ftraceToManagerMap.values()) { - TraceDebug.debug(traceMgr.toString() + "\n\t\t"); - } - } - } - }; - - // Execute event data request - experiment.sendRequest(request); - if (fwaitForCompletion) { - try { - request.waitForCompletion(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - return request; - } - - private LttngSyntheticEvent updateSynEvent(LttngEvent e, - IStateTraceManager stateTraceManager) { - if (syntheticEvent == null || syntheticEvent.getBaseEvent() != e) { - syntheticEvent = new LttngSyntheticEvent(e); - } - - // Trace model needed by application handlers - syntheticEvent.setTraceModel(stateTraceManager.getStateModel()); - syntheticEvent.setSequenceInd(SequenceInd.UPDATE); - - return syntheticEvent; - } - -} \ No newline at end of file +} diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/experiment/StateManagerFactory.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/experiment/StateManagerFactory.java index b120b0bc56..b196ae4a7b 100644 --- a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/experiment/StateManagerFactory.java +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/experiment/StateManagerFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2010 Ericsson + * Copyright (c) 2009 Ericsson * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which @@ -12,13 +12,12 @@ package org.eclipse.linuxtools.lttng.state.experiment; -import org.eclipse.linuxtools.lttng.TraceDebug; -import org.eclipse.linuxtools.lttng.model.LTTngTreeNode; -import org.eclipse.linuxtools.lttng.state.LttngStateException; -import org.eclipse.linuxtools.lttng.state.trace.IStateTraceManager; -import org.eclipse.linuxtools.lttng.state.trace.StateTraceManager; -import org.eclipse.linuxtools.tmf.experiment.TmfExperiment; -import org.eclipse.linuxtools.tmf.trace.ITmfTrace; +import java.util.Map; + +import org.eclipse.linuxtools.lttng.state.StateManager; +import org.eclipse.linuxtools.lttng.state.StateStacksHandler; +import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; +import org.eclipse.linuxtools.lttng.state.model.StateModelFactory; /** * @author alvaro @@ -29,64 +28,36 @@ public class StateManagerFactory { // Data // ======================================================================= - private static IStateExperimentManager experimentManager = null; - /** - * Allows to modify the check point interval for every new instance of trace manager - */ - private static Long ftraceCheckPointInterval = null; + private static StateExperimentManager experimentManager = null; + private static Map instanceBook = null; - static { - initCheck(); - } // ======================================================================== // Methods // ======================================================================= /** - * @param traceUniqueId - * @param experiment + * Provide a stateManager instance per trace + * * @return */ - public static LTTngTreeNode getManager(ITmfTrace rtrace, - LTTngTreeNode experiment) { + public static StateManager getManager(String traceUniqueId) { - // Validate - if (rtrace == null) { - return null; - } - - String traceUniqueId = rtrace.getName(); if (traceUniqueId == null) { return null; } + initCheck(); - LTTngTreeNode managerNode = null; - managerNode = experiment.getChildByName(traceUniqueId); - - if (managerNode != null && managerNode instanceof IStateTraceManager) { - return managerNode; + if (instanceBook.containsKey(traceUniqueId)) { + return instanceBook.get(traceUniqueId); } -// LttngTraceState traceModel = -// StateModelFactory.getStateEntryInstance(); - StateTraceManager manager = null; - - // catch potential construction problems - try { - manager = new StateTraceManager(experiment.getNextUniqueId(), experiment, traceUniqueId, rtrace); + LttngTraceState traceModel = StateModelFactory.getStateEntryInstance(); + StateStacksHandler stateInputHandler = new StateStacksHandler( + traceModel); + StateManager manager = new StateManager(stateInputHandler); - // Allow the possibility to configure the trace state check point - // interval at creation time - if (ftraceCheckPointInterval != null) { - manager.setCheckPointInterval(ftraceCheckPointInterval); - } - - } catch (LttngStateException e) { - e.printStackTrace(); - } - - experiment.addChild(manager); + instanceBook.put(traceUniqueId, manager); return manager; } @@ -95,7 +66,8 @@ public class StateManagerFactory { * * @return */ - public static IStateExperimentManager getExperimentManager() { + public static StateExperimentManager getExperimentManager() { + initCheck(); return experimentManager; } @@ -104,18 +76,10 @@ public class StateManagerFactory { * * @param traceUniqueId */ - public static void removeManager(ITmfTrace rtrace, LTTngTreeNode rexperiment) { - Object experimentObj = rexperiment.getValue(); - if (rtrace != null && rexperiment != null - && experimentObj instanceof TmfExperiment) { - LTTngTreeNode childToremove = rexperiment.getChildByName(rtrace - .getName()); - if (childToremove != null) { - rexperiment.removeChild(childToremove); - } - } else { - TraceDebug.debug("Invalid arguments to remove manager for trace: " - + rtrace.getName()); + public static void removeManager(String traceUniqueId) { + initCheck(); + if (traceUniqueId != null && instanceBook.containsKey(traceUniqueId)) { + instanceBook.remove(traceUniqueId); } } @@ -124,9 +88,8 @@ public class StateManagerFactory { */ private static void initCheck() { if (experimentManager == null) { - Long id = 0L; // unique id - String name = "StateExperimentManager"; // name - experimentManager = new StateExperimentManager(id, name); + experimentManager = new StateExperimentManager(); + instanceBook = experimentManager.getManagersByID(); } } @@ -135,22 +98,9 @@ public class StateManagerFactory { */ public static void dispose() { if (experimentManager != null) { + experimentManager.dispose(); experimentManager = null; + instanceBook = null; } } - - /** - * @return the traceCheckPointInterval - */ - public static Long getTraceCheckPointInterval() { - return ftraceCheckPointInterval; - } - - /** - * @param traceCheckPointInterval - * the traceCheckPointInterval to set - */ - public static void setTraceCheckPointInterval(Long traceCheckPointInterval) { - StateManagerFactory.ftraceCheckPointInterval = traceCheckPointInterval; - } -} \ No newline at end of file +} diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/model/ILttngStateInputRef.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/model/ILttngStateInputRef.java new file mode 100644 index 0000000000..51584f583c --- /dev/null +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/model/ILttngStateInputRef.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2009 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: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.state.model; + +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; + +/** + * ILttngStateModelInput + *

Interface providing the data needed by the State model + * + */ + +/** + * @author alvaro + * + */ +public interface ILttngStateInputRef { + + public int getNumberOfCpus(); + public TmfTimeRange getTraceTimeWindow(); + public String getTraceId(); + public TmfTimeRange getExperimentTimeWindow(); + +} diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/model/LttngTraceState.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/model/LttngTraceState.java index cb1183fee9..4d0ff321e5 100644 --- a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/model/LttngTraceState.java +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/model/LttngTraceState.java @@ -22,7 +22,6 @@ import org.eclipse.linuxtools.lttng.state.StateStrings.ExecutionMode; import org.eclipse.linuxtools.lttng.state.StateStrings.ExecutionSubMode; import org.eclipse.linuxtools.lttng.state.StateStrings.IRQMode; import org.eclipse.linuxtools.lttng.state.StateStrings.ProcessStatus; -import org.eclipse.linuxtools.lttng.state.resource.ILttngStateContext; import org.eclipse.linuxtools.tmf.event.TmfTimeRange; /** @@ -66,7 +65,7 @@ public class LttngTraceState implements Cloneable { private int nb_events = 0; // reference to input data provider - ILttngStateContext fContext = null; + ILttngStateInputRef inputDataRef = null; String traceId = ""; // ======================================================================== @@ -132,7 +131,7 @@ public class LttngTraceState implements Cloneable { newState.irq_names = this.irq_names; // This reference should never need to be updated, should it? - newState.fContext = this.fContext; + newState.inputDataRef = this.inputDataRef; // *** We need loop on each ArrayList and HashMap, as java implement // nothing that's remotely near deep copying. @@ -206,19 +205,19 @@ public class LttngTraceState implements Cloneable { return newState; } - public void init(ILttngStateContext context) + public void init(ILttngStateInputRef inputReference) throws LttngStateException { - if (context == null) { + if (inputReference == null) { StringBuilder sb = new StringBuilder( "The input provider reference must not be null"); throw new LttngStateException(sb.toString()); } // Save the input data reference - fContext = context; + inputDataRef = inputReference; // Save traceid - traceId = fContext.getTraceId(); + traceId = inputDataRef.getTraceId(); // max time max_time_state_recomputed_in_seek = 0L; @@ -228,7 +227,7 @@ public class LttngTraceState implements Cloneable { // Obtain the total num of available CPUs and initialize the map // to the corresponding size - int numCpus = fContext.getNumberOfCpus(); + int numCpus = inputDataRef.getNumberOfCpus(); for (Long i = 0L; i < numCpus; i++) { cpu_states.put(i, new LTTngCPUState()); } @@ -257,7 +256,7 @@ public class LttngTraceState implements Cloneable { processes.clear(); nb_events = 0; - TmfTimeRange timeWin = fContext.getTraceTimeWindow(); + TmfTimeRange timeWin = inputDataRef.getTraceTimeWindow(); /* Put the per cpu running_process to beginning state : process 0. */ for (Long i = 0L; i < numCpus; i++) { @@ -327,7 +326,7 @@ public class LttngTraceState implements Cloneable { * @return total number of CPUs registered as read from the Trace */ public int getNumberOfCPUs() { - return fContext.getNumberOfCpus(); + return inputDataRef.getNumberOfCpus(); } /** @@ -335,8 +334,8 @@ public class LttngTraceState implements Cloneable { * * @return */ - public ILttngStateContext getContext() { - return fContext; + public ILttngStateInputRef getInputDataRef() { + return inputDataRef; } public Long getMax_time_state_recomputed_in_seek() { diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/model/LttngTrapState.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/model/LttngTrapState.java index 94dba7db07..d1c3394a36 100644 --- a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/model/LttngTrapState.java +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/model/LttngTrapState.java @@ -23,16 +23,11 @@ public class LttngTrapState implements Cloneable { // Data // ======================================================================= private Long running; - + // ======================================================================== // Constructor // ======================================================================= - - public LttngTrapState() { - this.running = 0L; - } - public LttngTrapState(Long running) { this.running = running; } @@ -77,10 +72,4 @@ public class LttngTrapState implements Cloneable { running--; } } - - @Override - public String toString() { - return "running : " + running; - } - } \ No newline at end of file diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/model/StateModelFactory.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/model/StateModelFactory.java index 8ab180e119..81c806b222 100644 --- a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/model/StateModelFactory.java +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/state/model/StateModelFactory.java @@ -12,7 +12,6 @@ package org.eclipse.linuxtools.lttng.state.model; import org.eclipse.linuxtools.lttng.state.LttngStateException; -import org.eclipse.linuxtools.lttng.state.resource.ILttngStateContext; /** * Entry point to the package @@ -48,7 +47,7 @@ public class StateModelFactory { * @return */ public static LttngTraceState getStateEntryInstance( - ILttngStateContext stateInputRef) { + ILttngStateInputRef stateInputRef) { LttngTraceState traceState = new LttngTraceState(); try { traceState.init(stateInputRef); diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/trace/LTTngTextTrace.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/trace/LTTngTextTrace.java index 8fa150d0ed..61612f81c6 100644 --- a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/trace/LTTngTextTrace.java +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/trace/LTTngTextTrace.java @@ -15,6 +15,7 @@ package org.eclipse.linuxtools.lttng.trace; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; +import java.util.Collections; import java.util.HashMap; import org.eclipse.linuxtools.lttng.event.LttngEvent; @@ -25,16 +26,16 @@ import org.eclipse.linuxtools.lttng.event.LttngEventSource; import org.eclipse.linuxtools.lttng.event.LttngEventType; import org.eclipse.linuxtools.lttng.event.LttngTimestamp; import org.eclipse.linuxtools.lttng.jni.JniEvent; -import org.eclipse.linuxtools.tmf.event.TmfNoSuchFieldException; +import org.eclipse.linuxtools.tmf.event.TmfEvent; import org.eclipse.linuxtools.tmf.event.TmfTimeRange; -import org.eclipse.linuxtools.tmf.trace.ITmfLocation; +import org.eclipse.linuxtools.tmf.event.TmfTimestamp; +import org.eclipse.linuxtools.tmf.request.ITmfRequestHandler; import org.eclipse.linuxtools.tmf.trace.ITmfTrace; -import org.eclipse.linuxtools.tmf.trace.TmfCheckpoint; -import org.eclipse.linuxtools.tmf.trace.TmfContext; -import org.eclipse.linuxtools.tmf.trace.TmfLocation; import org.eclipse.linuxtools.tmf.trace.TmfTrace; +import org.eclipse.linuxtools.tmf.trace.TmfTraceCheckpoint; +import org.eclipse.linuxtools.tmf.trace.TmfTraceContext; -public class LTTngTextTrace extends TmfTrace implements ITmfTrace { +public class LTTngTextTrace extends TmfTrace implements ITmfTrace, ITmfRequestHandler { private LttngTimestamp eventTimestamp = null; private LttngEventSource eventSource = null; private LttngEventType eventType = null; @@ -59,7 +60,7 @@ public class LTTngTextTrace extends TmfTrace implements ITmfTrace { } public LTTngTextTrace(String path, boolean skipIndexing) throws Exception { - super(path, LttngEvent.class, path, 1); + super(path, 1, true); tracepath = path; traceTypes = new HashMap(); @@ -70,27 +71,27 @@ public class LTTngTextTrace extends TmfTrace implements ITmfTrace { eventContent = new TextLttngEventContent(currentLttngEvent); eventReference = new LttngEventReference(this.getName()); - currentLttngEvent = new TextLttngEvent(this, eventTimestamp, eventSource, eventType, eventContent, eventReference); + currentLttngEvent = new TextLttngEvent(eventTimestamp, eventSource, eventType, eventContent, eventReference); eventContent.setEvent(currentLttngEvent); if ( positionToFirstEvent() == false ) { throw new IOException("Fail to position to the beginning of the trace"); } else { - fIndexPageSize = 1000; + fCacheSize = 1000; // Skip indexing if asked -// if ( skipIndexing == true ) { - fCheckpoints.add(new TmfCheckpoint(new LttngTimestamp(0L), new TmfLocation(0L))); -// } -// else { -// indexTrace(true); -// } + if ( skipIndexing == true ) { + fCheckpoints.add(new TmfTraceCheckpoint(new LttngTimestamp(0L), 0L)); + } + else { + indexStream(); + } Long endTime = currentLttngEvent.getTimestamp().getValue(); positionToFirstEvent(); - getNextEvent(new TmfContext(null, 0)); + getNextEvent(new TmfTraceContext(null, null, 0)); Long starTime = currentLttngEvent.getTimestamp().getValue(); positionToFirstEvent(); @@ -101,27 +102,59 @@ public class LTTngTextTrace extends TmfTrace implements ITmfTrace { } - public LTTngTextTrace(LTTngTextTrace oldTrace) throws Exception { - this(oldTrace.getPath(), true); - - // *** VERIFY *** - // Is this safe? - fCheckpoints = oldTrace.fCheckpoints; + private LTTngTextTrace(LTTngTrace oldStream) throws Exception { + super(null); + throw new Exception("Copy constructor should never be use with a LTTngTrace!"); } - public LTTngTextTrace createTraceCopy() { - - LTTngTextTrace returnedTrace = null; - - try { - returnedTrace = new LTTngTextTrace(this); - } - catch (Exception e) { - System.out.println("ERROR : Could not create LTTngTextTrace copy (createTraceCopy).\nError is : " + e.getStackTrace()); - } - - return returnedTrace; - } + @Override + public void indexStream() { + // Position the trace at the beginning + TmfTraceContext context = seekLocation(null); + + long nbEvents=1L; + fCheckpoints.add(new TmfTraceCheckpoint(new LttngTimestamp(0L), 0L)); + + LttngTimestamp startTime = null; + LttngTimestamp lastTime = new LttngTimestamp(); + LttngTimestamp timestamp = null; + Long previousCharRead = 0L; + + TextLttngEvent tmpEvent = (TextLttngEvent)getNextEvent(context); + + while ( tmpEvent != null) { + timestamp = (LttngTimestamp)context.getTimestamp(); + previousCharRead = nbCharRead; + + if ( startTime == null ) { + startTime = new LttngTimestamp(timestamp.getValue()); + } + + if ((++nbEvents % fCacheSize) == 0) { + fCheckpoints.add(new TmfTraceCheckpoint(new LttngTimestamp(timestamp.getValue()), previousCharRead)); + } + + tmpEvent = (TextLttngEvent)getNextEvent(context); + } + + if (timestamp != null) { + lastTime.setValue(timestamp.getValue()); + + setTimeRange( new TmfTimeRange(startTime, lastTime) ); + notifyListeners(getTimeRange()); + } + + fNbEvents = nbEvents; + + if ( showDebug == true ) { + for ( int pos=0; pos < fCheckpoints.size(); pos++) { + System.out.print(pos + ": " + "\t"); + System.out.print( fCheckpoints.get(pos).getTimestamp() + "\t" ); + System.out.println( fCheckpoints.get(pos).getLocation() ); + } + } + + } private boolean positionToFirstEvent() { @@ -150,23 +183,15 @@ public class LTTngTextTrace extends TmfTrace implements ITmfTrace { return isSuccessful; } - private void skipToPosition(TmfLocation skip) { + private void skipToPosition(Long skipPosition) { try { - long skipPosition = skip.getLocation(); - if ( skipPosition < 0 ) { - skipPosition = 0L; - } - if ( showDebug == true ) { System.out.println("skipToPosition(Long skipPosition)"); System.out.println("\tSkipping to : " + skipPosition); System.out.println(); } positionToFirstEvent(); - long nbSkipped = br.skip(skipPosition); - if ( nbSkipped != skipPosition) { - throw new IOException("Too few characters skipped, positionning failed! (skipToPosition)"); - } + br.skip(skipPosition); nbCharRead = skipPosition; } @@ -175,23 +200,134 @@ public class LTTngTextTrace extends TmfTrace implements ITmfTrace { } } - @Override - @SuppressWarnings("unchecked") - public TmfContext seekLocation(ITmfLocation location) { + public TmfTraceContext seekLocation(Object location) { if (location == null) { - location = new TmfLocation(0L); + location = 0L; } - - if (!((TmfLocation) location).getLocation().equals(nbCharRead)) { - skipToPosition((TmfLocation) location); + + TmfTraceContext tmpTraceContext = new TmfTraceContext(nbCharRead, (LttngTimestamp)currentLttngEvent.getTimestamp(), 0L); + Long previousCharRead = nbCharRead; + Long previousTimestamp = currentLttngEvent.getTimestamp().getValue(); + Long tmploc = (Long)location; + + if ( showDebug == true ) { + System.out.println("seekLocation(Object location)"); + System.out.println("\ttimestamp: " + (LttngTimestamp)currentLttngEvent.getTimestamp()); + System.out.println("\tnbCharRead:" + nbCharRead); + System.out.println("\tlocation: " + location); + System.out.println(); } - - TmfContext tmpTraceContext = new TmfContext(location, 0L); + + if ( tmploc < nbCharRead ) { + skipToPosition(tmploc); + } + + if ( tmploc > nbCharRead ) { + while ( tmploc > nbCharRead ) { + previousCharRead = nbCharRead; + previousTimestamp = currentLttngEvent.getTimestamp().getValue(); + getNextEvent(tmpTraceContext); + } + } + + tmpTraceContext.setTimestamp(new LttngTimestamp(previousTimestamp)); + tmpTraceContext.setLocation(previousCharRead); return tmpTraceContext; } - private LttngEvent parseMyNextEvent(TmfContext context) { + + @Override + public TmfTraceContext seekEvent(TmfTimestamp timestamp) { + + if (timestamp == null) { + timestamp = getStartTime(); + } + + int index = Collections.binarySearch(fCheckpoints, new TmfTraceCheckpoint(timestamp, 0)); + + if (index < 0) { + index = 0; + } + + Object location = (index < fCheckpoints.size()) ? fCheckpoints.elementAt(index).getLocation() : null; + + if ( showDebug == true ) { + System.out.println("seekEvent(TmfTimestamp timestamp)"); + System.out.println("\ttimestamp: " + timestamp.getValue()); + System.out.println("\tindex: " + index); + System.out.println("\tlocation: " + location); + System.out.println(); + } + + // *** HACK *** + // We only know the timestamp AFTER we read the actual event + // For this reason, we save the current "position" in byte (nbCharRead) and we seek back 1 event after we find our event + TmfTraceContext currentEventContext = seekLocation(location); + + Long previousCharRead = nbCharRead; + Long previousTimestamp = currentLttngEvent.getTimestamp().getValue(); + TmfEvent event = getNextEvent(currentEventContext); + + while ( (event != null) && (event.getTimestamp().getValue() < timestamp.getValue()) ) { + previousCharRead = nbCharRead; + previousTimestamp = currentLttngEvent.getTimestamp().getValue(); + event = getNextEvent(currentEventContext); + } + + if ( event != null ) { + skipToPosition(previousCharRead); + currentEventContext.setLocation(previousCharRead); + currentEventContext.setTimestamp(new LttngTimestamp(previousTimestamp)); + } + + return currentEventContext; + } + + @Override + public TmfTraceContext seekEvent(long position) { + + int checkPointPos = ((int)position / fCacheSize); + + Object location; + location = ( checkPointPos < fCheckpoints.size()) ? fCheckpoints.elementAt(checkPointPos).getLocation() : null; + + long index = ((position / fCacheSize)*fCacheSize)-1; + + if ( index < 0) { + index = 0; + } + + if ( showDebug == true ) { + System.out.println("seekEvent(long position)"); + System.out.println("\tposition: " + position); + System.out.println("\tindex: " + index); + System.out.println("\tlocation: " + location); + System.out.println(); + } + TmfTraceContext currentEventContext = seekLocation(location); + Long previousCharRead = (Long)currentEventContext.getLocation(); + Long previousTimestamp = currentEventContext.getTimestamp().getValue(); + + TmfEvent event = null; + while (index < position) { + event = getNextEvent(currentEventContext); + previousCharRead = nbCharRead; + previousTimestamp = currentLttngEvent.getTimestamp().getValue(); + index++; + } + + if ( event != null ) { + skipToPosition(previousCharRead); + currentEventContext.setLocation(previousCharRead); + currentEventContext.setTimestamp(new LttngTimestamp(previousTimestamp)); + } + + return currentEventContext; + } + + @Override + public TmfEvent getNextEvent(TmfTraceContext context) { // All parsing variables declared here so to be able to print them into the catch if needed String tmpContent = null; @@ -236,14 +372,14 @@ public class LTTngTextTrace extends TmfTrace implements ITmfTrace { // *** HACK *** // Evil exit case here : the two last line of the text dump does not contain "." - // We should check in a better way (string comparison and such) but it make the whole process to weight a lot more + // We should check in a better way (string comparaison and such) but it make the whole process to weight a lot more // Conclusion : this is ugly but fast. if ( tmpCurIndex < 0 ) { if ( showDebug == true ) { System.out.println("END OF FILE."); System.out.println(); } - return null; + return returnedEvent; } tracefile = tmpContent.substring(tmpPrevIndex, tmpCurIndex ).trim(); @@ -394,6 +530,9 @@ public class LTTngTextTrace extends TmfTrace implements ITmfTrace { currentLttngEvent.setContent(eventContent); currentLttngEvent.setType(traceTypes.get(tmpTypeKey)); + context.setTimestamp(eventTimestamp); + context.setLocation(nbCharRead); + returnedEvent = currentLttngEvent; } else if ( showDebug == true ) { @@ -417,18 +556,34 @@ public class LTTngTextTrace extends TmfTrace implements ITmfTrace { } @Override - public ITmfLocation getCurrentLocation() { - return new TmfLocation(nbCharRead); + public Object getCurrentLocation() { + return nbCharRead; } - @Override - public LttngEvent parseEvent(TmfContext context) { - context = seekLocation(context.getLocation()); - return parseMyNextEvent(context); + @Override + public LttngEvent parseEvent(TmfTraceContext context) { + Long location = null; + LttngEvent returnedEvent = null; + + if ( (currentLttngEvent!= null) && (! currentLttngEvent.getTimestamp().equals(context.getTimestamp()) ) ) { + seekEvent(context.getTimestamp()); + getNextEvent(context); + } + + if ( currentLttngEvent != null ) { + returnedEvent = currentLttngEvent; + } + location = (Long)getCurrentLocation(); + + context.setLocation(location); + context.setTimestamp(currentLttngEvent.getTimestamp()); + context.incrIndex(); + + return returnedEvent; } - public int getCpuNumber() { + public int getCpuNumber() { return cpuNumber; } } @@ -437,19 +592,17 @@ public class LTTngTextTrace extends TmfTrace implements ITmfTrace { // Redefine event to override method we know won't work with a Text tracefile class TextLttngEvent extends LttngEvent { - public TextLttngEvent( TmfTrace parent, - LttngTimestamp timestamp, + public TextLttngEvent( LttngTimestamp timestamp, LttngEventSource source, LttngEventType type, LttngEventContent content, LttngEventReference reference) { - super(parent, timestamp, source, type, content, reference, null); + super(timestamp, source, type, content, reference, null); } public TextLttngEvent(TextLttngEvent oldEvent) { this( - oldEvent.getParentTrace(), (LttngTimestamp)oldEvent.getTimestamp(), (LttngEventSource)oldEvent.getSource(), (LttngEventType)oldEvent.getType(), @@ -504,15 +657,12 @@ class TextLttngEventContent extends LttngEventContent { @Override public LttngEventField getField(int position) { LttngEventField returnedField = null; - String label = null; - try { - label = fParentEvent.getType().getLabel(position); - returnedField = this.getField(label); - } - catch (TmfNoSuchFieldException e) { - System.out.println("Invalid field position requested : " + position + ", ignoring (getField)."); - } + String label = fParentEvent.getType().getLabel(position); + + if ( label != null ) { + returnedField = this.getField(label); + } return returnedField; } -} \ No newline at end of file +} diff --git a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/trace/LTTngTrace.java b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/trace/LTTngTrace.java index a9496e603c..c1b75ba8b4 100644 --- a/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/trace/LTTngTrace.java +++ b/org.eclipse.linuxtools.lttng/src/org/eclipse/linuxtools/lttng/trace/LTTngTrace.java @@ -22,20 +22,16 @@ import org.eclipse.linuxtools.lttng.event.LttngEventContent; import org.eclipse.linuxtools.lttng.event.LttngEventReference; import org.eclipse.linuxtools.lttng.event.LttngEventSource; import org.eclipse.linuxtools.lttng.event.LttngEventType; -import org.eclipse.linuxtools.lttng.event.LttngLocation; import org.eclipse.linuxtools.lttng.event.LttngTimestamp; import org.eclipse.linuxtools.lttng.jni.JniEvent; import org.eclipse.linuxtools.lttng.jni.JniMarker; +import org.eclipse.linuxtools.lttng.jni.JniTime; import org.eclipse.linuxtools.lttng.jni.JniTrace; import org.eclipse.linuxtools.lttng.jni.JniTracefile; -import org.eclipse.linuxtools.lttng.jni.common.JniTime; -import org.eclipse.linuxtools.lttng.jni.exception.JniException; -import org.eclipse.linuxtools.lttng.jni.factory.JniTraceFactory; import org.eclipse.linuxtools.tmf.event.TmfTimeRange; import org.eclipse.linuxtools.tmf.event.TmfTimestamp; -import org.eclipse.linuxtools.tmf.trace.ITmfLocation; -import org.eclipse.linuxtools.tmf.trace.TmfContext; import org.eclipse.linuxtools.tmf.trace.TmfTrace; +import org.eclipse.linuxtools.tmf.trace.TmfTraceContext; class LTTngTraceException extends LttngException { @@ -52,38 +48,25 @@ class LTTngTraceException extends LttngException { * LTTng trace implementation. It accesses the C trace handling library * (seeking, reading and parsing) through the JNI component. */ -public class LTTngTrace extends TmfTrace { - - public static boolean printDebug = false; - public static boolean uniqueEvent = false; - - private final static boolean SHOW_LTT_DEBUG_DEFAULT = false; - private final static boolean IS_PARSING_NEEDED_DEFAULT = true; - private final static int CHECKPOINT_PAGE_SIZE = 1000; +public class LTTngTrace extends TmfTrace { + private final static boolean SHOW_LTT_DEBUG_DEFAULT = false; + private final static boolean IS_PARSING_NEEDED_DEFAULT = false; + private final static int CHECKPOINT_PAGE_SIZE = 1; // Reference to our JNI trace private JniTrace currentJniTrace = null; - // *** - // UNHACKED : We can no longer do that because TCF need to maintain several events at once. - // This is very slow to do so in LTTng, this has to be temporary. - // *** HACK *** - // To save time, we will declare all component of the LttngEvent during the construction of the trace - // Then, while reading the trace, we will just SET the values instead of declaring new object - // *** + // *** HACK *** + // To save time, we will declare all component of the LttngEvent during the construction of the trace + // Then, while reading the trace, we will just SET the values instead of declaring new object LttngTimestamp eventTimestamp = null; LttngEventSource eventSource = null; + LttngEventType eventType = null; LttngEventContent eventContent = null; LttngEventReference eventReference = null; - - // The actual event LttngEvent currentLttngEvent = null; - // The current location - LttngLocation previousLocation = null; - - LttngEventType eventType = null; // Hashmap of the possible types of events (Tracefile/CPU/Marker in the JNI) HashMap traceTypes = null; // This vector will be used to quickly find a marker name from a position @@ -125,14 +108,20 @@ public class LTTngTrace extends TmfTrace { * */ public LTTngTrace(String path, boolean waitForCompletion, boolean bypassIndexing) throws Exception { - super(path, LttngEvent.class, path, CHECKPOINT_PAGE_SIZE); + super(path, CHECKPOINT_PAGE_SIZE, true); try { - currentJniTrace = JniTraceFactory.getJniTrace(path, SHOW_LTT_DEBUG_DEFAULT); + currentJniTrace = new JniTrace(path, SHOW_LTT_DEBUG_DEFAULT); } catch (Exception e) { throw new LTTngTraceException(e.getMessage()); } + // Set the start time of the trace + setTimeRange( new TmfTimeRange( new LttngTimestamp(currentJniTrace.getStartTime().getTime()), + new LttngTimestamp(currentJniTrace.getEndTime().getTime()) + ) + ); + // Export all the event types from the JNI side traceTypes = new HashMap(); traceTypeNames = new Vector(); @@ -147,114 +136,29 @@ public class LTTngTrace extends TmfTrace { eventReference = new LttngEventReference(this.getName()); // Create the skeleton event - currentLttngEvent = new LttngEvent(this, eventTimestamp, eventSource, eventType, eventContent, eventReference, null); - - // Create a new current location - previousLocation = new LttngLocation(); - + currentLttngEvent = new LttngEvent(eventTimestamp, eventSource, eventType, eventContent, eventReference, null); // Set the currentEvent to the eventContent eventContent.setEvent(currentLttngEvent); -// // Bypass indexing if asked -// if ( bypassIndexing == false ) { -// indexTrace(true); -// } -// else { - // Even if we don't have any index, set ONE checkpoint -// fCheckpoints.add(new TmfCheckpoint(new LttngTimestamp(0L) , new LttngLocation() ) ); - - // Set the start time of the trace - setTimeRange( new TmfTimeRange( new LttngTimestamp(currentJniTrace.getStartTime().getTime()), - new LttngTimestamp(currentJniTrace.getEndTime().getTime()) - ) ); -// } + // Bypass indexing if asked + if ( bypassIndexing == false ) { + indexStream(); + } } /* * Copy constructor is forbidden for LttngEvenmStream * + * Events are only valid for a very limited period of time and + * JNI library does not support multiple access at once (yet?). + * For this reason, copy constructor should NEVER be used. */ - public LTTngTrace(LTTngTrace oldTrace) throws Exception { - this(oldTrace.getPath(), false, true); - - // *** VERIFY *** - // Is this safe? - this.fCheckpoints = oldTrace.fCheckpoints; - - /* - // This would only work if the index is already done - this.fCheckpoints = new Vector( oldTrace.fCheckpoints.size() ); - for (int x = 0; x(); - clone.traceTypeNames = new Vector(); - clone.initialiseEventTypes(clone.currentJniTrace); - - // Verify that all those "default constructor" are safe to use - clone.eventTimestamp = new LttngTimestamp(); - clone.eventSource = new LttngEventSource(); - clone.eventType = new LttngEventType(); - clone.eventContent = new LttngEventContent(clone.currentLttngEvent); - clone.eventReference = new LttngEventReference(this.getName()); - - // Create the skeleton event - clone.currentLttngEvent = new LttngEvent(this, clone.eventTimestamp, clone.eventSource, clone.eventType, clone.eventContent, clone.eventReference, null); - - // Create a new current location - clone.previousLocation = new LttngLocation(); - - // Set the currentEvent to the eventContent - clone.eventContent.setEvent(clone.currentLttngEvent); - - // Set the start time of the trace - setTimeRange(new TmfTimeRange( - new LttngTimestamp(clone.currentJniTrace.getStartTime().getTime()), - new LttngTimestamp(clone.currentJniTrace.getEndTime().getTime()) - )); - } - catch (CloneNotSupportedException e) { - } - - return clone; + private LTTngTrace(LTTngTrace oldStream) throws Exception { + super(null); + throw new Exception("Copy constructor should never be use with a LTTngTrace!"); } - /* * Fill out the HashMap with "Type" (Tracefile/Marker) * @@ -305,417 +209,42 @@ public class LTTngTrace extends TmfTrace { this.traceTypeNames.add(newTypeKey); } -// /** -// * Index the current trace. -// * -// * @param useless This boolean is only to comply to the interface and will be ignored. -// */ -// @Override -// public synchronized void indexTrace(boolean useless) { -// -// long nbEvents=0L; -// -// // Start time need to be null to detect none have been set -// // LastTime need to exist so we can ajust it as we go -// LttngTimestamp startTime = null; -// LttngTimestamp lastTime = new LttngTimestamp(); -// -// // Position the trace at the beginning -// TmfContext context = seekEvent( new LttngTimestamp(0L) ); -// -// // Read the first event and extract the location -// LttngEvent tmpEvent = (LttngEvent)getNextEvent(context); -// -// // If we read the first event, define the start time. -// if ( tmpEvent != null ) { -// startTime = new LttngTimestamp( tmpEvent.getTimestamp() ); -// lastTime.setValue(tmpEvent.getTimestamp().getValue()); -// } -// -// // Now, we read each event until we hit the end of the trace -// // We will create a new checkpoint every "getCacheSize()" event -// while ( tmpEvent != null) { -// // Update the last time each time we read a new event -// lastTime.setValue(tmpEvent.getTimestamp().getValue()); -// -// // Save a check point if needed -// if ((nbEvents++ % getCacheSize()) == 0) { -// // *** IMPORTANT -// // We need to NEW each stuff we put in checkpoint -// // Otherwise everything will be the same! -// LttngTimestamp tmpTimestamp = new LttngTimestamp( (LttngTimestamp)tmpEvent.getTimestamp() ); -// LttngLocation newLocation = new LttngLocation( (LttngTimestamp)tmpEvent.getTimestamp() ); -// -// fCheckpoints.add(new TmfCheckpoint(tmpTimestamp, newLocation ) ); -// } -// // Read the next event -// tmpEvent = (LttngEvent)getNextEvent(context); -// } -// -// // If we have a start time, we should have an end time as well -// // Issue the new range -// if (startTime != null) { -// setTimeRange( new TmfTimeRange(startTime, lastTime) ); -// notifyListeners(getTimeRange() ); -// } -// -// // Ajust the total number of event in the trace -// fNbEvents = nbEvents; -// //printCheckpointsVector(); -// //printDebug = true; -// } - - /** - * Return the latest saved location. - * Note : Modifying the returned location may result in buggy positionning! - * - * @return The LttngLocation as it was after the last operation. - * - * @see org.eclipse.linuxtools.lttng.event.LttngLocation - */ - @Override - public ITmfLocation getCurrentLocation() { - return previousLocation; - } - - /** - * Position the trace to the event at the given location.

- * NOTE : Seeking by location is very fast compare to seeking by position - * but is still slower than "ReadNext", avoid using it for small interval. - * - * @param location Location of the event in the trace. - * If no event available at this exact location, we will position ourself to the next one. - * - * @return The TmfContext that point to this event - * - * @see org.eclipse.linuxtools.lttng.event.LttngLocation - * @see org.eclipse.linuxtools.tmf.trace.TmfContext - */ - @Override - public synchronized TmfContext seekLocation(ITmfLocation location) { - - if ( printDebug == true ) { - System.out.println("seekLocation(location) location -> " + location); - } - - // If the location in context is null, create a new one - LttngLocation curLocation = null; - if ( location == null ) { - curLocation = new LttngLocation(); - } - else { - curLocation = (LttngLocation)location; - } - - // *** NOTE : - // Update to location should (and will) be done in SeekEvent. - - // The only seek valid in LTTng is with the time, we call seekEvent(timestamp) - return seekEvent( curLocation.getOperationTime() ); - } - - /** - * Position the trace to the event at the given time.

- * NOTE : Seeking by time is very fast compare to seeking by position - * but is still slower than "ReadNext", avoid using it for small interval. + /** + * Return the next event in the trace.

* - * @param timestamp Time of the event in the trace. - * If no event available at this exact time, we will position ourself to the next one. + * @param context The actual context of the trace * - * @return The TmfContext that point to this event + * @return The next event, or null if none available * - * @see org.eclipse.linuxtools.lttng.event.LttngLocation - * @see org.eclipse.linuxtools.tmf.trace.TmfContext - */ + * @see org.eclipse.linuxtools.lttng.event.LttngEvent + */ @Override - public synchronized TmfContext seekEvent(TmfTimestamp timestamp) { - - if ( printDebug == true ) { - System.out.println("seekEvent(timestamp) timestamp -> " + timestamp); - } - - // Call JNI to seek - currentJniTrace.seekToTime(new JniTime(timestamp.getValue())); + public LttngEvent parseEvent(TmfTraceContext context) { + JniEvent jniEvent; + LttngTimestamp timestamp = null; + LttngEvent returnedEvent = null; - // Save the time at which we seeked - previousLocation.setOperationTime(timestamp.getValue()); - // Set the operation marker as seek, to be able to detect we did "seek" this event - previousLocation.setLastOperationSeek(); - - // *** VERIFY *** - // Is that too paranoid? - // - // We don't trust what upper level could do with our internal location - // so we create a new one to return instead - LttngLocation curLocation = new LttngLocation(previousLocation); - - return new TmfContext( curLocation ); - } - - /** - * Position the trace to the event at the given position (rank).

- * NOTE : Seeking by position is very slow in LTTng, consider seeking by timestamp. - * - * @param position Position (or rank) of the event in the trace, starting at 0. - * - * @return The TmfContext that point to this event - * - * @see org.eclipse.linuxtools.lttng.event.LttngLocation - * @see org.eclipse.linuxtools.tmf.trace.TmfContext - */ - @Override - public synchronized TmfContext seekEvent(long position) { - - if ( printDebug == true ) { - System.out.println("seekEvent(position) position -> " + position); - } - - TmfTimestamp timestamp = null; - long index = position / getCacheSize(); - - // Get the timestamp of the closest check point to the given position - if (fCheckpoints.size() > 0) { - if (index >= fCheckpoints.size()) { - index = fCheckpoints.size() - 1; - } - timestamp = (TmfTimestamp)fCheckpoints.elementAt((int)index).getTimestamp(); - } - // If none, take the start time of the trace - else { - timestamp = getStartTime(); - } - - // Seek to the found time - TmfContext tmpContext = seekEvent(timestamp); - previousLocation = (LttngLocation)tmpContext.getLocation(); - - // Ajust the index of the event we found at this check point position - Long currentPosition = index * getCacheSize(); - - Long lastTimeValueRead = 0L; - - // Get the event at current position. This won't move to the next one - JniEvent tmpJniEvent = currentJniTrace.findNextEvent(); - // Now that we are positionned at the checkpoint, - // we need to "readNext" (Position - CheckpointPosition) times or until trace "run out" - while ( (tmpJniEvent != null) && ( currentPosition < position ) ) { - tmpJniEvent = currentJniTrace.readNextEvent(); - currentPosition++; - } - - // If we found our event, save its timestamp - if ( tmpJniEvent != null ) { - lastTimeValueRead = tmpJniEvent.getEventTime().getTime(); - } - - // Set the operation marker as seek, to be able to detect we did "seek" this event - previousLocation.setLastOperationSeek(); - // Save read event time - previousLocation.setOperationTime(lastTimeValueRead); - - // *** VERIFY *** - // Is that too paranoid? - // - // We don't trust what upper level could do with our internal location - // so we create a new one to return instead - LttngLocation curLocation = new LttngLocation(previousLocation); - - return new TmfContext( curLocation ); - } - - /** - * Return the event in the trace according to the given context. Read it if necessary.

- * Similar (same?) as ParseEvent except that calling GetNext twice read the next one the second time. - * - * @param context Current TmfContext where to get the event - * - * @return The LttngEvent we read of null if no event are available - * - * @see org.eclipse.linuxtools.lttng.event.LttngLocation - * @see org.eclipse.linuxtools.tmf.trace.TmfContext - */ - - public int nbEventsRead = 0; - @Override - public synchronized LttngEvent getNextEvent(TmfContext context) { - - if ( printDebug == true ) { - System.out.println("getNextEvent(context) context.getLocation() -> " + context.getLocation()); - } - - LttngEvent returnedEvent = null; - LttngLocation curLocation = null; - - // If the location in context is null, create a new one - if ( context.getLocation() == null ) { - curLocation = new LttngLocation(); - context.setLocation(curLocation); - } - else { - // Otherwise, we use the one in context; it should be a valid LttngLocation - curLocation = (LttngLocation)context.getLocation(); - } - - // *** HACK *** - // TMF assumes it is possible to read (GetNextEvent) to the next Event once ParseEvent() is called - // In LTTNG, there is not difference between "Parsing" and "Reading" an event. - // Since parsing/reading invalidate the previous event, - // we need to make sure the sequence ParseEvent() -> GetNextEvent() will not actually move to the next event. - // To do so, we avoid moving for call to "GetNextEvent()" that follow call to a call to "ParseEvent()". - // However, calling ParseEvent() -> GetNextEvent() -> GetNextEvent() will only move next by one. - - // *** Positioning trick : - // GetNextEvent only read the trace if : - // 1- The last operation was NOT a ParseEvent --> A read is required - // OR - // 2- The time of the previous location is different from the current one --> A seek + a read is required - if ( (curLocation.isLastOperationParse() != true) || - (previousLocation.getOperationTimeValue() != curLocation.getOperationTimeValue() ) ) - { - if ( previousLocation.getOperationTimeValue() != curLocation.getOperationTimeValue() ) { - if ( printDebug == true ) { - System.out.println("\t\tSeeking in getNextEvent. [ LastTime : " + previousLocation.getOperationTimeValue() + " CurrentTime" + curLocation.getOperationTimeValue() + " ]"); - } - seekEvent( curLocation.getOperationTime() ); - } - // Read the next event from the trace. The last one will NO LONGER BE VALID. - returnedEvent = readEvent(curLocation); - nbEventsRead++; - - // Set the operation marker as read to both location, to be able to detect we did "read" this event - previousLocation.setLastOperationReadNext(); - curLocation.setLastOperationReadNext(); - } - else { - // No event was read, just return the one currently loaded (the last one we read) - returnedEvent = currentLttngEvent; + synchronized (currentJniTrace) { + // Seek to the context's location + seekLocation(context.getLocation()); - // *** IMPORTANT! - // Reset (erase) the operation marker to both location, to be able to detect we did NOT "read" this event - previousLocation.resetLocationState(); - curLocation.resetLocationState(); - } - - // If we read an event, set it's time to the locations (both previous and current) - if ( returnedEvent != null ) { - previousLocation.setOperationTime((LttngTimestamp)returnedEvent.getTimestamp()); - curLocation.setOperationTime((LttngTimestamp)returnedEvent.getTimestamp()); + // Read an event from the JNI and convert it into a LttngEvent + jniEvent = currentJniTrace.readNextEvent(); - updateIndex(context, context.getRank(), returnedEvent.getTimestamp()); - context.updateRank(1); - } - - return returnedEvent; - } - - - /** - * Return the event in the trace according to the given context. Read it if necessary.

- * Similar (same?) as GetNextEvent except that calling ParseEvent twice will return the same event - * - * @param context Current TmfContext where to get the event - * - * @return The LttngEvent we read of null if no event are available - * - * @see org.eclipse.linuxtools.lttng.event.LttngLocation - * @see org.eclipse.linuxtools.tmf.trace.TmfContext - */ - @Override - public synchronized LttngEvent parseEvent(TmfContext context) { - - if ( printDebug == true ) { - System.out.println("parseEvent(context) context.getLocation() -> " + context.getLocation()); - } - - LttngEvent returnedEvent = null; - LttngLocation curLocation = null; - - // If the location in context is null, create a new one - if ( context.getLocation() == null ) { - curLocation = new LttngLocation(); - context.setLocation(curLocation); - } - // Otherwise, we use the one in context; it should be a valid LttngLocation - else { - curLocation = (LttngLocation)context.getLocation(); - } - - // *** HACK *** - // TMF assumes it is possible to read (GetNextEvent) to the next Event once ParseEvent() is called - // In LTTNG, there is not difference between "Parsing" and "Reading" an event. - // So, before "Parsing" an event, we have to make sure we didn't "Read" it alreafy. - // Also, "Reading" invalidate the previous Event in LTTNG and seek back is very costly, - // so calling twice "Parse" will return the same event, giving a way to get the "Currently loaded" event - - // *** Positionning trick : - // ParseEvent only read the trace if : - // 1- The last operation was NOT a ParseEvent or a GetNextEvent --> A read is required - // OR - // 2- The time of the previous location is different from the current one --> A seek + a read is required - if ( ( (curLocation.isLastOperationParse() != true) && ((curLocation.isLastOperationReadNext() != true)) ) || - (previousLocation.getOperationTimeValue() != curLocation.getOperationTimeValue() ) ) - { - // Previous time != Current time : We need to reposition to the current time - if (previousLocation.getOperationTimeValue() != curLocation.getOperationTimeValue() ) { - if ( printDebug == true ) { - System.out.println("\t\tSeeking in getNextEvent. [ LastTime : " + previousLocation.getOperationTimeValue() + " CurrentTime" + curLocation.getOperationTimeValue() + " ]"); - } - seekEvent( curLocation.getOperationTime() ); - } - - // Read the next event from the trace. The last one will NO LONGER BE VALID. - returnedEvent = readEvent(curLocation); - } - else { - // No event was read, just return the one currently loaded (the last one we read) - returnedEvent = currentLttngEvent; - } - - // If we read an event, set it's time to the locations (both previous and current) - if ( returnedEvent != null ) { - previousLocation.setOperationTime((LttngTimestamp)returnedEvent.getTimestamp()); - curLocation.setOperationTime((LttngTimestamp)returnedEvent.getTimestamp()); + //currentLttngEvent = (jniEvent != null) ? convertJniEventToTmf(jniEvent, true) : null; + if ( jniEvent != null ) { + currentLttngEvent = convertJniEventToTmf(jniEvent); + returnedEvent = currentLttngEvent; + } + + // Save timestamp + timestamp = (LttngTimestamp) getCurrentLocation(); } - - // Set the operation marker as parse to both location, to be able to detect we already "read" this event - previousLocation.setLastOperationParse(); - curLocation.setLastOperationParse(); - - return returnedEvent; - } - - /* - * Read the next event from the JNI and convert it as Lttng Event

- * - * @param location Current LttngLocation that to be updated with the event timestamp - * - * @return The LttngEvent we read of null if no event are available - * - * @see org.eclipse.linuxtools.lttng.event.LttngLocation - * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace - */ - private synchronized LttngEvent readEvent(LttngLocation location) { - LttngEvent returnedEvent = null; - JniEvent tmpEvent = null; - - // Read the next event from JNI. THIS WILL INVALIDATE THE CURRENT LTTNG EVENT. - tmpEvent = currentJniTrace.readNextEvent(); - - if ( tmpEvent != null ) { - // *** NOTE - // Convert will update the currentLttngEvent - returnedEvent = convertJniEventToTmf(tmpEvent); - - location.setOperationTime( (LttngTimestamp)returnedEvent.getTimestamp() ); - } - // *** NOTE - // If the read failed (likely the last event in the trace), set the LastReadTime to the JNI time - // That way, even if we try to read again, we will step over the bogus seek and read - else { - location.setOperationTime( getEndTime().getValue() + 1 ); - } - - return returnedEvent; + context.setLocation(timestamp); + context.setTimestamp(timestamp); + context.incrIndex(); + + return returnedEvent; } /** @@ -731,7 +260,7 @@ public class LTTngTrace extends TmfTrace { * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniEvent * @see org.eclipse.linuxtools.lttng.event.LttngEvent */ - public synchronized LttngEvent convertJniEventToTmf(JniEvent newEvent) { + public LttngEvent convertJniEventToTmf(JniEvent newEvent) { currentLttngEvent = convertJniEventToTmf(newEvent, IS_PARSING_NEEDED_DEFAULT); return currentLttngEvent; @@ -748,83 +277,97 @@ public class LTTngTrace extends TmfTrace { * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniEvent * @see org.eclipse.linuxtools.lttng.event.LttngEvent */ - public synchronized LttngEvent convertJniEventToTmf(JniEvent jniEvent, boolean isParsingNeeded) { - - if ( uniqueEvent == true ) { - - // *** - // UNHACKED : We can no longer do that because TCF need to maintain several events at once. - // This is very slow to do so in LTTng, this has to be temporary. - // *** HACK *** - // To save time here, we only set value instead of allocating new object - // This give an HUGE performance improvement - // all allocation done in the LttngTrace constructor - // *** - eventTimestamp.setValue(jniEvent.getEventTime().getTime()); - eventSource.setSourceId(jniEvent.requestEventSource()); - - eventType = traceTypes.get( EventTypeKey.getEventTypeKey(jniEvent) ); - - eventReference.setValue(jniEvent.getParentTracefile().getTracefilePath()); - eventReference.setTracepath(this.getName()); - - eventContent.emptyContent(); - - currentLttngEvent.setType(eventType); - // Save the jni reference - currentLttngEvent.updateJniEventReference(jniEvent); - - // Parse now if was asked - // Warning : THIS IS SLOW - if (isParsingNeeded == true ) { - eventContent.getFields(); - } - - return currentLttngEvent; + public LttngEvent convertJniEventToTmf(JniEvent jniEvent, boolean isParsingNeeded) { + // *** HACK *** + // To save time here, we only set value instead of allocating new object + // This give an HUGE performance improvement + // all allocation done in the LttngTrace constructor + + eventTimestamp.setValue(jniEvent.getEventTime().getTime()); + eventSource.setSourceId(jniEvent.requestEventSource()); + + eventType = traceTypes.get( EventTypeKey.getEventTypeKey(jniEvent) ); + + eventReference.setValue(jniEvent.getParentTracefile().getTracefilePath()); + eventReference.setTracepath(this.getName()); + +// eventContent.setEvent(currentLttngEvent); +// eventContent.setType(eventType); + eventContent.emptyContent(); + +// currentLttngEvent.setContent(eventContent); + currentLttngEvent.setType(eventType); + // Save the jni reference + currentLttngEvent.updateJniEventReference(jniEvent); + + // Parse now if was asked + // Warning : THIS IS SLOW + if (isParsingNeeded == true ) { + eventContent.getFields(); + } + + return currentLttngEvent; + } + + /** + * Seek (move) to a certain location in the trace.

+ * + * WARNING : No event is read by this function, it just seek to a certain time.
+ * Use "parseEvent()" or "getNextEvent()" to get the event we seeked to. + * + * @param location a TmfTimestamp of a position in the trace + * + * @return TmfTraceContext pointing the position in the trace at the seek location + */ + public TmfTraceContext seekLocation(Object location) { + + LttngTimestamp timestamp = null; + + // If location is null, interpret this as a request to get back to the beginning of the trace + // in that case, just change the location, the seek will happen below + if (location == null) { + location = getStartTime(); + } + + if (location instanceof TmfTimestamp) { + long value = ((TmfTimestamp) location).getValue(); + if (value != currentJniTrace.getCurrentEventTimestamp().getTime()) { + synchronized (currentJniTrace) { + currentJniTrace.seekToTime(new JniTime(value)); + timestamp = (LttngTimestamp) getCurrentLocation(); + } + } } else { - return convertJniEventToTmfMultipleEventEvilFix(jniEvent, isParsingNeeded); + System.out.println("ERROR : Location not instance of TmfTimestamp"); } - + + // FIXME: LTTng hack - start + // return new TmfTraceContext(timestamp, timestamp, 0); // Original + return new TmfTraceContext(timestamp, timestamp, -1); // Hacked + // FIXME: LTTng hack - end } /** - * This method is a temporary fix to support multiple events at once in TMF - * This is expected to be slow and should be fixed in another way. - * See comment in convertJniEventToTmf(); + * Location (timestamp) of our current position in the trace.

* - * @param jniEvent The current JNI Event - * @return Current Lttng Event fully parsed + * @return The time (in LttngTimestamp format) of the current event or AFTER endTime if no more event is available. */ - private synchronized LttngEvent convertJniEventToTmfMultipleEventEvilFix(JniEvent jniEvent, boolean isParsingNeeded) { - // *** HACK *** - // Below : the "fix" with all the new and the full-parse - // Allocating new memory is slow. - // Parsing every events is very slow. - eventTimestamp = new LttngTimestamp(jniEvent.getEventTime().getTime()); - eventSource = new LttngEventSource(jniEvent.requestEventSource()); - eventReference = new LttngEventReference(jniEvent.getParentTracefile().getTracefilePath(), this.getName()); - eventType = new LttngEventType(traceTypes.get( EventTypeKey.getEventTypeKey(jniEvent) )); - eventContent = new LttngEventContent(currentLttngEvent); - currentLttngEvent = new LttngEvent(this, eventTimestamp, eventSource, eventType, eventContent, eventReference, null); - - // The jni reference is no longer reliable but we will keep it anyhow - currentLttngEvent.updateJniEventReference(jniEvent); - // Ensure that the content is correctly set - eventContent.setEvent(currentLttngEvent); + @Override + public Object getCurrentLocation() { + LttngTimestamp returnedLocation = null; + JniEvent tmpJniEvent = currentJniTrace.findNextEvent(); - // Parse the event if it was needed - // *** WARNING *** - // ONLY for testing, NOT parsing events with non-unique events WILL result in segfault in the JVM - if ( isParsingNeeded == true ) { - eventContent.getFields(); + if ( tmpJniEvent != null ) { + returnedLocation = new LttngTimestamp(tmpJniEvent.getEventTime().getTime()); } - - return currentLttngEvent; + else { + returnedLocation = new LttngTimestamp( getEndTime().getValue() + 1 ); + } + + return returnedLocation; } - - /** * Reference to the current LttngTrace we are reading from.

* @@ -901,27 +444,7 @@ public class LTTngTrace extends TmfTrace { } } - /** - * Print the content of the checkpoint vector.

- * - * This is intended for debug purpose only. - */ - public void printCheckpointsVector() { - System.out.println("StartTime : " + getTimeRange().getStartTime().getValue()); - System.out.println("EndTime : " + getTimeRange().getEndTime().getValue()); - - for ( int pos=0; pos < fCheckpoints.size(); pos++) { - System.out.print(pos + ": " + "\t"); - System.out.print( fCheckpoints.get(pos).getTimestamp() + "\t" ); - System.out.println( fCheckpoints.get(pos).getLocation() ); - } - } - /** - * Return a String identifying this trace. - * - * @return String that identify this trace - */ @Override public String toString() { String returnedData=""; @@ -957,4 +480,4 @@ class EventTypeKey { return key; } -} \ No newline at end of file +} -- 2.34.1