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 | ||
83134537 AM |
17 | import org.eclipse.linuxtools.tmf.core.component.TmfComponent; |
18 | import org.eclipse.linuxtools.tmf.core.event.ITmfEvent; | |
2c2f900e AM |
19 | import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange; |
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; |
83134537 AM |
30 | import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; |
31 | import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment; | |
a52fde77 AM |
32 | |
33 | /** | |
34 | * This is the high-level wrapper around the State History and its input and | |
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 AM |
45 | |
46 | private final IStateChangeInput sci; | |
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 AM |
51 | /** |
52 | * Instantiate a new HistoryBuilder helper. | |
83134537 | 53 | * |
a52fde77 AM |
54 | * @param stateChangeInput |
55 | * The input plugin to use. This is required. | |
56 | * @param backend | |
5df842b3 AM |
57 | * The backend storage to use. |
58 | * @param buildManually | |
59 | * Should we build this history in-band or not. True means we | |
60 | * will start the building ourselves and block the caller until | |
a76f1067 AM |
61 | * construction is done. False (out-of-band) means we will start |
62 | * listening for the signal and return immediately. Another | |
5df842b3 | 63 | * signal will be sent when finished. |
a52fde77 AM |
64 | * @throws IOException |
65 | * Is thrown if anything went wrong (usually with the storage | |
66 | * backend) | |
67 | */ | |
68 | public HistoryBuilder(IStateChangeInput stateChangeInput, | |
e45de797 | 69 | IStateHistoryBackend backend, boolean buildManually) |
e34f7caa | 70 | throws IOException { |
36bf82a2 AM |
71 | if (stateChangeInput == null || backend == null) { |
72 | throw new IllegalArgumentException(); | |
73 | } | |
d26f90fd AM |
74 | sci = stateChangeInput; |
75 | hb = backend; | |
8d1346f0 | 76 | ss = new StateSystem(hb, true); |
a52fde77 | 77 | |
8d1346f0 | 78 | sci.assignTargetStateSystem(ss); |
e34f7caa AM |
79 | |
80 | if (buildManually) { | |
81 | TmfSignalManager.deregister(this); | |
82 | this.buildManually(); | |
83 | } else { | |
84 | started = false; | |
85 | /* We'll now wait for the signal to start building */ | |
86 | } | |
a52fde77 AM |
87 | } |
88 | ||
d26f90fd AM |
89 | /** |
90 | * Factory-style method to open an existing history, you only have to | |
91 | * provide the already-instantiated IStateHistoryBackend object. | |
83134537 | 92 | * |
d26f90fd AM |
93 | * @param hb |
94 | * The history-backend object | |
95 | * @return A IStateSystemBuilder reference to the new state system. If you | |
96 | * will only run queries on this history, you should *definitely* | |
97 | * cast it to IStateSystemQuerier. | |
98 | * @throws IOException | |
99 | * If there was something wrong. | |
100 | */ | |
f1f86dfb | 101 | public static ITmfStateSystemBuilder openExistingHistory( |
d26f90fd | 102 | IStateHistoryBackend hb) throws IOException { |
8d1346f0 | 103 | return new StateSystem(hb, false); |
d26f90fd AM |
104 | } |
105 | ||
a52fde77 | 106 | /** |
d26f90fd AM |
107 | * Return a read/write reference to the state system object that was |
108 | * created. | |
83134537 | 109 | * |
d26f90fd AM |
110 | * @return Reference to the state system, with access to everything. |
111 | */ | |
f1f86dfb | 112 | public ITmfStateSystemBuilder getStateSystemBuilder() { |
8d1346f0 | 113 | return ss; |
d26f90fd AM |
114 | } |
115 | ||
116 | /** | |
117 | * Return a read-only reference to the state system object that was created. | |
83134537 | 118 | * |
d26f90fd AM |
119 | * @return Reference to the state system, but only with the query methods |
120 | * available. | |
a52fde77 | 121 | */ |
f1f86dfb | 122 | public ITmfStateSystem getStateSystemQuerier() { |
8d1346f0 | 123 | return ss; |
a52fde77 | 124 | } |
36bf82a2 | 125 | |
e34f7caa AM |
126 | /** |
127 | * Build the state history without waiting for signals or anything | |
128 | */ | |
e34f7caa AM |
129 | private void buildManually() { |
130 | StateSystemBuildRequest request = new StateSystemBuildRequest(this); | |
131 | ||
132 | /* Send the request to the trace here, since there is probably no | |
133 | * experiment. */ | |
134 | sci.getTrace().sendRequest(request); | |
135 | try { | |
136 | request.waitForCompletion(); | |
137 | } catch (InterruptedException e) { | |
138 | e.printStackTrace(); | |
139 | } | |
140 | } | |
141 | ||
83134537 AM |
142 | |
143 | // ------------------------------------------------------------------------ | |
144 | // Signal handlers | |
145 | // ------------------------------------------------------------------------ | |
146 | ||
147 | /** | |
faa38350 | 148 | * Listen to the "trace range updated" signal to start the state history |
83134537 AM |
149 | * construction. |
150 | * | |
151 | * @param signal | |
faa38350 | 152 | * The "trace range updated" signal. Listening to this |
5df842b3 AM |
153 | * signal will coalesce this request with the one from the |
154 | * indexer and histogram. | |
83134537 | 155 | */ |
83134537 | 156 | @TmfSignalHandler |
faa38350 PT |
157 | public void traceRangeUpdated(final TmfTraceRangeUpdatedSignal signal) { |
158 | ITmfTrace trace = signal.getTrace(); | |
159 | if (signal.getTrace() instanceof TmfExperiment) { | |
160 | TmfExperiment experiment = (TmfExperiment) signal.getTrace(); | |
161 | for (ITmfTrace expTrace : experiment.getTraces()) { | |
162 | if (expTrace == sci.getTrace()) { | |
163 | trace = expTrace; | |
164 | break; | |
165 | } | |
166 | } | |
167 | } | |
168 | if (trace != sci.getTrace()) { | |
169 | return; | |
170 | } | |
171 | /* the signal is for this trace or for an experiment containing this trace */ | |
83134537 AM |
172 | |
173 | if (!started) { | |
174 | started = true; | |
faa38350 PT |
175 | StateSystemBuildRequest request = new StateSystemBuildRequest(this); |
176 | trace = signal.getTrace(); | |
177 | trace.sendRequest(request); | |
855a1bfb AM |
178 | } |
179 | } | |
180 | ||
faa38350 PT |
181 | /** |
182 | * Listen to the "trace closed" signal to clean up if necessary. | |
183 | * | |
184 | * @param signal | |
185 | * The "trace closed" signal. | |
186 | */ | |
187 | @TmfSignalHandler | |
188 | public void traceClosed(TmfTraceClosedSignal signal) { | |
189 | ITmfTrace trace = signal.getTrace(); | |
190 | if (signal.getTrace() instanceof TmfExperiment) { | |
191 | TmfExperiment experiment = (TmfExperiment) signal.getTrace(); | |
192 | for (ITmfTrace expTrace : experiment.getTraces()) { | |
193 | if (expTrace == sci.getTrace()) { | |
194 | trace = expTrace; | |
195 | break; | |
196 | } | |
197 | } | |
198 | } | |
199 | if (trace != sci.getTrace()) { | |
200 | return; | |
201 | } | |
202 | /* the signal is for this trace or for an experiment containing this trace */ | |
203 | ||
204 | if (!started) { | |
205 | close(true); | |
206 | } | |
207 | } | |
83134537 | 208 | |
855a1bfb AM |
209 | // ------------------------------------------------------------------------ |
210 | // Methods reserved for the request object below | |
211 | // ------------------------------------------------------------------------ | |
212 | ||
36bf82a2 AM |
213 | /** Get the input plugin object */ |
214 | IStateChangeInput getInputPlugin() { | |
215 | return sci; | |
216 | } | |
83134537 AM |
217 | |
218 | void close(boolean deleteFiles) { | |
219 | sci.dispose(); | |
220 | if (deleteFiles) { | |
221 | hb.removeFiles(); | |
222 | } | |
faa38350 | 223 | dispose(); |
83134537 | 224 | } |
2c2f900e AM |
225 | } |
226 | ||
6256d8ad | 227 | class StateSystemBuildRequest extends TmfEventRequest { |
2c2f900e AM |
228 | |
229 | /** The amount of events queried at a time through the requests */ | |
230 | private final static int chunkSize = 50000; | |
231 | ||
83134537 | 232 | private final HistoryBuilder builder; |
2c2f900e | 233 | private final IStateChangeInput sci; |
6256d8ad | 234 | private final ITmfTrace trace; |
2c2f900e | 235 | |
36bf82a2 | 236 | StateSystemBuildRequest(HistoryBuilder builder) { |
79044a66 | 237 | super(builder.getInputPlugin().getExpectedEventType(), |
83134537 AM |
238 | TmfTimeRange.ETERNITY, |
239 | TmfDataRequest.ALL_DATA, | |
240 | chunkSize, | |
2c2f900e | 241 | ITmfDataRequest.ExecutionType.BACKGROUND); |
83134537 | 242 | this.builder = builder; |
36bf82a2 | 243 | this.sci = builder.getInputPlugin(); |
83134537 | 244 | this.trace = sci.getTrace(); |
2c2f900e | 245 | } |
a52fde77 | 246 | |
2c2f900e | 247 | @Override |
83134537 | 248 | public void handleData(final ITmfEvent event) { |
2c2f900e AM |
249 | super.handleData(event); |
250 | if (event != null) { | |
83134537 AM |
251 | if (event.getTrace() == trace) { |
252 | sci.processEvent(event); | |
253 | } | |
2c2f900e AM |
254 | } |
255 | } | |
256 | ||
257 | @Override | |
258 | public void handleSuccess() { | |
855a1bfb | 259 | super.handleSuccess(); |
83134537 | 260 | builder.close(false); |
2c2f900e AM |
261 | } |
262 | ||
36bf82a2 AM |
263 | @Override |
264 | public void handleCancel() { | |
855a1bfb | 265 | super.handleCancel(); |
83134537 | 266 | builder.close(true); |
36bf82a2 AM |
267 | } |
268 | ||
2c2f900e | 269 | @Override |
855a1bfb AM |
270 | public void handleFailure() { |
271 | super.handleFailure(); | |
83134537 | 272 | builder.close(true); |
2c2f900e | 273 | } |
5419a136 | 274 | } |