analysis: Allow segment table viewer/provider to accept ISegment[] input
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.os.linux.core / src / org / eclipse / tracecompass / analysis / os / linux / core / latency / LatencyAnalysis.java
index 9a459702b9ee651478411211b7c753174b928a1c..457c43402f3a1adf31f321c912ba95ce7666f542 100644 (file)
@@ -13,39 +13,30 @@ import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
 
 import java.io.IOException;
 import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
+import java.util.Collection;
+import java.util.Comparator;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Map;
-import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
-import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.KernelTidAspect;
 import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
 import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace;
-import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.analysis.timing.core.segmentstore.AbstractSegmentStoreAnalysisModule;
 import org.eclipse.tracecompass.segmentstore.core.ISegment;
 import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
-import org.eclipse.tracecompass.segmentstore.core.treemap.TreeMapStore;
-import org.eclipse.tracecompass.tmf.core.analysis.TmfAbstractAnalysisModule;
 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
-import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
-import org.eclipse.tracecompass.tmf.core.request.ITmfEventRequest;
-import org.eclipse.tracecompass.tmf.core.request.TmfEventRequest;
-import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.core.segment.ISegmentAspect;
 
-import com.google.common.base.Function;
-import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
 
 /**
  * @author Alexandre Montplaisir
  * @since 2.0
  */
-public class LatencyAnalysis extends TmfAbstractAnalysisModule {
+public class LatencyAnalysis extends AbstractSegmentStoreAnalysisModule {
 
     /**
      * The ID of this analysis
@@ -54,142 +45,56 @@ public class LatencyAnalysis extends TmfAbstractAnalysisModule {
 
     private static final String DATA_FILENAME = "latency-analysis.dat"; //$NON-NLS-1$
 
-    private @Nullable ISegmentStore<ISegment> fSystemCalls;
-
-    private @Nullable ITmfEventRequest fOngoingRequest = null;
-
-    private final Set<LatencyAnalysisListener> fListeners = new HashSet<>();
+    private static final Collection<ISegmentAspect> BASE_ASPECTS =
+            checkNotNull(ImmutableList.of(SyscallNameAspect.INSTANCE));
 
     @Override
     public String getId() {
         return ID;
     }
 
-    /**
-     * Listener for the viewers
-     *
-     * @param listener
-     *            listener for each type of viewer
-     */
-    public void addListener(LatencyAnalysisListener listener) {
-        fListeners.add(listener);
+    @Override
+    public Iterable<ISegmentAspect> getSegmentAspects() {
+        return BASE_ASPECTS;
     }
 
     @Override
-    protected boolean executeAnalysis(IProgressMonitor monitor) throws TmfAnalysisException {
-        IKernelTrace trace = checkNotNull((IKernelTrace) getTrace());
-        IKernelAnalysisEventLayout layout = trace.getKernelEventLayout();
-
-        /* See if the data file already exists on disk */
-        String dir = TmfTraceManager.getSupplementaryFileDir(trace);
-        final Path file = Paths.get(dir, DATA_FILENAME);
-
-        if (Files.exists(file)) {
-            /* Attempt to read the existing file */
-            try (ObjectInputStream ois = new ObjectInputStream(Files.newInputStream(file))) {
-                Object[] syscallsArray = (Object[]) ois.readObject();
-                final ISegmentStore<ISegment> systemCalls = new TreeMapStore<>();
-                for (Object element : syscallsArray) {
-                    if (element instanceof ISegment) {
-                        ISegment segment = (ISegment) element;
-                        systemCalls.add(segment);
-                    }
-                }
-                fSystemCalls = systemCalls;
-                for (LatencyAnalysisListener listener : fListeners) {
-                    listener.onComplete(this, systemCalls);
-                }
-                return true;
-            } catch (IOException | ClassNotFoundException | ClassCastException e) {
-                /*
-                 * We did not manage to read the file successfully, we will just
-                 * fall-through to rebuild a new one.
-                 */
-                try {
-                    Files.delete(file);
-                } catch (IOException e1) {
-                }
-            }
-        }
-
-        ISegmentStore<ISegment> syscalls = new TreeMapStore<>();
-
-        /* Cancel an ongoing request */
-        ITmfEventRequest req = fOngoingRequest;
-        if ((req != null) && (!req.isCompleted())) {
-            req.cancel();
-        }
-
-        /* Create a new request */
-        req = new LatencyAnalysisRequest(layout, syscalls);
-        fOngoingRequest = req;
-        trace.sendRequest(req);
-        /* The request will fill 'syscalls' */
-        try {
-            req.waitForCompletion();
-        } catch (InterruptedException e) {
-        }
-
-        /* Do not process the results if the request was cancelled */
-        if (req.isCancelled() || req.isFailed()) {
-            return false;
-        }
-
-        /* The request will fill 'syscalls' */
-        fSystemCalls = syscalls;
-
-        /* Serialize the collections to disk for future usage */
-        try (ObjectOutputStream oos = new ObjectOutputStream(Files.newOutputStream(file))) {
-            oos.writeObject(syscalls.toArray());
-        } catch (IOException e) {
-            /* Didn't work, oh well. We will just re-read the trace next time */
-        }
-
-        for (LatencyAnalysisListener listener : fListeners) {
-            listener.onComplete(this, syscalls);
-        }
-
-        return true;
+    public String getDataFileName() {
+        return DATA_FILENAME;
     }
 
     @Override
-    protected void canceling() {
-        ITmfEventRequest req = fOngoingRequest;
-        if ((req != null) && (!req.isCompleted())) {
-            req.cancel();
-        }
+    public AbstractSegmentStoreAnalysisRequest createAnalysisRequest(ISegmentStore<ISegment> syscalls) {
+        return new SyscallLatencyAnalysisRequest(syscalls);
     }
 
-    /**
-     * @return Results from the analysis in a ISegmentStore
-     */
-    public @Nullable ISegmentStore<ISegment> getResults() {
-        return fSystemCalls;
+    @Override
+    protected Object[] readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
+        return checkNotNull((Object[]) ois.readObject());
     }
 
-    private static class LatencyAnalysisRequest extends TmfEventRequest {
+    private static class SyscallLatencyAnalysisRequest extends AbstractSegmentStoreAnalysisRequest {
 
-        private final IKernelAnalysisEventLayout fLayout;
-        private final ISegmentStore<ISegment> fFullSyscalls;
         private final Map<Integer, SystemCall.InitialInfo> fOngoingSystemCalls = new HashMap<>();
+        private @Nullable IKernelAnalysisEventLayout fLayout;
 
-        public LatencyAnalysisRequest(IKernelAnalysisEventLayout layout, ISegmentStore<ISegment> syscalls) {
-            super(ITmfEvent.class, 0, ITmfEventRequest.ALL_DATA, ExecutionType.BACKGROUND);
-            fLayout = layout;
-            /*
-             * We do NOT make a copy here! We want to modify the list that was
-             * passed in parameter.
-             */
-            fFullSyscalls = syscalls;
+        public SyscallLatencyAnalysisRequest(ISegmentStore<ISegment> syscalls) {
+            super(syscalls);
         }
 
         @Override
         public void handleData(final ITmfEvent event) {
             super.handleData(event);
+            IKernelAnalysisEventLayout layout = fLayout;
+            if (layout == null) {
+                IKernelTrace trace = checkNotNull((IKernelTrace) event.getTrace());
+                layout = trace.getKernelEventLayout();
+                fLayout = layout;
+            }
             final String eventName = event.getType().getName();
 
-            if (eventName.startsWith(fLayout.eventSyscallEntryPrefix()) ||
-                    eventName.startsWith(fLayout.eventCompatSyscallEntryPrefix())) {
+            if (eventName.startsWith(layout.eventSyscallEntryPrefix()) ||
+                    eventName.startsWith(layout.eventCompatSyscallEntryPrefix())) {
                 /* This is a system call entry event */
 
                 Integer tid = KernelTidAspect.INSTANCE.resolve(event);
@@ -201,18 +106,16 @@ public class LatencyAnalysis extends TmfAbstractAnalysisModule {
                 /* Record the event's data into the intial system call info */
                 // String syscallName = fLayout.getSyscallNameFromEvent(event);
                 long startTime = event.getTimestamp().getValue();
-                String syscallName = eventName.substring(fLayout.eventSyscallEntryPrefix().length());
-                FluentIterable<String> argNames = FluentIterable.from(event.getContent().getFieldNames());
-                Map<String, String> args = argNames.toMap(new Function<String, String>() {
-                    @Override
-                    public String apply(@Nullable String input) {
-                        return checkNotNull(event.getContent().getField(input).getValue().toString());
-                    }
-                });
-                SystemCall.InitialInfo newSysCall = new SystemCall.InitialInfo(startTime, NonNullUtils.checkNotNull(syscallName), NonNullUtils.checkNotNull(args));
+                String syscallName = eventName.substring(layout.eventSyscallEntryPrefix().length());
+
+                Map<String, String> args = event.getContent().getFieldNames().stream()
+                    .collect(Collectors.toMap(Function.identity(),
+                            input -> checkNotNull(event.getContent().getField(input).getValue().toString())));
+
+                SystemCall.InitialInfo newSysCall = new SystemCall.InitialInfo(startTime, checkNotNull(syscallName), checkNotNull(args));
                 fOngoingSystemCalls.put(tid, newSysCall);
 
-            } else if (eventName.startsWith(fLayout.eventSyscallExitPrefix())) {
+            } else if (eventName.startsWith(layout.eventSyscallExitPrefix())) {
                 /* This is a system call exit event */
 
                 Integer tid = KernelTidAspect.INSTANCE.resolve(event);
@@ -232,7 +135,7 @@ public class LatencyAnalysis extends TmfAbstractAnalysisModule {
                 long endTime = event.getTimestamp().getValue();
                 int ret = ((Long) event.getContent().getField("ret").getValue()).intValue(); //$NON-NLS-1$
                 ISegment syscall = new SystemCall(info, endTime, ret);
-                fFullSyscalls.add(syscall);
+                getSegmentStore().add(syscall);
             }
         }
 
@@ -242,4 +145,30 @@ public class LatencyAnalysis extends TmfAbstractAnalysisModule {
         }
     }
 
+    private static class SyscallNameAspect implements ISegmentAspect {
+        public static final ISegmentAspect INSTANCE = new SyscallNameAspect();
+
+        private SyscallNameAspect() { }
+
+        @Override
+        public String getHelpText() {
+            return checkNotNull(Messages.SegmentAspectHelpText_SystemCall);
+        }
+        @Override
+        public String getName() {
+            return checkNotNull(Messages.SegmentAspectName_SystemCall);
+        }
+        @Override
+        public @Nullable Comparator<?> getComparator() {
+            return null;
+        }
+        @Override
+        public @Nullable String resolve(ISegment segment) {
+            if (segment instanceof SystemCall) {
+                return ((SystemCall) segment).getName();
+            }
+            return EMPTY_STRING;
+        }
+    }
+
 }
This page took 0.027075 seconds and 5 git commands to generate.