package org.infinispan.jcache.embedded; import java.io.Serializable; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import javax.cache.management.CacheStatisticsMXBean; import org.infinispan.AdvancedCache; import org.infinispan.stats.Stats; /** * The reference implementation of {@link CacheStatisticsMXBean}. */ public class RICacheStatistics implements CacheStatisticsMXBean, Serializable { private static final long serialVersionUID = -5589437411679003894L; private final AdvancedCache<?, ?> cache; private final AtomicLong unsupportCacheHits = new AtomicLong(); private final AtomicLong unsupportCacheGetTotalTime = new AtomicLong(); /** * Constructs a cache statistics object * * @param cache the associated cache */ public RICacheStatistics(AdvancedCache<?, ?> cache) { this.cache = cache; } /** * {@inheritDoc} * <p/> * Statistics will also automatically be cleared if internal counters * overflow. */ @Override public void clear() { cache.getStats().reset(); } /** * @return the number of hits */ @Override public long getCacheHits() { return mapToSpecValidStat(cache.getStats().getHits() + unsupportCacheHits.longValue()); } /** * Returns cache hits as a percentage of total gets. * * @return the percentage of successful hits, as a decimal */ @Override public float getCacheHitPercentage() { long hits = getCacheHits(); if (hits == 0) return 0; return (float) hits / getCacheGets() * 100.0f; } /** * @return the number of misses */ @Override public long getCacheMisses() { return mapToSpecValidStat(cache.getStats().getMisses()); } /** * Returns cache misses as a percentage of total gets. * * @return the percentage of accesses that failed to find anything */ @Override public float getCacheMissPercentage() { long misses = getCacheMisses(); if (misses == 0) return 0; return (float) misses / getCacheGets() * 100.0f; } /** * The total number of requests to the cache. This will be equal to the sum * of the hits and misses. * <p/> * A "get" is an operation that returns the current or previous value. * * @return the number of hits */ @Override public long getCacheGets() { Stats stats = cache.getStats(); return stats.getHits() + stats.getMisses() + unsupportCacheHits.longValue(); } /** * The total number of puts to the cache. * <p/> * A put is counted even if it is immediately evicted. A replace includes a * put and remove. * * @return the number of hits */ @Override public long getCachePuts() { return mapToSpecValidStat(cache.getStats().getStores()); } /** * The total number of removals from the cache. This does not include * evictions, where the cache itself initiates the removal to make space. * <p/> * * @return the number of removals */ @Override public long getCacheRemovals() { Stats stats = cache.getStats(); return mapToSpecValidStat(stats.getRemoveHits()); } /** * @return the number of evictions from the cache */ @Override public long getCacheEvictions() { return mapToSpecValidStat(cache.getStats().getEvictions()); } /** * The mean time to execute gets. * <p/> * In a read-through cache the time taken to load an entry on miss is not included in get time. * * @return the time in µs */ @Override public float getAverageGetTime() { long unsupportedCacheGetTotalMillis = TimeUnit.NANOSECONDS.toMillis(unsupportCacheGetTotalTime.longValue()); return TimeUnit.MILLISECONDS.toMicros(mapToSpecValidStat( cache.getStats().getAverageReadTime() + unsupportedCacheGetTotalMillis)); } /** * The mean time to execute puts. * * @return the time in µs */ @Override public float getAveragePutTime() { return TimeUnit.MILLISECONDS.toMicros( mapToSpecValidStat(cache.getStats().getAverageWriteTime())); } /** * The mean time to execute removes. * * @return the time in µs */ @Override public float getAverageRemoveTime() { return TimeUnit.MILLISECONDS.toMicros( mapToSpecValidStat(cache.getStats().getAverageRemoveTime())); } //TODO: was package-level initially public void increaseCacheHits(long number) { unsupportCacheHits.getAndAdd(number); } //TODO: was package-level initially public void addGetTimeNano(long duration) { if (unsupportCacheGetTotalTime.get() <= Long.MAX_VALUE - duration) { unsupportCacheGetTotalTime.addAndGet(duration); } else { //counter full. Just reset. clear(); unsupportCacheGetTotalTime.set(duration); } } /** * Maps an Infinispan statistic to a value that's * accepted by the JCache specification. * * @param stat original Infinispan statistic * @return a JCache specification valid statistic */ private long mapToSpecValidStat(long stat) { return stat < 0 ? 0 : stat; } }