package com.googlecode.objectify.impl; import com.google.appengine.api.datastore.Key; import com.googlecode.objectify.cache.MemcacheStats; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; /** * Tracks hit/miss statistics for the memcache. */ public class EntityMemcacheStats implements MemcacheStats { /** */ public class Stat { private AtomicLong hits = new AtomicLong(); private AtomicLong misses = new AtomicLong(); public long getHits() { return this.hits.get(); } public long getMisses() { return this.misses.get(); } public float getPercent() { long h = this.getHits(); long m = this.getMisses(); long total = h + m; if (total == 0) return 0; else return (float)h / (float)total; } } /** */ private Map<String, Stat> stats = new ConcurrentHashMap<>(); /** * Get the live statistics. You can clear it if you want. * * @return the live map, but you can iterate through it just fine */ public Map<String, Stat> getStats() { return this.stats; } /** */ @Override public void recordHit(Key key) { this.getStat(key.getKind()).hits.incrementAndGet(); } /** */ @Override public void recordMiss(Key key) { this.getStat(key.getKind()).misses.incrementAndGet(); } /** * We're just tracking statistics so we don't really need to worry about these stepping on each other; * if there's a hit or miss lost no big deal. */ private Stat getStat(String kind) { Stat stat = this.stats.get(kind); if (stat == null) { stat = new Stat(); this.stats.put(kind, stat); } return stat; } }