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