ss: Bug 484776: Incorrect end time in HistoryTree
[deliverable/tracecompass.git] / statesystem / org.eclipse.tracecompass.statesystem.core / src / org / eclipse / tracecompass / internal / statesystem / core / backend / historytree / HistoryTreeBackend.java
... / ...
CommitLineData
1/*******************************************************************************
2 * Copyright (c) 2012, 2016 Ericsson
3 * Copyright (c) 2010, 2011 École Polytechnique de Montréal
4 * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
5 *
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
10 *
11 * Contributors:
12 * Alexandre Montplaisir - Initial API and implementation
13 * Patrick Tasse - Add message to exceptions
14 *******************************************************************************/
15
16package org.eclipse.tracecompass.internal.statesystem.core.backend.historytree;
17
18import java.io.File;
19import java.io.FileInputStream;
20import java.io.IOException;
21import java.io.PrintWriter;
22import java.nio.channels.ClosedChannelException;
23import java.util.List;
24
25import org.eclipse.jdt.annotation.NonNull;
26import org.eclipse.tracecompass.internal.statesystem.core.Activator;
27import org.eclipse.tracecompass.statesystem.core.backend.IStateHistoryBackend;
28import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
29import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
30import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
31import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
32import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
33
34/**
35 * History Tree backend for storing a state history. This is the basic version
36 * that runs in the same thread as the class creating it.
37 *
38 * @author Alexandre Montplaisir
39 */
40public class HistoryTreeBackend implements IStateHistoryBackend {
41
42 private final @NonNull String fSsid;
43
44 /**
45 * The history tree that sits underneath.
46 */
47 private final HistoryTree fSht;
48
49 /** Indicates if the history tree construction is done */
50 private volatile boolean fFinishedBuilding = false;
51
52 /**
53 * Indicates if the history tree construction is done
54 *
55 * @return if the history tree construction is done
56 */
57 protected boolean isFinishedBuilding() {
58 return fFinishedBuilding;
59 }
60
61 /**
62 * Sets if the history tree is finished building
63 *
64 * @param isFinishedBuilding
65 * is the history tree finished building
66 */
67 protected void setFinishedBuilding(boolean isFinishedBuilding) {
68 fFinishedBuilding = isFinishedBuilding;
69 }
70
71 /**
72 * Constructor for new history files. Use this when creating a new history
73 * from scratch.
74 *
75 * @param ssid
76 * The state system's ID
77 * @param newStateFile
78 * The filename/location where to store the state history (Should
79 * end in .ht)
80 * @param providerVersion
81 * Version of of the state provider. We will only try to reopen
82 * existing files if this version matches the one in the
83 * framework.
84 * @param startTime
85 * The earliest time stamp that will be stored in the history
86 * @param blockSize
87 * The size of the blocks in the history file. This should be a
88 * multiple of 4096.
89 * @param maxChildren
90 * The maximum number of children each core node can have
91 * @throws IOException
92 * Thrown if we can't create the file for some reason
93 */
94 public HistoryTreeBackend(@NonNull String ssid,
95 File newStateFile,
96 int providerVersion,
97 long startTime,
98 int blockSize,
99 int maxChildren) throws IOException {
100 fSsid = ssid;
101 final HTConfig conf = new HTConfig(newStateFile, blockSize, maxChildren,
102 providerVersion, startTime);
103 fSht = new HistoryTree(conf);
104 }
105
106 /**
107 * Constructor for new history files. Use this when creating a new history
108 * from scratch. This version supplies sane defaults for the configuration
109 * parameters.
110 *
111 * @param ssid
112 * The state system's id
113 * @param newStateFile
114 * The filename/location where to store the state history (Should
115 * end in .ht)
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.
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
124 * @since 1.0
125 */
126 public HistoryTreeBackend(@NonNull String ssid, File newStateFile, int providerVersion, long startTime)
127 throws IOException {
128 this(ssid, newStateFile, providerVersion, startTime, 64 * 1024, 50);
129 }
130
131 /**
132 * Existing history constructor. Use this to open an existing state-file.
133 *
134 * @param ssid
135 * The state system's id
136 * @param existingStateFile
137 * Filename/location of the history we want to load
138 * @param providerVersion
139 * Expected version of of the state provider plugin.
140 * @throws IOException
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.
144 */
145 public HistoryTreeBackend(@NonNull String ssid, File existingStateFile, int providerVersion)
146 throws IOException {
147 fSsid = ssid;
148 fSht = new HistoryTree(existingStateFile, providerVersion);
149 fFinishedBuilding = true;
150 }
151
152 /**
153 * Get the History Tree built by this backend.
154 *
155 * @return The history tree
156 */
157 protected HistoryTree getSHT() {
158 return fSht;
159 }
160
161 @Override
162 public String getSSID() {
163 return fSsid;
164 }
165
166 @Override
167 public long getStartTime() {
168 return fSht.getTreeStart();
169 }
170
171 @Override
172 public long getEndTime() {
173 return fSht.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 fSht.insertInterval(interval);
184 }
185
186 @Override
187 public void finishedBuilding(long endTime) {
188 fSht.closeTree(endTime);
189 fFinishedBuilding = true;
190 }
191
192 @Override
193 public FileInputStream supplyAttributeTreeReader() {
194 return fSht.supplyATReader();
195 }
196
197 @Override
198 public File supplyAttributeTreeWriterFile() {
199 return fSht.supplyATWriterFile();
200 }
201
202 @Override
203 public long supplyAttributeTreeWriterFilePosition() {
204 return fSht.supplyATWriterFilePos();
205 }
206
207 @Override
208 public void removeFiles() {
209 fSht.deleteFile();
210 }
211
212 @Override
213 public void dispose() {
214 if (fFinishedBuilding) {
215 fSht.closeFile();
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 */
222 fSht.deleteFile();
223 }
224 }
225
226 @Override
227 public void doQuery(List<ITmfStateInterval> stateInfo, long t)
228 throws TimeRangeException, StateSystemDisposedException {
229 checkValidTime(t);
230
231 /* We start by reading the information in the root node */
232 HTNode currentNode = fSht.getRootNode();
233 currentNode.writeInfoFromNode(stateInfo, t);
234
235 /* Then we follow the branch down in the relevant children */
236 try {
237 while (currentNode.getNodeType() == HTNode.NodeType.CORE) {
238 currentNode = fSht.selectNextChild((CoreNode) currentNode, t);
239 currentNode.writeInfoFromNode(stateInfo, t);
240 }
241 } catch (ClosedChannelException e) {
242 throw new StateSystemDisposedException(e);
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 }
250
251 @Override
252 public ITmfStateInterval doSingularQuery(long t, int attributeQuark)
253 throws TimeRangeException, StateSystemDisposedException {
254 return getRelevantInterval(t, attributeQuark);
255 }
256
257 private void checkValidTime(long t) {
258 long startTime = getStartTime();
259 long endTime = getEndTime();
260 if (t < startTime || t > endTime) {
261 throw new TimeRangeException(String.format("%s Time:%d, Start:%d, End:%d", //$NON-NLS-1$
262 fSsid, t, startTime, endTime));
263 }
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.
269 *
270 * @param t
271 * @param key
272 * @return The node containing the information we want
273 */
274 private HTInterval getRelevantInterval(long t, int key)
275 throws TimeRangeException, StateSystemDisposedException {
276 checkValidTime(t);
277
278 HTNode currentNode = fSht.getRootNode();
279 HTInterval interval = currentNode.getRelevantInterval(key, t);
280
281 try {
282 while (interval == null && currentNode.getNodeType() == HTNode.NodeType.CORE) {
283 currentNode = fSht.selectNextChild((CoreNode) currentNode, t);
284 interval = currentNode.getRelevantInterval(key, t);
285 }
286 } catch (ClosedChannelException e) {
287 throw new StateSystemDisposedException(e);
288 }
289 return interval;
290 }
291
292 /**
293 * Return the size of the tree history file
294 *
295 * @return The current size of the history file in bytes
296 */
297 public long getFileSize() {
298 return fSht.getFileSize();
299 }
300
301 /**
302 * Return the average node usage as a percentage (between 0 and 100)
303 *
304 * @return Average node usage %
305 */
306 public int getAverageNodeUsage() {
307 HTNode node;
308 long total = 0;
309 long ret;
310
311 try {
312 for (int seq = 0; seq < fSht.getNodeCount(); seq++) {
313 node = fSht.readNode(seq);
314 total += node.getNodeUsagePercent();
315 }
316 } catch (ClosedChannelException e) {
317 Activator.getDefault().logError(e.getMessage(), e);
318 }
319
320 ret = total / fSht.getNodeCount();
321 /* The return value should be a percentage */
322 if (ret < 0 || ret > 100) {
323 throw new IllegalStateException("Average node usage is not a percentage: " + ret); //$NON-NLS-1$
324 }
325 return (int) ret;
326 }
327
328 @Override
329 public void debugPrint(PrintWriter writer) {
330 /* By default don't print out all the intervals */
331 debugPrint(writer, false);
332 }
333
334 /**
335 * The basic debugPrint method will print the tree structure, but not their
336 * contents.
337 *
338 * This method here print the contents (the intervals) as well.
339 *
340 * @param writer
341 * The PrintWriter to which the debug info will be written
342 * @param printIntervals
343 * Should we also print every contained interval individually?
344 */
345 public void debugPrint(PrintWriter writer, boolean printIntervals) {
346 /* Only used for debugging, shouldn't be externalized */
347 writer.println("------------------------------"); //$NON-NLS-1$
348 writer.println("State History Tree:\n"); //$NON-NLS-1$
349 writer.println(fSht.toString());
350 writer.println("Average node utilization: " //$NON-NLS-1$
351 + getAverageNodeUsage());
352 writer.println(""); //$NON-NLS-1$
353
354 fSht.debugPrintFullTree(writer, printIntervals);
355 }
356}
This page took 0.027465 seconds and 5 git commands to generate.