tmf: Move statevalue unboxing method implementations to the base classes
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / internal / tmf / core / statesystem / HistoryBuilder.java
1 /*******************************************************************************
2 * Copyright (c) 2012, 2013 Ericsson
3 * Copyright (c) 2010, 2011 École Polytechnique de Montréal
4 * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
5 *
6 * All rights reserved. This program and the accompanying materials are
7 * made available under the terms of the Eclipse Public License v1.0 which
8 * accompanies this distribution, and is available at
9 * http://www.eclipse.org/legal/epl-v10.html
10 *
11 *******************************************************************************/
12
13 package org.eclipse.linuxtools.internal.tmf.core.statesystem;
14
15 import java.io.IOException;
16
17 import org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.IStateHistoryBackend;
18 import org.eclipse.linuxtools.tmf.core.component.TmfComponent;
19 import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
20 import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest;
21 import org.eclipse.linuxtools.tmf.core.request.TmfDataRequest;
22 import org.eclipse.linuxtools.tmf.core.request.TmfEventRequest;
23 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
24 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalManager;
25 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceClosedSignal;
26 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceRangeUpdatedSignal;
27 import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateProvider;
28 import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem;
29 import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystemBuilder;
30 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange;
31 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
32 import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;
33
34 /**
35 * This is the high-level wrapper around the State History and its provider and
36 * storage plugins. Just create the object using the constructor then .run()
37 *
38 * You can use one HistoryBuilder and it will instantiate everything underneath.
39 * If you need more fine-grained control you can still ignore this and
40 * instantiate everything manually.
41 *
42 * @author alexmont
43 *
44 */
45 public class HistoryBuilder extends TmfComponent {
46
47 private final ITmfStateProvider sp;
48 private final StateSystem ss;
49 private final IStateHistoryBackend hb;
50 private boolean started = true; /* Don't handle signals until we're ready */
51
52 /**
53 * Instantiate a new HistoryBuilder helper. The provider -> ss -> backend
54 * relationships should have been set up already.
55 *
56 * @param stateProvider
57 * The state provider plugin to use
58 * @param ss
59 * The state system object that will receive the state changes
60 * from the provider
61 * @param backend
62 * The back-end storage to use, which will receive the intervals
63 * from the ss
64 * @param buildManually
65 * Should we build this history in-band or not. True means we
66 * will start the building ourselves and block the caller until
67 * construction is done. False (out-of-band) means we will start
68 * listening for the signal and return immediately.
69 */
70 public HistoryBuilder(ITmfStateProvider stateProvider, StateSystem ss,
71 IStateHistoryBackend backend, boolean buildManually) {
72 if (stateProvider == null || backend == null || ss == null) {
73 throw new IllegalArgumentException();
74 }
75 if (stateProvider.getAssignedStateSystem() != ss) {
76 /* Logic check to make sure the provider is setup properly */
77 throw new IllegalArgumentException();
78 }
79
80 sp = stateProvider;
81 hb = backend;
82 this.ss = ss;
83
84 if (buildManually) {
85 TmfSignalManager.deregister(this);
86 this.buildManually();
87 } else {
88 started = false;
89 /* We'll now wait for the signal to start building */
90 }
91 }
92
93 /**
94 * Factory-style method to open an existing history, you only have to
95 * provide the already-instantiated IStateHistoryBackend object.
96 *
97 * @param hb
98 * The history-backend object
99 * @return A IStateSystemBuilder reference to the new state system. If you
100 * will only run queries on this history, you should *definitely*
101 * cast it to IStateSystemQuerier.
102 * @throws IOException
103 * If there was something wrong.
104 */
105 public static ITmfStateSystemBuilder openExistingHistory(
106 IStateHistoryBackend hb) throws IOException {
107 return new StateSystem(hb, false);
108 }
109
110 /**
111 * Return a read/write reference to the state system object that was
112 * created.
113 *
114 * @return Reference to the state system, with access to everything.
115 */
116 public ITmfStateSystemBuilder getStateSystemBuilder() {
117 return ss;
118 }
119
120 /**
121 * Return a read-only reference to the state system object that was created.
122 *
123 * @return Reference to the state system, but only with the query methods
124 * available.
125 */
126 public ITmfStateSystem getStateSystemQuerier() {
127 return ss;
128 }
129
130 /**
131 * Build the state history without waiting for signals or anything
132 */
133 private void buildManually() {
134 StateSystemBuildRequest request = new StateSystemBuildRequest(this);
135
136 /* Send the request to the trace here, since there is probably no
137 * experiment. */
138 sp.getTrace().sendRequest(request);
139 try {
140 request.waitForCompletion();
141 } catch (InterruptedException e) {
142 e.printStackTrace();
143 }
144 }
145
146
147 // ------------------------------------------------------------------------
148 // Signal handlers
149 // ------------------------------------------------------------------------
150
151 /**
152 * Listen to the "trace range updated" signal to start the state history
153 * construction.
154 *
155 * @param signal
156 * The "trace range updated" signal. Listening to this
157 * signal will coalesce this request with the one from the
158 * indexer and histogram.
159 */
160 @TmfSignalHandler
161 public void traceRangeUpdated(final TmfTraceRangeUpdatedSignal signal) {
162 ITmfTrace sender = signal.getTrace();
163
164 if (!signalIsForUs(sender)) {
165 return;
166 }
167
168 if (!started) {
169 started = true;
170 StateSystemBuildRequest request = new StateSystemBuildRequest(this);
171 sender.sendRequest(request);
172 }
173 }
174
175 /**
176 * Listen to the "trace closed" signal to clean up if necessary.
177 *
178 * @param signal
179 * The "trace closed" signal.
180 */
181 @TmfSignalHandler
182 public void traceClosed(TmfTraceClosedSignal signal) {
183 ITmfTrace sender = signal.getTrace();
184
185 if (signalIsForUs(sender) && !started) {
186 close(true);
187 }
188 }
189
190 /**
191 * Check if this signal is for this trace, or for an experiment containing
192 * this trace.
193 */
194 private boolean signalIsForUs(ITmfTrace sender) {
195 if (sender instanceof TmfExperiment) {
196 /* Yeah doing a lazy instanceof check here, but it's a special case! */
197 TmfExperiment exp = (TmfExperiment) sender;
198 for (ITmfTrace childTrace : exp.getTraces()) {
199 if (childTrace == sp.getTrace()) {
200 return true;
201 }
202 }
203 } else if (sender == sp.getTrace()) {
204 return true;
205 }
206 return false;
207 }
208
209 // ------------------------------------------------------------------------
210 // Methods reserved for the request object below
211 // ------------------------------------------------------------------------
212
213 /** Get the state provider object */
214 ITmfStateProvider getStateProvider() {
215 return sp;
216 }
217
218 void close(boolean deleteFiles) {
219 sp.dispose();
220 if (deleteFiles) {
221 hb.removeFiles();
222 }
223 dispose();
224 }
225 }
226
227 class StateSystemBuildRequest extends TmfEventRequest {
228
229 /** The amount of events queried at a time through the requests */
230 private static final int CHUNK_SIZE = 50000;
231
232 private final HistoryBuilder builder;
233 private final ITmfStateProvider sci;
234 private final ITmfTrace trace;
235
236 StateSystemBuildRequest(HistoryBuilder builder) {
237 super(builder.getStateProvider().getExpectedEventType(),
238 TmfTimeRange.ETERNITY,
239 TmfDataRequest.ALL_DATA,
240 CHUNK_SIZE,
241 ITmfDataRequest.ExecutionType.BACKGROUND);
242 this.builder = builder;
243 this.sci = builder.getStateProvider();
244 this.trace = sci.getTrace();
245 }
246
247 @Override
248 public void handleData(final ITmfEvent event) {
249 super.handleData(event);
250 if (event != null && event.getTrace() == trace) {
251 sci.processEvent(event);
252 }
253 }
254
255 @Override
256 public void handleSuccess() {
257 super.handleSuccess();
258 builder.close(false);
259 }
260
261 @Override
262 public void handleCancel() {
263 super.handleCancel();
264 builder.close(true);
265 }
266
267 @Override
268 public void handleFailure() {
269 super.handleFailure();
270 builder.close(true);
271 }
272 }
This page took 0.047928 seconds and 5 git commands to generate.