Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / clr / src / BCL / System / Runtime / Remoting / Lease.cs / 1 / Lease.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== //+---------------------------------------------------------------------------- // // Microsoft Windows // File: Lease.cs // // Contents: Lease class // // History: 1/5/00[....] Created // //+--------------------------------------------------------------------------- namespace System.Runtime.Remoting.Lifetime { using System; using System.Security; using System.Security.Permissions; using System.Collections; using System.Threading; using System.Runtime.Remoting.Messaging; using System.Runtime.Remoting.Proxies; using System.Globalization; internal class Lease : MarshalByRefObject, ILease { internal int id = 0; // Lease Time internal DateTime leaseTime; internal TimeSpan initialLeaseTime; // Renewal Policies internal TimeSpan renewOnCallTime; internal TimeSpan sponsorshipTimeout; internal Boolean isInfinite = false; // Sponsors internal Hashtable sponsorTable; internal int sponsorCallThread; // Links to leasemanager and managed object internal LeaseManager leaseManager; internal MarshalByRefObject managedObject; // State internal LeaseState state; internal static int nextId = 0; internal Lease(TimeSpan initialLeaseTime, TimeSpan renewOnCallTime, TimeSpan sponsorshipTimeout, MarshalByRefObject managedObject ) { id = nextId++; BCLDebug.Trace("REMOTE", "Lease Constructor ",managedObject," initialLeaseTime "+initialLeaseTime+" renewOnCall "+renewOnCallTime+" sponsorshipTimeout ",sponsorshipTimeout); // Set Policy this.renewOnCallTime = renewOnCallTime; this.sponsorshipTimeout = sponsorshipTimeout; this.initialLeaseTime = initialLeaseTime; this.managedObject = managedObject; //Add lease to leaseManager leaseManager = LeaseManager.GetLeaseManager(); // Initialize tables sponsorTable = new Hashtable(10); state = LeaseState.Initial; } internal void ActivateLease() { // Set leaseTime leaseTime = DateTime.UtcNow.Add(initialLeaseTime); state = LeaseState.Active; leaseManager.ActivateLease(this); } // Override MarshalByRefObject InitializeLifetimeService // Don't want a lease on a lease therefore returns null public override Object InitializeLifetimeService() { BCLDebug.Trace("REMOTE", "Lease ",id," InitializeLifetimeService, lease Marshalled"); return null; } // ILease Property and Methods public TimeSpan RenewOnCallTime { get { return renewOnCallTime; } [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)] set { if (state == LeaseState.Initial) { renewOnCallTime = value; BCLDebug.Trace("REMOTE", "Lease Set RenewOnCallProperty ",managedObject," "+renewOnCallTime); } else throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Lifetime_InitialStateRenewOnCall"), ((Enum)state).ToString())); } } public TimeSpan SponsorshipTimeout { get { return sponsorshipTimeout; } [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)] set { if (state == LeaseState.Initial) { sponsorshipTimeout = value; BCLDebug.Trace("REMOTE", "Lease Set SponsorshipTimeout Property ",managedObject," "+sponsorshipTimeout); } else throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Lifetime_InitialStateSponsorshipTimeout"), ((Enum)state).ToString())); } } public TimeSpan InitialLeaseTime { get { return initialLeaseTime; } [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)] set { if (state == LeaseState.Initial) { initialLeaseTime = value; if (TimeSpan.Zero.CompareTo(value) >= 0) state = LeaseState.Null; BCLDebug.Trace("REMOTE", "Lease Set InitialLeaseTime Property ",managedObject," "+InitialLeaseTime+", current state "+((Enum)state).ToString()); } else throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Lifetime_InitialStateInitialLeaseTime"), ((Enum)state).ToString())); } } public TimeSpan CurrentLeaseTime { get { return leaseTime.Subtract(DateTime.UtcNow); } } public LeaseState CurrentState { get { return state;} } [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)] public void Register(ISponsor obj) { Register(obj, TimeSpan.Zero); } [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)] public void Register(ISponsor obj, TimeSpan renewalTime) { lock(this) { BCLDebug.Trace("REMOTE", "Lease "+id+" Register Sponsor renewalTime ",renewalTime," state ",((Enum)state).ToString()); if (state == LeaseState.Expired || sponsorshipTimeout == TimeSpan.Zero) return; Object sponsorId = GetSponsorId(obj); lock(sponsorTable) { if (renewalTime > TimeSpan.Zero) AddTime(renewalTime); if (!sponsorTable.ContainsKey(sponsorId)) { // Place in tables sponsorTable[sponsorId] = new SponsorStateInfo(renewalTime, SponsorState.Initial); } } } } [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)] public void Unregister(ISponsor sponsor) { lock(this) { BCLDebug.Trace("REMOTE", "Lease",id," Unregister state ",((Enum)state).ToString()); if (state == LeaseState.Expired) return; Object sponsorId = GetSponsorId(sponsor); lock(sponsorTable) { if (sponsorId != null) { leaseManager.DeleteSponsor(sponsorId); SponsorStateInfo sponsorStateInfo = (SponsorStateInfo)sponsorTable[sponsorId]; sponsorTable.Remove(sponsorId); } } } } // Get the local representative of the sponsor to prevent a remote access when placing // in a hash table. private Object GetSponsorId(ISponsor obj) { Object sponsorId = null; if (obj != null) { if (RemotingServices.IsTransparentProxy(obj)) sponsorId = RemotingServices.GetRealProxy(obj); else sponsorId = obj; } return sponsorId; } // Convert from the local representative of the sponsor to either the MarshalByRefObject or local object private ISponsor GetSponsorFromId(Object sponsorId) { Object sponsor = null; RealProxy rp = sponsorId as RealProxy; if (null != rp) sponsor = rp.GetTransparentProxy(); else sponsor = sponsorId; return (ISponsor)sponsor; } [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)] public TimeSpan Renew(TimeSpan renewalTime) { return RenewInternal(renewalTime); } // We will call this internally within the server domain internal TimeSpan RenewInternal(TimeSpan renewalTime) { lock(this) { BCLDebug.Trace("REMOTE","Lease ",id," Renew ",renewalTime," state ",((Enum)state).ToString()); if (state == LeaseState.Expired) return TimeSpan.Zero; AddTime(renewalTime); return leaseTime.Subtract(DateTime.UtcNow); } } // Used for a lease which has been created, but will not be used internal void Remove() { BCLDebug.Trace("REMOTE","Lease ",id," Remove state ",((Enum)state).ToString()); if (state == LeaseState.Expired) return; state = LeaseState.Expired; leaseManager.DeleteLease(this); } internal void Cancel() { lock(this) { BCLDebug.Trace("REMOTE","Lease ",id," Cancel Managed Object ",managedObject," state ",((Enum)state).ToString()); if (state == LeaseState.Expired) return; Remove(); // Disconnect the object ... // We use the internal version of Disconnect passing "false" // for the bResetURI flag. This allows the object to keep its // old URI in case its lease gets reactivated later. RemotingServices.Disconnect(managedObject, false); // Disconnect the lease for the object. RemotingServices.Disconnect(this); } } #if _DEBUG ~Lease() { BCLDebug.Trace("REMOTE","Lease ",id," Finalize"); } #endif internal void RenewOnCall() { lock(this) { //BCLDebug.Trace("REMOTE","Lease ",id," RenewOnCall state ",((Enum)state).ToString()); if (state == LeaseState.Initial || state == LeaseState.Expired) return; AddTime(renewOnCallTime); } } internal void LeaseExpired(DateTime now) { lock(this) { BCLDebug.Trace("REMOTE","Lease ",id," LeaseExpired state ",((Enum)state).ToString()); if (state == LeaseState.Expired) return; // There is a small window between the time the leaseManager // thread examines all the leases and tests for expiry and // when an indivisual lease is locked for expiry. The object // could get marshal-ed in this time which would reset its lease // Therefore we check again to see if we should indeed proceed // with the expire code (using the same value of 'now' as used // by the leaseManager thread) if (leaseTime.CompareTo(now) < 0) ProcessNextSponsor(); } } internal delegate TimeSpan AsyncRenewal(ILease lease); internal void SponsorCall(ISponsor sponsor) { BCLDebug.Trace("REMOTE","Lease ",id," SponsorCall state ",((Enum)state).ToString()); bool exceptionOccurred = false; if (state == LeaseState.Expired) return; lock(sponsorTable) { try { Object sponsorId = GetSponsorId(sponsor); sponsorCallThread = Thread.CurrentThread.GetHashCode(); AsyncRenewal ar = new AsyncRenewal(sponsor.Renewal); SponsorStateInfo sponsorStateInfo = (SponsorStateInfo)sponsorTable[sponsorId]; sponsorStateInfo.sponsorState = SponsorState.Waiting; // The first parameter should be the lease we are trying to renew. IAsyncResult iar = ar.BeginInvoke(this, new AsyncCallback(this.SponsorCallback), null); if ((sponsorStateInfo.sponsorState == SponsorState.Waiting) && (state != LeaseState.Expired)) { // Even if we get here, the operation could still complete before // we call the the line below. This seems to be a ----. // Sponsor could have completed before statement is reached, so only execute // if the sponsor state is still waiting leaseManager.RegisterSponsorCall(this, sponsorId, sponsorshipTimeout); } sponsorCallThread = 0; }catch(Exception) { // Sponsor not avaiable exceptionOccurred = true; sponsorCallThread = 0; } } if (exceptionOccurred) { BCLDebug.Trace("REMOTE","Lease ",id," SponsorCall Sponsor Exception "); Unregister(sponsor); ProcessNextSponsor(); } } internal void SponsorTimeout(Object sponsorId) { lock (this) { if (!sponsorTable.ContainsKey(sponsorId)) return; lock(sponsorTable) { SponsorStateInfo sponsorStateInfo = (SponsorStateInfo)sponsorTable[sponsorId]; BCLDebug.Trace("REMOTE","Lease ",id," SponsorTimeout sponsorState ",((Enum)sponsorStateInfo.sponsorState).ToString()); if (sponsorStateInfo.sponsorState == SponsorState.Waiting) { Unregister(GetSponsorFromId(sponsorId)); ProcessNextSponsor(); } } } } private void ProcessNextSponsor() { BCLDebug.Trace("REMOTE","Lease ",id," ProcessNextSponsor"); Object largestSponsor = null; TimeSpan largestRenewalTime = TimeSpan.Zero; lock(sponsorTable) { IDictionaryEnumerator e = sponsorTable.GetEnumerator(); // Find sponsor with largest previous renewal value while(e.MoveNext()) { Object sponsorId = e.Key; SponsorStateInfo sponsorStateInfo = (SponsorStateInfo)e.Value; if ((sponsorStateInfo.sponsorState == SponsorState.Initial) && (largestRenewalTime == TimeSpan.Zero)) { largestRenewalTime = sponsorStateInfo.renewalTime; largestSponsor = sponsorId; } else if (sponsorStateInfo.renewalTime > largestRenewalTime) { largestRenewalTime = sponsorStateInfo.renewalTime; largestSponsor = sponsorId; } } } if (largestSponsor != null) SponsorCall(GetSponsorFromId(largestSponsor)); else { // No more sponsors to try, Cancel BCLDebug.Trace("REMOTE","Lease ",id," ProcessNextSponsor no more sponsors"); Cancel(); } } // This gets called when we explicitly transfer the call back from the // called function to a threadpool thread. internal void SponsorCallback(Object obj) { SponsorCallback((IAsyncResult)obj); } // On another thread internal void SponsorCallback(IAsyncResult iar) { BCLDebug.Trace("REMOTE","Lease ",id," SponsorCallback IAsyncResult ",iar," state ",((Enum)state).ToString()); if (state == LeaseState.Expired) { return; } int thisThread = Thread.CurrentThread.GetHashCode(); if (thisThread == sponsorCallThread) { // Looks like something went wrong and the thread that // did the AsyncRenewal::BeginInvoke is executing the callback // We will queue the work to the thread pool (otherwise there // is a possibility of stack overflow if all sponsors are down) WaitCallback threadFunc = new WaitCallback(this.SponsorCallback); ThreadPool.QueueUserWorkItem(threadFunc, iar); return; } AsyncResult asyncResult = (AsyncResult)iar; AsyncRenewal ar = (AsyncRenewal)asyncResult.AsyncDelegate; ISponsor sponsor = (ISponsor)ar.Target; SponsorStateInfo sponsorStateInfo = null; if (iar.IsCompleted) { // Sponsor came back with renewal BCLDebug.Trace("REMOTE","Lease ",id," SponsorCallback sponsor completed"); bool exceptionOccurred = false; TimeSpan renewalTime = TimeSpan.Zero; try { renewalTime = (TimeSpan)ar.EndInvoke(iar); }catch(Exception) { // Sponsor not avaiable exceptionOccurred = true; } if (exceptionOccurred) { BCLDebug.Trace("REMOTE","Lease ",id," SponsorCallback Sponsor Exception "); Unregister(sponsor); ProcessNextSponsor(); } else { Object sponsorId = GetSponsorId(sponsor); lock(sponsorTable) { if (sponsorTable.ContainsKey(sponsorId)) { sponsorStateInfo = (SponsorStateInfo)sponsorTable[sponsorId]; sponsorStateInfo.sponsorState = SponsorState.Completed; sponsorStateInfo.renewalTime = renewalTime; } else { // Sponsor was deleted, possibly from a sponsor time out } } if (sponsorStateInfo == null) { // Sponsor was deleted ProcessNextSponsor(); } else if (sponsorStateInfo.renewalTime == TimeSpan.Zero) { BCLDebug.Trace("REMOTE","Lease ",id," SponsorCallback sponsor did not renew "); Unregister(sponsor); ProcessNextSponsor(); } else RenewInternal(sponsorStateInfo.renewalTime); } } else { // Sponsor timed out // Note time outs should be handled by the LeaseManager BCLDebug.Trace("REMOTE","Lease ",id," SponsorCallback sponsor did not complete, timed out"); Unregister(sponsor); ProcessNextSponsor(); } } private void AddTime(TimeSpan renewalSpan) { if (state == LeaseState.Expired) return; DateTime now = DateTime.UtcNow; DateTime oldLeaseTime = leaseTime; DateTime renewTime = now.Add(renewalSpan); if (leaseTime.CompareTo(renewTime) < 0) { leaseManager.ChangedLeaseTime(this, renewTime); leaseTime = renewTime; state = LeaseState.Active; } //BCLDebug.Trace("REMOTE","Lease ",id," AddTime renewalSpan ",renewalSpan," current Time ",now," old leaseTime ",oldLeaseTime," new leaseTime ",leaseTime," state ",((Enum)state).ToString()); } [Serializable] internal enum SponsorState { Initial = 0, Waiting = 1, Completed = 2 } internal sealed class SponsorStateInfo { internal TimeSpan renewalTime; internal SponsorState sponsorState; internal SponsorStateInfo(TimeSpan renewalTime, SponsorState sponsorState) { this.renewalTime = renewalTime; this.sponsorState = sponsorState; } } } internal class LeaseSink : IMessageSink { Lease lease = null; IMessageSink nextSink = null; public LeaseSink(Lease lease, IMessageSink nextSink) { this.lease = lease; this.nextSink = nextSink; } //IMessageSink methods public IMessage SyncProcessMessage(IMessage msg) { //BCLDebug.Trace("REMOTE","Lease ",id," SyncProcessMessage"); lease.RenewOnCall(); return nextSink.SyncProcessMessage(msg); } public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink) { //BCLDebug.Trace("REMOTE","Lease ",id," AsyncProcessMessage"); lease.RenewOnCall(); return nextSink.AsyncProcessMessage(msg, replySink); } public IMessageSink NextSink { get { //BCLDebug.Trace("REMOTE","Lease ",id," NextSink"); return nextSink; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== //+---------------------------------------------------------------------------- // // Microsoft Windows // File: Lease.cs // // Contents: Lease class // // History: 1/5/00[....] Created // //+--------------------------------------------------------------------------- namespace System.Runtime.Remoting.Lifetime { using System; using System.Security; using System.Security.Permissions; using System.Collections; using System.Threading; using System.Runtime.Remoting.Messaging; using System.Runtime.Remoting.Proxies; using System.Globalization; internal class Lease : MarshalByRefObject, ILease { internal int id = 0; // Lease Time internal DateTime leaseTime; internal TimeSpan initialLeaseTime; // Renewal Policies internal TimeSpan renewOnCallTime; internal TimeSpan sponsorshipTimeout; internal Boolean isInfinite = false; // Sponsors internal Hashtable sponsorTable; internal int sponsorCallThread; // Links to leasemanager and managed object internal LeaseManager leaseManager; internal MarshalByRefObject managedObject; // State internal LeaseState state; internal static int nextId = 0; internal Lease(TimeSpan initialLeaseTime, TimeSpan renewOnCallTime, TimeSpan sponsorshipTimeout, MarshalByRefObject managedObject ) { id = nextId++; BCLDebug.Trace("REMOTE", "Lease Constructor ",managedObject," initialLeaseTime "+initialLeaseTime+" renewOnCall "+renewOnCallTime+" sponsorshipTimeout ",sponsorshipTimeout); // Set Policy this.renewOnCallTime = renewOnCallTime; this.sponsorshipTimeout = sponsorshipTimeout; this.initialLeaseTime = initialLeaseTime; this.managedObject = managedObject; //Add lease to leaseManager leaseManager = LeaseManager.GetLeaseManager(); // Initialize tables sponsorTable = new Hashtable(10); state = LeaseState.Initial; } internal void ActivateLease() { // Set leaseTime leaseTime = DateTime.UtcNow.Add(initialLeaseTime); state = LeaseState.Active; leaseManager.ActivateLease(this); } // Override MarshalByRefObject InitializeLifetimeService // Don't want a lease on a lease therefore returns null public override Object InitializeLifetimeService() { BCLDebug.Trace("REMOTE", "Lease ",id," InitializeLifetimeService, lease Marshalled"); return null; } // ILease Property and Methods public TimeSpan RenewOnCallTime { get { return renewOnCallTime; } [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)] set { if (state == LeaseState.Initial) { renewOnCallTime = value; BCLDebug.Trace("REMOTE", "Lease Set RenewOnCallProperty ",managedObject," "+renewOnCallTime); } else throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Lifetime_InitialStateRenewOnCall"), ((Enum)state).ToString())); } } public TimeSpan SponsorshipTimeout { get { return sponsorshipTimeout; } [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)] set { if (state == LeaseState.Initial) { sponsorshipTimeout = value; BCLDebug.Trace("REMOTE", "Lease Set SponsorshipTimeout Property ",managedObject," "+sponsorshipTimeout); } else throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Lifetime_InitialStateSponsorshipTimeout"), ((Enum)state).ToString())); } } public TimeSpan InitialLeaseTime { get { return initialLeaseTime; } [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)] set { if (state == LeaseState.Initial) { initialLeaseTime = value; if (TimeSpan.Zero.CompareTo(value) >= 0) state = LeaseState.Null; BCLDebug.Trace("REMOTE", "Lease Set InitialLeaseTime Property ",managedObject," "+InitialLeaseTime+", current state "+((Enum)state).ToString()); } else throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Lifetime_InitialStateInitialLeaseTime"), ((Enum)state).ToString())); } } public TimeSpan CurrentLeaseTime { get { return leaseTime.Subtract(DateTime.UtcNow); } } public LeaseState CurrentState { get { return state;} } [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)] public void Register(ISponsor obj) { Register(obj, TimeSpan.Zero); } [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)] public void Register(ISponsor obj, TimeSpan renewalTime) { lock(this) { BCLDebug.Trace("REMOTE", "Lease "+id+" Register Sponsor renewalTime ",renewalTime," state ",((Enum)state).ToString()); if (state == LeaseState.Expired || sponsorshipTimeout == TimeSpan.Zero) return; Object sponsorId = GetSponsorId(obj); lock(sponsorTable) { if (renewalTime > TimeSpan.Zero) AddTime(renewalTime); if (!sponsorTable.ContainsKey(sponsorId)) { // Place in tables sponsorTable[sponsorId] = new SponsorStateInfo(renewalTime, SponsorState.Initial); } } } } [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)] public void Unregister(ISponsor sponsor) { lock(this) { BCLDebug.Trace("REMOTE", "Lease",id," Unregister state ",((Enum)state).ToString()); if (state == LeaseState.Expired) return; Object sponsorId = GetSponsorId(sponsor); lock(sponsorTable) { if (sponsorId != null) { leaseManager.DeleteSponsor(sponsorId); SponsorStateInfo sponsorStateInfo = (SponsorStateInfo)sponsorTable[sponsorId]; sponsorTable.Remove(sponsorId); } } } } // Get the local representative of the sponsor to prevent a remote access when placing // in a hash table. private Object GetSponsorId(ISponsor obj) { Object sponsorId = null; if (obj != null) { if (RemotingServices.IsTransparentProxy(obj)) sponsorId = RemotingServices.GetRealProxy(obj); else sponsorId = obj; } return sponsorId; } // Convert from the local representative of the sponsor to either the MarshalByRefObject or local object private ISponsor GetSponsorFromId(Object sponsorId) { Object sponsor = null; RealProxy rp = sponsorId as RealProxy; if (null != rp) sponsor = rp.GetTransparentProxy(); else sponsor = sponsorId; return (ISponsor)sponsor; } [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)] public TimeSpan Renew(TimeSpan renewalTime) { return RenewInternal(renewalTime); } // We will call this internally within the server domain internal TimeSpan RenewInternal(TimeSpan renewalTime) { lock(this) { BCLDebug.Trace("REMOTE","Lease ",id," Renew ",renewalTime," state ",((Enum)state).ToString()); if (state == LeaseState.Expired) return TimeSpan.Zero; AddTime(renewalTime); return leaseTime.Subtract(DateTime.UtcNow); } } // Used for a lease which has been created, but will not be used internal void Remove() { BCLDebug.Trace("REMOTE","Lease ",id," Remove state ",((Enum)state).ToString()); if (state == LeaseState.Expired) return; state = LeaseState.Expired; leaseManager.DeleteLease(this); } internal void Cancel() { lock(this) { BCLDebug.Trace("REMOTE","Lease ",id," Cancel Managed Object ",managedObject," state ",((Enum)state).ToString()); if (state == LeaseState.Expired) return; Remove(); // Disconnect the object ... // We use the internal version of Disconnect passing "false" // for the bResetURI flag. This allows the object to keep its // old URI in case its lease gets reactivated later. RemotingServices.Disconnect(managedObject, false); // Disconnect the lease for the object. RemotingServices.Disconnect(this); } } #if _DEBUG ~Lease() { BCLDebug.Trace("REMOTE","Lease ",id," Finalize"); } #endif internal void RenewOnCall() { lock(this) { //BCLDebug.Trace("REMOTE","Lease ",id," RenewOnCall state ",((Enum)state).ToString()); if (state == LeaseState.Initial || state == LeaseState.Expired) return; AddTime(renewOnCallTime); } } internal void LeaseExpired(DateTime now) { lock(this) { BCLDebug.Trace("REMOTE","Lease ",id," LeaseExpired state ",((Enum)state).ToString()); if (state == LeaseState.Expired) return; // There is a small window between the time the leaseManager // thread examines all the leases and tests for expiry and // when an indivisual lease is locked for expiry. The object // could get marshal-ed in this time which would reset its lease // Therefore we check again to see if we should indeed proceed // with the expire code (using the same value of 'now' as used // by the leaseManager thread) if (leaseTime.CompareTo(now) < 0) ProcessNextSponsor(); } } internal delegate TimeSpan AsyncRenewal(ILease lease); internal void SponsorCall(ISponsor sponsor) { BCLDebug.Trace("REMOTE","Lease ",id," SponsorCall state ",((Enum)state).ToString()); bool exceptionOccurred = false; if (state == LeaseState.Expired) return; lock(sponsorTable) { try { Object sponsorId = GetSponsorId(sponsor); sponsorCallThread = Thread.CurrentThread.GetHashCode(); AsyncRenewal ar = new AsyncRenewal(sponsor.Renewal); SponsorStateInfo sponsorStateInfo = (SponsorStateInfo)sponsorTable[sponsorId]; sponsorStateInfo.sponsorState = SponsorState.Waiting; // The first parameter should be the lease we are trying to renew. IAsyncResult iar = ar.BeginInvoke(this, new AsyncCallback(this.SponsorCallback), null); if ((sponsorStateInfo.sponsorState == SponsorState.Waiting) && (state != LeaseState.Expired)) { // Even if we get here, the operation could still complete before // we call the the line below. This seems to be a ----. // Sponsor could have completed before statement is reached, so only execute // if the sponsor state is still waiting leaseManager.RegisterSponsorCall(this, sponsorId, sponsorshipTimeout); } sponsorCallThread = 0; }catch(Exception) { // Sponsor not avaiable exceptionOccurred = true; sponsorCallThread = 0; } } if (exceptionOccurred) { BCLDebug.Trace("REMOTE","Lease ",id," SponsorCall Sponsor Exception "); Unregister(sponsor); ProcessNextSponsor(); } } internal void SponsorTimeout(Object sponsorId) { lock (this) { if (!sponsorTable.ContainsKey(sponsorId)) return; lock(sponsorTable) { SponsorStateInfo sponsorStateInfo = (SponsorStateInfo)sponsorTable[sponsorId]; BCLDebug.Trace("REMOTE","Lease ",id," SponsorTimeout sponsorState ",((Enum)sponsorStateInfo.sponsorState).ToString()); if (sponsorStateInfo.sponsorState == SponsorState.Waiting) { Unregister(GetSponsorFromId(sponsorId)); ProcessNextSponsor(); } } } } private void ProcessNextSponsor() { BCLDebug.Trace("REMOTE","Lease ",id," ProcessNextSponsor"); Object largestSponsor = null; TimeSpan largestRenewalTime = TimeSpan.Zero; lock(sponsorTable) { IDictionaryEnumerator e = sponsorTable.GetEnumerator(); // Find sponsor with largest previous renewal value while(e.MoveNext()) { Object sponsorId = e.Key; SponsorStateInfo sponsorStateInfo = (SponsorStateInfo)e.Value; if ((sponsorStateInfo.sponsorState == SponsorState.Initial) && (largestRenewalTime == TimeSpan.Zero)) { largestRenewalTime = sponsorStateInfo.renewalTime; largestSponsor = sponsorId; } else if (sponsorStateInfo.renewalTime > largestRenewalTime) { largestRenewalTime = sponsorStateInfo.renewalTime; largestSponsor = sponsorId; } } } if (largestSponsor != null) SponsorCall(GetSponsorFromId(largestSponsor)); else { // No more sponsors to try, Cancel BCLDebug.Trace("REMOTE","Lease ",id," ProcessNextSponsor no more sponsors"); Cancel(); } } // This gets called when we explicitly transfer the call back from the // called function to a threadpool thread. internal void SponsorCallback(Object obj) { SponsorCallback((IAsyncResult)obj); } // On another thread internal void SponsorCallback(IAsyncResult iar) { BCLDebug.Trace("REMOTE","Lease ",id," SponsorCallback IAsyncResult ",iar," state ",((Enum)state).ToString()); if (state == LeaseState.Expired) { return; } int thisThread = Thread.CurrentThread.GetHashCode(); if (thisThread == sponsorCallThread) { // Looks like something went wrong and the thread that // did the AsyncRenewal::BeginInvoke is executing the callback // We will queue the work to the thread pool (otherwise there // is a possibility of stack overflow if all sponsors are down) WaitCallback threadFunc = new WaitCallback(this.SponsorCallback); ThreadPool.QueueUserWorkItem(threadFunc, iar); return; } AsyncResult asyncResult = (AsyncResult)iar; AsyncRenewal ar = (AsyncRenewal)asyncResult.AsyncDelegate; ISponsor sponsor = (ISponsor)ar.Target; SponsorStateInfo sponsorStateInfo = null; if (iar.IsCompleted) { // Sponsor came back with renewal BCLDebug.Trace("REMOTE","Lease ",id," SponsorCallback sponsor completed"); bool exceptionOccurred = false; TimeSpan renewalTime = TimeSpan.Zero; try { renewalTime = (TimeSpan)ar.EndInvoke(iar); }catch(Exception) { // Sponsor not avaiable exceptionOccurred = true; } if (exceptionOccurred) { BCLDebug.Trace("REMOTE","Lease ",id," SponsorCallback Sponsor Exception "); Unregister(sponsor); ProcessNextSponsor(); } else { Object sponsorId = GetSponsorId(sponsor); lock(sponsorTable) { if (sponsorTable.ContainsKey(sponsorId)) { sponsorStateInfo = (SponsorStateInfo)sponsorTable[sponsorId]; sponsorStateInfo.sponsorState = SponsorState.Completed; sponsorStateInfo.renewalTime = renewalTime; } else { // Sponsor was deleted, possibly from a sponsor time out } } if (sponsorStateInfo == null) { // Sponsor was deleted ProcessNextSponsor(); } else if (sponsorStateInfo.renewalTime == TimeSpan.Zero) { BCLDebug.Trace("REMOTE","Lease ",id," SponsorCallback sponsor did not renew "); Unregister(sponsor); ProcessNextSponsor(); } else RenewInternal(sponsorStateInfo.renewalTime); } } else { // Sponsor timed out // Note time outs should be handled by the LeaseManager BCLDebug.Trace("REMOTE","Lease ",id," SponsorCallback sponsor did not complete, timed out"); Unregister(sponsor); ProcessNextSponsor(); } } private void AddTime(TimeSpan renewalSpan) { if (state == LeaseState.Expired) return; DateTime now = DateTime.UtcNow; DateTime oldLeaseTime = leaseTime; DateTime renewTime = now.Add(renewalSpan); if (leaseTime.CompareTo(renewTime) < 0) { leaseManager.ChangedLeaseTime(this, renewTime); leaseTime = renewTime; state = LeaseState.Active; } //BCLDebug.Trace("REMOTE","Lease ",id," AddTime renewalSpan ",renewalSpan," current Time ",now," old leaseTime ",oldLeaseTime," new leaseTime ",leaseTime," state ",((Enum)state).ToString()); } [Serializable] internal enum SponsorState { Initial = 0, Waiting = 1, Completed = 2 } internal sealed class SponsorStateInfo { internal TimeSpan renewalTime; internal SponsorState sponsorState; internal SponsorStateInfo(TimeSpan renewalTime, SponsorState sponsorState) { this.renewalTime = renewalTime; this.sponsorState = sponsorState; } } } internal class LeaseSink : IMessageSink { Lease lease = null; IMessageSink nextSink = null; public LeaseSink(Lease lease, IMessageSink nextSink) { this.lease = lease; this.nextSink = nextSink; } //IMessageSink methods public IMessage SyncProcessMessage(IMessage msg) { //BCLDebug.Trace("REMOTE","Lease ",id," SyncProcessMessage"); lease.RenewOnCall(); return nextSink.SyncProcessMessage(msg); } public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink) { //BCLDebug.Trace("REMOTE","Lease ",id," AsyncProcessMessage"); lease.RenewOnCall(); return nextSink.AsyncProcessMessage(msg, replySink); } public IMessageSink NextSink { get { //BCLDebug.Trace("REMOTE","Lease ",id," NextSink"); return nextSink; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- GridViewHeaderRowPresenter.cs
- ChannelTracker.cs
- QuaternionKeyFrameCollection.cs
- QuerySettings.cs
- XslAst.cs
- UnsafeNativeMethods.cs
- JoinGraph.cs
- TaiwanLunisolarCalendar.cs
- BitmapFrame.cs
- Native.cs
- TransformedBitmap.cs
- PagedDataSource.cs
- SecurityDocument.cs
- PropertyPathWorker.cs
- ArcSegment.cs
- RevocationPoint.cs
- TreeViewImageKeyConverter.cs
- GradientSpreadMethodValidation.cs
- NameValueSectionHandler.cs
- InheritanceContextChangedEventManager.cs
- ValidationRuleCollection.cs
- EntityViewGenerationConstants.cs
- CRYPTPROTECT_PROMPTSTRUCT.cs
- NullableBoolConverter.cs
- ToolStripCustomTypeDescriptor.cs
- RootProfilePropertySettingsCollection.cs
- InputBinding.cs
- ContentType.cs
- ListSourceHelper.cs
- DataGridCell.cs
- MultipleCopiesCollection.cs
- TextOutput.cs
- PtsHost.cs
- FormattedTextSymbols.cs
- SoapEnumAttribute.cs
- DecimalConstantAttribute.cs
- TextParaClient.cs
- DBCSCodePageEncoding.cs
- ArithmeticException.cs
- ExpandoClass.cs
- PointLight.cs
- GeneralTransform2DTo3D.cs
- DataObjectAttribute.cs
- ValueUtilsSmi.cs
- RightNameExpirationInfoPair.cs
- BitArray.cs
- CollectionViewSource.cs
- FloaterParaClient.cs
- KeyedHashAlgorithm.cs
- OutputScopeManager.cs
- ClientApiGenerator.cs
- PackageDigitalSignatureManager.cs
- Message.cs
- ScriptDescriptor.cs
- ResourceLoader.cs
- HijriCalendar.cs
- LayoutEngine.cs
- XmlProcessingInstruction.cs
- ColorContextHelper.cs
- Panel.cs
- SizeChangedInfo.cs
- PerformanceCounter.cs
- BinaryUtilClasses.cs
- RulePatternOps.cs
- WrapPanel.cs
- XmlEnumAttribute.cs
- DefaultSection.cs
- Properties.cs
- HtmlCommandAdapter.cs
- OAVariantLib.cs
- XmlDeclaration.cs
- FontFamilyValueSerializer.cs
- OracleParameterCollection.cs
- Compiler.cs
- StaticDataManager.cs
- SByteConverter.cs
- TraversalRequest.cs
- XmlWrappingWriter.cs
- TextEffect.cs
- LogEntry.cs
- AuthenticationModuleElement.cs
- TimeoutValidationAttribute.cs
- DesignTimeTemplateParser.cs
- CellParaClient.cs
- TextBox.cs
- Nullable.cs
- ComNativeDescriptor.cs
- NetNamedPipeSecurityMode.cs
- GestureRecognitionResult.cs
- DesignerVerbToolStripMenuItem.cs
- DesignerAutoFormat.cs
- ExecutionPropertyManager.cs
- RefreshEventArgs.cs
- ParameterModifier.cs
- GridProviderWrapper.cs
- ProcessModuleCollection.cs
- LockedBorderGlyph.cs
- AsymmetricKeyExchangeFormatter.cs
- DataRowCollection.cs
- LoginCancelEventArgs.cs