Search in sources :

Example 6 with PrimitiveLongIntMap

use of org.neo4j.collection.primitive.PrimitiveLongIntMap 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()];
        PrimitiveLongIntMap heldShareLocks = sharedLockCounts[resourceType.typeId()];
        PrimitiveLongIntMap heldExclusiveLocks = exclusiveLockCounts[resourceType.typeId()];
        int heldCount = heldShareLocks.get(resourceId);
        if (heldCount != -1) {
            // 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 waitStartMillis = clock.millis();
        while (true) {
            assertValid(waitStartMillis, 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);
        return true;
    } finally {
        stateHolder.decrementActiveClients();
    }
}
Also used : PrimitiveLongIntMap(org.neo4j.collection.primitive.PrimitiveLongIntMap) ActiveLock(org.neo4j.kernel.impl.locking.ActiveLock)

Example 7 with PrimitiveLongIntMap

use of org.neo4j.collection.primitive.PrimitiveLongIntMap 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++) {
        PrimitiveLongIntMap exclusiveLocks = exclusiveLockCounts[i];
        PrimitiveLongIntMap sharedLocks = sharedLockCounts[i];
        // been re-instated after releasing the exclusive lock).
        if (exclusiveLocks != null) {
            int size = exclusiveLocks.size();
            exclusiveLocks.visitKeys(releaseExclusiveAndClearSharedVisitor.initialize(sharedLocks, lockMaps[i]));
            if (size <= 32) {
                // 2) Safer, because we guard against clients getting giant maps over time
                if (size > 0) {
                    exclusiveLocks.clear();
                }
            } else {
                exclusiveLockCounts[i] = Primitive.longIntMap();
            }
        }
        // Then release all remaining shared locks
        if (sharedLocks != null) {
            int size = sharedLocks.size();
            sharedLocks.visitKeys(releaseSharedDontCheckExclusiveVisitor.initialize(lockMaps[i]));
            if (size <= 32) {
                // 2) Safer, because we guard against clients getting giant maps over time
                if (size > 0) {
                    sharedLocks.clear();
                }
            } else {
                sharedLockCounts[i] = Primitive.longIntMap();
            }
        }
    }
}
Also used : PrimitiveLongIntMap(org.neo4j.collection.primitive.PrimitiveLongIntMap)

Example 8 with PrimitiveLongIntMap

use of org.neo4j.collection.primitive.PrimitiveLongIntMap 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()];
        PrimitiveLongIntMap heldLocks = exclusiveLockCounts[resourceType.typeId()];
        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));
            return true;
        }
        // Grab the global lock
        ForsetiLockManager.Lock lock;
        if ((lock = lockMap.putIfAbsent(resourceId, myExclusiveLock)) != null) {
            if (lock instanceof SharedLock && sharedLockCounts[resourceType.typeId()].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);
        return true;
    } finally {
        stateHolder.decrementActiveClients();
    }
}
Also used : PrimitiveLongIntMap(org.neo4j.collection.primitive.PrimitiveLongIntMap) ActiveLock(org.neo4j.kernel.impl.locking.ActiveLock)

Example 9 with PrimitiveLongIntMap

use of org.neo4j.collection.primitive.PrimitiveLongIntMap in project neo4j by neo4j.

the class ForsetiClient method collectActiveLocks.

private static void collectActiveLocks(PrimitiveLongIntMap[] counts, List<ActiveLock> locks, ActiveLock.Factory activeLock) {
    for (int typeId = 0; typeId < counts.length; typeId++) {
        PrimitiveLongIntMap lockCounts = counts[typeId];
        if (lockCounts != null) {
            ResourceType resourceType = ResourceTypes.fromId(typeId);
            lockCounts.visitEntries((resourceId, count) -> {
                locks.add(activeLock.create(resourceType, resourceId));
                return false;
            });
        }
    }
}
Also used : PrimitiveLongIntMap(org.neo4j.collection.primitive.PrimitiveLongIntMap) ResourceType(org.neo4j.storageengine.api.lock.ResourceType)

Example 10 with PrimitiveLongIntMap

use of org.neo4j.collection.primitive.PrimitiveLongIntMap 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)

Aggregations

PrimitiveLongIntMap (org.neo4j.collection.primitive.PrimitiveLongIntMap)16 Test (org.junit.Test)7 ActiveLock (org.neo4j.kernel.impl.locking.ActiveLock)4 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)2 LockWaitEvent (org.neo4j.kernel.impl.locking.LockWaitEvent)2 HashSet (java.util.HashSet)1 ResourceType (org.neo4j.storageengine.api.lock.ResourceType)1