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);
        }