/*
 * Copyright (c) 2020, 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
 */

package org.eclipse.persistence.internal.helper;

import org.eclipse.persistence.internal.helper.type.CacheKeyToThreadRelationships;
import org.eclipse.persistence.internal.helper.type.ConcurrencyManagerState;
import org.eclipse.persistence.internal.helper.type.DeadLockComponent;
import org.eclipse.persistence.internal.helper.type.IsBuildObjectCompleteOutcome;
import org.eclipse.persistence.internal.localization.TraceLocalization;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;

import java.io.StringWriter;
import java.util.*;

/**
 * The purpose of this class is to try explain the nature of a dead lock
 */
public class ExplainDeadLockUtil {

    public static final ExplainDeadLockUtil SINGLETON = new ExplainDeadLockUtil();

    private static final DeadLockComponent DEAD_LOCK_NOT_FOUND = null;

    private ExplainDeadLockUtil() {
    }

    /**
     * Given the concurrency manager state try to explain why we are facing a dead lock.
     *
     * @param concurrencyManagerState
     *            A clone we have assembled based on the concurrency manager and write lock manager state
     * @return A string that tries
     */
    public List<DeadLockComponent> explainPossibleDeadLockStartRecursion(ConcurrencyManagerState concurrencyManagerState) {
        // (a) start by initializing some basic variables
        final int maxNumberOfDifferentThreadsThatWillJustifyADeadLock = 5;
        final int recursionMaxDepth = maxNumberOfDifferentThreadsThatWillJustifyADeadLock + 1;
        final int initialRecursionDepth = 1;

        // (b) Initialize our candidate threads to justify the dead lock
        // we add all threads we know to be waiting to acquire write locks
        // stuck waiting for locks they deferred to be considered finished
        // stuck waiting for getting read locks
        final Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain = new HashSet<>();
        final Set<Thread> allCandidateThreadsToExpand = new HashSet<>();
        allCandidateThreadsToExpand.addAll(concurrencyManagerState.getUnifiedMapOfThreadsStuckTryingToAcquireWriteLock().keySet());
        allCandidateThreadsToExpand.addAll(concurrencyManagerState.getSetThreadWaitingToReleaseDeferredLocksClone());
        allCandidateThreadsToExpand.addAll(concurrencyManagerState.getMapThreadToWaitOnAcquireReadLockClone().keySet());

        // (c) loop over each candidate thread and try to find a dad lock
        DeadLockComponent deadLockOutcome = null;
        for (Thread currentCandidateThreadPartOfTheDeadLock : allCandidateThreadsToExpand) {
            deadLockOutcome = recursiveExplainPossibleDeadLockStep01(
                    concurrencyManagerState, recursionMaxDepth, initialRecursionDepth,
                    currentCandidateThreadPartOfTheDeadLock, Collections.<Thread> emptyList(),
                    threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain);
            if (deadLockOutcome != null) {
                break;
            }
        }
        if (deadLockOutcome != null) {
            return createListExplainingDeadLock(deadLockOutcome);
        } else {
            return Collections.emptyList();
        }
    }

    /**
     * When the last (repeating thread) of a dead lock is discovered and we start the unwinding of the recursion, the
     * first DTO we create is flagged with
     * {@link org.eclipse.persistence.internal.helper.type.DeadLockComponent#isFirstRepeatingThreadThatExplainsDeadLock()}
     *
     * but it lacks all additional metadata. so we want enrich the missing metadata into this dto.
     *
     * @param deadLockExplanation
     *            The outcome of the explain dead lock algorithm. The last DTO on this data structure is lacking
     *            metadata and we want to get rid of it.
     *
     * @return return the dead lock explanation as a simple list that is easy to iterate over without going into
     *         infinite loops and where we get rid of the primal repeating thread of our recursion which is lacking
     *         metadata about the nature of the dead lock on the thread.
     */
    protected List<DeadLockComponent> createListExplainingDeadLock(
            DeadLockComponent deadLockExplanation) {
        // (a) Initialize some basic loop variables Loop over all the elements
        DeadLockComponent previousElement = null;
        DeadLockComponent currentElementToIterate = deadLockExplanation;

        // (b) initialize a helper map where we can quickly access the dead lock component dto by thread id
        Map<Thread, DeadLockComponent> helperMap = new HashMap<>();

        // (c) start our correction loop
        List<DeadLockComponent> deadLockAsSimpleList = new ArrayList<>();
        while (currentElementToIterate != null) {

            // (d) In this chaing of DTOs we built during our recursion
            // the first DTO we built at the highest depth of the recursion
            // is lacking all metadata. The DTO is created just stating the thread is being repeater therefore
            // we have a dead lock.
            // we simply get rid of this DTO primal DTO and use the equivalent DTO thta has all proper metadata
            boolean foundDtoRepresentingRepeatingThreadInADeadLock = currentElementToIterate.isFirstRepeatingThreadThatExplainsDeadLock();
            if (foundDtoRepresentingRepeatingThreadInADeadLock) {
                // (i) we load equivalent DTO in the hiearchy
                Thread repatedThreadInDeadLock = currentElementToIterate.getThreadNotAbleToAccessResource();
                DeadLockComponent equivalentDtoHavingAllProperMetadata = helperMap.get(repatedThreadInDeadLock);

                // (ii) we flag the equivalent DTO as being the thread that we see repeating in the dead lock
                equivalentDtoHavingAllProperMetadata.setFirstRepeatingThreadThatExplainsDeadLock(true);

                // (iii) We go to the previous element of the dead lock and instead of making it point to the primal DTO
                // we make it point to the equivalent DTO that has all the metadata
                // NOTE: the currentElementToIterate can
                if (previousElement != null) {
                    // when foundDtoRepresentingRepeatingThreadInADeadLock it should always be true
                    // that our previous element is not null
                    previousElement.setNextThreadPartOfDeadLock(currentElementToIterate);
                }

                // (iv) popuplate our result list
                deadLockAsSimpleList.add(equivalentDtoHavingAllProperMetadata);

            } else {
                // we are dealing with from depth 1 to N-1 (where n-1 is the deepest depth we went to before creating
                // the primal repeating thread DTo)
                deadLockAsSimpleList.add(currentElementToIterate);
                helperMap.put(currentElementToIterate.getThreadNotAbleToAccessResource(), currentElementToIterate);
            }

            // (e) Update the loop control variables
            previousElement = currentElementToIterate;
            currentElementToIterate = currentElementToIterate.getNextThreadPartOfDeadLock();
        }

        return deadLockAsSimpleList;
    }

    /**
     * The algorithm expands the current thread in depth. If the current thread is already part of the
     * threadPartOfCurrentDeadLockExpansion then we have found our dead lock. If we return null, we are empty handed ...
     * we cannot explain the dad lock.
     *
     * @param recursionMaxDepth
     *            how deep do we want our brute force algorithm to go. Probably 6 threads is good enough to discover
     *            most dead locks. Max depth should be set to number of threads we believe can logically form a dead
     *            lock + 1.
     * @param currentRecursionDepth
     *            how deep we are in the recursion
     * @param currentCandidateThreadPartOfTheDeadLock
     *            the current thread we want to expand
     * @param threadPartOfCurrentDeadLockExpansion
     *            a small optimization. If in the past we xplored expanding Thread A and now we are via a different
     *            routing trying to find a dead lock via thread A again we can immediately ignore expanding the thread.
     * @return NULL, if we reach a dead end without a dead lock. If a non result is returned means that the current
     *         thread is part of a dead lock identified..
     */
    protected DeadLockComponent recursiveExplainPossibleDeadLockStep01(
            final ConcurrencyManagerState concurrencyManagerStateDto,
            final int recursionMaxDepth,
            final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock,
            List<Thread> threadPartOfCurrentDeadLockExpansion,
            Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain) {

        // (a) Check some trivial stop cases
        // (i) check if we have found our dead lock
        // we can stop the recursion we have finally found a thread
        if (threadPartOfCurrentDeadLockExpansion.contains(currentCandidateThreadPartOfTheDeadLock)) {
            // implement logic to build the dto to be returned
            return new DeadLockComponent(currentCandidateThreadPartOfTheDeadLock);
        }
        // (ii) check If the current thread is one of those we have already expanded
        // in the past and reched no dead lock then there is no point in expanding
        // this thread a second time
        if (threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain.contains(currentCandidateThreadPartOfTheDeadLock)) {
            return DEAD_LOCK_NOT_FOUND;
        }

        // (b) If the current depth is not too deep we should at the current thread to basket of threads to not expand
        // again
        // E.g. if assume that all dead locks are justified by 5 threads or less then given a Thread A if we have
        // expanded the thread A
        // at depth 1 and came out with no result
        // we know that if now are going via Different Route expanding Thrad B and thread B wants to expand Thread A
        // there is no point in doing so again because thread A has already been expanded at route level
        // On the other hand if we assume a dead lock would be: Thread A, Thread B, Thread C and Thread A.
        // And we are currently are expanding Thread D, E, F, G, A, B (we do not find the dead lock because thread B is
        // being exapnded at depth 6 so the algorithm
        // is not allowed to go any further
        if (currentRecursionDepth == 1) {
            // make sure that if we ever ecounter this thread in the middle of an exapnsion
            // we do not waste time expanding it a second time when we expanded it at the root level
            // we went nowhere
            threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain.add(currentCandidateThreadPartOfTheDeadLock);
        }

        // (c) Finish the recursion when we reach the max depath allowed
        if (currentRecursionDepth >= recursionMaxDepth) {
            // if we say a dead lock can at most involve 6 different threads to justify it
            // then max depth would be seven. E.g. Thread 1,2,3,4,5,6, the7thThreadWouldBeoneOf[1-5]
            return DEAD_LOCK_NOT_FOUND;
        }

        // (d) We need to exapnd the current thread our trivial checks so far yielded nothing so now
        // we need to navigate in depth
        return recursiveExplainPossibleDeadLockStep02(concurrencyManagerStateDto, recursionMaxDepth,
                currentRecursionDepth,
                currentCandidateThreadPartOfTheDeadLock, threadPartOfCurrentDeadLockExpansion,
                threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain);

    }

   
    /**
     * Precondition the logic of {@link #recursiveExplainPossibleDeadLockStep01(ConcurrencyManagerState, int, int, Thread, List, Set)} has been
     * invoked and determined that we need to go deeper and expand the current thread.
     *
     * @param recursionMaxDepth
     *            the max depth the recursion is allowed to reach before deciding it is pointless to go any further. Max
     *            depth should be set to number of threads we believe can logically form a dead lock + 1.
     * @param currentRecursionDepth
     *            how deep we are in the recursion
     * @param currentCandidateThreadPartOfTheDeadLock
     *            the current thread we want to expand
     * @param threadPartOfCurrentDeadLockExpansion
     *            a small optimization. If in the past we xplored expanding Thread A and now we are via a different
     *            routing trying to find a dead lock via thread A again we can immediately ignore expanding the thread.
     * @return NULL, if we reach a dead end without a dead lock. If a non result is returned means that the current
     *         thread is part of a dead lock identified..
     */
    protected DeadLockComponent recursiveExplainPossibleDeadLockStep02(
            final ConcurrencyManagerState concurrencyManagerStateDto,
            final int recursionMaxDepth, final int currentRecursionDepth,
            final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion,
            Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain) {

        // We need to start by trying to understand what is the problem of the current thread
        // what resources does it want get and fail to get
        // (a) Are we facing the scenario that our thread wants a write lock but cannot get it
        Set<ConcurrencyManager> writeLocksCurrentThreadWantsToGetButFailsToGet = concurrencyManagerStateDto
                .getUnifiedMapOfThreadsStuckTryingToAcquireWriteLock().get(currentCandidateThreadPartOfTheDeadLock);
        if (writeLocksCurrentThreadWantsToGetButFailsToGet != null
                && !writeLocksCurrentThreadWantsToGetButFailsToGet.isEmpty()) {
            for (ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet : writeLocksCurrentThreadWantsToGetButFailsToGet) {
                DeadLockComponent currentResult = recursiveExplainPossibleDeadLockStep03ExpandBasedOnCacheKeyWantedForWriting(
                        concurrencyManagerStateDto, recursionMaxDepth, currentRecursionDepth,
                        currentCandidateThreadPartOfTheDeadLock, threadPartOfCurrentDeadLockExpansion,
                        threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain,
                        cacheKeyCurrentThreadWantsForWritingButCannotGet);
                if (currentResult != null) {
                    // dead lock can be explained via this expansion
                    return currentResult;
                }
            }
        }

        // (b) Deferred lock problem
        // could it be the current thread failed to acquire some locks and its waiting for other threads to finish
        boolean isCurrentThreadWaitingForDeferredLocksToBeResolved = concurrencyManagerStateDto
                .getSetThreadWaitingToReleaseDeferredLocksClone()
                .contains(currentCandidateThreadPartOfTheDeadLock);
        if(isCurrentThreadWaitingForDeferredLocksToBeResolved) {
            DeadLockComponent currentResult = recursiveExplainPossibleDeadLockStep04ExpandBasedOnThreadStuckOnReleaseDeferredLocks(
                    concurrencyManagerStateDto, recursionMaxDepth, currentRecursionDepth,
                    currentCandidateThreadPartOfTheDeadLock, threadPartOfCurrentDeadLockExpansion,
                    threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain);
            if (currentResult != null) {
                // dead lock can be explained via this expansion
                return currentResult;
            }
        }

        // (c) check if perhaps the current thread is strugling because it is trying to get some read lock and cannot
        // access it
        ConcurrencyManager cacheKeyCurrentThreadWantsForReadingButCannotGet = concurrencyManagerStateDto
                .getMapThreadToWaitOnAcquireReadLockClone().get(currentCandidateThreadPartOfTheDeadLock);
        if (cacheKeyCurrentThreadWantsForReadingButCannotGet != null) {
            DeadLockComponent currentResult = recursiveExplainPossibleDeadLockStep05ExpandBasedOnCacheKeyWantedForReading(
                    concurrencyManagerStateDto,
                    recursionMaxDepth, currentRecursionDepth, currentCandidateThreadPartOfTheDeadLock,
                    threadPartOfCurrentDeadLockExpansion, threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain,
                    cacheKeyCurrentThreadWantsForReadingButCannotGet);
            if (currentResult != null) {
                // dead lock can be explained via this expansion
                return currentResult;
            }
        }
        // This expansion did not allow us to discover any dead lock
        return DEAD_LOCK_NOT_FOUND;
    }

    /**
     * This a helper sanity check. Whenever we expand a threa we expect the thread must be starved fro some resource.
     *
     * @param concurrencyManagerStateDto
     *            the dto that holds the state of the cocurrency manager for our dead lock detection algorithm
     * @param currentCandidateThreadPartOfTheDeadLock
     *            the thread we are trying to evaluate
     * @return TRUE if we are aware of one or more resources that the current thread strives to acquire but cannot get
     *         false if we are clueless as to any desire for the thread.
     */
    protected boolean currentThreadIsKnownToBeWaitingForAnyResource(
            final ConcurrencyManagerState concurrencyManagerStateDto,
            final Thread currentCandidateThreadPartOfTheDeadLock) {
        boolean currentThreadExpansionEnteredAnyOfTheScenarios = false;
        Set<ConcurrencyManager> writeLocksCurrentThreadWantsToGetButFailsToGet = concurrencyManagerStateDto
                .getUnifiedMapOfThreadsStuckTryingToAcquireWriteLock().get(currentCandidateThreadPartOfTheDeadLock);
        if (writeLocksCurrentThreadWantsToGetButFailsToGet != null && !writeLocksCurrentThreadWantsToGetButFailsToGet.isEmpty()) {
            currentThreadExpansionEnteredAnyOfTheScenarios = true;
        }

        boolean isCurrentThreadWaitingForDeferredLocksToBeResolved = concurrencyManagerStateDto
                .getSetThreadWaitingToReleaseDeferredLocksClone()
                .contains(currentCandidateThreadPartOfTheDeadLock);
        if (isCurrentThreadWaitingForDeferredLocksToBeResolved) {
            currentThreadExpansionEnteredAnyOfTheScenarios = true;
        }

        ConcurrencyManager cacheKeyCurrentThreadWantsForReadingButCannotGet = concurrencyManagerStateDto
                .getMapThreadToWaitOnAcquireReadLockClone().get(currentCandidateThreadPartOfTheDeadLock);
        if (cacheKeyCurrentThreadWantsForReadingButCannotGet != null) {
            currentThreadExpansionEnteredAnyOfTheScenarios = true;
        }
        return currentThreadExpansionEnteredAnyOfTheScenarios;
    }

    /**
     * We are looking at thread that we know has registered itself as wanting to acquire a write lock and not managing
     * to make progress getting the write lock. We need to have a look at the {@link DeadLockComponent}
     * to try to find out who is owning the lock at the current point in time. We will onsider th posisble writers,
     * readers and in case of desperation the active thread on the cache key.
     *
     * @param concurrencyManagerStateDto
     *            state of concurrency manager
     * @param recursionMaxDepth
     *            how deep the recursion can go
     * @param currentRecursionDepth
     *            the current depeth
     * @param currentCandidateThreadPartOfTheDeadLock
     *            the current thread we are expanding and that may be involved in explaning a dead lock
     *
     * @param threadPartOfCurrentDeadLockExpansion
     *            the predecessor threads that are part of a dead lock expansion we are searching
     * @param threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain
     *            these are threads we already expanded at depth 1 and we know they took us nowhere. We just assume
     *            expanding these a second time is a waste of time.
     * @param cacheKeyCurrentThreadWantsForWritingButCannotGet
     *            this is the cache key we have identified as making a our candidate thread stuck and we want to explore
     *            who is owning this cache key
     * @return NULL if we get nowhere trying to find the dead lock otherwise a DTO explaining this thread and the
     *         successor threads that make the dead lock
     */
    protected DeadLockComponent recursiveExplainPossibleDeadLockStep03ExpandBasedOnCacheKeyWantedForWriting(
            final ConcurrencyManagerState concurrencyManagerStateDto,
            final int recursionMaxDepth, final int currentRecursionDepth,
            final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion,
            Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain,
            ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet) {

        // (c) Scenario 1: (current writer thread competing with other writers)
        // The current cache key is acquired for Writing by some other thread so it cannot be acquired for writing by
        // this thread we are trying to expand
        // NOTE: at most there should only be one thread on this list
        DeadLockComponent expansionResult = recursiveExplainPossibleDeadLockStep03Scenario01CurrentWriterVsOtherWritersWriter(concurrencyManagerStateDto,
                recursionMaxDepth, currentRecursionDepth, currentCandidateThreadPartOfTheDeadLock,
                threadPartOfCurrentDeadLockExpansion, threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain,
                cacheKeyCurrentThreadWantsForWritingButCannotGet);
        if(expansionResult != null) {
            return expansionResult;
        }

        // (c) Scenario 2: (current writer thread competing with other readers)
        // NOTE: The current cache key is perhaps owned by threads reading threads
        // making this writer not be able to acquire the cache key
        expansionResult = recursiveExplainPossibleDeadLockStep03Scenario02CurrentWriterVsOtherReader(
                concurrencyManagerStateDto, recursionMaxDepth, currentRecursionDepth,
                currentCandidateThreadPartOfTheDeadLock, threadPartOfCurrentDeadLockExpansion,
                threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain,
                cacheKeyCurrentThreadWantsForWritingButCannotGet);
        if (expansionResult != null) {
            return expansionResult;
        }

        // (d) Scenario 3:
        // We need to have a look at the active thread on the cache key as a last resort aspect to consider
        // Our primary strategy of getThreadsThatAcquiredActiveLock did not bare any fruits we will still consider the
        // cache key itself and check if it has any active thread
        expansionResult = recursiveExplainPossibleDeadLockStep03Scenario03CurrentWriterVsCacheKeyActiveThread(
                concurrencyManagerStateDto, recursionMaxDepth, currentRecursionDepth,
                currentCandidateThreadPartOfTheDeadLock, threadPartOfCurrentDeadLockExpansion,
                threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain,
                cacheKeyCurrentThreadWantsForWritingButCannotGet);
        if (expansionResult != null) {
            // perhaps we could log a warning here becuase if this scenario bares any fruits we do not really understand
            // what we are doing wrong in tracing the concurrency layer
            // we assume that each time a thread sets itself as the active thread on a cache key
            // we will wil trace this thread when it needs to acquire a lock and fails to get it
            return expansionResult;
        }

        // (e) We are out of ideas on how to expand further the current thread
        // we need to
        return DEAD_LOCK_NOT_FOUND;
    }

    /**
     * Expand the possibility of the current thread wanting to acquire for writing what some other already has acquired for writing.
     *
     */
    protected DeadLockComponent recursiveExplainPossibleDeadLockStep03Scenario01CurrentWriterVsOtherWritersWriter(
            final ConcurrencyManagerState concurrencyManagerStateDto,
            final int recursionMaxDepth, final int currentRecursionDepth,
            final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion,
            Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain,
            ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet) {

        boolean currentThreadWantsToAcquireForWriting = true;
        return recursiveExpansionCurrentThreadBeingBlockedByActiveWriters(concurrencyManagerStateDto, recursionMaxDepth,
                currentRecursionDepth, currentCandidateThreadPartOfTheDeadLock, threadPartOfCurrentDeadLockExpansion,
                threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain,
                cacheKeyCurrentThreadWantsForWritingButCannotGet, currentThreadWantsToAcquireForWriting);
    }

    /**
     * Expand the possibility of the current thread wanting to acquire for writing what some other already has acquired for writing.
     *
     */
    protected DeadLockComponent recursiveExplainPossibleDeadLockStep05Scenario01CurrentReaderVsOtherWriters(
            final ConcurrencyManagerState concurrencyManagerStateDto,
            final int recursionMaxDepth, final int currentRecursionDepth,
            final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion,
            Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain,
            ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet) {

        boolean currentThreadWantsToAcquireForWriting = true;
        return recursiveExpansionCurrentThreadBeingBlockedByActiveWriters(concurrencyManagerStateDto, recursionMaxDepth,
                currentRecursionDepth, currentCandidateThreadPartOfTheDeadLock, threadPartOfCurrentDeadLockExpansion,
                threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain,
                cacheKeyCurrentThreadWantsForWritingButCannotGet, currentThreadWantsToAcquireForWriting);
    }


    /**
     * Try to expand the current thread from the perspective that it wants a cache key that may be own for writing by a competitor thread.
     *
     * @param concurrencyManagerState
     *            state of the concurrency manager
     * @param recursionMaxDepth
     *            max allowed depth for recursion.
     * @param currentRecursionDepth
     *            the current recursion depth
     * @param currentCandidateThreadPartOfTheDeadLock
     *            the current thread we are expanding in dpeth
     * @param threadPartOfCurrentDeadLockExpansion
     *            the current thread of sets comrpising our dead lock expansion.
     * @param threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain
     *            threads we have expanded in the past and gave no fruits
     * @param cacheKeyThreadWantsToAcquireButCannotGet
     *            the cache key we know our current candidate wants and is not getting.
     * @param currentThreadWantsToAcquireForWriting
     *            a flag that tells us if our current candidate thread is strugling to acquire a lock with the purpose
     *            of writing or just for reading.
     * @return NULL if no dead lock is found. a value if a deadlock is found
     */
    protected DeadLockComponent recursiveExpansionCurrentThreadBeingBlockedByActiveWriters(
            final ConcurrencyManagerState concurrencyManagerState,
            final int recursionMaxDepth, final int currentRecursionDepth,
            final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion,
            Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain,
            ConcurrencyManager cacheKeyThreadWantsToAcquireButCannotGet,
            boolean currentThreadWantsToAcquireForWriting) {
        // (a) we start by finding out the dto that explains what threads are having some sort of involvement with the
        // cache key our thread wants to acquire
        CacheKeyToThreadRelationships cacheKeyToThreadRelationships = concurrencyManagerState
                .getMapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey()
                .get(cacheKeyThreadWantsToAcquireButCannotGet);

        // (b) Start by preparing some basic immutable variables to go deeper one recursion level
        List<Thread> nexThreadPartOfCurrentDeadLockExpansion = new ArrayList<>(
                threadPartOfCurrentDeadLockExpansion);
        nexThreadPartOfCurrentDeadLockExpansion.add(currentCandidateThreadPartOfTheDeadLock);
        nexThreadPartOfCurrentDeadLockExpansion = Collections.unmodifiableList(nexThreadPartOfCurrentDeadLockExpansion);
        final int nextRecursionDepth = currentRecursionDepth + 1;

        // (c) Scenario 1: (current writer thread competing with other writers)
        // The current cache key is acquired for Writing by some other thread so it cannot be acquired for writing by
        // this thread we are trying to expand
        // NOTE: at most there should only be one thread on this list
        List<Thread> threadsThatHaveCurrentCacheKeyAsAnActiveLock = cacheKeyToThreadRelationships.getThreadsThatAcquiredActiveLock();
        for (Thread nextCandidateThreadPartOfTheDeadLock : threadsThatHaveCurrentCacheKeyAsAnActiveLock) {
            boolean isDifferentThread = !nextCandidateThreadPartOfTheDeadLock
                    .equals(currentCandidateThreadPartOfTheDeadLock);
            if (isDifferentThread) {

                // (i) Go deeper into the recursion expanding the next thread
                DeadLockComponent expansionResult = recursiveExplainPossibleDeadLockStep01(
                        concurrencyManagerState, recursionMaxDepth,
                        // go one level and thread deeper hunting for a dead lock
                        nextRecursionDepth, nextCandidateThreadPartOfTheDeadLock,
                        nexThreadPartOfCurrentDeadLockExpansion,
                        threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain);

                // (ii) check if we have found our dead lock
                if (expansionResult != null) {
                    if(currentThreadWantsToAcquireForWriting) {
                        return deadLockFoundCreateConcurrencyManagerStateWriterThreadCouldNotAcquireWriteLock(
                                expansionResult, currentCandidateThreadPartOfTheDeadLock,
                                cacheKeyThreadWantsToAcquireButCannotGet);
                    }  else {
                        return deadLockFoundCreateConcurrencyManagerStateReaderThreadCouldNotAcquireWriteLock(
                                expansionResult, currentCandidateThreadPartOfTheDeadLock,
                                cacheKeyThreadWantsToAcquireButCannotGet);
                    }

                }
            }
        }
        return DEAD_LOCK_NOT_FOUND;
    }


    /**
     * Expand the recursion exploring the possibility that the reason the current thread cannot acquire the cache key is
     * because there are readers on the cache key.
     *
     * @return NULL if dead lock not discovered. Otherwise dead lock component justifying the deadlock.
     */
    protected DeadLockComponent recursiveExplainPossibleDeadLockStep03Scenario02CurrentWriterVsOtherReader(
            final ConcurrencyManagerState concurrencyManagerState,
            final int recursionMaxDepth, final int currentRecursionDepth,
            final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion,
            Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain,
            ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet) {

        // (a) we start by finding out the dto that explains what threads are having some sort of involvement with the
        // cache key our thread wants to acquire
        CacheKeyToThreadRelationships cacheKeyToThreadRelationships = concurrencyManagerState
                .getMapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey()
                .get(cacheKeyCurrentThreadWantsForWritingButCannotGet);

        // (b) Start by preparing some basic immutable variables to go deeper one recursion level
        List<Thread> nexThreadPartOfCurrentDeadLockExpansion = new ArrayList<>(
                threadPartOfCurrentDeadLockExpansion);
        nexThreadPartOfCurrentDeadLockExpansion.add(currentCandidateThreadPartOfTheDeadLock);
        nexThreadPartOfCurrentDeadLockExpansion = Collections.unmodifiableList(nexThreadPartOfCurrentDeadLockExpansion);
        final int nextRecursionDepth = currentRecursionDepth + 1;


        // (c) Scenario 2: (current writer thread competing with other readers)
        // NOTE: The current cache key is perhaps owned by threads reading threads
        // making this writer not be able to acquire the cache key
        List<Thread> threadsThatHaveCurrentCacheKeyAsAReadLockLock = cacheKeyToThreadRelationships
                .getThreadsThatAcquiredReadLock();
        for (Thread nextCandidateThreadPartOfTheDeadLock : threadsThatHaveCurrentCacheKeyAsAReadLockLock) {
            boolean isDifferentThread = !nextCandidateThreadPartOfTheDeadLock
                    .equals(currentCandidateThreadPartOfTheDeadLock);
            if(isDifferentThread) {

                // (i) Go deeper into the recursion expanding the next thread
                DeadLockComponent expansionResult = recursiveExplainPossibleDeadLockStep01(
                        concurrencyManagerState, recursionMaxDepth,
                        // go one level and thread deeper hunting for a dead lock
                        nextRecursionDepth, nextCandidateThreadPartOfTheDeadLock,
                        nexThreadPartOfCurrentDeadLockExpansion,
                        threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain);

                // (ii) check if we have found our dead lock
                if (expansionResult != null) {
                    return deadLockFoundCreateConcurrencyManagerStateWriterThreadCouldNotAcquireWriteLock(
                            expansionResult, currentCandidateThreadPartOfTheDeadLock,
                            cacheKeyCurrentThreadWantsForWritingButCannotGet);
                }
            }
        }
        return DEAD_LOCK_NOT_FOUND;
    }

    /**
     * In scenario 3 is when we start considering the possbility our data for detecting the dead lock is not ok or the
     * cache is corrupted. We consider quite simply the thread that is flagged as the active thread on the cache key
     * since this is the thread owning the cache key. However if we call for this scenario it means we did not find in
     * our DTO any reader or writer owning the thread. So if indeed the cache key our thread is trying to acquire has an
     * active thread and we do not know what this thread is currently doing - since the thread should either be in our
     * basket of writers or in our basket of readers, we are stuck.
     *
     *
     * @return NULL if looking at the active thread of the wanted cache key does not bare any fruits, otherwise the dead
     *         lock component object are returned.
     */
    protected DeadLockComponent recursiveExplainPossibleDeadLockStep03Scenario03CurrentWriterVsCacheKeyActiveThread(
            final ConcurrencyManagerState concurrencyManagerStateDto,
            final int recursionMaxDepth, final int currentRecursionDepth,
            final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion,
            Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain,
            ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet) {
        boolean currentThreadWantsToAcquireForWriting = true;
        return recursiveExpansionCurrentThreadBeingBlockedByActiveThreadOnCacheKey(concurrencyManagerStateDto, recursionMaxDepth, currentRecursionDepth, currentCandidateThreadPartOfTheDeadLock, threadPartOfCurrentDeadLockExpansion,
                threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain,
                cacheKeyCurrentThreadWantsForWritingButCannotGet, currentThreadWantsToAcquireForWriting);
    }

    /**
     * Same as
     * {@link #recursiveExplainPossibleDeadLockStep03Scenario03CurrentWriterVsCacheKeyActiveThread(ConcurrencyManagerState, int, int, Thread, List, Set, ConcurrencyManager)}
     *
     * but in this case our candidate thread is trying to get the cache key with the purpose of READING and not for
     * writing.
     *
     */
    protected DeadLockComponent recursiveExplainPossibleDeadLockStep05Scenario02CurrentReaderVsCacheKeyActiveThread(
            final ConcurrencyManagerState concurrencyManagerStateDto,
            final int recursionMaxDepth, final int currentRecursionDepth,
            final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion,
            Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain,
            ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet) {
        boolean currentThreadWantsToAcquireForWriting = false;
        return recursiveExpansionCurrentThreadBeingBlockedByActiveThreadOnCacheKey(concurrencyManagerStateDto,
                recursionMaxDepth, currentRecursionDepth, currentCandidateThreadPartOfTheDeadLock,
                threadPartOfCurrentDeadLockExpansion, threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain,
                cacheKeyCurrentThreadWantsForWritingButCannotGet, currentThreadWantsToAcquireForWriting);
    }

    /**
     * Try to expand the current thread from the perspective that it wants a cache key that may be own for writing by a
     * competitor thread.
     *
     * @param concurrencyManagerState
     *            state of the concurrency manager
     * @param recursionMaxDepth
     *            max allowed depth for recursion.
     * @param currentRecursionDepth
     *            the current recursion depth
     * @param currentCandidateThreadPartOfTheDeadLock
     *            the current thread we are expanding in dpeth
     * @param threadPartOfCurrentDeadLockExpansion
     *            the current thread of sets comrpising our dead lock expansion.
     * @param threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain
     *            threads we have expanded in the past and gave no fruits
     * @param cacheKeyThreadWantsToAcquireButCannotGet
     *            the cache key we know our current candidate wants and is not getting.
     * @param currentThreadWantsToAcquireForWriting
     *            a flag that tells us if our current candidate thread is strugling to acquire a lock with the purpose
     *            of writing or just for reading.
     * @return NULL if no dead lock is found. a value if a deadlock is found
     */
    protected DeadLockComponent recursiveExpansionCurrentThreadBeingBlockedByActiveThreadOnCacheKey(
            final ConcurrencyManagerState concurrencyManagerState,
            final int recursionMaxDepth, final int currentRecursionDepth,
            final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion,
            Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain,
            ConcurrencyManager cacheKeyThreadWantsToAcquireButCannotGet,
            boolean currentThreadWantsToAcquireForWriting) {
        // (a) we start by finding out the dto that explains what threads are having some sort of involvement with the
        // cache key our thread wants to acquire
        CacheKeyToThreadRelationships cacheKeyToThreadRelationships = concurrencyManagerState
                .getMapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey()
                .get(cacheKeyThreadWantsToAcquireButCannotGet);

        // (b) Start by preparing some basic immutable variables to go deeper one recursion level
        List<Thread> nexThreadPartOfCurrentDeadLockExpansion = new ArrayList<>(
                threadPartOfCurrentDeadLockExpansion);
        nexThreadPartOfCurrentDeadLockExpansion.add(currentCandidateThreadPartOfTheDeadLock);
        nexThreadPartOfCurrentDeadLockExpansion = Collections.unmodifiableList(nexThreadPartOfCurrentDeadLockExpansion);
        final int nextRecursionDepth = currentRecursionDepth + 1;
        List<Thread> threadsThatHaveCurrentCacheKeyAsAnActiveLock = cacheKeyToThreadRelationships
                .getThreadsThatAcquiredActiveLock();
        List<Thread> threadsThatHaveCurrentCacheKeyAsAReadLockLock = cacheKeyToThreadRelationships
                .getThreadsThatAcquiredReadLock();

        // (c) Scenario 3:
        // We need to have a look at the active thread on the cache key as a last resort aspect to consider
        // Our primary strategy of getThreadsThatAcquiredActiveLock did not bare any fruits we will still consider the
        // cache key itself and check if it has any active thread
        Thread activeThreadOnCacheKey = cacheKeyThreadWantsToAcquireButCannotGet.getActiveThread();
        boolean cacheKeyHasActiveThreadWeDidNotAnalyze =
                // the hey is being owned by somebody
                activeThreadOnCacheKey != null
                        // that somebody is not the thread we are expanding in this iteration
                        && !activeThreadOnCacheKey.equals(currentCandidateThreadPartOfTheDeadLock)
                        // that thread is not any of the threads we have already tried expanding during this expansion
                        // logic
                        && !(threadsThatHaveCurrentCacheKeyAsAnActiveLock.contains(activeThreadOnCacheKey)
                                || threadsThatHaveCurrentCacheKeyAsAReadLockLock.contains(activeThreadOnCacheKey));
        if (cacheKeyHasActiveThreadWeDidNotAnalyze) {
            // NOTE:
            // here we have abit of a problem we are facing the following scenario we know our current Thread A wants to
            // acquire the cachke key B
            // and we now know as well that cache key B is being owned by Thread B
            // But our CacheKeyToThreadRelationships was not aware that Thread B was owning owning
            // cache key B for writing
            // this could be something similar to the scenario where we have seen a dead lock where the Lock at the
            // center of the dead lock
            // had as an active thread a thread that was no longer working...
            //

            // (i) We are afraid of cache corruptionso we do a small sanity to check to try to understand if we are
            // "tracking" this new active
            // thread and are aware of any resources it needs
            Thread nextCandidateThreadPartOfTheDeadLock = activeThreadOnCacheKey;
            boolean sanityCheckToDoKnowOfAnyResourcesNeededByNextThreadToExpand = currentThreadIsKnownToBeWaitingForAnyResource(
                    concurrencyManagerState, nextCandidateThreadPartOfTheDeadLock);
            if (!sanityCheckToDoKnowOfAnyResourcesNeededByNextThreadToExpand) {
                // We are clueless - perhaps we should return here a DTO saying we might have just found our dead lock
                // this cache key has an active thread that seems to not be tracked by our
                // ConcurrencyManagerState
                //
                StringWriter writer = new StringWriter();
                writer.write(TraceLocalization.buildMessage("explain_dead_lock_util_current_thread_blocked_active_thread_warning",
                        new Object[] {nextCandidateThreadPartOfTheDeadLock.getName(),
                        currentCandidateThreadPartOfTheDeadLock.getName(),
                        ConcurrencyUtil.SINGLETON.createToStringExplainingOwnedCacheKey(
                        cacheKeyThreadWantsToAcquireButCannotGet)}));
                AbstractSessionLog.getLog().log(SessionLog.WARNING, SessionLog.CACHE, writer.toString(), new Object[] {}, false);
                return DEAD_LOCK_NOT_FOUND;
            } else {
                // The active thread on the cache key is needing some resources we are tracing
                // so that means that the active thread is probably also stuck itself
                // we want to go forward with the recursive expansion

                // (i) Go deeper into the recursion expanding the next thread
                DeadLockComponent expansionResult = recursiveExplainPossibleDeadLockStep01(
                        concurrencyManagerState, recursionMaxDepth,
                        // go one level and thread deeper hunting for a dead lock
                        nextRecursionDepth, nextCandidateThreadPartOfTheDeadLock,
                        nexThreadPartOfCurrentDeadLockExpansion,
                        threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain);

                // (ii) check if we have found our dead lock
                if (expansionResult != null) {
                    if (currentThreadWantsToAcquireForWriting) {
                        return deadLockFoundCreateConcurrencyManagerStateWriterThreadCouldNotAcquireWriteLock(
                                expansionResult, currentCandidateThreadPartOfTheDeadLock,
                                cacheKeyThreadWantsToAcquireButCannotGet);
                    } else {
                        return deadLockFoundCreateConcurrencyManagerStateReaderThreadCouldNotAcquireWriteLock(
                                expansionResult, currentCandidateThreadPartOfTheDeadLock,
                                cacheKeyThreadWantsToAcquireButCannotGet);
                    }
                }
            }

        }
        return DEAD_LOCK_NOT_FOUND;
    }



    /**
     * When a thead cannot move forward due to having deferred cache keys, it means that the thread could not go as deep
     * as it wanted during object building and hda to defer making some parts of the object. The thread is stuck because
     * the parts of the object it could not build are apparently not finished either.
     *
     * @return NULL if we are able to explain a dead lock via expanding this the current candidate thread Otherwiser a
     *         DTO component that explains the the dad lock
     */
    protected DeadLockComponent recursiveExplainPossibleDeadLockStep04ExpandBasedOnThreadStuckOnReleaseDeferredLocks(
            final ConcurrencyManagerState concurrencyManagerStateDto,
            final int recursionMaxDepth, final int currentRecursionDepth,
            final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion,
            Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain) {

        // (a) Run the auxiliary algorithm that can explain why a thread stuck in the release deferred locks
        // is not able to make progress.
        // To understand why we do this one would need to have a good look at the concurrenyc manager implementation
        // at the logic that of the logic of the releaseDeferredLock method
        IsBuildObjectCompleteOutcome result = isBuildObjectOnThreadComplete(concurrencyManagerStateDto, currentCandidateThreadPartOfTheDeadLock,  new IdentityHashMap<>());

        // (b) Our expectation is that the result of the step above is always different than null
        // after all if this candidate thread is stuck trying to release deferred locks there must be an explanation for it not making progress
        // the only case where it would make sense for this to be null is if the current candidate is actually making progress and
        // was stuck for only a short period
        if(result == null) {
            StringWriter writer = new StringWriter();
            writer.write(TraceLocalization.buildMessage("explain_dead_lock_util_thread_stuck_deferred_locks", new Object[] {currentCandidateThreadPartOfTheDeadLock.getName()}));
            AbstractSessionLog.getLog().log(SessionLog.WARNING, SessionLog.CACHE, writer.toString(), new Object[] {}, false);
            return DEAD_LOCK_NOT_FOUND;
        }

        // (c) At this point we have an idea of what thread is causing harm to us
        // so we will now try to expand the thread that is harming us from progressing further

        // (i) Start by preparing some basic immutable variables to go deeper one recursion level
        List<Thread> nexThreadPartOfCurrentDeadLockExpansion = new ArrayList<>(threadPartOfCurrentDeadLockExpansion);
        nexThreadPartOfCurrentDeadLockExpansion.add(currentCandidateThreadPartOfTheDeadLock);
        nexThreadPartOfCurrentDeadLockExpansion = Collections.unmodifiableList(nexThreadPartOfCurrentDeadLockExpansion);
        final int nextRecursionDepth = currentRecursionDepth + 1;
        final Thread nextCandidateThreadPartOfTheDeadLock = result.getThreadBlockingTheDeferringThreadFromFinishing();
        final ConcurrencyManager cacheKeyBlockingIsBuildObjectComplete = result.getCacheKeyOwnedByBlockingThread();

        // (i) Go deeper into the recursion expanding the next thread
        DeadLockComponent expansionResult = recursiveExplainPossibleDeadLockStep01(
                concurrencyManagerStateDto, recursionMaxDepth,
                // go one level and thread deeper hunting for a dead lock
                nextRecursionDepth, nextCandidateThreadPartOfTheDeadLock, nexThreadPartOfCurrentDeadLockExpansion,
                threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain);

        // (ii) If the thread we expanded when we went deeper leads to a dead lock explanation
        // continue unwinding the dead lock explanation
        if(expansionResult != null) {
            return deadLockFoundCreateConcurrencyManagerStateDeferredThreadCouldNotAcquireWriteLock(
                    expansionResult, currentCandidateThreadPartOfTheDeadLock, cacheKeyBlockingIsBuildObjectComplete);
        }

        // (iii) We reached a dead end we need to continue expanding other candidate threads
        return DEAD_LOCK_NOT_FOUND;
    }

    /**
     * In this case have a thread that wants to acquire for reading a cache key but it does not manage to acquire it
     * because the cache key is being owned by somebody else. So we need to see what the writer of this cache key is
     * doing.
     *
     */
    protected DeadLockComponent recursiveExplainPossibleDeadLockStep05ExpandBasedOnCacheKeyWantedForReading(
            final ConcurrencyManagerState concurrencyManagerStateDto,
            final int recursionMaxDepth, final int currentRecursionDepth,
            final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion,
            Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain,
            ConcurrencyManager cacheKeyCurrentThreadWantsForReadingButCannotGet) {


        // (c) Scenario 1: (current writer thread competing with other writers)
        // The current cache key is acquired for Writing by some other thread so it cannot be acquired for writing by
        // this thread we are trying to expand
        // NOTE: at most there should only be one thread on this list
        DeadLockComponent expansionResult = recursiveExplainPossibleDeadLockStep05Scenario01CurrentReaderVsOtherWriters(concurrencyManagerStateDto,
                recursionMaxDepth, currentRecursionDepth, currentCandidateThreadPartOfTheDeadLock,
                threadPartOfCurrentDeadLockExpansion, threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain,
                cacheKeyCurrentThreadWantsForReadingButCannotGet);
        if(expansionResult != null) {
            return expansionResult;
        }


        // (d) Scenario 2:
        // We need to have a look at the active thread on the cache key as a last resort aspect to consider
        // Our primary strategy of getThreadsThatAcquiredActiveLock did not bare any fruits we will still consider the
        // cache key itself and check if it has any active thread
        expansionResult = recursiveExplainPossibleDeadLockStep05Scenario02CurrentReaderVsCacheKeyActiveThread(
                concurrencyManagerStateDto, recursionMaxDepth, currentRecursionDepth,
                currentCandidateThreadPartOfTheDeadLock, threadPartOfCurrentDeadLockExpansion,
                threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain,
                cacheKeyCurrentThreadWantsForReadingButCannotGet);
        if (expansionResult != null) {
            // perhaps we could log a warning here becuase if this scenario bares any fruits we do not really understand
            // what we are doing wrong in tracing the concurrency layer
            // we assume that each time a thread sets itself as the active thread on a cache key
            // we will wil trace this thread when it needs to acquire a lock and fails to get it
            return expansionResult;
        }

        // (e) We are out of ideas on how to expand further the current thread
        // we need to
        return DEAD_LOCK_NOT_FOUND;
    }

    /**
     * This method is nothing more than copy paste code from the algorithm
     *
     * {@link ConcurrencyManager#isBuildObjectOnThreadComplete(Thread, Map, List, boolean)}
     *
     * We re-write this code to instead of returning true/false return an actual DTO object that can allow our dead lock
     * explanation algorithm to identify the next thread to expand to explain the dead lock.
     *
     * @param concurrencyManagerStateDto
     *            our representation of a cloned ste of the concurrency manager and write lock manager
     * @param thread
     *            the current thread to explore which might have deferred locks. At level 1 of the recursion the thread
     *            is certain to have deferred locks.
     * @param recursiveSet
     *            this is an hash map holding the threads in the current recusion algorithm that have been expanded
     *            already to avoid expanding more than once the same thread and going into an infinite dead lock.
     *
     */
    public static IsBuildObjectCompleteOutcome isBuildObjectOnThreadComplete(
            final ConcurrencyManagerState concurrencyManagerStateDto, Thread thread,
            Map<Thread, Thread> recursiveSet) {
        if (recursiveSet.containsKey(thread)) {
            // if the thread we are consider as we go deeper in the recursion is thread in an upper stack of the
            // recursion
            // we can just return true since a thread A can not be responsible for getting itself stuck
            // simply return true and focus the attention on other threads not yet part of the recursive set
            // see if any of these is causing a blockage
            // return true
            return IsBuildObjectCompleteOutcome.BUILD_OBJECT_IS_COMPLETE_TRUE;
        }
        recursiveSet.put(thread, thread);

        // DeferredLockManager lockManager = getDeferredLockManager(thread);
        DeferredLockManager lockManager = concurrencyManagerStateDto.getDeferredLockManagerMapClone().get(thread);
        if (lockManager == null) {
            // return true
            return IsBuildObjectCompleteOutcome.BUILD_OBJECT_IS_COMPLETE_TRUE;
        }

        Vector<ConcurrencyManager> deferredLocks = lockManager.getDeferredLocks();
        for (Enumeration<ConcurrencyManager> deferredLocksEnum = deferredLocks.elements(); deferredLocksEnum.hasMoreElements();) {
            ConcurrencyManager deferedLock = deferredLocksEnum.nextElement();
            Thread activeThread = null;
            if (deferedLock.isAcquired()) {
                activeThread = deferedLock.getActiveThread();

                // the active thread may be set to null at anypoint
                // if added for CR 2330
                if (activeThread != null) {
                    // DeferredLockManager currentLockManager = getDeferredLockManager(activeThread);
                    DeferredLockManager currentLockManager = concurrencyManagerStateDto.getDeferredLockManagerMapClone()
                            .get(thread);
                    if (currentLockManager == null) {
                        // return false;

                        return new IsBuildObjectCompleteOutcome(activeThread, deferedLock);
                    } else if (currentLockManager.isThreadComplete()) {
                        activeThread = deferedLock.getActiveThread();
                        // The lock may suddenly finish and no longer have an active thread.
                        if (activeThread != null) {
                            IsBuildObjectCompleteOutcome recursiveOutcome = isBuildObjectOnThreadComplete(
                                    concurrencyManagerStateDto, activeThread, recursiveSet);
                            if (recursiveOutcome != null) {
                                return new IsBuildObjectCompleteOutcome(activeThread, deferedLock);
                            }
                        }
                    } else {
                        return new IsBuildObjectCompleteOutcome(activeThread, deferedLock);
                    }
                }
            }
        }
        return IsBuildObjectCompleteOutcome.BUILD_OBJECT_IS_COMPLETE_TRUE;
    }

    // Create DTO Components when a dead lock is discovered

    /**
     * Create a dead lock dto component.
     *
     * @param nextThreadPartOfDeadLock
     *            the dto component of a dead lock that comes from a depper recursion expansion
     * @param threadNotAbleToAccessResource
     *            the thread at the current depth that is part of the dead lock
     * @param cacheKeyThreadWantsToAcquireButCannotGet
     *            the cache key that the thread wanted to acquire for writing
     * @return the DTO representing a component part of a dead lock
     */
    protected DeadLockComponent deadLockFoundCreateConcurrencyManagerStateWriterThreadCouldNotAcquireWriteLock(
            final DeadLockComponent nextThreadPartOfDeadLock, Thread threadNotAbleToAccessResource,
            ConcurrencyManager cacheKeyThreadWantsToAcquireButCannotGet) {
        boolean stuckOnReleaseDeferredLock = false;
        boolean stuckThreadAcquiringLockForWriting = true;
        boolean stuckThreadAcquiringLockForReading = false;
        boolean deadLockPotentiallyCausedByCacheKeyWithCorruptedActiveThread = false;
        boolean deadLockPotentiallyCausedByCacheKeyWithCorruptedNumberOfReaders = false;
        return new DeadLockComponent(threadNotAbleToAccessResource, stuckOnReleaseDeferredLock,
                stuckThreadAcquiringLockForWriting, stuckThreadAcquiringLockForReading,
                cacheKeyThreadWantsToAcquireButCannotGet, deadLockPotentiallyCausedByCacheKeyWithCorruptedActiveThread,
                deadLockPotentiallyCausedByCacheKeyWithCorruptedNumberOfReaders, nextThreadPartOfDeadLock);
    }

    /**
     * Dto component participating in a dead lock.
     *
     * @param nextThreadPartOfDeadLock
     *            the thread that was participating in the dead lock as we went deeper in the recursion.
     * @param threadNotAbleToAccessResource
     *            the thread at the current depth that is part of the dead lock
     * @param cacheKeyThreadWantsToAcquireButCannotGet
     *            the cache key that the thread wanted to acquire for writing
     * @return the DTO representing a component part of a dead lock
     */
    protected DeadLockComponent deadLockFoundCreateConcurrencyManagerStateReaderThreadCouldNotAcquireWriteLock(
            final DeadLockComponent nextThreadPartOfDeadLock, Thread threadNotAbleToAccessResource,
            ConcurrencyManager cacheKeyThreadWantsToAcquireButCannotGet) {
        boolean stuckOnReleaseDeferredLock = false;
        boolean stuckThreadAcquiringLockForWriting = false;
        boolean stuckThreadAcquiringLockForReading = true;
        boolean deadLockPotentiallyCausedByCacheKeyWithCorruptedActiveThread = false;
        boolean deadLockPotentiallyCausedByCacheKeyWithCorruptedNumberOfReaders = false;
        return new DeadLockComponent(threadNotAbleToAccessResource, stuckOnReleaseDeferredLock,
                stuckThreadAcquiringLockForWriting, stuckThreadAcquiringLockForReading,
                cacheKeyThreadWantsToAcquireButCannotGet, deadLockPotentiallyCausedByCacheKeyWithCorruptedActiveThread,
                deadLockPotentiallyCausedByCacheKeyWithCorruptedNumberOfReaders, nextThreadPartOfDeadLock);
    }

    /**
     * Create a deadlock component for a thread known to be stuck trying to release deferred locks.
     *
     * @param nextThreadPartOfDeadLock
     *            the thread that was participating in the dead lock as we went deeper in the recursion.
     * @param threadNotAbleToAccessResource
     *            the thread at the current depth that is part of the dead lock
     * @param cacheKeyBlockingIsBuildObjectComplete
     *            this is a cache key that is not necessarily desired by the blocked thread, but which is recrusively
     *            blocking the thread stuck in {@code isBuildObjectcomplete} logic. This is a bit complicated to
     *            explain, but essentially when a thread cannot acquire write lock it sometimes can defer on the lock.
     *            Later to finish object building the thread will be waiting to make sure that locks it deferred are
     *            considered to be all finished. When deferred lock is not finished it could be cause much deeper some
     *            other secondary object could not be built due to some cache key not accessible.. Therefore the
     *            cacheKeyBlockingIsBuildObjectComplete might be quite deep and far away from the cache key our thread
     *            had to defer... It is an element blocking our thread from finishing.
     * @return the DTO representing a component part of a dead lock
     */
    protected DeadLockComponent deadLockFoundCreateConcurrencyManagerStateDeferredThreadCouldNotAcquireWriteLock(
            final DeadLockComponent nextThreadPartOfDeadLock, Thread threadNotAbleToAccessResource,
            ConcurrencyManager cacheKeyBlockingIsBuildObjectComplete) {
        boolean stuckOnReleaseDeferredLock = true;
        boolean stuckThreadAcquiringLockForWriting = false;
        boolean stuckThreadAcquiringLockForReading = false;
        boolean deadLockPotentiallyCausedByCacheKeyWithCorruptedActiveThread = false;
        boolean deadLockPotentiallyCausedByCacheKeyWithCorruptedNumberOfReaders = false;
        return new DeadLockComponent(threadNotAbleToAccessResource, stuckOnReleaseDeferredLock,
                stuckThreadAcquiringLockForWriting, stuckThreadAcquiringLockForReading,
                cacheKeyBlockingIsBuildObjectComplete, deadLockPotentiallyCausedByCacheKeyWithCorruptedActiveThread,
                deadLockPotentiallyCausedByCacheKeyWithCorruptedNumberOfReaders, nextThreadPartOfDeadLock);
    }
}
