UtilityExtension.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 / UtilityExtension.cs / 1 / UtilityExtension.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------
namespace System.ServiceModel.Channels
{ 
    using System.Collections.Generic;
    using System.Collections.ObjectModel; 
    using System.Diagnostics; 
    using System.Globalization;
    using System.Net; 
    using System.Runtime.Serialization;
    using System.ServiceModel.Diagnostics;
    using System.ServiceModel;
    using System.ServiceModel.Description; 
    using System.Text;
    using System.Threading; 
    using System.Xml; 

    class UtilityExtension : IExtension 
    {
        uint linkUtility;
        uint updateCount;
        IOThreadTimer ackTimer = null; 
        const uint linkUtilityIncrement = 128;
        const uint maxLinkUtility = 4096; 
        int outTotal=0; 
        uint inTotal=0;
        uint inUseful=0; 
        IPeerNeighbor owner;
        object thisLock = new object();
        object throttleLock = new object();
        public event EventHandler UtilityInfoReceived; 
        public event EventHandler UtilityInfoSent;
        TypedMessageConverter messageConverter; 
        public const int AcceptableMissDistance = 2; 
        int pendingSends = 0;
        int checkPointPendingSends = 0; 
        bool isMonitoring = false;
        int expectedClearance;
        IOThreadTimer pruneTimer;
        const int PruneIntervalMilliseconds = 10000; 
        TimeSpan pruneInterval;
        const int MinimumPendingMessages = 8; 
        public delegate void PruneNeighborCallback(IPeerNeighbor peer); 
        PruneNeighborCallback pruneNeighbor;
 
        UtilityExtension()
        {
            ackTimer = new IOThreadTimer(AcknowledgeLoop,null,false);
            pendingSends = 0; 
            pruneTimer = new IOThreadTimer(new WaitCallback(VerifyCheckPoint), null, false);
            pruneInterval = TimeSpan.FromMilliseconds(PruneIntervalMilliseconds + new Random(Process.GetCurrentProcess().Id).Next(PruneIntervalMilliseconds)); 
        } 

        public bool IsAccurate 
        {
            get { return updateCount >= 32; }
        }
 
        public uint LinkUtility
        { 
            get 
            {
                return linkUtility; 
            }
        }

        internal TypedMessageConverter MessageConverter 
        {
            get 
            { 
                if (messageConverter == null)
                { 
                    messageConverter = TypedMessageConverter.Create(typeof(UtilityInfo), PeerStrings.LinkUtilityAction);
                }
                return messageConverter;
            } 
        }
 
        public void Attach(IPeerNeighbor host) 
        {
            this.owner = host; 
            ackTimer.Set(PeerTransportConstants.AckTimeout);
        }

        static public void OnNeighborConnected(IPeerNeighbor neighbor) 
        {
            DiagnosticUtility.DebugAssert(neighbor != null, "Neighbor must have a value"); 
            neighbor.Extensions.Add(new UtilityExtension()); 
        }
 
        static public void OnNeighborClosed(IPeerNeighbor neighbor)
        {
            DiagnosticUtility.DebugAssert(neighbor != null, "Neighbor must have a value");
            UtilityExtension ext = neighbor.Extensions.Find(); 
            if(ext != null) neighbor.Extensions.Remove(ext);
        } 
 
        public void Detach(IPeerNeighbor host)
        { 
            ackTimer.Cancel();
            owner = null;

            lock(throttleLock) 
            {
                pruneTimer.Cancel(); 
            } 
        }
 
        public object ThisLock
        {
            get
            { 
                return thisLock;
            } 
        } 

        public static void OnMessageSent(IPeerNeighbor neighbor) 
        {
            UtilityExtension ext = neighbor.Extensions.Find();
            if(ext != null) ext.OnMessageSent();
        } 

        void OnMessageSent() 
        { 
            lock(ThisLock)
            { 
                outTotal++;
            }
            Interlocked.Increment(ref pendingSends);
        } 

        public static void OnEndSend(IPeerNeighbor neighbor, FloodAsyncResult fresult) 
        { 
            if(neighbor.State >= PeerNeighborState.Disconnecting)
                return; 
            UtilityExtension instance = neighbor.Utility;
            if(instance == null)
                return;
            instance.OnEndSend(fresult); 
        }
 
        public void OnEndSend(FloodAsyncResult fresult) 
        {
            Interlocked.Decrement(ref pendingSends); 
        }

        void AcknowledgeLoop(object state)
        { 
            IPeerNeighbor peer = owner;
            if(peer == null || !peer.IsConnected) 
                return; 
            FlushAcknowledge();
            if(owner != null) 
                ackTimer.Set(PeerTransportConstants.AckTimeout);
        }

        static public void ProcessLinkUtility(IPeerNeighbor neighbor, UtilityInfo umessage) 
        {
            DiagnosticUtility.DebugAssert(neighbor != null, "Neighbor must have a value"); 
            UtilityExtension ext = neighbor.Extensions.Find(); 
            if (ext != null)
            { 
                ext.ProcessLinkUtility(umessage.Useful, umessage.Total);
            }
        }
 
        // Update link utility for the neighbor. received from the neighbor
        void ProcessLinkUtility(uint useful, uint total) 
        { 
            uint i=0;
            lock(ThisLock) 
            {
                if (total > PeerTransportConstants.AckWindow
                    || useful > total
                    || (uint)outTotal < total 
                    )
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.PeerLinkUtilityInvalidValues, useful, total))); 
                }
 
                //VERIFY with in this range, we are hoping that the order of useful/useless messages doesnt matter much.
                for(i=0; i();
            if (ext != null) 
            { 
                // Can happen if the neighbor has been closed for instance
                linkUtility = ext.UpdateLinkUtility(useful); 
            }
            return linkUtility;
        }
 
        public uint UpdateLinkUtility(bool useful)
        { 
            lock(ThisLock) 
            {
                inTotal++; 
                if(useful)
                    inUseful++;
                linkUtility = Calculate(linkUtility, useful);
                if(inTotal == PeerTransportConstants.AckWindow) 
                {
                    FlushAcknowledge(); 
                } 
            }
            return linkUtility; 
        }

        public void FlushAcknowledge()
        { 
            if (inTotal == 0)
                return; 
            uint tempUseful=0, tempTotal=0; 
            lock(ThisLock)
            { 
                tempUseful = inUseful;
                tempTotal = inTotal;
                inUseful = 0;
                inTotal = 0; 
            }
            SendUtilityMessage(tempUseful, tempTotal); 
        } 

        class AsyncUtilityState 
        {
            public Message message;
            public UtilityInfo info;
            public AsyncUtilityState(Message message, UtilityInfo info) 
            {
                this.message = message; 
                this.info = info; 
            }
        } 

        void SendUtilityMessage(uint useful,uint total)
        {
            IPeerNeighbor host = owner; 
            if(host == null || !PeerNeighborStateHelper.IsConnected(host.State) || total == 0)
                return; 
            UtilityInfo umessage = new UtilityInfo(useful,total); 
            IAsyncResult result = null;
            Message message = MessageConverter.ToMessage(umessage, MessageVersion.Soap12WSAddressing10); 
            bool fatal = false;
            try
            {
                result = host.BeginSend(message, DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(UtilityMessageSent)), new AsyncUtilityState(message, umessage)); 
                if(result.CompletedSynchronously)
                { 
                    host.EndSend(result); 
                    EventHandler handler = UtilityInfoSent;
                    if (handler != null) 
                        handler(this, EventArgs.Empty);
                }
            }
            catch(Exception e) 
            {
                if(DiagnosticUtility.IsFatal(e)) 
                { 
                    fatal = true;
                    throw; 
                }
                if(null != HandleSendException(host,e,umessage))
                    throw ;
                DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); 
            }
            finally 
            { 
                if(!fatal && (result == null || result.CompletedSynchronously))
                    message.Close(); 
            }
        }

        void UtilityMessageSent(IAsyncResult result) 
        {
            if(result == null || result.AsyncState == null) 
                return; 
            IPeerNeighbor host = this.owner;
            if(host == null || !PeerNeighborStateHelper.IsConnected(host.State)) 
                return;
            if(result.CompletedSynchronously)
                return;
 
            AsyncUtilityState state = (AsyncUtilityState)result.AsyncState;
            DiagnosticUtility.DebugAssert(state != null, "IAsyncResult.AsyncState does not contain AsyncUtilityState"); 
            Message message = state.message; 
            UtilityInfo umessage = state.info;
            bool fatal = false; 
            if (!(umessage != null))
            {
                DiagnosticUtility.DebugAssert("expecting a UtilityInfo message in the AsyncState!");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
            }
 
            try 
            {
                host.EndSend(result); 
            }
            catch(Exception e)
            {
                if(DiagnosticUtility.IsFatal(e)) 
                {
                    fatal = true; 
                    throw; 
                }
                if(null != HandleSendException(host,e,umessage)) 
                    throw;
                DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information);
            }
            finally 
            {
                if(!fatal) 
                { 
                    DiagnosticUtility.DebugAssert(!result.CompletedSynchronously, "result.CompletedSynchronously");
                    message.Close(); 
                }
            }
            EventHandler handler = UtilityInfoSent;
            if (handler != null) 
                handler(this, EventArgs.Empty);
        } 
 
        Exception HandleSendException(IPeerNeighbor host, Exception e, UtilityInfo umessage)
        { 
            if ((e is ObjectDisposedException) ||
                (e is TimeoutException) ||
                (e is CommunicationException))
            { 
                if (!(!(e.InnerException is QuotaExceededException)))
                { 
                    DiagnosticUtility.DebugAssert("insufficient quota for sending messages!"); 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
                } 
                lock(ThisLock)
                {
                    this.inTotal += umessage.Total;
                    this.inUseful += umessage.Useful; 
                }
                return null; 
            } 
            else
            { 
                return e;
            }

        } 

        static internal void ReportCacheMiss(IPeerNeighbor neighbor, int missedBy) 
        { 
            DiagnosticUtility.DebugAssert(missedBy > AcceptableMissDistance, "Call this method for cache misses ONLY!");
            DiagnosticUtility.DebugAssert(neighbor != null, "Neighbor must have a value"); 

            if(!neighbor.IsConnected)
                return;
            UtilityExtension ext = neighbor.Extensions.Find(); 
            if (ext != null)
            { 
                ext.ReportCacheMiss(missedBy); 
            }
        } 

        void ReportCacheMiss(int missedBy)
        {
            lock(ThisLock) 
            {
                for(int i=0; i= lclCheckPointPendingSends)
            { 
                pruneNeighbor(peer);
            }
            else
            { 
                lock(throttleLock)
                { 
                    if(owner == null) 
                        return;
                    this.checkPointPendingSends = this.pendingSends; 
                    this.expectedClearance = this.expectedClearance/2;
                    pruneTimer.Set(pruneInterval);
                }
 
            }
        } 
    } 
}

// 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