You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jcs-dev@jakarta.apache.org by hc...@apache.org on 2005/02/01 11:34:29 UTC

cvs commit: jakarta-turbine-jcs/sandbox/yajcache/src/org/apache/jcs/yajcache/core CacheManager.java CacheManagerUtils.java SafeCacheManager.java

hchar       2005/02/01 02:34:29

  Modified:    sandbox/yajcache/src/org/apache/jcs/yajcache/core
                        CacheManager.java
  Removed:     sandbox/yajcache/src/org/apache/jcs/yajcache/core
                        CacheManagerUtils.java SafeCacheManager.java
  Log:
  simplify + unify into one CacheManager for all caches
  
  Revision  Changes    Path
  1.6       +157 -31   jakarta-turbine-jcs/sandbox/yajcache/src/org/apache/jcs/yajcache/core/CacheManager.java
  
  Index: CacheManager.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-jcs/sandbox/yajcache/src/org/apache/jcs/yajcache/core/CacheManager.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- CacheManager.java	29 Jan 2005 12:37:00 -0000	1.5
  +++ CacheManager.java	1 Feb 2005 10:34:29 -0000	1.6
  @@ -18,12 +18,15 @@
   
   import java.util.concurrent.ConcurrentHashMap;
   import java.util.concurrent.ConcurrentMap;
  +import java.util.concurrent.locks.Lock;
  +
   import org.apache.jcs.yajcache.lang.annotation.*;
  -import org.apache.jcs.yajcache.config.PerCacheConfig;
  -import org.apache.jcs.yajcache.file.CacheFileManager;
  -import org.apache.jcs.yajcache.soft.SoftRefFileCache;
  +import org.apache.jcs.yajcache.util.concurrent.locks.IKeyedReadWriteLock;
  +import org.apache.jcs.yajcache.util.concurrent.locks.KeyedReadWriteLock;
   
   /**
  + * Cache Manager for getting, creating and removing named caches.
  + *
    * @author Hanson Char
    */
   // @CopyRightApache
  @@ -33,38 +36,112 @@
       // Cache name to Cache mapping.
       private final ConcurrentMap<String,ICache<?>> map = 
                   new ConcurrentHashMap<String, ICache<?>>();
  -    private final CacheType DEFAULT_CACHE_TYPE = CacheType.SOFT_REFERENCE_FILE;
  +    private final IKeyedReadWriteLock<String> keyedRWLock = 
  +            new KeyedReadWriteLock<String>();
       /** 
  -     * Returns the cache for the specified name and value type;  
  -     * Creates the cache if necessary.
  +     * Returns an existing cache for the specified name; 
  +     * or null if not found.
  +     */
  +    public ICache getCache(@NonNullable String name) {
  +        return this.map.get(name);
  +    }
  +    /** 
  +     * Returns an existing safe cache for the specified name; 
  +     * or null if such a safe cache cannot not found.
  +     */
  +    public ICacheSafe getSafeCache(@NonNullable String name) {
  +        ICache c = this.getCache(name);
  +        
  +        if (c == null || !(c instanceof ICacheSafe))
  +            return null;
  +        return (ICacheSafe)c;
  +    }
  +    /** 
  +     * Returns an existing cache for the specified name and value type;  
  +     * or null if not found.
        *
        * @throws ClassCastException if the cache already exists for an
        * incompatible value type.
        */
   //    @SuppressWarnings({"unchecked"})
  -    public @NonNullable <V> ICache<V> getCache(
  -            @NonNullable String name, 
  +    public <V> ICache<V> getCache(
  +            @NonNullable String name,
               @NonNullable Class<V> valueType)
       {
  -        return this.getCache(DEFAULT_CACHE_TYPE, name, valueType);
  +        ICache c = this.map.get(name);
  +        this.checkValueType(c, valueType);
  +        return c;
       }
  -    public @NonNullable <V> ICache<V> getCache(
  -            @NonNullable CacheType cacheType, 
  -            @NonNullable String name, 
  +    /** 
  +     * Returns an existing safe cache for the specified name and value type;  
  +     * or null such a safe cache cannot be found.
  +     *
  +     * @throws ClassCastException if the cache already exists for an
  +     * incompatible value type.
  +     */
  +    public <V> ICacheSafe<V> getSafeCache(
  +            @NonNullable String name,
               @NonNullable Class<V> valueType)
       {
  +        ICache<V> c = this.getCache(name, valueType);
  +
  +        if (c == null || !(c instanceof ICacheSafe))
  +            return null;
  +        return (ICacheSafe<V>)c;
  +    }
  +    /** 
  +     * Returns a cache for the specified name, value type and cache type.
  +     * Creates the cache if necessary.
  +     *
  +     * @throws ClassCastException if the cache already exists for an
  +     * incompatible value type.
  +     */
  +    public @NonNullable <V> ICache<V> getCache(
  +            @NonNullable String name,
  +            @NonNullable Class<V> valueType,
  +            @NonNullable CacheType cacheType)
  +    {
           ICache c = this.map.get(name);
                  
  -        if (c == null)
  -            return this.createCache(cacheType, name, valueType);
  -        CacheManagerUtils.inst.checkValueType(c, valueType);
  +        if (c == null) {
  +            switch(cacheType) {
  +                case SOFT_REFERENCE:
  +                case SOFT_REFERENCE_SAFE:
  +                    c = this.tryCreateCache(name, valueType, cacheType);
  +                    break;
  +                case SOFT_REFERENCE_FILE:
  +                case SOFT_REFERENCE_FILE_SAFE:
  +                    c = this.tryCreateFileCache(name, valueType, cacheType);
  +                    break;
  +                default:
  +                    throw new AssertionError(cacheType);
  +            }
  +        }
  +        this.checkValueType(c, valueType);
           return c;
       }
       /** 
  -     * Returns an existing cache for the specified name; or null if not found.
  +     * Returns a safe cache for the specified name, value type and cache type.
  +     * Creates the cache if necessary.
  +     *
  +     * @throws IllegalArgumentException if the cache type specified is not a
  +     *  safe cache type.
  +     * @throws ClassCastException if the cache already exists for an
  +     *  incompatible value type.
        */
  -    public ICache getCache(@NonNullable String name) {
  -        return this.map.get(name);
  +    public @NonNullable <V> ICacheSafe<V> getSafeCache(
  +            @NonNullable String name,
  +            @NonNullable Class<V> valueType,
  +            @NonNullable CacheType cacheType)
  +    {
  +        switch(cacheType) {
  +            case SOFT_REFERENCE_SAFE:
  +            case SOFT_REFERENCE_FILE_SAFE:
  +                break;
  +            default:
  +                throw new IllegalArgumentException(cacheType.toString());
  +        }
  +        return (ICacheSafe<V>)this.getCache(name, valueType, cacheType);
       }
       /**
        * Removes the specified cache, if it exists.
  @@ -84,27 +161,76 @@
        * an existing cache created earlier by another thread.
        */
   //    @SuppressWarnings({"unchecked"})
  -    private @NonNullable <V> ICache<V> createCache(
  -            @NonNullable CacheType cacheType,
  +    private @NonNullable <V> ICache<V> tryCreateCache(
               @NonNullable String name, 
  -            @NonNullable Class<V> valueType)
  +            @NonNullable Class<V> valueType,
  +            @NonNullable CacheType cacheType)
       {
  -        ICache<V> c = cacheType.createCache(name, valueType);
  -//        SoftRefFileCache<V> c = new SoftRefFileCache<V>(name, valueType);
  -//        c.addCacheChangeListener(new CacheFileManager<V>(c));
  -        ICache old = this.map.putIfAbsent(name, c);
  +        ICache<V> newCache = cacheType.createCache(name, valueType);
  +//        SoftRefFileCache<V> newCache = new SoftRefFileCache<V>(name, valueType);
  +//        newCache.addCacheChangeListener(new CacheFileManager<V>(newCache));
  +        ICache oldCache = this.map.putIfAbsent(name, newCache);
   
  -        if (old != null) {
  +        if (oldCache != null) {
               // race condition: cache already created by another thread.
  -            CacheManagerUtils.inst.checkValueType(old, valueType);
  -            return old;
  +            this.checkValueType(oldCache, valueType);
  +            return oldCache;
           }
  -        return c;
  +        return newCache;
  +    }
  +    /** 
  +     * Creates the specified file cache if not already created.
  +     * 
  +     * @return either the file cache created by the current thread, or
  +     * an existing file cache created earlier by another thread.
  +     */
  +    private @NonNullable <V> ICache<V> tryCreateFileCache(
  +            @NonNullable String name, 
  +            @NonNullable Class<V> valueType,
  +            @NonNullable CacheType cacheType)
  +    {
  +        Lock lock = this.keyedRWLock.writeLock(name);
  +        lock.lock();
  +        ICache<V> newCache = null;
  +        ICache oldCache = null;
  +        try {
  +            newCache = cacheType.createCache(name, valueType);
  +//        SoftRefFileCache<V> newCache = new SoftRefFileCache<V>(name, valueType);
  +//        newCache.addCacheChangeListener(new CacheFileManager<V>(newCache));
  +            oldCache = this.map.putIfAbsent(name, newCache);
  +        } finally {
  +            lock.unlock();
  +        }
  +
  +        if (oldCache != null) {
  +            // race condition: cache already created by another thread.
  +            this.checkValueType(oldCache, valueType);
  +            return oldCache;
  +        }
  +        return newCache;
       }
   
       @TestOnly("Used solely to simluate a race condition during cache creation ")
  -    @NonNullable <V> ICache<V> testCreateCacheRaceCondition(@NonNullable String name, @NonNullable Class<V> valueType) 
  +    @NonNullable <V> ICache<V> testCreateCacheRaceCondition(
  +            @NonNullable String name, @NonNullable Class<V> valueType, @NonNullable CacheType cacheType) 
  +    {
  +        return this.tryCreateCache(name, valueType, cacheType);
  +    }
  +    @TestOnly("Used solely to simluate a race condition during cache creation ")
  +    @NonNullable <V> ICache<V> testCreateFileCacheRaceCondition(
  +            @NonNullable String name, @NonNullable Class<V> valueType, @NonNullable CacheType cacheType) 
       {
  -        return this.createCache(DEFAULT_CACHE_TYPE, name, valueType);
  +        return this.tryCreateCache(name, valueType, cacheType);
  +    }
  +    private void checkValueType(ICache c, @NonNullable Class<?> valueType) {
  +        if (c == null)
  +            return;
  +        Class<?> cacheValueType = c.getValueType();
  +        
  +        if (!cacheValueType.isAssignableFrom(valueType))
  +            throw new ClassCastException("Cache " + c.getName()
  +                + " of " + c.getValueType() 
  +                + " already exists and cannot be used for " + valueType);
  +        return;
       }
   }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-jcs-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-jcs-dev-help@jakarta.apache.org