/* * Copyright 2014, The OpenNMS Group * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.opennms.newts.api; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.primitives.UnsignedLong; public class Counter extends ValueType<UnsignedLong> { private static final long serialVersionUID = 1L; private static final UnsignedLong MAX32 = toUnsignedLong(0xFFFFFFFFL); private static final UnsignedLong MAX64 = toUnsignedLong(0xFFFFFFFFFFFFFFFFL); public static final String NAN_ON_COUNTER_WRAP_SYS_PROP = "org.opennms.newts.nan_on_counter_wrap"; public static boolean NAN_ON_COUNTER_WRAP = Boolean.getBoolean(NAN_ON_COUNTER_WRAP_SYS_PROP); private final UnsignedLong m_value; public Counter(long value) { this(UnsignedLong.fromLongBits(value)); } public Counter(UnsignedLong value) { m_value = checkNotNull(value, "value"); } @Override public Counter plus(Number value) { return new Counter(getValue().plus(toUnsignedLong(value))); } @Override public Counter minus(Number value) { return new Counter(getValue().minus(toUnsignedLong(value))); } @Override public ValueType<UnsignedLong> delta(Number value) { UnsignedLong previous = toUnsignedLong(value); // If previous value is greater-than this one, we've wrapped if (previous.compareTo(getValue()) > 0) { if (NAN_ON_COUNTER_WRAP) { throw new ArithmeticException(); } UnsignedLong count32 = getValue().plus(MAX32).plus(UnsignedLong.ONE); // Still smaller, this is a 64-bit counter wrap if (previous.compareTo(count32) > 0) { return new Counter(MAX64.minus(previous).plus(getValue()).plus(UnsignedLong.ONE)); } // Process as 32-bit counter wrap else { return new Counter(MAX32.minus(previous).plus(getValue())).plus(UnsignedLong.ONE); } } // ...no counter wrap has occurred. else { return new Counter(getValue().minus(previous)); } } @Override public Counter times(Number value) { return new Counter(getValue().times(toUnsignedLong(value))); } @Override public Counter divideBy(Number value) { return new Counter(getValue().dividedBy(toUnsignedLong(value))); } @Override UnsignedLong getValue() { return m_value; } @Override public MetricType getType() { return MetricType.COUNTER; } @Override public int intValue() { return getValue().intValue(); } @Override public long longValue() { return getValue().longValue(); } @Override public float floatValue() { return getValue().floatValue(); } @Override public double doubleValue() { return getValue().doubleValue(); } protected static UnsignedLong toUnsignedLong(Number value) { if (value instanceof UnsignedLong) return (UnsignedLong) value; return UnsignedLong.fromLongBits(value.longValue()); } }