- Tweaked the FW a little to accommodate LTTng indexing
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf / src / org / eclipse / linuxtools / tmf / event / TmfTimestamp.java
1 /*******************************************************************************
2 * Copyright (c) 2009 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Francois Chouinard - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.linuxtools.tmf.event;
14
15 import java.io.Serializable;
16
17 /**
18 * <b><u>TmfTimestamp</u></b>
19 * <p>
20 * The fundamental time reference in the TMF.
21 * <p>
22 * It provides a generic timestamp implementation in its most basic form:
23 * <ul>
24 * <li>an unstructured integer value
25 * <li>a time scale corresponding to the magnitude of the value wrt some
26 * application-specific base unit (e.g. the second)
27 * <li>a precision to indicate the error on the value (useful for comparing
28 * timestamps in different scales). Default: 0.
29 * </ul>
30 * To allow synchronization of timestamps from different reference clocks, there
31 * is a possibility to "adjust" the timestamp both by changing its scale (traces
32 * of different scale) and by adding an offset to its value (clock drift between
33 * traces).
34 * <p>
35 * Note that the adjusted timestamp value could be negative e.g. for events that
36 * occurred before t0 of the reference clock.
37 *
38 */
39 public class TmfTimestamp implements Serializable {
40
41 /**
42 *
43 */
44 private static final long serialVersionUID = -3196421507276821609L;
45
46 // ========================================================================
47 // Attributes
48 // ========================================================================
49
50 protected final long fValue; // The timestamp value
51 protected final byte fScale; // The time scale
52 protected final long fPrecision; // The value precision (tolerance)
53
54 // ========================================================================
55 // Constants
56 // ========================================================================
57
58 // The beginning and end of time
59 public static final TmfTimestamp BigBang = new TmfTimestamp(Long.MIN_VALUE, Byte.MAX_VALUE, 0);
60 public static final TmfTimestamp BigCrunch = new TmfTimestamp(Long.MAX_VALUE, Byte.MAX_VALUE, 0);
61
62 // ========================================================================
63 // Constructors
64 // ========================================================================
65
66 /**
67 * Default constructor.
68 */
69 public TmfTimestamp() {
70 this(0, (byte) 0, 0);
71 }
72
73 /**
74 * Simple constructor.
75 */
76 public TmfTimestamp(long value) {
77 this(value, (byte) 0, 0);
78 }
79
80 /**
81 * Simple constructor with default error value
82 *
83 * @param value
84 * @param scale
85 */
86 public TmfTimestamp(long value, byte scale) {
87 this(value, scale, 0);
88 }
89
90 /**
91 * Constructor with measurement error.
92 *
93 * @param value
94 * @param scale
95 * @param precision
96 */
97 public TmfTimestamp(long value, byte scale, long precision) {
98 fValue = value;
99 fScale = scale;
100 fPrecision = Math.abs(precision);
101 }
102
103 /**
104 * Copy constructor.
105 *
106 * @param other
107 */
108 public TmfTimestamp(TmfTimestamp other) {
109 this(other.fValue, other.fScale, other.fPrecision);
110 }
111
112 // ========================================================================
113 // Accessors
114 // ========================================================================
115
116 /**
117 * @return The timestamp value
118 */
119 public long getValue() {
120 return fValue;
121 }
122
123 /**
124 * @return The timestamp scale
125 */
126 public byte getScale() {
127 return fScale;
128 }
129
130 /**
131 * @return The timestamp value precision
132 */
133 public long getPrecision() {
134 return fPrecision;
135 }
136
137 // ========================================================================
138 // Operators
139 // ========================================================================
140
141 /**
142 * Return a shifted and scaled timestamp.
143 *
144 * Limitation: The scaling is limited to MAX_SCALING orders of magnitude.
145 * The main reason is that the 64 bits value starts to lose any significance
146 * meaning beyond that scale difference and it's not even worth the trouble
147 * to switch to BigDecimal arithmetics.
148 *
149 * @param offset
150 * - the shift value (in the same scale as newScale)
151 * @param newScale
152 * - the new scale
153 * @return The synchronized timestamp
154 */
155
156 /*
157 * A java <code>long</code> has a maximum of 19 significant digits.
158 * (-9,223,372,036,854,775,808 .. +9,223,372,036,854,775,807)
159 *
160 * It is therefore useless to try to synchronize 2 timestamps whose
161 * difference in scale exceeds that value.
162 */
163 private static int MAX_SCALING = 19;
164
165 public TmfTimestamp synchronize(long offset, byte newScale) throws ArithmeticException {
166 long newValue = fValue;
167 long newPrecision = fPrecision;
168
169 // Determine the scaling factor
170 if (fScale != newScale) {
171 int scaleDiff = Math.abs(fScale - newScale);
172 // Let's try to be realistic...
173 if (scaleDiff > MAX_SCALING) {
174 throw new ArithmeticException("Scaling exception");
175 }
176 // Not pretty...
177 long scalingFactor = 1;
178 for (int i = 0; i < scaleDiff; i++) {
179 scalingFactor *= 10;
180 }
181 if (newScale < fScale) {
182 newValue *= scalingFactor;
183 newPrecision *= scalingFactor;
184 } else {
185 newValue /= scalingFactor;
186 newPrecision /= scalingFactor;
187 }
188 }
189
190 return new TmfTimestamp(newValue + offset, newScale, newPrecision);
191 }
192
193 /**
194 * Compute the adjustment, in the reference scale, needed to synchronize
195 * this timestamp with a reference timestamp.
196 *
197 * @param reference
198 * - the reference timestamp to synchronize with
199 * @return The adjustment term in the reference time scale
200 * @throws TmfNumericalException
201 */
202 public long getAdjustment(TmfTimestamp reference) throws ArithmeticException {
203 TmfTimestamp ts = synchronize(0, reference.fScale);
204 return reference.fValue - ts.fValue;
205 }
206
207 /**
208 * Compare with another timestamp
209 *
210 * @param other
211 * - the other timestamp
212 * @param withinPrecision
213 * - indicates if precision is to be take into consideration
214 * @return <li>-1: this timestamp is lower <li>0: timestamps are equal
215 * (within precision if requested) <li>1: this timestamp is higher
216 * @throws TmfNumericalException
217 */
218 public int compareTo(final TmfTimestamp other, boolean withinPrecision) {
219
220 // If values have the same time scale, perform the comparison
221 if (fScale == other.fScale) {
222 if (withinPrecision) {
223 if ((fValue + fPrecision) < (other.fValue - other.fPrecision))
224 return -1;
225 if ((fValue - fPrecision) > (other.fValue + other.fPrecision))
226 return 1;
227 return 0;
228 }
229 return (fValue == other.fValue) ? 0 : (fValue < other.fValue) ? -1
230 : 1;
231 }
232
233 // If values have different time scales, adjust to the finest one and
234 // then compare. If the scaling difference is too large, revert to
235 // some heuristics. Hopefully, nobody will try to compare galactic and
236 // quantic clock events...
237 byte newScale = (fScale < other.fScale) ? fScale : other.fScale;
238 try {
239 TmfTimestamp ts1 = this.synchronize(0, newScale);
240 TmfTimestamp ts2 = other.synchronize(0, newScale);
241 return ts1.compareTo(ts2, withinPrecision);
242 } catch (ArithmeticException e) {
243 if ((fValue == 0) || (other.fValue == 0)) {
244 return (fValue == other.fValue) ? 0
245 : (fValue < other.fValue) ? -1 : 1;
246 }
247 if ((fValue > 0) && (other.fValue > 0)) {
248 return (fScale < other.fScale) ? -1 : 1;
249 }
250 if ((fValue < 0) && (other.fValue < 0)) {
251 return (fScale > other.fScale) ? -1 : 1;
252 }
253 return (fValue < 0) ? -1 : 1;
254 }
255 }
256
257 /*
258 * (non-Javadoc)
259 *
260 * @see java.lang.Object#equals(java.lang.Object)
261 */
262 @Override
263 public boolean equals(Object other) {
264 if (other instanceof TmfTimestamp)
265 return compareTo((TmfTimestamp) other, false) == 0;
266 return super.equals(other);
267 }
268
269 /* (non-Javadoc)
270 * @see java.lang.Object#toString()
271 */
272 @Override
273 public String toString() {
274 return "[TmfTimestamp:" + fValue + "," + fScale + "," + fPrecision + "]";
275 }
276
277 }
This page took 0.039159 seconds and 6 git commands to generate.