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