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> | |
5 | * | |
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 | |
10 | * | |
11 | *******************************************************************************/ | |
12 | ||
18ab1d18 | 13 | package org.eclipse.linuxtools.tmf.core.statesystem; |
a52fde77 AM |
14 | |
15 | import java.io.IOException; | |
855a1bfb | 16 | import java.util.concurrent.Semaphore; |
a52fde77 | 17 | |
18ab1d18 | 18 | import org.eclipse.linuxtools.internal.tmf.core.statesystem.StateHistorySystem; |
855a1bfb | 19 | import org.eclipse.linuxtools.tmf.core.component.TmfComponent; |
2c2f900e | 20 | import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfEvent; |
855a1bfb | 21 | import org.eclipse.linuxtools.tmf.core.event.ITmfEvent; |
2c2f900e AM |
22 | import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange; |
23 | import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest; | |
24 | import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest; | |
25 | import org.eclipse.linuxtools.tmf.core.request.TmfDataRequest; | |
26 | import org.eclipse.linuxtools.tmf.core.request.TmfEventRequest; | |
855a1bfb AM |
27 | import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentRangeUpdatedSignal; |
28 | import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentSelectedSignal; | |
29 | import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler; | |
30 | import org.eclipse.linuxtools.tmf.core.signal.TmfSignalManager; | |
a52fde77 AM |
31 | |
32 | /** | |
33 | * This is the high-level wrapper around the State History and its input and | |
34 | * storage plugins. Just create the object using the constructor then .run() | |
35 | * | |
36 | * You can use one HistoryBuilder and it will instantiate everything underneath. | |
37 | * If you need more fine-grained control you can still ignore this and | |
38 | * instantiate everything manually. | |
39 | * | |
40 | * @author alexmont | |
41 | * | |
42 | */ | |
855a1bfb AM |
43 | public class HistoryBuilder extends TmfComponent { |
44 | ||
45 | private static final Semaphore hbSem = new Semaphore(1); | |
46 | ||
47 | private ITmfEventRequest<CtfTmfEvent> currentRequest = null; | |
48 | private boolean isRunning = false; | |
a52fde77 AM |
49 | |
50 | private final IStateChangeInput sci; | |
d26f90fd | 51 | private final StateHistorySystem shs; |
a52fde77 AM |
52 | private final IStateHistoryBackend hb; |
53 | ||
a52fde77 AM |
54 | /** |
55 | * Instantiate a new HistoryBuilder helper. | |
56 | * | |
57 | * @param stateChangeInput | |
58 | * The input plugin to use. This is required. | |
59 | * @param backend | |
60 | * The backend storage to use. Use "null" here if you want a | |
61 | * state system with no history. | |
62 | * @throws IOException | |
63 | * Is thrown if anything went wrong (usually with the storage | |
64 | * backend) | |
65 | */ | |
66 | public HistoryBuilder(IStateChangeInput stateChangeInput, | |
67 | IStateHistoryBackend backend) throws IOException { | |
36bf82a2 AM |
68 | if (stateChangeInput == null || backend == null) { |
69 | throw new IllegalArgumentException(); | |
70 | } | |
d26f90fd AM |
71 | sci = stateChangeInput; |
72 | hb = backend; | |
73 | shs = new StateHistorySystem(hb, true); | |
a52fde77 | 74 | |
d26f90fd | 75 | sci.assignTargetStateSystem(shs); |
a52fde77 AM |
76 | } |
77 | ||
d26f90fd AM |
78 | /** |
79 | * Factory-style method to open an existing history, you only have to | |
80 | * provide the already-instantiated IStateHistoryBackend object. | |
81 | * | |
82 | * @param hb | |
83 | * The history-backend object | |
84 | * @return A IStateSystemBuilder reference to the new state system. If you | |
85 | * will only run queries on this history, you should *definitely* | |
86 | * cast it to IStateSystemQuerier. | |
87 | * @throws IOException | |
88 | * If there was something wrong. | |
89 | */ | |
90 | public static IStateSystemBuilder openExistingHistory( | |
91 | IStateHistoryBackend hb) throws IOException { | |
92 | return new StateHistorySystem(hb, false); | |
93 | } | |
94 | ||
a52fde77 | 95 | /** |
d26f90fd AM |
96 | * Return a read/write reference to the state system object that was |
97 | * created. | |
98 | * | |
99 | * @return Reference to the state system, with access to everything. | |
100 | */ | |
101 | public IStateSystemBuilder getStateSystemBuilder() { | |
102 | return shs; | |
103 | } | |
104 | ||
105 | /** | |
106 | * Return a read-only reference to the state system object that was created. | |
a52fde77 | 107 | * |
d26f90fd AM |
108 | * @return Reference to the state system, but only with the query methods |
109 | * available. | |
a52fde77 | 110 | */ |
d26f90fd AM |
111 | public IStateSystemQuerier getStateSystemQuerier() { |
112 | return shs; | |
a52fde77 | 113 | } |
36bf82a2 | 114 | |
855a1bfb AM |
115 | // ------------------------------------------------------------------------ |
116 | // Signal handlers | |
117 | // ------------------------------------------------------------------------ | |
118 | ||
119 | /** | |
120 | * Signal handler to start building the configured state history. | |
121 | * | |
122 | * This could also be called by anyone to trigger the building of the | |
123 | * history without using any TMF signals. Simply pass 'null' as a parameter | |
124 | * then. | |
125 | * | |
126 | * @param signal The signal that triggered the build | |
127 | */ | |
128 | @TmfSignalHandler | |
129 | public void startBuilding(final TmfExperimentRangeUpdatedSignal signal) { | |
130 | /* Start the construction of the history if it's not started yet */ | |
131 | if (!this.isRunning) { | |
132 | hbSem.acquireUninterruptibly(); | |
133 | currentRequest = new StateSystemBuildRequest(this); | |
134 | isRunning = true; | |
135 | sci.getTrace().sendRequest(currentRequest); | |
136 | } | |
137 | } | |
138 | ||
36bf82a2 | 139 | /** |
855a1bfb AM |
140 | * Signal handler to cancel any currently running requests. It will delete |
141 | * any incomplete file that might have been created. | |
142 | * | |
143 | * This could also be called by anyone to cancel the current request without | |
144 | * using any TMF signals. Simply pass 'null' as a parameter then. | |
145 | * | |
146 | * @param signal | |
36bf82a2 | 147 | */ |
855a1bfb AM |
148 | @TmfSignalHandler |
149 | public void cancelCurrentBuild(final TmfExperimentSelectedSignal<? extends ITmfEvent> signal) { | |
150 | /* | |
151 | * We've switched experiments (or re-opened the current one), so stop | |
152 | * whatever request is currently running. | |
153 | */ | |
154 | if (this.isRunning && currentRequest != null) { | |
155 | currentRequest.cancel(); | |
156 | } | |
157 | } | |
158 | ||
36bf82a2 | 159 | |
855a1bfb AM |
160 | // ------------------------------------------------------------------------ |
161 | // Methods reserved for the request object below | |
162 | // ------------------------------------------------------------------------ | |
163 | ||
36bf82a2 AM |
164 | /** Get the input plugin object */ |
165 | IStateChangeInput getInputPlugin() { | |
166 | return sci; | |
167 | } | |
168 | ||
855a1bfb AM |
169 | /** Shutdown this builder object when the request is over */ |
170 | void finish(boolean deleteFile) { | |
171 | sci.dispose(); | |
172 | if (deleteFile) { | |
173 | hb.removeFiles(); | |
174 | } | |
175 | currentRequest = null; | |
176 | isRunning = false; | |
177 | TmfSignalManager.deregister(this); | |
178 | hbSem.release(); | |
36bf82a2 | 179 | } |
2c2f900e AM |
180 | } |
181 | ||
36bf82a2 | 182 | |
2c2f900e AM |
183 | class StateSystemBuildRequest extends TmfEventRequest<CtfTmfEvent> { |
184 | ||
185 | /** The amount of events queried at a time through the requests */ | |
186 | private final static int chunkSize = 50000; | |
187 | ||
36bf82a2 | 188 | private final HistoryBuilder builder; |
2c2f900e AM |
189 | private final IStateChangeInput sci; |
190 | ||
36bf82a2 AM |
191 | StateSystemBuildRequest(HistoryBuilder builder) { |
192 | super((Class<CtfTmfEvent>) builder.getInputPlugin().getExpectedEventType().getClass(), | |
2c2f900e AM |
193 | TmfTimeRange.ETERNITY, TmfDataRequest.ALL_DATA, chunkSize, |
194 | ITmfDataRequest.ExecutionType.BACKGROUND); | |
36bf82a2 AM |
195 | this.builder = builder; |
196 | this.sci = builder.getInputPlugin(); | |
2c2f900e | 197 | } |
a52fde77 | 198 | |
2c2f900e AM |
199 | @Override |
200 | public void handleData(final CtfTmfEvent event) { | |
201 | super.handleData(event); | |
202 | if (event != null) { | |
203 | sci.processEvent(event); | |
204 | } | |
205 | } | |
206 | ||
207 | @Override | |
208 | public void handleSuccess() { | |
855a1bfb AM |
209 | super.handleSuccess(); |
210 | builder.finish(false); | |
2c2f900e AM |
211 | } |
212 | ||
36bf82a2 AM |
213 | @Override |
214 | public void handleCancel() { | |
855a1bfb AM |
215 | super.handleCancel(); |
216 | builder.finish(true); | |
36bf82a2 AM |
217 | } |
218 | ||
2c2f900e | 219 | @Override |
855a1bfb AM |
220 | public void handleFailure() { |
221 | super.handleFailure(); | |
222 | builder.finish(true); | |
2c2f900e | 223 | } |
a52fde77 | 224 | } |