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