Skip to content

Commit 5aad3f7

Browse files
authored
Merge pull request #31 from aubi/FISH-9063-allow-throw-after-interrupted-locks-for-clone
FISH-9063 Allow Throwing an Exception After Locks for Clone Is Interrupted
2 parents 7d09197 + a296980 commit 5aad3f7

File tree

4 files changed

+40
-3
lines changed

4 files changed

+40
-3
lines changed

foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/config/SystemProperties.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,22 @@ public class SystemProperties {
186186
*/
187187
public static final String CONCURRENCY_MANAGER_ALLOW_STACK_TRACE_READ_LOCK = "eclipselink.concurrency.manager.allow.readlockstacktrace";
188188

189+
/**
190+
* <p>
191+
* This property control (enable/disable) if
192+
* <code>ConcurrencyException</code> fired when dead-lock diagnostic is
193+
* enabled.
194+
* <p>
195+
* <b>Allowed Values</b> (case sensitive String)<b>:</b>
196+
* <ul>
197+
* <li>"<code>false</code>" (DEFAULT) - don't collect debug/trace
198+
* information during ReadLock acquisition
199+
* <li>"<code>true</code>" - collect debug/trace information during ReadLock
200+
* acquisition. Has negative impact to the performance.
201+
* </ul>
202+
*/
203+
public static final String CONCURRENCY_MANAGER_ALLOW_INTERRUPTION_OF_LOCKWAIT = "eclipselink.concurrency.manager.allow.interruption.lockwait";
204+
189205
/**
190206
* <p>
191207
* This property control (enable/disable) semaphore in {@link org.eclipse.persistence.internal.descriptors.ObjectBuilder}

foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/ConcurrencyUtil.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public class ConcurrencyUtil {
5959
public static final int DEFAULT_CONCURRENCY_MANAGER_WRITE_LOCK_MANAGER_ACQUIRE_REQUIRED_LOCKS_NO_THREADS = 2;
6060
public static final long DEFAULT_CONCURRENCY_SEMAPHORE_MAX_TIME_PERMIT = 2000L;
6161
public static final long DEFAULT_CONCURRENCY_SEMAPHORE_LOG_TIMEOUT = 10000L;
62+
private static final boolean DEFAULT_INTERRUPTION_OF_LOCKWAIT = false;
6263

6364
private long acquireWaitTime = getLongProperty(SystemProperties.CONCURRENCY_MANAGER_ACQUIRE_WAIT_TIME, DEFAULT_ACQUIRE_WAIT_TIME);
6465
private long buildObjectCompleteWaitTime = getLongProperty(SystemProperties.CONCURRENCY_MANAGER_BUILD_OBJECT_COMPLETE_WAIT_TIME, DEFAULT_BUILD_OBJECT_COMPLETE_WAIT_TIME);
@@ -68,6 +69,7 @@ public class ConcurrencyUtil {
6869
private boolean allowInterruptedExceptionFired = getBooleanProperty(SystemProperties.CONCURRENCY_MANAGER_ALLOW_INTERRUPTED_EXCEPTION, DEFAULT_INTERRUPTED_EXCEPTION_FIRED);
6970
private boolean allowConcurrencyExceptionToBeFiredUp = getBooleanProperty(SystemProperties.CONCURRENCY_MANAGER_ALLOW_CONCURRENCY_EXCEPTION, DEFAULT_CONCURRENCY_EXCEPTION_FIRED);
7071
private boolean allowTakingStackTraceDuringReadLockAcquisition = getBooleanProperty(SystemProperties.CONCURRENCY_MANAGER_ALLOW_STACK_TRACE_READ_LOCK, DEFAULT_TAKING_STACKTRACE_DURING_READ_LOCK_ACQUISITION);
72+
private boolean allowInterruptionOfLockWait = getBooleanProperty(SystemProperties.CONCURRENCY_MANAGER_ALLOW_INTERRUPTION_OF_LOCKWAIT, DEFAULT_INTERRUPTION_OF_LOCKWAIT);
7173

7274
private boolean useSemaphoreInObjectBuilder = getBooleanProperty(SystemProperties.CONCURRENCY_MANAGER_USE_SEMAPHORE_TO_SLOW_DOWN_OBJECT_BUILDING, DEFAULT_USE_SEMAPHORE_TO_SLOW_DOWN_OBJECT_BUILDING_CONCURRENCY);
7375
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);
@@ -300,6 +302,14 @@ public void setAllowTakingStackTraceDuringReadLockAcquisition(boolean allowTakin
300302
this.allowTakingStackTraceDuringReadLockAcquisition = allowTakingStackTraceDuringReadLockAcquisition;
301303
}
302304

305+
public boolean isInterruptionOfLockWaitEnabled() {
306+
return allowInterruptionOfLockWait;
307+
}
308+
309+
public void setInterruptionOfLockWaitEnabled(boolean interruptionOfLockWaitEnabled) {
310+
this.allowInterruptionOfLockWait = interruptionOfLockWaitEnabled;
311+
}
312+
303313
public boolean isUseSemaphoreInObjectBuilder() {
304314
return useSemaphoreInObjectBuilder;
305315
}

foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/WriteLockManager.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.eclipse.persistence.internal.sessions.MergeManager;
3838
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
3939
import org.eclipse.persistence.internal.sessions.UnitOfWorkChangeSet;
40+
import org.eclipse.persistence.logging.AbstractSessionLog;
4041
import org.eclipse.persistence.logging.SessionLog;
4142
import org.eclipse.persistence.mappings.DatabaseMapping;
4243

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

170172
synchronized (toWaitOn) {
171173
try {
172174
if (toWaitOn.isAcquired()) {//last minute check to insure it is still locked.
173175
toWaitOn.wait(ConcurrencyUtil.SINGLETON.getAcquireWaitTime());// wait for lock on object to be released
174176
}
175177
} catch (InterruptedException ex) {
176-
// Ignore exception thread should continue.
178+
// Allow thread interruptions for bad threads stuck in org.eclipse.persistence.internal.helper.WriteLockManager.acquireLocksForClone
179+
if (ConcurrencyUtil.SINGLETON.isInterruptionOfLockWaitEnabled()) {
180+
logger.log(SessionLog.SEVERE, SessionLog.CACHE, "write_lock_manager_allow_interruption_lockwait_interrupted_throws");
181+
throw ConcurrencyException.waitWasInterrupted(ex.getMessage());
182+
}
183+
logger.log(SessionLog.FINE, SessionLog.CACHE, "write_lock_manager_allow_interruption_lockwait_interrupted_continues");
177184
}
178185
}
179186
Object waitObject = toWaitOn.getObject();
@@ -185,6 +192,7 @@ public Map acquireLocksForClone(Object objectForClone, ClassDescriptor descripto
185192
toWaitOn = acquireLockAndRelatedLocks(objectForClone, lockedObjects, refreshedObjects, cacheKey, descriptor, cloningSession);
186193
if ((toWaitOn != null) && ((++tries) > MAXTRIES)) {
187194
// If we've tried too many times abort.
195+
logger.log(SessionLog.FINE, SessionLog.CACHE, "write_lock_manager_lockwait_exceeded_max_tries", MAXTRIES);
188196
throw ConcurrencyException.maxTriesLockOnCloneExceded(objectForClone);
189197
}
190198
}

foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/localization/i18n/TraceLocalizationResource.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,11 @@ public class TraceLocalizationResource extends ListResourceBundle {
268268
+ " But our hacked implementation of the isBuildObjectOnThreadComplete was not able to explain what thread and cache key are recursively "
269269
+ " stopping the candidate thread to make progress... We expect this code spot to never be invoked. "
270270
+ " Either this thread made progress or if it continues to be stuck in the releaseDeferredLock "
271-
+ " we most likely have an implementation bug somewhere. "},
272-
271+
+ " we most likely have an implementation bug somewhere. "},
272+
{"write_lock_manager_lockwait_exceeded_max_tries", "Max {0} tries exceeded during Write Lock Manager acquiring locks for clone."},
273+
{"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"},
274+
{"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"},
275+
273276
{ "XML_call", "XML call" },
274277
{ "XML_data_call", "XML data call" },
275278
{ "XML_data_delete", "XML data delete" },

0 commit comments

Comments
 (0)