Search in sources :

Example 1 with LockWaitEvent

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();
    }
}
Also used : LockWaitEvent(org.neo4j.kernel.impl.locking.LockWaitEvent) Thread.currentThread(java.lang.Thread.currentThread)

Example 2 with LockWaitEvent

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);
            }
        }
    }
}
Also used : LockWaitEvent(org.neo4j.kernel.impl.locking.LockWaitEvent)

Example 3 with LockWaitEvent

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;
}
Also used : LockClientStoppedException(org.neo4j.kernel.impl.locking.LockClientStoppedException) DeadlockDetectedException(org.neo4j.kernel.DeadlockDetectedException) LockWaitEvent(org.neo4j.kernel.impl.locking.LockWaitEvent)

Example 4 with LockWaitEvent

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();
    }
}
Also used : PrimitiveLongIntMap(org.neo4j.collection.primitive.PrimitiveLongIntMap) LockWaitEvent(org.neo4j.kernel.impl.locking.LockWaitEvent) ActiveLock(org.neo4j.kernel.impl.locking.ActiveLock)

Example 5 with LockWaitEvent

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);
            }
        }
    }
}
Also used : LockWaitEvent(org.neo4j.kernel.impl.locking.LockWaitEvent)

Aggregations

LockWaitEvent (org.neo4j.kernel.impl.locking.LockWaitEvent)9 Thread.currentThread (java.lang.Thread.currentThread)2 Test (org.junit.Test)2 PrimitiveLongIntMap (org.neo4j.collection.primitive.PrimitiveLongIntMap)2 ActiveLock (org.neo4j.kernel.impl.locking.ActiveLock)2 DeadlockDetectedException (org.neo4j.kernel.DeadlockDetectedException)1 LockClientStoppedException (org.neo4j.kernel.impl.locking.LockClientStoppedException)1