From 5ec096e7f15b1cb1914ff5abc4cf1ec28302b460 Mon Sep 17 00:00:00 2001 From: Kalin Chan Date: Tue, 24 Sep 2024 14:14:17 +0100 Subject: [PATCH] L2 Cache Deadlock Prevention --- .../internal/helper/ConcurrencyManager.java | 2 +- .../internal/sessions/ObjectChangeSet.java | 50 ++++++++++++------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/ConcurrencyManager.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/ConcurrencyManager.java index 18fdf3f63c0..fd2899e5224 100644 --- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/ConcurrencyManager.java +++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/ConcurrencyManager.java @@ -721,7 +721,7 @@ public void releaseDeferredLock() throws ConcurrencyException { throw ConcurrencyException.waitWasInterrupted(interrupted.getMessage()); } } - } catch (Error error) { + } catch (Error | Exception error) { if (!releaseAllLocksAquiredByThreadAlreadyPerformed) { THREADS_WAITING_TO_RELEASE_DEFERRED_LOCKS.remove(currentThread); AbstractSessionLog.getLog().logThrowable(SessionLog.SEVERE, SessionLog.CACHE, error); diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/sessions/ObjectChangeSet.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/sessions/ObjectChangeSet.java index bc910625502..434b267a208 100644 --- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/sessions/ObjectChangeSet.java +++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/sessions/ObjectChangeSet.java @@ -521,33 +521,47 @@ protected Object getObjectForMerge(MergeManager mergeManager, AbstractSession se CacheKey cacheKey = session.getIdentityMapAccessorInstance().getCacheKeyForObject(primaryKey, descriptor.getJavaClass(), descriptor, true); if (cacheKey != null) { if (cacheKey.acquireReadLockNoWait()) { - domainObject = cacheKey.getObject(); - cacheKey.releaseReadLock(); + try { + domainObject = cacheKey.getObject(); + } catch (Exception exception) { + exception.printStackTrace(); + } + finally { + cacheKey.releaseReadLock(); + } } else { if (!mergeManager.isTransitionedToDeferredLocks()) { session.getIdentityMapAccessorInstance().getWriteLockManager().transitionToDeferredLocks(mergeManager); } cacheKey.acquireDeferredLock(); - domainObject = cacheKey.getObject(); - int tries = 0; - while (domainObject == null) { - ++tries; - if (tries > MAX_TRIES){ - session.getParent().log(SessionLog.SEVERE, SessionLog.CACHE, "entity_not_available_during_merge", new Object[]{descriptor.getJavaClassName(), cacheKey.getKey(), Thread.currentThread().getName(), cacheKey.getActiveThread()}); - break; - } - synchronized (cacheKey) { - if (cacheKey.isAcquired()) { - try { - cacheKey.wait(10); - } catch (InterruptedException e) { - //ignore and return + try { + domainObject = cacheKey.getObject(); + int tries = 0; + while (domainObject == null) { + ++tries; + if (tries > MAX_TRIES){ + if (session.getParent() != null) { + session.getParent().log(SessionLog.SEVERE, SessionLog.CACHE, "entity_not_available_during_merge", new Object[]{descriptor.getJavaClassName(), cacheKey.getKey(), Thread.currentThread().getName(), cacheKey.getActiveThread()}); } + break; + } + synchronized (cacheKey) { + if (cacheKey.isAcquired()) { + try { + cacheKey.wait(10); + } catch (InterruptedException e) { + //ignore and return + } + } + domainObject = cacheKey.getObject(); } - domainObject = cacheKey.getObject(); } + } catch (Exception exception) { + exception.printStackTrace(); + } + finally { + cacheKey.releaseDeferredLock(); } - cacheKey.releaseDeferredLock(); } } else { domainObject = mergeManager.registerExistingObjectOfReadOnlyClassInNestedTransaction(getUnitOfWorkClone(), descriptor, session);