/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You 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.apache.geode.internal.cache.lru; import java.util.concurrent.atomic.AtomicLong; import org.apache.geode.Statistics; import org.apache.geode.StatisticsFactory; import org.apache.geode.StatisticsType; import org.apache.geode.internal.Assert; /** * Statistics for both the LocalLRUClockHand. Note that all its instance fields are * <code>final</code>. Thus, we do not need to worry about refreshing an instance when it resides in * shared memory. */ public class LRUStatistics { /** The Statistics object that we delegate most behavior to */ private final Statistics stats; protected int limitId; /** * the number of destroys that must occur before a list scan is initiated to to remove unlinked * entries. */ protected int destroysLimitId; protected int counterId; /** entries that have been evicted from the LRU list */ protected int evictionsId; /** entries that have been destroyed, but not yet evicted from the LRU list */ protected int destroysId; protected int evaluationsId; protected int greedyReturnsId; // Note: the following atomics have been added so that the LRU code // does not depend on the value of a statistic for its operations. // In particular they optimize the "get" methods for these items. // Striped stats optimize inc but cause set and get to be more expensive. private final AtomicLong counter = new AtomicLong(); private final AtomicLong limit = new AtomicLong(); private final AtomicLong destroysLimit = new AtomicLong(); private final AtomicLong destroys = new AtomicLong(); private final AtomicLong evictions = new AtomicLong(); ///////////////////////// Constructors ///////////////////////// /** * Constructor for the LRUStatistics object * * @param name Description of the Parameter */ public LRUStatistics(StatisticsFactory factory, String name, EnableLRU helper) { String statName = helper.getStatisticsName() + "-" + name; stats = factory.createAtomicStatistics(helper.getStatisticsType(), statName); if (!helper.getEvictionAlgorithm().isLRUHeap()) { limitId = helper.getLimitStatId(); } destroysLimitId = helper.getDestroysLimitStatId(); counterId = helper.getCountStatId(); evictionsId = helper.getEvictionsStatId(); destroysId = helper.getDestroysStatId(); this.evaluationsId = helper.getEvaluationsStatId(); this.greedyReturnsId = helper.getGreedyReturnsStatId(); } public LRUStatistics(StatisticsFactory factory, String name, StatisticsType statisticsType) { stats = factory.createAtomicStatistics(statisticsType, name); limitId = 0; destroysLimitId = 0; counterId = 0; evictionsId = 0; destroysId = 0; this.evaluationsId = 0; this.greedyReturnsId = 0; } public void close() { stats.close(); } /** common counter for different lru types */ public long getCounter() { return this.counter.get(); } /** limit */ public void setLimit(long newValue) { Assert.assertTrue(newValue > 0L, "limit must be positive, an attempt was made to set it to: " + newValue); long oldValue = this.limit.get(); if (oldValue != newValue) { this.limit.set(newValue); stats.setLong(limitId, newValue); } } /** destroy limit */ public void setDestroysLimit(long newValue) { Assert.assertTrue(newValue > 0L, "destroys limit must be positive, an attempt was made to set it to: " + newValue); long oldValue = this.destroysLimit.get(); if (oldValue != newValue) { this.destroysLimit.set(newValue); stats.setLong(destroysLimitId, newValue); } } public long getLimit() { return this.limit.get(); } public long getDestroysLimit() { return this.destroysLimit.get(); } public void updateCounter(long delta) { if (delta != 0) { this.counter.getAndAdd(delta); stats.incLong(counterId, delta); } } public void resetCounter() { if (this.counter.get() != 0) { this.counter.set(0); stats.setLong(counterId, 0); } } // public void setCounter(long newValue) { // long oldValue = this.counter.get(); // if (oldValue != newValue) { // this.counter.set(oldValue+newValue); // stats.setLong(counterId, newValue); // } // } // public void decrementCounter(long delta) { if (delta != 0) { this.counter.addAndGet(-delta); stats.setLong(counterId, counter.get()); } } public void incEvictions() { this.evictions.getAndAdd(1); stats.incLong(evictionsId, 1); } public void incEvictions(long delta) { this.evictions.getAndAdd(delta); stats.incLong(evictionsId, delta); } public long getEvictions() { return this.evictions.get(); } public void resetDestroys() { if (this.destroys.get() != 0) { this.destroys.set(0); stats.setLong(destroysId, 0); } } public void incDestroys() { this.destroys.getAndAdd(1); stats.incLong(destroysId, 1); } public long getDestroys() { return this.destroys.get(); } public void incEvaluations(long numEvals) { stats.incLong(evaluationsId, numEvals); } public void incGreedyReturns(long numEvals) { stats.incLong(greedyReturnsId, numEvals); } public Statistics getStats() { return this.stats; } }