package org.apache.commons.jcs3.auxiliary.remote.server;

/*
 * 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.io.Serializable;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.rmi.server.RMISocketFactory;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.server.Unreferenced;
import java.util.Collections;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.commons.jcs3.access.exception.CacheException;
import org.apache.commons.jcs3.auxiliary.remote.behavior.IRemoteCacheListener;
import org.apache.commons.jcs3.auxiliary.remote.server.behavior.IRemoteCacheServer;
import org.apache.commons.jcs3.auxiliary.remote.server.behavior.IRemoteCacheServerAttributes;
import org.apache.commons.jcs3.auxiliary.remote.server.behavior.RemoteType;
import org.apache.commons.jcs3.engine.CacheEventQueueFactory;
import org.apache.commons.jcs3.engine.CacheListeners;
import org.apache.commons.jcs3.engine.behavior.ICacheElement;
import org.apache.commons.jcs3.engine.behavior.ICacheEventQueue;
import org.apache.commons.jcs3.engine.behavior.ICacheListener;
import org.apache.commons.jcs3.engine.control.CompositeCache;
import org.apache.commons.jcs3.engine.control.CompositeCacheManager;
import org.apache.commons.jcs3.engine.logging.CacheEvent;
import org.apache.commons.jcs3.engine.logging.behavior.ICacheEvent;
import org.apache.commons.jcs3.engine.logging.behavior.ICacheEventLogger;
import org.apache.commons.jcs3.log.Log;
import org.apache.commons.jcs3.log.LogManager;
import org.apache.commons.jcs3.utils.timing.ElapsedTimer;

/**
 * This class provides remote cache services. The remote cache server propagates events from local
 * caches to other local caches. It can also store cached data, making it available to new clients.
 * <p>
 * Remote cache servers can be clustered. If the cache used by this remote cache is configured to
 * use a remote cache of type cluster, the two remote caches will communicate with each other.
 * Remote and put requests can be sent from one remote to another. If they are configured to
 * broadcast such event to their client, then remove an puts can be sent to all locals in the
 * cluster.
 * <p>
 * Get requests are made between clustered servers if AllowClusterGet is true. You can setup several
 * clients to use one remote server and several to use another. The get local will be distributed
 * between the two servers. Since caches are usually high get and low put, this should allow you to
 * scale.
 */
public class RemoteCacheServer<K, V>
    extends UnicastRemoteObject
    implements IRemoteCacheServer<K, V>, Unreferenced
{
    public static final String DFEAULT_REMOTE_CONFIGURATION_FILE = "/remote.cache.ccf";

    /** For serialization. Don't change. */
    private static final long serialVersionUID = -8072345435941473116L;

    /** log instance */
    private static final Log log = LogManager.getLog( RemoteCacheServer.class );

    /** Number of puts into the cache. */
    private int puts = 0;

    /** Maps cache name to CacheListeners object. association of listeners (regions). */
    private final transient ConcurrentMap<String, CacheListeners<K, V>> cacheListenersMap =
        new ConcurrentHashMap<>();

    /** maps cluster listeners to regions. */
    private final transient ConcurrentMap<String, CacheListeners<K, V>> clusterListenersMap =
        new ConcurrentHashMap<>();

    /** The central hub */
    private transient CompositeCacheManager cacheManager;

    /** relates listener id with a type */
    private final ConcurrentMap<Long, RemoteType> idTypeMap = new ConcurrentHashMap<>();

    /** relates listener id with an ip address */
    private final ConcurrentMap<Long, String> idIPMap = new ConcurrentHashMap<>();

    /** Used to get the next listener id. */
    private final int[] listenerId = new int[1];

    /** Configuration settings. */
    // package protected for access by unit test code
    final IRemoteCacheServerAttributes remoteCacheServerAttributes;

    /** The interval at which we will log updates. */
    private final int logInterval = 100;

    /** An optional event logger */
    private transient ICacheEventLogger cacheEventLogger;

    /**
     * Constructor for the RemoteCacheServer object. This initializes the server with the values
     * from the properties object.
     * <p>
     * @param rcsa
     * @param config cache hub configuration
     * @throws RemoteException
     */
    protected RemoteCacheServer( IRemoteCacheServerAttributes rcsa, Properties config )
        throws RemoteException
    {
        super( rcsa.getServicePort() );
        this.remoteCacheServerAttributes = rcsa;
        init( config );
    }

    /**
     * Constructor for the RemoteCacheServer object. This initializes the server with the values
     * from the properties object.
     * <p>
     * @param rcsa
     * @param config cache hub configuration
     * @param customRMISocketFactory
     * @throws RemoteException
     */
    protected RemoteCacheServer( IRemoteCacheServerAttributes rcsa, Properties config, RMISocketFactory customRMISocketFactory )
        throws RemoteException
    {
        super( rcsa.getServicePort(), customRMISocketFactory, customRMISocketFactory );
        this.remoteCacheServerAttributes = rcsa;
        init( config );
    }

    /**
     * Initialize the RMI Cache Server from a properties object.
     * <p>
     * @param prop the configuration properties
     * @throws RemoteException if the configuration of the cache manager instance fails
     */
    private void init( Properties prop ) throws RemoteException
    {
        try
        {
            cacheManager = createCacheManager( prop );
        }
        catch (CacheException e)
        {
            throw new RemoteException(e.getMessage(), e);
        }

        // cacheManager would have created a number of ICache objects.
        // Use these objects to set up the cacheListenersMap.
        cacheManager.getCacheNames().forEach(name -> {
            CompositeCache<K, V> cache = cacheManager.getCache( name );
            cacheListenersMap.put( name, new CacheListeners<>( cache ) );
        });
    }

    /**
     * Subclass can override this method to create the specific cache manager.
     * <p>
     * @param prop the configuration object.
     * @return The cache hub configured with this configuration.
     *
     * @throws CacheException if the configuration cannot be loaded
     */
    private CompositeCacheManager createCacheManager( Properties prop ) throws CacheException
    {
        CompositeCacheManager hub = CompositeCacheManager.getUnconfiguredInstance();
        hub.configure( prop );
        return hub;
    }

    /**
     * Puts a cache bean to the remote cache and notifies all listeners which <br>
     * <ol>
     * <li>have a different listener id than the originating host;</li>
     * <li>are currently subscribed to the related cache.</li>
     * </ol>
     * <p>
     * @param item
     * @throws IOException
     */
    public void put( ICacheElement<K, V> item )
        throws IOException
    {
        update( item );
    }

    /**
     * @param item
     * @throws IOException
     */
    @Override
    public void update( ICacheElement<K, V> item )
        throws IOException
    {
        update( item, 0 );
    }

    /**
     * The internal processing is wrapped in event logging calls.
     * <p>
     * @param item
     * @param requesterId
     * @throws IOException
     */
    @Override
    public void update( ICacheElement<K, V> item, long requesterId )
        throws IOException
    {
        ICacheEvent<ICacheElement<K, V>> cacheEvent = createICacheEvent( item, requesterId, ICacheEventLogger.UPDATE_EVENT );
        try
        {
            processUpdate( item, requesterId );
        }
        finally
        {
            logICacheEvent( cacheEvent );
        }
    }

    /**
     * An update can come from either a local cache's remote auxiliary, or it can come from a remote
     * server. A remote server is considered a a source of type cluster.
     * <p>
     * If the update came from a cluster, then we should tell the cache manager that this was a
     * remote put. This way, any lateral and remote auxiliaries configured for the region will not
     * be updated. This is basically how a remote listener works when plugged into a local cache.
     * <p>
     * If the cluster is configured to keep local cluster consistency, then all listeners will be
     * updated. This allows cluster server A to update cluster server B and then B to update its
     * clients if it is told to keep local cluster consistency. Otherwise, server A will update
     * server B and B will not tell its clients. If you cluster using lateral caches for instance,
     * this is how it will work. Updates to a cluster node, will never get to the leaves. The remote
     * cluster, with local cluster consistency, allows you to update leaves. This basically allows
     * you to have a failover remote server.
     * <p>
     * Since currently a cluster will not try to get from other cluster servers, you can scale a bit
     * with a cluster configuration. Puts and removes will be broadcasted to all clients, but the
     * get load on a remote server can be reduced.
     * <p>
     * @param item
     * @param requesterId
     */
    private void processUpdate( ICacheElement<K, V> item, long requesterId )
    {
        ElapsedTimer timer = new ElapsedTimer();
        logUpdateInfo( item );

        try
        {
            CacheListeners<K, V> cacheDesc = getCacheListeners( item.getCacheName() );
            /* Object val = */item.getVal();

            boolean fromCluster = isRequestFromCluster( requesterId );

            log.debug( "In update, requesterId = [{0}] fromCluster = {1}", requesterId, fromCluster );

            // ordered cache item update and notification.
            synchronized ( cacheDesc )
            {
                try
                {
                    CompositeCache<K, V> c = (CompositeCache<K, V>) cacheDesc.cache;

                    // If the source of this request was not from a cluster,
                    // then consider it a local update. The cache manager will
                    // try to
                    // update all auxiliaries.
                    //
                    // This requires that two local caches not be connected to
                    // two clustered remote caches. The failover runner will
                    // have to make sure of this. ALos, the local cache needs
                    // avoid updating this source. Will need to pass the source
                    // id somehow. The remote cache should update all local
                    // caches
                    // but not update the cluster source. Cluster remote caches
                    // should only be updated by the server and not the
                    // RemoteCache.
                    if ( fromCluster )
                    {
                        log.debug( "Put FROM cluster, NOT updating other auxiliaries for region. "
                                + " requesterId [{0}]", requesterId );
                        c.localUpdate( item );
                    }
                    else
                    {
                        log.debug( "Put NOT from cluster, updating other auxiliaries for region. "
                                + " requesterId [{0}]", requesterId );
                        c.update( item );
                    }
                }
                catch ( IOException ce )
                {
                    // swallow
                    log.info( "Exception caught updating item. requesterId [{0}]: {1}",
                            requesterId, ce.getMessage() );
                }

                // UPDATE LOCALS IF A REQUEST COMES FROM A CLUSTER
                // IF LOCAL CLUSTER CONSISTENCY IS CONFIGURED
                if (!fromCluster || fromCluster && remoteCacheServerAttributes.isLocalClusterConsistency())
                {
                    ICacheEventQueue<K, V>[] qlist = getEventQList( cacheDesc, requesterId );
                    log.debug( "qlist.length = {0}", qlist.length );
                    for ( int i = 0; i < qlist.length; i++ )
                    {
                        qlist[i].addPutEvent( item );
                    }
                }
            }
        }
        catch ( IOException e )
        {
            if ( cacheEventLogger != null )
            {
                cacheEventLogger.logError( "RemoteCacheServer", ICacheEventLogger.UPDATE_EVENT, e.getMessage()
                    + " REGION: " + item.getCacheName() + " ITEM: " + item );
            }

            log.error( "Trouble in Update. requesterId [{0}]", requesterId, e );
        }

        // TODO use JAMON for timing
        log.debug( "put took {0} ms.", () -> timer.getElapsedTime());
    }

    /**
     * Log some details.
     * <p>
     * @param item
     */
    private void logUpdateInfo( ICacheElement<K, V> item )
    {
        // not thread safe, but it doesn't have to be 100% accurate
        puts++;

        if ( log.isInfoEnabled() )
        {
            if ( puts % logInterval == 0 )
            {
                log.info( "puts = {0}", puts );
            }
        }

        log.debug( "In update, put [{0}] in [{1}]",
                () -> item.getKey(), () -> item.getCacheName() );
    }

    /**
     * Returns a cache value from the specified remote cache; or null if the cache or key does not
     * exist.
     * <p>
     * @param cacheName
     * @param key
     * @return ICacheElement
     * @throws IOException
     */
    @Override
    public ICacheElement<K, V> get( String cacheName, K key )
        throws IOException
    {
        return this.get( cacheName, key, 0 );
    }

    /**
     * Returns a cache bean from the specified cache; or null if the key does not exist.
     * <p>
     * Adding the requestor id, allows the cache to determine the source of the get.
     * <p>
     * The internal processing is wrapped in event logging calls.
     * <p>
     * @param cacheName
     * @param key
     * @param requesterId
     * @return ICacheElement
     * @throws IOException
     */
    @Override
    public ICacheElement<K, V> get( String cacheName, K key, long requesterId )
        throws IOException
    {
        ICacheElement<K, V> element = null;
        ICacheEvent<K> cacheEvent = createICacheEvent( cacheName, key, requesterId, ICacheEventLogger.GET_EVENT );
        try
        {
            element = processGet( cacheName, key, requesterId );
        }
        finally
        {
            logICacheEvent( cacheEvent );
        }
        return element;
    }

    /**
     * Returns a cache bean from the specified cache; or null if the key does not exist.
     * <p>
     * Adding the requester id, allows the cache to determine the source of the get.
     * <p>
     * @param cacheName
     * @param key
     * @param requesterId
     * @return ICacheElement
     */
    private ICacheElement<K, V> processGet( String cacheName, K key, long requesterId )
    {
        boolean fromCluster = isRequestFromCluster( requesterId );

        log.debug( "get [{0}] from cache [{1}] requesterId = [{2}] fromCluster = {3}",
                key, cacheName, requesterId, fromCluster );

        CacheListeners<K, V> cacheDesc = getCacheListeners( cacheName );

        ICacheElement<K, V> element = getFromCacheListeners( key, fromCluster, cacheDesc, null );
        return element;
    }

    /**
     * Gets the item from the associated cache listeners.
     * <p>
     * @param key
     * @param fromCluster
     * @param cacheDesc
     * @param element
     * @return ICacheElement
     */
    private ICacheElement<K, V> getFromCacheListeners( K key, boolean fromCluster, CacheListeners<K, V> cacheDesc,
                                                 ICacheElement<K, V> element )
    {
        ICacheElement<K, V> returnElement = element;

        if ( cacheDesc != null )
        {
            CompositeCache<K, V> c = (CompositeCache<K, V>) cacheDesc.cache;

            // If we have a get come in from a client and we don't have the item
            // locally, we will allow the cache to look in other non local sources,
            // such as a remote cache or a lateral.
            //
            // Since remote servers never get from clients and clients never go
            // remote from a remote call, this
            // will not result in any loops.
            //
            // This is the only instance I can think of where we allow a remote get
            // from a remote call. The purpose is to allow remote cache servers to
            // talk to each other. If one goes down, you want it to be able to get
            // data from those that were up when the failed server comes back o
            // line.

            if ( !fromCluster && this.remoteCacheServerAttributes.isAllowClusterGet() )
            {
                log.debug( "NonLocalGet. fromCluster [{0}] AllowClusterGet [{1}]",
                        fromCluster, this.remoteCacheServerAttributes.isAllowClusterGet() );
                returnElement = c.get( key );
            }
            else
            {
                // Gets from cluster type remote will end up here.
                // Gets from all clients will end up here if allow cluster get is
                // false.
                log.debug( "LocalGet. fromCluster [{0}] AllowClusterGet [{1}]",
                        fromCluster, this.remoteCacheServerAttributes.isAllowClusterGet() );
                returnElement = c.localGet( key );
            }
        }

        return returnElement;
    }

    /**
     * Gets all matching items.
     * <p>
     * @param cacheName
     * @param pattern
     * @return Map of keys and wrapped objects
     * @throws IOException
     */
    @Override
    public Map<K, ICacheElement<K, V>> getMatching( String cacheName, String pattern )
        throws IOException
    {
        return getMatching( cacheName, pattern, 0 );
    }

    /**
     * Retrieves all matching keys.
     * <p>
     * @param cacheName
     * @param pattern
     * @param requesterId
     * @return Map of keys and wrapped objects
     * @throws IOException
     */
    @Override
    public Map<K, ICacheElement<K, V>> getMatching( String cacheName, String pattern, long requesterId )
        throws IOException
    {
        ICacheEvent<String> cacheEvent = createICacheEvent( cacheName, pattern, requesterId,
                                                    ICacheEventLogger.GETMATCHING_EVENT );
        try
        {
            return processGetMatching( cacheName, pattern, requesterId );
        }
        finally
        {
            logICacheEvent( cacheEvent );
        }
    }

    /**
     * Retrieves all matching keys.
     * <p>
     * @param cacheName
     * @param pattern
     * @param requesterId
     * @return Map of keys and wrapped objects
     */
    protected Map<K, ICacheElement<K, V>> processGetMatching( String cacheName, String pattern, long requesterId )
    {
        boolean fromCluster = isRequestFromCluster( requesterId );

        log.debug( "getMatching [{0}] from cache [{1}] requesterId = [{2}] fromCluster = {3}",
                pattern, cacheName, requesterId, fromCluster );

        CacheListeners<K, V> cacheDesc = null;
        try
        {
            cacheDesc = getCacheListeners( cacheName );
        }
        catch ( Exception e )
        {
            log.error( "Problem getting listeners.", e );

            if ( cacheEventLogger != null )
            {
                cacheEventLogger.logError( "RemoteCacheServer", ICacheEventLogger.GETMATCHING_EVENT, e.getMessage()
                    + cacheName + " pattern: " + pattern );
            }
        }

        return getMatchingFromCacheListeners( pattern, fromCluster, cacheDesc );
    }

    /**
     * Gets the item from the associated cache listeners.
     * <p>
     * @param pattern
     * @param fromCluster
     * @param cacheDesc
     * @return Map of keys to results
     */
    private Map<K, ICacheElement<K, V>> getMatchingFromCacheListeners( String pattern, boolean fromCluster, CacheListeners<K, V> cacheDesc )
    {
        Map<K, ICacheElement<K, V>> elements = null;
        if ( cacheDesc != null )
        {
            CompositeCache<K, V> c = (CompositeCache<K, V>) cacheDesc.cache;

            // We always want to go remote and then merge the items.  But this can lead to inconsistencies after
            // failover recovery.  Removed items may show up.  There is no good way to prevent this.
            // We should make it configurable.

            if ( !fromCluster && this.remoteCacheServerAttributes.isAllowClusterGet() )
            {
                log.debug( "NonLocalGetMatching. fromCluster [{0}] AllowClusterGet [{1}]",
                        fromCluster, this.remoteCacheServerAttributes.isAllowClusterGet() );
                elements = c.getMatching( pattern );
            }
            else
            {
                // Gets from cluster type remote will end up here.
                // Gets from all clients will end up here if allow cluster get is
                // false.

                log.debug( "LocalGetMatching. fromCluster [{0}] AllowClusterGet [{1}]",
                        fromCluster, this.remoteCacheServerAttributes.isAllowClusterGet() );
                elements = c.localGetMatching( pattern );
            }
        }
        return elements;
    }

    /**
     * Gets multiple items from the cache based on the given set of keys.
     * <p>
     * @param cacheName
     * @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
     * @throws IOException
     */
    @Override
    public Map<K, ICacheElement<K, V>> getMultiple( String cacheName, Set<K> keys )
        throws IOException
    {
        return this.getMultiple( cacheName, keys, 0 );
    }

    /**
     * Gets multiple items from the cache based on the given set of keys.
     * <p>
     * The internal processing is wrapped in event logging calls.
     * <p>
     * @param cacheName
     * @param keys
     * @param requesterId
     * @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
     * @throws IOException
     */
    @Override
    public Map<K, ICacheElement<K, V>> getMultiple( String cacheName, Set<K> keys, long requesterId )
        throws IOException
    {
        ICacheEvent<Serializable> cacheEvent = createICacheEvent( cacheName, (Serializable) keys, requesterId,
                                                    ICacheEventLogger.GETMULTIPLE_EVENT );
        try
        {
            return processGetMultiple( cacheName, keys, requesterId );
        }
        finally
        {
            logICacheEvent( cacheEvent );
        }
    }

    /**
     * Gets multiple items from the cache based on the given set of keys.
     * <p>
     * @param cacheName
     * @param keys
     * @param requesterId
     * @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
     */
    private Map<K, ICacheElement<K, V>> processGetMultiple( String cacheName, Set<K> keys, long requesterId )
    {
        boolean fromCluster = isRequestFromCluster( requesterId );

        log.debug( "getMultiple [{0}] from cache [{1}] requesterId = [{2}] fromCluster = {3}",
                keys, cacheName, requesterId, fromCluster );

        CacheListeners<K, V> cacheDesc = getCacheListeners( cacheName );
        Map<K, ICacheElement<K, V>> elements = getMultipleFromCacheListeners( keys, null, fromCluster, cacheDesc );
        return elements;
    }

    /**
     * Since a non-receiving remote cache client will not register a listener, it will not have a
     * listener id assigned from the server. As such the remote server cannot determine if it is a
     * cluster or a normal client. It will assume that it is a normal client.
     * <p>
     * @param requesterId
     * @return true is from a cluster.
     */
    private boolean isRequestFromCluster( long requesterId )
    {
        RemoteType remoteTypeL = idTypeMap.get( Long.valueOf( requesterId ) );
        return remoteTypeL == RemoteType.CLUSTER;
    }

    /**
     * Gets the items from the associated cache listeners.
     * <p>
     * @param keys
     * @param elements
     * @param fromCluster
     * @param cacheDesc
     * @return Map
     */
    private Map<K, ICacheElement<K, V>> getMultipleFromCacheListeners( Set<K> keys, Map<K, ICacheElement<K, V>> elements, boolean fromCluster, CacheListeners<K, V> cacheDesc )
    {
        Map<K, ICacheElement<K, V>> returnElements = elements;

        if ( cacheDesc != null )
        {
            CompositeCache<K, V> c = (CompositeCache<K, V>) cacheDesc.cache;

            // If we have a getMultiple come in from a client and we don't have the item
            // locally, we will allow the cache to look in other non local sources,
            // such as a remote cache or a lateral.
            //
            // Since remote servers never get from clients and clients never go
            // remote from a remote call, this
            // will not result in any loops.
            //
            // This is the only instance I can think of where we allow a remote get
            // from a remote call. The purpose is to allow remote cache servers to
            // talk to each other. If one goes down, you want it to be able to get
            // data from those that were up when the failed server comes back on
            // line.

            if ( !fromCluster && this.remoteCacheServerAttributes.isAllowClusterGet() )
            {
                log.debug( "NonLocalGetMultiple. fromCluster [{0}] AllowClusterGet [{1}]",
                        fromCluster, this.remoteCacheServerAttributes.isAllowClusterGet() );

                returnElements = c.getMultiple( keys );
            }
            else
            {
                // Gets from cluster type remote will end up here.
                // Gets from all clients will end up here if allow cluster get is
                // false.

                log.debug( "LocalGetMultiple. fromCluster [{0}] AllowClusterGet [{1}]",
                        fromCluster, this.remoteCacheServerAttributes.isAllowClusterGet() );

                returnElements = c.localGetMultiple( keys );
            }
        }

        return returnElements;
    }

    /**
     * Return the keys in the cache.
     * <p>
     * @param cacheName the name of the cache region
     * @see org.apache.commons.jcs3.auxiliary.AuxiliaryCache#getKeySet()
     */
    @Override
    public Set<K> getKeySet(String cacheName) throws IOException
    {
        return processGetKeySet( cacheName );
    }

    /**
     * Gets the set of keys of objects currently in the cache.
     * <p>
     * @param cacheName
     * @return Set
     */
    protected Set<K> processGetKeySet( String cacheName )
    {
        CacheListeners<K, V> cacheDesc = getCacheListeners( cacheName );

        if ( cacheDesc == null )
        {
            return Collections.emptySet();
        }

        CompositeCache<K, V> c = (CompositeCache<K, V>) cacheDesc.cache;
        return c.getKeySet();
    }

    /**
     * Removes the given key from the specified remote cache. Defaults the listener id to 0.
     * <p>
     * @param cacheName
     * @param key
     * @throws IOException
     */
    @Override
    public void remove( String cacheName, K key )
        throws IOException
    {
        remove( cacheName, key, 0 );
    }

    /**
     * Remove the key from the cache region and don't tell the source listener about it.
     * <p>
     * The internal processing is wrapped in event logging calls.
     * <p>
     * @param cacheName
     * @param key
     * @param requesterId
     * @throws IOException
     */
    @Override
    public void remove( String cacheName, K key, long requesterId )
        throws IOException
    {
        ICacheEvent<K> cacheEvent = createICacheEvent( cacheName, key, requesterId, ICacheEventLogger.REMOVE_EVENT );
        try
        {
            processRemove( cacheName, key, requesterId );
        }
        finally
        {
            logICacheEvent( cacheEvent );
        }
    }

    /**
     * Remove the key from the cache region and don't tell the source listener about it.
     * <p>
     * @param cacheName
     * @param key
     * @param requesterId
     * @throws IOException
     */
    private void processRemove( String cacheName, K key, long requesterId )
        throws IOException
    {
        log.debug( "remove [{0}] from cache [{1}]", key, cacheName );

        CacheListeners<K, V> cacheDesc = cacheListenersMap.get( cacheName );

        boolean fromCluster = isRequestFromCluster( requesterId );

        if ( cacheDesc != null )
        {
            // best attempt to achieve ordered cache item removal and
            // notification.
            synchronized ( cacheDesc )
            {
                boolean removeSuccess = false;

                // No need to notify if it was not cached.
                CompositeCache<K, V> c = (CompositeCache<K, V>) cacheDesc.cache;

                if ( fromCluster )
                {
                    log.debug( "Remove FROM cluster, NOT updating other auxiliaries for region" );
                    removeSuccess = c.localRemove( key );
                }
                else
                {
                    log.debug( "Remove NOT from cluster, updating other auxiliaries for region" );
                    removeSuccess = c.remove( key );
                }

                log.debug( "remove [{0}] from cache [{1}] success (was it found) = {2}",
                        key, cacheName, removeSuccess );

                // UPDATE LOCALS IF A REQUEST COMES FROM A CLUSTER
                // IF LOCAL CLUSTER CONSISTENCY IS CONFIGURED
                if (!fromCluster || fromCluster && remoteCacheServerAttributes.isLocalClusterConsistency())
                {
                    ICacheEventQueue<K, V>[] qlist = getEventQList( cacheDesc, requesterId );

                    for ( int i = 0; i < qlist.length; i++ )
                    {
                        qlist[i].addRemoveEvent( key );
                    }
                }
            }
        }
    }

    /**
     * Remove all keys from the specified remote cache.
     * <p>
     * @param cacheName
     * @throws IOException
     */
    @Override
    public void removeAll( String cacheName )
        throws IOException
    {
        removeAll( cacheName, 0 );
    }

    /**
     * Remove all keys from the specified remote cache.
     * <p>
     * The internal processing is wrapped in event logging calls.
     * <p>
     * @param cacheName
     * @param requesterId
     * @throws IOException
     */
    @Override
    public void removeAll( String cacheName, long requesterId )
        throws IOException
    {
        ICacheEvent<String> cacheEvent = createICacheEvent( cacheName, "all", requesterId, ICacheEventLogger.REMOVEALL_EVENT );
        try
        {
            processRemoveAll( cacheName, requesterId );
        }
        finally
        {
            logICacheEvent( cacheEvent );
        }
    }

    /**
     * Remove all keys from the specified remote cache.
     * <p>
     * @param cacheName
     * @param requesterId
     * @throws IOException
     */
    private void processRemoveAll( String cacheName, long requesterId )
        throws IOException
    {
        CacheListeners<K, V> cacheDesc = cacheListenersMap.get( cacheName );

        boolean fromCluster = isRequestFromCluster( requesterId );

        if ( cacheDesc != null )
        {
            // best attempt to achieve ordered cache item removal and
            // notification.
            synchronized ( cacheDesc )
            {
                // No need to broadcast, or notify if it was not cached.
                CompositeCache<K, V> c = (CompositeCache<K, V>) cacheDesc.cache;

                if ( fromCluster )
                {
                    log.debug( "RemoveALL FROM cluster, NOT updating other auxiliaries for region" );
                    c.localRemoveAll();
                }
                else
                {
                    log.debug( "RemoveALL NOT from cluster, updating other auxiliaries for region" );
                    c.removeAll();
                }

                // update registered listeners
                if (!fromCluster || fromCluster && remoteCacheServerAttributes.isLocalClusterConsistency())
                {
                    ICacheEventQueue<K, V>[] qlist = getEventQList( cacheDesc, requesterId );

                    for (ICacheEventQueue<K, V> q : qlist)
                    {
                        q.addRemoveAllEvent();
                    }
                }
            }
        }
    }

    /**
     * How many put events have we received.
     * <p>
     * @return puts
     */
    // Currently only intended for use by unit tests
    int getPutCount()
    {
        return puts;
    }

    /**
     * Frees the specified remote cache.
     * <p>
     * @param cacheName
     * @throws IOException
     */
    @Override
    public void dispose( String cacheName )
        throws IOException
    {
        dispose( cacheName, 0 );
    }

    /**
     * Frees the specified remote cache.
     * <p>
     * @param cacheName
     * @param requesterId
     * @throws IOException
     */
    public void dispose( String cacheName, long requesterId )
        throws IOException
    {
        ICacheEvent<String> cacheEvent = createICacheEvent( cacheName, "none", requesterId, ICacheEventLogger.DISPOSE_EVENT );
        try
        {
            processDispose( cacheName, requesterId );
        }
        finally
        {
            logICacheEvent( cacheEvent );
        }
    }

    /**
     * @param cacheName
     * @param requesterId
     * @throws IOException
     */
    private void processDispose( String cacheName, long requesterId )
        throws IOException
    {
        log.info( "Dispose request received from listener [{0}]", requesterId );

        CacheListeners<K, V> cacheDesc = cacheListenersMap.get( cacheName );

        // this is dangerous
        if ( cacheDesc != null )
        {
            // best attempt to achieve ordered free-cache-op and notification.
            synchronized ( cacheDesc )
            {
                ICacheEventQueue<K, V>[] qlist = getEventQList( cacheDesc, requesterId );

                for ( int i = 0; i < qlist.length; i++ )
                {
                    qlist[i].addDisposeEvent();
                }
                cacheManager.freeCache( cacheName );
            }
        }
    }

    /**
     * Frees all remote caches.
     * <p>
     * @throws IOException
     */
    @Override
    public void release()
        throws IOException
    {
        for (CacheListeners<K, V> cacheDesc : cacheListenersMap.values())
        {
            ICacheEventQueue<K, V>[] qlist = getEventQList( cacheDesc, 0 );

            for ( int i = 0; i < qlist.length; i++ )
            {
                qlist[i].addDisposeEvent();
            }
        }
        cacheManager.release();
    }

    /**
     * Returns the cache listener for the specified cache. Creates the cache and the cache
     * descriptor if they do not already exist.
     * <p>
     * @param cacheName
     * @return The cacheListeners value
     */
    protected CacheListeners<K, V> getCacheListeners( String cacheName )
    {
        CacheListeners<K, V> cacheListeners = cacheListenersMap.computeIfAbsent(cacheName, key -> {
            CompositeCache<K, V> cache = cacheManager.getCache(key);
            return new CacheListeners<>( cache );
        });

        return cacheListeners;
    }

    /**
     * Gets the clusterListeners attribute of the RemoteCacheServer object.
     * <p>
     * TODO may be able to remove this
     * @param cacheName
     * @return The clusterListeners value
     */
    protected CacheListeners<K, V> getClusterListeners( String cacheName )
    {
        CacheListeners<K, V> cacheListeners = clusterListenersMap.computeIfAbsent(cacheName, key -> {
            CompositeCache<K, V> cache = cacheManager.getCache( cacheName );
            return new CacheListeners<>( cache );
        });

        return cacheListeners;
    }

    /**
     * Gets the eventQList attribute of the RemoteCacheServer object. This returns the event queues
     * stored in the cacheListeners object for a particular region, if the queue is not for this
     * requester.
     * <p>
     * Basically, this makes sure that a request from a particular local cache, identified by its
     * listener id, does not result in a call to that same listener.
     * <p>
     * @param cacheListeners
     * @param requesterId
     * @return The eventQList value
     */
    @SuppressWarnings("unchecked") // No generic arrays in java
    private ICacheEventQueue<K, V>[] getEventQList( CacheListeners<K, V> cacheListeners, long requesterId )
    {
        ICacheEventQueue<K, V>[] list = cacheListeners.eventQMap.values().toArray( new ICacheEventQueue[0] );
        int count = 0;
        // Set those not qualified to null; Count those qualified.
        for ( int i = 0; i < list.length; i++ )
        {
            ICacheEventQueue<K, V> q = list[i];
            if ( q.isWorking() && q.getListenerId() != requesterId )
            {
                count++;
            }
            else
            {
                list[i] = null;
            }
        }
        if ( count == list.length )
        {
            // All qualified.
            return list;
        }

        // Returns only the qualified.
        ICacheEventQueue<K, V>[] qq = new ICacheEventQueue[count];
        count = 0;
        for ( int i = 0; i < list.length; i++ )
        {
            if ( list[i] != null )
            {
                qq[count++] = list[i];
            }
        }
        return qq;
    }

    /**
     * Removes dead event queues. Should clean out deregistered listeners.
     * <p>
     * @param eventQMap
     */
    private static <KK, VV> void cleanupEventQMap( Map<Long, ICacheEventQueue<KK, VV>> eventQMap )
    {
        // this does not care if the q is alive (i.e. if
        // there are active threads; it cares if the queue
        // is working -- if it has not encountered errors
        // above the failure threshold
        eventQMap.entrySet().removeIf(e -> !e.getValue().isWorking());
    }

    /**
     * Subscribes to the specified remote cache.
     * <p>
     * If the client id is 0, then the remote cache server will increment it's local count and
     * assign an id to the client.
     * <p>
     * @param cacheName the specified remote cache.
     * @param listener object to notify for cache changes. must be synchronized since there are
     *            remote calls involved.
     * @throws IOException
     */
    @Override
    @SuppressWarnings("unchecked") // Need to cast to specific return type from getClusterListeners()
    public <KK, VV> void addCacheListener( String cacheName, ICacheListener<KK, VV> listener )
        throws IOException
    {
        if ( cacheName == null || listener == null )
        {
            throw new IllegalArgumentException( "cacheName and listener must not be null" );
        }
        CacheListeners<KK, VV> cacheListeners;

        IRemoteCacheListener<KK, VV> ircl = (IRemoteCacheListener<KK, VV>) listener;

        String listenerAddress = ircl.getLocalHostAddress();

        RemoteType remoteType = ircl.getRemoteType();
        if ( remoteType == RemoteType.CLUSTER )
        {
            log.debug( "adding cluster listener, listenerAddress [{0}]", listenerAddress );
            cacheListeners = (CacheListeners<KK, VV>)getClusterListeners( cacheName );
        }
        else
        {
            log.debug( "adding normal listener, listenerAddress [{0}]", listenerAddress );
            cacheListeners = (CacheListeners<KK, VV>)getCacheListeners( cacheName );
        }
        Map<Long, ICacheEventQueue<KK, VV>> eventQMap = cacheListeners.eventQMap;
        cleanupEventQMap( eventQMap );

        // synchronized ( listenerId )
        synchronized ( ICacheListener.class )
        {
            long id = 0;
            try
            {
                id = listener.getListenerId();
                // clients probably shouldn't do this.
                if ( id == 0 )
                {
                    // must start at one so the next gets recognized
                    long listenerIdB = nextListenerId();
                    log.debug( "listener id={0} addded for cache [{1}], listenerAddress [{2}]",
                            listenerIdB & 0xff, cacheName, listenerAddress );
                    listener.setListenerId( listenerIdB );
                    id = listenerIdB;

                    // in case it needs synchronization
                    String message = "Adding vm listener under new id = [" + listenerIdB + "], listenerAddress ["
                        + listenerAddress + "]";
                    logApplicationEvent( "RemoteCacheServer", "addCacheListener", message );
                    log.info( message );
                }
                else
                {
                    String message = "Adding listener under existing id = [" + id + "], listenerAddress ["
                        + listenerAddress + "]";
                    logApplicationEvent( "RemoteCacheServer", "addCacheListener", message );
                    log.info( message );
                    // should confirm the the host is the same as we have on
                    // record, just in case a client has made a mistake.
                }

                // relate the type to an id
                this.idTypeMap.put( Long.valueOf( id ), remoteType);
                if ( listenerAddress != null )
                {
                    this.idIPMap.put( Long.valueOf( id ), listenerAddress );
                }
            }
            catch ( IOException ioe )
            {
                String message = "Problem setting listener id, listenerAddress [" + listenerAddress + "]";
                log.error( message, ioe );

                if ( cacheEventLogger != null )
                {
                    cacheEventLogger.logError( "RemoteCacheServer", "addCacheListener", message + " - "
                        + ioe.getMessage() );
                }
            }

            CacheEventQueueFactory<KK, VV> fact = new CacheEventQueueFactory<>();
            ICacheEventQueue<KK, VV> q = fact.createCacheEventQueue( listener, id, cacheName, remoteCacheServerAttributes
                .getEventQueuePoolName(), remoteCacheServerAttributes.getEventQueueType() );

            eventQMap.put(Long.valueOf(listener.getListenerId()), q);

            log.info( cacheListeners );
        }
    }

    /**
     * Subscribes to all remote caches.
     * <p>
     * @param listener The feature to be added to the CacheListener attribute
     * @throws IOException
     */
    @Override
    public <KK, VV> void addCacheListener( ICacheListener<KK, VV> listener )
        throws IOException
    {
        for (String cacheName : cacheListenersMap.keySet())
        {
            addCacheListener( cacheName, listener );

            log.debug( "Adding listener for cache [{0}]", cacheName );
        }
    }

    /**
     * Unsubscribe this listener from this region. If the listener is registered, it will be removed
     * from the event queue map list.
     * <p>
     * @param cacheName
     * @param listener
     * @throws IOException
     */
    @Override
    public <KK, VV> void removeCacheListener( String cacheName, ICacheListener<KK, VV> listener )
        throws IOException
    {
        removeCacheListener( cacheName, listener.getListenerId() );
    }

    /**
     * Unsubscribe this listener from this region. If the listener is registered, it will be removed
     * from the event queue map list.
     * <p>
     * @param cacheName
     * @param listenerId
     */
    public void removeCacheListener( String cacheName, long listenerId )
    {
        String message = "Removing listener for cache region = [" + cacheName + "] and listenerId [" + listenerId + "]";
        logApplicationEvent( "RemoteCacheServer", "removeCacheListener", message );
        log.info( message );

        boolean isClusterListener = isRequestFromCluster( listenerId );

        CacheListeners<K, V> cacheDesc = null;

        if ( isClusterListener )
        {
            cacheDesc = getClusterListeners( cacheName );
        }
        else
        {
            cacheDesc = getCacheListeners( cacheName );
        }
        Map<Long, ICacheEventQueue<K, V>> eventQMap = cacheDesc.eventQMap;
        cleanupEventQMap( eventQMap );
        ICacheEventQueue<K, V> q = eventQMap.remove( Long.valueOf( listenerId ) );

        if ( q != null )
        {
            log.debug( "Found queue for cache region = [{0}] and listenerId [{1}]",
                    cacheName, listenerId );
            q.destroy();
            cleanupEventQMap( eventQMap );
        }
        else
        {
            log.debug( "Did not find queue for cache region = [{0}] and listenerId [{1}]",
                    cacheName, listenerId );
        }

        // cleanup
        idTypeMap.remove( Long.valueOf( listenerId ) );
        idIPMap.remove( Long.valueOf( listenerId ) );

        log.info( "After removing listener [{0}] cache region {1} listener size [{2}]",
                listenerId, cacheName, eventQMap.size() );
    }

    /**
     * Unsubscribes from all remote caches.
     * <p>
     * @param listener
     * @throws IOException
     */
    @Override
    public <KK, VV> void removeCacheListener( ICacheListener<KK, VV> listener )
        throws IOException
    {
        for (String cacheName : cacheListenersMap.keySet())
        {
            removeCacheListener( cacheName, listener );

            log.info( "Removing listener for cache [{0}]", cacheName );
        }
    }

    /**
     * Shuts down the remote server.
     * <p>
     * @throws IOException
     */
    @Override
    public void shutdown()
        throws IOException
    {
        shutdown("", Registry.REGISTRY_PORT);
    }

    /**
     * Shuts down a server at a particular host and port. Then it calls shutdown on the cache
     * itself.
     * <p>
     * @param host
     * @param port
     * @throws IOException
     */
    @Override
    public void shutdown( String host, int port )
        throws IOException
    {
        log.info( "Received shutdown request. Shutting down server." );

        synchronized (listenerId)
        {
            for (String cacheName : cacheListenersMap.keySet())
            {
                for (int i = 0; i <= listenerId[0]; i++)
                {
                    removeCacheListener( cacheName, i );
                }

                log.info( "Removing listener for cache [{0}]", cacheName );
            }

            cacheListenersMap.clear();
            clusterListenersMap.clear();
        }
        RemoteCacheServerFactory.shutdownImpl( host, port );
        this.cacheManager.shutDown();
    }

    /**
     * Called by the RMI runtime sometime after the runtime determines that the reference list, the
     * list of clients referencing the remote object, becomes empty.
     */
    // TODO: test out the DGC.
    @Override
    public void unreferenced()
    {
        log.info( "*** Server now unreferenced and subject to GC. ***" );
    }

    /**
     * Returns the next generated listener id [0,255].
     * <p>
     * @return the listener id of a client. This should be unique for this server.
     */
    private long nextListenerId()
    {
        long id = 0;
        if ( listenerId[0] == Integer.MAX_VALUE )
        {
            synchronized ( listenerId )
            {
                id = listenerId[0];
                listenerId[0] = 0;
                // TODO: record & check if the generated id is currently being
                // used by a valid listener. Currently if the id wraps after
                // Long.MAX_VALUE,
                // we just assume it won't collide with an existing listener who
                // is live.
            }
        }
        else
        {
            synchronized ( listenerId )
            {
                id = ++listenerId[0];
            }
        }
        return id;
    }

    /**
     * Gets the stats attribute of the RemoteCacheServer object.
     * <p>
     * @return The stats value
     * @throws IOException
     */
    @Override
    public String getStats()
        throws IOException
    {
        return cacheManager.getStats();
    }

    /**
     * Logs an event if an event logger is configured.
     * <p>
     * @param item
     * @param requesterId
     * @param eventName
     * @return ICacheEvent
     */
    private ICacheEvent<ICacheElement<K, V>> createICacheEvent( ICacheElement<K, V> item, long requesterId, String eventName )
    {
        if ( cacheEventLogger == null )
        {
            return new CacheEvent<>();
        }
        String ipAddress = getExtraInfoForRequesterId( requesterId );
        return cacheEventLogger
            .createICacheEvent( "RemoteCacheServer", item.getCacheName(), eventName, ipAddress, item );
    }

    /**
     * Logs an event if an event logger is configured.
     * <p>
     * @param cacheName
     * @param key
     * @param requesterId
     * @param eventName
     * @return ICacheEvent
     */
    private <T> ICacheEvent<T> createICacheEvent( String cacheName, T key, long requesterId, String eventName )
    {
        if ( cacheEventLogger == null )
        {
            return new CacheEvent<>();
        }
        String ipAddress = getExtraInfoForRequesterId( requesterId );
        return cacheEventLogger.createICacheEvent( "RemoteCacheServer", cacheName, eventName, ipAddress, key );
    }

    /**
     * Logs an event if an event logger is configured.
     * <p>
     * @param source
     * @param eventName
     * @param optionalDetails
     */
    protected void logApplicationEvent( String source, String eventName, String optionalDetails )
    {
        if ( cacheEventLogger != null )
        {
            cacheEventLogger.logApplicationEvent( source, eventName, optionalDetails );
        }
    }

    /**
     * Logs an event if an event logger is configured.
     * <p>
     * @param cacheEvent
     */
    protected <T> void logICacheEvent( ICacheEvent<T> cacheEvent )
    {
        if ( cacheEventLogger != null )
        {
            cacheEventLogger.logICacheEvent( cacheEvent );
        }
    }

    /**
     * Ip address for the client, if one is stored.
     * <p>
     * Protected for testing.
     * <p>
     * @param requesterId
     * @return String
     */
    protected String getExtraInfoForRequesterId( long requesterId )
    {
        String ipAddress = idIPMap.get( Long.valueOf( requesterId ) );
        return ipAddress;
    }

    /**
     * Allows it to be injected.
     * <p>
     * @param cacheEventLogger
     */
    public void setCacheEventLogger( ICacheEventLogger cacheEventLogger )
    {
        this.cacheEventLogger = cacheEventLogger;
    }
}
