Commit | Line | Data |
---|---|---|
a52fde77 AM |
1 | /******************************************************************************* |
2 | * Copyright (c) 2012 Ericsson | |
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; | |
2c2f900e | 20 | import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest; |
2c2f900e AM |
21 | import org.eclipse.linuxtools.tmf.core.request.TmfDataRequest; |
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; | |
2ab9afbc | 27 | import org.eclipse.linuxtools.tmf.core.statesystem.IStateChangeInput; |
f1f86dfb | 28 | import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem; |
faa38350 | 29 | import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystemBuilder; |
3bd46eef | 30 | import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange; |
83134537 AM |
31 | import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; |
32 | import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment; | |
a52fde77 AM |
33 | |
34 | /** | |
35 | * This is the high-level wrapper around the State History and its input and | |
36 | * storage plugins. Just create the object using the constructor then .run() | |
83134537 | 37 | * |
a52fde77 AM |
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. | |
83134537 | 41 | * |
a52fde77 | 42 | * @author alexmont |
83134537 | 43 | * |
a52fde77 | 44 | */ |
83134537 | 45 | public class HistoryBuilder extends TmfComponent { |
a52fde77 AM |
46 | |
47 | private final IStateChangeInput sci; | |
8d1346f0 | 48 | private final StateSystem ss; |
a52fde77 | 49 | private final IStateHistoryBackend hb; |
83134537 | 50 | private boolean started = true; /* Don't handle signals until we're ready */ |
a52fde77 | 51 | |
a52fde77 | 52 | /** |
7e634be6 AM |
53 | * Instantiate a new HistoryBuilder helper. The input -> ss -> backend |
54 | * relationships should have been set up already. | |
83134537 | 55 | * |
a52fde77 | 56 | * @param stateChangeInput |
7e634be6 AM |
57 | * The input plugin to use |
58 | * @param ss | |
59 | * The state system object that will receive the state changes | |
60 | * from the input | |
a52fde77 | 61 | * @param backend |
7e634be6 AM |
62 | * The back-end storage to use, which will receive the intervals |
63 | * from the ss | |
5df842b3 AM |
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 | |
a76f1067 | 67 | * construction is done. False (out-of-band) means we will start |
7e634be6 | 68 | * listening for the signal and return immediately. |
a52fde77 | 69 | */ |
7e634be6 | 70 | public HistoryBuilder(IStateChangeInput stateChangeInput, StateSystem ss, |
f9a76cac | 71 | IStateHistoryBackend backend, boolean buildManually) { |
7e634be6 | 72 | if (stateChangeInput == null || backend == null || ss == null) { |
36bf82a2 AM |
73 | throw new IllegalArgumentException(); |
74 | } | |
7e634be6 AM |
75 | if (stateChangeInput.getAssignedStateSystem() != ss) { |
76 | /* Logic check to make sure the input is setup properly */ | |
77 | throw new RuntimeException(); | |
78 | } | |
79 | ||
d26f90fd AM |
80 | sci = stateChangeInput; |
81 | hb = backend; | |
7e634be6 | 82 | this.ss = ss; |
e34f7caa AM |
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 | } | |
a52fde77 AM |
91 | } |
92 | ||
d26f90fd AM |
93 | /** |
94 | * Factory-style method to open an existing history, you only have to | |
95 | * provide the already-instantiated IStateHistoryBackend object. | |
83134537 | 96 | * |
d26f90fd AM |
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 | */ | |
f1f86dfb | 105 | public static ITmfStateSystemBuilder openExistingHistory( |
d26f90fd | 106 | IStateHistoryBackend hb) throws IOException { |
8d1346f0 | 107 | return new StateSystem(hb, false); |
d26f90fd AM |
108 | } |
109 | ||
a52fde77 | 110 | /** |
d26f90fd AM |
111 | * Return a read/write reference to the state system object that was |
112 | * created. | |
83134537 | 113 | * |
d26f90fd AM |
114 | * @return Reference to the state system, with access to everything. |
115 | */ | |
f1f86dfb | 116 | public ITmfStateSystemBuilder getStateSystemBuilder() { |
8d1346f0 | 117 | return ss; |
d26f90fd AM |
118 | } |
119 | ||
120 | /** | |
121 | * Return a read-only reference to the state system object that was created. | |
83134537 | 122 | * |
d26f90fd AM |
123 | * @return Reference to the state system, but only with the query methods |
124 | * available. | |
a52fde77 | 125 | */ |
f1f86dfb | 126 | public ITmfStateSystem getStateSystemQuerier() { |
8d1346f0 | 127 | return ss; |
a52fde77 | 128 | } |
36bf82a2 | 129 | |
e34f7caa AM |
130 | /** |
131 | * Build the state history without waiting for signals or anything | |
132 | */ | |
e34f7caa AM |
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 | sci.getTrace().sendRequest(request); | |
139 | try { | |
140 | request.waitForCompletion(); | |
141 | } catch (InterruptedException e) { | |
142 | e.printStackTrace(); | |
143 | } | |
144 | } | |
145 | ||
83134537 AM |
146 | |
147 | // ------------------------------------------------------------------------ | |
148 | // Signal handlers | |
149 | // ------------------------------------------------------------------------ | |
150 | ||
151 | /** | |
faa38350 | 152 | * Listen to the "trace range updated" signal to start the state history |
83134537 AM |
153 | * construction. |
154 | * | |
155 | * @param signal | |
faa38350 | 156 | * The "trace range updated" signal. Listening to this |
5df842b3 AM |
157 | * signal will coalesce this request with the one from the |
158 | * indexer and histogram. | |
83134537 | 159 | */ |
83134537 | 160 | @TmfSignalHandler |
faa38350 PT |
161 | public void traceRangeUpdated(final TmfTraceRangeUpdatedSignal signal) { |
162 | ITmfTrace trace = signal.getTrace(); | |
163 | if (signal.getTrace() instanceof TmfExperiment) { | |
164 | TmfExperiment experiment = (TmfExperiment) signal.getTrace(); | |
165 | for (ITmfTrace expTrace : experiment.getTraces()) { | |
166 | if (expTrace == sci.getTrace()) { | |
167 | trace = expTrace; | |
168 | break; | |
169 | } | |
170 | } | |
171 | } | |
172 | if (trace != sci.getTrace()) { | |
173 | return; | |
174 | } | |
175 | /* the signal is for this trace or for an experiment containing this trace */ | |
83134537 AM |
176 | |
177 | if (!started) { | |
178 | started = true; | |
faa38350 PT |
179 | StateSystemBuildRequest request = new StateSystemBuildRequest(this); |
180 | trace = signal.getTrace(); | |
181 | trace.sendRequest(request); | |
855a1bfb AM |
182 | } |
183 | } | |
184 | ||
faa38350 PT |
185 | /** |
186 | * Listen to the "trace closed" signal to clean up if necessary. | |
187 | * | |
188 | * @param signal | |
189 | * The "trace closed" signal. | |
190 | */ | |
191 | @TmfSignalHandler | |
192 | public void traceClosed(TmfTraceClosedSignal signal) { | |
193 | ITmfTrace trace = signal.getTrace(); | |
194 | if (signal.getTrace() instanceof TmfExperiment) { | |
195 | TmfExperiment experiment = (TmfExperiment) signal.getTrace(); | |
196 | for (ITmfTrace expTrace : experiment.getTraces()) { | |
197 | if (expTrace == sci.getTrace()) { | |
198 | trace = expTrace; | |
199 | break; | |
200 | } | |
201 | } | |
202 | } | |
203 | if (trace != sci.getTrace()) { | |
204 | return; | |
205 | } | |
206 | /* the signal is for this trace or for an experiment containing this trace */ | |
207 | ||
208 | if (!started) { | |
209 | close(true); | |
210 | } | |
211 | } | |
83134537 | 212 | |
855a1bfb AM |
213 | // ------------------------------------------------------------------------ |
214 | // Methods reserved for the request object below | |
215 | // ------------------------------------------------------------------------ | |
216 | ||
36bf82a2 AM |
217 | /** Get the input plugin object */ |
218 | IStateChangeInput getInputPlugin() { | |
219 | return sci; | |
220 | } | |
83134537 AM |
221 | |
222 | void close(boolean deleteFiles) { | |
223 | sci.dispose(); | |
224 | if (deleteFiles) { | |
225 | hb.removeFiles(); | |
226 | } | |
faa38350 | 227 | dispose(); |
83134537 | 228 | } |
2c2f900e AM |
229 | } |
230 | ||
6256d8ad | 231 | class StateSystemBuildRequest extends TmfEventRequest { |
2c2f900e AM |
232 | |
233 | /** The amount of events queried at a time through the requests */ | |
234 | private final static int chunkSize = 50000; | |
235 | ||
83134537 | 236 | private final HistoryBuilder builder; |
2c2f900e | 237 | private final IStateChangeInput sci; |
6256d8ad | 238 | private final ITmfTrace trace; |
2c2f900e | 239 | |
36bf82a2 | 240 | StateSystemBuildRequest(HistoryBuilder builder) { |
79044a66 | 241 | super(builder.getInputPlugin().getExpectedEventType(), |
83134537 AM |
242 | TmfTimeRange.ETERNITY, |
243 | TmfDataRequest.ALL_DATA, | |
244 | chunkSize, | |
2c2f900e | 245 | ITmfDataRequest.ExecutionType.BACKGROUND); |
83134537 | 246 | this.builder = builder; |
36bf82a2 | 247 | this.sci = builder.getInputPlugin(); |
83134537 | 248 | this.trace = sci.getTrace(); |
2c2f900e | 249 | } |
a52fde77 | 250 | |
2c2f900e | 251 | @Override |
83134537 | 252 | public void handleData(final ITmfEvent event) { |
2c2f900e AM |
253 | super.handleData(event); |
254 | if (event != null) { | |
83134537 AM |
255 | if (event.getTrace() == trace) { |
256 | sci.processEvent(event); | |
257 | } | |
2c2f900e AM |
258 | } |
259 | } | |
260 | ||
261 | @Override | |
262 | public void handleSuccess() { | |
855a1bfb | 263 | super.handleSuccess(); |
83134537 | 264 | builder.close(false); |
2c2f900e AM |
265 | } |
266 | ||
36bf82a2 AM |
267 | @Override |
268 | public void handleCancel() { | |
855a1bfb | 269 | super.handleCancel(); |
83134537 | 270 | builder.close(true); |
36bf82a2 AM |
271 | } |
272 | ||
2c2f900e | 273 | @Override |
855a1bfb AM |
274 | public void handleFailure() { |
275 | super.handleFailure(); | |
83134537 | 276 | builder.close(true); |
2c2f900e | 277 | } |
5419a136 | 278 | } |