All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.datanucleus.cache.JavaxCacheLevel2Cache Maven / Gradle / Ivy

Go to download

DataNucleus Core provides the primary components of a heterogenous Java persistence solution. It supports persistence API's being layered on top of the core functionality.

There is a newer version: 6.0.9
Show newest version
/**********************************************************************
Copyright (c) 2012 Andy Jefferson and others. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Contributors:
    ...
**********************************************************************/
package org.datanucleus.cache;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.CacheManager;
import javax.cache.configuration.MutableConfiguration;
import javax.cache.spi.CachingProvider;
import javax.cache.Caching;

import org.datanucleus.NucleusContext;
import org.datanucleus.Configuration;
import org.datanucleus.PropertyNames;
import org.datanucleus.exceptions.NucleusException;
import org.datanucleus.identity.IdentityUtils;
import org.datanucleus.metadata.AbstractClassMetaData;
import org.datanucleus.metadata.IdentityType;
import org.datanucleus.util.NucleusLogger;

/**
 * Simple implementation of a plugin for use of javax.cache (v0.61+) product with DataNucleus. 
 */
public class JavaxCacheLevel2Cache extends AbstractLevel2Cache
{
    public static final String NAME = "javax.cache";

    private static final long serialVersionUID = 3218890128547271239L;

    /** Cache of CachedPC keyed by "id". */
    private Cache cache;

    /** Cache of "id" keyed by "uniqueKey". */
    private Cache cacheUnique;

    /**
     * Constructor.
     * @param nucleusCtx Context
     */
    public JavaxCacheLevel2Cache(NucleusContext nucleusCtx)
    {
        super(nucleusCtx);

        try
        {
            CachingProvider cacheProvider = Caching.getCachingProvider();
            CacheManager cacheMgr = cacheProvider.getCacheManager();
            Cache tmpcache = cacheMgr.getCache(cacheName);
            if (tmpcache == null)
            {
                MutableConfiguration cacheConfig = new MutableConfiguration();
                Configuration conf = nucleusCtx.getConfiguration();
                if (conf.hasProperty(PropertyNames.PROPERTY_CACHE_L2_READ_THROUGH))
                {
                    cacheConfig.setReadThrough(conf.getBooleanProperty(PropertyNames.PROPERTY_CACHE_L2_READ_THROUGH));
                }
                if (conf.hasProperty(PropertyNames.PROPERTY_CACHE_L2_WRITE_THROUGH))
                {
                    cacheConfig.setWriteThrough(conf.getBooleanProperty(PropertyNames.PROPERTY_CACHE_L2_WRITE_THROUGH));
                }
                if (conf.hasProperty(PropertyNames.PROPERTY_CACHE_L2_STATISTICS_ENABLED))
                {
                    cacheConfig.setStatisticsEnabled(conf.getBooleanProperty(PropertyNames.PROPERTY_CACHE_L2_STATISTICS_ENABLED));
                }
                if (conf.hasProperty(PropertyNames.PROPERTY_CACHE_L2_STORE_BY_VALUE))
                {
                    cacheConfig.setStoreByValue(conf.getBooleanProperty(PropertyNames.PROPERTY_CACHE_L2_STORE_BY_VALUE));
                }
                if (expiryMillis > 0)
                {
                    // TODO Some way to set the expiry
                }
                cacheMgr.createCache(cacheName, cacheConfig);
                tmpcache = cacheMgr.getCache(cacheName);
            }
            cache = tmpcache;

            // Cache for unique key to "id"
            String cacheNameUnique = cacheName + "UNIQUE";
            tmpcache = cacheMgr.getCache(cacheNameUnique);
            if (tmpcache == null)
            {
                MutableConfiguration cacheConfig = new MutableConfiguration();
                Configuration conf = nucleusCtx.getConfiguration();
                if (conf.hasProperty(PropertyNames.PROPERTY_CACHE_L2_READ_THROUGH))
                {
                    cacheConfig.setReadThrough(conf.getBooleanProperty(PropertyNames.PROPERTY_CACHE_L2_READ_THROUGH));
                }
                if (conf.hasProperty(PropertyNames.PROPERTY_CACHE_L2_WRITE_THROUGH))
                {
                    cacheConfig.setWriteThrough(conf.getBooleanProperty(PropertyNames.PROPERTY_CACHE_L2_WRITE_THROUGH));
                }
                if (conf.hasProperty(PropertyNames.PROPERTY_CACHE_L2_STATISTICS_ENABLED))
                {
                    cacheConfig.setStatisticsEnabled(conf.getBooleanProperty(PropertyNames.PROPERTY_CACHE_L2_STATISTICS_ENABLED));
                }
                if (conf.hasProperty(PropertyNames.PROPERTY_CACHE_L2_STORE_BY_VALUE))
                {
                    cacheConfig.setStoreByValue(conf.getBooleanProperty(PropertyNames.PROPERTY_CACHE_L2_STORE_BY_VALUE));
                }
                if (expiryMillis > 0)
                {
                    // TODO Some way to set the expiry
                }
                cacheMgr.createCache(cacheNameUnique, cacheConfig);
                tmpcache = cacheMgr.getCache(cacheNameUnique);
            }
            cacheUnique = tmpcache;
        }
        catch (CacheException e)
        {
            throw new NucleusException("Error creating cache", e);
        }
    }

    /**
     * Method to close the cache when no longer needed. Provides a hook to release resources etc.
     */
    public void close()
    {
        if (clearAtClose)
        {
            try
            {
                cache.removeAll();
            }
            catch (Exception re)
            {
                NucleusLogger.CACHE.debug("Objects not evicted from cache due to : " + re.getMessage());
            }
            cache.close();

            try
            {
                cacheUnique.removeAll();
            }
            catch (Exception re)
            {
                NucleusLogger.CACHE.debug("Objects not evicted from cache due to : " + re.getMessage());
            }
            cacheUnique.close();
        }

        cache = null;
        cacheUnique = null;
    }

    /**
     * Accessor for whether the cache contains the specified id.
     * @see org.datanucleus.cache.Level2Cache#containsOid(java.lang.Object)
     */
    public boolean containsOid(Object oid)
    {
        return get(oid) != null;
    }

    /**
     * Accessor for an object in the cache.
     * @see org.datanucleus.cache.Level2Cache#get(java.lang.Object)
     */
    public CachedPC get(Object oid)
    {
        try
        {
            return (CachedPC) cache.get(oid);
        }
        catch (Exception e)
        {
            NucleusLogger.CACHE.debug("Object with id " + oid +" not retrieved from cache due to : " + e.getMessage());
            return null;
        }
    }

    /* (non-Javadoc)
     * @see org.datanucleus.cache.AbstractLevel2Cache#getAll(java.util.Collection)
     */
    @Override
    public Map getAll(Collection oids)
    {
        try
        {
            if (oids instanceof Set)
            {
                return cache.getAll((Set)oids);
            }
            return cache.getAll(new HashSet(oids));
        }
        catch (Exception e)
        {
            NucleusLogger.CACHE.debug("Objects not retrieved from cache due to : " + e.getMessage());
            return null;
        }
    }

    /**
     * Method to add an object to the cache under its id
     * @param oid The identity
     * @param pc The cacheable object
     */
    public CachedPC put(Object oid, CachedPC pc)
    {
        if (oid == null || pc == null)
        {
            return null;
        }
        else if (maxSize >= 0 && getSize() == maxSize)
        {
            return null;
        }

        try
        {
            cache.put(oid, pc);
        }
        catch (Exception e)
        {
            // Not cached due to some problem. Not serializable?
            NucleusLogger.CACHE.debug("Object with id " + oid + " for cachedPC=" + pc.toString("", true) + " not cached due to : " + e.getMessage());
        }
        return pc;
    }

    /* (non-Javadoc)
     * @see org.datanucleus.cache.AbstractLevel2Cache#putAll(java.util.Map)
     */
    @Override
    public void putAll(Map objs)
    {
        if (objs == null)
        {
            return;
        }

        try
        {
            cache.putAll(objs);
        }
        catch (Exception e)
        {
            // Not cached due to some problem. Not serializable?
            NucleusLogger.CACHE.debug("Objects not cached due to : " + e.getMessage());
        }
    }

    /**
     * Evict the parameter instance from the second-level cache.
     * @param oid the object id of the instance to evict.
     */
    public void evict(Object oid)
    {
        try
        {
            cache.remove(oid);
        }
        catch (Exception re)
        {
            NucleusLogger.CACHE.debug("Object with id=" + oid + " not evicted from cache due to : " + re.getMessage());
        }
    }

    /**
     * Evict the parameter instances from the second-level cache.
     * All instances in the PersistenceManager's cache are evicted
     * from the second-level cache.
     */
    public void evictAll()
    {
        try
        {
            cache.removeAll();
        }
        catch (Exception re)
        {
            NucleusLogger.CACHE.debug("Objects not evicted from cache due to : " + re.getMessage());
        }
    }

    /**
     * Evict the parameter instances from the second-level cache.
     * @param oids the object ids of the instance to evict.
     */
    public void evictAll(Collection oids)
    {
        if (oids == null)
        {
            return;
        }

        try
        {
            if (oids instanceof Set)
            {
                cache.removeAll((Set)oids);
            }
            else
            {
                cache.removeAll(new HashSet(oids));
            }
        }
        catch (Exception re)
        {
            NucleusLogger.CACHE.debug("Objects not evicted from cache due to : " + re.getMessage());
        }
    }

    /**
     * Evict the parameter instances from the second-level cache.
     * @param oids the object ids of the instance to evict.
     */
    public void evictAll(Object[] oids)
    {
        if (oids == null)
        {
            return;
        }

        try
        {
            Set oidSet = new HashSet(Arrays.asList(oids));
            cache.removeAll(oidSet);
        }
        catch (Exception re)
        {
            NucleusLogger.CACHE.debug("Objects not evicted from cache due to : " + re.getMessage());
        }
    }

    /**
     * Evict the parameter instances from the second-level cache.
     * @param pcClass the class of instances to evict
     * @param subclasses if true, evict instances of subclasses also
     */
    public void evictAll(Class pcClass, boolean subclasses)
    {
        if (!nucleusCtx.getApiAdapter().isPersistable(pcClass))
        {
            return;
        }

        evictAllOfClass(pcClass.getName());
        if (subclasses)
        {
            String[] subclassNames = nucleusCtx.getMetaDataManager().getSubclassesForClass(pcClass.getName(), true);
            if (subclassNames != null)
            {
                for (int i=0;i entryIter = cache.iterator();
            while (entryIter.hasNext())
            {
                Cache.Entry entry = entryIter.next();
                Object key = entry.getKey();
                if (cmd.getIdentityType() == IdentityType.APPLICATION)
                {
                    String targetClassName = IdentityUtils.getTargetClassNameForIdentity(key);
                    if (className.equals(targetClassName))
                    {
                        entryIter.remove();
                    }
                }
                else if (cmd.getIdentityType() == IdentityType.DATASTORE)
                {
                    String targetClassName = IdentityUtils.getTargetClassNameForIdentity(key);
                    if (className.equals(targetClassName))
                    {
                        entryIter.remove();
                    }
                }
            }
        }
        catch (Exception re)
        {
            NucleusLogger.CACHE.debug("Objects not evicted from cache due to : " + re.getMessage());
        }
    }

    /* (non-Javadoc)
     * @see org.datanucleus.cache.Level2Cache#getUnique(org.datanucleus.cache.CacheUniqueKey)
     */
    @Override
    public CachedPC getUnique(CacheUniqueKey key)
    {
        return (CachedPC) cacheUnique.get(key);
    }

    /* (non-Javadoc)
     * @see org.datanucleus.cache.Level2Cache#putUnique(org.datanucleus.cache.CacheUniqueKey, org.datanucleus.cache.CachedPC)
     */
    @Override
    public CachedPC putUnique(CacheUniqueKey key, CachedPC pc)
    {
        try
        {
            cacheUnique.put(key, pc);
        }
        catch (Exception e)
        {
            // Not cached due to some problem. Not serializable?
            NucleusLogger.CACHE.debug("Object with key " + key +" not cached due to : " + e.getMessage());
        }
        return pc;
    }

    /* (non-Javadoc)
     * @see org.datanucleus.cache.Level2Cache#putUniqueAll(java.util.Map)
     */
    @Override
    public void putUniqueAll(Map objs)
    {
        if (objs == null)
        {
            return;
        }

        try
        {
            cacheUnique.putAll(objs);
        }
        catch (Exception e)
        {
            // Not cached due to some problem. Not serializable?
            NucleusLogger.CACHE.debug("Objects not cached due to : " + e.getMessage());
        }
    }

    /* (non-Javadoc)
     * @see org.datanucleus.cache.Level2Cache#removeUnique(org.datanucleus.cache.CacheUniqueKey)
     */
    @Override
    public void removeUnique(CacheUniqueKey key)
    {
        cacheUnique.remove(key);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy