Class WriteLockManager
- java.lang.Object
-
- org.eclipse.persistence.internal.helper.WriteLockManager
-
public class WriteLockManager extends java.lang.ObjectINTERNAL:Purpose: Acquires all required locks for a particular merge process. Implements a deadlock avoidance algorithm to prevent concurrent merge conflicts.
Responsibilities:
- Acquires locks for writing threads.
- Provides deadlock avoidance behavior.
- Releases locks for writing threads.
- Since:
- 10.0.3
- Author:
- Gordon Yorke
-
-
Field Summary
Fields Modifier and Type Field Description static intMAX_WAITstatic intMAXTRIESprotected ExposedNodeLinkedListprevailingQueue
-
Constructor Summary
Constructors Constructor Description WriteLockManager()
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description CacheKeyacquireLockAndRelatedLocks(java.lang.Object objectForClone, java.util.Map lockedObjects, java.util.Map refreshedObjects, CacheKey cacheKey, ClassDescriptor descriptor, AbstractSession cloningSession)INTERNAL: This is a recursive method used to acquire read locks on all objects that will be cloned.java.util.MapacquireLocksForClone(java.lang.Object objectForClone, ClassDescriptor descriptor, CacheKey cacheKey, AbstractSession cloningSession)INTERNAL: This method will return once the object is locked and all non-indirect related objects are also locked.voidacquireRequiredLocks(MergeManager mergeManager, UnitOfWorkChangeSet changeSet)INTERNAL: This method will be the entry point for threads attempting to acquire locks for all objects that have a changeset.static voidaddCacheKeyToMapWriteLockManagerToCacheKeysThatCouldNotBeAcquired(java.lang.Thread thread, ConcurrencyManager cacheKeyThatCouldNotBeAcquired, long whileStartDate)The thread was doing its while loop to acquire all required locks to proceed with the commmit and it realized there was one cache key it is unable to acquireCacheKeyappendLock(java.lang.Object primaryKey, java.lang.Object objectToLock, ClassDescriptor descriptor, MergeManager mergeManager, AbstractSession session)INTERNAL: This method will be called by a merging thread that is attempting to lock a new object that was not locked previously.protected CacheKeyattemptToAcquireLock(ClassDescriptor descriptor, java.lang.Object primaryKey, AbstractSession session)INTERNAL: This method performs the operations of finding the cacheKey and locking it if possible.protected CacheKeycheckAndLockObject(java.lang.Object objectToLock, java.util.Map lockedObjects, java.util.Map refreshedObjects, DatabaseMapping mapping, AbstractSession cloningSession)INTERNAL: Simply check that the object is not already locked then pass it on to the locking methodstatic voidclearMapThreadToObjectIdsWithChagenSet(java.lang.Thread thread)Remove the current thread from the map of object ids with change sets that are about to bec ommitedstatic voidclearMapWriteLockManagerToCacheKeysThatCouldNotBeAcquired(java.lang.Thread thread)Before the problematic while loop starts we should always clear for this thread the set of cache keys it could not acquire.static java.util.Map<java.lang.Thread,java.util.Set<java.lang.Object>>getMapWriteLockManagerThreadToObjectIdsWithChangeSet()static java.util.Map<java.lang.Thread,java.util.Set<ConcurrencyManager>>getThreadToFailToAcquireCacheKeys()Getter forTHREAD_TO_FAIL_TO_ACQUIRE_CACHE_KEYSstatic voidpopulateMapThreadToObjectIdsWithChagenSet(java.lang.Thread thread, java.util.Collection<ObjectChangeSet> objectChangeSets)Before a thread starts long wait loop to acquire write locks during a commit transaction the thread will record in this map the object ids it holds with chance sets.voidreleaseAllAcquiredLocks(MergeManager mergeManager)INTERNAL: This method will release all acquired locksstatic voidremoveCacheKeyFromMapWriteLockManagerToCacheKeysThatCouldNotBeAcquired(java.lang.Thread thread, ConcurrencyManager cacheKeyThatCouldNotBeAcquired)A cache keys was successfully acquired we want to make sure it is not recorded in the map of cache keys that could not be acquired.voidtransitionToDeferredLocks(MergeManager mergeManager)INTERNAL: This method will transition the previously acquired active locks to deferred locks in the case a readlock could not be acquired for a related object.CacheKeytraverseRelatedLocks(java.lang.Object objectForClone, java.util.Map lockedObjects, java.util.Map refreshedObjects, ClassDescriptor descriptor, AbstractSession cloningSession)INTERNAL: Traverse the object and acquire locks on all related objects.protected CacheKeywaitOnObjectLock(ClassDescriptor descriptor, java.lang.Object primaryKey, AbstractSession session, int waitTime)INTERNAL: This method performs the operations of finding the cacheKey and locking it if possible.
-
-
-
Field Detail
-
MAXTRIES
public static int MAXTRIES
-
MAX_WAIT
public static int MAX_WAIT
-
prevailingQueue
protected ExposedNodeLinkedList prevailingQueue
-
-
Method Detail
-
acquireLocksForClone
public java.util.Map acquireLocksForClone(java.lang.Object objectForClone, ClassDescriptor descriptor, CacheKey cacheKey, AbstractSession cloningSession)INTERNAL: This method will return once the object is locked and all non-indirect related objects are also locked.
-
acquireLockAndRelatedLocks
public CacheKey acquireLockAndRelatedLocks(java.lang.Object objectForClone, java.util.Map lockedObjects, java.util.Map refreshedObjects, CacheKey cacheKey, ClassDescriptor descriptor, AbstractSession cloningSession)
INTERNAL: This is a recursive method used to acquire read locks on all objects that will be cloned. These include all related objects for which there is no indirection. The returned object is the first object that the lock could not be acquired for. The caller must try for exceptions and release locked objects in the case of an exception.
-
transitionToDeferredLocks
public void transitionToDeferredLocks(MergeManager mergeManager)
INTERNAL: This method will transition the previously acquired active locks to deferred locks in the case a readlock could not be acquired for a related object. Deferred locks must be employed to prevent deadlock when waiting for the readlock while still protecting readers from incomplete data.
-
traverseRelatedLocks
public CacheKey traverseRelatedLocks(java.lang.Object objectForClone, java.util.Map lockedObjects, java.util.Map refreshedObjects, ClassDescriptor descriptor, AbstractSession cloningSession)
INTERNAL: Traverse the object and acquire locks on all related objects.
-
acquireRequiredLocks
public void acquireRequiredLocks(MergeManager mergeManager, UnitOfWorkChangeSet changeSet)
INTERNAL: This method will be the entry point for threads attempting to acquire locks for all objects that have a changeset. This method will hand off the processing of the deadlock algorithm to other member methods. The mergeManager must be the active mergemanager for the calling thread. Returns true if all required locks were acquired This is wrapper method with semaphore logic.
-
appendLock
public CacheKey appendLock(java.lang.Object primaryKey, java.lang.Object objectToLock, ClassDescriptor descriptor, MergeManager mergeManager, AbstractSession session)
INTERNAL: This method will be called by a merging thread that is attempting to lock a new object that was not locked previously. Unlike the other methods within this class this method will lock only this object.
-
attemptToAcquireLock
protected CacheKey attemptToAcquireLock(ClassDescriptor descriptor, java.lang.Object primaryKey, AbstractSession session)
INTERNAL: This method performs the operations of finding the cacheKey and locking it if possible. Returns True if the lock was acquired, false otherwise
-
checkAndLockObject
protected CacheKey checkAndLockObject(java.lang.Object objectToLock, java.util.Map lockedObjects, java.util.Map refreshedObjects, DatabaseMapping mapping, AbstractSession cloningSession)
INTERNAL: Simply check that the object is not already locked then pass it on to the locking method
-
releaseAllAcquiredLocks
public void releaseAllAcquiredLocks(MergeManager mergeManager)
INTERNAL: This method will release all acquired locks
-
waitOnObjectLock
protected CacheKey waitOnObjectLock(ClassDescriptor descriptor, java.lang.Object primaryKey, AbstractSession session, int waitTime)
INTERNAL: This method performs the operations of finding the cacheKey and locking it if possible. Waits until the lock can be acquired
-
getThreadToFailToAcquireCacheKeys
public static java.util.Map<java.lang.Thread,java.util.Set<ConcurrencyManager>> getThreadToFailToAcquireCacheKeys()
Getter forTHREAD_TO_FAIL_TO_ACQUIRE_CACHE_KEYS
-
getMapWriteLockManagerThreadToObjectIdsWithChangeSet
public static java.util.Map<java.lang.Thread,java.util.Set<java.lang.Object>> getMapWriteLockManagerThreadToObjectIdsWithChangeSet()
-
clearMapThreadToObjectIdsWithChagenSet
public static void clearMapThreadToObjectIdsWithChagenSet(java.lang.Thread thread)
Remove the current thread from the map of object ids with change sets that are about to bec ommited- Parameters:
thread- the thread that is clearing itself out of the map of change sets it needs to merge into the shared cache
-
populateMapThreadToObjectIdsWithChagenSet
public static void populateMapThreadToObjectIdsWithChagenSet(java.lang.Thread thread, java.util.Collection<ObjectChangeSet> objectChangeSets)Before a thread starts long wait loop to acquire write locks during a commit transaction the thread will record in this map the object ids it holds with chance sets. It will be useful information if a dead lock is taking place.- Parameters:
thread- the thread that is in the middle of merge to the shared cache trying to acquire write locks to do this mergeobjectChangeSets- the object change sets it has in its hands and that it would like to merge into the cache
-
clearMapWriteLockManagerToCacheKeysThatCouldNotBeAcquired
public static void clearMapWriteLockManagerToCacheKeysThatCouldNotBeAcquired(java.lang.Thread thread)
Before the problematic while loop starts we should always clear for this thread the set of cache keys it could not acquire.- Parameters:
thread- the thread that what clear his set of cache keys it is struggling to acquire.
-
addCacheKeyToMapWriteLockManagerToCacheKeysThatCouldNotBeAcquired
public static void addCacheKeyToMapWriteLockManagerToCacheKeysThatCouldNotBeAcquired(java.lang.Thread thread, ConcurrencyManager cacheKeyThatCouldNotBeAcquired, long whileStartDate) throws java.lang.InterruptedExceptionThe thread was doing its while loop to acquire all required locks to proceed with the commmit and it realized there was one cache key it is unable to acquire- Parameters:
thread- thread the thread working on updating the shared cachecacheKeyThatCouldNotBeAcquired- the cache key it is not managing to acquire- Throws:
java.lang.InterruptedException- Should be fired because we are passing a flag into the determineIfReleaseDeferredLockAppearsToBeDeadLocked to say we do not want the thread to be blown up (e.g. we are afraid of breaking threads in the middle of a commit process could be quite dangerous). SeeALLOW_INTERRUPTED_EXCEPTION_TO_BE_FIRED_UP_FALSE
-
removeCacheKeyFromMapWriteLockManagerToCacheKeysThatCouldNotBeAcquired
public static void removeCacheKeyFromMapWriteLockManagerToCacheKeysThatCouldNotBeAcquired(java.lang.Thread thread, ConcurrencyManager cacheKeyThatCouldNotBeAcquired)A cache keys was successfully acquired we want to make sure it is not recorded in the map of cache keys that could not be acquired. The situation theoretically can change. Failing to acquire a write lock can be a temporary situation. The lock might become available eventually. Otherwise there would be no point for the while loop that is trying to acquire these locks.- Parameters:
thread- the thread that just managed to grab a write lockcacheKeyThatCouldNotBeAcquired- the cache key it managed to acquire for writing.
-
-