~ubuntu-branches/ubuntu/trusty/ehcache/trusty

« back to all changes in this revision

Viewing changes to src/main/java/net/sf/ehcache/store/MemoryStore.java

  • Committer: Package Import Robot
  • Author(s): Emmanuel Bourg
  • Date: 2013-05-06 14:53:07 UTC
  • mfrom: (1.1.7) (2.1.8 sid)
  • Revision ID: package-import@ubuntu.com-20130506145307-v5bhw5yu70re00l3
Tags: 2.6.7-1
* Team upload.
* New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/**
2
 
 *  Copyright 2003-2010 Terracotta, Inc.
 
2
 *  Copyright Terracotta, Inc.
3
3
 *
4
4
 *  Licensed under the Apache License, Version 2.0 (the "License");
5
5
 *  you may not use this file except in compliance with the License.
54
54
 * configured in the cache.
55
55
 *
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 $
58
58
 */
59
59
public class MemoryStore extends AbstractStore implements TierableStore, PoolableStore, CacheConfigurationListener {
60
60
 
89
89
    private final RateStatistic hitRate = new AtomicRateStatistic(1000, TimeUnit.MILLISECONDS);
90
90
    private final RateStatistic missRate = new AtomicRateStatistic(1000, TimeUnit.MILLISECONDS);
91
91
 
92
 
    private final boolean cachePinned;
 
92
    private final boolean storePinned;
93
93
    private final boolean elementPinningEnabled;
94
94
 
95
95
    /**
112
112
     */
113
113
 
114
114
    private volatile CacheLockProvider lockProvider;
115
 
    private final boolean tierPinned;
116
115
 
117
116
    /**
118
117
     * Constructs things that all MemoryStores have in common.
119
118
     *
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
123
122
     */
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));
133
132
 
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());
140
135
 
141
136
        this.elementPinningEnabled = !cache.getCacheConfiguration().isOverflowToOffHeap();
142
 
 
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);
149
 
 
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);
 
145
        } else {
 
146
            this.map = factory.newBackingMap(poolAccessor, elementPinningEnabled, CONCURRENCY_LEVEL, maximumCapacity, eventListener);
 
147
        }
 
148
 
 
149
        this.status = Status.STATUS_ALIVE;
151
150
 
152
151
        if (LOG.isDebugEnabled()) {
153
152
            LOG.debug("Initialized " + this.getClass().getName() + " for " + cache.getName());
154
153
        }
155
154
    }
156
155
 
157
 
    private boolean determineCachePinned(CacheConfiguration cacheConfiguration) {
 
156
    private boolean determineStorePinned(CacheConfiguration cacheConfiguration) {
158
157
        PinningConfiguration pinningConfiguration = cacheConfiguration.getPinningConfiguration();
159
158
        if (pinningConfiguration == null) {
160
159
            return false;
168
167
                return !cacheConfiguration.isOverflowToOffHeap();
169
168
 
170
169
            case INCACHE:
171
 
                return !(cacheConfiguration.isOverflowToOffHeap() || cacheConfiguration.isOverflowToDisk() || cacheConfiguration.isDiskPersistent());
 
170
                return !cacheConfiguration.isOverflowToOffHeap() && !cacheConfiguration.isOverflowToDisk();
172
171
 
173
172
            default:
174
173
                throw new IllegalArgumentException();
183
182
     * @return the calculated initialCapacity. Returns 0 if the parameter <tt>maximumSizeGoal</tt> is less than or equal
184
183
     *         to 0
185
184
     */
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);
189
188
    }
196
195
     * @return an instance of a MemoryStore, configured with the appropriate eviction policy
197
196
     */
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;
202
201
    }
 
202
 
203
203
    /**
204
204
     * {@inheritDoc}
205
205
     */
226
226
    }
227
227
 
228
228
    private boolean isPinningEnabled(Element element) {
229
 
        return cachePinned || (elementPinningEnabled && isPinned(element.getObjectKey()));
 
229
        return storePinned || isPinned(element.getObjectKey());
230
230
    }
231
231
 
232
232
    /**
241
241
    /**
242
242
     * {@inheritDoc}
243
243
     */
244
 
    public boolean removeIfTierNotPinned(final Object key) {
245
 
        return !tierPinned && remove(key) != null;
 
244
    public boolean removeIfNotPinned(final Object key) {
 
245
        return !storePinned && !isPinned(key) && remove(key) != null;
246
246
    }
247
247
 
248
248
    /**
258
258
        long delta = poolAccessor.add(element.getObjectKey(), element.getObjectValue(), map.storedObject(element), isPinningEnabled(element));
259
259
        if (delta > -1) {
260
260
            Element old = map.put(element.getObjectKey(), element, delta);
261
 
            if (old == null) {
262
 
                checkCapacity(element);
263
 
                return true;
264
 
            } else {
265
 
                return false;
266
 
            }
 
261
            checkCapacity(element);
 
262
            return old == null;
267
263
        } else {
268
264
            notifyDirectEviction(element);
269
265
            return true;
273
269
    /**
274
270
     * {@inheritDoc}
275
271
     */
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);
284
280
                    throw new StoreUpdateException(e, old != null);
285
281
                }
286
282
            }
287
 
            if (old == null) {
288
 
                checkCapacity(element);
289
 
                return true;
290
 
            } else {
291
 
                return false;
292
 
            }
 
283
            checkCapacity(element);
 
284
            return old == null;
293
285
        } else {
294
286
            notifyDirectEviction(element);
295
287
            return true;
308
300
        if (key == null) {
309
301
            return null;
310
302
        } else {
311
 
            Element e = map.get(key);
312
 
            boolean sentinelElementFound = (e != null) && (e.equals(SelectableConcurrentHashMap.DUMMY_PINNED_ELEMENT));
313
 
            if (sentinelElementFound) {
314
 
                e = null;
315
 
            }
 
303
            final Element e = map.get(key);
316
304
            if (e == null) {
317
305
                missRate.event();
318
306
            } else {
356
344
    /**
357
345
     * {@inheritDoc}
358
346
     */
 
347
    public boolean isTierPinned() {
 
348
        return storePinned;
 
349
    }
 
350
 
 
351
    /**
 
352
     * {@inheritDoc}
 
353
     */
 
354
    public Set getPresentPinnedKeys() {
 
355
        return map.pinnedKeySet();
 
356
    }
 
357
 
 
358
    /**
 
359
     * {@inheritDoc}
 
360
     */
 
361
    public boolean isPersistent() {
 
362
        return false;
 
363
    }
 
364
 
 
365
    /**
 
366
     * {@inheritDoc}
 
367
     */
359
368
    public final Element removeWithWriter(Object key, CacheWriterManager writerManager) throws CacheException {
360
369
        if (key == null) {
361
370
            return null;
445
454
    /**
446
455
     * Flush to disk only if the cache is diskPersistent.
447
456
     */
448
 
    public final void flush() {
 
457
    public void flush() {
449
458
        if (cache.getCacheConfiguration().isClearOnFlush()) {
450
459
            removeAll();
451
460
        }
664
673
     */
665
674
    public void memoryCapacityChanged(int oldCapacity, int newCapacity) {
666
675
        maximumSize = newCapacity;
667
 
        if (isClockEviction() && !cachePinned) {
 
676
        if (isClockEviction() && !storePinned) {
668
677
            map.setMaxSize(maximumSize);
669
678
        }
670
679
    }
940
949
     * {@inheritDoc}
941
950
     */
942
951
    public boolean evictFromOnHeap(int count, long size) {
943
 
        if (cachePinned) {
 
952
        if (storePinned) {
944
953
            return false;
945
954
        }
946
955
 
1055
1064
        }
1056
1065
        map.recalculateSize(key);
1057
1066
    }
 
1067
 
 
1068
    /**
 
1069
     * Factory interface to create a MemoryStore backing.
 
1070
     */
 
1071
    protected interface BackingFactory {
 
1072
        /**
 
1073
         * Create a MemoryStore backing map.
 
1074
         *
 
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
 
1083
         */
 
1084
        @Deprecated
 
1085
        SelectableConcurrentHashMap newBackingMap(PoolAccessor<?> poolAccessor, boolean elementPinning, int initialCapacity,
 
1086
                float loadFactor, int concurrency, int maximumCapacity, RegisteredEventListeners eventListener);
 
1087
 
 
1088
        /**
 
1089
         * Create a MemoryStore backing map.
 
1090
         *
 
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
 
1096
         */
 
1097
        SelectableConcurrentHashMap newBackingMap(PoolAccessor<?> poolAccessor, boolean elementPinning, int concurrency,
 
1098
                int maximumCapacity, RegisteredEventListeners eventListener);
 
1099
    }
 
1100
 
 
1101
    /**
 
1102
     * Simple backing map factory.
 
1103
     */
 
1104
    static class BasicBackingFactory implements BackingFactory {
 
1105
 
 
1106
        @Override
 
1107
        public SelectableConcurrentHashMap newBackingMap(PoolAccessor<?> poolAccessor, boolean elementPinning,
 
1108
                int concurrency, int maximumCapacity, RegisteredEventListeners eventListener) {
 
1109
            return new SelectableConcurrentHashMap(poolAccessor, elementPinning, concurrency, maximumCapacity, eventListener);
 
1110
        }
 
1111
 
 
1112
        @Override
 
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);
 
1117
        }
 
1118
    }
1058
1119
}
1059
1120