Top Description Fields Constructors Methods
org.eclipse.persistence.internal.helper

public Class ExplainDeadLockUtil

extends Object
Class Inheritance
Imports
org.eclipse.persistence.internal.helper.type.CacheKeyToThreadRelationships, .ConcurrencyManagerState, .DeadLockComponent, .IsBuildObjectCompleteOutcome, org.eclipse.persistence.internal.localization.TraceLocalization, org.eclipse.persistence.logging.AbstractSessionLog, .SessionLog, java.io.StringWriter, java.util.*

The purpose of this class is to try explain the nature of a dead lock

Field Summary

Modifier and TypeField and Description
private static final DeadLockComponent
public static final ExplainDeadLockUtil

Constructor Summary

AccessConstructor and Description
private

Method Summary

Modifier and TypeMethod and Description
protected List<DeadLockComponent>

Returns:

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.
createListExplainingDeadLock
(DeadLockComponent
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.
deadLockExplanation
)

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 org.eclipse.persistence.internal.helper.type.DeadLockComponent#isFirstRepeatingThreadThatExplainsDeadLock() but it lacks all additional metadata.

protected boolean

Returns:

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.
currentThreadIsKnownToBeWaitingForAnyResource
(final ConcurrencyManagerState
the dto that holds the state of the cocurrency manager for our dead lock detection algorithm
concurrencyManagerStateDto
,
final Thread
the thread we are trying to evaluate
currentCandidateThreadPartOfTheDeadLock
)

This a helper sanity check.

protected DeadLockComponent

Returns:

the DTO representing a component part of a dead lock
deadLockFoundCreateConcurrencyManagerStateDeferredThreadCouldNotAcquireWriteLock
(final DeadLockComponent
the thread that was participating in the dead lock as we went deeper in the recursion.
nextThreadPartOfDeadLock
,
Thread
the thread at the current depth that is part of the dead lock
threadNotAbleToAccessResource
,
ConcurrencyManager
this is a cache key that is not necessarily desired by the blocked thread, but which is recrusively blocking the thread stuck in 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.
cacheKeyBlockingIsBuildObjectComplete
)

Create a deadlock component for a thread known to be stuck trying to release deferred locks.

protected DeadLockComponent

Returns:

the DTO representing a component part of a dead lock
deadLockFoundCreateConcurrencyManagerStateReaderThreadCouldNotAcquireWriteLock
(final DeadLockComponent
the thread that was participating in the dead lock as we went deeper in the recursion.
nextThreadPartOfDeadLock
,
Thread
the thread at the current depth that is part of the dead lock
threadNotAbleToAccessResource
,
ConcurrencyManager
the cache key that the thread wanted to acquire for writing
cacheKeyThreadWantsToAcquireButCannotGet
)

Dto component participating in a dead lock.

protected DeadLockComponent

Returns:

the DTO representing a component part of a dead lock
deadLockFoundCreateConcurrencyManagerStateWriterThreadCouldNotAcquireWriteLock
(final DeadLockComponent
the dto component of a dead lock that comes from a depper recursion expansion
nextThreadPartOfDeadLock
,
Thread
the thread at the current depth that is part of the dead lock
threadNotAbleToAccessResource
,
ConcurrencyManager
the cache key that the thread wanted to acquire for writing
cacheKeyThreadWantsToAcquireButCannotGet
)

Create a dead lock dto component.

public List<DeadLockComponent>

Returns:

A string that tries
explainPossibleDeadLockStartRecursion
(ConcurrencyManagerState
A clone we have assembled based on the concurrency manager and write lock manager state
concurrencyManagerState
)

Given the concurrency manager state try to explain why we are facing a dead lock.

public static IsBuildObjectCompleteOutcome
isBuildObjectOnThreadComplete(final ConcurrencyManagerState
our representation of a cloned ste of the concurrency manager and write lock manager
concurrencyManagerStateDto
,
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.
thread
,
Map<Thread, Thread>
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.
recursiveSet
)

This method is nothing more than copy paste code from the algorithm 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.

protected DeadLockComponent

Returns:

NULL if no dead lock is found. a value if a deadlock is found
recursiveExpansionCurrentThreadBeingBlockedByActiveThreadOnCacheKey
(final ConcurrencyManagerState
state of the concurrency manager
concurrencyManagerState
,
final int
max allowed depth for recursion.
recursionMaxDepth
,
final int
the current recursion depth
currentRecursionDepth
,
final Thread
the current thread we are expanding in dpeth
currentCandidateThreadPartOfTheDeadLock
,
List<Thread>
the current thread of sets comrpising our dead lock expansion.
threadPartOfCurrentDeadLockExpansion
,
Set<Thread>
threads we have expanded in the past and gave no fruits
threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain
,
ConcurrencyManager
the cache key we know our current candidate wants and is not getting.
cacheKeyThreadWantsToAcquireButCannotGet
,
boolean
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.
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.

protected DeadLockComponent

Returns:

NULL if no dead lock is found. a value if a deadlock is found
recursiveExpansionCurrentThreadBeingBlockedByActiveWriters
(final ConcurrencyManagerState
state of the concurrency manager
concurrencyManagerState
,
final int
max allowed depth for recursion.
recursionMaxDepth
,
final int
the current recursion depth
currentRecursionDepth
,
final Thread
the current thread we are expanding in dpeth
currentCandidateThreadPartOfTheDeadLock
,
List<Thread>
the current thread of sets comrpising our dead lock expansion.
threadPartOfCurrentDeadLockExpansion
,
Set<Thread>
threads we have expanded in the past and gave no fruits
threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain
,
ConcurrencyManager
the cache key we know our current candidate wants and is not getting.
cacheKeyThreadWantsToAcquireButCannotGet
,
boolean
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.
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.

protected DeadLockComponent

Returns:

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..
recursiveExplainPossibleDeadLockStep01
(final ConcurrencyManagerState concurrencyManagerStateDto, final int
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.
recursionMaxDepth
,
final int
how deep we are in the recursion
currentRecursionDepth
,
final Thread
the current thread we want to expand
currentCandidateThreadPartOfTheDeadLock
,
List<Thread>
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.
threadPartOfCurrentDeadLockExpansion
,
Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain)

The algorithm expands the current thread in depth.

protected DeadLockComponent

Returns:

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..
recursiveExplainPossibleDeadLockStep02
(final ConcurrencyManagerState concurrencyManagerStateDto, final int
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.
recursionMaxDepth
,
final int
how deep we are in the recursion
currentRecursionDepth
,
final Thread
the current thread we want to expand
currentCandidateThreadPartOfTheDeadLock
,
List<Thread>
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.
threadPartOfCurrentDeadLockExpansion
,
Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain)

Precondition the logic of recursiveExplainPossibleDeadLockStep01(ConcurrencyManagerState, int, int, Thread, List, Set) has been invoked and determined that we need to go deeper and expand the current thread.

protected DeadLockComponent

Returns:

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
recursiveExplainPossibleDeadLockStep03ExpandBasedOnCacheKeyWantedForWriting
(final ConcurrencyManagerState
state of concurrency manager
concurrencyManagerStateDto
,
final int
how deep the recursion can go
recursionMaxDepth
,
final int
the current depeth
currentRecursionDepth
,
final Thread
the current thread we are expanding and that may be involved in explaning a dead lock
currentCandidateThreadPartOfTheDeadLock
,
List<Thread>
the predecessor threads that are part of a dead lock expansion we are searching
threadPartOfCurrentDeadLockExpansion
,
Set<Thread>
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.
threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain
,
ConcurrencyManager
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
cacheKeyCurrentThreadWantsForWritingButCannotGet
)

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.

protected DeadLockComponent
recursiveExplainPossibleDeadLockStep03Scenario01CurrentWriterVsOtherWritersWriter(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet)

Expand the possibility of the current thread wanting to acquire for writing what some other already has acquired for writing.

protected DeadLockComponent

Returns:

NULL if dead lock not discovered. Otherwise dead lock component justifying the deadlock.
recursiveExplainPossibleDeadLockStep03Scenario02CurrentWriterVsOtherReader
(final ConcurrencyManagerState concurrencyManagerState, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet)

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.

protected DeadLockComponent

Returns:

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.
recursiveExplainPossibleDeadLockStep03Scenario03CurrentWriterVsCacheKeyActiveThread
(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet)

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.

protected DeadLockComponent

Returns:

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
recursiveExplainPossibleDeadLockStep04ExpandBasedOnThreadStuckOnReleaseDeferredLocks
(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain)

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.

protected DeadLockComponent
recursiveExplainPossibleDeadLockStep05ExpandBasedOnCacheKeyWantedForReading(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForReadingButCannotGet)

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.

protected DeadLockComponent
recursiveExplainPossibleDeadLockStep05Scenario01CurrentReaderVsOtherWriters(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet)

Expand the possibility of the current thread wanting to acquire for writing what some other already has acquired 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)

Same as 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.

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

DEAD_LOCK_NOT_FOUNDback to summary
private static final DeadLockComponent DEAD_LOCK_NOT_FOUND
SINGLETONback to summary
public static final ExplainDeadLockUtil SINGLETON

Constructor Detail

ExplainDeadLockUtilback to summary
private ExplainDeadLockUtil()

Method Detail

createListExplainingDeadLockback to summary
protected List<DeadLockComponent> createListExplainingDeadLock(DeadLockComponent deadLockExplanation)

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 org.eclipse.persistence.internal.helper.type.DeadLockComponent#isFirstRepeatingThreadThatExplainsDeadLock() but it lacks all additional metadata. so we want enrich the missing metadata into this dto.

Parameters
deadLockExplanation:DeadLockComponent

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.

Returns:List<DeadLockComponent>

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.

currentThreadIsKnownToBeWaitingForAnyResourceback to summary
protected boolean currentThreadIsKnownToBeWaitingForAnyResource(final ConcurrencyManagerState concurrencyManagerStateDto, final Thread currentCandidateThreadPartOfTheDeadLock)

This a helper sanity check. Whenever we expand a threa we expect the thread must be starved fro some resource.

Parameters
concurrencyManagerStateDto:ConcurrencyManagerState

the dto that holds the state of the cocurrency manager for our dead lock detection algorithm

currentCandidateThreadPartOfTheDeadLock:Thread

the thread we are trying to evaluate

Returns:boolean

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.

deadLockFoundCreateConcurrencyManagerStateDeferredThreadCouldNotAcquireWriteLockback to summary
protected DeadLockComponent deadLockFoundCreateConcurrencyManagerStateDeferredThreadCouldNotAcquireWriteLock(final DeadLockComponent nextThreadPartOfDeadLock, Thread threadNotAbleToAccessResource, ConcurrencyManager cacheKeyBlockingIsBuildObjectComplete)

Create a deadlock component for a thread known to be stuck trying to release deferred locks.

Parameters
nextThreadPartOfDeadLock:DeadLockComponent

the thread that was participating in the dead lock as we went deeper in the recursion.

threadNotAbleToAccessResource:Thread

the thread at the current depth that is part of the dead lock

cacheKeyBlockingIsBuildObjectComplete:ConcurrencyManager

this is a cache key that is not necessarily desired by the blocked thread, but which is recrusively blocking the thread stuck in 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.

Returns:DeadLockComponent

the DTO representing a component part of a dead lock

deadLockFoundCreateConcurrencyManagerStateReaderThreadCouldNotAcquireWriteLockback to summary
protected DeadLockComponent deadLockFoundCreateConcurrencyManagerStateReaderThreadCouldNotAcquireWriteLock(final DeadLockComponent nextThreadPartOfDeadLock, Thread threadNotAbleToAccessResource, ConcurrencyManager cacheKeyThreadWantsToAcquireButCannotGet)

Dto component participating in a dead lock.

Parameters
nextThreadPartOfDeadLock:DeadLockComponent

the thread that was participating in the dead lock as we went deeper in the recursion.

threadNotAbleToAccessResource:Thread

the thread at the current depth that is part of the dead lock

cacheKeyThreadWantsToAcquireButCannotGet:ConcurrencyManager

the cache key that the thread wanted to acquire for writing

Returns:DeadLockComponent

the DTO representing a component part of a dead lock

deadLockFoundCreateConcurrencyManagerStateWriterThreadCouldNotAcquireWriteLockback to summary
protected DeadLockComponent deadLockFoundCreateConcurrencyManagerStateWriterThreadCouldNotAcquireWriteLock(final DeadLockComponent nextThreadPartOfDeadLock, Thread threadNotAbleToAccessResource, ConcurrencyManager cacheKeyThreadWantsToAcquireButCannotGet)

Create a dead lock dto component.

Parameters
nextThreadPartOfDeadLock:DeadLockComponent

the dto component of a dead lock that comes from a depper recursion expansion

threadNotAbleToAccessResource:Thread

the thread at the current depth that is part of the dead lock

cacheKeyThreadWantsToAcquireButCannotGet:ConcurrencyManager

the cache key that the thread wanted to acquire for writing

Returns:DeadLockComponent

the DTO representing a component part of a dead lock

explainPossibleDeadLockStartRecursionback to summary
public List<DeadLockComponent> explainPossibleDeadLockStartRecursion(ConcurrencyManagerState concurrencyManagerState)

Given the concurrency manager state try to explain why we are facing a dead lock.

Parameters
concurrencyManagerState:ConcurrencyManagerState

A clone we have assembled based on the concurrency manager and write lock manager state

Returns:List<DeadLockComponent>

A string that tries

isBuildObjectOnThreadCompleteback to summary
public static IsBuildObjectCompleteOutcome isBuildObjectOnThreadComplete(final ConcurrencyManagerState concurrencyManagerStateDto, Thread thread, Map<Thread, Thread> recursiveSet)

This method is nothing more than copy paste code from the algorithm 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.

Parameters
concurrencyManagerStateDto:ConcurrencyManagerState

our representation of a cloned ste of the concurrency manager and write lock manager

thread: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.

recursiveSet:Map<Thread, Thread>

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.

recursiveExpansionCurrentThreadBeingBlockedByActiveThreadOnCacheKeyback to summary
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)

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.

Parameters
concurrencyManagerState:ConcurrencyManagerState

state of the concurrency manager

recursionMaxDepth:int

max allowed depth for recursion.

currentRecursionDepth:int

the current recursion depth

currentCandidateThreadPartOfTheDeadLock:Thread

the current thread we are expanding in dpeth

threadPartOfCurrentDeadLockExpansion:List<Thread>

the current thread of sets comrpising our dead lock expansion.

threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain:Set<Thread>

threads we have expanded in the past and gave no fruits

cacheKeyThreadWantsToAcquireButCannotGet:ConcurrencyManager

the cache key we know our current candidate wants and is not getting.

currentThreadWantsToAcquireForWriting:boolean

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.

Returns:DeadLockComponent

NULL if no dead lock is found. a value if a deadlock is found

recursiveExpansionCurrentThreadBeingBlockedByActiveWritersback to summary
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)

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.

Parameters
concurrencyManagerState:ConcurrencyManagerState

state of the concurrency manager

recursionMaxDepth:int

max allowed depth for recursion.

currentRecursionDepth:int

the current recursion depth

currentCandidateThreadPartOfTheDeadLock:Thread

the current thread we are expanding in dpeth

threadPartOfCurrentDeadLockExpansion:List<Thread>

the current thread of sets comrpising our dead lock expansion.

threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain:Set<Thread>

threads we have expanded in the past and gave no fruits

cacheKeyThreadWantsToAcquireButCannotGet:ConcurrencyManager

the cache key we know our current candidate wants and is not getting.

currentThreadWantsToAcquireForWriting:boolean

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.

Returns:DeadLockComponent

NULL if no dead lock is found. a value if a deadlock is found

recursiveExplainPossibleDeadLockStep01back to summary
protected DeadLockComponent recursiveExplainPossibleDeadLockStep01(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain)

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.

Parameters
recursionMaxDepth:int

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.

currentRecursionDepth:int

how deep we are in the recursion

currentCandidateThreadPartOfTheDeadLock:Thread

the current thread we want to expand

threadPartOfCurrentDeadLockExpansion:List<Thread>

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.

Returns:DeadLockComponent

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..

recursiveExplainPossibleDeadLockStep02back to summary
protected DeadLockComponent recursiveExplainPossibleDeadLockStep02(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain)

Precondition the logic of recursiveExplainPossibleDeadLockStep01(ConcurrencyManagerState, int, int, Thread, List, Set) has been invoked and determined that we need to go deeper and expand the current thread.

Parameters
recursionMaxDepth:int

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.

currentRecursionDepth:int

how deep we are in the recursion

currentCandidateThreadPartOfTheDeadLock:Thread

the current thread we want to expand

threadPartOfCurrentDeadLockExpansion:List<Thread>

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.

Returns:DeadLockComponent

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..

recursiveExplainPossibleDeadLockStep03ExpandBasedOnCacheKeyWantedForWritingback to summary
protected DeadLockComponent recursiveExplainPossibleDeadLockStep03ExpandBasedOnCacheKeyWantedForWriting(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet)

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 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.

Parameters
concurrencyManagerStateDto:ConcurrencyManagerState

state of concurrency manager

recursionMaxDepth:int

how deep the recursion can go

currentRecursionDepth:int

the current depeth

currentCandidateThreadPartOfTheDeadLock:Thread

the current thread we are expanding and that may be involved in explaning a dead lock

threadPartOfCurrentDeadLockExpansion:List<Thread>

the predecessor threads that are part of a dead lock expansion we are searching

threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain:Set<Thread>

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.

cacheKeyCurrentThreadWantsForWritingButCannotGet:ConcurrencyManager

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

Returns:DeadLockComponent

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

recursiveExplainPossibleDeadLockStep03Scenario01CurrentWriterVsOtherWritersWriterback to summary
protected DeadLockComponent recursiveExplainPossibleDeadLockStep03Scenario01CurrentWriterVsOtherWritersWriter(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet)

Expand the possibility of the current thread wanting to acquire for writing what some other already has acquired for writing.

recursiveExplainPossibleDeadLockStep03Scenario02CurrentWriterVsOtherReaderback to summary
protected DeadLockComponent recursiveExplainPossibleDeadLockStep03Scenario02CurrentWriterVsOtherReader(final ConcurrencyManagerState concurrencyManagerState, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet)

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.

Returns:DeadLockComponent

NULL if dead lock not discovered. Otherwise dead lock component justifying the deadlock.

recursiveExplainPossibleDeadLockStep03Scenario03CurrentWriterVsCacheKeyActiveThreadback to summary
protected DeadLockComponent recursiveExplainPossibleDeadLockStep03Scenario03CurrentWriterVsCacheKeyActiveThread(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet)

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.

Returns:DeadLockComponent

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.

recursiveExplainPossibleDeadLockStep04ExpandBasedOnThreadStuckOnReleaseDeferredLocksback to summary
protected DeadLockComponent recursiveExplainPossibleDeadLockStep04ExpandBasedOnThreadStuckOnReleaseDeferredLocks(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain)

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.

Returns:DeadLockComponent

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

recursiveExplainPossibleDeadLockStep05ExpandBasedOnCacheKeyWantedForReadingback to summary
protected DeadLockComponent recursiveExplainPossibleDeadLockStep05ExpandBasedOnCacheKeyWantedForReading(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForReadingButCannotGet)

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.

recursiveExplainPossibleDeadLockStep05Scenario01CurrentReaderVsOtherWritersback to summary
protected DeadLockComponent recursiveExplainPossibleDeadLockStep05Scenario01CurrentReaderVsOtherWriters(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet)

Expand the possibility of the current thread wanting to acquire for writing what some other already has acquired for writing.

recursiveExplainPossibleDeadLockStep05Scenario02CurrentReaderVsCacheKeyActiveThreadback to summary
protected DeadLockComponent recursiveExplainPossibleDeadLockStep05Scenario02CurrentReaderVsCacheKeyActiveThread(final ConcurrencyManagerState concurrencyManagerStateDto, final int recursionMaxDepth, final int currentRecursionDepth, final Thread currentCandidateThreadPartOfTheDeadLock, List<Thread> threadPartOfCurrentDeadLockExpansion, Set<Thread> threadsAlreadyExpandedInThePastThatWeDoNotWantToExpandAgain, ConcurrencyManager cacheKeyCurrentThreadWantsForWritingButCannotGet)

Same as 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.