/// <summary> /// Attempt to upgrade a share lock that we hold to an exclusive lock. </summary> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: private boolean tryUpgradeToExclusiveWithShareLockHeld(org.neo4j.storageengine.api.lock.LockTracer tracer, org.neo4j.storageengine.api.lock.LockWaitEvent priorEvent, org.neo4j.storageengine.api.lock.ResourceType resourceType, long resourceId, SharedLock sharedLock, int tries, long waitStartMillis) throws org.neo4j.storageengine.api.lock.AcquireLockTimeoutException private bool TryUpgradeToExclusiveWithShareLockHeld(LockTracer tracer, LockWaitEvent priorEvent, ResourceType resourceType, long resourceId, SharedLock sharedLock, int tries, long waitStartMillis) { 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); } WaitFor(sharedLock, resourceType, resourceId, true, tries++); } return(true); } catch (Exception e) { sharedLock.ReleaseUpdateLock(); if (e is DeadlockDetectedException || e is LockClientStoppedException) { throw ( Exception )e; } throw new TransactionFailureException("Failed to upgrade shared lock to exclusive: " + sharedLock, e); } finally { if (waitEvent != null) { waitEvent.Close(); } ClearWaitList(); _waitingForLock = null; } } return(false); }
/// <summary> /// 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 <seealso cref="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 /// <seealso cref="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 /// </summary> /// <returns> true is lock was acquired, false otherwise </returns> /// <exception cref="DeadlockDetectedException"> if a deadlock is detected </exception> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: synchronized boolean acquireWriteLock(org.neo4j.storageengine.api.lock.LockTracer tracer, Object tx) throws org.neo4j.kernel.DeadlockDetectedException internal virtual bool AcquireWriteLock(LockTracer tracer, object tx) { lock (this) { 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 bool addLockRequest = true; try { tle.IncrementRequests(); Thread currentThread = currentThread(); long lockAcquisitionTimeBoundary = _clock.millis() + _lockAcquisitionTimeoutMillis; while (!tle.Terminated && (_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.Terminated) { RegisterWriteLockAcquired(tx, tle); return(true); } else { // in case if lock element was interrupted and it was never register before // we need to clean it from lock element map // if it was register before it will be cleaned up during standard lock release call if (tle.Requests == 1 && tle.Free) { _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(); } } }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: public void acquireExclusive(org.neo4j.storageengine.api.lock.LockTracer tracer, org.neo4j.storageengine.api.lock.ResourceType resourceType, long... resourceIds) throws org.neo4j.storageengine.api.lock.AcquireLockTimeoutException public override void AcquireExclusive(LockTracer tracer, ResourceType resourceType, params long[] resourceIds) { _hasLocks = true; _stateHolder.incrementActiveClients(this); LockWaitEvent waitEvent = null; try { ConcurrentMap <long, ForsetiLockManager.Lock> lockMap = _lockMaps[resourceType.TypeId()]; MutableLongIntMap heldLocks = _exclusiveLockCounts[resourceType.TypeId()]; foreach (long resourceId in resourceIds) { int heldCount = heldLocks.getIfAbsent(resourceId, -1); if (heldCount != -1) { // 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 waitStartMillis = _clock.millis(); while ((existingLock = lockMap.putIfAbsent(resourceId, _myExclusiveLock)) != null) { AssertValid(waitStartMillis, resourceType, resourceId); // If this is a shared lock: // Given a grace period of tries (to try and not starve readers), grab an update lock and wait // for it to convert to an exclusive lock. if (tries > 50 && existingLock is 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); } WaitFor(existingLock, resourceType, resourceId, true, tries++); } heldLocks.put(resourceId, 1); } } finally { if (waitEvent != null) { waitEvent.Close(); } ClearWaitList(); _waitingForLock = null; _stateHolder.decrementActiveClients(); } }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: public void acquireShared(org.neo4j.storageengine.api.lock.LockTracer tracer, org.neo4j.storageengine.api.lock.ResourceType resourceType, long... resourceIds) throws org.neo4j.storageengine.api.lock.AcquireLockTimeoutException public override void AcquireShared(LockTracer tracer, ResourceType resourceType, params long[] resourceIds) { _hasLocks = true; _stateHolder.incrementActiveClients(this); LockWaitEvent waitEvent = null; try { // Grab the global lock map we will be using ConcurrentMap <long, ForsetiLockManager.Lock> lockMap = _lockMaps[resourceType.TypeId()]; // And grab our local lock maps MutableLongIntMap heldShareLocks = _sharedLockCounts[resourceType.TypeId()]; MutableLongIntMap heldExclusiveLocks = _exclusiveLockCounts[resourceType.TypeId()]; foreach (long resourceId in resourceIds) { // First, check if we already hold this as a shared lock int heldCount = heldShareLocks.getIfAbsent(resourceId, -1); if (heldCount != -1) { // We already have a lock on this, just increment our local reference counter. heldShareLocks.put(resourceId, Math.incrementExact(heldCount)); continue; } // Second, check if we hold it as an exclusive lock 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); continue; } // We don't hold the lock, so we need to grab it via the global lock map int tries = 0; SharedLock mySharedLock = null; long waitStartMillis = _clock.millis(); // Retry loop while (true) { AssertValid(waitStartMillis, resourceType, resourceId); // Check if there is a lock for this entity in the map ForsetiLockManager.Lock existingLock = lockMap.get(resourceId); // No lock if (existingLock == null) { // Try to create a new shared lock if (mySharedLock == null) { mySharedLock = new SharedLock(this); } if (lockMap.putIfAbsent(resourceId, mySharedLock) == null) { // Success, we now hold the shared lock. break; } else { continue; } } // Someone holds shared lock on this entity, try and get in on that action else if (existingLock is SharedLock) { if ((( SharedLock )existingLock).Acquire(this)) { // Success! break; } } // Someone holds an exclusive lock on this entity else if (existingLock is ExclusiveLock) { // We need to wait, just let the loop run. } else { throw new System.NotSupportedException("Unknown lock type: " + existingLock); } if (waitEvent == null) { waitEvent = tracer.WaitForLock(false, resourceType, resourceId); } // And take note of who we are waiting for. This is used for deadlock detection. WaitFor(existingLock, resourceType, resourceId, false, tries++); } // Make a local note about the fact that we now hold this lock heldShareLocks.put(resourceId, 1); } } finally { if (waitEvent != null) { waitEvent.Close(); } ClearWaitList(); _waitingForLock = null; _stateHolder.decrementActiveClients(); } }