package io.ebean.datasource.pool;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.Map;

A LRU based cache for PreparedStatements.
/** * A LRU based cache for PreparedStatements. */
class PstmtCache extends LinkedHashMap<String, ExtendedPreparedStatement> { private static final Logger logger = LoggerFactory.getLogger(PstmtCache.class); static final long serialVersionUID = -3096406924865550697L;
The maximum size of the cache. When this is exceeded the oldest entry is removed.
/** * The maximum size of the cache. When this is exceeded the oldest entry is removed. */
private final int maxSize;
The total number of entries removed from this cache.
/** * The total number of entries removed from this cache. */
private int removeCounter;
The number of get hits.
/** * The number of get hits. */
private int hitCounter;
The number of get() misses.
/** * The number of get() misses. */
private int missCounter;
The number of puts into this cache.
/** * The number of puts into this cache. */
private int putCounter; PstmtCache(int maxCacheSize) { // note = access ordered list. This is what gives it the LRU order super(maxCacheSize * 3, 0.75f, true); this.maxSize = maxCacheSize; }
Return a summary description of this cache.
/** * Return a summary description of this cache. */
String getDescription() { return "size[" + size() + "] max[" + maxSize + "] hits[" + hitCounter + "] miss[" + missCounter + "] hitRatio[" + getHitRatio() + "] removes[" + removeCounter + "]"; }
returns the current maximum size of the cache.
/** * returns the current maximum size of the cache. */
public int getMaxSize() { return maxSize; }
Gets the hit ratio. A number between 0 and 100 indicating the number of hits to misses. A number approaching 100 is desirable.
/** * Gets the hit ratio. A number between 0 and 100 indicating the number of * hits to misses. A number approaching 100 is desirable. */
private int getHitRatio() { if (hitCounter == 0) { return 0; } else { return hitCounter * 100 / (hitCounter + missCounter); } }
The total number of hits against this cache.
/** * The total number of hits against this cache. */
public int getHitCounter() { return hitCounter; }
The total number of misses against this cache.
/** * The total number of misses against this cache. */
public int getMissCounter() { return missCounter; }
The total number of puts against this cache.
/** * The total number of puts against this cache. */
public int getPutCounter() { return putCounter; }
Try to add the returning statement to the cache. If there is already a matching ExtendedPreparedStatement in the cache return false else add the statement to the cache and return true.
/** * Try to add the returning statement to the cache. If there is already a * matching ExtendedPreparedStatement in the cache return false else add * the statement to the cache and return true. */
boolean returnStatement(ExtendedPreparedStatement stmt) { ExtendedPreparedStatement alreadyInCache = super.get(stmt.getCacheKey()); if (alreadyInCache != null) { return false; } // add the returning prepared statement to the cache. // Note that the LRUCache will automatically close fully old unused // statements when the cache has hit its maximum size. put(stmt.getCacheKey(), stmt); return true; }
additionally maintains hit and miss statistics.
/** * additionally maintains hit and miss statistics. */
public ExtendedPreparedStatement get(Object key) { ExtendedPreparedStatement o = super.get(key); if (o == null) { missCounter++; } else { hitCounter++; } return o; }
additionally maintains hit and miss statistics.
/** * additionally maintains hit and miss statistics. */
public ExtendedPreparedStatement remove(Object key) { ExtendedPreparedStatement o = super.remove(key); if (o == null) { missCounter++; } else { hitCounter++; } return o; }
additionally maintains put counter statistics.
/** * additionally maintains put counter statistics. */
public ExtendedPreparedStatement put(String key, ExtendedPreparedStatement value) { putCounter++; return super.put(key, value); }
will check to see if we need to remove entries and if so call the cacheCleanup.cleanupEldestLRUCacheEntry() if one has been set.
/** * will check to see if we need to remove entries and * if so call the cacheCleanup.cleanupEldestLRUCacheEntry() if * one has been set. */
protected boolean removeEldestEntry(Map.Entry<String, ExtendedPreparedStatement> eldest) { if (size() < maxSize) { return false; } removeCounter++; try { ExtendedPreparedStatement stmt = eldest.getValue(); stmt.closeDestroy(); } catch (SQLException e) { logger.error("Error closing ExtendedPreparedStatement", e); } return true; } }