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
.tmf
.core
.statesystem
.backend
.historytree
;
15 import java
.io
.IOException
;
16 import java
.nio
.ByteBuffer
;
18 import org
.eclipse
.linuxtools
.tmf
.core
.interval
.ITmfStateInterval
;
19 import org
.eclipse
.linuxtools
.tmf
.core
.statesystem
.TimeRangeException
;
20 import org
.eclipse
.linuxtools
.tmf
.core
.statevalue
.ITmfStateValue
;
21 import org
.eclipse
.linuxtools
.tmf
.core
.statevalue
.StateValueTypeException
;
22 import org
.eclipse
.linuxtools
.tmf
.core
.statevalue
.TmfStateValue
;
25 * The interval component, which will be contained in a node of the History
31 final class HTInterval
implements ITmfStateInterval
, Comparable
<HTInterval
> {
33 private final long start
;
34 private final long end
;
35 private final int attribute
;
36 private final TmfStateValue sv
;
39 * Size of the strings section entry used by this interval (= 0 if not used)
41 private final int stringsEntrySize
;
44 * Standard constructor
46 * @param intervalStart
50 * @throws TimeRangeException
52 HTInterval(long intervalStart
, long intervalEnd
, int attribute
,
53 TmfStateValue value
) throws TimeRangeException
{
54 if (intervalStart
> intervalEnd
) {
55 throw new TimeRangeException();
58 this.start
= intervalStart
;
59 this.end
= intervalEnd
;
60 this.attribute
= attribute
;
62 this.stringsEntrySize
= computeStringsEntrySize();
66 * Reader constructor. Builds the interval using an already-allocated
67 * ByteBuffer, which normally comes from a NIO FileChannel.
70 * The ByteBuffer from which to read the information
73 final static HTInterval
readFrom(ByteBuffer buffer
) throws IOException
{
75 long intervalStart
, intervalEnd
;
78 int valueOrOffset
, valueSize
, res
;
82 /* Read the Data Section entry */
83 intervalStart
= buffer
.getLong();
84 intervalEnd
= buffer
.getLong();
85 attribute
= buffer
.getInt();
87 /* Read the 'type' of the value, then react accordingly */
88 valueType
= buffer
.get();
90 /* the type of ValueOrOffset is 'value' */
91 valueOrOffset
= buffer
.getInt();
92 if (valueOrOffset
== -1) {
94 value
= TmfStateValue
.nullValue();
96 /* Normal integer value */
97 value
= TmfStateValue
.newValueInt(valueOrOffset
);
100 } else { // valueType > 0
101 /* the type is 'offset' */
102 valueOrOffset
= buffer
.getInt();
105 * Go read the corresponding entry in the Strings section of the
109 buffer
.position(valueOrOffset
);
111 /* the first byte = the size to read */
112 valueSize
= buffer
.get();
115 * Careful though, 'valueSize' is the total size of the entry,
116 * including the 'size' byte at the start and end (0'ed) byte at the
117 * end. Here we want 'array' to only contain the real payload of the
120 array
= new byte[valueSize
- 2];
122 value
= TmfStateValue
.newValueString(new String(array
));
124 /* Confirm the 0'ed byte at the end */
127 throw new IOException(
128 "Invalid interval data. Maybe your file is corrupt?"); //$NON-NLS-1$
132 * Restore the file pointer's position (so we can read the next
139 interval
= new HTInterval(intervalStart
, intervalEnd
, attribute
,
141 } catch (TimeRangeException e
) {
142 throw new IOException(
143 "Invalid interval data. Maybe your file is corrupt?"); //$NON-NLS-1$
149 * Antagonist of the previous constructor, write the Data entry
150 * corresponding to this interval in a ByteBuffer (mapped to a block in the
151 * history-file, hopefully)
154 * The already-allocated ByteBuffer corresponding to a SHT Node
155 * @param endPosOfStringEntry
156 * The initial (before calling this function for this interval)
157 * position of the Strings Entry for this node. This will change
158 * from one call to the other if we're writing String
160 * @return The size of the Strings Entry that was written, if any.
162 int writeInterval(ByteBuffer buffer
, int endPosOfStringEntry
) {
163 int sizeOfStringEntry
;
164 byte[] byteArrayToWrite
;
166 buffer
.putLong(start
);
168 buffer
.putInt(attribute
);
169 buffer
.put(sv
.getType());
171 byteArrayToWrite
= sv
.toByteArray();
173 if (byteArrayToWrite
== null) {
174 /* We write the 'valueOffset' field as a straight value */
179 buffer
.putInt(sv
.unboxInt());
180 } catch (StateValueTypeException e
) {
182 * This should not happen, since the value told us it was of
183 * type Integer (corrupted value?)
188 return 0; /* we didn't use a Strings section entry */
192 * Size to write (+2 = +1 for size at the start, +1 for the 0 at the
195 sizeOfStringEntry
= byteArrayToWrite
.length
+ 2;
197 /* we use the valueOffset as an offset. */
198 buffer
.putInt(endPosOfStringEntry
- sizeOfStringEntry
);
200 buffer
.position(endPosOfStringEntry
- sizeOfStringEntry
);
203 * write the Strings entry (1st byte = size, then the bytes, then
206 buffer
.put((byte) sizeOfStringEntry
);
207 buffer
.put(byteArrayToWrite
);
208 buffer
.put((byte) 0);
209 assert (buffer
.position() == endPosOfStringEntry
);
211 return sizeOfStringEntry
;
215 public long getStartTime() {
220 public long getEndTime() {
225 public int getAttribute() {
230 public ITmfStateValue
getStateValue() {
235 public boolean intersects(long timestamp
) {
236 if (start
<= timestamp
) {
237 if (end
>= timestamp
) {
244 int getStringsEntrySize() {
245 return stringsEntrySize
;
249 * Total serialized size of this interval
253 int getIntervalSize() {
254 return stringsEntrySize
+ HTNode
.getDataEntrySize();
257 private int computeStringsEntrySize() {
258 if (sv
.toByteArray() == null) {
261 return sv
.toByteArray().length
+ 2;
262 /* (+1 for the first byte indicating the size, +1 for the 0'ed byte) */
266 * Compare the END TIMES of different intervals. This is used to sort the
267 * intervals when we close down a node.
270 public int compareTo(HTInterval other
) {
271 if (this.end
< other
.end
) {
273 } else if (this.end
> other
.end
) {