tmf: Export xychart packages in tmf.ui
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / statesystem / TmfStateSystemAnalysisModule.java
CommitLineData
8a6ff07f 1/*******************************************************************************
60ae41e1 2 * Copyright (c) 2013, 2014 École Polytechnique de Montréal
8a6ff07f
GB
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 * Geneviève Bastien - Initial API and implementation
baa96b1d 11 * Bernd Hufmann - Integrated history builder functionality
8a6ff07f
GB
12 *******************************************************************************/
13
14package org.eclipse.linuxtools.tmf.core.statesystem;
15
16import java.io.File;
baa96b1d 17import java.io.IOException;
5237a931 18import java.util.Collections;
09ec275e 19import java.util.concurrent.CountDownLatch;
8a6ff07f
GB
20
21import org.eclipse.core.runtime.IProgressMonitor;
baa96b1d 22import org.eclipse.core.runtime.NullProgressMonitor;
8a6ff07f 23import org.eclipse.jdt.annotation.NonNull;
baa96b1d
BH
24import org.eclipse.jdt.annotation.NonNullByDefault;
25import org.eclipse.jdt.annotation.Nullable;
26import org.eclipse.linuxtools.internal.tmf.core.statesystem.StateSystem;
27import org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.IStateHistoryBackend;
28import org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.InMemoryBackend;
29import org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.NullBackend;
30import org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.historytree.HistoryTreeBackend;
31import org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.historytree.ThreadedHistoryTreeBackend;
32import org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.partial.PartialHistoryBackend;
33import org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.partial.PartialStateSystem;
8a6ff07f 34import org.eclipse.linuxtools.tmf.core.analysis.TmfAbstractAnalysisModule;
baa96b1d 35import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
8a6ff07f 36import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException;
baa96b1d
BH
37import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest;
38import org.eclipse.linuxtools.tmf.core.request.TmfEventRequest;
39import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange;
40import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
8a6ff07f
GB
41import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager;
42
43/**
44 * Abstract analysis module to generate a state system. It is a base class that
45 * can be used as a shortcut by analysis who just need to build a single state
46 * system with a state provider.
47 *
48 * Analysis implementing this class should only need to provide a state system
49 * and optionally a backend (default to NULL) and, if required, a filename
50 * (defaults to the analysis'ID)
51 *
52 * @author Geneviève Bastien
53 * @since 3.0
54 */
baa96b1d 55@NonNullByDefault
8a6ff07f 56public abstract class TmfStateSystemAnalysisModule extends TmfAbstractAnalysisModule
5237a931 57 implements ITmfAnalysisModuleWithStateSystems {
8a6ff07f 58
8a6ff07f 59 private static final String EXTENSION = ".ht"; //$NON-NLS-1$
84a9548a 60 private static final String UNDEFINED_ID = "undefined"; //$NON-NLS-1$
8a6ff07f 61
09ec275e
AM
62 private final CountDownLatch fInitialized = new CountDownLatch(1);
63
baa96b1d
BH
64 @Nullable private ITmfStateSystemBuilder fStateSystem;
65 @Nullable private ITmfStateProvider fStateProvider;
66 @Nullable private IStateHistoryBackend fHtBackend;
67 @Nullable private ITmfEventRequest fRequest;
5237a931 68
8a6ff07f
GB
69 /**
70 * State system backend types
71 *
72 * @author Geneviève Bastien
73 */
74 protected enum StateSystemBackendType {
75 /** Full history in file */
76 FULL,
77 /** In memory state system */
78 INMEM,
79 /** Null history */
80 NULL,
81 /** State system backed with partial history */
82 PARTIAL
83 }
84
85 /**
86 * Get the state provider for this analysis module
87 *
88 * @return the state provider
89 */
8a6ff07f
GB
90 protected abstract ITmfStateProvider createStateProvider();
91
92 /**
93 * Get the state system backend type used by this module
94 *
95 * @return The {@link StateSystemBackendType}
96 */
a3b864c0
AM
97 protected StateSystemBackendType getBackendType() {
98 /* Using full history by default, sub-classes can override */
99 return StateSystemBackendType.FULL;
100 }
8a6ff07f
GB
101
102 /**
103 * Get the supplementary file name where to save this state system. The
104 * default is the ID of the analysis followed by the extension.
105 *
106 * @return The supplementary file name
107 */
108 protected String getSsFileName() {
109 return getId() + EXTENSION;
110 }
111
112 /**
baa96b1d
BH
113 * Get the state system generated by this analysis, or null if it is not yet
114 * created.
8a6ff07f
GB
115 *
116 * @return The state system
117 */
baa96b1d 118 @Nullable
8a6ff07f
GB
119 public ITmfStateSystem getStateSystem() {
120 return fStateSystem;
121 }
122
09ec275e
AM
123 /**
124 * Block the calling thread until the analysis module has been initialized.
125 * After this method returns, {@link #getStateSystem()} should not return
126 * null anymore.
127 */
128 public void waitForInitialization() {
129 try {
130 fInitialized.await();
131 } catch (InterruptedException e) {}
132 }
133
baa96b1d
BH
134 // ------------------------------------------------------------------------
135 // TmfAbstractAnalysisModule
136 // ------------------------------------------------------------------------
8a6ff07f 137
baa96b1d
BH
138 @Override
139 protected boolean executeAnalysis(@Nullable final IProgressMonitor monitor) {
140 IProgressMonitor mon = (monitor == null ? new NullProgressMonitor() : monitor);
141 final ITmfStateProvider provider = createStateProvider();
8a6ff07f 142
84a9548a
AM
143 String id = getId();
144 if (id == null) {
145 /* The analysis module does not specify an ID, use a generic one */
146 id = UNDEFINED_ID;
147 }
148
8a6ff07f
GB
149 /* FIXME: State systems should make use of the monitor, to be cancelled */
150 try {
151 /* Get the state system according to backend */
152 StateSystemBackendType backend = getBackendType();
153 String directory;
baa96b1d 154 File htFile;
8a6ff07f
GB
155 switch (backend) {
156 case FULL:
157 directory = TmfTraceManager.getSupplementaryFileDir(getTrace());
baa96b1d 158 htFile = new File(directory + getSsFileName());
84a9548a 159 createFullHistory(id, provider, htFile);
8a6ff07f
GB
160 break;
161 case PARTIAL:
162 directory = TmfTraceManager.getSupplementaryFileDir(getTrace());
baa96b1d 163 htFile = new File(directory + getSsFileName());
84a9548a 164 createPartialHistory(id, provider, htFile);
8a6ff07f
GB
165 break;
166 case INMEM:
84a9548a 167 createInMemoryHistory(id, provider);
8a6ff07f
GB
168 break;
169 case NULL:
84a9548a 170 createNullHistory(id, provider);
8a6ff07f
GB
171 break;
172 default:
173 break;
174 }
175 } catch (TmfTraceException e) {
176 return false;
177 }
baa96b1d 178 return !mon.isCanceled();
8a6ff07f
GB
179 }
180
181 @Override
182 protected void canceling() {
baa96b1d
BH
183 ITmfEventRequest req = fRequest;
184 if ((req != null) && (!req.isCompleted())) {
185 req.cancel();
186 }
187 }
188
a1529f38
AM
189 @Override
190 public void dispose() {
191 if (fStateSystem != null) {
192 fStateSystem.dispose();
193 }
194 super.dispose();
195 }
196
baa96b1d
BH
197 // ------------------------------------------------------------------------
198 // History creation methods
199 // ------------------------------------------------------------------------
200
201 /*
202 * Load the history file matching the target trace. If the file already
203 * exists, it will be opened directly. If not, it will be created from
204 * scratch.
205 */
84a9548a 206 private void createFullHistory(String id, ITmfStateProvider provider, File htFile) throws TmfTraceException {
baa96b1d
BH
207
208 /* If the target file already exists, do not rebuild it uselessly */
209 // TODO for now we assume it's complete. Might be a good idea to check
210 // at least if its range matches the trace's range.
211
212 if (htFile.exists()) {
213 /* Load an existing history */
214 final int version = provider.getVersion();
215 try {
84a9548a
AM
216 IStateHistoryBackend backend = new HistoryTreeBackend(htFile, version);
217 fHtBackend = backend;
218 fStateSystem = new StateSystem(id, backend, false);
09ec275e 219 fInitialized.countDown();
baa96b1d
BH
220 return;
221 } catch (IOException e) {
222 /*
223 * There was an error opening the existing file. Perhaps it was
224 * corrupted, perhaps it's an old version? We'll just
225 * fall-through and try to build a new one from scratch instead.
226 */
227 }
228 }
229
230 /* Size of the blocking queue to use when building a state history */
231 final int QUEUE_SIZE = 10000;
232
233 try {
84a9548a 234 IStateHistoryBackend backend = new ThreadedHistoryTreeBackend(htFile,
baa96b1d 235 provider.getStartTime(), provider.getVersion(), QUEUE_SIZE);
84a9548a
AM
236 fHtBackend = backend;
237 fStateSystem = new StateSystem(id, backend);
baa96b1d
BH
238 provider.assignTargetStateSystem(fStateSystem);
239 build(provider);
240 } catch (IOException e) {
241 /*
242 * If it fails here however, it means there was a problem writing to
243 * the disk, so throw a real exception this time.
244 */
245 throw new TmfTraceException(e.toString(), e);
246 }
247 }
248
249 /*
250 * Create a new state system backed with a partial history. A partial
251 * history is similar to a "full" one (which you get with
252 * {@link #newFullHistory}), except that the file on disk is much smaller,
253 * but queries are a bit slower.
254 *
255 * Also note that single-queries are implemented using a full-query
256 * underneath, (which are much slower), so this might not be a good fit for
257 * a use case where you have to do lots of single queries.
258 */
84a9548a 259 private void createPartialHistory(String id, ITmfStateProvider provider, File htPartialFile)
baa96b1d
BH
260 throws TmfTraceException {
261 /*
262 * The order of initializations is very tricky (but very important!)
263 * here. We need to follow this pattern:
264 * (1 is done before the call to this method)
265 *
266 * 1- Instantiate realStateProvider
267 * 2- Instantiate realBackend
268 * 3- Instantiate partialBackend, with prereqs:
269 * 3a- Instantiate partialProvider, via realProvider.getNew()
270 * 3b- Instantiate nullBackend (partialSS's backend)
271 * 3c- Instantiate partialSS
272 * 3d- partialProvider.assignSS(partialSS)
273 * 4- Instantiate realSS
274 * 5- partialSS.assignUpstream(realSS)
275 * 6- realProvider.assignSS(realSS)
276 * 7- Call HistoryBuilder(realProvider, realSS, partialBackend) to build the thing.
277 */
278
279 /* Size of the blocking queue to use when building a state history */
280 final int QUEUE_SIZE = 10000;
281
282 final long granularity = 50000;
283
284 /* 2 */
285 IStateHistoryBackend realBackend = null;
286 try {
287 realBackend = new ThreadedHistoryTreeBackend(htPartialFile,
288 provider.getStartTime(), provider.getVersion(), QUEUE_SIZE);
289 } catch (IOException e) {
290 throw new TmfTraceException(e.toString(), e);
291 }
292
293 /* 3a */
294 ITmfStateProvider partialProvider = provider.getNewInstance();
295
296 /* 3b-3c, constructor automatically uses a NullBackend */
297 PartialStateSystem pss = new PartialStateSystem();
298
299 /* 3d */
300 partialProvider.assignTargetStateSystem(pss);
301
302 /* 3 */
303 IStateHistoryBackend partialBackend =
304 new PartialHistoryBackend(partialProvider, pss, realBackend, granularity);
305
306 /* 4 */
84a9548a 307 StateSystem realSS = new StateSystem(id, partialBackend);
baa96b1d
BH
308
309 /* 5 */
310 pss.assignUpstream(realSS);
311
312 /* 6 */
313 provider.assignTargetStateSystem(realSS);
314
315 /* 7 */
316 fHtBackend = partialBackend;
317 fStateSystem = realSS;
318
319 build(provider);
320 }
321
322 /*
323 * Create a new state system using a null history back-end. This means that
324 * no history intervals will be saved anywhere, and as such only
325 * {@link ITmfStateSystem#queryOngoingState} will be available.
326 */
84a9548a
AM
327 private void createNullHistory(String id, ITmfStateProvider provider) {
328 IStateHistoryBackend backend = new NullBackend();
329 fHtBackend = backend;
330 fStateSystem = new StateSystem(id, backend);
baa96b1d
BH
331 provider.assignTargetStateSystem(fStateSystem);
332 build(provider);
333 }
334
335 /*
336 * Create a new state system using in-memory interval storage. This should
337 * only be done for very small state system, and will be naturally limited
338 * to 2^31 intervals.
339 */
84a9548a
AM
340 private void createInMemoryHistory(String id, ITmfStateProvider provider) {
341 IStateHistoryBackend backend = new InMemoryBackend(provider.getStartTime());
342 fHtBackend = backend;
343 fStateSystem = new StateSystem(id, backend);
baa96b1d
BH
344 provider.assignTargetStateSystem(fStateSystem);
345 build(provider);
346 }
347
a1529f38 348 private void disposeProvider(boolean deleteFiles) {
baa96b1d
BH
349 ITmfStateProvider provider = fStateProvider;
350 if (provider != null) {
351 provider.dispose();
352 }
353 if (deleteFiles && (fHtBackend != null)) {
354 fHtBackend.removeFiles();
355 }
356 }
357
358 private void build(ITmfStateProvider provider) {
359 if ((fStateSystem == null) || (fHtBackend == null)) {
360 throw new IllegalArgumentException();
361 }
362
363 ITmfEventRequest request = fRequest;
364 if ((request != null) && (!request.isCompleted())) {
365 request.cancel();
366 }
367
368 request = new StateSystemEventRequest(provider);
369 provider.getTrace().sendRequest(request);
370
8a6ff07f 371 /*
baa96b1d
BH
372 * Only now that we've actually started the build, we'll update the
373 * class fields, so that they become visible for other callers.
8a6ff07f 374 */
baa96b1d
BH
375 fStateProvider = provider;
376 fRequest = request;
377
09ec275e
AM
378 /*
379 * The state system object is now created, we can consider this module
380 * "initialized" (components can retrieve it and start doing queries).
381 */
382 fInitialized.countDown();
383
384 /*
385 * Block the executeAnalysis() construction is complete (so that the
386 * progress monitor displays that it is running).
387 */
baa96b1d 388 try {
09ec275e 389 request.waitForCompletion();
baa96b1d
BH
390 } catch (InterruptedException e) {
391 e.printStackTrace();
392 }
393 }
394
395 private class StateSystemEventRequest extends TmfEventRequest {
396 private final ITmfStateProvider sci;
397 private final ITmfTrace trace;
398
399 public StateSystemEventRequest(ITmfStateProvider sp) {
400 super(sp.getExpectedEventType(),
401 TmfTimeRange.ETERNITY,
402 0,
403 ITmfEventRequest.ALL_DATA,
404 ITmfEventRequest.ExecutionType.BACKGROUND);
405 this.sci = sp;
406
407 // sci.getTrace() will eventually return a @NonNull
408 @SuppressWarnings("null")
409 @NonNull ITmfTrace tr = sci.getTrace();
410
411 this.trace = tr;
412 }
413
414 @Override
415 public void handleData(final @Nullable ITmfEvent event) {
416 super.handleData(event);
417 if (event != null && event.getTrace() == trace) {
418 sci.processEvent(event);
419 }
420 }
421
422 @Override
423 public void handleSuccess() {
424 super.handleSuccess();
a1529f38 425 disposeProvider(false);
baa96b1d
BH
426 }
427
428 @Override
429 public void handleCancel() {
430 super.handleCancel();
a1529f38 431 disposeProvider(true);
baa96b1d
BH
432 }
433
434 @Override
435 public void handleFailure() {
436 super.handleFailure();
a1529f38 437 disposeProvider(true);
baa96b1d 438 }
8a6ff07f
GB
439 }
440
5237a931
AM
441 // ------------------------------------------------------------------------
442 // ITmfAnalysisModuleWithStateSystems
443 // ------------------------------------------------------------------------
444
445 @Override
baa96b1d
BH
446 @Nullable
447 public ITmfStateSystem getStateSystem(String id) {
5237a931
AM
448 if (id.equals(getId())) {
449 return fStateSystem;
450 }
451 return null;
452 }
453
8a6ff07f 454 @Override
5237a931 455 public Iterable<ITmfStateSystem> getStateSystems() {
baa96b1d
BH
456 @SuppressWarnings("null")
457 @NonNull Iterable<ITmfStateSystem> ret = Collections.singleton((ITmfStateSystem) fStateSystem);
458 return ret;
8a6ff07f
GB
459 }
460}
This page took 0.050544 seconds and 5 git commands to generate.