54
54
* configured in the cache.
56
56
* @author <a href="mailto:ssuravarapu@users.sourceforge.net">Surya Suravarapu</a>
57
* @version $Id: MemoryStore.java 4919 2011-11-03 16:36:33Z asingh $
57
* @version $Id: MemoryStore.java 7369 2013-04-10 17:49:29Z cdennis $
59
59
public class MemoryStore extends AbstractStore implements TierableStore, PoolableStore, CacheConfigurationListener {
89
89
private final RateStatistic hitRate = new AtomicRateStatistic(1000, TimeUnit.MILLISECONDS);
90
90
private final RateStatistic missRate = new AtomicRateStatistic(1000, TimeUnit.MILLISECONDS);
92
private final boolean cachePinned;
92
private final boolean storePinned;
93
93
private final boolean elementPinningEnabled;
114
114
private volatile CacheLockProvider lockProvider;
115
private final boolean tierPinned;
118
117
* Constructs things that all MemoryStores have in common.
120
119
* @param cache the cache
121
120
* @param pool the pool tracking the on-heap usage
122
* @param doNotifications whether to notify the Cache's EventNotificationService on eviction and expiry
121
* @param notify whether to notify the Cache's EventNotificationService on eviction and expiry
124
protected MemoryStore(final Ehcache cache, Pool pool, final boolean doNotifications) {
123
protected MemoryStore(Ehcache cache, Pool pool, boolean notify, BackingFactory factory) {
125
124
status = Status.STATUS_UNINITIALISED;
126
125
this.cache = cache;
127
126
this.maximumSize = (int) cache.getCacheConfiguration().getMaxEntriesLocalHeap();
132
131
SizeOfPolicyConfiguration.resolveBehavior(cache).equals(SizeOfPolicyConfiguration.MaxDepthExceededBehavior.ABORT));
134
133
this.alwaysPutOnHeap = getAdvancedBooleanConfigProperty("alwaysPutOnHeap", cache.getCacheConfiguration().getName(), false);
135
this.cachePinned = determineCachePinned(cache.getCacheConfiguration());
136
this.tierPinned = cache.getCacheConfiguration().getPinningConfiguration() != null
137
&& cache.getCacheConfiguration()
138
.getPinningConfiguration()
139
.getStore() == PinningConfiguration.Store.LOCALHEAP;
134
this.storePinned = determineStorePinned(cache.getCacheConfiguration());
141
136
this.elementPinningEnabled = !cache.getCacheConfiguration().isOverflowToOffHeap();
143
// create the CHM with initialCapacity sufficient to hold maximumSize
144
final float loadFactor = maximumSize == 1 ? 1 : DEFAULT_LOAD_FACTOR;
145
int initialCapacity = getInitialCapacityForLoadFactor(maximumSize, loadFactor);
146
map = new SelectableConcurrentHashMap(poolAccessor, elementPinningEnabled, initialCapacity,
147
loadFactor, CONCURRENCY_LEVEL, isClockEviction() && !cachePinned ? maximumSize : 0,
148
doNotifications ? cache.getCacheEventNotificationService() : null);
150
status = Status.STATUS_ALIVE;
137
int maximumCapacity = isClockEviction() && !storePinned ? maximumSize : 0;
138
RegisteredEventListeners eventListener = notify ? cache.getCacheEventNotificationService() : null;
139
if (Boolean.getBoolean(MemoryStore.class.getName() + ".presize")) {
140
// create the CHM with initialCapacity sufficient to hold maximumSize
141
final float loadFactor = maximumSize == 1 ? 1 : DEFAULT_LOAD_FACTOR;
142
int initialCapacity = getInitialCapacityForLoadFactor(maximumSize, loadFactor);
143
this.map = factory.newBackingMap(poolAccessor, elementPinningEnabled, initialCapacity,
144
loadFactor, CONCURRENCY_LEVEL, maximumCapacity, eventListener);
146
this.map = factory.newBackingMap(poolAccessor, elementPinningEnabled, CONCURRENCY_LEVEL, maximumCapacity, eventListener);
149
this.status = Status.STATUS_ALIVE;
152
151
if (LOG.isDebugEnabled()) {
153
152
LOG.debug("Initialized " + this.getClass().getName() + " for " + cache.getName());
157
private boolean determineCachePinned(CacheConfiguration cacheConfiguration) {
156
private boolean determineStorePinned(CacheConfiguration cacheConfiguration) {
158
157
PinningConfiguration pinningConfiguration = cacheConfiguration.getPinningConfiguration();
159
158
if (pinningConfiguration == null) {
183
182
* @return the calculated initialCapacity. Returns 0 if the parameter <tt>maximumSizeGoal</tt> is less than or equal
186
static int getInitialCapacityForLoadFactor(int maximumSizeGoal, float loadFactor) {
185
protected static int getInitialCapacityForLoadFactor(int maximumSizeGoal, float loadFactor) {
187
186
double actualMaximum = Math.ceil(maximumSizeGoal / loadFactor);
188
187
return Math.max(0, actualMaximum >= Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) actualMaximum);
196
195
* @return an instance of a MemoryStore, configured with the appropriate eviction policy
198
197
public static MemoryStore create(final Ehcache cache, Pool pool) {
199
MemoryStore memoryStore = new MemoryStore(cache, pool, false);
198
MemoryStore memoryStore = new MemoryStore(cache, pool, false, new BasicBackingFactory());
200
199
cache.getCacheConfiguration().addConfigurationListener(memoryStore);
201
200
return memoryStore;
276
public final boolean putWithWriter(Element element, CacheWriterManager writerManager) throws CacheException {
272
public boolean putWithWriter(Element element, CacheWriterManager writerManager) throws CacheException {
277
273
long delta = poolAccessor.add(element.getObjectKey(), element.getObjectValue(), map.storedObject(element), isPinningEnabled(element));
278
274
if (delta > -1) {
279
275
Element old = map.put(element.getObjectKey(), element, delta);
1056
1065
map.recalculateSize(key);
1069
* Factory interface to create a MemoryStore backing.
1071
protected interface BackingFactory {
1073
* Create a MemoryStore backing map.
1075
* @param poolAccessor on-heap pool accessor
1076
* @param elementPinning element pinning in this store
1077
* @param initialCapacity initial store capacity
1078
* @param loadFactor map load factor
1079
* @param concurrency map concurrency
1080
* @param maximumCapacity maximum store capacity
1081
* @param eventListener event listener (or {@code null} for no notifications)
1082
* @return a backing map
1085
SelectableConcurrentHashMap newBackingMap(PoolAccessor<?> poolAccessor, boolean elementPinning, int initialCapacity,
1086
float loadFactor, int concurrency, int maximumCapacity, RegisteredEventListeners eventListener);
1089
* Create a MemoryStore backing map.
1091
* @param poolAccessor on-heap pool accessor
1092
* @param concurrency map concurrency
1093
* @param maximumCapacity maximum store capacity
1094
* @param eventListener event listener (or {@code null} for no notifications)
1095
* @return a backing map
1097
SelectableConcurrentHashMap newBackingMap(PoolAccessor<?> poolAccessor, boolean elementPinning, int concurrency,
1098
int maximumCapacity, RegisteredEventListeners eventListener);
1102
* Simple backing map factory.
1104
static class BasicBackingFactory implements BackingFactory {
1107
public SelectableConcurrentHashMap newBackingMap(PoolAccessor<?> poolAccessor, boolean elementPinning,
1108
int concurrency, int maximumCapacity, RegisteredEventListeners eventListener) {
1109
return new SelectableConcurrentHashMap(poolAccessor, elementPinning, concurrency, maximumCapacity, eventListener);
1113
public SelectableConcurrentHashMap newBackingMap(PoolAccessor poolAccessor, boolean elementPinning, int initialCapacity,
1114
float loadFactor, int concurrency, int maximumCapacity, RegisteredEventListeners eventListener) {
1115
return new SelectableConcurrentHashMap(poolAccessor, elementPinning, initialCapacity,
1116
loadFactor, concurrency, maximumCapacity, eventListener);