~ubuntu-branches/ubuntu/oneiric/ehcache/oneiric

« back to all changes in this revision

Viewing changes to core/src/main/java/net/sf/ehcache/constructs/blocking/UpdatingSelfPopulatingCache.java

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Werner
  • Date: 2010-06-23 10:35:31 UTC
  • mfrom: (1.1.5 upstream) (2.1.6 sid)
  • Revision ID: james.westby@ubuntu.com-20100623103531-ra0qdpmotoz6ygct
Tags: 2.1.0-1
Merge changes from Thierry's PPA and upload to Debian.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**
2
 
 *  Copyright 2003-2009 Terracotta, Inc.
3
 
 *
4
 
 *  Licensed under the Apache License, Version 2.0 (the "License");
5
 
 *  you may not use this file except in compliance with the License.
6
 
 *  You may obtain a copy of the License at
7
 
 *
8
 
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 
 *
10
 
 *  Unless required by applicable law or agreed to in writing, software
11
 
 *  distributed under the License is distributed on an "AS IS" BASIS,
12
 
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 
 *  See the License for the specific language governing permissions and
14
 
 *  limitations under the License.
15
 
 */
16
 
 
17
 
package net.sf.ehcache.constructs.blocking;
18
 
 
19
 
 
20
 
import net.sf.ehcache.CacheException;
21
 
import net.sf.ehcache.Ehcache;
22
 
import net.sf.ehcache.Element;
23
 
import net.sf.ehcache.concurrent.Mutex;
24
 
 
25
 
import java.util.logging.Level;
26
 
import java.util.logging.Logger;
27
 
 
28
 
 
29
 
/**
30
 
 * A {@link net.sf.ehcache.Cache} backed cache that creates entries on demand.
31
 
 * <p/>
32
 
 * Clients of the cache simply call it without needing knowledge of whether
33
 
 * the entry exists in the cache, or whether it needs updating before use.
34
 
 * <p/>
35
 
 * <p/>
36
 
 * Thread safety depends on the factory being used. The UpdatingCacheEntryFactory should be made
37
 
 * thread safe. In addition users of returned values should not modify their contents.
38
 
 *
39
 
 * @author Greg Luck
40
 
 * @version $Id: UpdatingSelfPopulatingCache.java 1012 2009-08-20 04:23:00Z gregluck $
41
 
 */
42
 
public class UpdatingSelfPopulatingCache extends SelfPopulatingCache {
43
 
 
44
 
    private static final Logger LOG = Logger.getLogger(UpdatingSelfPopulatingCache.class.getName());
45
 
 
46
 
    /**
47
 
     * Creates a SelfPopulatingCache.
48
 
     */
49
 
    public UpdatingSelfPopulatingCache(Ehcache cache, final UpdatingCacheEntryFactory factory)
50
 
            throws CacheException {
51
 
        super(cache, factory);
52
 
    }
53
 
 
54
 
    /**
55
 
     * Looks up an object.
56
 
     * <p/>
57
 
     * If null, it creates it. If not null, it updates it. For performance this method should only be
58
 
     * used with {@link UpdatingCacheEntryFactory}'s
59
 
     * <p/>
60
 
     * It is expected that
61
 
     * gets, which update as part of the get, might take considerable time. Access to the cache cannot be blocked
62
 
     * while that is happening. This method is therefore not synchronized. Mutexes are used for thread safety based on key
63
 
     *
64
 
     * @param key
65
 
     * @return a value
66
 
     * @throws net.sf.ehcache.CacheException
67
 
     */
68
 
    public Element get(final Object key) throws LockTimeoutException {
69
 
 
70
 
        try {
71
 
 
72
 
            Ehcache backingCache = getCache();
73
 
            Element element = backingCache.get(key);
74
 
 
75
 
            if (element == null) {
76
 
                element = super.get(key);
77
 
            } else {
78
 
                Mutex lock = stripedMutex.getMutexForKey(key);
79
 
                try {
80
 
                    lock.acquire();
81
 
                    update(key);
82
 
                } finally {
83
 
                    lock.release();
84
 
                }
85
 
            }
86
 
            return element;
87
 
        } catch (final Throwable throwable) {
88
 
            // Could not fetch - Ditch the entry from the cache and rethrow
89
 
            put(new Element(key, null));
90
 
            throw new LockTimeoutException("Could not update object for cache entry with key \"" + key + "\".", throwable);
91
 
        }
92
 
    }
93
 
 
94
 
    /**
95
 
     * Element can never be null. Add a null guard just in case.
96
 
     * @param key
97
 
     */
98
 
    protected void update(final Object key) {
99
 
        try {
100
 
            Ehcache backingCache = getCache();
101
 
            final Element element = backingCache.getQuiet(key);
102
 
 
103
 
            if (element == null) {
104
 
                if (LOG.isLoggable(Level.FINE)) {
105
 
                    LOG.fine(getName() + ": entry with key " + key + " has been removed - skipping it");
106
 
                }
107
 
                return;
108
 
            }
109
 
 
110
 
            refreshElement(element, backingCache);
111
 
        } catch (final Exception e) {
112
 
            // Collect the exception and keep going.
113
 
            // Throw the exception once all the entries have been refreshed
114
 
            // If the refresh fails, keep the old element. It will simply become staler.
115
 
            LOG.log(Level.WARNING, getName() + "Could not refresh element " + key, e);
116
 
        }
117
 
    }
118
 
 
119
 
    /**
120
 
     * This method should not be used. Because elements are always updated before they are
121
 
     * returned, it makes no sense to refresh this cache.
122
 
     */
123
 
    public void refresh() throws CacheException {
124
 
        throw new CacheException("UpdatingSelfPopulatingCache objects should not be refreshed.");
125
 
    }
126
 
 
127
 
}