* LifetimeServices.cs: Implemented all methods.
authorLluis Sanchez <lluis@novell.com>
Tue, 4 Feb 2003 12:53:28 +0000 (12:53 -0000)
committerLluis Sanchez <lluis@novell.com>
Tue, 4 Feb 2003 12:53:28 +0000 (12:53 -0000)
* LeaseSink.cs: implemented renewal of lease.
* Lease.cs: Added. It is an implementation of ILease.
* LeaseManager.cs: Added. Tracks lifetime of remote objects.

svn path=/trunk/mcs/; revision=11198

mcs/class/corlib/System.Runtime.Remoting.Lifetime/ChangeLog
mcs/class/corlib/System.Runtime.Remoting.Lifetime/Lease.cs [new file with mode: 0644]
mcs/class/corlib/System.Runtime.Remoting.Lifetime/LeaseManager.cs [new file with mode: 0644]
mcs/class/corlib/System.Runtime.Remoting.Lifetime/LeaseSink.cs
mcs/class/corlib/System.Runtime.Remoting.Lifetime/LifetimeServices.cs

index b9e34d56ec2a84139a0567172557a0e7ef8e28b1..9f5769845f22556cc7ff1adf0c1bdf73074a8cfe 100644 (file)
@@ -1,3 +1,10 @@
+2003-02-04  Lluis Sanchez Gual <lluis@ideary.com>
+
+       * LifetimeServices.cs: Implemented all methods.
+       * LeaseSink.cs: implemented renewal of lease.
+       * Lease.cs: Added. It is an implementation of ILease.
+       * LeaseManager.cs: Added. Tracks lifetime of remote objects.
+
 2003-01-29  Lluis Sanchez Gual <lluis@ideary.com>
 
        * LifetimeServices.cs: Implemented some basic properties.
diff --git a/mcs/class/corlib/System.Runtime.Remoting.Lifetime/Lease.cs b/mcs/class/corlib/System.Runtime.Remoting.Lifetime/Lease.cs
new file mode 100644 (file)
index 0000000..849bd0e
--- /dev/null
@@ -0,0 +1,191 @@
+//
+// System.Runtime.Remoting.Identity.cs
+//
+// Author: Lluis Sanchez Gual (lluis@ideary.com)
+//
+// (C) 2003, Lluis Sanchez Gual
+//
+\r
+using System;\r
+using System.Threading;\r
+using System.Collections;\r
+\r
+namespace System.Runtime.Remoting.Lifetime\r
+{\r
+       internal class Lease : MarshalByRefObject, ILease\r
+       {\r
+               DateTime _leaseExpireTime;
+               LeaseState _currentState;
+               TimeSpan _initialLeaseTime;
+               TimeSpan _renewOnCallTime;
+               TimeSpan _sponsorshipTimeout;
+               ArrayList _sponsors;
+               Queue _renewingSponsors;
+               RenewalDelegate _renewalDelegate;
+
+               delegate TimeSpan RenewalDelegate(ILease lease);
+\r
+               public Lease()\r
+               {\r
+                       _currentState = LeaseState.Initial;\r
+                       _initialLeaseTime = LifetimeServices.LeaseTime;\r
+                       _renewOnCallTime = LifetimeServices.RenewOnCallTime;\r
+                       _sponsorshipTimeout = LifetimeServices.SponsorshipTimeout;\r
+                       _leaseExpireTime = DateTime.Now + _initialLeaseTime;\r
+               }\r
+\r
+               public TimeSpan CurrentLeaseTime 
+               { 
+                       get { return _leaseExpireTime - DateTime.Now; }
+               }
+
+               public LeaseState CurrentState 
+               { 
+                       get { return _currentState; }
+               }
+
+               public void Activate()
+               {
+                       // Called when then Lease is registered in the LeaseManager
+                       _currentState = LeaseState.Active;
+               }
+
+               public TimeSpan InitialLeaseTime 
+               { 
+                       get { return _initialLeaseTime; }
+                       set 
+                       { 
+                               if (_currentState != LeaseState.Initial)
+                                       throw new RemotingException ("InitialLeaseTime property can only be set when the lease is in initial state; state is " + _currentState + ".");
+
+                               _initialLeaseTime = value; 
+                               _leaseExpireTime = DateTime.Now + _initialLeaseTime;\r
+                               if (value == TimeSpan.Zero) _currentState = LeaseState.Null;
+                       }
+               }
+
+               public TimeSpan RenewOnCallTime 
+               { 
+                       get { return _renewOnCallTime; }
+                       set 
+                       { 
+                               if (_currentState != LeaseState.Initial)
+                                       throw new RemotingException ("RenewOnCallTime property can only be set when the lease is in initial state; state is " + _currentState + ".");
+
+                               _renewOnCallTime = value; 
+                       }
+               }
+
+               public TimeSpan SponsorshipTimeout 
+               {
+                       get { return _sponsorshipTimeout; }
+                       set 
+                       { 
+                               if (_currentState != LeaseState.Initial)
+                                       throw new RemotingException ("SponsorshipTimeout property can only be set when the lease is in initial state; state is " + _currentState + ".");
+
+                               _sponsorshipTimeout = value; 
+                       }
+               }
+
+               public void Register (ISponsor obj)
+               {
+                       Register (obj, TimeSpan.Zero);
+               }
+
+               public void Register (ISponsor obj, TimeSpan renewalTime)
+               {
+                       if (_sponsors == null) \r
+                       {
+                               lock (this) {
+                                       if (_sponsors == null)
+                                               _sponsors = new ArrayList();
+                               }
+                       }
+
+                       lock (_sponsors.SyncRoot) {
+                               _sponsors.Add (obj);
+                       }
+
+                       if (renewalTime != TimeSpan.Zero)
+                               Renew (renewalTime);
+               }
+
+               public TimeSpan Renew (TimeSpan renewalTime)
+               {
+                       DateTime newTime = DateTime.Now + renewalTime;
+                       if (newTime > _leaseExpireTime) _leaseExpireTime = newTime;
+                       return CurrentLeaseTime;
+               }
+
+               public void Unregister (ISponsor obj)
+               {
+                       if (_sponsors == null) return;
+                       
+                       lock (_sponsors.SyncRoot) {
+                               _sponsors.Remove (obj);
+                       }
+               }
+
+               internal void UpdateState ()
+               {
+                       // Called by the lease manager to update the state of this lease,
+                       // basically for knowing if it has expired
+
+                       if (_currentState != LeaseState.Active) return;
+                       if (CurrentLeaseTime > TimeSpan.Zero) return;
+
+                       // Expired. Try to renew using sponsors.
+
+                       if (_sponsors != null)
+                       {
+                               _currentState = LeaseState.Renewing;
+                               lock (_sponsors.SyncRoot) {
+                                       _renewingSponsors = new Queue (_sponsors);
+                               }
+                               CheckNextSponsor ();
+                       }
+                       else
+                               _currentState = LeaseState.Expired;
+               }
+
+               void CheckNextSponsor ()
+               {
+                       if (_renewingSponsors.Count == 0) {
+                               _currentState = LeaseState.Expired;
+                               _renewingSponsors = null;
+                               return;
+                       }
+
+                       ISponsor nextSponsor = (ISponsor) _renewingSponsors.Peek();
+                       _renewalDelegate = new RenewalDelegate (nextSponsor.Renewal);
+                       IAsyncResult ar = _renewalDelegate.BeginInvoke (this, null, null);
+                       ThreadPool.RegisterWaitForSingleObject (ar.AsyncWaitHandle, new WaitOrTimerCallback (ProcessSponsorResponse), ar, _sponsorshipTimeout, true);
+               }
+
+               void ProcessSponsorResponse (object state, bool timedOut)
+               {
+                       if (!timedOut)
+                       {
+                               try
+                               {
+                                       IAsyncResult ar = (IAsyncResult)state;
+                                       TimeSpan newSpan = _renewalDelegate.EndInvoke (ar);
+                                       if (newSpan != TimeSpan.Zero)
+                                       {
+                                               Renew (newSpan);
+                                               _currentState = LeaseState.Active;
+                                               _renewingSponsors = null;
+                                               return;
+                                       }
+                               }
+                               catch { }
+                       }
+
+                       // Sponsor failed, timed out, or returned TimeSpan.Zero
+
+                       Unregister ((ISponsor) _renewingSponsors.Dequeue());    // Drop the sponsor
+                       CheckNextSponsor ();
+               }
+       }\r
+}\r
diff --git a/mcs/class/corlib/System.Runtime.Remoting.Lifetime/LeaseManager.cs b/mcs/class/corlib/System.Runtime.Remoting.Lifetime/LeaseManager.cs
new file mode 100644 (file)
index 0000000..c8699eb
--- /dev/null
@@ -0,0 +1,75 @@
+//
+// System.Runtime.Remoting.Identity.cs
+//
+// Author: Lluis Sanchez Gual (lluis@ideary.com)
+//
+// (C) 2003, Lluis Sanchez Gual
+//\r
+\r
+using System;\r
+using System.Threading;\r
+using System.Collections;\r
+using System.Runtime.Remoting;\r
+\r
+namespace System.Runtime.Remoting.Lifetime\r
+{\r
+       internal class LeaseManager\r
+       {\r
+               ArrayList _objects = new ArrayList();\r
+               Timer _timer = null;\r
+\r
+               public void SetPollTime (TimeSpan timeSpan)\r
+               {\r
+                       lock (_objects.SyncRoot) \r
+                       {\r
+                               if (_timer != null)\r
+                                       _timer.Change (timeSpan,timeSpan);\r
+                       }\r
+               }\r
+\r
+               public void TrackLifetime (ServerIdentity identity)\r
+               {\r
+                       lock (_objects.SyncRoot)\r
+                       {\r
+                               identity.Lease.Activate();\r
+                               _objects.Add (identity);\r
+\r
+                               if (_timer == null) StartManager();\r
+                       }\r
+               }\r
+\r
+               public void StartManager()\r
+               {\r
+                       _timer = new Timer (new TimerCallback (ManageLeases), null, LifetimeServices.LeaseManagerPollTime,LifetimeServices.LeaseManagerPollTime);\r
+               }\r
+\r
+               public void StopManager()\r
+               {\r
+                       _timer.Dispose();\r
+                       _timer = null;\r
+               }\r
+\r
+               public void ManageLeases(object state)\r
+               {\r
+                       lock (_objects.SyncRoot)\r
+                       {\r
+                               int n=0;\r
+                               while (n < _objects.Count)\r
+                               {\r
+                                       ServerIdentity ident = (ServerIdentity)_objects[n];\r
+                                       ident.Lease.UpdateState();\r
+                                       if (ident.Lease.CurrentState == LeaseState.Expired)\r
+                                       {\r
+                                               _objects.RemoveAt (n);\r
+                                               ident.OnLifetimeExpired ();\r
+                                       }\r
+                                       else\r
+                                               n++;\r
+                               }\r
+\r
+                               if (_objects.Count == 0) \r
+                                       StopManager();\r
+                       }\r
+               }\r
+       }\r
+}\r
index c50c98f3dd2cf080882b154fa120aaa61af5c5a1..44d717a11212c6ade2ea72a75b5128509d1da1f0 100644 (file)
@@ -1,7 +1,7 @@
 //
 // System.Runtime.Remoting.LeaseSink.cs
 //
-// Author: Lluis Sanchez Gual (lsg@ctv.es)
+// Author: Lluis Sanchez Gual (lluis@ideary.com)
 //
 // (C) 2002, Lluis Sanchez Gual
 //
@@ -23,18 +23,27 @@ namespace System.Runtime.Remoting.Lifetime
                        _nextSink = nextSink;
                }
 
-               [MonoTODO("Manage leases")]
                public IMessage SyncProcessMessage (IMessage msg)
                {
+                       RenewLease (msg);
                        return _nextSink.SyncProcessMessage (msg);
                }
 
-               [MonoTODO("Manage leases")]
                public IMessageCtrl AsyncProcessMessage (IMessage msg, IMessageSink replySink)
                {
+                       RenewLease (msg);
                        return _nextSink.AsyncProcessMessage (msg, replySink);
                }
 
+               void RenewLease (IMessage msg)
+               {
+                       ServerIdentity identity = RemotingServices.GetMessageTargetIdentity (msg);
+
+                       ILease lease = identity.Lease;
+                       if (lease != null && lease.CurrentLeaseTime < lease.RenewOnCallTime)
+                               lease.Renew (lease.RenewOnCallTime);
+               }
+
                public IMessageSink NextSink 
                { 
                        get { return _nextSink; }
index d670832ccfad32a6dff0c31b43360c2d1d534517..e0c6bb0b370bd6350c7715a70f04b781ff82a7a3 100644 (file)
@@ -19,56 +19,52 @@ namespace System.Runtime.Remoting.Lifetime {
                private static TimeSpan _renewOnCallTime;
                private static TimeSpan _sponsorshipTimeout;
 
-               public LifetimeServices ()
+               private static LeaseManager _leaseManager = new LeaseManager();
+
+               static LifetimeServices ()
                {
+                       _leaseManagerPollTime = TimeSpan.FromSeconds (10);
+                       _leaseTime = TimeSpan.FromMinutes (5);
+                       _renewOnCallTime = TimeSpan.FromMinutes (2);
+                       _sponsorshipTimeout = TimeSpan.FromMinutes (2);
+                       // TODO: read values form config file
                }
 
-               public static TimeSpan LeaseManagerPollTime {
-                       get {
-                               return _leaseManagerPollTime;
-                       }
-
-                       set {
-                               _leaseManagerPollTime = value;
-                       }
+               public LifetimeServices ()
+               {
                }
 
-               public static TimeSpan LeaseTime {
-                       get {
-                               return _leaseTime;
-                       }
+               public static TimeSpan LeaseManagerPollTime 
+               {
+                       get { return _leaseManagerPollTime; }
 
                        set {
-                               _leaseTime = value;
+                               _leaseManagerPollTime = value;
+                               _leaseManager.SetPollTime (value);
                        }
                }
 
-               public static TimeSpan RenewOnCallTime {
-                       get {
-                               return _renewOnCallTime;
-                       }
-                       
-                       set {
-                               _renewOnCallTime = value;
-                       }
+               public static TimeSpan LeaseTime 
+               {
+                       get { return _leaseTime; }
+                       set { _leaseTime = value; }
                }
 
-               public static TimeSpan SponsorshipTimeout {
-                       get {
-                               return _sponsorshipTimeout;
-                       }
-
-                       set {
-                               _sponsorshipTimeout = value;
-                       }
+               public static TimeSpan RenewOnCallTime 
+               {
+                       get { return _renewOnCallTime; }
+                       set { _renewOnCallTime = value; }
                }
 
-               internal static void TrackLifetime (Identity identity)
+               public static TimeSpan SponsorshipTimeout 
                {
+                       get { return _sponsorshipTimeout; }
+                       set { _sponsorshipTimeout = value; }
                }
 
-               internal static void ManageLeases ()
+               internal static void TrackLifetime (ServerIdentity identity)
                {
+                       _leaseManager.TrackLifetime (identity);
                }
        }
 }