/*
 * Copyright (c) 1998, 2019 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.internal.identitymaps;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.helper.linkedlist.ExposedNodeLinkedList;
import org.eclipse.persistence.internal.helper.linkedlist.LinkedNode;
import org.eclipse.persistence.internal.sessions.AbstractSession;

/**
 * <p><b>Purpose</b>: A HardCacheWeakIdentityMap is identical to the weak identity map, however the weak reference
 * can be a performance problem for some types of apps because it can cause too much garbage collection
 * of objects read causing them to be re-read and re-built (this defeats the purpose of the cache).
 * The hard weak cache solves this by also holding a fixed number of objects in memory to improve caching.<br>
 * This class makes use of an exposed node linked list to maintain the objects by storing the link nodes in the cache key.
 * <p><b>Responsibilities</b>:<ul>
 * <li> Guarantees identity
 * <li> Allows garbage collection
 * <li> Increases performance by maintaining a fixed size cache of LRU objects when memory is available
 * <li> The default size of the reference cache is half the max size
 * </ul>
 * @since TOPLink/Java 1.2
 */
public class HardCacheWeakIdentityMap extends WeakIdentityMap {
    /** A subset of cache entries have hard references maintained in this list to reduce garbage collection frequency */
    protected ExposedNodeLinkedList referenceCache;

    public HardCacheWeakIdentityMap(int size, ClassDescriptor descriptor, AbstractSession session, boolean isIsolated) {
        super(size, descriptor, session, isIsolated);
        this.referenceCache = new ExposedNodeLinkedList();
    }

    /**
     * Use a ReferenceCacheKey that also stores the linked list node to manage
     * the LRU sub-cache of references.
     */
    @Override
    public CacheKey createCacheKey(Object primaryKey, Object object, Object writeLockValue, long readTime) {
        return new ReferenceCacheKey(primaryKey, object, writeLockValue, readTime, isIsolated);
    }

    /**
     * Return the linked reference cache.
     */
    public ExposedNodeLinkedList getReferenceCache() {
        return referenceCache;
    }

    /**
     * Allows subclass to create a SoftReference to the object.
     * @param object is the domain object to cache.
     */
    public Object buildReference(Object object) {
        return object;
    }

    /**
     * Checks if the object is null, or reference's object is null.
     * @param reference the object for hard or the reference for soft.
     */
    public boolean hasReference(Object reference) {
        return reference != null;
    }

    /**
     * Remove the cache key from the map and the sub-cache list.
     */
    @Override
    public Object remove(CacheKey cacheKey) {
        if (cacheKey == null) {
            return null;
        }
        LinkedNode node = ((ReferenceCacheKey)cacheKey).getReferenceCacheNode();
        // Node is initially null while object is being built.
        if (node != null) {
            synchronized (this.referenceCache) {
                this.referenceCache.remove(node);
            }
        }
        return super.remove(cacheKey);
    }

    /**
     * Store the object in the cache at its primary key, and add to sub-cache list.
     */
    @Override
    public CacheKey put(Object primaryKey, Object object, Object writeLockValue, long readTime) {
        CacheKey cacheKey = super.put(primaryKey, object, writeLockValue, readTime);
        cacheKey.updateAccess();
        return cacheKey;
    }

    /**
     * This method will be used to update the max cache size.
     */
    @Override
    public synchronized void updateMaxSize(int maxSize) {
        setMaxSize(maxSize);
        synchronized (this.referenceCache) {
            // Remove the LRU items if max size exceeded.
            while (this.referenceCache.size() > this.maxSize) {
                this.referenceCache.removeLast();
            }
        }
    }

    /**
     * Inner class to define the specialized weak cache key.
     * Keeps track of the linked list node to allow quick repositioning.
     */
    public class ReferenceCacheKey extends WeakCacheKey {
        protected LinkedNode referenceNode;

        public ReferenceCacheKey(Object primaryKey, Object object, Object writeLockValue, long readTime, boolean isIsolated) {
            super(primaryKey, object, writeLockValue, readTime, isIsolated);
        }

        public LinkedNode getReferenceCacheNode() {
            return referenceNode;
        }

        public void setReferenceCacheNode(LinkedNode referenceNode) {
            this.referenceNode = referenceNode;
        }

        public ExposedNodeLinkedList getReferenceCache() {
            return referenceCache;
        }

        /**
         * Notifies that cache key that it has been accessed.
         * Allows the LRU sub-cache to be maintained,
         * the cache node must be moved to the front of the list.
         */
        @Override
        public void updateAccess() {
            // Check if the node's contents is null (was removed),
            // or ref value may have garbage collected so reset it.
            if ((this.referenceNode != null) && (!hasReference(this.referenceNode.getContents()))) {
                this.referenceNode.setContents(buildReference(getObject()));
            }
            // PERF: Synchronize on the linked list.
            synchronized (referenceCache) {
                // If reference node is null, add to start (new cache key).
                if (this.referenceNode == null) {
                    this.referenceNode = referenceCache.addFirst(buildReference(getObject()));
                } else {
                    // This is a fast constant time operations because of the linked list usage.
                    referenceCache.moveFirst(getReferenceCacheNode());
                }
                // Remove the old LRU items if max size exceeded (if was removed).
                while (referenceCache.size() > maxSize) {
                    referenceCache.removeLast();
                }
            }
        }
    }
}
