Class WriteLockManager
- java.lang.Object
-
- org.eclipse.persistence.internal.helper.WriteLockManager
-
public class WriteLockManager extends Object
INTERNAL: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 int
MAX_WAIT
static int
MAXTRIES
protected ExposedNodeLinkedList
prevailingQueue
-
Constructor Summary
Constructors Constructor Description WriteLockManager()
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description CacheKey
acquireLockAndRelatedLocks(Object objectForClone, Map lockedObjects, 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.Map
acquireLocksForClone(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.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.static void
addCacheKeyToMapWriteLockManagerToCacheKeysThatCouldNotBeAcquired(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 acquireCacheKey
appendLock(Object primaryKey, 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 CacheKey
attemptToAcquireLock(ClassDescriptor descriptor, Object primaryKey, AbstractSession session)
INTERNAL: This method performs the operations of finding the cacheKey and locking it if possible.protected CacheKey
checkAndLockObject(Object objectToLock, Map lockedObjects, Map refreshedObjects, DatabaseMapping mapping, AbstractSession cloningSession)
INTERNAL: Simply check that the object is not already locked then pass it on to the locking methodstatic void
clearMapThreadToObjectIdsWithChagenSet(Thread thread)
Remove the current thread from the map of object ids with change sets that are about to bec ommitedstatic void
clearMapWriteLockManagerToCacheKeysThatCouldNotBeAcquired(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 Map<Thread,Set<Object>>
getMapWriteLockManagerThreadToObjectIdsWithChangeSet()
static Map<Thread,Set<ConcurrencyManager>>
getThreadToFailToAcquireCacheKeys()
Getter forTHREAD_TO_FAIL_TO_ACQUIRE_CACHE_KEYS
static void
populateMapThreadToObjectIdsWithChagenSet(Thread thread, 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.void
releaseAllAcquiredLocks(MergeManager mergeManager)
INTERNAL: This method will release all acquired locksstatic void
removeCacheKeyFromMapWriteLockManagerToCacheKeysThatCouldNotBeAcquired(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.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.CacheKey
traverseRelatedLocks(Object objectForClone, Map lockedObjects, Map refreshedObjects, ClassDescriptor descriptor, AbstractSession cloningSession)
INTERNAL: Traverse the object and acquire locks on all related objects.protected CacheKey
waitOnObjectLock(ClassDescriptor descriptor, 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 final int MAXTRIES
- See Also:
- Constant Field Values
-
MAX_WAIT
public static final int MAX_WAIT
- See Also:
- Constant Field Values
-
prevailingQueue
protected ExposedNodeLinkedList prevailingQueue
-
-
Method Detail
-
acquireLocksForClone
public Map acquireLocksForClone(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(Object objectForClone, Map lockedObjects, 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(Object objectForClone, Map lockedObjects, 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(Object primaryKey, 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, 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(Object objectToLock, Map lockedObjects, 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, 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 Map<Thread,Set<ConcurrencyManager>> getThreadToFailToAcquireCacheKeys()
Getter forTHREAD_TO_FAIL_TO_ACQUIRE_CACHE_KEYS
-
getMapWriteLockManagerThreadToObjectIdsWithChangeSet
public static Map<Thread,Set<Object>> getMapWriteLockManagerThreadToObjectIdsWithChangeSet()
-
clearMapThreadToObjectIdsWithChagenSet
public static void clearMapThreadToObjectIdsWithChagenSet(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(Thread thread, 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(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(Thread thread, ConcurrencyManager cacheKeyThatCouldNotBeAcquired, long whileStartDate) throws InterruptedException
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 acquire- Parameters:
thread
- thread the thread working on updating the shared cachecacheKeyThatCouldNotBeAcquired
- the cache key it is not managing to acquire- Throws:
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(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.
-
-