public class LeaseRenewalManager extends Object
This class removes much of the administrative burden associated with
lease renewal. Clients of the renewal manager simply give their
leases to the manager and the manager renews each lease as necessary
to achieve a desired expiration time (which may be later
than the lease's current actual expiration time). Failures
encountered while renewing a lease can optionally be reflected to the
client via LeaseRenewalEvent
instances.
Note that this class is not remote. Entities wishing to use this class must create an instance of this class in their own virtual machine to locally manage the leases granted to them. If the virtual machine that the manager was created in exits or crashes, the renewal manager will be destroyed.
The LeaseRenewalManager
distinguishes between two time
values associated with lease expiration: the desired
expiration time for the lease, and the actual
expiration time granted when the lease is created or last
renewed. The desired expiration represents when the client would like
the lease to expire. The actual expiration represents when the lease
is going to expire if it is not renewed. Both time values are
absolute times, not relative time durations. The desired expiration
time can be retrieved using the renewal manager's
getExpiration
method. The actual expiration time of a
lease object can be retrieved by invoking the lease's
getExpiration
method.
Each lease in the managed set also has two other associated
attributes: a desired renewal duration, and a remaining
desired duration. The desired renewal duration is specified
(directly or indirectly) when the lease is added to the set. This
duration must normally be a positive number; however, it may be
Lease.ANY
if the lease's desired expiration is
Lease.FOREVER
. The remaining desired duration is always
the desired expiration less the current time.
Each time a lease is renewed, the renewal manager will ask for an extension equal to the lease's renewal duration if the renewal duration is:
Lease.ANY
, or
Once a lease is given to a lease renewal manager, the manager will continue to renew the lease until one of the following occurs:
cancel
, clear
, or remove
call on the renewal manager.
LeaseException
.
The methods of this class are appropriately synchronized for concurrent operation. Additionally, this class makes certain guarantees with respect to concurrency. When this class makes a remote call (for example, when requesting the renewal of a lease), any invocations made on the methods of this class will not be blocked. Similarly, this class makes a reentrancy guarantee with respect to the listener objects registered with this class. Should this class invoke a method on a registered listener (a local call), calls from that method to any other method of this class are guaranteed not to result in a deadlock condition.
Lease
,
LeaseException
,
LeaseRenewalEvent
Configuring LeaseRenewalManager
This implementation of
LeaseRenewalManager
supports the
following configuration entries, with component
net.jini.lease.LeaseRenewalManager
:
• |
renewBatchTimeWindow
| |
---|---|---|
  | Type: | long
|
  | Default: | 5 * 60 * 1000 // 5 minutes
|
  | Description: | The maximum number of milliseconds earlier than a lease would typically be renewed to allow it to be renewed in order to permit batching its renewal with that of other leases. The value must not be negative. This entry is obtained in the constructor. |
• |
roundTripTime
| |
---|---|---|
  | Type: | long
|
  | Default: | 10 * 1000 // 10 seconds
|
  | Description: | The worst-case latency, expressed in milliseconds,
to assume for a remote call to renew a lease. The value must be greater
than zero. Unrealistically low values for this entry may
result in failure to renew a lease. Leases managed by this manager
should have durations exceeding the roundTripTime .
This entry is obtained in the constructor.
|
• |
executorService
| |
---|---|---|
  | Type: | ExecutorService
|
  | Default: | new ThreadPoolExecutor(1,11,15,TimeUnit.SECONDS,
new LinkedBlockingQueue())
|
  | Description: | The object used to manage queuing tasks
involved with renewing leases and sending notifications. The
value must not be null . The default value creates
a maximum of 11 threads for performing operations, waits 15
seconds before removing idle threads.
|
Logging
This implementation uses the
Logger
named
net.jini.lease.LeaseRenewalManager
to log information at
the following logging levels:
Level | Description |
---|---|
FAILED
| Lease renewal failure events, or leases that expire before reaching the desired expiration time |
HANDLED
| Lease renewal attempts that produce indefinite exceptions |
FINE
| Adding and removing leases, lease renewal attempts, and desired lease expiration events |
For a way of using the The renewal algorithm
FAILED
and HANDLED
logging
levels in standard logging configuration files, see the LogManager
class.
roundTripTime
, which defaults to ten seconds, represents
the total time to make the remote call.
The following pseudocode was derived from the code which computes
the renewal time. In this code, rtt
represents the
value of the roundTripTime
:
endTime = lease.getExpiration(); delta = endTime - now; if (delta <= rtt * 2) { delta = rtt; } else if (delta <= rtt * 8) { delta /= 2; } else if (delta <= 1000 * 60 * 60 * 24 * 7) { delta /= 8; } else if (delta <= 1000 * 60 * 60 * 24 * 14) { delta = 1000 * 60 * 60 * 24; } else { delta = 1000 * 60 * 60 * 24 * 3; } renew = endTime - delta;It is important to note that
delta
is never less than
rtt
when the renewal time is computed. A lease which
would expire within this time range will be scheduled for immediate
renewal. The use of very short lease durations (at or below rtt
)
can cause the renewal manager to effectively ignore the lease duration
and repeatedly schedule the lease for immediate renewal.
If an attempt to renew a lease fails with an indefinite exception, a renewal is rescheduled with an updated renewal time as computed by the following pseudocode:
delta = endTime - renew; if (delta > rtt) { if (delta <= rtt * 3) { delta = rtt; } else if (delta <= 1000 * 60 * 60) { delta /= 3; } else if (delta <= 1000 * 60 * 60 * 24) { delta = 1000 * 60 * 30; } else if (delta <= 1000 * 60 * 60 * 24 * 7) { delta = 1000 * 60 * 60 * 3; } else { delta = 1000 * 60 * 60 * 8; } renew += delta; }Client leases are maintained in a collection sorted by descending renewal time. A renewal thread is spawned whenever the renewal time of the last lease in the collection is reached. This renewal thread examines all of the leases in the collection whose renewal time falls within
renewBatchTimeWindow
milliseconds of the renewal time of the
last lease. If any of these leases can be batch renewed with the last lease (as
determined by calling the canBatch
method of
the last lease) then a LeaseMap
is created, all eligible leases
are added to it and the LeaseMap.renewAll()
method is called. Otherwise, the
last lease is renewed directly.
The ExecutorService
that manages the renewal threads has a bound on
the number of simultaneous threads it will support. The renewal time of
leases may be adjusted earlier in time to reduce the likelihood that the
renewal of a lease will be delayed due to exhaustion of the thread pool.
Actual renewal times are determined by starting with the lease with the
latest (farthest off) desired renewal time and working backwards. When
computing the actual renewal time for a lease, the renewals of all leases
with later renewal times, which will be initiated during the round trip time
of the current lease's renewal, are considered. If using the desired
renewal time for the current lease would result in more in-progress renewals
than the number of threads allowed, the renewal time of the current lease is
shifted earlier in time, such that the maximum number of threads is not
exceeded.
Constructor and Description |
---|
LeaseRenewalManager()
No-argument constructor that creates an instance of this class
that initially manages no leases.
|
LeaseRenewalManager(Configuration config)
Constructs an instance of this class that initially manages no leases
and that uses
config to control implementation-specific
details of the behavior of the instance created. |
LeaseRenewalManager(Lease lease,
long desiredExpiration,
LeaseListener listener)
Constructs an instance of this class that will initially manage a
single lease.
|
Modifier and Type | Method and Description |
---|---|
void |
cancel(Lease lease)
Removes a given lease from the managed set, and cancels it.
|
void |
clear()
Removes all leases from the managed set of leases.
|
void |
close() |
long |
getExpiration(Lease lease)
Returns the current desired expiration time associated with a
particular lease, (not the actual expiration that was granted
when the lease was created or last renewed).
|
void |
remove(Lease lease)
Removes a given lease from the managed set of leases; but does
not cancel the given lease.
|
void |
renewFor(Lease lease,
long desiredDuration,
LeaseListener listener)
Include a lease in the managed set for a specified duration.
|
void |
renewFor(Lease lease,
long desiredDuration,
long renewDuration,
LeaseListener listener)
Include a lease in the managed set for a specified duration and
with specified renewal duration.
|
void |
renewUntil(Lease lease,
long desiredExpiration,
LeaseListener listener)
Include a lease in the managed set until a specified time.
|
void |
renewUntil(Lease lease,
long desiredExpiration,
long renewDuration,
LeaseListener listener)
Include a lease in the managed set until a specified time and
with a specified renewal duration.
|
void |
setExpiration(Lease lease,
long expiration)
Replaces the current desired expiration of a given lease from the
managed set with a new desired expiration time.
|
public LeaseRenewalManager()
public LeaseRenewalManager(Configuration config) throws ConfigurationException
config
to control implementation-specific
details of the behavior of the instance created.config
- supplies entries that control the configuration of this
instanceConfigurationException
- if a problem occurs when obtaining
entries from the configurationNullPointerException
- if the configuration is null
public LeaseRenewalManager(Lease lease, long desiredExpiration, LeaseListener listener)
renewUntil
method. See renewUntil
for
details on the arguments and what exceptions may be thrown by
this constructor.lease
- reference to the initial lease to managedesiredExpiration
- the desired expiration for
lease
listener
- reference to the LeaseListener
object that will receive notifications of any exceptional
conditions that occur during renewal attempts. If
null
no notifications will be sent.NullPointerException
- if lease
is
null
LeaseListener
,
renewUntil(net.jini.core.lease.Lease, long, net.jini.lease.LeaseListener)
public final void renewUntil(Lease lease, long desiredExpiration, LeaseListener listener)
If desiredExpiration
is Lease.ANY
calling this method is equivalent the following call:
renewUntil(lease, Lease.FOREVER, Lease.ANY, listener)otherwise it is equivalent to this call:
renewUntil(lease, desiredExpiration, Lease.FOREVER, listener)
lease
- the Lease
to be manageddesiredExpiration
- when the client wants the lease to
expire, in milliseconds since the beginning of the epochlistener
- reference to the LeaseListener
object that will receive notifications of any exceptional
conditions that occur during renewal attempts. If
null
no notifications will be sent.NullPointerException
- if lease
is
null
renewUntil(net.jini.core.lease.Lease, long, net.jini.lease.LeaseListener)
public void renewUntil(Lease lease, long desiredExpiration, long renewDuration, LeaseListener listener)
This method takes as arguments: a reference to the lease to
manage, the desired expiration time of the lease, the renewal
duration time for the lease, and a reference to the
LeaseListener
object that will receive notification
of exceptional conditions when attempting to renew this
lease. The LeaseListener
argument may be
null
.
If the lease
argument is null
, a
NullPointerException
will be thrown. If the
desiredExpiration
argument is
Lease.FOREVER
, the renewDuration
argument may be Lease.ANY
or any positive value;
otherwise, the renewDuration
argument must be a
positive value. If the renewDuration
argument does
not meet these requirements, an
IllegalArgumentException
will be thrown.
If the lease passed to this method is already in the set of managed leases, the listener object, the desired expiration, and the renewal duration associated with that lease will be replaced with the new listener, desired expiration, and renewal duration.
The lease will remain in the set until one of the following occurs:
cancel
, clear
, or
remove
call on the renewal manager.
LeaseException
.
This method will interpret the value of the
desiredExpiration
argument as the desired absolute
system time after which the lease is no longer valid. This
argument provides the ability to indicate an expiration time that
extends beyond the actual expiration of the lease. If the value
passed for this argument does indeed extend beyond the lease's
actual expiration time, then the lease will be systematically
renewed at appropriate times until one of the conditions listed
above occurs. If the value is less than or equal to the actual
expiration time, nothing will be done to modify the time when the
lease actually expires. That is, the lease will not be renewed
with an expiration time that is less than the actual expiration
time of the lease at the time of the call.
If the LeaseListener
argument is a
non-null
object reference, it will receive
notification of exceptional conditions occurring upon a renewal
attempt of the lease. In particular, exceptional conditions
include the reception of a LeaseException
, bad
object exception, or bad invocation exception (collectively these
are referred to as definite exceptions) during a renewal
attempt or the lease's actual expiration being reached before its
desired expiration.
If a definite exception occurs during a lease renewal request,
the exception will be wrapped in an instance of the
LeaseRenewalEvent
class and sent to the listener.
If an indefinite exception occurs during a renewal request for
the lease, renewal requests will continue to be made for that
lease until: the lease is renewed successfully, a renewal attempt
results in a definite exception, or the lease's actual expiration
time has been exceeded. If the lease cannot be successfully
renewed before its actual expiration is reached, the exception
associated with the most recent renewal attempt will be wrapped
in an instance of the LeaseRenewalEvent
class and
sent to the listener.
If the lease's actual expiration is reached before the lease's
desired expiration time, and either 1) the last renewal attempt
succeeded or 2) there have been no renewal attempts, a
LeaseRenewalEvent
containing a null
exception will be sent to the listener.
lease
- the Lease
to be manageddesiredExpiration
- when the client wants the lease to
expire, in milliseconds since the beginning of the epochrenewDuration
- the renewal duration to associate with the
lease, in millisecondslistener
- reference to the LeaseListener
object that will receive notifications of any exceptional
conditions that occur during renewal attempts. If
null
, no notifications will be sent.NullPointerException
- if lease
is
null
IllegalArgumentException
- if renewDuration
is
invalidLeaseRenewalEvent
,
LeaseException
public void renewFor(Lease lease, long desiredDuration, LeaseListener listener)
Calling this method is equivalent the following call:
renewFor(lease, desiredDuration, Lease.FOREVER, listener)
lease
- reference to the new lease to managedesiredDuration
- the desired duration (relative time) that
the caller wants lease
to be valid for, in
millisecondslistener
- reference to the LeaseListener
object that will receive notifications of any exceptional
conditions that occur during renewal attempts. If
null
, no notifications will be sent.NullPointerException
- if lease
is
null
renewFor(net.jini.core.lease.Lease, long, net.jini.lease.LeaseListener)
public void renewFor(Lease lease, long desiredDuration, long renewDuration, LeaseListener listener)
The semantics of this method are similar to those of the
four-argument form of renewUntil
, with
desiredDuration
+ current time being used for the
value of the desiredExpiration
argument of
renewUntil
. The only exception to this is that, in
the context of renewFor
, the value of the
renewDuration
argument may only be
Lease.ANY
if the value of the
desiredDuration
argument is exactly
Lease.FOREVER.
This method tests for arithmetic overflow in the desired
expiration time computed from the value of
desiredDuration
argument
(desiredDuration
+ current time). Should such
overflow be present, a value of Lease.FOREVER
is
used to represent the lease's desired expiration time.
lease
- reference to the new lease to managedesiredDuration
- the desired duration (relative time) that
the caller wants lease
to be valid for, in
millisecondsrenewDuration
- the renewal duration to associate with the
lease, in millisecondslistener
- reference to the LeaseListener
object that will receive notifications of any exceptional
conditions that occur during renewal attempts. If
null
, no notifications will be sent.NullPointerException
- if lease
is
null
IllegalArgumentException
- if renewDuration
is
invalidrenewUntil(net.jini.core.lease.Lease, long, net.jini.lease.LeaseListener)
public long getExpiration(Lease lease) throws UnknownLeaseException
lease
- the lease the caller wants the current desired
expiration forlong
value corresponding to the current
desired expiration time associated with lease
UnknownLeaseException
- if the lease passed to this method
is not in the set of managed leasesUnknownLeaseException
,
setExpiration(net.jini.core.lease.Lease, long)
public void setExpiration(Lease lease, long expiration) throws UnknownLeaseException
Note that an invocation of this method with a lease that is
currently a member of the managed set is equivalent to an
invocation of the renewUntil
method with the lease's
current listener as that method's listener
argument. Specifically, if the value of the
expiration
argument is less than or equal to the
lease's current desired expiration, this method takes no action.
lease
- the lease whose desired expiration time should be
replacedexpiration
- long
value representing the new
desired expiration time for the lease
argumentUnknownLeaseException
- if the lease passed to this method
is not in the set of managed leasesrenewUntil(net.jini.core.lease.Lease, long, net.jini.lease.LeaseListener)
,
UnknownLeaseException
,
getExpiration(net.jini.core.lease.Lease)
public void cancel(Lease lease) throws UnknownLeaseException, RemoteException
Note that even if an exception is thrown as a result of the
cancel operation, the lease will still have been removed from the
set of leases managed by this class. Additionally, any exception
thrown by the cancel
method of the lease object
itself may also be thrown by this method.
lease
- the lease to remove and cancelUnknownLeaseException
- if the lease passed to this method
is not in the set of managed leasesRemoteException
- typically, this exception occurs when
there is a communication failure between the client and
the server. When this exception does occur, the lease may
or may not have been successfully cancelled, (but the
lease is guaranteed to have been removed from the managed
set).Lease.cancel()
,
UnknownLeaseException
public void close()
public void remove(Lease lease) throws UnknownLeaseException
lease
- the lease to remove from the managed setUnknownLeaseException
- if the lease passed to this method
is not in the set of managed leasesUnknownLeaseException
public void clear()
Copyright 2007-2013, multiple authors.
Licensed under the Apache License, Version 2.0, see the NOTICE file for attributions.