001: /*
002: * The contents of this file are subject to the Sapient Public License
003: * Version 1.0 (the "License"); you may not use this file except in compliance
004: * with the License. You may obtain a copy of the License at
005: * http://carbon.sf.net/License.html.
006: *
007: * Software distributed under the License is distributed on an "AS IS" basis,
008: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
009: * the specific language governing rights and limitations under the License.
010: *
011: * The Original Code is The Carbon Component Framework.
012: *
013: * The Initial Developer of the Original Code is Sapient Corporation
014: *
015: * Copyright (C) 2003 Sapient Corporation. All Rights Reserved.
016: */
017:
018: package org.sape.carbon.services.cache.mru;
019:
020: import org.sape.carbon.core.component.ComponentConfiguration;
021: import org.sape.carbon.services.cache.CacheLoadException;
022:
023: import org.apache.commons.logging.Log;
024: import org.apache.commons.logging.LogFactory;
025:
026: /**
027: * Extends AbsractMRUCache to provide the get method
028: *
029: * Copyright 2002 Sapient
030: * @since carbon 1.0
031: * @author Doug Voet, April 2002
032: * @version $Revision: 1.9 $($Author: dvoet $ / $Date: 2003/05/05 21:21:07 $)
033: */
034: public class DefaultMRUCacheImpl extends AbstractMRUCache {
035: /** Holds the loader used to load this cache. */
036: protected MRUCacheDataLoader dataLoader;
037:
038: /** The handle to Apache-commons logger */
039: private Log log = LogFactory.getLog(this .getClass());
040:
041: /**
042: * Configures the component with a <code>MRUCacheConfiguration</code>.
043: *
044: * @param configuration <code>MRUCacheConfiguration</code> used to
045: * configure the component.
046: */
047: public void configure(ComponentConfiguration configuration) {
048: super .configure(configuration);
049: this .dataLoader = ((MRUCacheConfiguration) configuration)
050: .getDataLoader();
051: }
052:
053: /**
054: * <p>For a given key value, return the object associated with the key
055: * value from the cache. If the value is not found in the cache OR if the
056: * value in the cache has expired, the cache will attempt to load it from
057: * the DataLoader. If the DataLoader returns a null value, a null value
058: * will be stored in the cache and returned to the caller.</p>
059: *
060: * <p>Unlike other methods on the MRUCache class, this method is not
061: * synchronized at the method level. It is, however, synchronized within the
062: * method. The purpose of this is to allow the cache to continue servicing
063: * requests while it is loading data from the DataLoader. All other
064: * activities in this method are synchronized, but the load of data from the
065: * MRUCacheDataLoader is unsycnchronized, and will not stop other threads
066: * from reading from the cache, or loading other datums.</p>
067: *
068: * @param key the key for the desired cache entry
069: * @return <code>Object</code> the cached object
070: */
071: public Object get(Object key) {
072: Object value = getObject(key);
073:
074: // If it's not there...get it from the dataloader and put it
075: // into the cache. Note that this step is not synchronized!
076: if (value == null) {
077: this .cacheMisses++;
078:
079: try {
080: value = this .dataLoader.loadDatum(key);
081:
082: // Seeing as how we just had a cache miss, check to see if we
083: // are loggin detailed information. If we are, then log
084: // information about the cache hit rate statistics.
085: if (log.isDebugEnabled()) {
086: log.debug("missed on cache: " + this .toString());
087: }
088:
089: synchronized (this ) {
090: // Now that we have loaded from the external source, do the
091: // double-check, and if nobody else put it into the cache in
092: // the mean time, drop it in!
093: if (this .map.get(key) == null) {
094: put(key, value);
095: }
096: }
097: } catch (CacheLoadException cle) {
098: if (log.isWarnEnabled()) {
099: log.warn("Caught CacheLoadException loading datum "
100: + "with key [" + key
101: + "], returning null: " + cle);
102: }
103: }
104: }
105:
106: // Finally return the value that we found either from the cache or
107: // the DataLoader
108: return value;
109: }
110: }
|