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