package org.apache.commons.jcs3.engine.control;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.jcs3.access.exception.CacheException;
import org.apache.commons.jcs3.access.exception.ObjectNotFoundException;
import org.apache.commons.jcs3.auxiliary.AuxiliaryCache;
import org.apache.commons.jcs3.engine.CacheStatus;
import org.apache.commons.jcs3.engine.behavior.ICache;
import org.apache.commons.jcs3.engine.behavior.ICacheElement;
import org.apache.commons.jcs3.engine.behavior.ICompositeCacheAttributes;
import org.apache.commons.jcs3.engine.behavior.IElementAttributes;
import org.apache.commons.jcs3.engine.behavior.IRequireScheduler;
import org.apache.commons.jcs3.engine.behavior.ICompositeCacheAttributes.DiskUsagePattern;
import org.apache.commons.jcs3.engine.control.event.ElementEvent;
import org.apache.commons.jcs3.engine.control.event.behavior.ElementEventType;
import org.apache.commons.jcs3.engine.control.event.behavior.IElementEvent;
import org.apache.commons.jcs3.engine.control.event.behavior.IElementEventHandler;
import org.apache.commons.jcs3.engine.control.event.behavior.IElementEventQueue;
import org.apache.commons.jcs3.engine.control.group.GroupId;
import org.apache.commons.jcs3.engine.match.KeyMatcherPatternImpl;
import org.apache.commons.jcs3.engine.match.behavior.IKeyMatcher;
import org.apache.commons.jcs3.engine.memory.behavior.IMemoryCache;
import org.apache.commons.jcs3.engine.memory.lru.LRUMemoryCache;
import org.apache.commons.jcs3.engine.memory.shrinking.ShrinkerThread;
import org.apache.commons.jcs3.engine.stats.CacheStats;
import org.apache.commons.jcs3.engine.stats.StatElement;
import org.apache.commons.jcs3.engine.stats.behavior.ICacheStats;
import org.apache.commons.jcs3.engine.stats.behavior.IStatElement;
import org.apache.commons.jcs3.engine.stats.behavior.IStats;
import org.apache.commons.jcs3.log.Log;
import org.apache.commons.jcs3.log.LogManager;

/**
 * This is the primary hub for a single cache/region. It controls the flow of items through the
 * cache. The auxiliary and memory caches are plugged in here.
 * <p>
 * This is the core of a JCS region. Hence, this simple class is the core of JCS.
 */
public class CompositeCache<K, V>
    implements ICache<K, V>, IRequireScheduler
{
    /** log instance */
    private static final Log log = LogManager.getLog(CompositeCache.class);

    /**
     * EventQueue for handling element events. Lazy initialized. One for each region. To be more efficient, the manager
     * should pass a shared queue in.
     */
    private IElementEventQueue elementEventQ;

    /** Auxiliary caches. */
    @SuppressWarnings("unchecked") // OK because this is an empty array
    private AuxiliaryCache<K, V>[] auxCaches = new AuxiliaryCache[0];

    /** is this alive? */
    private final AtomicBoolean alive;

    /** Region Elemental Attributes, default. */
    private IElementAttributes attr;

    /** Cache Attributes, for hub and memory auxiliary. */
    private ICompositeCacheAttributes cacheAttr;

    /** How many times update was called. */
    private final AtomicLong updateCount;

    /** How many times remove was called. */
    private final AtomicLong removeCount;

    /** Memory cache hit count */
    private final AtomicLong hitCountRam;

    /** Auxiliary cache hit count (number of times found in ANY auxiliary) */
    private final AtomicLong hitCountAux;

    /** Count of misses where element was not found. */
    private final AtomicLong missCountNotFound;

    /** Count of misses where element was expired. */
    private final AtomicLong missCountExpired;

    /** Cache manager. */
    private CompositeCacheManager cacheManager = null;

    /**
     * The cache hub can only have one memory cache. This could be made more flexible in the future,
     * but they are tied closely together. More than one doesn't make much sense.
     */
    private IMemoryCache<K, V> memCache;

    /** Key matcher used by the getMatching API */
    private IKeyMatcher<K> keyMatcher = new KeyMatcherPatternImpl<>();

    private ScheduledFuture<?> future;

    /**
     * Constructor for the Cache object
     * <p>
     * @param cattr The cache attribute
     * @param attr The default element attributes
     */
    public CompositeCache(ICompositeCacheAttributes cattr, IElementAttributes attr)
    {
        this.attr = attr;
        this.cacheAttr = cattr;
        this.alive = new AtomicBoolean(true);
        this.updateCount = new AtomicLong(0);
        this.removeCount = new AtomicLong(0);
        this.hitCountRam = new AtomicLong(0);
        this.hitCountAux = new AtomicLong(0);
        this.missCountNotFound = new AtomicLong(0);
        this.missCountExpired = new AtomicLong(0);

        createMemoryCache(cattr);

        log.info("Constructed cache with name [{0}] and cache attributes {1}",
                cacheAttr.getCacheName(), cattr);
    }

    /**
     * Injector for Element event queue
     *
     * @param queue
     */
    public void setElementEventQueue(IElementEventQueue queue)
    {
        this.elementEventQ = queue;
    }

    /**
     * Injector for cache manager
     *
     * @param manager
     */
    public void setCompositeCacheManager(CompositeCacheManager manager)
    {
        this.cacheManager = manager;
    }

    /**
     * @see org.apache.commons.jcs3.engine.behavior.IRequireScheduler#setScheduledExecutorService(java.util.concurrent.ScheduledExecutorService)
     */
    @Override
    public void setScheduledExecutorService(ScheduledExecutorService scheduledExecutor)
    {
        if (cacheAttr.isUseMemoryShrinker())
        {
            future = scheduledExecutor.scheduleAtFixedRate(
                    new ShrinkerThread<>(this), 0, cacheAttr.getShrinkerIntervalSeconds(),
                    TimeUnit.SECONDS);
        }
    }

    /**
     * This sets the list of auxiliary caches for this region.
     * <p>
     * @param auxCaches
     */
    public void setAuxCaches(AuxiliaryCache<K, V>[] auxCaches)
    {
        this.auxCaches = auxCaches;
    }

    /**
     * Get the list of auxiliary caches for this region.
     * <p>
     * @return an array of auxiliary caches, may be empty, never null
     */
    public AuxiliaryCache<K, V>[] getAuxCaches()
    {
        return this.auxCaches;
    }

    /**
     * Standard update method.
     * <p>
     * @param ce
     * @throws IOException
     */
    @Override
    public void update(ICacheElement<K, V> ce)
        throws IOException
    {
        update(ce, false);
    }

    /**
     * Standard update method.
     * <p>
     * @param ce
     * @throws IOException
     */
    public void localUpdate(ICacheElement<K, V> ce)
        throws IOException
    {
        update(ce, true);
    }

    /**
     * Put an item into the cache. If it is localOnly, then do no notify remote or lateral
     * auxiliaries.
     * <p>
     * @param cacheElement the ICacheElement&lt;K, V&gt;
     * @param localOnly Whether the operation should be restricted to local auxiliaries.
     * @throws IOException
     */
    protected void update(ICacheElement<K, V> cacheElement, boolean localOnly)
        throws IOException
    {

        if (cacheElement.getKey() instanceof String
            && cacheElement.getKey().toString().endsWith(NAME_COMPONENT_DELIMITER))
        {
            throw new IllegalArgumentException("key must not end with " + NAME_COMPONENT_DELIMITER
                + " for a put operation");
        }
        else if (cacheElement.getKey() instanceof GroupId)
        {
            throw new IllegalArgumentException("key cannot be a GroupId " + " for a put operation");
        }

        log.debug("Updating memory cache {0}", () -> cacheElement.getKey());

        updateCount.incrementAndGet();
        memCache.update(cacheElement);
        updateAuxiliaries(cacheElement, localOnly);

        cacheElement.getElementAttributes().setLastAccessTimeNow();
    }

    /**
     * This method is responsible for updating the auxiliaries if they are present. If it is local
     * only, any lateral and remote auxiliaries will not be updated.
     * <p>
     * Before updating an auxiliary it checks to see if the element attributes permit the operation.
     * <p>
     * Disk auxiliaries are only updated if the disk cache is not merely used as a swap. If the disk
     * cache is merely a swap, then items will only go to disk when they overflow from memory.
     * <p>
     * This is called by update(cacheElement, localOnly) after it updates the memory cache.
     * <p>
     * This is protected to make it testable.
     * <p>
     * @param cacheElement
     * @param localOnly
     * @throws IOException
     */
    protected void updateAuxiliaries(ICacheElement<K, V> cacheElement, boolean localOnly)
        throws IOException
    {
        // UPDATE AUXILLIARY CACHES
        // There are 3 types of auxiliary caches: remote, lateral, and disk
        // more can be added if future auxiliary caches don't fit the model
        // You could run a database cache as either a remote or a local disk.
        // The types would describe the purpose.
        if (auxCaches.length > 0)
        {
            log.debug("Updating auxiliary caches");
        }
        else
        {
            log.debug("No auxiliary cache to update");
        }

        for (ICache<K, V> aux : auxCaches)
        {
            if (aux == null)
            {
                continue;
            }

            log.debug("Auxiliary cache type: {0}", aux.getCacheType());

            switch (aux.getCacheType())
            {
                // SEND TO REMOTE STORE
                case REMOTE_CACHE:
                    log.debug("ce.getElementAttributes().getIsRemote() = {0}",
                        () -> cacheElement.getElementAttributes().getIsRemote());

                    if (cacheElement.getElementAttributes().getIsRemote() && !localOnly)
                    {
                        try
                        {
                            // need to make sure the group cache understands that
                            // the key is a group attribute on update
                            aux.update(cacheElement);
                            log.debug("Updated remote store for {0} {1}",
                                    cacheElement.getKey(), cacheElement);
                        }
                        catch (IOException ex)
                        {
                            log.error("Failure in updateExclude", ex);
                        }
                    }
                    break;

                // SEND LATERALLY
                case LATERAL_CACHE:
                    // lateral can't do the checking since it is dependent on the
                    // cache region restrictions
                    log.debug("lateralcache in aux list: cattr {0}", () -> cacheAttr.isUseLateral());
                    if (cacheAttr.isUseLateral() && cacheElement.getElementAttributes().getIsLateral() && !localOnly)
                    {
                        // DISTRIBUTE LATERALLY
                        // Currently always multicast even if the value is
                        // unchanged, to cause the cache item to move to the front.
                        aux.update(cacheElement);
                        log.debug("updated lateral cache for {0}", () -> cacheElement.getKey());
                    }
                    break;

                // update disk if the usage pattern permits
                case DISK_CACHE:
                    log.debug("diskcache in aux list: cattr {0}", () -> cacheAttr.isUseDisk());
                    if (cacheAttr.isUseDisk()
                        && cacheAttr.getDiskUsagePattern() == DiskUsagePattern.UPDATE
                        && cacheElement.getElementAttributes().getIsSpool())
                    {
                        aux.update(cacheElement);
                        log.debug("updated disk cache for {0}", () -> cacheElement.getKey());
                    }
                    break;

                default: // CACHE_HUB
                    break;
            }
        }
    }

    /**
     * Writes the specified element to any disk auxiliaries. Might want to rename this "overflow" in
     * case the hub wants to do something else.
     * <p>
     * If JCS is not configured to use the disk as a swap, that is if the the
     * CompositeCacheAttribute diskUsagePattern is not SWAP_ONLY, then the item will not be spooled.
     * <p>
     * @param ce The CacheElement
     */
    public void spoolToDisk(ICacheElement<K, V> ce)
    {
        // if the item is not spoolable, return
        if (!ce.getElementAttributes().getIsSpool())
        {
            // there is an event defined for this.
            handleElementEvent(ce, ElementEventType.SPOOLED_NOT_ALLOWED);
            return;
        }

        boolean diskAvailable = false;

        // SPOOL TO DISK.
        for (ICache<K, V> aux : auxCaches)
        {
            if (aux != null && aux.getCacheType() == CacheType.DISK_CACHE)
            {
                diskAvailable = true;

                if (cacheAttr.getDiskUsagePattern() == DiskUsagePattern.SWAP)
                {
                    // write the last items to disk.2
                    try
                    {
                        handleElementEvent(ce, ElementEventType.SPOOLED_DISK_AVAILABLE);
                        aux.update(ce);
                    }
                    catch (IOException ex)
                    {
                        // impossible case.
                        log.error("Problem spooling item to disk cache.", ex);
                        throw new IllegalStateException(ex.getMessage());
                    }

                    log.debug("spoolToDisk done for: {0} on disk cache[{1}]",
                            () -> ce.getKey(), () -> aux.getCacheName());
                }
                else
                {
                    log.debug("DiskCache available, but JCS is not configured "
                            + "to use the DiskCache as a swap.");
                }
            }
        }

        if (!diskAvailable)
        {
            handleElementEvent(ce, ElementEventType.SPOOLED_DISK_NOT_AVAILABLE);
        }
    }

    /**
     * Gets an item from the cache.
     * <p>
     * @param key
     * @return element from the cache, or null if not present
     * @see org.apache.commons.jcs3.engine.behavior.ICache#get(Object)
     */
    @Override
    public ICacheElement<K, V> get(K key)
    {
        return get(key, false);
    }

    /**
     * Do not try to go remote or laterally for this get.
     * <p>
     * @param key
     * @return ICacheElement
     */
    public ICacheElement<K, V> localGet(K key)
    {
        return get(key, true);
    }

    /**
     * Look in memory, then disk, remote, or laterally for this item. The order is dependent on the
     * order in the cache.ccf file.
     * <p>
     * Do not try to go remote or laterally for this get if it is localOnly. Otherwise try to go
     * remote or lateral if such an auxiliary is configured for this region.
     * <p>
     * @param key
     * @param localOnly
     * @return ICacheElement
     */
    protected ICacheElement<K, V> get(K key, boolean localOnly)
    {
        ICacheElement<K, V> element = null;

        boolean found = false;

        log.debug("get: key = {0}, localOnly = {1}", key, localOnly);

        try
        {
            // First look in memory cache
            element = memCache.get(key);

            if (element != null)
            {
                // Found in memory cache
                if (isExpired(element))
                {
                    log.debug("{0} - Memory cache hit, but element expired",
                            () -> cacheAttr.getCacheName());

                    doExpires(element);
                    element = null;
                }
                else
                {
                    log.debug("{0} - Memory cache hit", () -> cacheAttr.getCacheName());

                    // Update counters
                    hitCountRam.incrementAndGet();
                }

                found = true;
            }
            else
            {
                // Item not found in memory. If local invocation look in aux
                // caches, even if not local look in disk auxiliaries
                for (AuxiliaryCache<K, V> aux : auxCaches)
                {
                    if (aux != null)
                    {
                        CacheType cacheType = aux.getCacheType();

                        if (!localOnly || cacheType == CacheType.DISK_CACHE)
                        {
                            log.debug("Attempting to get from aux [{0}] which is of type: {1}",
                                    () -> aux.getCacheName(), () -> cacheType);

                            try
                            {
                                element = aux.get(key);
                            }
                            catch (IOException e)
                            {
                                log.error("Error getting from aux", e);
                            }
                        }

                        log.debug("Got CacheElement: {0}", element);

                        // Item found in one of the auxiliary caches.
                        if (element != null)
                        {
                            if (isExpired(element))
                            {
                                log.debug("{0} - Aux cache[{1}] hit, but element expired.",
                                        () -> cacheAttr.getCacheName(), () -> aux.getCacheName());

                                // This will tell the remotes to remove the item
                                // based on the element's expiration policy. The elements attributes
                                // associated with the item when it created govern its behavior
                                // everywhere.
                                doExpires(element);
                                element = null;
                            }
                            else
                            {
                                log.debug("{0} - Aux cache[{1}] hit.",
                                        () -> cacheAttr.getCacheName(), () -> aux.getCacheName());

                                // Update counters
                                hitCountAux.incrementAndGet();
                                copyAuxiliaryRetrievedItemToMemory(element);
                            }

                            found = true;

                            break;
                        }
                    }
                }
            }
        }
        catch (IOException e)
        {
            log.error("Problem encountered getting element.", e);
        }

        if (!found)
        {
            missCountNotFound.incrementAndGet();

            log.debug("{0} - Miss", () -> cacheAttr.getCacheName());
        }

        if (element != null)
        {
            element.getElementAttributes().setLastAccessTimeNow();
        }

        return element;
    }

    protected void doExpires(ICacheElement<K, V> element)
    {
        missCountExpired.incrementAndGet();
        remove(element.getKey());
    }

    /**
     * Gets multiple items from the cache based on the given set of keys.
     * <p>
     * @param keys
     * @return a map of K key to ICacheElement&lt;K, V&gt; element, or an empty map if there is no
     *         data in cache for any of these keys
     */
    @Override
    public Map<K, ICacheElement<K, V>> getMultiple(Set<K> keys)
    {
        return getMultiple(keys, false);
    }

    /**
     * Gets multiple items from the cache based on the given set of keys. Do not try to go remote or
     * laterally for this data.
     * <p>
     * @param keys
     * @return a map of K key to ICacheElement&lt;K, V&gt; element, or an empty map if there is no
     *         data in cache for any of these keys
     */
    public Map<K, ICacheElement<K, V>> localGetMultiple(Set<K> keys)
    {
        return getMultiple(keys, true);
    }

    /**
     * Look in memory, then disk, remote, or laterally for these items. The order is dependent on
     * the order in the cache.ccf file. Keep looking in each cache location until either the element
     * is found, or the method runs out of places to look.
     * <p>
     * Do not try to go remote or laterally for this get if it is localOnly. Otherwise try to go
     * remote or lateral if such an auxiliary is configured for this region.
     * <p>
     * @param keys
     * @param localOnly
     * @return ICacheElement
     */
    protected Map<K, ICacheElement<K, V>> getMultiple(Set<K> keys, boolean localOnly)
    {
        Map<K, ICacheElement<K, V>> elements = new HashMap<>();

        log.debug("get: key = {0}, localOnly = {1}", keys, localOnly);

        try
        {
            // First look in memory cache
            elements.putAll(getMultipleFromMemory(keys));

            // If fewer than all items were found in memory, then keep looking.
            if (elements.size() != keys.size())
            {
                Set<K> remainingKeys = pruneKeysFound(keys, elements);
                elements.putAll(getMultipleFromAuxiliaryCaches(remainingKeys, localOnly));
            }
        }
        catch (IOException e)
        {
            log.error("Problem encountered getting elements.", e);
        }

        // if we didn't find all the elements, increment the miss count by the number of elements not found
        if (elements.size() != keys.size())
        {
            missCountNotFound.addAndGet(keys.size() - elements.size());

            log.debug("{0} - {1} Misses", () -> cacheAttr.getCacheName(),
                    () -> keys.size() - elements.size());
        }

        return elements;
    }

    /**
     * Gets items for the keys in the set. Returns a map: key -> result.
     * <p>
     * @param keys
     * @return the elements found in the memory cache
     * @throws IOException
     */
    private Map<K, ICacheElement<K, V>> getMultipleFromMemory(Set<K> keys)
        throws IOException
    {
        Map<K, ICacheElement<K, V>> elementsFromMemory = memCache.getMultiple(keys);
        elementsFromMemory.entrySet().removeIf(entry -> {
            ICacheElement<K, V> element = entry.getValue();
            if (isExpired(element))
            {
                log.debug("{0} - Memory cache hit, but element expired",
                        () -> cacheAttr.getCacheName());

                doExpires(element);
                return true;
            }
            else
            {
                log.debug("{0} - Memory cache hit", () -> cacheAttr.getCacheName());

                // Update counters
                hitCountRam.incrementAndGet();
                return false;
            }
        });

        return elementsFromMemory;
    }

    /**
     * If local invocation look in aux caches, even if not local look in disk auxiliaries.
     * <p>
     * @param keys
     * @param localOnly
     * @return the elements found in the auxiliary caches
     * @throws IOException
     */
    private Map<K, ICacheElement<K, V>> getMultipleFromAuxiliaryCaches(Set<K> keys, boolean localOnly)
        throws IOException
    {
        Map<K, ICacheElement<K, V>> elements = new HashMap<>();
        Set<K> remainingKeys = new HashSet<>(keys);

        for (AuxiliaryCache<K, V> aux : auxCaches)
        {
            if (aux != null)
            {
                Map<K, ICacheElement<K, V>> elementsFromAuxiliary =
                    new HashMap<>();

                CacheType cacheType = aux.getCacheType();

                if (!localOnly || cacheType == CacheType.DISK_CACHE)
                {
                    log.debug("Attempting to get from aux [{0}] which is of type: {1}",
                            () -> aux.getCacheName(), () -> cacheType);

                    try
                    {
                        elementsFromAuxiliary.putAll(aux.getMultiple(remainingKeys));
                    }
                    catch (IOException e)
                    {
                        log.error("Error getting from aux", e);
                    }
                }

                log.debug("Got CacheElements: {0}", elementsFromAuxiliary);

                processRetrievedElements(aux, elementsFromAuxiliary);
                elements.putAll(elementsFromAuxiliary);

                if (elements.size() == keys.size())
                {
                    break;
                }
                else
                {
                    remainingKeys = pruneKeysFound(keys, elements);
                }
            }
        }

        return elements;
    }

    /**
     * Build a map of all the matching elements in all of the auxiliaries and memory.
     * <p>
     * @param pattern
     * @return a map of K key to ICacheElement&lt;K, V&gt; element, or an empty map if there is no
     *         data in cache for any matching keys
     */
    @Override
    public Map<K, ICacheElement<K, V>> getMatching(String pattern)
    {
        return getMatching(pattern, false);
    }

    /**
     * Build a map of all the matching elements in all of the auxiliaries and memory. Do not try to
     * go remote or laterally for this data.
     * <p>
     * @param pattern
     * @return a map of K key to ICacheElement&lt;K, V&gt; element, or an empty map if there is no
     *         data in cache for any matching keys
     */
    public Map<K, ICacheElement<K, V>> localGetMatching(String pattern)
    {
        return getMatching(pattern, true);
    }

    /**
     * Build a map of all the matching elements in all of the auxiliaries and memory. Items in
     * memory will replace from the auxiliaries in the returned map. The auxiliaries are accessed in
     * opposite order. It's assumed that those closer to home are better.
     * <p>
     * Do not try to go remote or laterally for this get if it is localOnly. Otherwise try to go
     * remote or lateral if such an auxiliary is configured for this region.
     * <p>
     * @param pattern
     * @param localOnly
     * @return a map of K key to ICacheElement&lt;K, V&gt; element, or an empty map if there is no
     *         data in cache for any matching keys
     */
    protected Map<K, ICacheElement<K, V>> getMatching(String pattern, boolean localOnly)
    {
        log.debug("get: pattern [{0}], localOnly = {1}", pattern, localOnly);

        try
        {
            return Stream.concat(
                    getMatchingFromMemory(pattern).entrySet().stream(),
                    getMatchingFromAuxiliaryCaches(pattern, localOnly).entrySet().stream())
                    .collect(Collectors.toMap(
                            entry -> entry.getKey(),
                            entry -> entry.getValue(),
                            // Prefer memory entries
                            (mem, aux) -> mem));
        }
        catch (IOException e)
        {
            log.error("Problem encountered getting elements.", e);
        }

        return new HashMap<>();
    }

    /**
     * Gets the key array from the memcache. Builds a set of matches. Calls getMultiple with the
     * set. Returns a map: key -&gt; result.
     * <p>
     * @param pattern
     * @return a map of K key to ICacheElement&lt;K, V&gt; element, or an empty map if there is no
     *         data in cache for any matching keys
     * @throws IOException
     */
    protected Map<K, ICacheElement<K, V>> getMatchingFromMemory(String pattern)
        throws IOException
    {
        // find matches in key array
        // this avoids locking the memory cache, but it uses more memory
        Set<K> keyArray = memCache.getKeySet();
        Set<K> matchingKeys = getKeyMatcher().getMatchingKeysFromArray(pattern, keyArray);

        // call get multiple
        return getMultipleFromMemory(matchingKeys);
    }

    /**
     * If local invocation look in aux caches, even if not local look in disk auxiliaries.
     * <p>
     * Moves in reverse order of definition. This will allow you to override those that are from the
     * remote with those on disk.
     * <p>
     * @param pattern
     * @param localOnly
     * @return a map of K key to ICacheElement&lt;K, V&gt; element, or an empty map if there is no
     *         data in cache for any matching keys
     * @throws IOException
     */
    private Map<K, ICacheElement<K, V>> getMatchingFromAuxiliaryCaches(String pattern, boolean localOnly)
        throws IOException
    {
        Map<K, ICacheElement<K, V>> elements = new HashMap<>();

        for (int i = auxCaches.length - 1; i >= 0; i--)
        {
            AuxiliaryCache<K, V> aux = auxCaches[i];

            if (aux != null)
            {
                Map<K, ICacheElement<K, V>> elementsFromAuxiliary =
                    new HashMap<>();

                CacheType cacheType = aux.getCacheType();

                if (!localOnly || cacheType == CacheType.DISK_CACHE)
                {
                    log.debug("Attempting to get from aux [{0}] which is of type: {1}",
                            () -> aux.getCacheName(), () -> cacheType);

                    try
                    {
                        elementsFromAuxiliary.putAll(aux.getMatching(pattern));
                    }
                    catch (IOException e)
                    {
                        log.error("Error getting from aux", e);
                    }

                    log.debug("Got CacheElements: {0}", elementsFromAuxiliary);

                    processRetrievedElements(aux, elementsFromAuxiliary);
                    elements.putAll(elementsFromAuxiliary);
                }
            }
        }

        return elements;
    }

    /**
     * Remove expired elements retrieved from an auxiliary. Update memory with good items.
     * <p>
     * @param aux the auxiliary cache instance
     * @param elementsFromAuxiliary
     * @throws IOException
     */
    private void processRetrievedElements(AuxiliaryCache<K, V> aux, Map<K, ICacheElement<K, V>> elementsFromAuxiliary)
        throws IOException
    {
        elementsFromAuxiliary.entrySet().removeIf(entry -> {
            ICacheElement<K, V> element = entry.getValue();

            // Item found in one of the auxiliary caches.
            if (element != null)
            {
                if (isExpired(element))
                {
                    log.debug("{0} - Aux cache[{1}] hit, but element expired.",
                            () -> cacheAttr.getCacheName(), () -> aux.getCacheName());

                    // This will tell the remote caches to remove the item
                    // based on the element's expiration policy. The elements attributes
                    // associated with the item when it created govern its behavior
                    // everywhere.
                    doExpires(element);
                    return true;
                }
                else
                {
                    log.debug("{0} - Aux cache[{1}] hit.",
                            () -> cacheAttr.getCacheName(), () -> aux.getCacheName());

                    // Update counters
                    hitCountAux.incrementAndGet();
                    try
                    {
                        copyAuxiliaryRetrievedItemToMemory(element);
                    }
                    catch (IOException e)
                    {
                        log.error("{0} failed to copy element to memory {1}",
                                cacheAttr.getCacheName(), element, e);
                    }
                }
            }

            return false;
        });
    }

    /**
     * Copies the item to memory if the memory size is greater than 0. Only spool if the memory
     * cache size is greater than 0, else the item will immediately get put into purgatory.
     * <p>
     * @param element
     * @throws IOException
     */
    private void copyAuxiliaryRetrievedItemToMemory(ICacheElement<K, V> element)
        throws IOException
    {
        if (memCache.getCacheAttributes().getMaxObjects() > 0)
        {
            memCache.update(element);
        }
        else
        {
            log.debug("Skipping memory update since no items are allowed in memory");
        }
    }

    /**
     * Returns a set of keys that were not found.
     * <p>
     * @param keys
     * @param foundElements
     * @return the original set of cache keys, minus any cache keys present in the map keys of the
     *         foundElements map
     */
    private Set<K> pruneKeysFound(Set<K> keys, Map<K, ICacheElement<K, V>> foundElements)
    {
        Set<K> remainingKeys = new HashSet<>(keys);
        remainingKeys.removeAll(foundElements.keySet());

        return remainingKeys;
    }

    /**
     * Get a set of the keys for all elements in the cache
     * <p>
     * @return A set of the key type
     */
    public Set<K> getKeySet()
    {
        return getKeySet(false);
    }

    /**
     * Get a set of the keys for all elements in the cache
     * <p>
     * @param localOnly true if only memory keys are requested
     *
     * @return A set of the key type
     */
    public Set<K> getKeySet(boolean localOnly)
    {
        HashSet<K> allKeys = new HashSet<>();

        allKeys.addAll(memCache.getKeySet());
        for (AuxiliaryCache<K, V> aux : auxCaches)
        {
            if (aux != null)
            {
                if(!localOnly || aux.getCacheType() == CacheType.DISK_CACHE)
                {
                    try
                    {
                        allKeys.addAll(aux.getKeySet());
                    }
                    catch (IOException e)
                    {
                        // ignore
                    }
                }
            }
        }
        return allKeys;
    }

    /**
     * Removes an item from the cache.
     * <p>
     * @param key
     * @return true is it was removed
     * @see org.apache.commons.jcs3.engine.behavior.ICache#remove(Object)
     */
    @Override
    public boolean remove(K key)
    {
        return remove(key, false);
    }

    /**
     * Do not propagate removeall laterally or remotely.
     * <p>
     * @param key
     * @return true if the item was already in the cache.
     */
    public boolean localRemove(K key)
    {
        return remove(key, true);
    }

    /**
     * fromRemote: If a remove call was made on a cache with both, then the remote should have been
     * called. If it wasn't then the remote is down. we'll assume it is down for all. If it did come
     * from the remote then the cache is remotely configured and lateral removal is unnecessary. If
     * it came laterally then lateral removal is unnecessary. Does this assume that there is only
     * one lateral and remote for the cache? Not really, the initial removal should take care of the
     * problem if the source cache was similarly configured. Otherwise the remote cache, if it had
     * no laterals, would remove all the elements from remotely configured caches, but if those
     * caches had some other weird laterals that were not remotely configured, only laterally
     * propagated then they would go out of synch. The same could happen for multiple remotes. If
     * this looks necessary we will need to build in an identifier to specify the source of a
     * removal.
     * <p>
     * @param key
     * @param localOnly
     * @return true if the item was in the cache, else false
     */
    protected boolean remove(K key, boolean localOnly)
    {
        removeCount.incrementAndGet();

        boolean removed = false;

        try
        {
            removed = memCache.remove(key);
        }
        catch (IOException e)
        {
            log.error(e);
        }

        // Removes from all auxiliary caches.
        for (ICache<K, V> aux : auxCaches)
        {
            if (aux == null)
            {
                continue;
            }

            CacheType cacheType = aux.getCacheType();

            // for now let laterals call remote remove but not vice versa
            if (localOnly && (cacheType == CacheType.REMOTE_CACHE || cacheType == CacheType.LATERAL_CACHE))
            {
                continue;
            }
            try
            {
                log.debug("Removing {0} from cacheType {1}", key, cacheType);

                boolean b = aux.remove(key);

                // Don't take the remote removal into account.
                if (!removed && cacheType != CacheType.REMOTE_CACHE)
                {
                    removed = b;
                }
            }
            catch (IOException ex)
            {
                log.error("Failure removing from aux", ex);
            }
        }

        return removed;
    }

    /**
     * Clears the region. This command will be sent to all auxiliaries. Some auxiliaries, such as
     * the JDBC disk cache, can be configured to not honor removeAll requests.
     * <p>
     * @see org.apache.commons.jcs3.engine.behavior.ICache#removeAll()
     */
    @Override
    public void removeAll()
        throws IOException
    {
        removeAll(false);
    }

    /**
     * Will not pass the remove message remotely.
     * <p>
     * @throws IOException
     */
    public void localRemoveAll()
        throws IOException
    {
        removeAll(true);
    }

    /**
     * Removes all cached items.
     * <p>
     * @param localOnly must pass in false to get remote and lateral aux's updated. This prevents
     *            looping.
     * @throws IOException
     */
    protected void removeAll(boolean localOnly)
        throws IOException
    {
        try
        {
            memCache.removeAll();

            log.debug("Removed All keys from the memory cache.");
        }
        catch (IOException ex)
        {
            log.error("Trouble updating memory cache.", ex);
        }

        // Removes from all auxiliary disk caches.
        for (ICache<K, V> aux : auxCaches)
        {
            if (aux != null && (aux.getCacheType() == CacheType.DISK_CACHE || !localOnly))
            {
                try
                {
                    log.debug("Removing All keys from cacheType {0}",
                            () -> aux.getCacheType());

                    aux.removeAll();
                }
                catch (IOException ex)
                {
                    log.error("Failure removing all from aux", ex);
                }
            }
        }
    }

    /**
     * Flushes all cache items from memory to auxiliary caches and close the auxiliary caches.
     */
    @Override
    public void dispose()
    {
        dispose(false);
    }

    /**
     * Invoked only by CacheManager. This method disposes of the auxiliaries one by one. For the
     * disk cache, the items in memory are freed, meaning that they will be sent through the
     * overflow channel to disk. After the auxiliaries are disposed, the memory cache is disposed.
     * <p>
     * @param fromRemote
     */
    public void dispose(boolean fromRemote)
    {
         // If already disposed, return immediately
        if (alive.compareAndSet(true, false) == false)
        {
            return;
        }

        log.info("In DISPOSE, [{0}] fromRemote [{1}]",
                () -> this.cacheAttr.getCacheName(), () -> fromRemote);

        // Remove us from the cache managers list
        // This will call us back but exit immediately
        if (cacheManager != null)
        {
            cacheManager.freeCache(getCacheName(), fromRemote);
        }

        // Try to stop shrinker thread
        if (future != null)
        {
            future.cancel(true);
        }

        // Now, shut down the event queue
        if (elementEventQ != null)
        {
            elementEventQ.dispose();
            elementEventQ = null;
        }

        // Dispose of each auxiliary cache, Remote auxiliaries will be
        // skipped if 'fromRemote' is true.
        for (ICache<K, V> aux : auxCaches)
        {
            try
            {
                // Skip this auxiliary if:
                // - The auxiliary is null
                // - The auxiliary is not alive
                // - The auxiliary is remote and the invocation was remote
                if (aux == null || aux.getStatus() != CacheStatus.ALIVE
                    || (fromRemote && aux.getCacheType() == CacheType.REMOTE_CACHE))
                {
                    log.info("In DISPOSE, [{0}] SKIPPING auxiliary [{1}] fromRemote [{2}]",
                            () -> this.cacheAttr.getCacheName(), () -> aux.getCacheName(),
                            () -> fromRemote);
                    continue;
                }

                log.info("In DISPOSE, [{0}] auxiliary [{1}]",
                        () -> this.cacheAttr.getCacheName(), () -> aux.getCacheName());

                // IT USED TO BE THE CASE THAT (If the auxiliary is not a lateral, or the cache
                // attributes
                // have 'getUseLateral' set, all the elements currently in
                // memory are written to the lateral before disposing)
                // I changed this. It was excessive. Only the disk cache needs the items, since only
                // the disk cache is in a situation to not get items on a put.
                if (aux.getCacheType() == CacheType.DISK_CACHE)
                {
                    int numToFree = memCache.getSize();
                    memCache.freeElements(numToFree);

                    log.info("In DISPOSE, [{0}] put {1} into auxiliary [{2}]",
                            () -> this.cacheAttr.getCacheName(), () -> numToFree,
                            () -> aux.getCacheName());
                }

                // Dispose of the auxiliary
                aux.dispose();
            }
            catch (IOException ex)
            {
                log.error("Failure disposing of aux.", ex);
            }
        }

        log.info("In DISPOSE, [{0}] disposing of memory cache.",
                () -> this.cacheAttr.getCacheName());
        try
        {
            memCache.dispose();
        }
        catch (IOException ex)
        {
            log.error("Failure disposing of memCache", ex);
        }
    }

    /**
     * Calling save cause the entire contents of the memory cache to be flushed to all auxiliaries.
     * Though this put is extremely fast, this could bog the cache and should be avoided. The
     * dispose method should call a version of this. Good for testing.
     */
    public void save()
    {
        if (alive.compareAndSet(true, false) == false)
        {
            return;
        }

        for (ICache<K, V> aux : auxCaches)
        {
            try
            {
                if (aux.getStatus() == CacheStatus.ALIVE)
                {
                    for (K key : memCache.getKeySet())
                    {
                        ICacheElement<K, V> ce = memCache.get(key);

                        if (ce != null)
                        {
                            aux.update(ce);
                        }
                    }
                }
            }
            catch (IOException ex)
            {
                log.error("Failure saving aux caches.", ex);
            }
        }

        log.debug("Called save for [{0}]", () -> cacheAttr.getCacheName());
    }

    /**
     * Gets the size attribute of the Cache object. This return the number of elements, not the byte
     * size.
     * <p>
     * @return The size value
     */
    @Override
    public int getSize()
    {
        return memCache.getSize();
    }

    /**
     * Gets the cacheType attribute of the Cache object.
     * <p>
     * @return The cacheType value
     */
    @Override
    public CacheType getCacheType()
    {
        return CacheType.CACHE_HUB;
    }

    /**
     * Gets the status attribute of the Cache object.
     * <p>
     * @return The status value
     */
    @Override
    public CacheStatus getStatus()
    {
        return alive.get() ? CacheStatus.ALIVE : CacheStatus.DISPOSED;
    }

    /**
     * Gets stats for debugging.
     * <p>
     * @return String
     */
    @Override
    public String getStats()
    {
        return getStatistics().toString();
    }

    /**
     * This returns data gathered for this region and all the auxiliaries it currently uses.
     * <p>
     * @return Statistics and Info on the Region.
     */
    public ICacheStats getStatistics()
    {
        ICacheStats stats = new CacheStats();
        stats.setRegionName(this.getCacheName());

        // store the composite cache stats first
        ArrayList<IStatElement<?>> elems = new ArrayList<>();

        elems.add(new StatElement<>("HitCountRam", Long.valueOf(getHitCountRam())));
        elems.add(new StatElement<>("HitCountAux", Long.valueOf(getHitCountAux())));

        stats.setStatElements(elems);

        // memory + aux, memory is not considered an auxiliary internally
        int total = auxCaches.length + 1;
        ArrayList<IStats> auxStats = new ArrayList<>(total);

        auxStats.add(getMemoryCache().getStatistics());

        for (AuxiliaryCache<K, V> aux : auxCaches)
        {
            auxStats.add(aux.getStatistics());
        }

        // store the auxiliary stats
        stats.setAuxiliaryCacheStats(auxStats);

        return stats;
    }

    /**
     * Gets the cacheName attribute of the Cache object. This is also known as the region name.
     * <p>
     * @return The cacheName value
     */
    @Override
    public String getCacheName()
    {
        return cacheAttr.getCacheName();
    }

    /**
     * Gets the default element attribute of the Cache object This returns a copy. It does not
     * return a reference to the attributes.
     * <p>
     * @return The attributes value
     */
    public IElementAttributes getElementAttributes()
    {
        if (attr != null)
        {
            return attr.clone();
        }
        return null;
    }

    /**
     * Sets the default element attribute of the Cache object.
     * <p>
     * @param attr
     */
    public void setElementAttributes(IElementAttributes attr)
    {
        this.attr = attr;
    }

    /**
     * Gets the ICompositeCacheAttributes attribute of the Cache object.
     * <p>
     * @return The ICompositeCacheAttributes value
     */
    public ICompositeCacheAttributes getCacheAttributes()
    {
        return this.cacheAttr;
    }

    /**
     * Sets the ICompositeCacheAttributes attribute of the Cache object.
     * <p>
     * @param cattr The new ICompositeCacheAttributes value
     */
    public void setCacheAttributes(ICompositeCacheAttributes cattr)
    {
        this.cacheAttr = cattr;
        // need a better way to do this, what if it is in error
        this.memCache.initialize(this);
    }

    /**
     * Gets the elementAttributes attribute of the Cache object.
     * <p>
     * @param key
     * @return The elementAttributes value
     * @throws CacheException
     * @throws IOException
     */
    public IElementAttributes getElementAttributes(K key)
        throws CacheException, IOException
    {
        ICacheElement<K, V> ce = get(key);
        if (ce == null)
        {
            throw new ObjectNotFoundException("key " + key + " is not found");
        }
        return ce.getElementAttributes();
    }

    /**
     * Determine if the element is expired based on the values of the element attributes
     *
     * @param element the element
     *
     * @return true if the element is expired
     */
    public boolean isExpired(ICacheElement<K, V> element)
    {
        return isExpired(element, System.currentTimeMillis(),
                ElementEventType.EXCEEDED_MAXLIFE_ONREQUEST,
                ElementEventType.EXCEEDED_IDLETIME_ONREQUEST);
    }

    /**
     * Check if the element is expired based on the values of the element attributes
     *
     * @param element the element
     * @param timestamp the timestamp to compare to
     * @param eventMaxlife the event to fire in case the max life time is exceeded
     * @param eventIdle the event to fire in case the idle time is exceeded
     *
     * @return true if the element is expired
     */
    public boolean isExpired(ICacheElement<K, V> element, long timestamp,
            ElementEventType eventMaxlife, ElementEventType eventIdle)
    {
        try
        {
            IElementAttributes attributes = element.getElementAttributes();

            if (!attributes.getIsEternal())
            {
                // Remove if maxLifeSeconds exceeded
                long maxLifeSeconds = attributes.getMaxLife();
                long createTime = attributes.getCreateTime();

                final long timeFactorForMilliseconds = attributes.getTimeFactorForMilliseconds();

                if (maxLifeSeconds != -1 && (timestamp - createTime) > (maxLifeSeconds * timeFactorForMilliseconds))
                {
                    log.debug("Exceeded maxLife: {0}", () -> element.getKey());

                    handleElementEvent(element, eventMaxlife);
                    return true;
                }
                long idleTime = attributes.getIdleTime();
                long lastAccessTime = attributes.getLastAccessTime();

                // Remove if maxIdleTime exceeded
                // If you have a 0 size memory cache, then the last access will
                // not get updated.
                // you will need to set the idle time to -1.
                if ((idleTime != -1) && (timestamp - lastAccessTime) > idleTime * timeFactorForMilliseconds)
                {
                    log.debug("Exceeded maxIdle: {0}", () -> element.getKey());

                    handleElementEvent(element, eventIdle);
                    return true;
                }
            }
        }
        catch (Exception e)
        {
            log.error("Error determining expiration period, expiring", e);
            return true;
        }

        return false;
    }

    /**
     * If there are event handlers for the item, then create an event and queue it up.
     * <p>
     * This does not call handle directly; instead the handler and the event are put into a queue.
     * This prevents the event handling from blocking normal cache operations.
     * <p>
     * @param element the item
     * @param eventType the event type
     */
    public void handleElementEvent(ICacheElement<K, V> element, ElementEventType eventType)
    {
        ArrayList<IElementEventHandler> eventHandlers = element.getElementAttributes().getElementEventHandlers();
        if (eventHandlers != null)
        {
            log.debug("Element Handlers are registered.  Create event type {0}", eventType);
            if (elementEventQ == null)
            {
                log.warn("No element event queue available for cache {0}", getCacheName());
                return;
            }
            IElementEvent<ICacheElement<K, V>> event = new ElementEvent<>(element, eventType);
            for (IElementEventHandler hand : eventHandlers)
            {
                try
                {
                   elementEventQ.addElementEvent(hand, event);
                }
                catch (IOException e)
                {
                    log.error("Trouble adding element event to queue", e);
                }
            }
        }
    }

    /**
     * Create the MemoryCache based on the config parameters.
     * TODO: consider making this an auxiliary, despite its close tie to the CacheHub.
     * TODO: might want to create a memory cache config file separate from that of the hub -- ICompositeCacheAttributes
     * <p>
     * @param cattr
     */
    private void createMemoryCache(ICompositeCacheAttributes cattr)
    {
        if (memCache == null)
        {
            try
            {
                Class<?> c = Class.forName(cattr.getMemoryCacheName());
                @SuppressWarnings("unchecked") // Need cast
                IMemoryCache<K, V> newInstance = (IMemoryCache<K, V>) c.newInstance();
                memCache = newInstance;
                memCache.initialize(this);
            }
            catch (Exception e)
            {
                log.warn("Failed to init mem cache, using: LRUMemoryCache", e);

                this.memCache = new LRUMemoryCache<>();
                this.memCache.initialize(this);
            }
        }
        else
        {
            log.warn("Refusing to create memory cache -- already exists.");
        }
    }

    /**
     * Access to the memory cache for instrumentation.
     * <p>
     * @return the MemoryCache implementation
     */
    public IMemoryCache<K, V> getMemoryCache()
    {
        return memCache;
    }

    /**
     * Number of times a requested item was found in the memory cache.
     * <p>
     * @return number of hits in memory
     */
    public long getHitCountRam()
    {
        return hitCountRam.get();
    }

    /**
     * Number of times a requested item was found in and auxiliary cache.
     * @return number of auxiliary hits.
     */
    public long getHitCountAux()
    {
        return hitCountAux.get();
    }

    /**
     * Number of times a requested element was not found.
     * @return number of misses.
     */
    public long getMissCountNotFound()
    {
        return missCountNotFound.get();
    }

    /**
     * Number of times a requested element was found but was expired.
     * @return number of found but expired gets.
     */
    public long getMissCountExpired()
    {
        return missCountExpired.get();
    }

    /**
     * @return Returns the updateCount.
     */
    public long getUpdateCount()
    {
        return updateCount.get();
    }

    /**
     * Sets the key matcher used by get matching.
     * <p>
     * @param keyMatcher
     */
    @Override
    public void setKeyMatcher(IKeyMatcher<K> keyMatcher)
    {
        if (keyMatcher != null)
        {
            this.keyMatcher = keyMatcher;
        }
    }

    /**
     * Returns the key matcher used by get matching.
     * <p>
     * @return keyMatcher
     */
    public IKeyMatcher<K> getKeyMatcher()
    {
        return this.keyMatcher;
    }

    /**
     * This returns the stats.
     * <p>
     * @return getStats()
     */
    @Override
    public String toString()
    {
        return getStats();
    }
}
