private NotificationManager.AsyncEvent GetNextEvent()
        {
            IAsyncCommand asyncCommand = this.command;

            NotificationManager.AsyncEvent result;
            lock (this.eventQueue)
            {
                if (this.eventQueue.Count > 0)
                {
                    NotificationManager.AsyncEvent asyncEvent = this.eventQueue.Peek();
                    if ((asyncCommand != null && !asyncCommand.ProcessingEventsEnabled) || (asyncEvent.Command != null && !asyncEvent.Command.ProcessingEventsEnabled))
                    {
                        result = null;
                    }
                    else
                    {
                        result = this.eventQueue.Dequeue();
                    }
                }
                else
                {
                    result = null;
                }
            }
            return(result);
        }
        private bool EnqueueEvent(NotificationManager.AsyncEvent evt)
        {
            bool result;

            lock (this.eventQueue)
            {
                if (this.disposed && evt.Type != NotificationManager.AsyncEventType.Release)
                {
                    result = false;
                }
                else if (evt.Type == NotificationManager.AsyncEventType.Acquire && (!this.subscriptionCanBeTaken || ExDateTime.UtcNow > this.policyExpirationTime))
                {
                    result = false;
                }
                else
                {
                    if (evt.Type != NotificationManager.AsyncEventType.Timeout && evt.Type != NotificationManager.AsyncEventType.Acquire && evt.Type != NotificationManager.AsyncEventType.Release)
                    {
                        this.subscriptionCanBeTaken = false;
                        this.EnqueueDiagOperation(NotificationManager.DiagnosticEvent.Locked);
                    }
                    this.eventQueue.Enqueue(evt);
                    AirSyncDiagnostics.TraceDebug <string, string>(ExTraceGlobals.ThreadingTracer, this, "Enqueue event for {0}. processingEnabled:{1}", this.uniqueId, (this.command == null) ? "<null command>" : this.command.ProcessingEventsEnabled.ToString());
                    if (this.command == null || this.command.ProcessingEventsEnabled)
                    {
                        this.ProcessQueuedEvents(null);
                    }
                    result = true;
                }
            }
            return(result);
        }
 private void ProcessAccountTerminated(NotificationManager.AsyncEvent evt)
 {
     this.EnqueueDiagOperation(NotificationManager.DiagnosticEvent.AccountTerminated);
     if (this.command == null)
     {
         AirSyncDiagnostics.TraceDebug <string>(ExTraceGlobals.ThreadingTracer, this, "Account terminated after XSO event callback for {0}, but command is not available. Calling Kill", this.uniqueId);
         this.Kill();
         return;
     }
     this.command.HandleAccountTerminated(evt);
     AirSyncDiagnostics.TraceDebug <string>(ExTraceGlobals.ThreadingTracer, this, "Account terminated after XSO event callback for {0}. calling Command.HandleAccountTerminated", this.uniqueId);
 }
 private void ProcessXsoEventAvailable(NotificationManager.AsyncEvent evt, IBudget budget)
 {
     Interlocked.Increment(ref this.totalXsoEvents);
     this.EnqueueDiagOperation(NotificationManager.DiagnosticEvent.XsoEvent, new EventType?(evt.Event.EventType), new EventObjectType?(evt.Event.ObjectType), null);
     if (this.command == null)
     {
         AirSyncDiagnostics.TraceDebug <string>(ExTraceGlobals.ThreadingTracer, this, "XSO event available for {0}, but command is not available. Calling Kill", this.uniqueId);
         this.Kill();
         return;
     }
     budget.CheckOverBudget();
     this.command.Consume(evt.Event);
     AirSyncDiagnostics.TraceDebug <string>(ExTraceGlobals.ThreadingTracer, this, "XSO event available for {0}. calling Command.Consume", this.uniqueId);
 }
 private void ProcessAcquire(NotificationManager.AsyncEvent evt)
 {
     Interlocked.Increment(ref this.totalAcquires);
     this.EnqueueDiagOperation(NotificationManager.DiagnosticEvent.Acquired);
     if (this.command != null)
     {
         AirSyncDiagnostics.TraceDebug <string>(ExTraceGlobals.ThreadingTracer, this, "Release notificationManager for {0}", this.uniqueId);
         this.command.ReleaseNotificationManager(true);
     }
     this.command = evt.Command;
     AirSyncDiagnostics.TraceDebug <string>(ExTraceGlobals.ThreadingTracer, this, "Acquiring notification manager for {0}", this.uniqueId);
     if (this.RequestedWaitTime > 0U && this.command != null)
     {
         this.InternalStartTimer(this.command.Context.RequestTime, this.RequestedWaitTime);
     }
 }
 private void ProcessRelease(NotificationManager.AsyncEvent evt)
 {
     Interlocked.Increment(ref this.totalReleases);
     this.EnqueueDiagOperation(NotificationManager.DiagnosticEvent.Released);
     evt.Command.ReleaseNotificationManager(false);
     if (this.command == evt.Command)
     {
         this.command = null;
         if (this.RequestedWaitTime > 0U && !this.disposed)
         {
             this.InternalStartTimer(ExDateTime.UtcNow, 120U);
             return;
         }
         this.Kill();
         AirSyncDiagnostics.TraceDebug <string>(ExTraceGlobals.ThreadingTracer, this, "Release & killing {0}", this.uniqueId);
     }
 }
 private void ProcessXsoException(NotificationManager.AsyncEvent evt)
 {
     Interlocked.Increment(ref this.totalXsoExceptions);
     this.EnqueueDiagOperation(NotificationManager.DiagnosticEvent.XsoException, null, null, evt.Exception);
     if (this.command == null)
     {
         if (!this.InternalHandleException(evt.Exception))
         {
             throw evt.Exception;
         }
     }
     else
     {
         AirSyncDiagnostics.TraceDebug <string>(ExTraceGlobals.ThreadingTracer, this, "XSO exception event available for {0}. calling Command.HandleException", this.uniqueId);
         this.command.HandleException(evt.Exception);
     }
 }
        private void Kill()
        {
            Interlocked.Increment(ref this.totalKills);
            if (this.disposed)
            {
                return;
            }
            AirSyncDiagnostics.TraceDebug <string>(ExTraceGlobals.ThreadingTracer, this, "Processing Kill event for {0}", this.uniqueId);
            lock (NotificationManager.notificationManagerCache)
            {
                NotificationManager notificationManager;
                if (NotificationManager.notificationManagerCache.TryGetValue(this.uniqueId, out notificationManager) && notificationManager == this)
                {
                    notificationManager.EnqueueDiagOperation(NotificationManager.DiagnosticEvent.Removed);
                    NotificationManager.notificationManagerCache.Remove(this.uniqueId);
                    AirSyncCounters.NumberOfNotificationManagerInCache.RawValue = (long)NotificationManager.notificationManagerCache.Count;
                }
            }
            NotificationManager notificationManager2 = null;

            if (NotificationManager.removedInstances.TryGetValue(this.uniqueId, out notificationManager2) && notificationManager2 == this)
            {
                NotificationManager.removedInstances.TryRemove(this.uniqueId, out notificationManager2);
            }
            this.EnqueueDiagOperation(NotificationManager.DiagnosticEvent.Killed);
            lock (this.eventQueue)
            {
                GC.SuppressFinalize(this);
                this.subscriptionCanBeTaken = false;
                this.EnqueueDiagOperation(NotificationManager.DiagnosticEvent.Locked);
                if (this.disposeTracker != null)
                {
                    this.disposeTracker.Dispose();
                    this.disposeTracker = null;
                }
                if (this.timer != null)
                {
                    this.timer.Dispose();
                    this.timer = null;
                }
                if (this.eventSubscriptions.Count > 0)
                {
                    foreach (EventSubscription eventSubscription in this.eventSubscriptions)
                    {
                        eventSubscription.Dispose();
                    }
                    this.eventSubscriptions.Clear();
                }
                List <NotificationManager.AsyncEvent> list = new List <NotificationManager.AsyncEvent>(this.eventSubscriptions.Count + 1);
                if (this.command != null)
                {
                    NotificationManager.AsyncEvent item = new NotificationManager.AsyncEvent(NotificationManager.AsyncEventType.Release, this.command);
                    list.Add(item);
                }
                foreach (NotificationManager.AsyncEvent asyncEvent in this.eventQueue)
                {
                    if (asyncEvent.Type == NotificationManager.AsyncEventType.Acquire)
                    {
                        AirSyncDiagnostics.TraceDebug <string>(ExTraceGlobals.ThreadingTracer, this, "Changing Acquire into a Release for {0}", this.uniqueId);
                        asyncEvent.Type = NotificationManager.AsyncEventType.Release;
                        list.Add(asyncEvent);
                    }
                    else if (asyncEvent.Type == NotificationManager.AsyncEventType.Release)
                    {
                        list.Add(asyncEvent);
                    }
                    else
                    {
                        AirSyncDiagnostics.TraceDebug <NotificationManager.AsyncEventType, string>(ExTraceGlobals.ThreadingTracer, this, "Ignoring event {0} after a Kill for {1}", asyncEvent.Type, this.uniqueId);
                    }
                }
                this.eventQueue.Clear();
                foreach (NotificationManager.AsyncEvent item2 in list)
                {
                    this.eventQueue.Enqueue(item2);
                }
                this.disposed = true;
            }
        }
 public void ReleaseCommand(IAsyncCommand command)
 {
     AirSyncDiagnostics.TraceDebug <string>(ExTraceGlobals.ThreadingTracer, this, "Release Command for {0}", this.uniqueId);
     NotificationManager.AsyncEvent evt = new NotificationManager.AsyncEvent(NotificationManager.AsyncEventType.Release, command);
     this.EnqueueEvent(evt);
 }
        public void ProcessQueuedEvents(IAsyncCommand callingCommand)
        {
            NotificationManager.AsyncEvent asyncEvent = null;
            if (this.currentlyExecuting)
            {
                AirSyncDiagnostics.TraceDebug <string>(ExTraceGlobals.RequestsTracer, this, "ProcessQueuedEvents.UniqueId:{0}.  Already processing event.  Exiting.", this.uniqueId);
                return;
            }
            lock (this.eventQueue)
            {
                if (this.currentlyExecuting)
                {
                    AirSyncDiagnostics.TraceDebug <string>(ExTraceGlobals.RequestsTracer, this, "ProcessQueuedEvents.UniqueId:{0}.  Already processing event.  Exiting.", this.uniqueId);
                    return;
                }
                this.currentlyExecuting = true;
            }
            IBudget budget = null;

            try
            {
                this.EnqueueDiagOperation(NotificationManager.DiagnosticEvent.RunStart);
                budget = StandardBudget.Acquire(this.budgetKey);
                lock (this.eventQueue)
                {
                    if (callingCommand != null)
                    {
                        callingCommand.ProcessingEventsEnabled = true;
                    }
                    AirSyncDiagnostics.TraceDebug <string, string, int>(ExTraceGlobals.RequestsTracer, this, "ProcessQueuedEvents.UniqueId:{0}, ProcessingEnabled: {1}, eventQueue count:{2}.", this.uniqueId, (callingCommand == null) ? "<null command>" : "true", this.eventQueue.Count);
                    asyncEvent = this.GetNextEvent();
                }
                IAsyncCommand cmd   = null;
                bool          flag3 = asyncEvent != null;
                while (flag3)
                {
                    try
                    {
                        cmd = this.StartCommandContext();
                        AirSyncDiagnostics.TraceDebug <NotificationManager.AsyncEventType, string, bool>(ExTraceGlobals.ThreadingTracer, this, "Processing event {0} for {1}. Command is null? {2}", asyncEvent.Type, this.uniqueId, this.command == null);
                        switch (asyncEvent.Type)
                        {
                        case NotificationManager.AsyncEventType.XsoEventAvailable:
                            this.ProcessXsoEventAvailable(asyncEvent, budget);
                            break;

                        case NotificationManager.AsyncEventType.XsoException:
                            this.ProcessXsoException(asyncEvent);
                            break;

                        case NotificationManager.AsyncEventType.Timeout:
                            this.ProcessTimeout(budget);
                            break;

                        case NotificationManager.AsyncEventType.Acquire:
                            this.ProcessAcquire(asyncEvent);
                            break;

                        case NotificationManager.AsyncEventType.Release:
                            this.ProcessRelease(asyncEvent);
                            break;

                        case NotificationManager.AsyncEventType.Kill:
                            this.Kill();
                            break;

                        case NotificationManager.AsyncEventType.AccountTerminated:
                            this.ProcessAccountTerminated(asyncEvent);
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                        AirSyncDiagnostics.TraceDebug <string, string>(ExTraceGlobals.ThreadingTracer, this, "Exception in processQueuedEvents for {0}. Exception:{1}", this.uniqueId, ex.ToString());
                        if (!this.InternalHandleException(ex))
                        {
                            throw;
                        }
                    }
                    finally
                    {
                        this.EndCommandContext(cmd);
                        asyncEvent = this.GetNextEvent();
                        flag3      = (asyncEvent != null);
                    }
                }
            }
            finally
            {
                this.currentlyExecuting = false;
                this.EnqueueDiagOperation(NotificationManager.DiagnosticEvent.RunEnd);
                if (budget != null)
                {
                    try
                    {
                        budget.Dispose();
                    }
                    catch (FailFastException arg)
                    {
                        AirSyncDiagnostics.TraceError <FailFastException>(ExTraceGlobals.RequestsTracer, this, "Budget.Dispose failed with exception: {0}", arg);
                    }
                }
            }
        }
        public static NotificationManager GetOrCreateNotificationManager(INotificationManagerContext context, IAsyncCommand command, out bool wasTakenOver)
        {
            string text = NotificationManager.GetUniqueId(context);
            uint   num  = context.PolicyKey;
            int    mailboxPolicyHash = context.MailboxPolicyHash;

            wasTakenOver = false;
            NotificationManager notificationManager  = null;
            NotificationManager notificationManager2 = null;

            lock (NotificationManager.notificationManagerCache)
            {
                bool flag2 = NotificationManager.notificationManagerCache.TryGetValue(text, out notificationManager2);
                if (flag2)
                {
                    NotificationManager.hitsPerMinute.Add(1U);
                }
                if (flag2 && notificationManager2.subscriptionCanBeTaken && !notificationManager2.MailboxLoggingEnabled && mailboxPolicyHash == notificationManager2.policyHashCode && num == notificationManager2.policyKey)
                {
                    wasTakenOver = true;
                }
                else
                {
                    if (flag2)
                    {
                        NotificationManager.cacheContentionsPerMinute.Add(1U);
                        notificationManager2.EnqueueDiagOperation(NotificationManager.DiagnosticEvent.Removed);
                        NotificationManager.notificationManagerCache.Remove(text);
                        NotificationManager.removedInstances[text] = notificationManager2;
                        notificationManager = notificationManager2;
                    }
                    notificationManager2 = new NotificationManager(command, text, mailboxPolicyHash, num);
                    NotificationManager.createsPerMinute.Add(1U);
                    notificationManager2.EnqueueDiagOperation(NotificationManager.DiagnosticEvent.Cached);
                    NotificationManager.notificationManagerCache.Add(text, notificationManager2);
                    AirSyncCounters.NumberOfNotificationManagerInCache.RawValue = (long)NotificationManager.notificationManagerCache.Count;
                }
            }
            if (notificationManager != null)
            {
                AirSyncDiagnostics.TraceDebug <string>(ExTraceGlobals.ThreadingTracer, notificationManager2, "Disposing existing NotificationManager for {0}", text);
                notificationManager.EnqueueEvent(new NotificationManager.AsyncEvent(NotificationManager.AsyncEventType.Acquire, null));
                notificationManager.EnqueueDispose();
                notificationManager = null;
            }
            if (wasTakenOver)
            {
                NotificationManager.AsyncEvent evt = new NotificationManager.AsyncEvent(NotificationManager.AsyncEventType.Acquire, command);
                if (!notificationManager2.EnqueueEvent(evt))
                {
                    AirSyncDiagnostics.TraceDebug <string>(ExTraceGlobals.ThreadingTracer, notificationManager2, "A NotificationManager was attempted to be taken over but failed for {0}", text);
                    wasTakenOver         = false;
                    notificationManager2 = NotificationManager.CreateNotificationManager(context, command);
                }
                else
                {
                    notificationManager2.EnqueueDiagOperation(NotificationManager.DiagnosticEvent.Stolen);
                    NotificationManager.stealsPerMinute.Add(1U);
                }
            }
            AirSyncDiagnostics.TraceDebug <string>(ExTraceGlobals.ThreadingTracer, notificationManager2, "Got or created notification manager for {0}", text);
            return(notificationManager2);
        }