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