ss: Move all debugPrint() methods to the test stubs
[deliverable/tracecompass.git] / statesystem / org.eclipse.tracecompass.statesystem.core / src / org / eclipse / tracecompass / internal / statesystem / core / backend / historytree / HistoryTreeBackend.java
CommitLineData
a52fde77 1/*******************************************************************************
e8aa3325 2 * Copyright (c) 2012, 2016 Ericsson
a52fde77
AM
3 * Copyright (c) 2010, 2011 École Polytechnique de Montréal
4 * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
5df842b3 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
5df842b3 10 *
e13bd4cd
PT
11 * Contributors:
12 * Alexandre Montplaisir - Initial API and implementation
13 * Patrick Tasse - Add message to exceptions
a52fde77
AM
14 *******************************************************************************/
15
0306a843 16package org.eclipse.tracecompass.internal.statesystem.core.backend.historytree;
a52fde77
AM
17
18import java.io.File;
19import java.io.FileInputStream;
20import java.io.IOException;
3b7f5abe 21import java.nio.channels.ClosedChannelException;
a52fde77
AM
22import java.util.List;
23
b2f62cb5 24import org.eclipse.jdt.annotation.NonNull;
0e9b2f07 25import org.eclipse.tracecompass.internal.statesystem.core.Activator;
e894a508
AM
26import org.eclipse.tracecompass.statesystem.core.backend.IStateHistoryBackend;
27import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
28import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
29import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
30import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
31import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
a52fde77 32
068641fa
GB
33import com.google.common.annotations.VisibleForTesting;
34
a52fde77
AM
35/**
36 * History Tree backend for storing a state history. This is the basic version
37 * that runs in the same thread as the class creating it.
5df842b3 38 *
360f899e 39 * @author Alexandre Montplaisir
a52fde77
AM
40 */
41public class HistoryTreeBackend implements IStateHistoryBackend {
42
0e9b2f07 43 private final @NonNull String fSsid;
b2f62cb5 44
bcec0116
AM
45 /**
46 * The history tree that sits underneath.
bcec0116 47 */
3a081e85 48 private final @NonNull IHistoryTree fSht;
6f4e8ec0 49
1a4205d9 50 /** Indicates if the history tree construction is done */
d740e018
MK
51 private volatile boolean fFinishedBuilding = false;
52
53 /**
54 * Indicates if the history tree construction is done
55 *
56 * @return if the history tree construction is done
57 */
58 protected boolean isFinishedBuilding() {
59 return fFinishedBuilding;
60 }
61
62 /**
63 * Sets if the history tree is finished building
64 *
65 * @param isFinishedBuilding
66 * is the history tree finished building
67 */
68 protected void setFinishedBuilding(boolean isFinishedBuilding) {
0e9b2f07 69 fFinishedBuilding = isFinishedBuilding;
d740e018 70 }
1a4205d9 71
a52fde77 72 /**
7453b40e 73 * Constructor for new history files. Use this when creating a new history
a52fde77 74 * from scratch.
5df842b3 75 *
b2f62cb5
AM
76 * @param ssid
77 * The state system's ID
a52fde77
AM
78 * @param newStateFile
79 * The filename/location where to store the state history (Should
80 * end in .ht)
a96cc6be
AM
81 * @param providerVersion
82 * Version of of the state provider. We will only try to reopen
83 * existing files if this version matches the one in the
84 * framework.
a52fde77
AM
85 * @param startTime
86 * The earliest time stamp that will be stored in the history
f6d24a71
AM
87 * @param blockSize
88 * The size of the blocks in the history file. This should be a
89 * multiple of 4096.
90 * @param maxChildren
91 * The maximum number of children each core node can have
a52fde77
AM
92 * @throws IOException
93 * Thrown if we can't create the file for some reason
94 */
f6d24a71
AM
95 public HistoryTreeBackend(@NonNull String ssid,
96 File newStateFile,
97 int providerVersion,
98 long startTime,
99 int blockSize,
100 int maxChildren) throws IOException {
0e9b2f07 101 fSsid = ssid;
a96cc6be
AM
102 final HTConfig conf = new HTConfig(newStateFile, blockSize, maxChildren,
103 providerVersion, startTime);
068641fa 104 fSht = initializeSHT(conf);
a52fde77
AM
105 }
106
107 /**
7453b40e 108 * Constructor for new history files. Use this when creating a new history
a52fde77
AM
109 * from scratch. This version supplies sane defaults for the configuration
110 * parameters.
5df842b3 111 *
b2f62cb5
AM
112 * @param ssid
113 * The state system's id
a52fde77
AM
114 * @param newStateFile
115 * The filename/location where to store the state history (Should
116 * end in .ht)
a96cc6be
AM
117 * @param providerVersion
118 * Version of of the state provider. We will only try to reopen
119 * existing files if this version matches the one in the
120 * framework.
a52fde77
AM
121 * @param startTime
122 * The earliest time stamp that will be stored in the history
123 * @throws IOException
124 * Thrown if we can't create the file for some reason
dbc7991d 125 * @since 1.0
a52fde77 126 */
b2f62cb5 127 public HistoryTreeBackend(@NonNull String ssid, File newStateFile, int providerVersion, long startTime)
a52fde77 128 throws IOException {
f6d24a71 129 this(ssid, newStateFile, providerVersion, startTime, 64 * 1024, 50);
a52fde77
AM
130 }
131
132 /**
133 * Existing history constructor. Use this to open an existing state-file.
5df842b3 134 *
b2f62cb5
AM
135 * @param ssid
136 * The state system's id
0d9a6d76 137 * @param existingStateFile
b255ae4b 138 * Filename/location of the history we want to load
a96cc6be
AM
139 * @param providerVersion
140 * Expected version of of the state provider plugin.
b255ae4b 141 * @throws IOException
a96cc6be
AM
142 * If we can't read the file, if it doesn't exist, is not
143 * recognized, or if the version of the file does not match the
144 * expected providerVersion.
a52fde77 145 */
068641fa 146 public HistoryTreeBackend(@NonNull String ssid, @NonNull File existingStateFile, int providerVersion)
a96cc6be 147 throws IOException {
0e9b2f07 148 fSsid = ssid;
068641fa 149 fSht = initializeSHT(existingStateFile, providerVersion);
d740e018 150 fFinishedBuilding = true;
a52fde77
AM
151 }
152
068641fa
GB
153 /**
154 * New-tree initializer for the History Tree wrapped by this backend. Can be
155 * overriden to use different implementations.
156 *
157 * @param conf
158 * The HTConfig configuration object
159 * @return The new history tree
160 * @throws IOException
161 * If there was a problem during creation
162 */
163 @VisibleForTesting
3a081e85 164 protected @NonNull IHistoryTree initializeSHT(@NonNull HTConfig conf) throws IOException {
9a4c098d 165 return HistoryTreeFactory.createHistoryTree(conf);
068641fa
GB
166 }
167
168 /**
169 * Existing-tree initializer for the History Tree wrapped by this backend.
170 * Can be overriden to use different implementations.
171 *
172 * @param existingStateFile
173 * The file to open
174 * @param providerVersion
175 * The expected state provider version
176 * @return The history tree opened from the given file
177 * @throws IOException
178 * If there was a problem during creation
179 */
180 @VisibleForTesting
3a081e85 181 protected @NonNull IHistoryTree initializeSHT(@NonNull File existingStateFile, int providerVersion) throws IOException {
9a4c098d 182 return HistoryTreeFactory.createFromFile(existingStateFile.toPath(), providerVersion);
068641fa
GB
183 }
184
e62a23a9
AM
185 /**
186 * Get the History Tree built by this backend.
187 *
068641fa
GB
188 * Note: Do not override this method. If you want to extend the class to use
189 * a different History Tree implementation, override both variants of
190 * {@link #initializeSHT} instead.
191 *
e62a23a9
AM
192 * @return The history tree
193 */
3a081e85 194 protected final @NonNull IHistoryTree getSHT() {
0e9b2f07 195 return fSht;
e62a23a9
AM
196 }
197
b2f62cb5
AM
198 @Override
199 public String getSSID() {
0e9b2f07 200 return fSsid;
b2f62cb5
AM
201 }
202
a52fde77
AM
203 @Override
204 public long getStartTime() {
068641fa 205 return getSHT().getTreeStart();
a52fde77
AM
206 }
207
208 @Override
209 public long getEndTime() {
068641fa 210 return getSHT().getTreeEnd();
a52fde77
AM
211 }
212
213 @Override
214 public void insertPastState(long stateStartTime, long stateEndTime,
215 int quark, ITmfStateValue value) throws TimeRangeException {
216 HTInterval interval = new HTInterval(stateStartTime, stateEndTime,
217 quark, (TmfStateValue) value);
218
219 /* Start insertions at the "latest leaf" */
068641fa 220 getSHT().insertInterval(interval);
a52fde77
AM
221 }
222
223 @Override
b33c7369 224 public void finishedBuilding(long endTime) {
068641fa 225 getSHT().closeTree(endTime);
d740e018 226 fFinishedBuilding = true;
a52fde77
AM
227 }
228
229 @Override
230 public FileInputStream supplyAttributeTreeReader() {
068641fa 231 return getSHT().supplyATReader();
a52fde77
AM
232 }
233
234 @Override
235 public File supplyAttributeTreeWriterFile() {
068641fa 236 return getSHT().supplyATWriterFile();
a52fde77
AM
237 }
238
239 @Override
240 public long supplyAttributeTreeWriterFilePosition() {
068641fa 241 return getSHT().supplyATWriterFilePos();
a52fde77
AM
242 }
243
36bf82a2
AM
244 @Override
245 public void removeFiles() {
068641fa 246 getSHT().deleteFile();
36bf82a2
AM
247 }
248
1a4205d9
AM
249 @Override
250 public void dispose() {
d740e018 251 if (fFinishedBuilding) {
068641fa 252 getSHT().closeFile();
1a4205d9
AM
253 } else {
254 /*
255 * The build is being interrupted, delete the file we partially
256 * built since it won't be complete, so shouldn't be re-used in the
257 * future (.deleteFile() will close the file first)
258 */
068641fa 259 getSHT().deleteFile();
1a4205d9
AM
260 }
261 }
262
a52fde77
AM
263 @Override
264 public void doQuery(List<ITmfStateInterval> stateInfo, long t)
3b7f5abe 265 throws TimeRangeException, StateSystemDisposedException {
e13bd4cd 266 checkValidTime(t);
a52fde77
AM
267
268 /* We start by reading the information in the root node */
068641fa 269 HTNode currentNode = getSHT().getRootNode();
a52fde77
AM
270 currentNode.writeInfoFromNode(stateInfo, t);
271
272 /* Then we follow the branch down in the relevant children */
3b7f5abe 273 try {
bb7f92ce 274 while (currentNode.getNodeType() == HTNode.NodeType.CORE) {
068641fa 275 currentNode = getSHT().selectNextChild((CoreNode) currentNode, t);
3b7f5abe
AM
276 currentNode.writeInfoFromNode(stateInfo, t);
277 }
278 } catch (ClosedChannelException e) {
cb42195c 279 throw new StateSystemDisposedException(e);
a52fde77
AM
280 }
281
282 /*
283 * The stateInfo should now be filled with everything needed, we pass
284 * the control back to the State System.
285 */
a52fde77
AM
286 }
287
288 @Override
289 public ITmfStateInterval doSingularQuery(long t, int attributeQuark)
3b7f5abe 290 throws TimeRangeException, StateSystemDisposedException {
a52fde77
AM
291 return getRelevantInterval(t, attributeQuark);
292 }
293
e13bd4cd 294 private void checkValidTime(long t) {
e8aa3325
PT
295 long startTime = getStartTime();
296 long endTime = getEndTime();
297 if (t < startTime || t > endTime) {
298 throw new TimeRangeException(String.format("%s Time:%d, Start:%d, End:%d", //$NON-NLS-1$
299 fSsid, t, startTime, endTime));
e13bd4cd 300 }
a52fde77
AM
301 }
302
303 /**
304 * Inner method to find the interval in the tree containing the requested
305 * key/timestamp pair, wherever in which node it is.
5df842b3 306 *
a52fde77
AM
307 * @param t
308 * @param key
309 * @return The node containing the information we want
310 */
311 private HTInterval getRelevantInterval(long t, int key)
3b7f5abe 312 throws TimeRangeException, StateSystemDisposedException {
e13bd4cd 313 checkValidTime(t);
a52fde77 314
068641fa 315 HTNode currentNode = getSHT().getRootNode();
a52fde77
AM
316 HTInterval interval = currentNode.getRelevantInterval(key, t);
317
3b7f5abe 318 try {
bb7f92ce 319 while (interval == null && currentNode.getNodeType() == HTNode.NodeType.CORE) {
068641fa 320 currentNode = getSHT().selectNextChild((CoreNode) currentNode, t);
3b7f5abe
AM
321 interval = currentNode.getRelevantInterval(key, t);
322 }
323 } catch (ClosedChannelException e) {
cb42195c 324 throw new StateSystemDisposedException(e);
a52fde77 325 }
a52fde77
AM
326 return interval;
327 }
328
329 /**
330 * Return the size of the tree history file
5df842b3 331 *
a52fde77
AM
332 * @return The current size of the history file in bytes
333 */
334 public long getFileSize() {
068641fa 335 return getSHT().getFileSize();
a52fde77
AM
336 }
337
a52fde77
AM
338 /**
339 * Return the average node usage as a percentage (between 0 and 100)
5df842b3 340 *
a52fde77
AM
341 * @return Average node usage %
342 */
343 public int getAverageNodeUsage() {
344 HTNode node;
345 long total = 0;
346 long ret;
347
3b7f5abe 348 try {
068641fa
GB
349 for (int seq = 0; seq < getSHT().getNodeCount(); seq++) {
350 node = getSHT().readNode(seq);
8d47cc34 351 total += node.getNodeUsagePercent();
3b7f5abe
AM
352 }
353 } catch (ClosedChannelException e) {
0e9b2f07 354 Activator.getDefault().logError(e.getMessage(), e);
a52fde77
AM
355 }
356
068641fa 357 ret = total / getSHT().getNodeCount();
822798a3 358 /* The return value should be a percentage */
09e814aa 359 if (ret < 0 || ret > 100) {
822798a3
GB
360 throw new IllegalStateException("Average node usage is not a percentage: " + ret); //$NON-NLS-1$
361 }
a52fde77
AM
362 return (int) ret;
363 }
364
a52fde77 365}
This page took 0.105986 seconds and 5 git commands to generate.