//---------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------- namespace System.Activities.DurableInstancing { using System; using System.Runtime; using System.Runtime.DurableInstancing; abstract class PersistenceTask { bool automaticallyResetTimer; AsyncCallback commandCompletedCallback; InstancePersistenceCommand instancePersistenceCommand; TimeSpan taskInterval; IOThreadTimer taskTimer; object thisLock; bool timerCancelled; TimeSpan taskTimeout; public PersistenceTask(SqlWorkflowInstanceStore store, SqlWorkflowInstanceStoreLock storeLock, InstancePersistenceCommand instancePersistenceCommand, TimeSpan taskInterval, TimeSpan taskTimeout, bool automaticallyResetTimer) { this.automaticallyResetTimer = automaticallyResetTimer; this.commandCompletedCallback = Fx.ThunkCallback(CommandCompletedCallback); this.instancePersistenceCommand = instancePersistenceCommand; this.Store = store; this.StoreLock = storeLock; this.SurrogateLockOwnerId = this.StoreLock.SurrogateLockOwnerId; this.taskInterval = taskInterval; this.thisLock = new object(); this.taskTimeout = taskTimeout; } protected SqlWorkflowInstanceStore Store { get; set; } protected SqlWorkflowInstanceStoreLock StoreLock { get; set; } protected long SurrogateLockOwnerId { get; set; } object ThisLock { get { return this.thisLock; } } public void CancelTimer() { lock (ThisLock) { this.timerCancelled = true; if (this.taskTimer != null) { this.taskTimer.Cancel(); this.taskTimer = null; } } } public void ResetTimer(bool fireImmediately) { this.ResetTimer(fireImmediately, null); } public virtual void ResetTimer(bool fireImmediately, TimeSpan? taskIntervalOverride) { TimeSpan timeTillNextPoll = this.taskInterval; if (taskIntervalOverride.HasValue) { if (taskIntervalOverride.Value < this.taskInterval) timeTillNextPoll = taskIntervalOverride.Value; } lock (ThisLock) { if (!this.timerCancelled) { if (this.taskTimer == null) { this.taskTimer = new IOThreadTimer(new Action(this.OnTimerFired), null, false); } this.taskTimer.Set(fireImmediately ? TimeSpan.Zero : timeTillNextPoll); } } } protected abstract void HandleError(Exception exception); void CommandCompletedCallback(IAsyncResult result) { SqlWorkflowInstanceStoreAsyncResult sqlResult = (SqlWorkflowInstanceStoreAsyncResult) result; try { this.Store.EndTryCommand(result); if (this.automaticallyResetTimer) { this.ResetTimer(false); } } catch (Exception exception) { if (Fx.IsFatal(exception)) { throw; } HandleError(exception); } } void OnTimerFired(object state) { if (this.StoreLock.IsLockOwnerValid(this.SurrogateLockOwnerId)) { try { this.Store.BeginTryCommandSkipRetry(null, this.instancePersistenceCommand, this.taskTimeout, this.commandCompletedCallback, null); } catch (Exception exception) { if (Fx.IsFatal(exception)) { throw; } this.HandleError(exception); } } } } }