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