Line data Source code
1 : // Copyright (C) 2015 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.metrics.dropwizard; 16 : 17 : import com.google.common.collect.ImmutableSet; 18 : import java.util.concurrent.TimeUnit; 19 : import java.util.concurrent.atomic.AtomicLong; 20 : 21 : /** 22 : * Run a user specified trigger only once every 2 seconds. 23 : * 24 : * <p>This allows the same Runnable trigger to be applied to several metrics. When a recorder is 25 : * sampling the related metrics only the first access will perform recomputation. Reading other 26 : * related metrics will rely on the already set values for the next several seconds. 27 : */ 28 : class CallbackGroup implements Runnable { 29 16 : private static final long PERIOD = TimeUnit.SECONDS.toNanos(2); 30 : 31 : private final AtomicLong reloadAt; 32 : private final Runnable trigger; 33 : private final ImmutableSet<CallbackMetricGlue> metrics; 34 16 : private final Object reloadLock = new Object(); 35 : 36 16 : CallbackGroup(Runnable trigger, ImmutableSet<CallbackMetricGlue> metrics) { 37 16 : this.reloadAt = new AtomicLong(0); 38 16 : this.trigger = trigger; 39 16 : this.metrics = metrics; 40 16 : } 41 : 42 : @Override 43 : public void run() { 44 16 : if (reload()) { 45 16 : synchronized (reloadLock) { 46 16 : for (CallbackMetricGlue m : metrics) { 47 16 : m.beginSet(); 48 16 : } 49 16 : trigger.run(); 50 16 : for (CallbackMetricGlue m : metrics) { 51 16 : m.endSet(); 52 16 : } 53 16 : } 54 : } 55 16 : } 56 : 57 : private boolean reload() { 58 : for (; ; ) { 59 16 : long now = System.nanoTime(); 60 16 : long next = reloadAt.get(); 61 16 : if (next > now) { 62 1 : return false; 63 16 : } else if (reloadAt.compareAndSet(next, now + PERIOD)) { 64 16 : return true; 65 : } 66 0 : } 67 : } 68 : }