/*
 * Copyright (c) 1998, 2021 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.exceptions.ConcurrencyException;
import org.eclipse.persistence.internal.helper.*;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.queries.ObjectBuildingQuery;
import org.eclipse.persistence.sessions.DataRecord;
import org.eclipse.persistence.sessions.DatabaseRecord;

/**
 * <p><b>Purpose</b>: Container class for storing objects in an IdentityMap.
 * <p><b>Responsibilities</b>:<ul>
 * <li> Hold key and object.
 * <li> Maintain and update the current writeLockValue.
 * </ul>
 * @since TOPLink/Java 1.0
 */
public class CacheKey extends ConcurrencyManager implements Cloneable {

    //These constants are used in extended cache logging to compare cache item creation thread and thread which picking item from the cache
    public final long CREATION_THREAD_ID = Thread.currentThread().getId();
    public final String CREATION_THREAD_NAME = String.copyValueOf(Thread.currentThread().getName().toCharArray());
    public final long CREATION_THREAD_HASHCODE = Thread.currentThread().hashCode();

    /** The key holds the vector of primary key values for the object. */
    protected Object key;

    protected Object object;

    //used to store a reference to the map this cachekey is in in cases where the
    //cache key is to be removed, prevents us from having to track down the owning
    //map
    protected IdentityMap mapOwner;

    /** The writeLock value is being held as an object so that it might contain a number or timestamp. */
    protected Object writeLockValue;

    /** The cached wrapper for the object, used in EJB. */
    protected Object wrapper;

    /** This is used for Document Preservation to cache the record that this object was built from */
    protected DataRecord dataRecord;

    /** This attribute is the system time in milli seconds that the object was last refreshed on */

    //CR #4365
    // CR #2698903 - fix for the previous fix. No longer using millis.
    protected long lastUpdatedQueryId;

    /** Invalidation State can be used to indicate whether this cache key is considered valid */
    protected int invalidationState = CHECK_INVALIDATION_POLICY;

    /** The following constants are used for the invalidationState variable */
    public static final int CHECK_INVALIDATION_POLICY = 0;
    public static final int CACHE_KEY_INVALID = -1;

    public static final int MAX_WAIT_TRIES = 10000;

    /** The read time stores the millisecond value of the last time the object help by
    this cache key was confirmed as up to date. */
    protected long readTime = 0;

    /**
     * Stores if this CacheKey instance is a wrapper for the underlying CacheKey.  CacheKey wrappers
     * may be used with cache interceptors.
     */
    protected boolean isWrapper = false;

    /**
     * Stores retrieved FK values for relationships that are not stored in the Entity
     */
    protected AbstractRecord protectedForeignKeys;

    /**
     * Set to true if this CacheKey comes from an IsolatedClientSession, or DatabaseSessionImpl.
     */
    protected boolean isIsolated;

    /**
     * The ID of the database transaction that last wrote the object.
     * This is used for database change notification.
     */
    protected Object transactionId;

    /**
     * Internal:
     * Only used by subclasses that may want to wrap the cache key.  Could be replaced
     * by switching to an interface.
     */
    protected CacheKey(){
    }

    public CacheKey(Object primaryKey) {
        this.key = primaryKey;
    }

    public CacheKey(Object primaryKey, Object object, Object lockValue) {
        this.key = primaryKey;
        this.writeLockValue = lockValue;
        //bug4649617  use setter instead of this.object = object to avoid hard reference on object in subclasses
        if (object != null) {
            setObject(object);
        }
    }

    public CacheKey(Object primaryKey, Object object, Object lockValue, long readTime, boolean isIsolated) {
        this.key = primaryKey;
        this.writeLockValue = lockValue;
        //bug4649617  use setter instead of this.object = object to avoid hard reference on object in subclasses
        if (object != null) {
            setObject(object);
        }
        this.readTime = readTime;
        this.isIsolated = isIsolated;
    }

    /**
     * Acquire the lock on the cache key object.
     */
    @Override
    public void acquire() {
        if (this.isIsolated) {
            this.depth.incrementAndGet();
            return;
        }
        super.acquire(false);
    }

    /**
     * Acquire the lock on the cache key object. For the merge process
     * called with true from the merge process, if true then the refresh will not refresh the object
     */
    @Override
    public void acquire(boolean forMerge) {
        if (this.isIsolated) {
            this.depth.incrementAndGet();
            return;
        }
        super.acquire(forMerge);
    }

    /**
     * Acquire the lock on the cache key object. But only if the object has no lock on it
     * Added for CR 2317
     */
    @Override
    public boolean acquireNoWait() {
        if (this.isIsolated) {
            this.depth.incrementAndGet();
            return true;
        }
        return super.acquireNoWait(false);
    }

    /**
     * Acquire the lock on the cache key object. Only acquire a lock if the cache key's
     * active thread is not set.
     * Added for Bug 5840635
     */

    public boolean acquireIfUnownedNoWait() {
        if (this.isIsolated) {
            if (this.depth.get() > 0) {
                return false;
            }
            this.depth.incrementAndGet();
            return true;
        }
        return super.acquireIfUnownedNoWait(false);
    }

    /**
     * Acquire the lock on the cache key object. But only if the object has no lock on it
     * Added for CR 2317
     * called with true from the merge process, if true then the refresh will not refresh the object
     */
    @Override
    public boolean acquireNoWait(boolean forMerge) {
        if (this.isIsolated) {
            this.depth.incrementAndGet();
            return true;
        }
        return super.acquireNoWait(forMerge);
    }

    /**
     * Acquire the lock on the cache key object. But only if the object has no lock on it
     * Added for CR 2317
     * called with true from the merge process, if true then the refresh will not refresh the object
     */
    @Override
    public boolean acquireWithWait(boolean forMerge, int wait) {
        if (this.isIsolated) {
            this.depth.incrementAndGet();
            return true;
        }
        return super.acquireWithWait(forMerge, wait);
    }

    /**
     * Acquire the deferred lock.
     */
    @Override
    public void acquireDeferredLock() {
        if (this.isIsolated) {
            this.depth.incrementAndGet();
            return;
        }
        super.acquireDeferredLock();
    }

    public void acquireLock(ObjectBuildingQuery query){

        // PERF: Only use deferred locking if required.
        // CR#3876308 If joining is used, deferred locks are still required.
        if (query.requiresDeferredLocks()) {
            this.acquireDeferredLock();

            int counter = 0;
            while ((this.object == null) && (counter < 1000)) {
                if (this.getActiveThread() == Thread.currentThread()) {
                    break;
                }
                //must release lock here to prevent acquiring multiple deferred locks but only
                //releasing one at the end of the build object call.
                //bug 5156075
                this.releaseDeferredLock();
                //sleep and try again if we are not the owner of the lock for CR 2317
                // prevents us from modifying a cache key that another thread has locked.
                try {
                    Thread.sleep(10);
                } catch (InterruptedException exception) {
                }
                this.acquireDeferredLock();
                counter++;
            }
            if (counter == 1000) {
                throw ConcurrencyException.maxTriesLockOnBuildObjectExceded(this.getActiveThread(), Thread.currentThread());
            }
        } else {
            this.acquire();
        }
    }

    /**
     * Check the read lock on the cache key object.
     * This can be called to ensure the cache key has a valid built object.
     * It does not hold a lock, so the object could be refreshed afterwards.
     */
    @Override
    public void checkReadLock() {
        if (this.isIsolated) {
            return;
        }
        super.checkReadLock();
    }

    /**
     * Check the deferred lock on the cache key object.
     * This can be called to ensure the cache key has a valid built object.
     * It does not hold a lock, so the object could be refreshed afterwards.
     */
    @Override
    public void checkDeferredLock() {
        if (this.isIsolated) {
            return;
        }
        super.checkDeferredLock();
    }

    /**
     * Acquire the read lock on the cache key object.
     */
    @Override
    public void acquireReadLock() {
        if (this.isIsolated) {
            return;
        }
        super.acquireReadLock();
    }

    /**
     * Acquire the read lock on the cache key object.  Return true if acquired.
     */
    @Override
    public boolean acquireReadLockNoWait() {
        if (this.isIsolated) {
            return true;
        }
        return super.acquireReadLockNoWait();
    }

    /**
     * INTERNAL:
     * Clones itself.
     */
    @Override
    public Object clone() {
        Object object = null;

        try {
            object = super.clone();
        } catch (Exception exception) {
            throw new InternalError(exception.toString());
        }

        return object;
    }

    /**
     * Determine if the receiver is equal to anObject.
     * If anObject is a CacheKey, do further comparison, otherwise, return false.
     * @see CacheKey#equals(CacheKey)
     */
    @Override
    public boolean equals(Object object) {
        try {
            return equals((CacheKey)object);
        } catch (ClassCastException incorrectType) {
            return false;
        }
    }

    /**
     * Determine if the receiver is equal to key.
     * Use an index compare, because it is much faster than enumerations.
     */
    public boolean equals(CacheKey key) {
        if (this == key) {
            return true;
        }
        if (key.key == null || this.key == null) {
            return false;
        }
        return this.key.equals(key.key);
    }

    /**
     * INTERNAL:
     * This method returns the system time in millis seconds at which this object was last refreshed
     * CR #4365
     * CR #2698903 ... instead of using millis we will now use id's instead. Method
     * renamed appropriately.
     */
    public long getLastUpdatedQueryId() {
        return this.lastUpdatedQueryId;
    }

    public Object getKey() {
        return key;
    }

    /**
     * Return the active thread.
     */
    @Override
    public Thread getActiveThread() {
        if (this.isIsolated) {
            if (this.depth.get() > 0) {
                return Thread.currentThread();
            } else {
                return null;
            }
        }
        return super.getActiveThread();
    }

    public Object getObject() {
        return object;
    }

    public IdentityMap getOwningMap(){
        return this.mapOwner;
    }

    /**
     * INTERNAL:
     * Return the current value of the Read Time variable
     */
    public long getReadTime() {
        return readTime;
    }

    public DataRecord getRecord() {
        return dataRecord;
    }

    public Object getWrapper() {
        return wrapper;
    }

    /**
     * If a Wrapper subclasses this CacheKey this method will be used to unwrap the cache key.
     */
    public CacheKey getWrappedCacheKey(){
        return this;
    }

    public Object getWriteLockValue() {
        return writeLockValue;
    }

    /**
     * Overrides hashCode() in Object to use the primaryKey's hashCode for storage in data structures.
     */
    @Override
    public int hashCode() {
        return this.key.hashCode();
    }
    
    /**
     * Returns true if the protectedForeignKeys record is non-null and non-empty, false otherwise.
     */
    public boolean hasProtectedForeignKeys() {
        return (this.protectedForeignKeys != null) && (this.protectedForeignKeys.size() > 0);
    }

    /**
     * Returns true if this CacheKey is from an IsolatedClientSession
     */
    public boolean isIsolated() {
        return isIsolated;
    }

    /**
     * Returns true if this Instance of CacheKey is a wrapper and should be unwrapped before passing
     * to IdentityMap APIs.  Wrapped CacheKeys may be used in the Cache Interceptors.
     */
    public boolean isWrapper(){
        return this.isWrapper;
    }

    /**
     * INTERNAL:
     * Return the FK cache
     */
    public AbstractRecord getProtectedForeignKeys(){
        if (this.protectedForeignKeys == null){
            this.protectedForeignKeys = new DatabaseRecord();
        }
        return this.protectedForeignKeys;
    }

    /**
     * INTERNAL:
     * Return the value of the invalidationState Variable
     * The return value will be a constant
     * CHECK_INVALIDATION_POLICY - The Invalidation policy is must be checked for this cache key's sate
     * CACHE_KEY_INVALID - This cache key has been labeled invalid.
     */
    public int getInvalidationState() {
        return invalidationState;
    }

    /**
     * Release the lock on the cache key object.
     */
    @Override
    public void release() {
        if (this.isIsolated) {
            this.depth.decrementAndGet();
            return;
        }
        super.release();
    }

    /**
     * Release the deferred lock
     */
    @Override
    public void releaseDeferredLock() {
        if (this.isIsolated) {
            this.depth.decrementAndGet();
            return;
        }
        super.releaseDeferredLock();
    }

    /**
     * Release the read lock on the cache key object.
     */
    @Override
    public void releaseReadLock() {
        if (this.isIsolated) {
            return;
        }
        super.releaseReadLock();
    }

    /**
     * Removes this cacheKey from the owning map
     */
    public Object removeFromOwningMap(){
        if (getOwningMap() != null){
            return getOwningMap().remove(this);
        }
        return null;
    }

    /**
     * INTERNAL:
     * Set the value of the invalidationState Variable
     * The possible values are from an enumeration of constants
     * CHECK_INVALIDATION_POLICY - The invalidation policy is must be checked for this cache key's sate
     * CACHE_KEY_INVALID - This cache key has been labelled invalid.
     */
    public void setInvalidationState(int invalidationState) {
        this.invalidationState = invalidationState;
    }

    /**
     * INTERNAL:
     * This method sets the system time in millis seconds at which this object was last refreshed
     * CR #4365
     * CR #2698903 ... instead of using millis we will now use ids instead. Method
     * renamed appropriately.
     */
    public void setLastUpdatedQueryId(long id) {
        this.lastUpdatedQueryId = id;
    }

    public void setKey(Object key) {
        this.key = key;
    }

    public void setObject(Object object) {
        this.object = object;
    }

    public void setOwningMap(IdentityMap map){
        this.mapOwner = map;
    }

    public void setProtectedForeignKeys(AbstractRecord protectedForeignKeys) {
        this.protectedForeignKeys = protectedForeignKeys;
    }

    /**
     * INTERNAL:
     * Set the read time of this cache key
     */
    public void setReadTime(long readTime) {
        this.readTime = readTime;
        invalidationState = CHECK_INVALIDATION_POLICY;
    }

    public void setRecord(DataRecord newDataRecord) {
        this.dataRecord = newDataRecord;
    }

    public void setWrapper(Object wrapper) {
        this.wrapper = wrapper;
    }

    public void setWriteLockValue(Object writeLockValue) {
        this.writeLockValue = writeLockValue;
    }

    @Override
    public String toString() {
        int hashCode = 0;
        if (getObject() != null) {
            hashCode = getObject().hashCode();
        }

        return "[" + getKey() + ": " + hashCode + ": " + getWriteLockValue() + ": " + getReadTime() + ": " + getObject() + "]";
    }

    /**
     * Notifies that cache key that it has been accessed.
     * Allows the LRU sub-cache to be maintained.
     */
    public void updateAccess() {
        // Nothing required by default.
    }

    public void setIsolated(boolean isIsolated) {
        this.isIsolated = isIsolated;
    }

    public void setIsWrapper(boolean isWrapper) {
        this.isWrapper = isWrapper;
    }

    public Object getTransactionId() {
        return transactionId;
    }

    public void setTransactionId(Object transactionId) {
        this.transactionId = transactionId;
    }

    public synchronized Object waitForObject(){
        try {
            int count = 0;
            while (this.object == null && isAcquired()) {
                if (count > MAX_WAIT_TRIES)
                    throw ConcurrencyException.maxTriesLockOnBuildObjectExceded(getActiveThread(), Thread.currentThread());
                wait(10);
                ++count;
            }
        } catch(InterruptedException ex) {
            //ignore as the loop is broken
        }
        return this.object;
    }
}
