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