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