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

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------
namespace System.ServiceModel.PeerResolvers
{ 
    using System;
    using System.ServiceModel; 
    using System.Collections.Generic; 
    using System.Collections.ObjectModel;
    using System.Configuration; 
    using System.Diagnostics;
    using System.Globalization;
    using System.Net.Security;
    using System.ServiceModel.Configuration; 
    using System.ServiceModel.Channels;
    using System.Threading; 
 
    [ServiceBehavior(UseSynchronizationContext = false, InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class CustomPeerResolverService : IPeerResolverContract 
    {
        internal enum RegistrationState
        {
            OK, Deleted 
        }
 
        internal class RegistrationEntry 
        {
 
            Guid clientId;
            Guid registrationId;
            string meshId;
            DateTime expires; 
            PeerNodeAddress address;
            RegistrationState state; 
 

            public RegistrationEntry(Guid clientId, Guid registrationId, string meshId, DateTime expires, PeerNodeAddress address) 
            {
                this.ClientId = clientId;
                this.RegistrationId = registrationId;
                this.MeshId = meshId; 
                this.Expires = expires;
                this.Address = address; 
                this.State = RegistrationState.OK; 
            }
 
            public Guid ClientId
            {
                get { return clientId; }
                set { clientId = value; } 
            }
 
            public Guid RegistrationId 
            {
                get { return registrationId; } 
                set { registrationId = value; }
            }

            public string MeshId 
            {
                get { return meshId; } 
                set { meshId = value; } 
            }
 
            public DateTime Expires
            {
                get { return expires; }
                set { expires = value; } 
            }
 
            public PeerNodeAddress Address 
            {
                get { return address; } 
                set { address = value; }
            }

            public RegistrationState State 
            {
                get { return state; } 
                set { state = value; } 
            }
 
        }

        internal class LiteLock
        { 
            bool forWrite;
            bool upgraded; 
            ReaderWriterLock locker; 
            TimeSpan timeout = TimeSpan.FromMinutes(1);
            LockCookie lc ; 

            LiteLock(ReaderWriterLock locker, bool forWrite)
            {
                this.locker = locker; 
                this.forWrite = forWrite;
            } 
 
            public static void Acquire(out LiteLock liteLock, ReaderWriterLock locker)
            { 
                Acquire(out liteLock, locker, false);
            }

            public static void Acquire(out LiteLock liteLock, ReaderWriterLock locker, bool forWrite) 
            {
                LiteLock theLock = new LiteLock(locker, forWrite); 
                try { } 
                finally
                { 
                    if(forWrite)
                    {
                        locker.AcquireWriterLock(theLock.timeout);
                    } 
                    else
                    { 
                        locker.AcquireReaderLock(theLock.timeout); 
                    }
                    liteLock = theLock; 
                }
            }

            public static void Release(LiteLock liteLock) 
            {
                if (liteLock == null) 
                { 
                    return;
                } 

                if(liteLock.forWrite)
                {
                    liteLock.locker.ReleaseWriterLock(); 
                }
                else 
                { 
                    DiagnosticUtility.DebugAssert(!liteLock.upgraded, "Can't release while upgraded!");
                    liteLock.locker.ReleaseReaderLock(); 
                }
            }
            public void UpgradeToWriterLock()
            { 
                DiagnosticUtility.DebugAssert(!forWrite, "Invalid call to Upgrade!!");
                DiagnosticUtility.DebugAssert(!upgraded, "Already upgraded!"); 
                try { } 
                finally
                { 
                    lc = locker.UpgradeToWriterLock(timeout);
                    upgraded = true;
                }
            } 
            public void DowngradeFromWriterLock()
            { 
                DiagnosticUtility.DebugAssert(!forWrite, "Invalid call to Downgrade!!"); 
                if (upgraded)
                { 
                    locker.DowngradeFromWriterLock(ref lc);
                    upgraded = false;
                }
            } 
        }
 
        internal class MeshEntry 
        {
            Dictionary entryTable; 
            Dictionary service2EntryTable;
            List entryList;
            ReaderWriterLock gate;
 
            internal MeshEntry()
            { 
                EntryTable = new Dictionary(); 
                Service2EntryTable = new Dictionary();
                EntryList = new List(); 
                Gate = new ReaderWriterLock();
            }

            public Dictionary EntryTable 
            {
                get { return entryTable; } 
                set { entryTable = value; } 
            }
 
            public Dictionary Service2EntryTable
            {
                get { return service2EntryTable; }
                set { service2EntryTable = value; } 
            }
 
            public List EntryList 
            {
                get { return entryList; } 
                set { entryList = value; }
            }

            public ReaderWriterLock Gate 
            {
                get { return gate; } 
                set { gate = value; } 
            }
        } 

        Dictionary meshId2Entry = new Dictionary();
        ReaderWriterLock gate;
 
        TimeSpan timeout = TimeSpan.FromMinutes(1);
        TimeSpan cleanupInterval = TimeSpan.FromMinutes(1); 
        TimeSpan refreshInterval = TimeSpan.FromMinutes(10); 
        bool controlShape;
        bool isCleaning; 
        IOThreadTimer timer;
        object thisLock = new object();
        bool opened;
        TimeSpan LockWait = TimeSpan.FromSeconds(5); 

        public CustomPeerResolverService() 
        { 
            isCleaning = false;
            gate = new ReaderWriterLock(); 
        }

        public TimeSpan CleanupInterval
        { 
            get
            { 
                return cleanupInterval; 
            }
            set 
            {
                if (value < TimeSpan.Zero)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value, 
                        SR.GetString(SR.SFxTimeoutOutOfRange0)));
                } 
 
                if (TimeoutHelper.IsTooLarge(value))
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value,
                        SR.GetString(SR.SFxTimeoutOutOfRangeTooBig)));
                }
 
                lock (ThisLock)
                { 
                    ThrowIfOpened("Set CleanupInterval"); 
                    this.cleanupInterval = value;
                } 
            }
        }

        public TimeSpan RefreshInterval 
        {
            get 
            { 
                return refreshInterval;
            } 
            set
            {
                if (value < TimeSpan.Zero)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value,
                        SR.GetString(SR.SFxTimeoutOutOfRange0))); 
                } 

                if (TimeoutHelper.IsTooLarge(value)) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value,
                        SR.GetString(SR.SFxTimeoutOutOfRangeTooBig)));
                } 

                lock (ThisLock) 
                { 
                    ThrowIfOpened("Set RefreshInterval");
                    this.refreshInterval = value; 
                }
            }
        }
 
        public bool ControlShape
        { 
            get 
            {
                return this.controlShape; 
            }
            set
            {
                lock (ThisLock) 
                {
                    ThrowIfOpened("Set ControlShape"); 
                    this.controlShape = value; 
                }
            } 
        }

        MeshEntry GetMeshEntry(string meshId){return GetMeshEntry(meshId,true);}
        MeshEntry GetMeshEntry(string meshId, bool createIfNotExists) 
        {
            MeshEntry meshEntry = null; 
            LiteLock ll = null; 
            try
            { 
                LiteLock.Acquire(out ll, gate);
                if(!this.meshId2Entry.TryGetValue(meshId, out meshEntry) && createIfNotExists)
                {
                    meshEntry = new MeshEntry(); 
                    try
                    { 
                        ll.UpgradeToWriterLock(); 
                        meshId2Entry.Add(meshId,meshEntry);
                    } 
                    finally
                    {
                        ll.DowngradeFromWriterLock();
                    } 
                }
            } 
            finally 
            {
                LiteLock.Release(ll); 
            }
            DiagnosticUtility.DebugAssert(meshEntry != null || !createIfNotExists, "GetMeshEntry failed to get an entry!");
            return meshEntry;
        } 

        public virtual RegisterResponseInfo Register(Guid clientId, string meshId, PeerNodeAddress address) 
        { 
            Guid registrationId = Guid.NewGuid();
            DateTime expiry = DateTime.UtcNow + RefreshInterval; 

            RegistrationEntry entry = null;
            MeshEntry meshEntry = null;
 
            lock (ThisLock)
            { 
                entry = new RegistrationEntry(clientId, registrationId, meshId, expiry, address); 
                meshEntry = GetMeshEntry(meshId);
                if(meshEntry.Service2EntryTable.ContainsKey(address.ServicePath)) 
                    PeerExceptionHelper.ThrowInvalidOperation_DuplicatePeerRegistration(address.ServicePath);
                LiteLock ll = null;
                try
                { 
                    LiteLock.Acquire(out ll, meshEntry.Gate, true);
                    meshEntry.EntryTable.Add(registrationId,entry); 
                    meshEntry.EntryList.Add(entry); 
                    meshEntry.Service2EntryTable.Add(address.ServicePath, entry);
                } 
                finally
                {
                    LiteLock.Release(ll);
                } 
            }
            return new RegisterResponseInfo(registrationId, RefreshInterval); 
        } 

        public virtual RegisterResponseInfo Register(RegisterInfo registerInfo) 
        {
            if (registerInfo == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("registerInfo", SR.GetString(SR.PeerNullRegistrationInfo)); 
            }
 
            ThrowIfClosed("Register"); 

            if (!registerInfo.HasBody() || String.IsNullOrEmpty(registerInfo.MeshId)) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("registerInfo", SR.GetString(SR.PeerInvalidMessageBody, registerInfo));
            }
            return Register(registerInfo.ClientId, registerInfo.MeshId, registerInfo.NodeAddress); 
        }
 
        public virtual RegisterResponseInfo Update(UpdateInfo updateInfo) 
        {
            if (updateInfo == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("updateInfo", SR.GetString(SR.PeerNullRegistrationInfo));
            }
 
            ThrowIfClosed("Update");
 
            if(!updateInfo.HasBody() || String.IsNullOrEmpty(updateInfo.MeshId) || updateInfo.NodeAddress == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("updateInfo", SR.GetString(SR.PeerInvalidMessageBody, updateInfo)); 
            }

            Guid registrationId = updateInfo.RegistrationId;
            RegistrationEntry entry; 

            MeshEntry meshEntry = GetMeshEntry(updateInfo.MeshId); 
            LiteLock ll = null; 

            //handle cases when Update races with Register. 
            if (updateInfo.RegistrationId == Guid.Empty || meshEntry == null)
                return Register(updateInfo.ClientId, updateInfo.MeshId, updateInfo.NodeAddress);

            try 
            {
                LiteLock.Acquire(out ll, meshEntry.Gate); 
                if(!meshEntry.EntryTable.TryGetValue(updateInfo.RegistrationId, out entry)) 
                    return Register(updateInfo.ClientId, updateInfo.MeshId, updateInfo.NodeAddress);
                lock(entry) 
                {
                    entry.Address = updateInfo.NodeAddress;
                    entry.Expires = DateTime.UtcNow + this.RefreshInterval;
                } 
            }
            finally 
            { 
                LiteLock.Release(ll);
            } 
            return new RegisterResponseInfo(registrationId, RefreshInterval);
        }

        public virtual ResolveResponseInfo Resolve(ResolveInfo resolveInfo) 
        {
            if (resolveInfo == null) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("resolveInfo", SR.GetString(SR.PeerNullResolveInfo));
            } 

            ThrowIfClosed("Resolve");

            if(!resolveInfo.HasBody()) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("resolveInfo", SR.GetString(SR.PeerInvalidMessageBody, resolveInfo)); 
            } 

            int currentCount=0; 
            int index=0;
            int maxEntries = resolveInfo.MaxAddresses;
            ResolveResponseInfo response = new ResolveResponseInfo();
            List results = new List(); 
            List entries = null;
            PeerNodeAddress address; 
            RegistrationEntry entry; 
            MeshEntry meshEntry = GetMeshEntry(resolveInfo.MeshId, false);
            if(meshEntry != null) 
            {
                LiteLock ll = null;
                try
                { 
                    LiteLock.Acquire(out ll, meshEntry.Gate);
                    entries = meshEntry.EntryList; 
                    if(entries.Count <= maxEntries) 
                    {
                        foreach(RegistrationEntry e in entries) 
                        {
                            results.Add(e.Address);
                        }
                    } 
                    else
                    { 
                        Random random = new Random(); 
                        while(currentCount keys = null; 
                            LiteLock ll = null; 
                            try
                            { 
                                LiteLock.Acquire(out ll, gate);
                                keys = meshId2Entry.Keys;
                            }
                            finally 
                            {
                                LiteLock.Release(ll); 
                            } 
                            foreach(string meshId in keys)
                            { 
                                meshEntry  = GetMeshEntry(meshId);
                                CleanupMeshEntry(meshEntry);
                            }
                        } 
                        finally
                        { 
                            isCleaning = false; 
                            if(opened)
                                timer.Set(this.CleanupInterval); 
                        }
                    }
                }
            } 
        }
 
        //always call this from a readlock 
        void CleanupMeshEntry(MeshEntry meshEntry)
        { 
            List remove = new List();
            if(!opened)
                return;
            LiteLock ll = null; 
            try
            { 
                LiteLock.Acquire(out ll, meshEntry.Gate, true); 
                foreach(KeyValuePair item in meshEntry.EntryTable)
                { 
                    if((item.Value.Expires <= DateTime.UtcNow)|| (item.Value.State == RegistrationState.Deleted))
                    {
                        remove.Add(item.Key);
                        meshEntry.EntryList.Remove(item.Value); 
                        meshEntry.Service2EntryTable.Remove(item.Value.Address.ServicePath);
                    } 
                } 
                foreach(Guid id in remove)
                { 
                    meshEntry.EntryTable.Remove(id);
                }
            }
            finally 
            {
                LiteLock.Release(ll); 
            } 
        }
 
        object ThisLock
        {
            get
            { 
                return this.thisLock;
            } 
        } 
        void ThrowIfOpened(string operation)
        { 
            if (opened)
                PeerExceptionHelper.ThrowInvalidOperation_NotValidWhenOpen(operation);
        }
        void ThrowIfClosed(string operation) 
        {
            if (!opened) 
                PeerExceptionHelper.ThrowInvalidOperation_NotValidWhenClosed(operation); 

        } 
    }
}


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