segment store: introduce a Segment Store Factory and centralize segment stores
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.timing.core / src / org / eclipse / tracecompass / analysis / timing / core / segmentstore / AbstractSegmentStoreAnalysisModule.java
1 /*******************************************************************************
2 * Copyright (c) 2015, 2016 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 package org.eclipse.tracecompass.analysis.timing.core.segmentstore;
10
11 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
12
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.Collections;
21 import java.util.List;
22
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.common.core.NonNullUtils;
27 import org.eclipse.tracecompass.segmentstore.core.ISegment;
28 import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
29 import org.eclipse.tracecompass.segmentstore.core.SegmentStoreFactory;
30 import org.eclipse.tracecompass.tmf.core.analysis.TmfAbstractAnalysisModule;
31 import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
32 import org.eclipse.tracecompass.tmf.core.segment.ISegmentAspect;
33 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
34 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
35
36 /**
37 * Abstract analysis module to generate a segment store. It is a base class that
38 * can be used as a shortcut by analysis who just need to build a single segment
39 * store.
40 *
41 * @author Bernd Hufmann
42 * @since 2.0
43 *
44 */
45 public abstract class AbstractSegmentStoreAnalysisModule extends TmfAbstractAnalysisModule implements ISegmentStoreProvider {
46
47 private final ListenerList fListeners = new ListenerList(ListenerList.IDENTITY);
48
49 private @Nullable ISegmentStore<ISegment> fSegmentStore;
50
51 @Override
52 public void addListener(IAnalysisProgressListener listener) {
53 fListeners.add(listener);
54 }
55
56 @Override
57 public void removeListener(IAnalysisProgressListener listener) {
58 fListeners.remove(listener);
59 }
60
61 /**
62 * Returns all the listeners
63 *
64 * @return latency listeners
65 */
66 protected Iterable<IAnalysisProgressListener> getListeners() {
67 List<IAnalysisProgressListener> listeners = new ArrayList<>();
68 for (Object listener : fListeners.getListeners()) {
69 if (listener != null) {
70 listeners.add((IAnalysisProgressListener) listener);
71 }
72 }
73 return listeners;
74 }
75
76 @Override
77 public Iterable<ISegmentAspect> getSegmentAspects() {
78 return Collections.emptyList();
79 }
80
81 /**
82 * Returns the file name for storing segment store
83 *
84 * @return segment store fine name, or null if you don't want a file
85 */
86 protected @Nullable String getDataFileName() {
87 return null;
88 }
89
90 /**
91 * Read an object from the ObjectInputStream.
92 *
93 * @param ois
94 * the ObjectInputStream to used
95 * @return the read object
96 * @throws ClassNotFoundException
97 * - Class of a serialized object cannot be found.
98 * @throws IOException
99 * - Any of the usual Input/Output related exceptions.
100 */
101 protected abstract Object[] readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException;
102
103 /**
104 * Fills the segment store. This is the main method that children classes
105 * need to implement to build the segment store. For example, if the
106 * segments are found by parsing the events of a trace, the event request
107 * would be done in this method.
108 *
109 * Note: After this method, the segment store should be completed, so it
110 * should also close the segment store at the end of the analysis
111 *
112 * @param segmentStore
113 * The segment store to fill
114 * @param monitor
115 * Progress monitor
116 * @return Whether the segments was resolved successfully or not
117 * @throws TmfAnalysisException
118 * Method may throw an analysis exception
119 */
120 protected abstract boolean buildAnalysisSegments(ISegmentStore<ISegment> segmentStore, IProgressMonitor monitor) throws TmfAnalysisException;
121
122 @Override
123 public @Nullable ISegmentStore<ISegment> getSegmentStore() {
124 return fSegmentStore;
125 }
126
127 @Override
128 public void dispose() {
129 super.dispose();
130 ISegmentStore<ISegment> store = fSegmentStore;
131 if (store != null) {
132 store.dispose();
133 }
134 }
135
136 @Override
137 protected boolean executeAnalysis(IProgressMonitor monitor) throws TmfAnalysisException {
138 ITmfTrace trace = checkNotNull(getTrace());
139
140 final @Nullable String dataFileName = getDataFileName();
141 if (dataFileName != null) {
142 /* See if the data file already exists on disk */
143 String dir = TmfTraceManager.getSupplementaryFileDir(trace);
144 final Path file = Paths.get(dir, dataFileName);
145
146 if (Files.exists(file)) {
147 /* Attempt to read the existing file */
148 try (ObjectInputStream ois = new ObjectInputStream(Files.newInputStream(file))) {
149 Object[] segmentArray = readObject(ois);
150 ISegmentStore<ISegment> store = SegmentStoreFactory.createSegmentStore(NonNullUtils.checkNotNullContents(segmentArray));
151 fSegmentStore = store;
152 sendUpdate(store);
153 return true;
154 } catch (IOException | ClassNotFoundException | ClassCastException e) {
155 /*
156 * We did not manage to read the file successfully, we will
157 * just fall-through to rebuild a new one.
158 */
159 try {
160 Files.delete(file);
161 } catch (IOException e1) {
162 }
163 }
164 }
165 }
166
167 ISegmentStore<ISegment> segmentStore = SegmentStoreFactory.createSegmentStore();
168 boolean completed = buildAnalysisSegments(segmentStore, monitor);
169 if (!completed) {
170 return false;
171 }
172 fSegmentStore = segmentStore;
173
174 if (dataFileName != null) {
175 String dir = TmfTraceManager.getSupplementaryFileDir(trace);
176 final Path file = Paths.get(dir, dataFileName);
177
178 /* Serialize the collections to disk for future usage */
179 try (ObjectOutputStream oos = new ObjectOutputStream(Files.newOutputStream(file))) {
180 oos.writeObject(segmentStore.toArray());
181 } catch (IOException e) {
182 /*
183 * Didn't work, oh well. We will just re-read the trace next
184 * time
185 */
186 }
187 }
188
189 sendUpdate(segmentStore);
190
191 return true;
192 }
193
194 /**
195 * Send the segment store to all its listener
196 *
197 * @param store
198 * The segment store to broadcast
199 */
200 protected void sendUpdate(final ISegmentStore<ISegment> store) {
201 for (IAnalysisProgressListener listener : getListeners()) {
202 listener.onComplete(this, store);
203 }
204 }
205 }
This page took 0.036158 seconds and 5 git commands to generate.