/// <summary /> public AcquireReaderLock(Guid id, string traceInfo) { this.LockTime = 0; m_Lock = LockingManager.GetLocker(id); _id = id; if (!ConfigHelper.AllowReadLocking) { return; } this.ReadLockCount = m_Lock.CurrentReadCount; this.WaitingLocksOnEntry = m_Lock.WaitingWriteCount; if (this.WaitingLocksOnEntry > 10) { LoggerCQ.LogWarning($"AcquireReaderLock Waiting Writer Locks: Count={this.WaitingLocksOnEntry}, RepositoryId={id}, TraceInfo={traceInfo}"); } if (!m_Lock.TryEnterReadLock(TimeOut)) { _inError = true; throw new Exception("Could not get reader lock: " + ((m_Lock.ObjectId == Guid.Empty) ? string.Empty : $"ID={m_Lock.ObjectId}") + $", CurrentReadCount={m_Lock.CurrentReadCount}" + $", WaitingReadCount={m_Lock.WaitingReadCount}" + $", WaitingWriteCount={m_Lock.WaitingWriteCount}" + $", HoldingThread={m_Lock.HoldingThreadId}" + $", TraceInfo={m_Lock.TraceInfo}" + $", LockFailTime={(int)DateTime.Now.Subtract(_initTime).TotalMilliseconds}" + $", WriteHeldTime={m_Lock.WriteHeldTime}"); } this.LockTime = (int)DateTime.Now.Subtract(_initTime).TotalMilliseconds; Interlocked.Increment(ref _counter); _lockIndex = _counter; m_Lock.HeldReads.AddOrUpdate(_lockIndex, DateTime.Now, (key, value) => DateTime.Now); m_Lock.TraceInfo = traceInfo; m_Lock.HoldingThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId; }
public AcquireWriterLock(Guid id, string traceInfo) { if (id == Guid.Empty) { return; } m_Lock = LockingManager.GetLocker(id); if (!ConfigHelper.AllowWriteLocking) { return; } this.ReadLockCount = m_Lock.CurrentReadCount; this.WaitingLocksOnEntry = m_Lock.WaitingWriteCount; if (this.WaitingLocksOnEntry > 10) { LoggerCQ.LogWarning($"AcquireWriterLock Waiting Writer Locks: Count={this.WaitingLocksOnEntry}, RepositoryId={id}, TraceInfo={traceInfo}"); } //If there is another write lock held then wait to enter and give the read locks to run //This is a hack to address the issue with the lock object: it prioritizes writes and starves reads var lockHeld = false; if (traceInfo == RepositoryManager.TraceInfoUpdateData) { while (m_Lock.IsWriteLockHeld && DateTime.Now.Subtract(_initTime).TotalMilliseconds < 10000) { System.Threading.Thread.Sleep(20); lockHeld = true; } } var delay = (int)DateTime.Now.Subtract(_initTime).TotalMilliseconds; if (lockHeld) { LoggerCQ.LogDebug($"AcquireWriterLock: Held={delay}, RepositoryId={id}, TraceInfo={traceInfo}"); } var timeoutValue = TimeOut - delay; if (!m_Lock.TryEnterWriteLock(timeoutValue)) { _inError = true; RepositoryManager.SystemCore.LogLockStat(new LockInfoItem { CurrentReadCount = m_Lock.CurrentReadCount, Elapsed = (int)DateTime.Now.Subtract(_initTime).TotalMilliseconds, Failure = true, IsWriteLockHeld = m_Lock.IsWriteLockHeld, ThreadId = (m_Lock.HoldingThreadId == null) ? 0 : m_Lock.HoldingThreadId.Value, WaitingReadCount = m_Lock.WaitingReadCount, WaitingWriteCount = m_Lock.WaitingWriteCount, TraceInfo = traceInfo, }); var lapses = string.Join("-", m_Lock.HeldReads.Values.ToList().Select(x => (int)DateTime.Now.Subtract(x).TotalSeconds).ToList()); throw new Exception("Could not get writer lock: " + ((m_Lock.ObjectId == Guid.Empty) ? string.Empty : $"ID={m_Lock.ObjectId}") + $", CurrentReadCount={m_Lock.CurrentReadCount}" + $", WaitingReadCount={m_Lock.WaitingReadCount}" + $", WaitingWriteCount={m_Lock.WaitingWriteCount}" + $", HoldingThread={m_Lock.HoldingThreadId}" + $", TraceInfo={m_Lock.TraceInfo}" + $", WriteHeldTime={m_Lock.WriteHeldTime}" + $", LockFailTime={(int)DateTime.Now.Subtract(_initTime).TotalMilliseconds}" + $", Lapses={lapses}"); } this.LockTime = (int)DateTime.Now.Subtract(_initTime).TotalMilliseconds; m_Lock.TraceInfo = traceInfo; m_Lock.WriteLockHeldTime = DateTime.Now; m_Lock.HoldingThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId; }