tmf: remove deprecated methods from tmf
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / tmf / core / trace / TmfTraceUtils.java
CommitLineData
b8585c7c
AM
1/*******************************************************************************
2 * Copyright (c) 2014 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Alexandre Montplaisir - Initial API and implementation
11 *******************************************************************************/
12
13package org.eclipse.tracecompass.tmf.core.trace;
14
aa353506
AM
15import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
16
d26d67f5
BH
17import java.io.BufferedInputStream;
18import java.io.File;
19import java.io.FileInputStream;
20import java.io.IOException;
daf3c7eb 21import java.util.ArrayList;
cf392b73 22import java.util.HashSet;
daf3c7eb 23import java.util.List;
c93f91d9 24import java.util.Optional;
cf392b73 25import java.util.Set;
dba71686 26import java.util.function.Predicate;
b8585c7c 27
f8a23812 28import org.eclipse.core.runtime.IProgressMonitor;
df2597e0 29import org.eclipse.jdt.annotation.NonNull;
1d83ed07 30import org.eclipse.jdt.annotation.NonNullByDefault;
b8585c7c 31import org.eclipse.jdt.annotation.Nullable;
c15e897d 32import org.eclipse.tracecompass.common.core.StreamUtils;
b8585c7c 33import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
daf3c7eb 34import org.eclipse.tracecompass.tmf.core.component.ITmfEventProvider;
b1aad44e 35import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
35f39420 36import org.eclipse.tracecompass.tmf.core.event.aspect.ITmfEventAspect;
dba71686 37import org.eclipse.tracecompass.tmf.core.request.TmfEventRequest;
b8585c7c 38
daf3c7eb 39import com.google.common.collect.Iterables;
c93f91d9 40import com.google.common.collect.Lists;
daf3c7eb 41
b8585c7c
AM
42/**
43 * Utility methods for ITmfTrace's.
44 *
45 * @author Alexandre Montplaisir
46 */
1d83ed07 47@NonNullByDefault
b8585c7c
AM
48public final class TmfTraceUtils {
49
d26d67f5 50 private static final int MAX_NB_BINARY_BYTES = 2048;
cf392b73 51 private static final Set<ITmfEventAspect<?>> EXTRA_ASPECTS = new HashSet<>();
d26d67f5 52
b1aad44e
GB
53 private TmfTraceUtils() {
54 }
b8585c7c
AM
55
56 /**
daf3c7eb
MK
57 * Return the first result of the first analysis module belonging to this trace or its children,
58 * with the specified ID and class.
b8585c7c
AM
59 *
60 * @param trace
61 * The trace for which you want the modules
62 * @param moduleClass
63 * Returned modules must extend this class
64 * @param id
65 * The ID of the analysis module
66 * @return The analysis module with specified class and ID, or null if no
67 * such module exists.
68 */
69 public static @Nullable <T extends IAnalysisModule> T getAnalysisModuleOfClass(ITmfTrace trace,
70 Class<T> moduleClass, String id) {
71 Iterable<T> modules = getAnalysisModulesOfClass(trace, moduleClass);
72 for (T module : modules) {
73 if (id.equals(module.getId())) {
74 return module;
75 }
76 }
77 return null;
78 }
79
cf392b73
GB
80 /**
81 * Registers an extra event aspect that may apply to all traces, not
82 * directly linked to a trace type. These can be used to retrieve values
83 * using the
84 * {@link #resolveEventAspectOfClassForEvent(ITmfTrace, Class, ITmfEvent)}
85 * method, but will not appear where trace aspects are being displayed.
86 *
87 * @param aspect
88 * The event aspect to register
4b40a764 89 * @since 3.0
cf392b73
GB
90 */
91 public static void registerEventAspect(ITmfEventAspect<?> aspect) {
92 EXTRA_ASPECTS.add(aspect);
93 }
94
b8585c7c 95 /**
daf3c7eb
MK
96 * Return the analysis modules that are of a given class. The modules will be
97 * cast to the requested class. If the trace has children, the childrens modules
98 * are also returned.
b8585c7c
AM
99 *
100 * @param trace
daf3c7eb
MK
101 * The trace for which you want the modules, the children trace modules
102 * are added as well.
b8585c7c
AM
103 * @param moduleClass
104 * Returned modules must extend this class
105 * @return List of modules of class moduleClass
106 */
df2597e0 107 public static <T> Iterable<@NonNull T> getAnalysisModulesOfClass(ITmfTrace trace, Class<T> moduleClass) {
b8585c7c 108 Iterable<IAnalysisModule> analysisModules = trace.getAnalysisModules();
daf3c7eb 109 List<@NonNull T> modules = new ArrayList<>();
b1aad44e 110 for (IAnalysisModule module : analysisModules) {
b8585c7c 111 if (moduleClass.isAssignableFrom(module.getClass())) {
aa353506 112 modules.add(checkNotNull(moduleClass.cast(module)));
b8585c7c
AM
113 }
114 }
daf3c7eb
MK
115 for (ITmfEventProvider child : trace.getChildren()) {
116 if (child instanceof ITmfTrace) {
117 ITmfTrace childTrace = (ITmfTrace) child;
118 Iterables.addAll(modules, getAnalysisModulesOfClass(childTrace, moduleClass));
119 }
120 }
b8585c7c
AM
121 return modules;
122 }
35f39420
AM
123
124 /**
b1aad44e
GB
125 * Return the first result of the first aspect that resolves as non null for
126 * the event received in parameter. If the returned value is not null, it
127 * can be safely cast to the aspect's class proper return type.
35f39420
AM
128 *
129 * @param trace
130 * The trace for which you want the event aspects
131 * @param aspectClass
b1aad44e
GB
132 * The class of the aspect(s) to resolve
133 * @param event
134 * The event for which to get the aspect
135 * @return The first result of the
136 * {@link ITmfEventAspect#resolve(ITmfEvent)} that returns non null
137 * for the event or {@code null} otherwise
35f39420 138 */
c15e897d 139 public static <T extends ITmfEventAspect<?>> @Nullable Object resolveEventAspectOfClassForEvent(
1d83ed07 140 ITmfTrace trace, Class<T> aspectClass, ITmfEvent event) {
cf392b73
GB
141 // First look in the trace aspects
142 Object value = StreamUtils.getStream(trace.getEventAspects())
143 .filter(aspect -> aspectClass.isAssignableFrom(aspect.getClass()))
144 .map(aspect -> aspect.resolve(event))
145 .filter(obj -> obj != null)
146 .findFirst().orElse(null);
147 if (value != null) {
148 return value;
149 }
150 // If the value is not found, look at the global aspects
151 return EXTRA_ASPECTS.stream()
152 .filter(aspect -> aspectClass.isAssignableFrom(aspect.getClass()))
153 .map(aspect -> aspect.resolve(event))
154 .filter(obj -> obj != null)
155 .findFirst().orElse(null);
35f39420 156 }
d26d67f5 157
f75806c1
GB
158 /**
159 * Return the first result of the first aspect that resolves as non null for
160 * the event received in parameter. If the returned value is not null, it
161 * can be safely cast to the aspect's class proper return type.
162 *
163 * @param trace
164 * The trace for which you want the event aspects
165 * @param aspectName
166 * The class of the aspect(s) to resolve
167 * @param event
168 * The event for which to get the aspect
169 * @return The first result of the
170 * {@link ITmfEventAspect#resolve(ITmfEvent)} that returns non null
171 * for the event or {@code null} otherwise
4b40a764 172 * @since 3.0
f75806c1
GB
173 */
174 public static @Nullable Object resolveAspectOfNameForEvent(ITmfTrace trace, String aspectName, ITmfEvent event) {
175 // First look in the trace aspects
176 Object value = StreamUtils.getStream(trace.getEventAspects())
177 .filter(aspect -> aspectName.equalsIgnoreCase(aspect.getName()))
178 .map(aspect -> aspect.resolve(event))
179 .filter(obj -> obj != null)
180 .findFirst().orElse(null);
181 if (value != null) {
182 return value;
183 }
184 // If the value is not found, look at the global aspects
185 for (ITmfEventAspect<?> aspect : EXTRA_ASPECTS) {
186 if (aspectName.equalsIgnoreCase(aspect.getName())) {
187 value = aspect.resolve(event);
188 if (value != null) {
189 return value;
190 }
191 }
192 }
193 return null;
194 }
195
b3867ecc 196 /**
c15e897d
AM
197 * Return the first result of the first aspect that resolves as a non-null
198 * Integer for the event received in parameter. If no matching aspects are
199 * found then null is returned.
b3867ecc
MAL
200 *
201 * @param trace
202 * The trace for which you want the event aspects
203 * @param aspectClass
204 * The class of the aspect(s) to resolve
205 * @param event
206 * The event for which to get the aspect
207 * @return Integer of the first result of the
208 * {@link ITmfEventAspect#resolve(ITmfEvent)} that returns non null
209 * for the event or {@code null} otherwise
210 * @since 2.0
211 */
c15e897d 212 public static <T extends ITmfEventAspect<Integer>> @Nullable Integer resolveIntEventAspectOfClassForEvent(
b3867ecc 213 ITmfTrace trace, Class<T> aspectClass, ITmfEvent event) {
c15e897d
AM
214 return StreamUtils.getStream(trace.getEventAspects())
215 .filter(aspect -> aspectClass.isAssignableFrom(aspect.getClass()))
216 /* Enforced by the T parameter bounding */
217 .map(aspect -> (Integer) aspect.resolve(event))
218 .filter(obj -> obj != null)
219 .findFirst().orElse(null);
b3867ecc
MAL
220 }
221
d26d67f5
BH
222 /**
223 * Checks for text file.
224 *
225 * Note that it checks for binary value 0 in the first MAX_NB_BINARY_BYTES
226 * bytes to determine if the file is text.
227 *
228 * @param file
229 * the file to check. Caller has to make sure that file exists.
230 * @return true if it is binary else false
231 * @throws IOException
232 * if IOException occurs
066b02aa 233 * @since 1.2
d26d67f5
BH
234 */
235 public static boolean isText(File file) throws IOException {
236 try (BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file))) {
237 int count = 0;
238 int val = bufferedInputStream.read();
239 while ((count < MAX_NB_BINARY_BYTES) && (val >= 0)) {
240 if (val == 0) {
241 return false;
242 }
243 count++;
244 val = bufferedInputStream.read();
245 }
246 }
247 return true;
248 }
dba71686
AM
249
250 // ------------------------------------------------------------------------
251 // Event matching methods
252 // ------------------------------------------------------------------------
253
254 /**
255 * Retrieve from a trace the next event, from a starting rank, matching the
256 * given predicate.
257 *
258 * @param trace
259 * The trace
260 * @param startRank
261 * The rank of the event at which to start searching. Use
262 * <code>0</code> to search from the start of the trace.
263 * @param predicate
264 * The predicate to test events against
f8a23812
AM
265 * @param monitor
266 * Optional progress monitor that can be used to cancel the
267 * operation
dba71686
AM
268 * @return The first event matching the predicate, or null if the end of the
269 * trace was reached and no event was found
dc281431 270 * @since 2.1
dba71686 271 */
f8a23812
AM
272 public static @Nullable ITmfEvent getNextEventMatching(ITmfTrace trace, long startRank,
273 Predicate<ITmfEvent> predicate, @Nullable IProgressMonitor monitor) {
1353a51a
AM
274 if (monitor != null && monitor.isCanceled()) {
275 return null;
276 }
277
dba71686
AM
278 /* rank + 1 because we do not want to include the start event itself in the search */
279 EventMatchingRequest req = new EventMatchingRequest(startRank + 1, predicate, false);
280 trace.sendRequest(req);
281 try {
f8a23812
AM
282 /* Check periodically if the job was cancelled */
283 req.waitForStart();
284 while (req.isRunning()) {
285 Thread.sleep(200);
286 if (monitor != null && monitor.isCanceled()) {
287 req.cancel();
288 return null;
289 }
290 }
dba71686
AM
291 req.waitForCompletion();
292 } catch (InterruptedException e) {
293 return null;
294 }
295
296 return req.getFoundEvent();
297 }
298
299 /**
300 * Retrieve from a trace the previous event, from a given rank, matching the
301 * given predicate.
302 *
303 * @param trace
304 * The trace
305 * @param startRank
306 * The rank of the event at which to start searching backwards.
307 * @param predicate
308 * The predicate to test events against
f8a23812
AM
309 * @param monitor Optional progress monitor that can be used to cancel the
310 * operation
dba71686
AM
311 * @return The first event found matching the predicate, or null if the
312 * beginning of the trace was reached and no event was found
dc281431 313 * @since 2.1
dba71686 314 */
f8a23812
AM
315 public static @Nullable ITmfEvent getPreviousEventMatching(ITmfTrace trace, long startRank,
316 Predicate<ITmfEvent> predicate, @Nullable IProgressMonitor monitor) {
1353a51a
AM
317 if (monitor != null && monitor.isCanceled()) {
318 return null;
319 }
dba71686 320 /*
c93f91d9
MK
321 * We are going to do a series of queries matching the trace's cache
322 * size in length (which should minimize on-disk seeks), then iterate on
323 * the found events in reverse order until we find a match.
dba71686 324 */
c93f91d9 325 int step = trace.getCacheSize();
dba71686
AM
326
327 /*
328 * If we are close to the beginning of the trace, make sure we only look
329 * for the events before the startRank.
330 */
c93f91d9
MK
331 if (startRank < step) {
332 step = (int) startRank;
333 }
dba71686
AM
334
335 long currentRank = startRank;
336 try {
337 while (currentRank > 0) {
338 currentRank = Math.max(currentRank - step, 0);
339
c93f91d9
MK
340 List<ITmfEvent> list = new ArrayList<>(step);
341 ArrayFillingRequest req = new ArrayFillingRequest(currentRank, step, list);
dba71686 342 trace.sendRequest(req);
f8a23812
AM
343
344 /* Check periodically if the job was cancelled */
345 req.waitForStart();
346 while (req.isRunning()) {
347 Thread.sleep(200);
348 if (monitor != null && monitor.isCanceled()) {
349 req.cancel();
350 return null;
351 }
352 }
dba71686
AM
353 req.waitForCompletion();
354
c93f91d9
MK
355 Optional<ITmfEvent> matchingEvent = Lists.reverse(list).stream()
356 .filter(predicate)
357 .findFirst();
358
359 if (matchingEvent.isPresent()) {
360 /* We found an event matching, return it! */
361 return matchingEvent.get();
dba71686
AM
362 }
363 /* Keep searching, next loop */
364
365 }
366 } catch (InterruptedException e) {
367 return null;
368 }
369
370 /*
371 * We searched up to the beginning of the trace and didn't find
372 * anything.
373 */
374 return null;
375
376 }
377
378 /**
379 * Event request looking for an event matching a Predicate.
380 */
381 private static class EventMatchingRequest extends TmfEventRequest {
382
383 private final Predicate<ITmfEvent> fPredicate;
384 private final boolean fReturnLast;
385
386 private @Nullable ITmfEvent fFoundEvent = null;
387
388 /**
389 * Basic constructor, will query the trace until the end.
390 *
391 * @param startRank
392 * The rank at which to start, use 0 for the beginning
393 * @param predicate
394 * The predicate to test against each event
395 * @param returnLast
396 * Should we return the last or first event found. If false,
397 * the request ends as soon as a matching event is found. If
398 * false, we will go through all events to find a possible
399 * last-match.
400 */
401 public EventMatchingRequest(long startRank, Predicate<ITmfEvent> predicate, boolean returnLast) {
402 super(ITmfEvent.class, startRank, ALL_DATA, ExecutionType.FOREGROUND);
403 fPredicate = predicate;
404 fReturnLast = returnLast;
405 }
406
407 /**
408 * Basic constructor, will query the trace the limit is reached.
409 *
410 * @param startRank
411 * The rank at which to start, use 0 for the beginning
412 * @param limit
413 * The limit on the number of events
414 * @param predicate
415 * The predicate to test against each event
416 * @param returnLast
417 * Should we return the last or first event found. If false,
418 * the request ends as soon as a matching event is found. If
419 * false, we will go through all events to find a possible
420 * last-match.
421 */
422 public EventMatchingRequest(long startRank, int limit, Predicate<ITmfEvent> predicate, boolean returnLast) {
423 super(ITmfEvent.class, startRank, limit, ExecutionType.FOREGROUND);
424 fPredicate = predicate;
425 fReturnLast = returnLast;
426 }
427
428 public @Nullable ITmfEvent getFoundEvent() {
429 return fFoundEvent;
430 }
431
432 @Override
433 public void handleData(ITmfEvent event) {
434 super.handleData(event);
435
436 if (fPredicate.test(event)) {
437 fFoundEvent = event;
438 if (!fReturnLast) {
439 this.done();
440 }
441 }
442 }
443 }
c93f91d9
MK
444
445 /**
446 * Event request that simply puts all returned events into a list passed in
447 * parameter.
448 */
449 private static class ArrayFillingRequest extends TmfEventRequest {
450
451 private final List<ITmfEvent> fList;
452
453 public ArrayFillingRequest(long startRank, int limit, List<ITmfEvent> listToFill) {
454 super(ITmfEvent.class, startRank, limit, ExecutionType.FOREGROUND);
455 fList = listToFill;
456 }
457
458 @Override
459 public void handleData(ITmfEvent event) {
460 super.handleData(event);
461 fList.add(event);
462 }
463
464 }
b8585c7c 465}
This page took 0.099372 seconds and 5 git commands to generate.