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();
}
}
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();
}
}
}
}
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();
}
}
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;
});
}
}
}
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();
}
}
Aggregations