1 /*******************************************************************************
2 * Copyright (c) 2015 Ericsson
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 package org
.eclipse
.tracecompass
.analysis
.timing
.core
.segmentstore
;
11 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
13 import java
.io
.IOException
;
14 import java
.io
.ObjectInputStream
;
15 import java
.io
.ObjectOutputStream
;
16 import java
.nio
.file
.Files
;
17 import java
.nio
.file
.Path
;
18 import java
.nio
.file
.Paths
;
19 import java
.util
.ArrayList
;
20 import java
.util
.Collection
;
21 import java
.util
.List
;
23 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
24 import org
.eclipse
.core
.runtime
.ListenerList
;
25 import org
.eclipse
.jdt
.annotation
.Nullable
;
26 import org
.eclipse
.tracecompass
.segmentstore
.core
.ISegment
;
27 import org
.eclipse
.tracecompass
.segmentstore
.core
.ISegmentStore
;
28 import org
.eclipse
.tracecompass
.segmentstore
.core
.treemap
.TreeMapStore
;
29 import org
.eclipse
.tracecompass
.tmf
.core
.analysis
.TmfAbstractAnalysisModule
;
30 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
31 import org
.eclipse
.tracecompass
.tmf
.core
.exceptions
.TmfAnalysisException
;
32 import org
.eclipse
.tracecompass
.tmf
.core
.request
.ITmfEventRequest
;
33 import org
.eclipse
.tracecompass
.tmf
.core
.request
.TmfEventRequest
;
34 import org
.eclipse
.tracecompass
.tmf
.core
.segment
.ISegmentAspect
;
35 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
36 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
38 import com
.google
.common
.collect
.ImmutableList
;
41 * Abstract analysis module to generate a segment store. It is a base class that
42 * can be used as a shortcut by analysis who just need to build a single segment
45 * @author Bernd Hufmann
49 public abstract class AbstractSegmentStoreAnalysisModule
extends TmfAbstractAnalysisModule
{
51 private final ListenerList fListeners
= new ListenerList(ListenerList
.IDENTITY
);
53 private @Nullable ISegmentStore
<ISegment
> fSegmentStore
;
55 private @Nullable ITmfEventRequest fOngoingRequest
= null;
58 * Listener for the viewers
61 * listener for each type of viewer
63 public void addListener(IAnalysisProgressListener listener
) {
64 fListeners
.add(listener
);
68 * Removes a listener for the viewers
71 * listener for each type of viewer to remove
73 public void removeListener(IAnalysisProgressListener listener
) {
74 fListeners
.remove(listener
);
78 * Returns all the listeners
80 * @return latency listeners
82 protected Iterable
<IAnalysisProgressListener
> getListeners() {
83 List
<IAnalysisProgressListener
> listeners
= new ArrayList
<>();
84 for (Object listener
: fListeners
.getListeners()) {
85 if (listener
!= null) {
86 listeners
.add((IAnalysisProgressListener
) listener
);
93 * Return the pre-defined set of segment aspects exposed by this analysis.
95 * It should not be null, but could be empty.
97 * @return The segment aspects for this analysis
99 public Iterable
<ISegmentAspect
> getSegmentAspects() {
100 Collection
<ISegmentAspect
> coll
= ImmutableList
.of();
101 return checkNotNull(coll
);
105 * Returns the file name for storing segment store
107 * @return segment store fine name, or null if you don't want a file
109 protected @Nullable String
getDataFileName() {
114 * Returns the analysis request for creating the segment store
116 * @param segmentStore
117 * a segment store to fill
118 * @return the segment store analysis request implementation
120 protected abstract AbstractSegmentStoreAnalysisRequest
createAnalysisRequest(ISegmentStore
<ISegment
> segmentStore
);
123 * Read an object from the ObjectInputStream.
126 * the ObjectInputStream to used
127 * @return the read object
128 * @throws ClassNotFoundException
129 * - Class of a serialized object cannot be found.
130 * @throws IOException
131 * - Any of the usual Input/Output related exceptions.
133 protected abstract Object
[] readObject(ObjectInputStream ois
) throws ClassNotFoundException
, IOException
;
136 * Returns the result in a from the analysis in a ISegmentStore
138 * @return Results from the analysis in a ISegmentStore
140 public @Nullable ISegmentStore
<ISegment
> getResults() {
141 return fSegmentStore
;
145 protected void canceling() {
146 ITmfEventRequest req
= fOngoingRequest
;
147 if ((req
!= null) && (!req
.isCompleted())) {
153 public void dispose() {
155 ISegmentStore
<ISegment
> store
= fSegmentStore
;
162 protected boolean executeAnalysis(IProgressMonitor monitor
) throws TmfAnalysisException
{
163 ITmfTrace trace
= checkNotNull(getTrace());
165 final @Nullable String dataFileName
= getDataFileName();
166 if (dataFileName
!= null) {
167 /* See if the data file already exists on disk */
168 String dir
= TmfTraceManager
.getSupplementaryFileDir(trace
);
169 final Path file
= Paths
.get(dir
, dataFileName
);
171 if (Files
.exists(file
)) {
172 /* Attempt to read the existing file */
173 try (ObjectInputStream ois
= new ObjectInputStream(Files
.newInputStream(file
))) {
174 Object
[] segmentArray
= readObject(ois
);
175 final ISegmentStore
<ISegment
> store
= new TreeMapStore
<>();
176 for (Object element
: segmentArray
) {
177 if (element
instanceof ISegment
) {
178 ISegment segment
= (ISegment
) element
;
182 fSegmentStore
= store
;
183 for (IAnalysisProgressListener listener
: getListeners()) {
184 listener
.onComplete(this, store
);
187 } catch (IOException
| ClassNotFoundException
| ClassCastException e
) {
189 * We did not manage to read the file successfully, we will
190 * just fall-through to rebuild a new one.
194 } catch (IOException e1
) {
199 ISegmentStore
<ISegment
> segmentStore
= new TreeMapStore
<>();
201 /* Cancel an ongoing request */
202 ITmfEventRequest req
= fOngoingRequest
;
203 if ((req
!= null) && (!req
.isCompleted())) {
207 /* Create a new request */
208 req
= createAnalysisRequest(segmentStore
);
209 fOngoingRequest
= req
;
210 trace
.sendRequest(req
);
213 req
.waitForCompletion();
214 } catch (InterruptedException e
) {
217 /* Do not process the results if the request was cancelled */
218 if (req
.isCancelled() || req
.isFailed()) {
222 /* The request will fill 'syscalls' */
223 fSegmentStore
= segmentStore
;
225 if (dataFileName
!= null) {
226 String dir
= TmfTraceManager
.getSupplementaryFileDir(trace
);
227 final Path file
= Paths
.get(dir
, dataFileName
);
229 /* Serialize the collections to disk for future usage */
230 try (ObjectOutputStream oos
= new ObjectOutputStream(Files
.newOutputStream(file
))) {
231 oos
.writeObject(segmentStore
.toArray());
232 } catch (IOException e
) {
234 * Didn't work, oh well. We will just re-read the trace next
240 for (IAnalysisProgressListener listener
: getListeners()) {
241 listener
.onComplete(this, segmentStore
);
248 * Abstract event request to fill a a segment store
250 protected static abstract class AbstractSegmentStoreAnalysisRequest
extends TmfEventRequest
{
252 private final ISegmentStore
<ISegment
> fFullLatencyStore
;
257 * @param latencyStore
258 * a latency segment store to fill
260 public AbstractSegmentStoreAnalysisRequest(ISegmentStore
<ISegment
> latencyStore
) {
261 super(ITmfEvent
.class, 0, ITmfEventRequest
.ALL_DATA
, ExecutionType
.BACKGROUND
);
263 * We do NOT make a copy here! We want to modify the list that was
264 * passed in parameter.
266 fFullLatencyStore
= latencyStore
;
270 * Returns the segment store
272 * @return the segment store
274 public ISegmentStore
<ISegment
> getSegmentStore() {
275 return fFullLatencyStore
;