/* * Copyright (c) 2008-2012, Hazel Bilisim Ltd. All Rights Reserved. * * 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 com.hazelcast.impl.monitor; import com.hazelcast.monitor.LocalInstanceOperationStats; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicLong; abstract class OperationsCounterSupport<T extends LocalInstanceOperationStats> { final long interval; final Object lock = new Object(); long startTime = now(); long endTime = Long.MAX_VALUE; transient volatile T published = null; final List listOfSubCounters = new ArrayList(); public OperationsCounterSupport() { this(5000); } public OperationsCounterSupport(long interval) { super(); this.interval = interval; } public final T getPublishedStats() { //noinspection DoubleCheckedLocking if (published == null) { synchronized (lock) { if (published == null) { published = getThis(); } } } if (published.getPeriodEnd() < now() - interval) { return getEmpty(); } return published; } final void publishSubResult() { long subInterval = interval / 5; if (now() - startTime > subInterval) { synchronized (lock) { if (now() - startTime >= subInterval) { OperationsCounterSupport<T> copy = getAndReset(); if (listOfSubCounters.size() == 5) { listOfSubCounters.remove(0); } listOfSubCounters.add(copy); this.published = aggregateSubCounterStats(); } } } } abstract T getThis(); abstract T getEmpty(); abstract OperationsCounterSupport<T> getAndReset(); abstract T aggregateSubCounterStats(); final long now() { return System.currentTimeMillis(); } class OperationCounter { final AtomicLong count; final AtomicLong totalLatency; public OperationCounter() { this(0, 0); } public OperationCounter(long c, long l) { this.count = new AtomicLong(c); totalLatency = new AtomicLong(l); } public OperationCounter copyAndReset() { OperationCounter copy = new OperationCounter(count.get(), totalLatency.get()); this.count.set(0); this.totalLatency.set(0); return copy; } public void set(OperationCounter now) { this.count.set(now.count.get()); this.totalLatency.set(now.totalLatency.get()); } public void count(long elapsed) { this.count.incrementAndGet(); this.totalLatency.addAndGet(elapsed); } @Override public String toString() { long count = this.count.get(); return "OperationStat{" + "count=" + count + ", averageLatency=" + ((count == 0) ? 0 : totalLatency.get() / count) + '}'; } } }