[Bug 303523] LTTng/TMF udpates:
[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
16 /**
17 * <b><u>TmfTimestamp</u></b>
18 * <p>
19 * The fundamental time reference in the TMF.
20 * <p>
21 * It provides a generic timestamp implementation in its most basic form:
22 * <ul>
23 * <li>an unstructured integer value
24 * <li>a time scale corresponding to the magnitude of the value wrt some
25 * application-specific base unit (e.g. the second)
26 * <li>a precision to indicate the error on the value (useful for comparing
27 * timestamps in different scales). Default: 0.
28 * </ul>
29 * To allow synchronization of timestamps from different reference clocks,
30 * there is a possibility to "adjust" the timestamp both by changing its scale
31 * (traces of different scale) and by adding an offset to its value (clock
32 * drift between traces).
33 * <p>
34 * Notice that the adjusted timestamp value could be negative e.g. for events
35 * that occurred before t0 wrt the reference clock.
36 * <p>
37 * Finally, notice that timestamps are immutable.
38 */
39 public class TmfTimestamp implements Cloneable {
40
41 // ========================================================================
42 // Attributes
43 // ========================================================================
44
45 protected long fValue; // The timestamp value
46 protected byte fScale; // The time scale
47 protected long fPrecision; // The value precision (tolerance)
48
49 // ========================================================================
50 // Constants
51 // ========================================================================
52
53 // The beginning and end of time
54 public static final TmfTimestamp BigBang = new TmfTimestamp(Long.MIN_VALUE, Byte.MAX_VALUE, 0);
55 public static final TmfTimestamp BigCrunch = new TmfTimestamp(Long.MAX_VALUE, Byte.MAX_VALUE, 0);
56 public static final TmfTimestamp Zero = new TmfTimestamp(0, (byte) 0, 0);
57
58 // ========================================================================
59 // Constructors
60 // ========================================================================
61
62 /**
63 * Default constructor
64 */
65 public TmfTimestamp() {
66 this(0, (byte) 0, 0);
67 }
68
69 /**
70 * Simple constructor with value only
71 */
72 public TmfTimestamp(long value) {
73 this(value, (byte) 0, 0);
74 }
75
76 /**
77 * Simple constructor with value and scale
78 *
79 * @param value
80 * @param scale
81 */
82 public TmfTimestamp(long value, byte scale) {
83 this(value, scale, 0);
84 }
85
86 /**
87 * Constructor with value, scale and precision
88 *
89 * @param value
90 * @param scale
91 * @param precision
92 */
93 public TmfTimestamp(long value, byte scale, long precision) {
94 fValue = value;
95 fScale = scale;
96 fPrecision = Math.abs(precision);
97 }
98
99 /**
100 * Copy constructor
101 *
102 * @param other
103 */
104 public TmfTimestamp(TmfTimestamp other) {
105 assert(other != null);
106 fValue = other.fValue;
107 fScale = other.fScale;
108 fPrecision = other.fPrecision;
109 }
110
111 // ========================================================================
112 // Accessors
113 // ========================================================================
114
115 /**
116 * @return the timestamp value
117 */
118 public long getValue() {
119 return fValue;
120 }
121
122 /**
123 * @return the timestamp scale
124 */
125 public byte getScale() {
126 return fScale;
127 }
128
129 /**
130 * @return the timestamp value precision
131 */
132 public long getPrecision() {
133 return fPrecision;
134 }
135
136 // ========================================================================
137 // Operators
138 // ========================================================================
139
140 /**
141 * Return a shifted and scaled timestamp.
142 *
143 * Limitation: The scaling is limited to MAX_SCALING orders of magnitude.
144 * The main reason is that the 64 bits value starts to lose any significance
145 * meaning beyond that scale difference and it's not even worth the trouble
146 * to switch to BigDecimal arithmetics.
147 *
148 * @param offset
149 * - the shift value (in the same scale as newScale)
150 * @param newScale
151 * - the new scale
152 * @return The synchronized timestamp
153 */
154
155 /*
156 * A java <code>long</code> has a maximum of 19 significant digits.
157 * (-9,223,372,036,854,775,808 .. +9,223,372,036,854,775,807)
158 *
159 * It is therefore useless to try to synchronize 2 timestamps whose
160 * difference in scale exceeds that value.
161 */
162 private static int MAX_SCALING = 19;
163
164 public TmfTimestamp synchronize(long offset, byte newScale) throws ArithmeticException {
165 long newValue = fValue;
166 long newPrecision = fPrecision;
167
168 // Determine the scaling factor
169 if (fScale != newScale) {
170 int scaleDiff = Math.abs(fScale - newScale);
171 // Let's try to be realistic...
172 if (scaleDiff > MAX_SCALING) {
173 throw new ArithmeticException("Scaling exception");
174 }
175 // Not pretty...
176 long scalingFactor = 1;
177 for (int i = 0; i < scaleDiff; i++) {
178 scalingFactor *= 10;
179 }
180 if (newScale < fScale) {
181 newValue *= scalingFactor;
182 newPrecision *= scalingFactor;
183 } else {
184 newValue /= scalingFactor;
185 newPrecision /= scalingFactor;
186 }
187 }
188
189 return new TmfTimestamp(newValue + offset, newScale, newPrecision);
190 }
191
192 /**
193 * Compute the adjustment, in the reference scale, needed to synchronize
194 * this timestamp with a reference timestamp.
195 *
196 * @param reference
197 * - the reference timestamp to synchronize with
198 * @return the adjustment term in the reference time scale
199 * @throws TmfNumericalException
200 */
201 public long getAdjustment(TmfTimestamp reference) throws ArithmeticException {
202 TmfTimestamp ts = synchronize(0, reference.fScale);
203 return reference.fValue - ts.fValue;
204 }
205
206 /**
207 * Compare with another timestamp
208 *
209 * @param other
210 * - the other timestamp
211 * @param withinPrecision
212 * - indicates if precision is to be take into consideration
213 * @return -1: this timestamp is lower
214 * 0: timestamps are equal (within precision if requested)
215 * 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 @Override
258 public TmfTimestamp clone() {
259 return new TmfTimestamp(this);
260 }
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 @Override
270 public String toString() {
271 return "[TmfTimestamp(" + fValue + "," + fScale + "," + fPrecision + ")]";
272 }
273
274 }
This page took 0.035865 seconds and 5 git commands to generate.