Module org.eclipse.persistence.core
Class ConcurrencyUtil
java.lang.Object
org.eclipse.persistence.internal.helper.ConcurrencyUtil
-
Field Summary
Modifier and TypeFieldDescriptionstatic final int
static final int
static final long
static final long
static final boolean
static final boolean
static final ConcurrencyUtil
-
Method Summary
Modifier and TypeMethodDescriptioncloneDeferredLockManager
(DeferredLockManager deferredLockManagerOriginal) Clone an originalDeferredLockManager
so that our algorithms of state dump or dead lock search can safely work ina stable model state that is not constantly changing.cloneDeferredLockManagerMap
(Map<Thread, DeferredLockManager> deferredLockManagersOriginal) The exact same thing as thecloneReadLockManagerMap(Map)
but the map we are cloning here is the one of threads to deferred lockscloneMapThreadToMethodName
(Map<Thread, String> mapThreadToWaitOnAcquireOriginal) Clone the map of the method names that tells us justification where threads acquire locks.cloneMapThreadToObjectIdWithWriteLockManagerChanges
(Map<Thread, Set<Object>> mapThreadToObjectIdWithWriteLockManagerChangesOriginal) Clone the information about threads that are in the write lock manager trying to commit and the object ids they are holding with some arbitrary changes.static Map
<Thread, ConcurrencyManager> cloneMapThreadToWaitOnAcquire
(Map<Thread, ConcurrencyManager> mapThreadToWaitOnAcquireOriginal) Clone the static map of the concurrency manager that tells us about threads waiting to acquire locks.static Map
<Thread, Set<ConcurrencyManager>> cloneMapThreadToWaitOnAcquireInsideWriteLockManagerOriginal
(Map<Thread, Set<ConcurrencyManager>> mapThreadToWaitOnAcquireInsideWriteLockManagerOriginal) Clone the static map of the concurrency manager that tells us about threads waiting to acquire locks.cloneReadLockManagerMap
(Map<Thread, ReadLockManager> readLockManagersOriginal) To facilitate algorithms that want to dump a snapshot of the current state of the concurrency manager or to start a hunt for dead locks this api faciliates the boostraping logic of such algorithms by giving the algorithm a stable clone of the map of read locks that we know will not change throughout the time the algorithm is running.cloneSetThreadsThatAreCurrentlyWaitingToReleaseDeferredLocks
(Set<Thread> setThreadWaitingToReleaseDeferredLocksOriginal) A set of threads that are at the end of object building and are waiting for the deferred locks to be resolved.createConcurrencyManagerState
(Map<Thread, DeferredLockManager> deferredLockManagers, Map<Thread, ReadLockManager> readLockManagersOriginal, Map<Thread, ConcurrencyManager> mapThreadToWaitOnAcquireOriginal, Map<Thread, String> mapThreadToWaitOnAcquireMethodNameOriginal, Map<Thread, Set<ConcurrencyManager>> mapThreadToWaitOnAcquireInsideWriteLockManagerOriginal, Map<Thread, ConcurrencyManager> mapThreadToWaitOnAcquireReadLockOriginal, Map<Thread, String> mapThreadToWaitOnAcquireReadLockMethodNameOriginal, Set<Thread> setThreadWaitingToReleaseDeferredLocksOriginal, Map<Thread, String> mapThreadsThatAreCurrentlyWaitingToReleaseDeferredLocksJustificationClone, Map<Thread, Set<Object>> mapThreadToObjectIdWithWriteLockManagerChangesOriginal) create a DTO that tries to represent the current snapshot of the concurrency manager and write lock manager cache stateprotected String
createInformationAboutAllResourcesAcquiredAndDeferredByAllThreads
(ConcurrencyManagerState concurrencyManagerState) Log information about all threads tracked in the concurrency manager.protected String
createInformationAboutAllResourcesAcquiredAndDeferredByThread
(ReadLockManager readLockManager, DeferredLockManager lockManager, Set<ConcurrencyManager> waitingOnAcquireCacheKeys, ConcurrencyManager waitingOnAcquireReadCacheKey, boolean threadWaitingToReleaseDeferredLocks, Thread thread, int currentThreadNumber, int totalNumberOfThreads, Set<Object> writeManagerThreadPrimaryKeysWithChangesToBeMerged, String waitingToReleaseDeferredLocksJustification) Build a string that tries to describe in as much detail as possible the resources associated to the current thread.protected String
createInformationAboutAllThreadsWaitingToAcquireReadCacheKeys
(Map<Thread, ConcurrencyManager> mapThreadToWaitOnAcquireReadLockClone, Map<Thread, String> mapThreadToWaitOnAcquireReadLockMethodNameClone) In this page of log dumping information we want to give a summary to the user of threads that appear to be stuck doing an acquire of the cache key.protected String
createInformationAboutAllThreadsWaitingToReleaseDeferredLocks
(Set<Thread> setThreadWaitingToReleaseDeferredLocksClone) Log information about threads not moving forward because they are waiting for theisBuildObjectOnThreadComplete
to return true.createReadLockAcquisitionMetadata
(ConcurrencyManager concurrencyManager) The concurrency managers about to acquire a cache key.createToStringExplainingOwnedCacheKey
(ConcurrencyManager concurrencyManager) protected String
currentThreadIsStuckForSomeTimeProduceTinyLogMessage
(long elapsedTime, ConcurrencyManager concurrencyManager, DeferredLockManager lockManager, ReadLockManager readLockManager) We have a thread that is not evolving for quite some while.void
determineIfReleaseDeferredLockAppearsToBeDeadLocked
(ConcurrencyManager concurrencyManager, long whileStartTimeMillis, DeferredLockManager lockManager, ReadLockManager readLockManager, boolean callerIsWillingToAllowInterruptedExceptionToBeFiredUpIfNecessary) Throw an interrupted exception if appears that eclipse link code is taking too long to release a deferred lock.void
Invoke thedumpConcurrencyManagerInformationStep01(Map, Map, Map, Map, Map, Map, Map, Set, Map, Map)
if sufficient time has passed.protected void
dumpConcurrencyManagerInformationStep01
(Map<Thread, DeferredLockManager> deferredLockManagers, Map<Thread, ReadLockManager> readLockManagersOriginal, Map<Thread, ConcurrencyManager> mapThreadToWaitOnAcquireOriginal, Map<Thread, String> mapThreadToWaitOnAcquireMethodNameOriginal, Map<Thread, Set<ConcurrencyManager>> mapThreadToWaitOnAcquireInsideWriteLockManagerOriginal, Map<Thread, ConcurrencyManager> mapThreadToWaitOnAcquireReadLockOriginal, Map<Thread, String> mapThreadToWaitOnAcquireReadLockMethodNameOriginal, Set<Thread> setThreadWaitingToReleaseDeferredLocksOriginal, Map<Thread, String> mapThreadsThatAreCurrentlyWaitingToReleaseDeferredLocksJustificationClone, Map<Thread, Set<Object>> mapThreadToObjectIdWithWriteLockManagerChangesOriginal) The current working thread is having problems.protected void
dumpConcurrencyManagerInformationStep02
(ConcurrencyManagerState concurrencyManagerState) Dump the server log all of the information that we managed to aggregate about the current state of the concurrency manager.protected String
dumpDeadLockExplanationIfPossible
(ConcurrencyManagerState concurrencyManagerState) This helper API is created due to the problem of the corruption of the eclipselink cache.void
enrichMapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKeyInfoAboutActiveAndDeferredLocks
(Map<ConcurrencyManager, CacheKeyToThreadRelationships> mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey, Map<Thread, DeferredLockManager> deferredLockManagerMapClone) Enrich our map map of cache key to threads having a relationship with that object in regards to active locks on the cache key and deferred locks on the cache keyvoid
enrichMapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKeyInfoAboutReadLocks
(Map<ConcurrencyManager, CacheKeyToThreadRelationships> mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey, Map<Thread, ReadLockManager> readLockManagerMapClone) Enrich the mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey based on the read locksvoid
enrichMapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKeyInfoThreadsStuckOnAcquire
(Map<ConcurrencyManager, CacheKeyToThreadRelationships> mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey, Map<Thread, Set<ConcurrencyManager>> unifiedMapOfThreadsStuckTryingToAcquireWriteLock) Enrich the mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey by setting on the cache keys the threads that are stuck trying to acquire the cache key.void
enrichMapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKeyInfoThreadsStuckOnAcquireLockForReading
(Map<ConcurrencyManager, CacheKeyToThreadRelationships> mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey, Map<Thread, ConcurrencyManager> mapThreadToWaitOnAcquireReadLockClone) Enrich the mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey by setting on the cache keys the threads that are stuck trying to acquire the cache key with a read lock.static void
enrichMapThreadToWaitOnAcquireInsideWriteLockManagerClone
(Map<Thread, Set<ConcurrencyManager>> mapThreadToWaitOnAcquireInsideWriteLockManagerClone, Map<Thread, ConcurrencyManager> mapThreadToWaitOnAcquireClone) We have two maps we are using to trace threads that are stuck acquiring locks.protected CacheKeyToThreadRelationships
get
(ConcurrencyManager cacheKey, Map<ConcurrencyManager, CacheKeyToThreadRelationships> mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey) Helper method to make sure we never get null dto from the mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey.long
long
long
long
long
If the system is perceived to be frozen and not evolving any longer, we will allow that every so often (e.g.long
Just like we have a massive dump log message seegetMaxAllowedFrequencyToProduceMassiveDumpLogMessage()
we also want threads to produce "tiny" dump about the fact that they rae stuck.long
int
int
boolean
boolean
boolean
boolean
boolean
readLockManagerProblem01CreateLogErrorMessageToIndicateThatCurrentThreadHasNullReadLockManagerWhileDecrementingNumberOfReaders
(int currentNumberOfReaders, int decrementedNumberOfReaders, ConcurrencyManager cacheKey) If when we are decrement the counter of number of readers on a cache key we find ourselves lacking the read lock manager at the time of the decrement we want to log a big fat error on the server log protecting that the current thread is misbehaving.readLockManagerProblem02ReadLockManageHasNoEntriesForThread
(ConcurrencyManager cacheKey, long threadId) readLockManagerProblem03ReadLockManageHasNoEntriesForThread
(ConcurrencyManager cacheKey, long threadId) void
setAcquireWaitTime
(long acquireWaitTime) void
setAllowConcurrencyExceptionToBeFiredUp
(boolean allowConcurrencyExceptionToBeFiredUp) void
setAllowInterruptedExceptionFired
(boolean allowInterruptedExceptionFired) void
setAllowTakingStackTraceDuringReadLockAcquisition
(boolean allowTakingStackTraceDuringReadLockAcquisition) void
setBuildObjectCompleteWaitTime
(long buildObjectCompleteWaitTime) void
setConcurrencySemaphoreLogTimeout
(long concurrencySemaphoreLogTimeout) void
setConcurrencySemaphoreMaxTimePermit
(long concurrencySemaphoreMaxTimePermit) void
setMaxAllowedFrequencyToProduceMassiveDumpLogMessage
(long maxAllowedFrequencyToProduceMassiveDumpLogMessage) void
setMaxAllowedFrequencyToProduceTinyDumpLogMessage
(long maxAllowedFrequencyToProduceTinyDumpLogMessage) void
setMaxAllowedSleepTime
(long maxAllowedSleepTime) void
setNoOfThreadsAllowedToDoWriteLockManagerAcquireRequiredLocksInParallel
(int noOfThreadsAllowedToDoWriteLockManagerAcquireRequiredLocksInParallel) void
setNoOfThreadsAllowedToObjectBuildInParallel
(int noOfThreadsAllowedToObjectBuildInParallel) void
setUseSemaphoreInObjectBuilder
(boolean useSemaphoreInObjectBuilder) void
setUseSemaphoreToLimitConcurrencyOnWriteLockManagerAcquireRequiredLocks
(boolean useSemaphoreToLimitConcurrencyOnWriteLockManagerAcquireRequiredLocks) boolean
tooMuchTimeHasElapsed
(long whileStartTimeMillis, long maxAllowedSleepTimeMs)
-
Field Details
-
SINGLETON
-
DEFAULT_USE_SEMAPHORE_TO_SLOW_DOWN_OBJECT_BUILDING_CONCURRENCY
public static final boolean DEFAULT_USE_SEMAPHORE_TO_SLOW_DOWN_OBJECT_BUILDING_CONCURRENCY- See Also:
-
DEFAULT_USE_SEMAPHORE_TO_SLOW_DOWN_WRITE_LOCK_MANAGER_ACQUIRE_REQUIRED_LOCKS
public static final boolean DEFAULT_USE_SEMAPHORE_TO_SLOW_DOWN_WRITE_LOCK_MANAGER_ACQUIRE_REQUIRED_LOCKS- See Also:
-
DEFAULT_CONCURRENCY_MANAGER_OBJECT_BUILDING_NO_THREADS
public static final int DEFAULT_CONCURRENCY_MANAGER_OBJECT_BUILDING_NO_THREADS- See Also:
-
DEFAULT_CONCURRENCY_MANAGER_WRITE_LOCK_MANAGER_ACQUIRE_REQUIRED_LOCKS_NO_THREADS
public static final int DEFAULT_CONCURRENCY_MANAGER_WRITE_LOCK_MANAGER_ACQUIRE_REQUIRED_LOCKS_NO_THREADS- See Also:
-
DEFAULT_CONCURRENCY_SEMAPHORE_MAX_TIME_PERMIT
public static final long DEFAULT_CONCURRENCY_SEMAPHORE_MAX_TIME_PERMIT- See Also:
-
DEFAULT_CONCURRENCY_SEMAPHORE_LOG_TIMEOUT
public static final long DEFAULT_CONCURRENCY_SEMAPHORE_LOG_TIMEOUT- See Also:
-
-
Method Details
-
determineIfReleaseDeferredLockAppearsToBeDeadLocked
public void determineIfReleaseDeferredLockAppearsToBeDeadLocked(ConcurrencyManager concurrencyManager, long whileStartTimeMillis, DeferredLockManager lockManager, ReadLockManager readLockManager, boolean callerIsWillingToAllowInterruptedExceptionToBeFiredUpIfNecessary) throws InterruptedException Throw an interrupted exception if appears that eclipse link code is taking too long to release a deferred lock.- Parameters:
whileStartTimeMillis
- the start date of the while tru loop for releasing a deferred lockcallerIsWillingToAllowInterruptedExceptionToBeFiredUpIfNecessary
- this flag is to allow the write lock manager to say that it is afraid of a concurrency exception being fire up because the thread in a dead lock might be trying to do a commit and blowing these threads up is most likely too dangerous and possibly the eclipselink code is not robust enough to code with such scenarios We do not care so much about blowing up exception during object building but during committing of transactions we are very afraid- Throws:
InterruptedException
- we fire an interrupted exception to ensure that the code blows up and releases all of the locks it had.
-
getAcquireWaitTime
public long getAcquireWaitTime()- Returns:
- "eclipselink.concurrency.manager.waittime" persistence property value.
-
setAcquireWaitTime
public void setAcquireWaitTime(long acquireWaitTime) -
getBuildObjectCompleteWaitTime
public long getBuildObjectCompleteWaitTime()- Returns:
- "eclipselink.concurrency.manager.build.object.complete.waittime" persistence property value.
-
setBuildObjectCompleteWaitTime
public void setBuildObjectCompleteWaitTime(long buildObjectCompleteWaitTime) -
getMaxAllowedSleepTime
public long getMaxAllowedSleepTime()- Returns:
- property to control how long we are willing to wait before firing up an exception
-
setMaxAllowedSleepTime
public void setMaxAllowedSleepTime(long maxAllowedSleepTime) -
getMaxAllowedFrequencyToProduceTinyDumpLogMessage
public long getMaxAllowedFrequencyToProduceTinyDumpLogMessage()Just like we have a massive dump log message seegetMaxAllowedFrequencyToProduceMassiveDumpLogMessage()
we also want threads to produce "tiny" dump about the fact that they rae stuck. We want to avoid these threads spaming too much the server log ... once the log message is out there not much point in continuously pumping the same log message out over and over again. Controlling how frequently the tiny dump is important especially when the user configures the hacked eclipselink to not fire up a blow up exception and instead to allow eclipselink to remain frozen forever.- Returns:
- the frequency with which we are allowed to create a tiny dump log message
-
setMaxAllowedFrequencyToProduceTinyDumpLogMessage
public void setMaxAllowedFrequencyToProduceTinyDumpLogMessage(long maxAllowedFrequencyToProduceTinyDumpLogMessage) -
getMaxAllowedFrequencyToProduceMassiveDumpLogMessage
public long getMaxAllowedFrequencyToProduceMassiveDumpLogMessage()If the system is perceived to be frozen and not evolving any longer, we will allow that every so often (e.g. once a minute) the logic complaining that the thread is stuck and going nowhere logs a very big dump message where the FULL concurrency manager state is explained. So that we can (manually) try to understand the dead lock based on the dumped information See alsodateWhenLastConcurrencyManagerStateFullDumpWasPerformed
. -
setMaxAllowedFrequencyToProduceMassiveDumpLogMessage
public void setMaxAllowedFrequencyToProduceMassiveDumpLogMessage(long maxAllowedFrequencyToProduceMassiveDumpLogMessage) -
isAllowInterruptedExceptionFired
public boolean isAllowInterruptedExceptionFired() -
setAllowInterruptedExceptionFired
public void setAllowInterruptedExceptionFired(boolean allowInterruptedExceptionFired) -
isAllowConcurrencyExceptionToBeFiredUp
public boolean isAllowConcurrencyExceptionToBeFiredUp()- Returns:
- true if we are supposed to be firing up exception to abort the thread in a dead lock, false we are afraid of trying to abort the transaction and not managing to resolve the dead lock and prefer to system frozen and be forced into restarting it.
-
setAllowConcurrencyExceptionToBeFiredUp
public void setAllowConcurrencyExceptionToBeFiredUp(boolean allowConcurrencyExceptionToBeFiredUp) -
isAllowTakingStackTraceDuringReadLockAcquisition
public boolean isAllowTakingStackTraceDuringReadLockAcquisition() -
setAllowTakingStackTraceDuringReadLockAcquisition
public void setAllowTakingStackTraceDuringReadLockAcquisition(boolean allowTakingStackTraceDuringReadLockAcquisition) -
isUseSemaphoreInObjectBuilder
public boolean isUseSemaphoreInObjectBuilder() -
setUseSemaphoreInObjectBuilder
public void setUseSemaphoreInObjectBuilder(boolean useSemaphoreInObjectBuilder) -
isUseSemaphoreToLimitConcurrencyOnWriteLockManagerAcquireRequiredLocks
public boolean isUseSemaphoreToLimitConcurrencyOnWriteLockManagerAcquireRequiredLocks() -
setUseSemaphoreToLimitConcurrencyOnWriteLockManagerAcquireRequiredLocks
public void setUseSemaphoreToLimitConcurrencyOnWriteLockManagerAcquireRequiredLocks(boolean useSemaphoreToLimitConcurrencyOnWriteLockManagerAcquireRequiredLocks) -
getNoOfThreadsAllowedToObjectBuildInParallel
public int getNoOfThreadsAllowedToObjectBuildInParallel() -
setNoOfThreadsAllowedToObjectBuildInParallel
public void setNoOfThreadsAllowedToObjectBuildInParallel(int noOfThreadsAllowedToObjectBuildInParallel) -
getNoOfThreadsAllowedToDoWriteLockManagerAcquireRequiredLocksInParallel
public int getNoOfThreadsAllowedToDoWriteLockManagerAcquireRequiredLocksInParallel() -
setNoOfThreadsAllowedToDoWriteLockManagerAcquireRequiredLocksInParallel
public void setNoOfThreadsAllowedToDoWriteLockManagerAcquireRequiredLocksInParallel(int noOfThreadsAllowedToDoWriteLockManagerAcquireRequiredLocksInParallel) -
getConcurrencySemaphoreMaxTimePermit
public long getConcurrencySemaphoreMaxTimePermit() -
setConcurrencySemaphoreMaxTimePermit
public void setConcurrencySemaphoreMaxTimePermit(long concurrencySemaphoreMaxTimePermit) -
getConcurrencySemaphoreLogTimeout
public long getConcurrencySemaphoreLogTimeout() -
setConcurrencySemaphoreLogTimeout
public void setConcurrencySemaphoreLogTimeout(long concurrencySemaphoreLogTimeout) -
createToStringExplainingOwnedCacheKey
- Returns:
- A to string of the cache key (e.g. that we are trying to lock
-
currentThreadIsStuckForSomeTimeProduceTinyLogMessage
protected String currentThreadIsStuckForSomeTimeProduceTinyLogMessage(long elapsedTime, ConcurrencyManager concurrencyManager, DeferredLockManager lockManager, ReadLockManager readLockManager) We have a thread that is not evolving for quite some while. This is a fairy good indication of eclipselink being stuck in a dead lock. So we log some information about the thread that is stuck.- Parameters:
elapsedTime
- how many ms have passed since the thread stopped movingconcurrencyManager
- the current cache key that the thread is trying to acquire or the object where the thread is waiting for the release deferred locks .lockManager
- the lock managerreadLockManager
- the read lock manager- Returns:
- Return the string with the tiny message we logged on the server log. This message can be interesting if we decide to fire up an interrupted exception
-
tooMuchTimeHasElapsed
public boolean tooMuchTimeHasElapsed(long whileStartTimeMillis, long maxAllowedSleepTimeMs) -
dumpConcurrencyManagerInformationIfAppropriate
public void dumpConcurrencyManagerInformationIfAppropriate()Invoke thedumpConcurrencyManagerInformationStep01(Map, Map, Map, Map, Map, Map, Map, Set, Map, Map)
if sufficient time has passed. This log message will potentially create a massive dump in the server log file. So we need to check when was the last time that the masive dump was produced and decide if we can log again the state of the concurrency manager. The access to dateWhenLastConcurrencyManagerStateFullDumpWasPerformedLock is synchronized, because we do not want two threads in parallel to star deciding to dump the complete state of the concurrency manager at the same time. Only one thread should succeed in producing the massive dump in a given time window. -
dumpConcurrencyManagerInformationStep01
protected void dumpConcurrencyManagerInformationStep01(Map<Thread, DeferredLockManager> deferredLockManagers, Map<Thread, ReadLockManager> readLockManagersOriginal, Map<Thread, ConcurrencyManager> mapThreadToWaitOnAcquireOriginal, Map<Thread, String> mapThreadToWaitOnAcquireMethodNameOriginal, Map<Thread, Set<ConcurrencyManager>> mapThreadToWaitOnAcquireInsideWriteLockManagerOriginal, Map<Thread, ConcurrencyManager> mapThreadToWaitOnAcquireReadLockOriginal, Map<Thread, String> mapThreadToWaitOnAcquireReadLockMethodNameOriginal, Set<Thread> setThreadWaitingToReleaseDeferredLocksOriginal, Map<Thread, String> mapThreadsThatAreCurrentlyWaitingToReleaseDeferredLocksJustificationClone, Map<Thread, Set<Object>> mapThreadToObjectIdWithWriteLockManagerChangesOriginal) The current working thread is having problems. It seems to not go forward being stuck either trying to acquire a cache key for writing, as a deferred cache key or it is at the end of the process and it is waiting for some other thread to finish building some objects it needed to defer. Now that the system is frozen we want to start spamming into the server log file the state of the concurrency manager since this might help us understand the situation of the system.- Parameters:
deferredLockManagers
- static map coming from the concurrency manager telling us all the threds and their defferred locks and active locksreadLockManagersOriginal
- static map coming from the concurrency manager telling us all the threads and their read locksmapThreadToWaitOnAcquireOriginal
- static map of threads that have registered themselves as waiting for some cache keymapThreadToWaitOnAcquireInsideWriteLockManagerOriginal
- this map relates to the fact that the write lock manager during transaction commits is very illusive. The write lock manger is not allowing itself to get stuck on acquiring any cache key. It uses waits with timings and therefore the locks needed to write and that cannot be obtained are not appearing inside our tracebility maps of the concurrency manager. We needed add theWriteLockManager.THREAD_TO_FAIL_TO_ACQUIRE_CACHE_KEYS
but semantically this map is 100 percent the same thing as the mapThreadToWaitOnAcquireOriginal. It still represents a thread wanting to grab a write lock and not managing to get it. Being stuck in that step. Wo we will want to fuse together the (mapThreadToWaitOnAcquireOriginal and the mapThreadToWaitOnAcquireInsideWriteLockManagerOriginal) to make our lives much easier.setThreadWaitingToReleaseDeferredLocksOriginal
- static map of threads that have stopped going deeped in the recursion of object building and are waiting for the confirmation that some of the objects they needed to build are finished building.mapThreadToObjectIdWithWriteLockManagerChangesOriginal
- The write lock manager has been tweaked to store information about objects ids that the current thread has in its hands and that will required for write locks to be acquired by a committing thread. This information is especially interesting if any thread participating in a dead lock is getting stuck in the acquisition of write locks as part of the commit process. This information might end up revealing a thread that has done too many changes and is creating a bigger risk fo dead lock. The more resources an individual thread tries to grab the worse it is for the concurrency layer. The size of the change set can be interesting.
-
dumpConcurrencyManagerInformationStep02
protected void dumpConcurrencyManagerInformationStep02(ConcurrencyManagerState concurrencyManagerState) Dump the server log all of the information that we managed to aggregate about the current state of the concurrency manager.- Parameters:
concurrencyManagerState
- a snapshot of the current state of the concurrency manager and threads accessing locks.
-
dumpDeadLockExplanationIfPossible
-
createConcurrencyManagerState
public ConcurrencyManagerState createConcurrencyManagerState(Map<Thread, DeferredLockManager> deferredLockManagers, Map<Thread, ReadLockManager> readLockManagersOriginal, Map<Thread, ConcurrencyManager> mapThreadToWaitOnAcquireOriginal, Map<Thread, String> mapThreadToWaitOnAcquireMethodNameOriginal, Map<Thread, Set<ConcurrencyManager>> mapThreadToWaitOnAcquireInsideWriteLockManagerOriginal, Map<Thread, ConcurrencyManager> mapThreadToWaitOnAcquireReadLockOriginal, Map<Thread, String> mapThreadToWaitOnAcquireReadLockMethodNameOriginal, Set<Thread> setThreadWaitingToReleaseDeferredLocksOriginal, Map<Thread, String> mapThreadsThatAreCurrentlyWaitingToReleaseDeferredLocksJustificationClone, Map<Thread, Set<Object>> mapThreadToObjectIdWithWriteLockManagerChangesOriginal) create a DTO that tries to represent the current snapshot of the concurrency manager and write lock manager cache state -
enrichGenerateThreadDumpForCurrentThread
This helper API is created due to the problem of the corruption of the eclipselink cache. The idea is to have a tool that allows us to know specifically where the current thread was located when it acquired a READ LOCK.Cache corruption problem:
namely the fact that when dead locks are seen to be taking place some of the threads that seem to be primary culprits of the dead lock are actually idle doing nothing but they have have left the number of readers of the cache corrupted (e.g. typically forever incremnted).- Returns:
- get the stack trace of the current thread.
-
createInformationAboutAllThreadsWaitingToAcquireReadCacheKeys
protected String createInformationAboutAllThreadsWaitingToAcquireReadCacheKeys(Map<Thread, ConcurrencyManager> mapThreadToWaitOnAcquireReadLockClone, Map<Thread, String> mapThreadToWaitOnAcquireReadLockMethodNameClone) In this page of log dumping information we want to give a summary to the user of threads that appear to be stuck doing an acquire of the cache key.- Parameters:
mapThreadToWaitOnAcquireReadLockClone
- this a cloned map that has an association between thread and cache keys the thread would like to acquire for READING but cannot because there is some active thread (other than themselves) holding the cache key (e.g. for writing)
-
createInformationAboutAllThreadsWaitingToReleaseDeferredLocks
protected String createInformationAboutAllThreadsWaitingToReleaseDeferredLocks(Set<Thread> setThreadWaitingToReleaseDeferredLocksClone) Log information about threads not moving forward because they are waiting for theisBuildObjectOnThreadComplete
to return true.- Parameters:
setThreadWaitingToReleaseDeferredLocksClone
- threads waiting for the release deferred lock process to complete.
-
createInformationAboutAllResourcesAcquiredAndDeferredByAllThreads
protected String createInformationAboutAllResourcesAcquiredAndDeferredByAllThreads(ConcurrencyManagerState concurrencyManagerState) Log information about all threads tracked in the concurrency manager.- Parameters:
concurrencyManagerState
- and object that represents a snapshot of the current state of the concurrency manager.
-
createInformationAboutAllResourcesAcquiredAndDeferredByThread
protected String createInformationAboutAllResourcesAcquiredAndDeferredByThread(ReadLockManager readLockManager, DeferredLockManager lockManager, Set<ConcurrencyManager> waitingOnAcquireCacheKeys, ConcurrencyManager waitingOnAcquireReadCacheKey, boolean threadWaitingToReleaseDeferredLocks, Thread thread, int currentThreadNumber, int totalNumberOfThreads, Set<Object> writeManagerThreadPrimaryKeysWithChangesToBeMerged, String waitingToReleaseDeferredLocksJustification) Build a string that tries to describe in as much detail as possible the resources associated to the current thread.- Parameters:
readLockManager
- the read lock manager for the current threadlockManager
- the lock manager for the current threadwaitingOnAcquireCacheKeys
- null if the current thread is not waiting to acquire a cache key otherwise the cachekey that the current thread wants to acquire and that is making it block. This field evolved to be a set and not just one cache key because when we needed to tweak the write lock manager code to report about why the write lock manager is stuck we need it to create the mapWriteLockManager.THREAD_TO_FAIL_TO_ACQUIRE_CACHE_KEYS
whereby during a commit where entiteis are merged into the shared cache a thread might be trying to grab several write locks. so here we have a mix between the concurrency manager cache key a thread currently wants together with cache keys the write lock managed is not managing to grab.waitingOnAcquireReadCacheKey
- cache key the thread is failing to acquire in theConcurrencyManager.acquireReadLock()
threadWaitingToReleaseDeferredLocks
- true if the curren thread is now blocked waiting to confirm the locks it deferred have finished building the corresponding objects.thread
- the thread eing describedcurrentThreadNumber
- just loop incremented index to help the dump log messages give the feeling of the current thread being described and how many more threads are still to be describedtotalNumberOfThreads
- the total number of threads being described in a for loopwriteManagerThreadPrimaryKeysWithChangesToBeMerged
- Null for all threads excep those that are currently about to commit and merge changes to the shared cache. In this case it holds the primary keys of the objects that were changed by the transaction. The write lock manager has been tweaked to store information about objects ids that the current thread has in its hands and that will required for write locks to be acquired by a committing thread. This information is especially interesting if any thread participating in a dead lock is getting stuck in the acquisition of write locks as part of the commit process. This information might end up revealing a thread that has done too many changes and is creating a bigger risk fo dead lock. The more resources an individual thread tries to grab the worse it is for the concurrency layer. The size of the change set can be interesting.waitingToReleaseDeferredLocksJustification
- when a thread is stuck for more than 500 ms in the release defferred locks algorithm, the concurrency manager starts try to justify why the method isBuildObjectComplete keeps returning false. This information is important whenever the param thread waiting to release deferred locks is true- Returns:
- a string describing the thread provided. We can see the active locks, deferred locks, read locks etc... as well sa if the thread is waiting to acquire a specific cache key or waiting for build object to complete.
-
cloneMapThreadToWaitOnAcquire
public static Map<Thread,ConcurrencyManager> cloneMapThreadToWaitOnAcquire(Map<Thread, ConcurrencyManager> mapThreadToWaitOnAcquireOriginal) Clone the static map of the concurrency manager that tells us about threads waiting to acquire locks.- Parameters:
mapThreadToWaitOnAcquireOriginal
- the original map we want to clone- Returns:
- a cloned map
-
cloneMapThreadToMethodName
public static Map<Thread,String> cloneMapThreadToMethodName(Map<Thread, String> mapThreadToWaitOnAcquireOriginal) Clone the map of the method names that tells us justification where threads acquire locks.- Parameters:
mapThreadToWaitOnAcquireOriginal
- the original map we want to clone- Returns:
- a cloned map
-
cloneMapThreadToWaitOnAcquireInsideWriteLockManagerOriginal
public static Map<Thread,Set<ConcurrencyManager>> cloneMapThreadToWaitOnAcquireInsideWriteLockManagerOriginal(Map<Thread, Set<ConcurrencyManager>> mapThreadToWaitOnAcquireInsideWriteLockManagerOriginal) Clone the static map of the concurrency manager that tells us about threads waiting to acquire locks.- Parameters:
mapThreadToWaitOnAcquireInsideWriteLockManagerOriginal
- the original map we want to clone- Returns:
- a cloned map
-
enrichMapThreadToWaitOnAcquireInsideWriteLockManagerClone
public static void enrichMapThreadToWaitOnAcquireInsideWriteLockManagerClone(Map<Thread, Set<ConcurrencyManager>> mapThreadToWaitOnAcquireInsideWriteLockManagerClone, Map<Thread, ConcurrencyManager> mapThreadToWaitOnAcquireClone) We have two maps we are using to trace threads that are stuck acquiring locks. One map is found in the concurrency manager the other in the write lock manager. When we start dumping information we only care about working with one and only one map. Therefore we merge the two maps together since semantically they both mean the exact same thing: a thread A wants a cachekey B for writing and is not getting it.- Parameters:
mapThreadToWaitOnAcquireInsideWriteLockManagerClone
- this is the map we want o enrichmapThreadToWaitOnAcquireClone
- this is the map whose entries we want to copy into the map to enrich
-
cloneSetThreadsThatAreCurrentlyWaitingToReleaseDeferredLocks
public static Set<Thread> cloneSetThreadsThatAreCurrentlyWaitingToReleaseDeferredLocks(Set<Thread> setThreadWaitingToReleaseDeferredLocksOriginal) A set of threads that are at the end of object building and are waiting for the deferred locks to be resolved.- Parameters:
setThreadWaitingToReleaseDeferredLocksOriginal
- the original set of threads that are waiting for deferred locks to be resolved.- Returns:
- A cloned has set of threads waiting for their deferred locks to be resolved.
-
cloneMapThreadToObjectIdWithWriteLockManagerChanges
public static Map<Thread,Set<Object>> cloneMapThreadToObjectIdWithWriteLockManagerChanges(Map<Thread, Set<Object>> mapThreadToObjectIdWithWriteLockManagerChangesOriginal) Clone the information about threads that are in the write lock manager trying to commit and the object ids they are holding with some arbitrary changes.- Parameters:
mapThreadToObjectIdWithWriteLockManagerChangesOriginal
- map of thread to the primary keys of of objects changed by a transaction in the commit phase. This is the original map grabbed from the WriteLockManager.- Returns:
- a cloned map of thread to object id primary keys that a thread committing might have changed.
-
cloneReadLockManagerMap
public Map<Thread,ReadLockManager> cloneReadLockManagerMap(Map<Thread, ReadLockManager> readLockManagersOriginal) To facilitate algorithms that want to dump a snapshot of the current state of the concurrency manager or to start a hunt for dead locks this api faciliates the boostraping logic of such algorithms by giving the algorithm a stable clone of the map of read locks that we know will not change throughout the time the algorithm is running.- Parameters:
readLockManagersOriginal
- This the original map of read locks referred by the concurrency manager. This is a very bad platform to work with because if for whatever reason not all threads are frozen and some are actualy managing to complete their transactions the contents of this map are systematically changing with threds being added in and removed.- Returns:
- A clone of the readLockManagersOriginal. Essentially the map instance returned is new and independent and
the values
ReadLockManager
are also clones and independent. The only thing that is not cloned here - whose state could be changing - are the cache key themselves. The cache keys pointed by the vectorReadLockManager.getReadLocks()
are the original values. So our clone from the read lock manager is not a perfectly stable clone. It will not be blowing up telling us concurrent access modification when we loop through the vector. But no one can guarnate the number of readers on the cache key stays the same nor that the active thread on a cache key stays the same... Those values can definitely be fluctuating (not ideal ... but it would be quite hard to get better than this).
-
cloneDeferredLockManagerMap
public Map<Thread,DeferredLockManager> cloneDeferredLockManagerMap(Map<Thread, DeferredLockManager> deferredLockManagersOriginal) The exact same thing as thecloneReadLockManagerMap(Map)
but the map we are cloning here is the one of threads to deferred locks- Parameters:
deferredLockManagersOriginal
- the original map taken from the conrruency manager itself- Returns:
- A clone of that map that is a relatively stable data structure to work with since no new threads will
register in or out in the map nor will the DeferredLockManager values be changing. As for the read lock
manager we have no assurance as to what is happening with the cache keys themselves refered by the
DeferredLockManager
values, the cache keys are always changing their metadata as new threads come in to do work or finish doing work. So it is not a perfect snapshot of the state of the system, but it is as close as we can get.
-
cloneDeferredLockManager
public DeferredLockManager cloneDeferredLockManager(DeferredLockManager deferredLockManagerOriginal) Clone an originalDeferredLockManager
so that our algorithms of state dump or dead lock search can safely work ina stable model state that is not constantly changing.- Parameters:
deferredLockManagerOriginal
- an object that is originating from the map of thread to deferred locks from the concurrency manager class. We do not want to be carrying around the original object while try to make a dump/snapshot of the current state of the concurrency manager since these objects are always mutating. Locks are being acquired and released etc... All the tiem. The only objest thta will be stable are those of threads involved ina dead lock. And those are the threads that matter the most to us anyway.- Returns:
- a cloned deferred lock manager. The newly created deferred lock manager will have its vectors of cache keys holding references the same cache keys as the original object. The cache keys themselves are not cloned. That measn that the DeferredLockManager will be immuatable in terms of its vectors and held references. But the objects it refers to (e.g. cache keys) can be mutating all the time if new readers or active threads arrive.
-
enrichMapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKeyInfoThreadsStuckOnAcquire
public void enrichMapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKeyInfoThreadsStuckOnAcquire(Map<ConcurrencyManager, CacheKeyToThreadRelationships> mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey, Map<Thread, Set<ConcurrencyManager>> unifiedMapOfThreadsStuckTryingToAcquireWriteLock) Enrich the mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey by setting on the cache keys the threads that are stuck trying to acquire the cache key.- Parameters:
mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey
- the map we are trying to enirhc with additional informationunifiedMapOfThreadsStuckTryingToAcquireWriteLock
- a map telling us about threads that at a certain point in time were not progressing anywhere because they were waiting to acquire a write lock. These are threads either stuck on the concurrency manager or in the write lock manager during a transaction commmit
-
enrichMapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKeyInfoThreadsStuckOnAcquireLockForReading
public void enrichMapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKeyInfoThreadsStuckOnAcquireLockForReading(Map<ConcurrencyManager, CacheKeyToThreadRelationships> mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey, Map<Thread, ConcurrencyManager> mapThreadToWaitOnAcquireReadLockClone) Enrich the mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey by setting on the cache keys the threads that are stuck trying to acquire the cache key with a read lock. These are threads stuck on theConcurrencyManager.acquireReadLock()
- Parameters:
mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey
- the map we are trying to enirhc with additional informationmapThreadToWaitOnAcquireReadLockClone
- a map telling us about threads that at a certain point in time were not progressing anywhere because they were waiting to acquire a lock.
-
enrichMapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKeyInfoAboutReadLocks
public void enrichMapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKeyInfoAboutReadLocks(Map<ConcurrencyManager, CacheKeyToThreadRelationships> mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey, Map<Thread, ReadLockManager> readLockManagerMapClone) Enrich the mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey based on the read locks- Parameters:
mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey
- a map whose metadata we need to enrichreadLockManagerMapClone
- map cloned from the original map and that gives us a snapshot of threads that acquired read locks
-
enrichMapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKeyInfoAboutActiveAndDeferredLocks
public void enrichMapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKeyInfoAboutActiveAndDeferredLocks(Map<ConcurrencyManager, CacheKeyToThreadRelationships> mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey, Map<Thread, DeferredLockManager> deferredLockManagerMapClone) Enrich our map map of cache key to threads having a relationship with that object in regards to active locks on the cache key and deferred locks on the cache key- Parameters:
mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey
- the map we want to enrich with more informationdeferredLockManagerMapClone
- the cloned map with information about threads and their deferred locks.
-
get
protected CacheKeyToThreadRelationships get(ConcurrencyManager cacheKey, Map<ConcurrencyManager, CacheKeyToThreadRelationships> mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey) Helper method to make sure we never get null dto from the mapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey.- Parameters:
cacheKey
- the cache key we are search formapOfCacheKeyToDtosExplainingThreadExpectationsOnCacheKey
- the map of cache key to concurrency manager locking metadata- Returns:
- never returls null. If the cache key is not yet in the map a ney entry is returned.
-
readLockManagerProblem01CreateLogErrorMessageToIndicateThatCurrentThreadHasNullReadLockManagerWhileDecrementingNumberOfReaders
public String readLockManagerProblem01CreateLogErrorMessageToIndicateThatCurrentThreadHasNullReadLockManagerWhileDecrementingNumberOfReaders(int currentNumberOfReaders, int decrementedNumberOfReaders, ConcurrencyManager cacheKey) If when we are decrement the counter of number of readers on a cache key we find ourselves lacking the read lock manager at the time of the decrement we want to log a big fat error on the server log protecting that the current thread is misbehaving.- Parameters:
currentNumberOfReaders
- the current count of readers on the cache key about to be decrementeddecrementedNumberOfReaders
- the number of readers of the cache key if we subtract one readercacheKey
- the cache key that is about to suffer a decrement on the number of readers
-
readLockManagerProblem02ReadLockManageHasNoEntriesForThread
public String readLockManagerProblem02ReadLockManageHasNoEntriesForThread(ConcurrencyManager cacheKey, long threadId) -
readLockManagerProblem03ReadLockManageHasNoEntriesForThread
public String readLockManagerProblem03ReadLockManageHasNoEntriesForThread(ConcurrencyManager cacheKey, long threadId) -
createReadLockAcquisitionMetadata
public ReadLockAcquisitionMetadata createReadLockAcquisitionMetadata(ConcurrencyManager concurrencyManager) The concurrency managers about to acquire a cache key. And since we have been suffering from cache corruption on the acquire read locks we need to collect a lot more information about the time of acquisition of a read lock.- Parameters:
concurrencyManager
- the cache key we are about to increment and acquire for reading- Returns:
- object that have all the context information to allow us to know when and where exactly this key acquisition took place.
-