package org.apache.commons.jcs.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.jcs.access.exception.CacheException;
import org.apache.commons.jcs.access.exception.ObjectNotFoundException;
import org.apache.commons.jcs.auxiliary.AuxiliaryCache;
import org.apache.commons.jcs.engine.CacheStatus;
import org.apache.commons.jcs.engine.behavior.ICache;
import org.apache.commons.jcs.engine.behavior.ICacheElement;
import org.apache.commons.jcs.engine.behavior.ICompositeCacheAttributes;
import org.apache.commons.jcs.engine.behavior.ICompositeCacheAttributes.DiskUsagePattern;
import org.apache.commons.jcs.engine.behavior.IElementAttributes;
import org.apache.commons.jcs.engine.behavior.IRequireScheduler;
import org.apache.commons.jcs.engine.control.event.ElementEvent;
import org.apache.commons.jcs.engine.control.event.behavior.ElementEventType;
import org.apache.commons.jcs.engine.control.event.behavior.IElementEvent;
import org.apache.commons.jcs.engine.control.event.behavior.IElementEventHandler;
import org.apache.commons.jcs.engine.control.event.behavior.IElementEventQueue;
import org.apache.commons.jcs.engine.control.group.GroupId;
import org.apache.commons.jcs.engine.match.KeyMatcherPatternImpl;
import org.apache.commons.jcs.engine.match.behavior.IKeyMatcher;
import org.apache.commons.jcs.engine.memory.behavior.IMemoryCache;
import org.apache.commons.jcs.engine.memory.lru.LRUMemoryCache;
import org.apache.commons.jcs.engine.memory.shrinking.ShrinkerThread;
import org.apache.commons.jcs.engine.stats.CacheStats;
import org.apache.commons.jcs.engine.stats.StatElement;
import org.apache.commons.jcs.engine.stats.behavior.ICacheStats;
import org.apache.commons.jcs.engine.stats.behavior.IStatElement;
import org.apache.commons.jcs.engine.stats.behavior.IStats;
import org.apache.commons.jcs.log.Log;
import org.apache.commons.jcs.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 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 AtomicLong updateCount;

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

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

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

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

    /** Count of misses where element was expired. */
    private 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.jcs.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.jcs.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.jcs.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.jcs.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();
    }
}
