1 /*******************************************************************************
2 * Copyright (c) 2012 Ericsson
3 * Copyright (c) 2010, 2011 École Polytechnique de Montréal
4 * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
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
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.internal
.tmf
.core
.statesystem
.backends
.historytree
;
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
;
22 import org
.eclipse
.linuxtools
.internal
.tmf
.core
.statesystem
.backends
.IStateHistoryBackend
;
23 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.StateSystemDisposedException
;
24 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.TimeRangeException
;
25 import org
.eclipse
.linuxtools
.tmf
.core
.interval
.ITmfStateInterval
;
26 import org
.eclipse
.linuxtools
.tmf
.core
.statevalue
.ITmfStateValue
;
27 import org
.eclipse
.linuxtools
.tmf
.core
.statevalue
.TmfStateValue
;
30 * History Tree backend for storing a state history. This is the basic version
31 * that runs in the same thread as the class creating it.
36 public class HistoryTreeBackend
implements IStateHistoryBackend
{
38 /** The history tree that sits underneath */
39 protected final HistoryTree sht
;
41 /** Direct reference to the tree's IO object */
42 private final HT_IO treeIO
;
44 /** Indicates if the history tree construction is done */
45 protected boolean isFinishedBuilding
= false;
48 * Constructor for new history files. Use this when creating a new history
52 * The filename/location where to store the state history (Should
55 * The size of the blocks in the history file. This should be a
58 * The maximum number of children each core node can have
60 * The earliest time stamp that will be stored in the history
62 * Thrown if we can't create the file for some reason
64 public HistoryTreeBackend(File newStateFile
, int blockSize
,
65 int maxChildren
, long startTime
) throws IOException
{
66 final HTConfig conf
= new HTConfig(newStateFile
, blockSize
, maxChildren
, startTime
);
67 sht
= new HistoryTree(conf
);
68 treeIO
= sht
.getTreeIO();
72 * Constructor for new history files. Use this when creating a new history
73 * from scratch. This version supplies sane defaults for the configuration
77 * The filename/location where to store the state history (Should
80 * The earliest time stamp that will be stored in the history
82 * Thrown if we can't create the file for some reason
84 public HistoryTreeBackend(File newStateFile
, long startTime
)
86 this(newStateFile
, 64 * 1024, 50, startTime
);
90 * Existing history constructor. Use this to open an existing state-file.
92 * @param existingStateFile
93 * Filename/location of the history we want to load
95 * If we can't read the file, if it doesn't exist or is not
98 public HistoryTreeBackend(File existingStateFile
) throws IOException
{
99 sht
= new HistoryTree(existingStateFile
);
100 treeIO
= sht
.getTreeIO();
101 isFinishedBuilding
= true;
105 public long getStartTime() {
106 return sht
.getTreeStart();
110 public long getEndTime() {
111 return sht
.getTreeEnd();
115 public void insertPastState(long stateStartTime
, long stateEndTime
,
116 int quark
, ITmfStateValue value
) throws TimeRangeException
{
117 HTInterval interval
= new HTInterval(stateStartTime
, stateEndTime
,
118 quark
, (TmfStateValue
) value
);
120 /* Start insertions at the "latest leaf" */
121 sht
.insertInterval(interval
);
125 public void finishedBuilding(long endTime
) {
126 sht
.closeTree(endTime
);
127 isFinishedBuilding
= true;
131 public FileInputStream
supplyAttributeTreeReader() {
132 return treeIO
.supplyATReader();
136 public File
supplyAttributeTreeWriterFile() {
137 return treeIO
.supplyATWriterFile();
141 public long supplyAttributeTreeWriterFilePosition() {
142 return treeIO
.supplyATWriterFilePos();
146 public void removeFiles() {
151 public void dispose() {
152 if (isFinishedBuilding
) {
156 * The build is being interrupted, delete the file we partially
157 * built since it won't be complete, so shouldn't be re-used in the
158 * future (.deleteFile() will close the file first)
165 public void doQuery(List
<ITmfStateInterval
> stateInfo
, long t
)
166 throws TimeRangeException
, StateSystemDisposedException
{
167 if (!checkValidTime(t
)) {
168 /* We can't possibly have information about this query */
169 throw new TimeRangeException();
172 /* We start by reading the information in the root node */
173 // FIXME using CoreNode for now, we'll have to redo this part to handle
174 // different node types
175 CoreNode currentNode
= sht
.latestBranch
.firstElement();
176 currentNode
.writeInfoFromNode(stateInfo
, t
);
178 /* Then we follow the branch down in the relevant children */
180 while (currentNode
.getNbChildren() > 0) {
181 currentNode
= (CoreNode
) sht
.selectNextChild(currentNode
, t
);
182 currentNode
.writeInfoFromNode(stateInfo
, t
);
184 } catch (ClosedChannelException e
) {
185 throw new StateSystemDisposedException();
189 * The stateInfo should now be filled with everything needed, we pass
190 * the control back to the State System.
196 public ITmfStateInterval
doSingularQuery(long t
, int attributeQuark
)
197 throws TimeRangeException
, StateSystemDisposedException
{
198 return getRelevantInterval(t
, attributeQuark
);
202 public boolean checkValidTime(long t
) {
203 return (t
>= sht
.getTreeStart() && t
<= sht
.getTreeEnd());
207 * Inner method to find the interval in the tree containing the requested
208 * key/timestamp pair, wherever in which node it is.
212 * @return The node containing the information we want
214 private HTInterval
getRelevantInterval(long t
, int key
)
215 throws TimeRangeException
, StateSystemDisposedException
{
216 if (!checkValidTime(t
)) {
217 throw new TimeRangeException();
220 // FIXME using CoreNode for now, we'll have to redo this part to handle
221 // different node types
222 CoreNode currentNode
= sht
.latestBranch
.firstElement();
223 HTInterval interval
= currentNode
.getRelevantInterval(key
, t
);
226 while (interval
== null && currentNode
.getNbChildren() > 0) {
227 currentNode
= (CoreNode
) sht
.selectNextChild(currentNode
, t
);
228 interval
= currentNode
.getRelevantInterval(key
, t
);
230 } catch (ClosedChannelException e
) {
231 throw new StateSystemDisposedException();
234 * Since we should now have intervals at every attribute/timestamp
235 * combination, it should NOT be null here.
237 assert (interval
!= null);
242 * Return the size of the tree history file
244 * @return The current size of the history file in bytes
246 public long getFileSize() {
247 return sht
.getFileSize();
251 * Return the current depth of the tree, ie the number of node levels.
253 * @return The tree depth
255 public int getTreeDepth() {
256 return sht
.latestBranch
.size();
260 * Return the average node usage as a percentage (between 0 and 100)
262 * @return Average node usage %
264 public int getAverageNodeUsage() {
270 for (int seq
= 0; seq
< sht
.getNodeCount(); seq
++) {
271 node
= treeIO
.readNode(seq
);
272 total
+= node
.getNodeUsagePRC();
274 } catch (ClosedChannelException e
) {
278 ret
= total
/ sht
.getNodeCount();
279 assert (ret
>= 0 && ret
<= 100);
284 public void debugPrint(PrintWriter writer
) {
285 /* By default don't print out all the intervals */
286 this.debugPrint(writer
, false);
290 * The basic debugPrint method will print the tree structure, but not their
293 * This method here print the contents (the intervals) as well.
296 * The PrintWriter to which the debug info will be written
297 * @param printIntervals
298 * Should we also print every contained interval individually?
300 public void debugPrint(PrintWriter writer
, boolean printIntervals
) {
301 /* Only used for debugging, shouldn't be externalized */
302 writer
.println("------------------------------"); //$NON-NLS-1$
303 writer
.println("State History Tree:\n"); //$NON-NLS-1$
304 writer
.println(sht
.toString());
305 writer
.println("Average node utilization: " //$NON-NLS-1$
306 + this.getAverageNodeUsage());
307 writer
.println(""); //$NON-NLS-1$
309 sht
.debugPrintFullTree(writer
, printIntervals
);