Ejemplo n.º 1
0
        /// <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();
                }
            }
        }