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