--- /dev/null
+//
+// 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
--- /dev/null
+//
+// 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
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);
}
}
}