Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / 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
- XmlSchemaObjectCollection.cs
- TemplateBindingExpressionConverter.cs
- DbSource.cs
- DiscoveryProxy.cs
- ServiceDescriptions.cs
- GeneralTransformGroup.cs
- XmlAtomErrorReader.cs
- OdbcError.cs
- OletxResourceManager.cs
- HtmlElement.cs
- ASCIIEncoding.cs
- Vector3DCollectionConverter.cs
- InsufficientMemoryException.cs
- Array.cs
- RootAction.cs
- XmlILConstructAnalyzer.cs
- HtmlInputFile.cs
- _TLSstream.cs
- EdmComplexPropertyAttribute.cs
- LoginView.cs
- LinkedResource.cs
- ValueConversionAttribute.cs
- Point4DValueSerializer.cs
- StringFormat.cs
- ListCollectionView.cs
- DefinitionBase.cs
- DecimalConstantAttribute.cs
- ResizeBehavior.cs
- ValidationHelpers.cs
- NullReferenceException.cs
- AdapterUtil.cs
- ImageCollectionEditor.cs
- HtmlTableCell.cs
- XmlSchemaAnyAttribute.cs
- PointKeyFrameCollection.cs
- PanningMessageFilter.cs
- DoubleUtil.cs
- HwndHost.cs
- TextBoxBase.cs
- RangeContentEnumerator.cs
- FilterUserControlBase.cs
- ILGenerator.cs
- smtppermission.cs
- SelectionRange.cs
- ControlValuePropertyAttribute.cs
- CodeParameterDeclarationExpression.cs
- DiscardableAttribute.cs
- ObjectViewEntityCollectionData.cs
- XsdDuration.cs
- FileUtil.cs
- HtmlWindowCollection.cs
- _LocalDataStoreMgr.cs
- SerializationStore.cs
- ApplyTemplatesAction.cs
- MappingException.cs
- XmlSchemaSimpleContentRestriction.cs
- TransactionProxy.cs
- DataGridCommandEventArgs.cs
- TranslateTransform3D.cs
- _RequestCacheProtocol.cs
- NativeStructs.cs
- WebEventCodes.cs
- BezierSegment.cs
- SecurityState.cs
- sqlcontext.cs
- XmlWrappingWriter.cs
- CompilerGlobalScopeAttribute.cs
- RoleGroupCollectionEditor.cs
- WinFormsUtils.cs
- SQLResource.cs
- InputReferenceExpression.cs
- UserPersonalizationStateInfo.cs
- CompareValidator.cs
- NonSerializedAttribute.cs
- FixedPage.cs
- DocumentXmlWriter.cs
- CTreeGenerator.cs
- XmlConverter.cs
- _DomainName.cs
- ToolStripComboBox.cs
- BindToObject.cs
- SqlLiftIndependentRowExpressions.cs
- TagMapInfo.cs
- URI.cs
- HtmlInputControl.cs
- TableLayoutPanelCellPosition.cs
- DependsOnAttribute.cs
- FlowSwitch.cs
- RuleSettings.cs
- ImageAttributes.cs
- CompletionProxy.cs
- PolyLineSegment.cs
- bidPrivateBase.cs
- PassportAuthenticationModule.cs
- HttpValueCollection.cs
- WebPartVerbCollection.cs
- LocationFactory.cs
- PasswordBox.cs
- StylusPointPropertyId.cs
- PixelShader.cs