/*
 * 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.DatabaseRecord;
import org.eclipse.persistence.sessions.Record;

/**
 * <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 Record record;

    /** 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 Record getRecord() {
        return record;
    }

    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(Record newRecord) {
        this.record = newRecord;
    }

    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;
    }
}
