MsmqBindingMonitor.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / MsmqBindingMonitor.cs / 1 / MsmqBindingMonitor.cs

                            //---------------------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------------------

namespace System.ServiceModel.Channels 
{
    using System.Collections.Generic; 
    using System.ServiceModel; 
    using System.Diagnostics;
    using System.IO; 
    using System.Net;
    using System.ServiceModel.Diagnostics;
    using System.Text;
    using System.Threading; 
    using System.Web;
    using System.Web.Hosting; 
    using System.ServiceModel.Activation; 
    using System.Messaging;
 
    class MsmqBindingMonitor
    {
        static readonly TimeSpan DefaultUpdateInterval = TimeSpan.FromMinutes(10);
 
        CommunicationState currentState = CommunicationState.Created;
        List filters = new List(); 
        string host; 
        int iteration;
        Dictionary knownPublicQueues = new Dictionary(); 
        Dictionary knownPrivateQueues = new Dictionary();
        WaitCallback onTimer;
        object thisLock = new object();
        IOThreadTimer timer; 
        TimeSpan updateInterval;
        ManualResetEvent firstRoundComplete; 
 
        public MsmqBindingMonitor(string host)
          : this(host, DefaultUpdateInterval) 
        {
        }

        public MsmqBindingMonitor(string host, TimeSpan updateInterval) 
        {
            this.onTimer = new WaitCallback(OnTimer); 
 
            if (String.Compare(host, "localhost", StringComparison.OrdinalIgnoreCase) == 0)
                this.host = "."; 
            else
                this.host = host;

            this.firstRoundComplete = new ManualResetEvent(false); 

            this.updateInterval = updateInterval; 
            this.timer = new IOThreadTimer(this.onTimer, null, false); 
            this.iteration = 1;
        } 

        public void AddFilter(MsmqBindingFilter filter)
        {
            lock(this.thisLock) 
            {
                this.filters.Add(filter); 
 
                // Now - see if we match any known queues
                MatchFilter(filter, knownPublicQueues.Values); 
                MatchFilter(filter, knownPrivateQueues.Values);
            }
        }
 
        public bool ContainsFilter(MsmqBindingFilter filter)
        { 
            lock(this.thisLock) 
            {
                return this.filters.Contains(filter); 
            }
        }

        public void Open() 
        {
            lock(this.thisLock) 
            { 
                if(this.currentState != CommunicationState.Created)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.CommunicationObjectCannotBeModified, this.GetType().ToString()))); 

                this.currentState = CommunicationState.Opened;

                // Schedule one enumeration to run immediately... 
                IOThreadScheduler.ScheduleCallback(this.onTimer, null);
            } 
        } 

        public void RemoveFilter(MsmqBindingFilter filter) 
        {
            lock(this.thisLock)
            {
                this.filters.Remove(filter); 

                RematchQueues(filter, knownPublicQueues.Values); 
                RematchQueues(filter, knownPrivateQueues.Values); 
            }
        } 

        public void WaitForFirstRoundComplete()
        {
            this.firstRoundComplete.WaitOne(); 
        }
 
        void MatchFilter(MsmqBindingFilter filter, IEnumerable queues) 
        {
            // Run through all the queues - see if we are better than any existing matches... 
            foreach(MatchState state in queues)
            {
                int matchLength = filter.Match(state.QueueName);
                if(matchLength > state.LastMatchLength) 
                {
                    if(state.LastMatch != null) 
                    { 
                        state.LastMatch.MatchLost(this.host, state.QueueName, state.IsPrivate, state.CallbackState);
                    } 

                    state.LastMatchLength = matchLength;
                    state.LastMatch = filter;
 
                    state.CallbackState = filter.MatchFound(this.host, state.QueueName, state.IsPrivate);
                } 
            } 
        }
 
        void MatchQueue(MatchState state)
        {
            MsmqBindingFilter bestMatch = state.LastMatch;
            int bestMatchLength = state.LastMatchLength; 

            // look through all the filters for the largest match: 
            foreach(MsmqBindingFilter filter in this.filters) 
            {
                int matchLength = filter.Match(state.QueueName); 
                if(matchLength > bestMatchLength)
                {
                    bestMatchLength = matchLength;
                    bestMatch = filter; 
                }
            } 
 
            if(bestMatch != state.LastMatch)
            { 
                if(state.LastMatch != null)
                {
                    state.LastMatch.MatchLost(this.host, state.QueueName, state.IsPrivate, state.CallbackState);
                } 

                state.LastMatchLength = bestMatchLength; 
                state.LastMatch = bestMatch; 

                state.CallbackState = bestMatch.MatchFound(this.host, state.QueueName, state.IsPrivate); 
            }
        }

        void OnTimer(object state) 
        {
            try 
            { 
                lock(this.thisLock)
                { 
                    if(this.currentState != CommunicationState.Opened)
                        return;

                    MsmqDiagnostics.ScanStarted(); 

                    // enumerate the public queues first 
                    try 
                    {
                        MessageQueue[] queues = MessageQueue.GetPublicQueuesByMachine(this.host); 
                        ProcessFoundQueues(queues, knownPublicQueues, false);
                    }
                    catch(MessageQueueException ex)
                    { 
                        MsmqDiagnostics.CannotReadQueues(this.host, true, ex);
                    } 
 
                    // enumerate the private queues next
                    try 
                    {
                        MessageQueue[] queues = MessageQueue.GetPrivateQueuesByMachine(this.host);
                        ProcessFoundQueues(queues, knownPrivateQueues, true);
                    } 
                    catch(MessageQueueException ex)
                    { 
                        MsmqDiagnostics.CannotReadQueues(this.host, false, ex); 
                    }
 
                    // Figure out if we lost any queues:
                    ProcessLostQueues(knownPublicQueues);
                    ProcessLostQueues(knownPrivateQueues);
 
                    this.iteration++;
 
                    this.timer.Set(this.updateInterval); 
                }
            } 
            finally
            {
                this.firstRoundComplete.Set();
            } 
        }
 
        void ProcessFoundQueues(MessageQueue[] queues, Dictionary knownQueues, bool isPrivate) 
        {
            foreach(MessageQueue queue in queues) 
            {
                MatchState state;
                string name = ExtractQueueName(queue.QueueName, isPrivate);
 
                if(!knownQueues.TryGetValue(name, out state))
                { 
                    state = new MatchState(name, this.iteration, isPrivate); 
                    knownQueues.Add(name, state);
 
                    MatchQueue(state);
                }
                else
                { 
                    state.DiscoveryIteration = this.iteration;
                } 
            } 
        }
 
        string ExtractQueueName(string name, bool isPrivate)
        {
            // private queues start with "private$\\"
            if(isPrivate) 
            {
                return name.Substring("private$\\".Length); 
            } 
            else
            { 
                return name;
            }
        }
 
        void ProcessLostQueues(Dictionary knownQueues)
        { 
            List lostQueues = new List(); 

            foreach(MatchState state in knownQueues.Values) 
            {
                if(state.DiscoveryIteration != this.iteration)
                {
                    // we lost this queue! 
                    lostQueues.Add(state);
                } 
            } 

            foreach(MatchState state in lostQueues) 
            {
                knownQueues.Remove(state.QueueName);
                if(state.LastMatch != null)
                { 
                    state.LastMatch.MatchLost(this.host, state.QueueName, state.IsPrivate, state.CallbackState);
                } 
            } 
        }
 
        void RematchQueues(MsmqBindingFilter filter, IEnumerable queues)
        {
            // if any queue currently matches "filter", re-match it against the other filters:
            foreach(MatchState state in queues) 
            {
                if(state.LastMatch == filter) 
                { 
                    state.LastMatch.MatchLost(this.host, state.QueueName, state.IsPrivate, state.CallbackState);
                    state.LastMatch = null; 
                    state.LastMatchLength = -1;
                    MatchQueue(state);
                }
            } 
        }
 
        class MatchState 
        {
            string name; 
            int iteration;
            MsmqBindingFilter lastMatch;
            int lastMatchLength;
            object callbackState; 
            bool isPrivate;
 
            public MatchState(string name, int iteration, bool isPrivate) 
            {
                this.name = name; 
                this.iteration = iteration;
                this.isPrivate = isPrivate;
                this.lastMatchLength = -1;
            } 

            public object CallbackState 
            { 
                get { return this.callbackState; }
                set { this.callbackState = value; } 
            }

            public int DiscoveryIteration
            { 
                get { return this.iteration; }
                set { this.iteration = value; } 
            } 

            public bool IsPrivate 
            {
                get { return this.isPrivate; }
            }
 
            public MsmqBindingFilter LastMatch
            { 
                get { return this.lastMatch; } 
                set { this.lastMatch = value; }
            } 

            public int LastMatchLength
            {
                get { return this.lastMatchLength; } 
                set { this.lastMatchLength = value; }
            } 
 
            public string QueueName
            { 
                get { return this.name; }
            }
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK