use of org.neo4j.kernel.impl.locking.LockWaitEvent in project neo4j by neo4j.
the class RWLock method acquireWriteLock.
/**
* Tries to acquire write lock for a given transaction. If
* <CODE>this.writeCount</CODE> is greater than the currents tx's write
* count or the read count is greater than the currents tx's read count the
* transaction has to wait and the {@link RagManager#checkWaitOn} method is
* invoked for deadlock detection.
* <p/>
* If the lock can be acquires the lock count is updated on <CODE>this</CODE>
* and the transaction lock element (tle).
* Waiting for a lock can also be terminated. In that case waiting thread will be interrupted and corresponding
* {@link org.neo4j.kernel.impl.locking.community.RWLock.TxLockElement} will be marked as terminated.
* In that case lock will not be acquired and false will be return as result of acquisition
*
* @return true is lock was acquired, false otherwise
* @throws DeadlockDetectedException if a deadlock is detected
*/
synchronized boolean acquireWriteLock(LockTracer tracer, Object tx) throws DeadlockDetectedException {
TxLockElement tle = getOrCreateLockElement(tx);
LockRequest lockRequest = null;
LockWaitEvent waitEvent = null;
// used to track do we need to add lock request to a waiting queue or we still have it there
boolean addLockRequest = true;
try {
tle.incrementRequests();
Thread currentThread = currentThread();
long lockAcquisitionTimeBoundary = clock.millis() + lockAcquisitionTimeoutMillis;
while (!tle.isTerminated() && (totalWriteCount > tle.writeCount || totalReadCount > tle.readCount)) {
assertNotExpired(lockAcquisitionTimeBoundary);
ragManager.checkWaitOn(this, tx);
if (addLockRequest) {
lockRequest = new LockRequest(tle, WRITE, currentThread);
waitingThreadList.addFirst(lockRequest);
}
if (waitEvent == null) {
waitEvent = tracer.waitForLock(true, resource.type(), resource.resourceId());
}
addLockRequest = waitUninterruptedly(lockAcquisitionTimeBoundary);
ragManager.stopWaitOn(this, tx);
}
if (!tle.isTerminated()) {
registerWriteLockAcquired(tx, tle);
return true;
} else {
// if it was register before it will be cleaned up during standard lock release call
if (tle.requests == 1 && tle.isFree()) {
txLockElementMap.remove(tx);
}
return false;
}
} finally {
if (waitEvent != null) {
waitEvent.close();
}
cleanupWaitingListRequests(lockRequest, tle, addLockRequest);
// for cases when spurious wake up was the reason why we waked up, but also there
// was an interruption as described at 17.2 just clearing interruption flag
interrupted();
// if deadlocked, remove marking so lock is removed when empty
tle.decrementRequests();
unmark();
}
}
use of org.neo4j.kernel.impl.locking.LockWaitEvent in project neo4j by neo4j.
the class SlaveLocksClient method acquireExclusive.
@Override
public void acquireExclusive(LockTracer tracer, ResourceType resourceType, long... resourceIds) throws AcquireLockTimeoutException {
assertNotStopped();
long[] newResourceIds = firstTimeExclusiveLocks(resourceType, resourceIds);
if (newResourceIds.length > 0) {
try (LockWaitEvent event = tracer.waitForLock(true, resourceType, newResourceIds)) {
acquireExclusiveOnMaster(resourceType, newResourceIds);
} catch (Throwable failure) {
if (resourceIds != newResourceIds) {
releaseExclusive(resourceType, resourceIds, newResourceIds);
}
throw failure;
}
for (long resourceId : newResourceIds) {
if (!client.tryExclusiveLock(resourceType, resourceId)) {
throw new LocalDeadlockDetectedException(client, localLockManager, resourceType, resourceId, WRITE);
}
}
}
}
use of org.neo4j.kernel.impl.locking.LockWaitEvent in project neo4j by neo4j.
the class ForsetiClient method tryUpgradeToExclusiveWithShareLockHeld.
/** Attempt to upgrade a share lock that we hold to an exclusive lock. */
private boolean tryUpgradeToExclusiveWithShareLockHeld(LockTracer tracer, LockWaitEvent priorEvent, ResourceType resourceType, long resourceId, SharedLock sharedLock, int tries, long waitStartMillis) throws AcquireLockTimeoutException {
if (sharedLock.tryAcquireUpdateLock(this)) {
LockWaitEvent waitEvent = null;
try {
// Now we just wait for all clients to release the the share lock
while (sharedLock.numberOfHolders() > 1) {
assertValid(waitStartMillis, resourceType, resourceId);
if (waitEvent == null && priorEvent == null) {
waitEvent = tracer.waitForLock(true, resourceType, resourceId);
}
applyWaitStrategy(resourceType, tries++);
markAsWaitingFor(sharedLock, resourceType, resourceId);
}
return true;
} catch (DeadlockDetectedException e) {
sharedLock.releaseUpdateLock();
// markAsWaitingFor() before throwing DeadlockDetectedException
throw e;
} catch (LockClientStoppedException e) {
handleUpgradeToExclusiveFailure(sharedLock);
throw e;
} catch (Throwable e) {
handleUpgradeToExclusiveFailure(sharedLock);
throw new RuntimeException(e);
} finally {
if (waitEvent != null) {
waitEvent.close();
}
}
}
return false;
}
use of org.neo4j.kernel.impl.locking.LockWaitEvent in project neo4j by neo4j.
the class ForsetiClient method acquireExclusive.
@Override
public void acquireExclusive(LockTracer tracer, ResourceType resourceType, long... resourceIds) throws AcquireLockTimeoutException {
hasLocks = true;
stateHolder.incrementActiveClients(this);
try {
ConcurrentMap<Long, ForsetiLockManager.Lock> lockMap = lockMaps[resourceType.typeId()];
PrimitiveLongIntMap heldLocks = exclusiveLockCounts[resourceType.typeId()];
for (long resourceId : resourceIds) {
int heldCount = heldLocks.get(resourceId);
if (heldCount != -1) {
// We already have a lock on this, just increment our local reference counter.
heldLocks.put(resourceId, Math.incrementExact(heldCount));
continue;
}
LockWaitEvent waitEvent = null;
try {
// Grab the global lock
ForsetiLockManager.Lock existingLock;
int tries = 0;
long waitStartMillis = clock.millis();
while ((existingLock = lockMap.putIfAbsent(resourceId, myExclusiveLock)) != null) {
assertValid(waitStartMillis, resourceType, resourceId);
// for it to convert to an exclusive lock.
if (tries > 50 && existingLock instanceof SharedLock) {
// Then we should upgrade that lock
SharedLock sharedLock = (SharedLock) existingLock;
if (tryUpgradeSharedToExclusive(tracer, waitEvent, resourceType, lockMap, resourceId, sharedLock, waitStartMillis)) {
break;
}
}
if (waitEvent == null) {
waitEvent = tracer.waitForLock(true, resourceType, resourceId);
}
applyWaitStrategy(resourceType, tries++);
markAsWaitingFor(existingLock, resourceType, resourceId);
}
} finally {
if (waitEvent != null) {
waitEvent.close();
}
}
clearWaitList();
heldLocks.put(resourceId, 1);
}
} finally {
stateHolder.decrementActiveClients();
}
}
use of org.neo4j.kernel.impl.locking.LockWaitEvent in project neo4j by neo4j.
the class SlaveLocksClient method acquireShared.
@Override
public void acquireShared(LockTracer tracer, ResourceType resourceType, long... resourceIds) throws AcquireLockTimeoutException {
assertNotStopped();
long[] newResourceIds = firstTimeSharedLocks(resourceType, resourceIds);
if (newResourceIds.length > 0) {
try (LockWaitEvent event = tracer.waitForLock(false, resourceType, newResourceIds)) {
acquireSharedOnMaster(resourceType, newResourceIds);
} catch (Throwable failure) {
if (resourceIds != newResourceIds) {
releaseShared(resourceType, resourceIds, newResourceIds);
}
throw failure;
}
for (long resourceId : newResourceIds) {
if (!client.trySharedLock(resourceType, resourceId)) {
throw new LocalDeadlockDetectedException(client, localLockManager, resourceType, resourceId, READ);
}
}
}
}
Aggregations