Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FISH-9063 Allow Throwing an Exception After Locks for Clone Is Interrupted #31

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,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 @@ -59,6 +59,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 @@ -68,6 +69,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 @@ -300,6 +302,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 @@ -37,6 +37,7 @@
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.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.DatabaseMapping;

Expand Down Expand Up @@ -166,14 +167,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 @@ -185,6 +192,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
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,11 @@ public class TraceLocalizationResource extends ListResourceBundle {
+ " But our hacked implementation of the isBuildObjectOnThreadComplete was not able to explain what thread and cache key are recursively "
+ " 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. "},

+ " 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