Skip to content

Commit

Permalink
FISH-9063 allow throwing an exception after locks for clone is interr…
Browse files Browse the repository at this point in the history
…upted
  • Loading branch information
aubi committed Sep 19, 2024
1 parent 5714742 commit 6e75593
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,22 @@ public class SystemProperties {
*/
public static final String CONCURRENCY_MANAGER_ALLOW_STACK_TRACE_READ_LOCK = "eclipselink.concurrency.manager.allow.readlockstacktrace";

/**
* <p>
* This property control (enable/disable) if
* <code>ConcurrencyException</code> fired when dead-lock diagnostic is
* enabled.
* <p>
* <b>Allowed Values</b> (case sensitive String)<b>:</b>
* <ul>
* <li>"<code>false</code>" (DEFAULT) - don't collect debug/trace
* information during ReadLock acquisition
* <li>"<code>true</code>" - collect debug/trace information during ReadLock
* acquisition. Has negative impact to the performance.
* </ul>
*/
public static final String CONCURRENCY_MANAGER_ALLOW_INTERRUPTION_OF_LOCKWAIT = "eclipselink.concurrency.manager.allow.interruption.lockwait";

/**
* <p>
* This property control (enable/disable) semaphore in {@link org.eclipse.persistence.internal.descriptors.ObjectBuilder}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public class ConcurrencyUtil {
public static final int DEFAULT_CONCURRENCY_MANAGER_WRITE_LOCK_MANAGER_ACQUIRE_REQUIRED_LOCKS_NO_THREADS = 2;
public static final long DEFAULT_CONCURRENCY_SEMAPHORE_MAX_TIME_PERMIT = 2000L;
public static final long DEFAULT_CONCURRENCY_SEMAPHORE_LOG_TIMEOUT = 10000L;
private static final boolean DEFAULT_INTERRUPTION_OF_LOCKWAIT = false;

private long acquireWaitTime = getLongProperty(SystemProperties.CONCURRENCY_MANAGER_ACQUIRE_WAIT_TIME, DEFAULT_ACQUIRE_WAIT_TIME);
private long buildObjectCompleteWaitTime = getLongProperty(SystemProperties.CONCURRENCY_MANAGER_BUILD_OBJECT_COMPLETE_WAIT_TIME, DEFAULT_BUILD_OBJECT_COMPLETE_WAIT_TIME);
Expand All @@ -63,6 +64,7 @@ public class ConcurrencyUtil {
private boolean allowInterruptedExceptionFired = getBooleanProperty(SystemProperties.CONCURRENCY_MANAGER_ALLOW_INTERRUPTED_EXCEPTION, DEFAULT_INTERRUPTED_EXCEPTION_FIRED);
private boolean allowConcurrencyExceptionToBeFiredUp = getBooleanProperty(SystemProperties.CONCURRENCY_MANAGER_ALLOW_CONCURRENCY_EXCEPTION, DEFAULT_CONCURRENCY_EXCEPTION_FIRED);
private boolean allowTakingStackTraceDuringReadLockAcquisition = getBooleanProperty(SystemProperties.CONCURRENCY_MANAGER_ALLOW_STACK_TRACE_READ_LOCK, DEFAULT_TAKING_STACKTRACE_DURING_READ_LOCK_ACQUISITION);
private boolean allowInterruptionOfLockWait = getBooleanProperty(SystemProperties.CONCURRENCY_MANAGER_ALLOW_INTERRUPTION_OF_LOCKWAIT, DEFAULT_INTERRUPTION_OF_LOCKWAIT);

private boolean useSemaphoreInObjectBuilder = getBooleanProperty(SystemProperties.CONCURRENCY_MANAGER_USE_SEMAPHORE_TO_SLOW_DOWN_OBJECT_BUILDING, DEFAULT_USE_SEMAPHORE_TO_SLOW_DOWN_OBJECT_BUILDING_CONCURRENCY);
private boolean useSemaphoreToLimitConcurrencyOnWriteLockManagerAcquireRequiredLocks = getBooleanProperty(SystemProperties.CONCURRENCY_MANAGER_USE_SEMAPHORE_TO_SLOW_DOWN_WRITE_LOCK_MANAGER_ACQUIRE_REQUIRED_LOCKS, DEFAULT_USE_SEMAPHORE_TO_SLOW_DOWN_WRITE_LOCK_MANAGER_ACQUIRE_REQUIRED_LOCKS);
Expand Down Expand Up @@ -295,6 +297,14 @@ public void setAllowTakingStackTraceDuringReadLockAcquisition(boolean allowTakin
this.allowTakingStackTraceDuringReadLockAcquisition = allowTakingStackTraceDuringReadLockAcquisition;
}

public boolean isInterruptionOfLockWaitEnabled() {
return allowInterruptionOfLockWait;
}

public void setInterruptionOfLockWaitEnabled(boolean interruptionOfLockWaitEnabled) {
this.allowInterruptionOfLockWait = interruptionOfLockWaitEnabled;
}

public boolean isUseSemaphoreInObjectBuilder() {
return useSemaphoreInObjectBuilder;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,13 @@
// - 526957 : Split the logging and trace messages
package org.eclipse.persistence.internal.helper;

import java.util.Collection;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.*;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Semaphore;

Expand All @@ -34,14 +37,14 @@
import org.eclipse.persistence.exceptions.ConcurrencyException;
import org.eclipse.persistence.internal.helper.linkedlist.ExposedNodeLinkedList;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.localization.LoggingLocalization;
import org.eclipse.persistence.internal.localization.TraceLocalization;
import org.eclipse.persistence.internal.queries.ContainerPolicy;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.MergeManager;
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
import org.eclipse.persistence.internal.sessions.UnitOfWorkChangeSet;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.DatabaseMapping;

Expand Down Expand Up @@ -169,14 +172,20 @@ public Map acquireLocksForClone(Object objectForClone, ClassDescriptor descripto
// we will now always check for how long the current thread is stuck in this while loop going nowhere
// using the exact same approach we have been adding to the concurrency manager
ConcurrencyUtil.SINGLETON.determineIfReleaseDeferredLockAppearsToBeDeadLocked(toWaitOn, whileStartTimeMillis, lockManager, readLockManager, ALLOW_INTERRUPTED_EXCEPTION_TO_BE_FIRED_UP_TRUE);
SessionLog logger = AbstractSessionLog.getLog();

synchronized (toWaitOn) {
try {
if (toWaitOn.isAcquired()) {//last minute check to insure it is still locked.
toWaitOn.wait(ConcurrencyUtil.SINGLETON.getAcquireWaitTime());// wait for lock on object to be released
}
} catch (InterruptedException ex) {
// Ignore exception thread should continue.
// Allow thread interruptions for bad threads stuck in org.eclipse.persistence.internal.helper.WriteLockManager.acquireLocksForClone
if (ConcurrencyUtil.SINGLETON.isInterruptionOfLockWaitEnabled()) {
logger.log(SessionLog.SEVERE, SessionLog.CACHE, "write_lock_manager_allow_interruption_lockwait_interrupted_throws");
throw ConcurrencyException.waitWasInterrupted(ex.getMessage());
}
logger.log(SessionLog.FINE, SessionLog.CACHE, "write_lock_manager_allow_interruption_lockwait_interrupted_continues");
}
}
Object waitObject = toWaitOn.getObject();
Expand All @@ -188,6 +197,7 @@ public Map acquireLocksForClone(Object objectForClone, ClassDescriptor descripto
toWaitOn = acquireLockAndRelatedLocks(objectForClone, lockedObjects, refreshedObjects, cacheKey, descriptor, cloningSession);
if ((toWaitOn != null) && ((++tries) > MAXTRIES)) {
// If we've tried too many times abort.
logger.log(SessionLog.FINE, SessionLog.CACHE, "write_lock_manager_lockwait_exceeded_max_tries", MAXTRIES);
throw ConcurrencyException.maxTriesLockOnCloneExceded(objectForClone);
}
}
Expand Down Expand Up @@ -778,4 +788,4 @@ private static Set<ConcurrencyManager> getCacheKeysThatCouldNotBeAcquiredByThrea
// (b) We are certain the map is not empty anymore return the set
return THREAD_TO_FAIL_TO_ACQUIRE_CACHE_KEYS.get(thread);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,10 @@ public class TraceLocalizationResource extends ListResourceBundle {
+ " stopping the candidate thread to make progress... We expect this code spot to never be invoked. "
+ " Either this thread made progress or if it continues to be stuck in the releaseDeferredLock "
+ " we most likely have an implementation bug somewhere. "},
{"write_lock_manager_lockwait_exceeded_max_tries", "Max {0} tries exceeded during Write Lock Manager acquiring locks for clone."},
{"write_lock_manager_allow_interruption_lockwait_interrupted_throws", "Write Lock Manager was interrupted during acquiring locks for clone and 'eclipselink.concurrency.manager.allow.interruption.lockwait' was set to true, throwing ConcurrencyException"},
{"write_lock_manager_allow_interruption_lockwait_interrupted_continues", "Write Lock Manager was interrupted during acquiring locks for clone and 'eclipselink.concurrency.manager.allow.interruption.lockwait' was set to false, ignoring and continue"},

{ "XML_call", "XML call" },
{ "XML_data_call", "XML data call" },
{ "XML_data_delete", "XML data delete" },
Expand Down

0 comments on commit 6e75593

Please sign in to comment.