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