lttng: Fix string externalization in plugin.xml's
[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;
baa96b1d
BH
26import org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.partial.PartialHistoryBackend;
27import org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.partial.PartialStateSystem;
bcec0116
AM
28import org.eclipse.linuxtools.statesystem.core.ITmfStateSystem;
29import org.eclipse.linuxtools.statesystem.core.ITmfStateSystemBuilder;
30import org.eclipse.linuxtools.statesystem.core.StateSystemFactory;
31import org.eclipse.linuxtools.statesystem.core.backend.IStateHistoryBackend;
32import org.eclipse.linuxtools.statesystem.core.backend.InMemoryBackend;
33import org.eclipse.linuxtools.statesystem.core.backend.NullBackend;
34import org.eclipse.linuxtools.statesystem.core.backend.historytree.HistoryTreeBackend;
35import org.eclipse.linuxtools.statesystem.core.backend.historytree.ThreadedHistoryTreeBackend;
8a6ff07f 36import org.eclipse.linuxtools.tmf.core.analysis.TmfAbstractAnalysisModule;
baa96b1d 37import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
8a6ff07f 38import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException;
baa96b1d
BH
39import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest;
40import org.eclipse.linuxtools.tmf.core.request.TmfEventRequest;
41import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange;
42import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
2d208fb7 43import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;
8a6ff07f
GB
44import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager;
45
46/**
47 * Abstract analysis module to generate a state system. It is a base class that
48 * can be used as a shortcut by analysis who just need to build a single state
49 * system with a state provider.
50 *
51 * Analysis implementing this class should only need to provide a state system
52 * and optionally a backend (default to NULL) and, if required, a filename
53 * (defaults to the analysis'ID)
54 *
55 * @author Geneviève Bastien
56 * @since 3.0
57 */
baa96b1d 58@NonNullByDefault
8a6ff07f 59public abstract class TmfStateSystemAnalysisModule extends TmfAbstractAnalysisModule
5237a931 60 implements ITmfAnalysisModuleWithStateSystems {
8a6ff07f 61
8a6ff07f
GB
62 private static final String EXTENSION = ".ht"; //$NON-NLS-1$
63
09ec275e
AM
64 private final CountDownLatch fInitialized = new CountDownLatch(1);
65
baa96b1d
BH
66 @Nullable private ITmfStateSystemBuilder fStateSystem;
67 @Nullable private ITmfStateProvider fStateProvider;
68 @Nullable private IStateHistoryBackend fHtBackend;
69 @Nullable private ITmfEventRequest fRequest;
5237a931 70
8a6ff07f
GB
71 /**
72 * State system backend types
73 *
74 * @author Geneviève Bastien
75 */
76 protected enum StateSystemBackendType {
77 /** Full history in file */
78 FULL,
79 /** In memory state system */
80 INMEM,
81 /** Null history */
82 NULL,
83 /** State system backed with partial history */
84 PARTIAL
85 }
86
87 /**
88 * Get the state provider for this analysis module
89 *
90 * @return the state provider
91 */
8a6ff07f
GB
92 protected abstract ITmfStateProvider createStateProvider();
93
94 /**
95 * Get the state system backend type used by this module
96 *
97 * @return The {@link StateSystemBackendType}
98 */
a3b864c0
AM
99 protected StateSystemBackendType getBackendType() {
100 /* Using full history by default, sub-classes can override */
101 return StateSystemBackendType.FULL;
102 }
8a6ff07f
GB
103
104 /**
105 * Get the supplementary file name where to save this state system. The
106 * default is the ID of the analysis followed by the extension.
107 *
108 * @return The supplementary file name
109 */
110 protected String getSsFileName() {
111 return getId() + EXTENSION;
112 }
113
114 /**
baa96b1d
BH
115 * Get the state system generated by this analysis, or null if it is not yet
116 * created.
8a6ff07f
GB
117 *
118 * @return The state system
119 */
baa96b1d 120 @Nullable
8a6ff07f
GB
121 public ITmfStateSystem getStateSystem() {
122 return fStateSystem;
123 }
124
09ec275e
AM
125 /**
126 * Block the calling thread until the analysis module has been initialized.
127 * After this method returns, {@link #getStateSystem()} should not return
128 * null anymore.
129 */
130 public void waitForInitialization() {
131 try {
132 fInitialized.await();
133 } catch (InterruptedException e) {}
134 }
135
baa96b1d
BH
136 // ------------------------------------------------------------------------
137 // TmfAbstractAnalysisModule
138 // ------------------------------------------------------------------------
8a6ff07f 139
baa96b1d
BH
140 @Override
141 protected boolean executeAnalysis(@Nullable final IProgressMonitor monitor) {
142 IProgressMonitor mon = (monitor == null ? new NullProgressMonitor() : monitor);
143 final ITmfStateProvider provider = createStateProvider();
8a6ff07f 144
84a9548a 145 String id = getId();
84a9548a 146
8a6ff07f
GB
147 /* FIXME: State systems should make use of the monitor, to be cancelled */
148 try {
149 /* Get the state system according to backend */
150 StateSystemBackendType backend = getBackendType();
151 String directory;
baa96b1d 152 File htFile;
8a6ff07f
GB
153 switch (backend) {
154 case FULL:
155 directory = TmfTraceManager.getSupplementaryFileDir(getTrace());
baa96b1d 156 htFile = new File(directory + getSsFileName());
84a9548a 157 createFullHistory(id, provider, htFile);
8a6ff07f
GB
158 break;
159 case PARTIAL:
160 directory = TmfTraceManager.getSupplementaryFileDir(getTrace());
baa96b1d 161 htFile = new File(directory + getSsFileName());
84a9548a 162 createPartialHistory(id, provider, htFile);
8a6ff07f
GB
163 break;
164 case INMEM:
84a9548a 165 createInMemoryHistory(id, provider);
8a6ff07f
GB
166 break;
167 case NULL:
84a9548a 168 createNullHistory(id, provider);
8a6ff07f
GB
169 break;
170 default:
171 break;
172 }
173 } catch (TmfTraceException e) {
174 return false;
175 }
baa96b1d 176 return !mon.isCanceled();
8a6ff07f
GB
177 }
178
179 @Override
180 protected void canceling() {
baa96b1d
BH
181 ITmfEventRequest req = fRequest;
182 if ((req != null) && (!req.isCompleted())) {
183 req.cancel();
184 }
185 }
186
a1529f38
AM
187 @Override
188 public void dispose() {
130e6f4e 189 super.dispose();
a1529f38
AM
190 if (fStateSystem != null) {
191 fStateSystem.dispose();
192 }
a1529f38
AM
193 }
194
baa96b1d
BH
195 // ------------------------------------------------------------------------
196 // History creation methods
197 // ------------------------------------------------------------------------
198
199 /*
200 * Load the history file matching the target trace. If the file already
201 * exists, it will be opened directly. If not, it will be created from
202 * scratch.
203 */
84a9548a 204 private void createFullHistory(String id, ITmfStateProvider provider, File htFile) throws TmfTraceException {
baa96b1d
BH
205
206 /* If the target file already exists, do not rebuild it uselessly */
207 // TODO for now we assume it's complete. Might be a good idea to check
208 // at least if its range matches the trace's range.
209
210 if (htFile.exists()) {
211 /* Load an existing history */
212 final int version = provider.getVersion();
213 try {
84a9548a
AM
214 IStateHistoryBackend backend = new HistoryTreeBackend(htFile, version);
215 fHtBackend = backend;
bcec0116 216 fStateSystem = StateSystemFactory.newStateSystem(id, backend, false);
09ec275e 217 fInitialized.countDown();
baa96b1d
BH
218 return;
219 } catch (IOException e) {
220 /*
221 * There was an error opening the existing file. Perhaps it was
222 * corrupted, perhaps it's an old version? We'll just
223 * fall-through and try to build a new one from scratch instead.
224 */
225 }
226 }
227
228 /* Size of the blocking queue to use when building a state history */
229 final int QUEUE_SIZE = 10000;
230
231 try {
84a9548a 232 IStateHistoryBackend backend = new ThreadedHistoryTreeBackend(htFile,
baa96b1d 233 provider.getStartTime(), provider.getVersion(), QUEUE_SIZE);
84a9548a 234 fHtBackend = backend;
bcec0116 235 fStateSystem = StateSystemFactory.newStateSystem(id, backend);
baa96b1d
BH
236 provider.assignTargetStateSystem(fStateSystem);
237 build(provider);
238 } catch (IOException e) {
239 /*
240 * If it fails here however, it means there was a problem writing to
241 * the disk, so throw a real exception this time.
242 */
243 throw new TmfTraceException(e.toString(), e);
244 }
245 }
246
247 /*
248 * Create a new state system backed with a partial history. A partial
249 * history is similar to a "full" one (which you get with
250 * {@link #newFullHistory}), except that the file on disk is much smaller,
251 * but queries are a bit slower.
252 *
253 * Also note that single-queries are implemented using a full-query
254 * underneath, (which are much slower), so this might not be a good fit for
255 * a use case where you have to do lots of single queries.
256 */
84a9548a 257 private void createPartialHistory(String id, ITmfStateProvider provider, File htPartialFile)
baa96b1d
BH
258 throws TmfTraceException {
259 /*
260 * The order of initializations is very tricky (but very important!)
261 * here. We need to follow this pattern:
262 * (1 is done before the call to this method)
263 *
264 * 1- Instantiate realStateProvider
265 * 2- Instantiate realBackend
266 * 3- Instantiate partialBackend, with prereqs:
267 * 3a- Instantiate partialProvider, via realProvider.getNew()
268 * 3b- Instantiate nullBackend (partialSS's backend)
269 * 3c- Instantiate partialSS
270 * 3d- partialProvider.assignSS(partialSS)
271 * 4- Instantiate realSS
272 * 5- partialSS.assignUpstream(realSS)
273 * 6- realProvider.assignSS(realSS)
274 * 7- Call HistoryBuilder(realProvider, realSS, partialBackend) to build the thing.
275 */
276
277 /* Size of the blocking queue to use when building a state history */
278 final int QUEUE_SIZE = 10000;
279
280 final long granularity = 50000;
281
282 /* 2 */
283 IStateHistoryBackend realBackend = null;
284 try {
285 realBackend = new ThreadedHistoryTreeBackend(htPartialFile,
286 provider.getStartTime(), provider.getVersion(), QUEUE_SIZE);
287 } catch (IOException e) {
288 throw new TmfTraceException(e.toString(), e);
289 }
290
291 /* 3a */
292 ITmfStateProvider partialProvider = provider.getNewInstance();
293
294 /* 3b-3c, constructor automatically uses a NullBackend */
295 PartialStateSystem pss = new PartialStateSystem();
296
297 /* 3d */
298 partialProvider.assignTargetStateSystem(pss);
299
300 /* 3 */
301 IStateHistoryBackend partialBackend =
302 new PartialHistoryBackend(partialProvider, pss, realBackend, granularity);
303
304 /* 4 */
bcec0116
AM
305 @SuppressWarnings("restriction")
306 org.eclipse.linuxtools.internal.statesystem.core.StateSystem realSS =
307 (org.eclipse.linuxtools.internal.statesystem.core.StateSystem) StateSystemFactory.newStateSystem(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;
bcec0116 330 fStateSystem = StateSystemFactory.newStateSystem(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;
bcec0116 343 fStateSystem = StateSystemFactory.newStateSystem(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();
2d208fb7 410 trace = tr;
baa96b1d 411
baa96b1d
BH
412 }
413
414 @Override
41f3b36b 415 public void handleData(final ITmfEvent event) {
baa96b1d 416 super.handleData(event);
41f3b36b 417 if (event.getTrace() == trace) {
baa96b1d 418 sci.processEvent(event);
2d208fb7
GB
419 } else if (trace instanceof TmfExperiment) {
420 /*
421 * If the request is for an experiment, check if the event is
422 * from one of the child trace
423 */
424 for (ITmfTrace childTrace : ((TmfExperiment) trace).getTraces()) {
425 if (childTrace == event.getTrace()) {
426 sci.processEvent(event);
427 }
428 }
baa96b1d
BH
429 }
430 }
431
432 @Override
433 public void handleSuccess() {
434 super.handleSuccess();
a1529f38 435 disposeProvider(false);
baa96b1d
BH
436 }
437
438 @Override
439 public void handleCancel() {
440 super.handleCancel();
a1529f38 441 disposeProvider(true);
baa96b1d
BH
442 }
443
444 @Override
445 public void handleFailure() {
446 super.handleFailure();
a1529f38 447 disposeProvider(true);
baa96b1d 448 }
8a6ff07f
GB
449 }
450
5237a931
AM
451 // ------------------------------------------------------------------------
452 // ITmfAnalysisModuleWithStateSystems
453 // ------------------------------------------------------------------------
454
455 @Override
baa96b1d
BH
456 @Nullable
457 public ITmfStateSystem getStateSystem(String id) {
5237a931
AM
458 if (id.equals(getId())) {
459 return fStateSystem;
460 }
461 return null;
462 }
463
8a6ff07f 464 @Override
5237a931 465 public Iterable<ITmfStateSystem> getStateSystems() {
baa96b1d
BH
466 @SuppressWarnings("null")
467 @NonNull Iterable<ITmfStateSystem> ret = Collections.singleton((ITmfStateSystem) fStateSystem);
468 return ret;
8a6ff07f
GB
469 }
470}
This page took 0.064956 seconds and 5 git commands to generate.