public static void StartBatchOperation(BatchManager <TItem> .PerformFlushAsyncResult thisPtr, IList <BatchManager <TItem> .BatchedObjectsAsyncResult> batchedObjectsAsyncResults) { List <TItem> tItems = new List <TItem>(); foreach (BatchManager <TItem> .BatchedObjectsAsyncResult batchedObjectsAsyncResult in batchedObjectsAsyncResults) { TrackingContext trackingContext = batchedObjectsAsyncResult.TrackingContext; MessagingClientEtwProvider.TraceClient(() => { }); tItems.AddRange(batchedObjectsAsyncResult.BatchedObjects); } try { IAsyncResult batchedBegin = thisPtr.BatchManager.BatchedBegin(thisPtr.TrackingContext, tItems, thisPtr.transactionId, thisPtr.timeout, BatchManager <TItem> .PerformFlushAsyncResult.onFlushCompletionCallback, new Tuple <BatchManager <TItem> .PerformFlushAsyncResult, IList <BatchManager <TItem> .BatchedObjectsAsyncResult> >(thisPtr, batchedObjectsAsyncResults)); if (batchedBegin.CompletedSynchronously) { thisPtr.OnFlushCompleted(batchedBegin, batchedObjectsAsyncResults); } } catch (Exception exception1) { Exception exception = exception1; if (Fx.IsFatal(exception)) { throw; } thisPtr.TryContinueOperation(true, exception, batchedObjectsAsyncResults); } }
public static void StartGroupByBatchOperation(BatchManager <TItem> .PerformFlushAsyncResult thisPtr, IList <BatchManager <TItem> .BatchedObjectsAsyncResult> batchedObjectsAsyncResults) { ICollection <IList <BatchManager <TItem> .BatchedObjectsAsyncResult> > lists = BatchManager <TItem> .PerformFlushAsyncResult.GroupBy(batchedObjectsAsyncResults, thisPtr.BatchManager.GroupByKeySelector); Interlocked.Add(ref thisPtr.batchedResultsCount, lists.Count); foreach (IList <BatchManager <TItem> .BatchedObjectsAsyncResult> batchedObjectsAsyncResults1 in lists) { BatchManager <TItem> .PerformFlushAsyncResult.StartBatchOperation(thisPtr, batchedObjectsAsyncResults1); } }
public PerformFlushAsyncResult(TrackingContext trackingContext, BatchManager <TItem> batchManager, List <BatchManager <TItem> .BatchedObjectsAsyncResult> batchedResults, string transactionId, TimeSpan timeout, AsyncCallback callback, object state) : base(callback, state) { this.trackingContext = trackingContext; this.BatchManager = batchManager; this.startBatchOperation = this.BatchManager.StartBatchOperation; this.batchedResults = batchedResults; this.timeout = timeout; this.batchedResultsCount = 0; this.transactionId = transactionId; this.isInTransaction = transactionId != null; }
public BatchManagerAsyncResult(TrackingContext trackingContext, BatchManager <T> batchManager, IEnumerable <T> msgs, TimeSpan timeout, AsyncCallback callback, object state) : base(callback, state) { if (trackingContext == null) { throw Fx.Exception.ArgumentNull("trackingContext"); } this.BatchManager = batchManager; if (base.SyncContinue(this.BatchManager.BeginBatchedOperation(trackingContext, msgs, timeout, base.PrepareAsyncCompletion(BatchManagerAsyncResult <T> .onBatchedCompletion), this))) { base.Complete(true); } }
private void CompleteSingleOperation(BatchManager <TItem> .BatchedObjectsAsyncResult singleOperation, Exception delayedException) { if (delayedException != null) { this.completionException = delayedException; MessagingClientEtwProvider.TraceClient(() => MessagingClientEtwProvider.Provider.EventWriteBatchManagerException(this.TrackingContext.Activity, this.TrackingContext.TrackingId, this.TrackingContext.SystemTracker, "BatchManager.PerformFlushAsyncResult.CompleteSingleOperation", delayedException.ToStringSlim())); } IOThreadScheduler.ScheduleCallbackNoFlow((object s) => singleOperation.CompleteBatch(delayedException), null); if (Interlocked.Decrement(ref this.batchedResultsCount) == 0) { base.Complete(false, this.completionException); } }
private BatchManager <TItem> .PerformFlushAsyncResult BeginFlush(TrackingContext trackingContext, TimeSpan closeTimeout, AsyncCallback callback, object state) { this.isTimerSet = false; if (this.pendingBatchSize == this.batchOverheadSize) { return(null); } List <BatchManager <TItem> .BatchedObjectsAsyncResult> batchedObjectsAsyncResults = new List <BatchManager <TItem> .BatchedObjectsAsyncResult>(); TimeSpan remainingTime = closeTimeout; int num = 0; while (this.batchedResults.Count > 0) { BatchManager <TItem> .BatchedObjectsAsyncResult batchedObjectsAsyncResult = this.batchedResults.Peek(); int batchSize = batchedObjectsAsyncResult.BatchSize; if (batchedObjectsAsyncResult.RemainingTime > TimeSpan.Zero) { if ((long)(num + batchSize) > this.maximumBatchSize) { break; } if (batchedObjectsAsyncResult.RemainingTime < remainingTime) { remainingTime = batchedObjectsAsyncResult.RemainingTime; } batchedObjectsAsyncResults.Add(batchedObjectsAsyncResult); num = num + batchSize; this.batchedResults.Dequeue(); } else { ActionItem.Schedule((object s) => batchedObjectsAsyncResult.CompleteBatch(new TimeoutException()), null); BatchManager <TItem> batchManager = this; batchManager.pendingBatchSize = batchManager.pendingBatchSize - batchSize; this.batchedResults.Dequeue(); } } BatchManager <TItem> batchManager1 = this; batchManager1.pendingBatchSize = batchManager1.pendingBatchSize - num; if (this.pendingBatchSize > this.batchOverheadSize) { this.SetFlushTimer((long)this.pendingBatchSize >= this.flushThreshold); } if (batchedObjectsAsyncResults.Count <= 0) { return(null); } return(new BatchManager <TItem> .PerformFlushAsyncResult(trackingContext, this, batchedObjectsAsyncResults, null, remainingTime, callback, state)); }
void System.Transactions.IEnlistmentNotification.Prepare(PreparingEnlistment enlistment) { List <BatchManager <TItem> .BatchedObjectsAsyncResult> list; lock (this.batchManager.syncTransactionLock) { list = this.batchManager.transactionalBatchResults[this.transactionIdentifier].ToList <BatchManager <TItem> .BatchedObjectsAsyncResult>(); } TimeSpan maxValue = TimeSpan.MaxValue; foreach (BatchManager <TItem> .BatchedObjectsAsyncResult batchedObjectsAsyncResult in list) { if (batchedObjectsAsyncResult.RemainingTime >= maxValue) { continue; } maxValue = batchedObjectsAsyncResult.RemainingTime; } this.preparingEnlistment = enlistment; this.prepareCalled = true; try { BatchManager <TItem> .PerformFlushAsyncResult performFlushAsyncResult = new BatchManager <TItem> .PerformFlushAsyncResult(this.trackingContext, this.batchManager, list, this.transactionIdentifier, maxValue, BatchManager <TItem> .BatchNotification.onFlushCompleted, this); performFlushAsyncResult.StartOperation(); } catch (Exception exception1) { Exception exception = exception1; if (Fx.IsFatal(exception)) { throw; } MessagingClientEtwProvider.TraceClient(() => MessagingClientEtwProvider.Provider.EventWriteBatchManagerException(this.trackingContext.Activity, this.trackingContext.TrackingId, this.trackingContext.SystemTracker, string.Format(CultureInfo.InvariantCulture, "BatchManager<T>.BatchNotification.Prepare Rollback. Transaction ID: {0}", new object[] { this.transactionIdentifier }), exception.ToStringSlim())); TransactionResultManager.Instance.SetTransactionResult(this.transactionIdentifier, exception, this.trackingContext); try { this.preparingEnlistment.ForceRollback(exception); } catch (InvalidOperationException invalidOperationException1) { InvalidOperationException invalidOperationException = invalidOperationException1; MessagingClientEtwProvider.TraceClient(() => MessagingClientEtwProvider.Provider.EventWriteBatchManagerException(this.trackingContext.Activity, this.trackingContext.TrackingId, this.trackingContext.SystemTracker, "BatchManager<T>.BatchNotification.Prepare.ForceRollback", invalidOperationException.ToStringSlim())); } } }
protected override void OnAbort() { if (this.flushTimer != null) { this.flushTimer.Cancel(); } lock (this.syncLock) { foreach (BatchManager <TItem> .BatchedObjectsAsyncResult batchedResult in this.batchedResults) { BatchManager <TItem> .BatchedObjectsAsyncResult batchedObjectsAsyncResult = batchedResult; ActionItem.Schedule((object s) => batchedObjectsAsyncResult.CompleteBatch(new CommunicationObjectAbortedException(SRClient.BatchManagerAborted)), null); } this.batchedResults.Clear(); this.pendingBatchSize = 0; } }
private void EndFlush(IAsyncResult result) { try { BatchManager <TItem> .PerformFlushAsyncResult.End(result); } catch (Exception exception1) { Exception exception = exception1; if (Fx.IsFatal(exception)) { throw; } BatchManager <TItem> .PerformFlushAsyncResult performFlushAsyncResult = (BatchManager <TItem> .PerformFlushAsyncResult)result; MessagingClientEtwProvider.TraceClient(() => MessagingClientEtwProvider.Provider.EventWriteBatchManagerException(performFlushAsyncResult.TrackingContext.Activity, performFlushAsyncResult.TrackingContext.TrackingId, performFlushAsyncResult.TrackingContext.SystemTracker, "BatchManager.EndFlush", exception.ToStringSlim())); } }
protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state) { TrackingContext instance = TrackingContext.GetInstance(Guid.NewGuid()); BatchManager <TItem> .PerformFlushAsyncResult performFlushAsyncResult = null; lock (this.syncLock) { if (this.flushTimer.Cancel()) { performFlushAsyncResult = this.BeginFlush(instance, timeout, callback, state); } } if (performFlushAsyncResult != null) { performFlushAsyncResult.StartOperation(); return(performFlushAsyncResult); } return(new CompletedAsyncResult(callback, state)); }
private static void OnFlushCompleted(IAsyncResult result) { BatchManager <TItem> .BatchNotification asyncState = (BatchManager <TItem> .BatchNotification)result.AsyncState; bool flag = false; try { BatchManager <TItem> .PerformFlushAsyncResult.End(result); flag = true; } catch (Exception exception1) { Exception exception = exception1; if (Fx.IsFatal(exception)) { throw; } MessagingClientEtwProvider.TraceClient(() => MessagingClientEtwProvider.Provider.EventWriteBatchManagerException(asyncState.trackingContext.Activity, asyncState.trackingContext.TrackingId, asyncState.trackingContext.SystemTracker, "BatchManager<T>.BatchNotification.OnFlushCompleted", exception.ToStringSlim())); TransactionResultManager.Instance.SetTransactionResult(asyncState.transactionIdentifier, exception, asyncState.trackingContext); try { asyncState.preparingEnlistment.ForceRollback(exception); } catch (InvalidOperationException invalidOperationException1) { InvalidOperationException invalidOperationException = invalidOperationException1; MessagingClientEtwProvider.TraceClient(() => MessagingClientEtwProvider.Provider.EventWriteBatchManagerException(asyncState.trackingContext.Activity, asyncState.trackingContext.TrackingId, asyncState.trackingContext.SystemTracker, "BatchManager<T>.BatchNotification.OnFlushCompleted.ForceRollback", invalidOperationException.ToStringSlim())); } } lock (asyncState.batchManager.syncTransactionLock) { asyncState.batchManager.transactionalBatchResults.Remove(asyncState.transactionIdentifier); } if (asyncState.batchManager.OnTransactionStateChanged != null) { asyncState.batchManager.OnTransactionStateChanged(asyncState.trackingContext, asyncState.transactionIdentifier, (flag ? TransactionCommitStatus.Committed : TransactionCommitStatus.Aborted)); } if (flag) { asyncState.preparingEnlistment.Prepared(); } }
public BatchManager(BeginBatchedDelegate <TItem> batchedBeginOperation, EndBatchedDelegate batchedEndOperation, CalculateBatchSizeDelegate <TItem> calculateBatchSize, OnRetryDelegate <TItem> onRetryOperation, TransactionStateChangedDelegate transactionStateChanged, TransactionCompletedEventHandler transactionCompletedEventHandler, long flushThreshold, long maximumBatchSize, int batchOverheadSize) { this.StartBatchOperation = new BatchManager <TItem> .StartBatchOperationDelegate(BatchManager <TItem> .PerformFlushAsyncResult.StartBatchOperation); this.BatchedBegin = batchedBeginOperation; this.BatchedEnd = batchedEndOperation; this.CalculateBatchSize = calculateBatchSize; this.OnRetry = onRetryOperation; this.OnTransactionStateChanged = transactionStateChanged; this.transactionCompletedEventHandler = transactionCompletedEventHandler; this.batchedResults = new Queue <BatchManager <TItem> .BatchedObjectsAsyncResult>(); this.transactionalBatchResults = new Dictionary <string, Queue <BatchManager <TItem> .BatchedObjectsAsyncResult> >(); this.flushTimer = new IOThreadTimer(BatchManager <TItem> .flushTimerCallback, this, false); this.flushThreshold = flushThreshold; this.maximumBatchSize = maximumBatchSize; this.pendingBatchSize = batchOverheadSize; this.batchOverheadSize = batchOverheadSize; this.syncLock = new object(); this.syncTransactionLock = new object(); }
private void OnSingleOperationCompleted(IAsyncResult result) { Exception exception = null; BatchManager <TItem> .BatchedObjectsAsyncResult item2 = ((Tuple <BatchManager <TItem> .PerformFlushAsyncResult, BatchManager <TItem> .BatchedObjectsAsyncResult>)result.AsyncState).Item2; try { this.BatchManager.BatchedEnd(result, true); } catch (Exception exception2) { Exception exception1 = exception2; if (Fx.IsFatal(exception1)) { throw; } exception = exception1; } this.CompleteSingleOperation(item2, exception); }
private static void OnFlushTimerFired(object state) { BatchManager <TItem> .PerformFlushAsyncResult performFlushAsyncResult; TrackingContext instance = TrackingContext.GetInstance(Guid.NewGuid()); BatchManager <TItem> batchManager = (BatchManager <TItem>)state; if (batchManager.State == CommunicationState.Opened) { lock (batchManager.syncLock) { performFlushAsyncResult = batchManager.BeginFlush(instance, TimeSpan.MaxValue, BatchManager <TItem> .flushCompleteCallback, batchManager); } if (performFlushAsyncResult != null) { performFlushAsyncResult.StartOperation(); if (performFlushAsyncResult.CompletedSynchronously) { batchManager.EndFlush(performFlushAsyncResult); } } } }
private bool ShouldRetry(Exception delayedException, BatchManager <TItem> .BatchedObjectsAsyncResult singleOperation, bool isMultiCommandBatch) { bool onRetry = this.BatchManager.OnRetry == null; if (!onRetry) { try { onRetry = this.BatchManager.OnRetry(singleOperation.BatchedObjects, delayedException, isMultiCommandBatch); } catch (Exception exception1) { Exception exception = exception1; if (Fx.IsFatal(exception)) { throw; } MessagingClientEtwProvider.TraceClient(() => MessagingClientEtwProvider.Provider.EventWriteHandledExceptionWarning(exception.ToStringSlim())); onRetry = false; } } return(onRetry); }
public BatchNotification(TrackingContext trackingContext, BatchManager <TItem> batchManager, string transactionIdentifier) { this.trackingContext = trackingContext; this.batchManager = batchManager; this.transactionIdentifier = transactionIdentifier; }
public IAsyncResult BeginBatchedOperation(TrackingContext trackingContext, IEnumerable <TItem> batchItems, TimeSpan timeout, AsyncCallback callback, object state) { base.ThrowIfDisposedOrNotOpen(); if (!batchItems.Any <TItem>()) { return(new CompletedAsyncResult(callback, state)); } Transaction current = Transaction.Current; int calculateBatchSize = this.CalculateBatchSize(batchItems); if (current != null) { string localIdentifier = current.TransactionInformation.LocalIdentifier; BatchManager <TItem> .BatchedObjectsAsyncResult batchedObjectsAsyncResult = new BatchManager <TItem> .BatchedObjectsAsyncResult(trackingContext, batchItems, calculateBatchSize, timeout, BatchManager <TItem> .transactionObjectCompleteCallback, state); lock (this.syncTransactionLock) { if (this.transactionalBatchResults.ContainsKey(localIdentifier)) { this.transactionalBatchResults[localIdentifier].Enqueue(batchedObjectsAsyncResult); } else { if (this.transactionCompletedEventHandler != null) { current.TransactionCompleted += this.transactionCompletedEventHandler; } current.EnlistVolatile(new BatchManager <TItem> .BatchNotification(trackingContext, this, localIdentifier), EnlistmentOptions.EnlistDuringPrepareRequired); Queue <BatchManager <TItem> .BatchedObjectsAsyncResult> batchedObjectsAsyncResults = new Queue <BatchManager <TItem> .BatchedObjectsAsyncResult>(); batchedObjectsAsyncResults.Enqueue(batchedObjectsAsyncResult); this.transactionalBatchResults.Add(localIdentifier, batchedObjectsAsyncResults); } } return(new CompletedAsyncResult(callback, state)); } if ((long)(this.batchOverheadSize + calculateBatchSize) >= this.maximumBatchSize) { return(this.BatchedBegin(trackingContext, batchItems, null, timeout, callback, state)); } BatchManager <TItem> .BatchedObjectsAsyncResult batchedObjectsAsyncResult1 = new BatchManager <TItem> .BatchedObjectsAsyncResult(trackingContext, batchItems, calculateBatchSize, timeout, callback, state); BatchManager <TItem> .PerformFlushAsyncResult performFlushAsyncResult = null; lock (this.syncLock) { this.batchedResults.Enqueue(batchedObjectsAsyncResult1); BatchManager <TItem> batchManager = this; batchManager.pendingBatchSize = batchManager.pendingBatchSize + calculateBatchSize; if ((long)this.pendingBatchSize >= this.flushThreshold) { if (!this.isTimerSet || this.flushTimer.Cancel()) { performFlushAsyncResult = this.BeginFlush(trackingContext, TimeSpan.MaxValue, BatchManager <TItem> .flushCompleteCallback, this); } } else if (!this.isTimerSet) { this.SetFlushTimer(false); } } if (performFlushAsyncResult != null) { performFlushAsyncResult.StartOperation(); if (performFlushAsyncResult.CompletedSynchronously) { this.EndFlush(performFlushAsyncResult); } } return(batchedObjectsAsyncResult1); }