tmf: Bug 479994: TmfTraceSelectedSignal not sent when editor reused
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.os.linux.core / src / org / eclipse / tracecompass / analysis / os / linux / core / latency / LatencyAnalysis.java
CommitLineData
7b79ee46
FLN
1/*******************************************************************************
2 * Copyright (c) 2015 EfficiOS Inc., Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *******************************************************************************/
9
10package org.eclipse.tracecompass.analysis.os.linux.core.latency;
11
12import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
13
14import java.io.IOException;
15import java.io.ObjectInputStream;
16import java.io.ObjectOutputStream;
17import java.nio.file.Files;
18import java.nio.file.Path;
19import java.nio.file.Paths;
20import java.util.HashMap;
21import java.util.HashSet;
22import java.util.Map;
23import java.util.Set;
24
25import org.eclipse.core.runtime.IProgressMonitor;
26import org.eclipse.jdt.annotation.Nullable;
27import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.KernelTidAspect;
28import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
29import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace;
30import org.eclipse.tracecompass.common.core.NonNullUtils;
31import org.eclipse.tracecompass.segmentstore.core.ISegment;
32import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
33import org.eclipse.tracecompass.segmentstore.core.treemap.TreeMapStore;
34import org.eclipse.tracecompass.tmf.core.analysis.TmfAbstractAnalysisModule;
35import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
36import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
37import org.eclipse.tracecompass.tmf.core.request.ITmfEventRequest;
38import org.eclipse.tracecompass.tmf.core.request.TmfEventRequest;
39import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
40
41import com.google.common.base.Function;
42import com.google.common.collect.FluentIterable;
43
44/**
45 * @author Alexandre Montplaisir
46 * @since 1.1
47 */
48public class LatencyAnalysis extends TmfAbstractAnalysisModule {
49
50 /**
51 * The ID of this analysis
52 */
53 public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.latency"; //$NON-NLS-1$
54
55 private static final String DATA_FILENAME = "latency-analysis.dat"; //$NON-NLS-1$
56
57 private @Nullable ISegmentStore<ISegment> fSystemCalls;
58
7779da81
BH
59 private @Nullable ITmfEventRequest fOngoingRequest = null;
60
7b79ee46
FLN
61 private final Set<LatencyAnalysisListener> fListeners = new HashSet<>();
62
63 @Override
64 public String getId() {
65 return ID;
66 }
67
68 /**
69 * Listener for the viewers
70 *
71 * @param listener
72 * listener for each type of viewer
73 */
74 public void addListener(LatencyAnalysisListener listener) {
75 fListeners.add(listener);
76 }
77
78 @Override
79 protected boolean executeAnalysis(IProgressMonitor monitor) throws TmfAnalysisException {
80 IKernelTrace trace = checkNotNull((IKernelTrace) getTrace());
81 IKernelAnalysisEventLayout layout = trace.getKernelEventLayout();
82
83 /* See if the data file already exists on disk */
84 String dir = TmfTraceManager.getSupplementaryFileDir(trace);
85 final Path file = Paths.get(dir, DATA_FILENAME);
86
87 if (Files.exists(file)) {
88 /* Attempt to read the existing file */
89 try (ObjectInputStream ois = new ObjectInputStream(Files.newInputStream(file))) {
d948686f
MK
90 Object[] syscallsArray = (Object[]) ois.readObject();
91 final ISegmentStore<ISegment> systemCalls = new TreeMapStore<>();
92 for (Object element : syscallsArray) {
93 if (element instanceof ISegment) {
94 ISegment segment = (ISegment) element;
95 systemCalls.add(segment);
96 }
97 }
98 fSystemCalls = systemCalls;
99 for (LatencyAnalysisListener listener : fListeners) {
100 listener.onComplete(this, systemCalls);
101 }
7b79ee46
FLN
102 return true;
103 } catch (IOException | ClassNotFoundException | ClassCastException e) {
104 /*
105 * We did not manage to read the file successfully, we will just
106 * fall-through to rebuild a new one.
107 */
108 try {
109 Files.delete(file);
110 } catch (IOException e1) {
111 }
112 }
113 }
114
115 ISegmentStore<ISegment> syscalls = new TreeMapStore<>();
7779da81
BH
116
117 /* Cancel an ongoing request */
118 ITmfEventRequest req = fOngoingRequest;
119 if ((req != null) && (!req.isCompleted())) {
120 req.cancel();
121 }
122
123 /* Create a new request */
124 req = new LatencyAnalysisRequest(layout, syscalls);
125 fOngoingRequest = req;
7b79ee46 126 trace.sendRequest(req);
a5c41909 127 /* The request will fill 'syscalls' */
7b79ee46
FLN
128 try {
129 req.waitForCompletion();
130 } catch (InterruptedException e) {
131 }
7779da81
BH
132
133 /* Do not process the results if the request was cancelled */
134 if (req.isCancelled() || req.isFailed()) {
135 return false;
136 }
137
7b79ee46
FLN
138 /* The request will fill 'syscalls' */
139 fSystemCalls = syscalls;
140
141 /* Serialize the collections to disk for future usage */
142 try (ObjectOutputStream oos = new ObjectOutputStream(Files.newOutputStream(file))) {
d948686f 143 oos.writeObject(syscalls.toArray());
7b79ee46
FLN
144 } catch (IOException e) {
145 /* Didn't work, oh well. We will just re-read the trace next time */
146 }
147
148 for (LatencyAnalysisListener listener : fListeners) {
149 listener.onComplete(this, syscalls);
150 }
151
152 return true;
153 }
154
155 @Override
156 protected void canceling() {
7779da81
BH
157 ITmfEventRequest req = fOngoingRequest;
158 if ((req != null) && (!req.isCompleted())) {
159 req.cancel();
160 }
7b79ee46
FLN
161 }
162
163 /**
164 * @return Results from the analysis in a ISegmentStore
165 */
166 public @Nullable ISegmentStore<ISegment> getResults() {
167 return fSystemCalls;
168 }
169
170 private static class LatencyAnalysisRequest extends TmfEventRequest {
171
172 private final IKernelAnalysisEventLayout fLayout;
173 private final ISegmentStore<ISegment> fFullSyscalls;
174 private final Map<Integer, SystemCall.InitialInfo> fOngoingSystemCalls = new HashMap<>();
175
176 public LatencyAnalysisRequest(IKernelAnalysisEventLayout layout, ISegmentStore<ISegment> syscalls) {
177 super(ITmfEvent.class, 0, ITmfEventRequest.ALL_DATA, ExecutionType.BACKGROUND);
178 fLayout = layout;
179 /*
180 * We do NOT make a copy here! We want to modify the list that was
181 * passed in parameter.
182 */
183 fFullSyscalls = syscalls;
184 }
185
186 @Override
187 public void handleData(final ITmfEvent event) {
188 super.handleData(event);
189 final String eventName = event.getType().getName();
190
191 if (eventName.startsWith(fLayout.eventSyscallEntryPrefix()) ||
192 eventName.startsWith(fLayout.eventCompatSyscallEntryPrefix())) {
193 /* This is a system call entry event */
194
195 Integer tid = KernelTidAspect.INSTANCE.resolve(event);
196 if (tid == null) {
197 // no information on this event/trace ?
198 return;
199 }
200
201 /* Record the event's data into the intial system call info */
202 // String syscallName = fLayout.getSyscallNameFromEvent(event);
203 long startTime = event.getTimestamp().getValue();
204 String syscallName = eventName.substring(fLayout.eventSyscallEntryPrefix().length());
205 FluentIterable<String> argNames = FluentIterable.from(event.getContent().getFieldNames());
206 Map<String, String> args = argNames.toMap(new Function<String, String>() {
207 @Override
208 public String apply(@Nullable String input) {
209 return checkNotNull(event.getContent().getField(input).getValue().toString());
210 }
211 });
212 SystemCall.InitialInfo newSysCall = new SystemCall.InitialInfo(startTime, NonNullUtils.checkNotNull(syscallName), NonNullUtils.checkNotNull(args));
213 fOngoingSystemCalls.put(tid, newSysCall);
214
215 } else if (eventName.startsWith(fLayout.eventSyscallExitPrefix())) {
216 /* This is a system call exit event */
217
218 Integer tid = KernelTidAspect.INSTANCE.resolve(event);
219 if (tid == null) {
220 return;
221 }
222
223 SystemCall.InitialInfo info = fOngoingSystemCalls.remove(tid);
224 if (info == null) {
225 /*
226 * We have not seen the entry event corresponding to this
227 * exit (lost event, or before start of trace).
228 */
229 return;
230 }
231
232 long endTime = event.getTimestamp().getValue();
233 int ret = ((Long) event.getContent().getField("ret").getValue()).intValue(); //$NON-NLS-1$
234 ISegment syscall = new SystemCall(info, endTime, ret);
1a9cb076 235 fFullSyscalls.add(syscall);
7b79ee46
FLN
236 }
237 }
238
239 @Override
240 public void handleCompleted() {
241 fOngoingSystemCalls.clear();
242 }
243 }
244
245}
This page took 0.0501 seconds and 5 git commands to generate.