Search in sources :

Example 1 with HeapTrackingLongIntHashMap

use of org.neo4j.collection.trackable.HeapTrackingLongIntHashMap in project neo4j by neo4j.

the class ForsetiClient method tryExclusiveLock.

@Override
public boolean tryExclusiveLock(ResourceType resourceType, long resourceId) {
    hasLocks = true;
    stateHolder.incrementActiveClients(this);
    try {
        ConcurrentMap<Long, ForsetiLockManager.Lock> lockMap = lockMaps[resourceType.typeId()];
        HeapTrackingLongIntHashMap heldLocks = getExclusiveLockCount(resourceType);
        int heldCount = heldLocks.getIfAbsent(resourceId, NO_CLIENT_ID);
        if (heldCount != NO_CLIENT_ID) {
            // We already have a lock on this, just increment our local reference counter.
            heldLocks.put(resourceId, Math.incrementExact(heldCount));
            return true;
        }
        // Grab the global lock
        ForsetiLockManager.Lock lock;
        if ((lock = lockMap.putIfAbsent(resourceId, myExclusiveLock)) != null) {
            if (lock instanceof SharedLock && getSharedLockCount(resourceType).containsKey(resourceId)) {
                SharedLock sharedLock = (SharedLock) lock;
                if (sharedLock.tryAcquireUpdateLock(this)) {
                    if (sharedLock.numberOfHolders() == 1) {
                        heldLocks.put(resourceId, 1);
                        return true;
                    } else {
                        sharedLock.releaseUpdateLock();
                        return false;
                    }
                }
            }
            return false;
        }
        heldLocks.put(resourceId, 1);
        memoryTracker.allocateHeap(CONCURRENT_NODE_SIZE);
        return true;
    } finally {
        stateHolder.decrementActiveClients();
    }
}
Also used : HeapTrackingLongIntHashMap(org.neo4j.collection.trackable.HeapTrackingLongIntHashMap) ActiveLock(org.neo4j.lock.ActiveLock)

Example 2 with HeapTrackingLongIntHashMap

use of org.neo4j.collection.trackable.HeapTrackingLongIntHashMap in project neo4j by neo4j.

the class ForsetiClient method releaseAllClientLocks.

private void releaseAllClientLocks() {
    // Force the release of all locks held.
    for (int i = 0; i < exclusiveLockCounts.length; i++) {
        HeapTrackingLongIntHashMap exclusiveLocks = exclusiveLockCounts[i];
        HeapTrackingLongIntHashMap sharedLocks = sharedLockCounts[i];
        // been re-instated after releasing the exclusive lock).
        if (exclusiveLocks != null) {
            exclusiveLocks.forEachKey(releaseExclusiveAndClearSharedVisitor.initialize(sharedLocks, lockMaps[i]));
            exclusiveLockCounts[i] = null;
            exclusiveLocks.close();
        }
        // Then release all remaining shared locks
        if (sharedLocks != null) {
            sharedLocks.forEachKey(releaseSharedDontCheckExclusiveVisitor.initialize(lockMaps[i]));
            sharedLockCounts[i] = null;
            sharedLocks.close();
        }
    }
}
Also used : HeapTrackingLongIntHashMap(org.neo4j.collection.trackable.HeapTrackingLongIntHashMap)

Example 3 with HeapTrackingLongIntHashMap

use of org.neo4j.collection.trackable.HeapTrackingLongIntHashMap 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);
    LockWaitEvent waitEvent = null;
    try {
        ConcurrentMap<Long, ForsetiLockManager.Lock> lockMap = lockMaps[resourceType.typeId()];
        HeapTrackingLongIntHashMap heldLocks = getExclusiveLockCount(resourceType);
        for (long resourceId : resourceIds) {
            int heldCount = heldLocks.getIfAbsent(resourceId, NO_CLIENT_ID);
            if (heldCount != NO_CLIENT_ID) {
                // We already have a lock on this, just increment our local reference counter.
                heldLocks.put(resourceId, Math.incrementExact(heldCount));
                continue;
            }
            // Grab the global lock
            ForsetiLockManager.Lock existingLock;
            int tries = 0;
            long waitStartNano = clock.nanos();
            boolean upgraded = false;
            while ((existingLock = lockMap.putIfAbsent(resourceId, myExclusiveLock)) != null) {
                assertValid(waitStartNano, 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, waitStartNano)) {
                        upgraded = true;
                        break;
                    }
                }
                if (waitEvent == null) {
                    waitEvent = tracer.waitForLock(EXCLUSIVE, resourceType, userTransactionId, resourceId);
                }
                waitFor(existingLock, resourceType, resourceId, tries++);
            }
            heldLocks.put(resourceId, 1);
            if (!upgraded) {
                memoryTracker.allocateHeap(CONCURRENT_NODE_SIZE);
            }
        }
    } finally {
        if (waitEvent != null) {
            waitEvent.close();
        }
        clearWaitList();
        waitingForLock = null;
        stateHolder.decrementActiveClients();
    }
}
Also used : HeapTrackingLongIntHashMap(org.neo4j.collection.trackable.HeapTrackingLongIntHashMap) LockWaitEvent(org.neo4j.lock.LockWaitEvent) ActiveLock(org.neo4j.lock.ActiveLock)

Example 4 with HeapTrackingLongIntHashMap

use of org.neo4j.collection.trackable.HeapTrackingLongIntHashMap in project neo4j by neo4j.

the class ForsetiClient method trySharedLock.

@Override
public boolean trySharedLock(ResourceType resourceType, long resourceId) {
    hasLocks = true;
    stateHolder.incrementActiveClients(this);
    try {
        ConcurrentMap<Long, ForsetiLockManager.Lock> lockMap = lockMaps[resourceType.typeId()];
        HeapTrackingLongIntHashMap heldShareLocks = getSharedLockCount(resourceType);
        HeapTrackingLongIntHashMap heldExclusiveLocks = getExclusiveLockCount(resourceType);
        int heldCount = heldShareLocks.getIfAbsent(resourceId, NO_CLIENT_ID);
        if (heldCount != NO_CLIENT_ID) {
            // We already have a lock on this, just increment our local reference counter.
            heldShareLocks.put(resourceId, Math.incrementExact(heldCount));
            return true;
        }
        if (heldExclusiveLocks.containsKey(resourceId)) {
            // We already have an exclusive lock, so just leave that in place. When the exclusive lock is released,
            // it will be automatically downgraded to a shared lock, since we bumped the share lock reference count.
            heldShareLocks.put(resourceId, 1);
            return true;
        }
        long waitStartNano = clock.nanos();
        while (true) {
            assertValid(waitStartNano, resourceType, resourceId);
            ForsetiLockManager.Lock existingLock = lockMap.get(resourceId);
            if (existingLock == null) {
                // Try to create a new shared lock
                if (lockMap.putIfAbsent(resourceId, new SharedLock(this)) == null) {
                    // Success!
                    break;
                }
            } else if (existingLock instanceof SharedLock) {
                // even though this is a try-lock call.
                if (((SharedLock) existingLock).acquire(this)) {
                    // Success!
                    break;
                } else if (((SharedLock) existingLock).isUpdateLock()) {
                    return false;
                }
            } else if (existingLock instanceof ExclusiveLock) {
                return false;
            } else {
                throw new UnsupportedOperationException("Unknown lock type: " + existingLock);
            }
        }
        heldShareLocks.put(resourceId, 1);
        memoryTracker.allocateHeap(CONCURRENT_NODE_SIZE);
        return true;
    } finally {
        stateHolder.decrementActiveClients();
    }
}
Also used : HeapTrackingLongIntHashMap(org.neo4j.collection.trackable.HeapTrackingLongIntHashMap) ActiveLock(org.neo4j.lock.ActiveLock)

Example 5 with HeapTrackingLongIntHashMap

use of org.neo4j.collection.trackable.HeapTrackingLongIntHashMap in project neo4j by neo4j.

the class ForsetiClient method getSharedLockCount.

private HeapTrackingLongIntHashMap getSharedLockCount(ResourceType resourceType) {
    HeapTrackingLongIntHashMap sharedLockCount = sharedLockCounts[resourceType.typeId()];
    if (sharedLockCount == null) {
        sharedLockCount = HeapTrackingCollections.newLongIntMap(memoryTracker);
        sharedLockCounts[resourceType.typeId()] = sharedLockCount;
    }
    return sharedLockCount;
}
Also used : HeapTrackingLongIntHashMap(org.neo4j.collection.trackable.HeapTrackingLongIntHashMap)

Aggregations

HeapTrackingLongIntHashMap (org.neo4j.collection.trackable.HeapTrackingLongIntHashMap)9 ActiveLock (org.neo4j.lock.ActiveLock)6 LockWaitEvent (org.neo4j.lock.LockWaitEvent)2