Code:
/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / clr / src / BCL / System / Runtime / Remoting / Lease.cs / 2 / 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 race. // 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; } } } }
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- AsyncStreamReader.cs
- NavigatorOutput.cs
- RowBinding.cs
- SafePEFileHandle.cs
- SqlMethodTransformer.cs
- ObservableDictionary.cs
- TemplatePropertyEntry.cs
- PreservationFileReader.cs
- ShaderRenderModeValidation.cs
- Events.cs
- QilBinary.cs
- IntPtr.cs
- MultiBindingExpression.cs
- Stylus.cs
- DependencyObjectType.cs
- SvcMapFile.cs
- UnknownWrapper.cs
- shaperfactoryquerycacheentry.cs
- XmlChildNodes.cs
- DataSourceUtil.cs
- XmlSchemaExporter.cs
- ZipFileInfoCollection.cs
- Compiler.cs
- HtmlInputRadioButton.cs
- HttpContext.cs
- Frame.cs
- GroupDescription.cs
- CompositionAdorner.cs
- SynchronousReceiveElement.cs
- safesecurityhelperavalon.cs
- SerializerDescriptor.cs
- CharAnimationBase.cs
- Stack.cs
- TextServicesPropertyRanges.cs
- CodeRemoveEventStatement.cs
- SimpleBitVector32.cs
- SimpleWebHandlerParser.cs
- ParallelQuery.cs
- DataGridViewHitTestInfo.cs
- JoinGraph.cs
- XPathNavigator.cs
- SoundPlayerAction.cs
- DataRowView.cs
- PropertyEmitterBase.cs
- SafeEventLogReadHandle.cs
- ExtenderControl.cs
- SQLBoolean.cs
- SqlMetaData.cs
- CommandSet.cs
- TargetException.cs
- SmtpTransport.cs
- InputLanguageEventArgs.cs
- Helpers.cs
- CachedPathData.cs
- SoapConverter.cs
- CancelEventArgs.cs
- EntityContainerEmitter.cs
- XmlTextReader.cs
- DataProtection.cs
- SponsorHelper.cs
- WindowHideOrCloseTracker.cs
- CapabilitiesState.cs
- _NativeSSPI.cs
- entityreference_tresulttype.cs
- SingleConverter.cs
- ConfigurationElementCollection.cs
- MetadataProperty.cs
- ReferentialConstraint.cs
- MergablePropertyAttribute.cs
- ObjectDataSourceView.cs
- FixedTextContainer.cs
- ComNativeDescriptor.cs
- HttpContext.cs
- Propagator.Evaluator.cs
- Pkcs7Recipient.cs
- GeneralTransform3DTo2D.cs
- Attributes.cs
- X500Name.cs
- VisualBasicValue.cs
- Freezable.cs
- WorkflowInstance.cs
- SettingsBindableAttribute.cs
- QualifierSet.cs
- HttpCacheParams.cs
- TraceSwitch.cs
- XmlSerializerOperationGenerator.cs
- ListBoxItemWrapperAutomationPeer.cs
- PropertyDescriptor.cs
- FileSystemEventArgs.cs
- SqlCacheDependencyDatabase.cs
- HttpCachePolicy.cs
- ServiceX509SecurityTokenProvider.cs
- QilPatternVisitor.cs
- HScrollProperties.cs
- ToolStripSeparatorRenderEventArgs.cs
- WebPartConnectionsCloseVerb.cs
- ReferenceService.cs
- BrowserCapabilitiesFactoryBase.cs
- SoapAttributeAttribute.cs
- BinaryFormatter.cs