Code:
/ FX-1434 / FX-1434 / 1.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
- ETagAttribute.cs
- SamlNameIdentifierClaimResource.cs
- Maps.cs
- DynamicField.cs
- _FixedSizeReader.cs
- LinkButton.cs
- FileLevelControlBuilderAttribute.cs
- OledbConnectionStringbuilder.cs
- HttpDebugHandler.cs
- XmlLanguage.cs
- SHA256CryptoServiceProvider.cs
- CategoryGridEntry.cs
- SocketException.cs
- DataKey.cs
- NameTable.cs
- CursorConverter.cs
- ElementNotEnabledException.cs
- MULTI_QI.cs
- CqlLexer.cs
- BinaryCommonClasses.cs
- DataGridViewUtilities.cs
- ContentPosition.cs
- WhiteSpaceTrimStringConverter.cs
- SerializationSectionGroup.cs
- SafeViewOfFileHandle.cs
- RelationshipNavigation.cs
- OleDbParameterCollection.cs
- DiscoveryDocumentReference.cs
- SplitContainer.cs
- WindowsFormsLinkLabel.cs
- ElementProxy.cs
- LayoutDump.cs
- storepermission.cs
- Win32SafeHandles.cs
- DisplayToken.cs
- Transactions.cs
- DrawingContextDrawingContextWalker.cs
- ExtentCqlBlock.cs
- TextDocumentView.cs
- DivideByZeroException.cs
- XmlSchemaObjectTable.cs
- XmlSchemaExternal.cs
- ListViewItemEventArgs.cs
- PropertyToken.cs
- SessionPageStatePersister.cs
- ObjectItemNoOpAssemblyLoader.cs
- Trigger.cs
- BuildProviderAppliesToAttribute.cs
- AuthorizationSection.cs
- QueryableDataSource.cs
- ConfigurationElementProperty.cs
- DatatypeImplementation.cs
- ListView.cs
- TraceFilter.cs
- OpenFileDialog.cs
- DoubleIndependentAnimationStorage.cs
- SqlNodeAnnotation.cs
- WebPartEventArgs.cs
- DBPropSet.cs
- ComPlusDiagnosticTraceSchemas.cs
- BitmapImage.cs
- MachineKey.cs
- GlyphManager.cs
- RelationshipDetailsCollection.cs
- DocumentCollection.cs
- MouseCaptureWithinProperty.cs
- ObjectQuery.cs
- ProgressBar.cs
- HttpModuleCollection.cs
- CaseInsensitiveHashCodeProvider.cs
- TCPListener.cs
- SqlInternalConnectionSmi.cs
- Pipe.cs
- LiteralControl.cs
- TemplateParser.cs
- HttpDictionary.cs
- QueryHandler.cs
- ListViewCommandEventArgs.cs
- PathBox.cs
- OLEDB_Enum.cs
- GeneralTransform3DTo2DTo3D.cs
- Win32.cs
- ClearTypeHintValidation.cs
- AsyncOperation.cs
- BlockUIContainer.cs
- GridViewRowPresenter.cs
- QueryPrefixOp.cs
- Stroke2.cs
- OutputCacheProfile.cs
- BezierSegment.cs
- GlobalizationAssembly.cs
- SingleAnimationBase.cs
- DataGridCheckBoxColumn.cs
- LineServicesCallbacks.cs
- MetadataPropertyCollection.cs
- GridItemProviderWrapper.cs
- XmlReaderSettings.cs
- DbParameterCollectionHelper.cs
- ProfilePropertySettings.cs
- GeneralTransform3DGroup.cs