// This file is part of OpenTSDB. // Copyright (C) 2014 The OpenTSDB Authors. // // This program is free software: you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 2.1 of the License, or (at your // option) any later version. This program is distributed in the hope that it // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser // General Public License for more details. You should have received a copy // of the GNU Lesser General Public License along with this program. If not, // see <http://www.gnu.org/licenses/>. package net.opentsdb.core; /** * A mutable {@link DataPoint} that stores a value and a timestamp. */ public final class MutableDataPoint implements DataPoint { // NOTE: Fields are not final to make an instance available to store a new // pair of a timestamp and a value to reduce memory burden. /** The timestamp of the value. */ private long timestamp = Long.MAX_VALUE; /** True if the value is stored as a long. */ private boolean is_integer = true; /** A long value or a double encoded on a long if {@code is_integer} is false. */ private long value = 0; /** * Resets with a new pair of a timestamp and a double value. * * @param timestamp A timestamp. * @param value A double value. */ public void reset(final long timestamp, final double value) { this.timestamp = timestamp; this.is_integer = false; this.value = Double.doubleToRawLongBits(value); } /** * Resets with a new pair of a timestamp and a long value. * * @param timestamp A timestamp. * @param value A double value. */ public void reset(final long timestamp, final long value) { this.timestamp = timestamp; this.is_integer = true; this.value = value; } /** * Resets with a new data point. * * @param dp A new data point to store. */ public void reset(DataPoint dp) { this.timestamp = dp.timestamp(); this.is_integer = dp.isInteger(); if (is_integer) { this.value = dp.longValue(); } else { this.value = Double.doubleToRawLongBits(dp.doubleValue()); } } /** * Resets with a new pair of a timestamp and a double value. * * @param timestamp A timestamp. * @param value A double value. */ public static MutableDataPoint ofDoubleValue(final long timestamp, final double value) { final MutableDataPoint dp = new MutableDataPoint(); dp.reset(timestamp, value); return dp; } /** * Resets with a new pair of a timestamp and a long value. * * @param timestamp A timestamp. * @param value A double value. */ public static MutableDataPoint ofLongValue(final long timestamp, final long value) { final MutableDataPoint dp = new MutableDataPoint(); dp.reset(timestamp, value); return dp; } /** * Copy constructor * * @param value A datapoint value. */ public static MutableDataPoint fromPoint(final DataPoint value) { if (value.isInteger()) return ofLongValue(value.timestamp(), value.longValue()); else return ofDoubleValue(value.timestamp(), value.doubleValue()); } @Override public long timestamp() { return timestamp; } @Override public boolean isInteger() { return is_integer; } @Override public long longValue() { if (is_integer) { return value; } throw new ClassCastException("Not a long in " + toString()); } @Override public double doubleValue() { if (!is_integer) { return Double.longBitsToDouble(value); } throw new ClassCastException("Not a double in " + toString()); } @Override public double toDouble() { if (is_integer) { return value; } return Double.longBitsToDouble(value); } @Override public String toString() { return "MutableDataPoint(timestamp=" + timestamp + ", is_integer=" + is_integer + ", value=" + (is_integer ? value : Double.longBitsToDouble(value)) + ")"; } }