Commit | Line | Data |
---|---|---|
6e71ce46 | 1 | /******************************************************************************* |
61759503 | 2 | * Copyright (c) 2012, 2013 Ericsson |
6e71ce46 AM |
3 | * Copyright (c) 2010, 2011 École Polytechnique de Montréal |
4 | * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com> | |
83134537 | 5 | * |
6e71ce46 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 | * |
6e71ce46 AM |
11 | *******************************************************************************/ |
12 | ||
13 | package org.eclipse.linuxtools.tmf.core.statesystem; | |
14 | ||
15 | import java.io.File; | |
16 | import java.io.IOException; | |
17 | ||
84a9548a | 18 | import org.eclipse.jdt.annotation.NonNull; |
2ab9afbc | 19 | import org.eclipse.linuxtools.internal.tmf.core.statesystem.HistoryBuilder; |
7e634be6 | 20 | import org.eclipse.linuxtools.internal.tmf.core.statesystem.StateSystem; |
f9a76cac AM |
21 | import org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.IStateHistoryBackend; |
22 | import org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.InMemoryBackend; | |
23 | import org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.NullBackend; | |
24 | import org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.historytree.HistoryTreeBackend; | |
25 | import org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.historytree.ThreadedHistoryTreeBackend; | |
1b9d3765 AM |
26 | import org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.partial.PartialHistoryBackend; |
27 | import org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.partial.PartialStateSystem; | |
6e71ce46 AM |
28 | import org.eclipse.linuxtools.tmf.core.component.TmfComponent; |
29 | import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException; | |
6e71ce46 AM |
30 | |
31 | /** | |
3f436e7c AM |
32 | * This class handles loading or creating state history files for use in TMF's |
33 | * generic state system. | |
83134537 | 34 | * |
2cb26548 | 35 | * @author Alexandre Montplaisir |
3f436e7c | 36 | * @since 2.0 |
cf564892 AM |
37 | * |
38 | * @deprecated Building state systems should now be done via | |
39 | * {@link TmfStateSystemAnalysisModule} | |
6e71ce46 | 40 | */ |
cf564892 | 41 | @Deprecated |
3f436e7c AM |
42 | public final class TmfStateSystemFactory extends TmfComponent { |
43 | ||
44 | /** "static" class */ | |
45 | private TmfStateSystemFactory() {} | |
6e71ce46 | 46 | |
84a9548a AM |
47 | @NonNull private static final String SSID = "legacy-state-system"; //$NON-NLS-1$ |
48 | ||
6e71ce46 | 49 | /** Size of the blocking queue to use when building a state history */ |
cb42195c | 50 | private static final int QUEUE_SIZE = 10000; |
6e71ce46 AM |
51 | |
52 | /** | |
53 | * Load the history file matching the target trace. If the file already | |
54 | * exists, it will be opened directly. If not, it will be created from | |
55 | * scratch. In the case the history has to be built, it's possible to block | |
56 | * the calling thread until construction is complete. | |
83134537 | 57 | * |
6e71ce46 AM |
58 | * @param htFile |
59 | * The target name of the history file we want to use. If it | |
60 | * exists it will be opened. If it doesn't, a new file will be | |
61 | * created with this name/path. | |
0fe46f2a AM |
62 | * @param stateProvider |
63 | * The {@link ITmfStateProvider} to use for building the history | |
64 | * file. It may be required even if we are opening an | |
65 | * already-existing history (ie, for partial histories). | |
e34f7caa AM |
66 | * @param buildManually |
67 | * If false, the construction will wait for a signal before | |
68 | * starting. If true, it will build everything right now and | |
69 | * block the caller. It has no effect if the file already exists. | |
6e71ce46 AM |
70 | * @return A IStateSystemQuerier handler to the state system, with which you |
71 | * can then run queries on the history. | |
72 | * @throws TmfTraceException | |
5df842b3 AM |
73 | * If there was a problem reading or writing one of the files. |
74 | * See the contents of this exception for more info. | |
f1f86dfb | 75 | * @since 2.0 |
6e71ce46 | 76 | */ |
3f436e7c | 77 | public static ITmfStateSystem newFullHistory(File htFile, |
0fe46f2a | 78 | ITmfStateProvider stateProvider, boolean buildManually) |
51e216bd | 79 | throws TmfTraceException { |
6e71ce46 | 80 | IStateHistoryBackend htBackend; |
51e216bd | 81 | |
6e71ce46 AM |
82 | /* If the target file already exists, do not rebuild it uselessly */ |
83 | // TODO for now we assume it's complete. Might be a good idea to check | |
84 | // at least if its range matches the trace's range. | |
85 | if (htFile.exists()) { | |
86 | /* Load an existing history */ | |
0fe46f2a AM |
87 | final int version = (stateProvider == null) ? |
88 | ITmfStateProvider.IGNORE_PROVIDER_VERSION : | |
89 | stateProvider.getVersion(); | |
6e71ce46 | 90 | try { |
a96cc6be | 91 | htBackend = new HistoryTreeBackend(htFile, version); |
cb42195c | 92 | return HistoryBuilder.openExistingHistory(htBackend); |
6e71ce46 AM |
93 | } catch (IOException e) { |
94 | /* | |
95 | * There was an error opening the existing file. Perhaps it was | |
96 | * corrupted, perhaps it's an old version? We'll just | |
97 | * fall-through and try to build a new one from scratch instead. | |
98 | */ | |
99 | } | |
100 | } | |
101 | ||
102 | /* Create a new state history from scratch */ | |
103 | HistoryBuilder builder; | |
51e216bd | 104 | |
0fe46f2a | 105 | if (stateProvider == null) { |
6e71ce46 AM |
106 | return null; |
107 | } | |
108 | try { | |
a96cc6be | 109 | htBackend = new ThreadedHistoryTreeBackend(htFile, |
0fe46f2a | 110 | stateProvider.getStartTime(), stateProvider.getVersion(), QUEUE_SIZE); |
84a9548a | 111 | StateSystem ss = new StateSystem(SSID, htBackend); |
0fe46f2a AM |
112 | stateProvider.assignTargetStateSystem(ss); |
113 | builder = new HistoryBuilder(stateProvider, ss, htBackend, buildManually); | |
6e71ce46 | 114 | } catch (IOException e) { |
51e216bd AM |
115 | /* |
116 | * If it fails here however, it means there was a problem writing to | |
117 | * the disk, so throw a real exception this time. | |
6e71ce46 AM |
118 | */ |
119 | throw new TmfTraceException(e.toString(), e); | |
120 | } | |
121 | return builder.getStateSystemQuerier(); | |
122 | } | |
f9a76cac AM |
123 | |
124 | /** | |
125 | * Create a new state system using a null history back-end. This means that | |
126 | * no history intervals will be saved anywhere, and as such only | |
127 | * {@link ITmfStateSystem#queryOngoingState} will be available. | |
128 | * | |
129 | * This has to be built "manually" (which means you should call | |
0fe46f2a | 130 | * stateProvider.processEvent() to update the ongoing state of the state system). |
f9a76cac | 131 | * |
0fe46f2a AM |
132 | * @param stateProvider |
133 | * The state provider plugin to build the history | |
f9a76cac AM |
134 | * @return Reference to the history-less state system that got built |
135 | * @since 2.0 | |
136 | */ | |
0fe46f2a | 137 | public static ITmfStateSystem newNullHistory(ITmfStateProvider stateProvider) { |
f9a76cac | 138 | IStateHistoryBackend backend = new NullBackend(); |
84a9548a | 139 | StateSystem ss = new StateSystem(SSID, backend); |
0fe46f2a | 140 | stateProvider.assignTargetStateSystem(ss); |
7e634be6 | 141 | |
0fe46f2a | 142 | HistoryBuilder builder = new HistoryBuilder(stateProvider, ss, backend, true); |
7e634be6 | 143 | return builder.getStateSystemQuerier(); |
f9a76cac AM |
144 | } |
145 | ||
146 | /** | |
147 | * Create a new state system using in-memory interval storage. This should | |
148 | * only be done for very small state system, and will be naturally limited | |
149 | * to 2^31 intervals. | |
150 | * | |
151 | * This will block the caller while the construction is ongoing. | |
152 | * | |
0fe46f2a AM |
153 | * @param stateProvider |
154 | * The sstateProvider to use | |
f9a76cac AM |
155 | * @param buildManually |
156 | * Set to true to block the caller and build without using TMF | |
157 | * signals (for test programs most of the time). Use false if you | |
158 | * are using the TMF facilities (experiments, etc.) | |
159 | * @return Reference to the state system that just got built | |
160 | * @since 2.0 | |
161 | */ | |
0fe46f2a | 162 | public static ITmfStateSystem newInMemHistory(ITmfStateProvider stateProvider, |
f9a76cac | 163 | boolean buildManually) { |
0fe46f2a | 164 | IStateHistoryBackend backend = new InMemoryBackend(stateProvider.getStartTime()); |
84a9548a | 165 | StateSystem ss = new StateSystem(SSID, backend); |
0fe46f2a | 166 | stateProvider.assignTargetStateSystem(ss); |
7e634be6 | 167 | |
0fe46f2a | 168 | HistoryBuilder builder = new HistoryBuilder(stateProvider, ss, backend, buildManually); |
f9a76cac AM |
169 | return builder.getStateSystemQuerier(); |
170 | } | |
1b9d3765 AM |
171 | |
172 | /** | |
173 | * Create a new state system backed with a partial history. A partial | |
174 | * history is similar to a "full" one (which you get with | |
3f436e7c | 175 | * {@link #newFullHistory}), except that the file on disk is much smaller, |
1b9d3765 AM |
176 | * but queries are a bit slower. |
177 | * | |
178 | * Also note that single-queries are implemented using a full-query | |
179 | * underneath, (which are much slower), so this might not be a good fit for | |
180 | * a use case where you have to do lots of single queries. | |
181 | * | |
182 | * @param htFile | |
183 | * The target file of the history. Since they are usually quick | |
184 | * to build, it will overwrite any existing file, without trying | |
185 | * to re-open it. | |
0fe46f2a AM |
186 | * @param realStateProvider |
187 | * The state provider to use to build this history. | |
1b9d3765 AM |
188 | * @param buildManually |
189 | * Indicates if you want to build the state system in-band | |
190 | * ('true', for unit tests for example), or to not block the | |
191 | * caller and start the build once the RangeUpdated signal. | |
192 | * @return Reference to the newly constructed state system | |
193 | * @throws TmfTraceException | |
194 | * If the history file could not be created | |
195 | * @since 2.0 | |
196 | */ | |
197 | public static ITmfStateSystem newPartialHistory(File htFile, | |
0fe46f2a AM |
198 | ITmfStateProvider realStateProvider, boolean buildManually) |
199 | throws TmfTraceException { | |
1b9d3765 AM |
200 | /* |
201 | * The order of initializations is very tricky (but very important!) | |
202 | * here. We need to follow this pattern: | |
203 | * (1 is done before the call to this method) | |
204 | * | |
0fe46f2a | 205 | * 1- Instantiate realStateProvider |
1b9d3765 AM |
206 | * 2- Instantiate realBackend |
207 | * 3- Instantiate partialBackend, whith prereqs: | |
0fe46f2a | 208 | * 3a- Instantiate partialProvider, via realProvider.getNew() |
1b9d3765 AM |
209 | * 3b- Instantiate nullBackend (partialSS's backend) |
210 | * 3c- Instantiate partialSS | |
0fe46f2a | 211 | * 3d- partialProvider.assignSS(partialSS) |
1b9d3765 AM |
212 | * 4- Instantiate realSS |
213 | * 5- partialSS.assignUpstream(realSS) | |
0fe46f2a AM |
214 | * 6- realProvider.assignSS(realSS) |
215 | * 7- Call HistoryBuilder(realProvider, realSS, partialBackend) to build the thing. | |
1b9d3765 AM |
216 | */ |
217 | ||
218 | final long granularity = 50000; | |
219 | ||
220 | /* 2 */ | |
221 | IStateHistoryBackend realBackend = null; | |
222 | try { | |
223 | realBackend = new ThreadedHistoryTreeBackend(htFile, | |
0fe46f2a | 224 | realStateProvider.getStartTime(), realStateProvider.getVersion(), QUEUE_SIZE); |
1b9d3765 AM |
225 | } catch (IOException e) { |
226 | throw new TmfTraceException(e.toString(), e); | |
227 | } | |
228 | ||
229 | /* 3a */ | |
0fe46f2a | 230 | ITmfStateProvider partialProvider = realStateProvider.getNewInstance(); |
1b9d3765 AM |
231 | |
232 | /* 3b-3c, constructor automatically uses a NullBackend */ | |
233 | PartialStateSystem pss = new PartialStateSystem(); | |
234 | ||
235 | /* 3d */ | |
0fe46f2a | 236 | partialProvider.assignTargetStateSystem(pss); |
1b9d3765 AM |
237 | |
238 | /* 3 */ | |
239 | IStateHistoryBackend partialBackend = | |
0fe46f2a | 240 | new PartialHistoryBackend(partialProvider, pss, realBackend, granularity); |
1b9d3765 AM |
241 | |
242 | /* 4 */ | |
84a9548a | 243 | StateSystem realSS = new StateSystem(SSID, partialBackend); |
1b9d3765 AM |
244 | |
245 | /* 5 */ | |
246 | pss.assignUpstream(realSS); | |
247 | ||
248 | /* 6 */ | |
0fe46f2a | 249 | realStateProvider.assignTargetStateSystem(realSS); |
1b9d3765 AM |
250 | |
251 | /* 7 */ | |
0fe46f2a | 252 | HistoryBuilder builder = new HistoryBuilder(realStateProvider, realSS, partialBackend, buildManually); |
1b9d3765 AM |
253 | return builder.getStateSystemQuerier(); |
254 | } | |
6e71ce46 | 255 | } |