//----------------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- namespace System.Activities.DurableInstancing { using System; using System.Collections.Generic; using System.Runtime; using System.Runtime.DurableInstancing; sealed class LoadRetryHandler { BinaryHeap retryQueue; object syncLock; IOThreadTimer retryThreadTimer; public LoadRetryHandler() { this.retryQueue = new BinaryHeap(); this.syncLock = new object(); this.retryThreadTimer = new IOThreadTimer(new Action(this.OnRetryTimer), null, false); } public bool Enqueue(LoadRetryAsyncResult command) { bool firstInQueue = false; DateTime retryTime = DateTime.UtcNow.Add(command.RetryTimeout); lock (this.syncLock) { firstInQueue = this.retryQueue.Enqueue(retryTime, command); } if (firstInQueue) { this.retryThreadTimer.Set(command.RetryTimeout); } return true; } public void AbortPendingRetries() { this.retryThreadTimer.Cancel(); ICollection> result; lock (this.syncLock) { result = this.retryQueue.RemoveAll(x => x.Value != null); } foreach (KeyValuePair value in result) { ActionItem.Schedule ( (data) => { LoadRetryAsyncResult tryCommandResult = data as LoadRetryAsyncResult; tryCommandResult.AbortRetry(); }, value.Value ); } } void OnRetryTimer(object state) { TimeSpan waitTime = TimeSpan.Zero; ICollection> retryList; bool retriesPending = false; lock (this.syncLock) { if (!this.retryQueue.IsEmpty) { DateTime currentTime = DateTime.UtcNow; DateTime expirationTime = retryQueue.Peek().Key; if (currentTime.CompareTo(expirationTime) >= 0) { retriesPending = true; } else { waitTime = expirationTime.Subtract(currentTime); } } } if (retriesPending) { lock (this.syncLock) { DateTime currentTime = DateTime.UtcNow; retryList = retryQueue.TakeWhile(x => currentTime.CompareTo(x) >= 0); if (!this.retryQueue.IsEmpty) { DateTime expirationTime = this.retryQueue.Peek().Key; waitTime = expirationTime.Subtract(currentTime); } } foreach (KeyValuePair retry in retryList) { retry.Value.Retry(); } } if (waitTime != TimeSpan.Zero) { this.retryThreadTimer.Set(waitTime); } } } }