You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@river.apache.org by Itai Frenkel <it...@gigaspaces.com> on 2012/07/10 12:41:10 UTC

Question about LeaseRenewalManager and renewDuration

Hello,

I would like to use the LeaseRenewalManager to renew the lease every 30 seconds (desiredExpiration=Lease.FOREVER, renewDuration=30000).
I notice that the first renewal is delayed based on the server's maxEventLease and the renewDuration kicks in only after subsequent renewals.
Below is the output of the reproduction code (notice how the lease is first renewed after 2.5 minutes instead of 30 seconds). In this case the mock maxEventLease is 5 minutes thus the lease is renewed after 5/2=2.5 minutes.
The question is - what is the best way to add this functionality to the LeaseRenewalManager.

10/07/2012 13:18:51 Main main
INFO: Starting... Press any key to abort
10/07/2012 13:23:14 Main$MockEventLease doRenew
INFO: doRenew(duration=30000) returns 30000
10/07/2012 13:23:40 Main$MockEventLease doRenew
INFO: doRenew(duration=30000) returns 30000
10/07/2012 13:24:06 Main$MockEventLease doRenew
INFO: doRenew(duration=30000) returns 30000
10/07/2012 13:24:33 Main$MockEventLease doRenew
INFO: doRenew(duration=30000) returns 30000
10/07/2012 13:24:59 Main$MockEventLease doRenew
INFO: doRenew(duration=30000) returns 30000
10/07/2012 13:25:25 Main$MockEventLease doRenew
INFO: doRenew(duration=30000) returns 30000
10/07/2012 13:25:51 Main$MockEventLease doRenew
INFO: doRenew(duration=30000) returns 30000

Background Information:
The motivation for this is the way the Registrar handles event notifications.
When the Registrar fails to send a notification to a listener due to a temporary network glitch, it assumes the listener is no longer available and cancels the event lease.
The listener may not detect the temporary network glitch and would remain oblivious to the fact that it is no longer registered for events.
The fix is for the listener to send lease renew requests more often to the Registrar (and to get an UnknkownLeaseException).
Thus the motivation for setting renewDuration to 30 seconds.

Reproduction code for the LeaseRenewalManager renewDuration behavior is pasted below.

Any help would be appreciated,
Itai

import java.io.IOException;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

import net.jini.config.AbstractConfiguration;
import net.jini.config.ConfigurationException;
import net.jini.core.lease.Lease;
import net.jini.core.lease.UnknownLeaseException;
import net.jini.core.lookup.ServiceID;
import net.jini.id.Uuid;
import net.jini.lease.DesiredExpirationListener;
import net.jini.lease.LeaseListener;
import net.jini.lease.LeaseRenewalEvent;
import net.jini.lease.LeaseRenewalManager;

import com.sun.jini.reggie.EventLease;
import com.sun.jini.reggie.Registrar;
import com.sun.jini.thread.TaskManager;

public class Main {

       private static final Logger logger = Logger.getLogger("test-renew");
       private static final long MAX_EVENT_LEASE = TimeUnit.MINUTES.toMillis(5);
    private static final long RENEW_BATCH_TIME_WINDOW = TimeUnit.MINUTES.toMillis(5);
       private static final long ROUND_TRIP_TIME = TimeUnit.SECONDS.toMillis(3);
       private static final long RENEW_DURATION = TimeUnit.SECONDS.toMillis(30);

       public static void main(String[] args) throws IOException, ConfigurationException {

             LeaseRenewalManager lrm = new LeaseRenewalManager(new ConfigurationMock());

             Lease lease = MockEventLease.getInstance(System.currentTimeMillis() + MAX_EVENT_LEASE);

             long desiredDuration = Lease.FOREVER;
             long renewDuration = RENEW_DURATION;
             lrm.renewFor(lease,desiredDuration, renewDuration, new LeaseListenerMock());
             logger.info("Starting... Press any key to abort");
             System.in.read();
       }

       private final static class MockEventLease extends EventLease {

             MockEventLease(Registrar server, ServiceID registrarID, long eventID,
                           Uuid leaseID, long expiration) {
                    super(server, registrarID, eventID, leaseID, expiration);
             }

             private static final long serialVersionUID = 1L;

             public void cancel() throws UnknownLeaseException, RemoteException {
                    logger.info("cancel()");
             }

             protected long doRenew(long duration)
                           throws UnknownLeaseException, RemoteException
           {
                    long actualDuration = Math.min(duration, MAX_EVENT_LEASE);
                    logger.info("doRenew(duration="+duration+") returns " + actualDuration);
              return actualDuration;
           }

             static EventLease getInstance(long expiration)
               {
                    return new MockEventLease(null, new ServiceID(1,1),1,new Uuid(1,1),expiration);
               }
       }

       private final static class LeaseListenerMock implements LeaseListener , DesiredExpirationListener {

             /* When lease renewal fails, we discard the proxy  */
             public void notify(LeaseRenewalEvent e) {
                    logger.info("notify(e="+e+")");
             }

             @Override
             public void expirationReached(LeaseRenewalEvent e) {
                    logger.info("expirationReached(e="+e+")");

             }
       }

       private final static class ConfigurationMock extends AbstractConfiguration {

             private static final String LRM = "net.jini.lease.LeaseRenewalManager";

             Map<String,Object> properties = new HashMap<String,Object>();

             ConfigurationMock() {
                    setEntry(LRM, "renewBatchTimeWindow", new Primitive(RENEW_BATCH_TIME_WINDOW));
                    setEntry(LRM, "roundTripTime", new Primitive(ROUND_TRIP_TIME));
                    setEntry(LRM, "taskManager", new TaskManager(11, 1000 * 15, 1.0f));
             }

             @Override
             protected Object getEntryInternal(String component, String name,
                           Class type, Object data) throws ConfigurationException {

                    String key = key(component, name);
                    if (properties.containsKey(key)) {
                           return properties.get(key);
                    }
                    return data;
             }

             private void setEntry(String component, String name, Object value) {
                    properties.put(key(component, name),value);
             }

             private String key(String component, String name) {
                    return component+"."+name;
             }


       }
}

RE: Question about LeaseRenewalManager and renewDuration

Posted by Itai Frenkel <it...@gigaspaces.com>.
I agree.

We are assuming TCP keepalive enabled and there is a watch-dog on all synchronous remote method invocations that times-out after 30 seconds.

-----Original Message-----
From: Gregg Wonderly [mailto:gregg@wonderly.org] 
Sent: Wednesday, July 11, 2012 4:06 PM
To: dev@river.apache.org
Subject: Re: Question about LeaseRenewalManager and renewDuration

Yes, getting all of the stuff right with the LRM is the question, but I'm just suggesting that once you are satisfied with that, you might find that the usual TCP SYN timeout of 3-5 minutes is now in the way of getting 30sec responses.  There are lots of pieces to the puzzle, and I just wanted to point out that the LRM and TCP endpoints are usually not the most usable "connectivity" management solutions. 

I regularly use a TCP stream with keep alive on, and periodic traffic, or even UDP when I need "real-time" connectivity information.   What you are doing with the LRM can give you more information than you see by default, for sure.  But, you may find that even it, can't give you the granularity that you're after.

Gregg Wonderly

On Jul 11, 2012, at 12:15 AM, Itai Frenkel wrote:

> Gregg,
> 
> Let's assume for the sake of the discussion that an outgoing TCP connection throws ConnectException after 30 seconds in case the listener OS was abruptly shutdown without sending FIN, and also assume that any subsequent TCP connection to that listener would immediately throw ConnectException. 
> 
> This does not invalidate the basic question. And that is - how to configure an upper bound for the time it takes notification to "eventually" get to the client - once a temporary listener network unavailability has been resolved.
> 
> Thanks,
> Itai
> 
> -----Original Message-----
> From: Gregg Wonderly [mailto:gregg@wonderly.org]
> Sent: Tuesday, July 10, 2012 9:45 PM
> To: dev@river.apache.org
> Subject: Re: Question about LeaseRenewalManager and renewDuration
> 
> Recall, that under the covers there is also all the OS network stack behaviors.  What is the TCP SYN timeout, for example; i.e. how long will a TCP connect request, which will eventually fail, take before failing?
> 
> I think it's important to understand that unless you are on either end of a TCP connection, with timeout and keep alive settings for that connection, turned down to short intervals, that you're going to be mystified at the longer than expected timing of most failure detections.
> 
> Subclassing the appropriate endpoint class, and adjusting it's behavior and using that on your registrar may be part of what you need to do, to see quick notifications.
> 
> Gregg Wonderly
> 
> On Jul 10, 2012, at 10:49 AM, Greg Trasuk wrote:
> 
>> 
>> On Tue, 2012-07-10 at 10:14, Itai Frenkel wrote:
>>>>> Are you sure about that?  
>>> Looking at RegistrarImpl when ThrowableConstants.retryable(e) returns BAD_OBJECT, it rethrows only if (e instanceof Error), otherwise it cancels the lease. Since ConnectException is not an Error the lease would be canceled.
>>> Why is the Error check being performed ?
>>> 
>> ThrowableConstants.retryable(e) only returns BAD_OBJECT if it 
>> receives a definite response from the remote endpoint.  For a comm 
>> failure, it should return INDEFINITE.  Having said that, the logic 
>> seems to favour declaring an exception "Definite" where it might be 
>> arguable.  For instance, it will declare BAD_OBJECT in the case of a "No route to host"
>> exception, which arguably could be temporary, for instance if a 
>> router goes offline.
>> 
>>>>> Personally, I'd use an internal timer on the client side that says "if I don't receive any events for a given time, I'll cancel the current lease and re-register".  
>>> That requires the Registrar to periodically send probe notifications. The number of real world notifications could fluctuate from zero to high load and cannot be trusted without probe notifications.
>>> 
>> Might be an interesting improvement if a client could request a 
>> heartbeat or supervisory message from the registrar.  But my point 
>> above was that if the events are not coming fast enough to satisfy a 
>> reasonable "liveness" timeout, then it's probably not a big problem 
>> if the client simply cancels the lease and re-registers.  So you 
>> could effectively implement your own heartbeat.
>> 
>> Alternately (subject to exploring the loading and the number of
>> clients) you could create a service that does nothing but registers, 
>> then updates its service attributes periodically, which would have 
>> the effect of generating registrar messages.  Starting to get a 
>> little complicated and indirect, though.
>> 
>> In the end, however, it seems like your trying to have the client 
>> find out that it's not receiving registrar notifications.  I can't 
>> think of any better evidence than "you're not receiving registrar notifications".
>> 
>> Cheers,
>> 
>> Greg.
>> 
>>> Thanks,
>>> Itai
>>> 
>>> -----Original Message-----
>>> From: Greg Trasuk [mailto:trasukg@stratuscom.com]
>>> Sent: Tuesday, July 10, 2012 4:36 PM
>>> To: dev@river.apache.org
>>> Subject: Re: Question about LeaseRenewalManager and renewDuration
>>> 
>>> 
>>> On Tue, 2012-07-10 at 06:41, Itai Frenkel wrote:
>>> <snip...>
>>>> Background Information:
>>>> The motivation for this is the way the Registrar handles event notifications.
>>>> When the Registrar fails to send a notification to a listener due 
>>>> to a temporary network glitch, it assumes the listener is no longer available and cancels the event lease.
>>> 
>>> Are you sure about that?  Looking through com.sun.jini.reggie.RegistrarImpl, it appears that when an exception occurs during event notification, the code tries to categorize the exception as either "definite" (no such event, no such object, etc) or "indefinite" (communications failure).  Then it only cancels the lease on a definite exception.
>>> 
>>> In other words, the lease is maintained in the case of a temporary network failure.  After all, that's the whole point of the lease: it represents an agreement between the client and service that resources are going to be maintained for a definite time period.  
>>> 
>>> Personally, I'd use an internal timer on the client side that says "if I don't receive any events for a given time, I'll cancel the current lease and re-register".  If the events are that quiet, then clearly the registrar is not that heavily loaded, so the overhead of cancelling the lease and creating a new registration should not be too bad.  You'd want to test it under simulated load, of course.
>>> 
>>> Cheers,
>>> 
>>> Greg.
>>> --
>>> Greg Trasuk, President
>>> StratusCom Manufacturing Systems Inc. - We use information technology to solve business problems on your plant floor.
>>> http://stratuscom.com
>>> 
>>> 
>>> 
>> 
> 
> 
> 




Re: Question about LeaseRenewalManager and renewDuration

Posted by Gregg Wonderly <gr...@wonderly.org>.
Yes, getting all of the stuff right with the LRM is the question, but I'm just suggesting that once you are satisfied with that, you might find that the usual TCP SYN timeout of 3-5 minutes is now in the way of getting 30sec responses.  There are lots of pieces to the puzzle, and I just wanted to point out that the LRM and TCP endpoints are usually not the most usable "connectivity" management solutions. 

I regularly use a TCP stream with keep alive on, and periodic traffic, or even UDP when I need "real-time" connectivity information.   What you are doing with the LRM can give you more information than you see by default, for sure.  But, you may find that even it, can't give you the granularity that you're after.

Gregg Wonderly

On Jul 11, 2012, at 12:15 AM, Itai Frenkel wrote:

> Gregg,
> 
> Let's assume for the sake of the discussion that an outgoing TCP connection throws ConnectException after 30 seconds in case the listener OS was abruptly shutdown without sending FIN, and also assume that any subsequent TCP connection to that listener would immediately throw ConnectException. 
> 
> This does not invalidate the basic question. And that is - how to configure an upper bound for the time it takes notification to "eventually" get to the client - once a temporary listener network unavailability has been resolved.
> 
> Thanks,
> Itai
> 
> -----Original Message-----
> From: Gregg Wonderly [mailto:gregg@wonderly.org] 
> Sent: Tuesday, July 10, 2012 9:45 PM
> To: dev@river.apache.org
> Subject: Re: Question about LeaseRenewalManager and renewDuration
> 
> Recall, that under the covers there is also all the OS network stack behaviors.  What is the TCP SYN timeout, for example; i.e. how long will a TCP connect request, which will eventually fail, take before failing?
> 
> I think it's important to understand that unless you are on either end of a TCP connection, with timeout and keep alive settings for that connection, turned down to short intervals, that you're going to be mystified at the longer than expected timing of most failure detections.
> 
> Subclassing the appropriate endpoint class, and adjusting it's behavior and using that on your registrar may be part of what you need to do, to see quick notifications.
> 
> Gregg Wonderly
> 
> On Jul 10, 2012, at 10:49 AM, Greg Trasuk wrote:
> 
>> 
>> On Tue, 2012-07-10 at 10:14, Itai Frenkel wrote:
>>>>> Are you sure about that?  
>>> Looking at RegistrarImpl when ThrowableConstants.retryable(e) returns BAD_OBJECT, it rethrows only if (e instanceof Error), otherwise it cancels the lease. Since ConnectException is not an Error the lease would be canceled.
>>> Why is the Error check being performed ?
>>> 
>> ThrowableConstants.retryable(e) only returns BAD_OBJECT if it receives 
>> a definite response from the remote endpoint.  For a comm failure, it 
>> should return INDEFINITE.  Having said that, the logic seems to favour 
>> declaring an exception "Definite" where it might be arguable.  For 
>> instance, it will declare BAD_OBJECT in the case of a "No route to host"
>> exception, which arguably could be temporary, for instance if a router 
>> goes offline.
>> 
>>>>> Personally, I'd use an internal timer on the client side that says "if I don't receive any events for a given time, I'll cancel the current lease and re-register".  
>>> That requires the Registrar to periodically send probe notifications. The number of real world notifications could fluctuate from zero to high load and cannot be trusted without probe notifications.
>>> 
>> Might be an interesting improvement if a client could request a 
>> heartbeat or supervisory message from the registrar.  But my point 
>> above was that if the events are not coming fast enough to satisfy a 
>> reasonable "liveness" timeout, then it's probably not a big problem if 
>> the client simply cancels the lease and re-registers.  So you could 
>> effectively implement your own heartbeat.
>> 
>> Alternately (subject to exploring the loading and the number of 
>> clients) you could create a service that does nothing but registers, 
>> then updates its service attributes periodically, which would have the 
>> effect of generating registrar messages.  Starting to get a little 
>> complicated and indirect, though.
>> 
>> In the end, however, it seems like your trying to have the client find 
>> out that it's not receiving registrar notifications.  I can't think of 
>> any better evidence than "you're not receiving registrar notifications".
>> 
>> Cheers,
>> 
>> Greg.
>> 
>>> Thanks,
>>> Itai
>>> 
>>> -----Original Message-----
>>> From: Greg Trasuk [mailto:trasukg@stratuscom.com]
>>> Sent: Tuesday, July 10, 2012 4:36 PM
>>> To: dev@river.apache.org
>>> Subject: Re: Question about LeaseRenewalManager and renewDuration
>>> 
>>> 
>>> On Tue, 2012-07-10 at 06:41, Itai Frenkel wrote:
>>> <snip...>
>>>> Background Information:
>>>> The motivation for this is the way the Registrar handles event notifications.
>>>> When the Registrar fails to send a notification to a listener due to 
>>>> a temporary network glitch, it assumes the listener is no longer available and cancels the event lease.
>>> 
>>> Are you sure about that?  Looking through com.sun.jini.reggie.RegistrarImpl, it appears that when an exception occurs during event notification, the code tries to categorize the exception as either "definite" (no such event, no such object, etc) or "indefinite" (communications failure).  Then it only cancels the lease on a definite exception.
>>> 
>>> In other words, the lease is maintained in the case of a temporary network failure.  After all, that's the whole point of the lease: it represents an agreement between the client and service that resources are going to be maintained for a definite time period.  
>>> 
>>> Personally, I'd use an internal timer on the client side that says "if I don't receive any events for a given time, I'll cancel the current lease and re-register".  If the events are that quiet, then clearly the registrar is not that heavily loaded, so the overhead of cancelling the lease and creating a new registration should not be too bad.  You'd want to test it under simulated load, of course.
>>> 
>>> Cheers,
>>> 
>>> Greg.
>>> --
>>> Greg Trasuk, President
>>> StratusCom Manufacturing Systems Inc. - We use information technology to solve business problems on your plant floor.
>>> http://stratuscom.com
>>> 
>>> 
>>> 
>> 
> 
> 
> 


RE: Question about LeaseRenewalManager and renewDuration

Posted by Itai Frenkel <it...@gigaspaces.com>.
Gregg,

Let's assume for the sake of the discussion that an outgoing TCP connection throws ConnectException after 30 seconds in case the listener OS was abruptly shutdown without sending FIN, and also assume that any subsequent TCP connection to that listener would immediately throw ConnectException. 

This does not invalidate the basic question. And that is - how to configure an upper bound for the time it takes notification to "eventually" get to the client - once a temporary listener network unavailability has been resolved.

Thanks,
Itai

-----Original Message-----
From: Gregg Wonderly [mailto:gregg@wonderly.org] 
Sent: Tuesday, July 10, 2012 9:45 PM
To: dev@river.apache.org
Subject: Re: Question about LeaseRenewalManager and renewDuration

Recall, that under the covers there is also all the OS network stack behaviors.  What is the TCP SYN timeout, for example; i.e. how long will a TCP connect request, which will eventually fail, take before failing?

I think it's important to understand that unless you are on either end of a TCP connection, with timeout and keep alive settings for that connection, turned down to short intervals, that you're going to be mystified at the longer than expected timing of most failure detections.

Subclassing the appropriate endpoint class, and adjusting it's behavior and using that on your registrar may be part of what you need to do, to see quick notifications.

Gregg Wonderly

On Jul 10, 2012, at 10:49 AM, Greg Trasuk wrote:

> 
> On Tue, 2012-07-10 at 10:14, Itai Frenkel wrote:
>>>> Are you sure about that?  
>> Looking at RegistrarImpl when ThrowableConstants.retryable(e) returns BAD_OBJECT, it rethrows only if (e instanceof Error), otherwise it cancels the lease. Since ConnectException is not an Error the lease would be canceled.
>> Why is the Error check being performed ?
>> 
> ThrowableConstants.retryable(e) only returns BAD_OBJECT if it receives 
> a definite response from the remote endpoint.  For a comm failure, it 
> should return INDEFINITE.  Having said that, the logic seems to favour 
> declaring an exception "Definite" where it might be arguable.  For 
> instance, it will declare BAD_OBJECT in the case of a "No route to host"
> exception, which arguably could be temporary, for instance if a router 
> goes offline.
> 
>>>> Personally, I'd use an internal timer on the client side that says "if I don't receive any events for a given time, I'll cancel the current lease and re-register".  
>> That requires the Registrar to periodically send probe notifications. The number of real world notifications could fluctuate from zero to high load and cannot be trusted without probe notifications.
>> 
> Might be an interesting improvement if a client could request a 
> heartbeat or supervisory message from the registrar.  But my point 
> above was that if the events are not coming fast enough to satisfy a 
> reasonable "liveness" timeout, then it's probably not a big problem if 
> the client simply cancels the lease and re-registers.  So you could 
> effectively implement your own heartbeat.
> 
> Alternately (subject to exploring the loading and the number of 
> clients) you could create a service that does nothing but registers, 
> then updates its service attributes periodically, which would have the 
> effect of generating registrar messages.  Starting to get a little 
> complicated and indirect, though.
> 
> In the end, however, it seems like your trying to have the client find 
> out that it's not receiving registrar notifications.  I can't think of 
> any better evidence than "you're not receiving registrar notifications".
> 
> Cheers,
> 
> Greg.
> 
>> Thanks,
>> Itai
>> 
>> -----Original Message-----
>> From: Greg Trasuk [mailto:trasukg@stratuscom.com]
>> Sent: Tuesday, July 10, 2012 4:36 PM
>> To: dev@river.apache.org
>> Subject: Re: Question about LeaseRenewalManager and renewDuration
>> 
>> 
>> On Tue, 2012-07-10 at 06:41, Itai Frenkel wrote:
>> <snip...>
>>> Background Information:
>>> The motivation for this is the way the Registrar handles event notifications.
>>> When the Registrar fails to send a notification to a listener due to 
>>> a temporary network glitch, it assumes the listener is no longer available and cancels the event lease.
>> 
>> Are you sure about that?  Looking through com.sun.jini.reggie.RegistrarImpl, it appears that when an exception occurs during event notification, the code tries to categorize the exception as either "definite" (no such event, no such object, etc) or "indefinite" (communications failure).  Then it only cancels the lease on a definite exception.
>> 
>> In other words, the lease is maintained in the case of a temporary network failure.  After all, that's the whole point of the lease: it represents an agreement between the client and service that resources are going to be maintained for a definite time period.  
>> 
>> Personally, I'd use an internal timer on the client side that says "if I don't receive any events for a given time, I'll cancel the current lease and re-register".  If the events are that quiet, then clearly the registrar is not that heavily loaded, so the overhead of cancelling the lease and creating a new registration should not be too bad.  You'd want to test it under simulated load, of course.
>> 
>> Cheers,
>> 
>> Greg.
>> --
>> Greg Trasuk, President
>> StratusCom Manufacturing Systems Inc. - We use information technology to solve business problems on your plant floor.
>> http://stratuscom.com
>> 
>> 
>> 
> 




Re: Question about LeaseRenewalManager and renewDuration

Posted by Gregg Wonderly <gr...@wonderly.org>.
Recall, that under the covers there is also all the OS network stack behaviors.  What is the TCP SYN timeout, for example; i.e. how long will a TCP connect request, which will eventually fail, take before failing?

I think it's important to understand that unless you are on either end of a TCP connection, with timeout and keep alive settings for that connection, turned down to short intervals, that you're going to be mystified at the longer than expected timing of most failure detections.

Subclassing the appropriate endpoint class, and adjusting it's behavior and using that on your registrar may be part of what you need to do, to see quick notifications.

Gregg Wonderly

On Jul 10, 2012, at 10:49 AM, Greg Trasuk wrote:

> 
> On Tue, 2012-07-10 at 10:14, Itai Frenkel wrote:
>>>> Are you sure about that?  
>> Looking at RegistrarImpl when ThrowableConstants.retryable(e) returns BAD_OBJECT, it rethrows only if (e instanceof Error), otherwise it cancels the lease. Since ConnectException is not an Error the lease would be canceled.
>> Why is the Error check being performed ?
>> 
> ThrowableConstants.retryable(e) only returns BAD_OBJECT if it receives a
> definite response from the remote endpoint.  For a comm failure, it
> should return INDEFINITE.  Having said that, the logic seems to favour
> declaring an exception "Definite" where it might be arguable.  For
> instance, it will declare BAD_OBJECT in the case of a "No route to host"
> exception, which arguably could be temporary, for instance if a router
> goes offline.
> 
>>>> Personally, I'd use an internal timer on the client side that says "if I don't receive any events for a given time, I'll cancel the current lease and re-register".  
>> That requires the Registrar to periodically send probe notifications. The number of real world notifications could fluctuate from zero to high load and cannot be trusted without probe notifications.
>> 
> Might be an interesting improvement if a client could request a
> heartbeat or supervisory message from the registrar.  But my point above
> was that if the events are not coming fast enough to satisfy a
> reasonable "liveness" timeout, then it's probably not a big problem if
> the client simply cancels the lease and re-registers.  So you could
> effectively implement your own heartbeat.
> 
> Alternately (subject to exploring the loading and the number of clients)
> you could create a service that does nothing but registers, then updates
> its service attributes periodically, which would have the effect of
> generating registrar messages.  Starting to get a little complicated and
> indirect, though.
> 
> In the end, however, it seems like your trying to have the client find
> out that it's not receiving registrar notifications.  I can't think of
> any better evidence than "you're not receiving registrar notifications".
> 
> Cheers,
> 
> Greg.
> 
>> Thanks,
>> Itai
>> 
>> -----Original Message-----
>> From: Greg Trasuk [mailto:trasukg@stratuscom.com] 
>> Sent: Tuesday, July 10, 2012 4:36 PM
>> To: dev@river.apache.org
>> Subject: Re: Question about LeaseRenewalManager and renewDuration
>> 
>> 
>> On Tue, 2012-07-10 at 06:41, Itai Frenkel wrote:
>> <snip...>
>>> Background Information:
>>> The motivation for this is the way the Registrar handles event notifications.
>>> When the Registrar fails to send a notification to a listener due to a 
>>> temporary network glitch, it assumes the listener is no longer available and cancels the event lease.
>> 
>> Are you sure about that?  Looking through com.sun.jini.reggie.RegistrarImpl, it appears that when an exception occurs during event notification, the code tries to categorize the exception as either "definite" (no such event, no such object, etc) or "indefinite" (communications failure).  Then it only cancels the lease on a definite exception.
>> 
>> In other words, the lease is maintained in the case of a temporary network failure.  After all, that's the whole point of the lease: it represents an agreement between the client and service that resources are going to be maintained for a definite time period.  
>> 
>> Personally, I'd use an internal timer on the client side that says "if I don't receive any events for a given time, I'll cancel the current lease and re-register".  If the events are that quiet, then clearly the registrar is not that heavily loaded, so the overhead of cancelling the lease and creating a new registration should not be too bad.  You'd want to test it under simulated load, of course.
>> 
>> Cheers,
>> 
>> Greg.
>> --
>> Greg Trasuk, President
>> StratusCom Manufacturing Systems Inc. - We use information technology to solve business problems on your plant floor.
>> http://stratuscom.com
>> 
>> 
>> 
> 


RE: Question about LeaseRenewalManager and renewDuration

Posted by Itai Frenkel <it...@gigaspaces.com>.
Here is what I gathered so far from this email thread:

1. It is quite possible for the  Registar to cancel the lease even if the disconnection would have been temporary.

2. There are three mitigations currently proposed, each can solve the temporary network disconnection problem:
               2A. Fix the LeaseRenewalManager to use renewDuration to from the first lease request, and not just from the second lease request (the original email in this thread)

               2B. Create a new mechanism in which the Registrar sends periodic events to the client, and have the client reconnect if it has not received any event for a while.

               2C. Create a new mechanism in which the Listener sends periodic listener attribute updates.



Here is the proposed patch that uses the existing renewDuration mechanism:


Index: src/net/jini/lease/LeaseRenewalManager.java
===================================================================
--- src/net/jini/lease/LeaseRenewalManager.java  (revision 1359529)
+++ src/net/jini/lease/LeaseRenewalManager.java  (working copy)
@@ -577,7 +577,15 @@
        } else {
          delta = 1000 * 60 * 60 * 24 * 3;
        }
-        renew = endTime - delta;
+
+        long renewTime = endTime - delta;
+        if (renewDuration != Lease.ANY &&
+            renewTime - now > renewDuration) {
+
+        // shorten the time between two consecutive lease renewals
+         renewTime = now + renewDuration;
+        }
+        this.renew = renewTime;
    }
     /** Calculate a new renew time due to an indefinite exception */



Regards,

Itai





-----Original Message-----
From: Greg Trasuk [mailto:trasukg@stratuscom.com]
Sent: Tuesday, July 10, 2012 6:50 PM
To: dev@river.apache.org
Subject: RE: Question about LeaseRenewalManager and renewDuration





On Tue, 2012-07-10 at 10:14, Itai Frenkel wrote:

> >> Are you sure about that?

> Looking at RegistrarImpl when ThrowableConstants.retryable(e) returns BAD_OBJECT, it rethrows only if (e instanceof Error), otherwise it cancels the lease. Since ConnectException is not an Error the lease would be canceled.

> Why is the Error check being performed ?

>

ThrowableConstants.retryable(e) only returns BAD_OBJECT if it receives a definite response from the remote endpoint.  For a comm failure, it should return INDEFINITE.  Having said that, the logic seems to favour declaring an exception "Definite" where it might be arguable.  For instance, it will declare BAD_OBJECT in the case of a "No route to host"

exception, which arguably could be temporary, for instance if a router goes offline.



> >> Personally, I'd use an internal timer on the client side that says "if I don't receive any events for a given time, I'll cancel the current lease and re-register".

> That requires the Registrar to periodically send probe notifications. The number of real world notifications could fluctuate from zero to high load and cannot be trusted without probe notifications.

>

Might be an interesting improvement if a client could request a heartbeat or supervisory message from the registrar.  But my point above was that if the events are not coming fast enough to satisfy a reasonable "liveness" timeout, then it's probably not a big problem if the client simply cancels the lease and re-registers.  So you could effectively implement your own heartbeat.



Alternately (subject to exploring the loading and the number of clients) you could create a service that does nothing but registers, then updates its service attributes periodically, which would have the effect of generating registrar messages.  Starting to get a little complicated and indirect, though.



In the end, however, it seems like your trying to have the client find out that it's not receiving registrar notifications.  I can't think of any better evidence than "you're not receiving registrar notifications".



Cheers,



Greg.



> Thanks,

> Itai

>

> -----Original Message-----

> From: Greg Trasuk [mailto:trasukg@stratuscom.com]<mailto:[mailto:trasukg@stratuscom.com]>

> Sent: Tuesday, July 10, 2012 4:36 PM

> To: dev@river.apache.org<ma...@river.apache.org>

> Subject: Re: Question about LeaseRenewalManager and renewDuration

>

>

> On Tue, 2012-07-10 at 06:41, Itai Frenkel wrote:

> <snip...>

> > Background Information:

> > The motivation for this is the way the Registrar handles event notifications.

> > When the Registrar fails to send a notification to a listener due to

> > a temporary network glitch, it assumes the listener is no longer available and cancels the event lease.

>

> Are you sure about that?  Looking through com.sun.jini.reggie.RegistrarImpl, it appears that when an exception occurs during event notification, the code tries to categorize the exception as either "definite" (no such event, no such object, etc) or "indefinite" (communications failure).  Then it only cancels the lease on a definite exception.

>

> In other words, the lease is maintained in the case of a temporary network failure.  After all, that's the whole point of the lease: it represents an agreement between the client and service that resources are going to be maintained for a definite time period.

>

> Personally, I'd use an internal timer on the client side that says "if I don't receive any events for a given time, I'll cancel the current lease and re-register".  If the events are that quiet, then clearly the registrar is not that heavily loaded, so the overhead of cancelling the lease and creating a new registration should not be too bad.  You'd want to test it under simulated load, of course.

>

> Cheers,

>

> Greg.

> --

> Greg Trasuk, President

> StratusCom Manufacturing Systems Inc. - We use information technology to solve business problems on your plant floor.

> http://stratuscom.com

>

>

>





RE: Question about LeaseRenewalManager and renewDuration

Posted by Greg Trasuk <tr...@stratuscom.com>.
On Tue, 2012-07-10 at 10:14, Itai Frenkel wrote:
> >> Are you sure about that?  
> Looking at RegistrarImpl when ThrowableConstants.retryable(e) returns BAD_OBJECT, it rethrows only if (e instanceof Error), otherwise it cancels the lease. Since ConnectException is not an Error the lease would be canceled.
> Why is the Error check being performed ?
> 
ThrowableConstants.retryable(e) only returns BAD_OBJECT if it receives a
definite response from the remote endpoint.  For a comm failure, it
should return INDEFINITE.  Having said that, the logic seems to favour
declaring an exception "Definite" where it might be arguable.  For
instance, it will declare BAD_OBJECT in the case of a "No route to host"
exception, which arguably could be temporary, for instance if a router
goes offline.

> >> Personally, I'd use an internal timer on the client side that says "if I don't receive any events for a given time, I'll cancel the current lease and re-register".  
> That requires the Registrar to periodically send probe notifications. The number of real world notifications could fluctuate from zero to high load and cannot be trusted without probe notifications.
> 
Might be an interesting improvement if a client could request a
heartbeat or supervisory message from the registrar.  But my point above
was that if the events are not coming fast enough to satisfy a
reasonable "liveness" timeout, then it's probably not a big problem if
the client simply cancels the lease and re-registers.  So you could
effectively implement your own heartbeat.

Alternately (subject to exploring the loading and the number of clients)
you could create a service that does nothing but registers, then updates
its service attributes periodically, which would have the effect of
generating registrar messages.  Starting to get a little complicated and
indirect, though.

In the end, however, it seems like your trying to have the client find
out that it's not receiving registrar notifications.  I can't think of
any better evidence than "you're not receiving registrar notifications".

Cheers,

Greg.

> Thanks,
> Itai
> 
> -----Original Message-----
> From: Greg Trasuk [mailto:trasukg@stratuscom.com] 
> Sent: Tuesday, July 10, 2012 4:36 PM
> To: dev@river.apache.org
> Subject: Re: Question about LeaseRenewalManager and renewDuration
> 
> 
> On Tue, 2012-07-10 at 06:41, Itai Frenkel wrote:
> <snip...>
> > Background Information:
> > The motivation for this is the way the Registrar handles event notifications.
> > When the Registrar fails to send a notification to a listener due to a 
> > temporary network glitch, it assumes the listener is no longer available and cancels the event lease.
> 
> Are you sure about that?  Looking through com.sun.jini.reggie.RegistrarImpl, it appears that when an exception occurs during event notification, the code tries to categorize the exception as either "definite" (no such event, no such object, etc) or "indefinite" (communications failure).  Then it only cancels the lease on a definite exception.
> 
> In other words, the lease is maintained in the case of a temporary network failure.  After all, that's the whole point of the lease: it represents an agreement between the client and service that resources are going to be maintained for a definite time period.  
> 
> Personally, I'd use an internal timer on the client side that says "if I don't receive any events for a given time, I'll cancel the current lease and re-register".  If the events are that quiet, then clearly the registrar is not that heavily loaded, so the overhead of cancelling the lease and creating a new registration should not be too bad.  You'd want to test it under simulated load, of course.
> 
> Cheers,
> 
> Greg.
> --
> Greg Trasuk, President
> StratusCom Manufacturing Systems Inc. - We use information technology to solve business problems on your plant floor.
> http://stratuscom.com
> 
> 
> 


RE: Question about LeaseRenewalManager and renewDuration

Posted by Itai Frenkel <it...@gigaspaces.com>.
>> Are you sure about that?  
Looking at RegistrarImpl when ThrowableConstants.retryable(e) returns BAD_OBJECT, it rethrows only if (e instanceof Error), otherwise it cancels the lease. Since ConnectException is not an Error the lease would be canceled.
Why is the Error check being performed ?

>> Personally, I'd use an internal timer on the client side that says "if I don't receive any events for a given time, I'll cancel the current lease and re-register".  
That requires the Registrar to periodically send probe notifications. The number of real world notifications could fluctuate from zero to high load and cannot be trusted without probe notifications.

Thanks,
Itai

-----Original Message-----
From: Greg Trasuk [mailto:trasukg@stratuscom.com] 
Sent: Tuesday, July 10, 2012 4:36 PM
To: dev@river.apache.org
Subject: Re: Question about LeaseRenewalManager and renewDuration


On Tue, 2012-07-10 at 06:41, Itai Frenkel wrote:
<snip...>
> Background Information:
> The motivation for this is the way the Registrar handles event notifications.
> When the Registrar fails to send a notification to a listener due to a 
> temporary network glitch, it assumes the listener is no longer available and cancels the event lease.

Are you sure about that?  Looking through com.sun.jini.reggie.RegistrarImpl, it appears that when an exception occurs during event notification, the code tries to categorize the exception as either "definite" (no such event, no such object, etc) or "indefinite" (communications failure).  Then it only cancels the lease on a definite exception.

In other words, the lease is maintained in the case of a temporary network failure.  After all, that's the whole point of the lease: it represents an agreement between the client and service that resources are going to be maintained for a definite time period.  

Personally, I'd use an internal timer on the client side that says "if I don't receive any events for a given time, I'll cancel the current lease and re-register".  If the events are that quiet, then clearly the registrar is not that heavily loaded, so the overhead of cancelling the lease and creating a new registration should not be too bad.  You'd want to test it under simulated load, of course.

Cheers,

Greg.
--
Greg Trasuk, President
StratusCom Manufacturing Systems Inc. - We use information technology to solve business problems on your plant floor.
http://stratuscom.com




Re: Question about LeaseRenewalManager and renewDuration

Posted by Greg Trasuk <tr...@stratuscom.com>.
On Tue, 2012-07-10 at 06:41, Itai Frenkel wrote:
<snip...>
> Background Information:
> The motivation for this is the way the Registrar handles event notifications.
> When the Registrar fails to send a notification to a listener due to a temporary network glitch, 
> it assumes the listener is no longer available and cancels the event lease.

Are you sure about that?  Looking through
com.sun.jini.reggie.RegistrarImpl, it appears that when an exception
occurs during event notification, the code tries to categorize the
exception as either "definite" (no such event, no such object, etc) or
"indefinite" (communications failure).  Then it only cancels the lease
on a definite exception.

In other words, the lease is maintained in the case of a temporary
network failure.  After all, that's the whole point of the lease: it
represents an agreement between the client and service that resources
are going to be maintained for a definite time period.  

Personally, I'd use an internal timer on the client side that says "if I
don't receive any events for a given time, I'll cancel the current lease
and re-register".  If the events are that quiet, then clearly the
registrar is not that heavily loaded, so the overhead of cancelling the
lease and creating a new registration should not be too bad.  You'd want
to test it under simulated load, of course.

Cheers,

Greg.
-- 
Greg Trasuk, President
StratusCom Manufacturing Systems Inc. - We use information technology to
solve business problems on your plant floor.
http://stratuscom.com


RE: Question about LeaseRenewalManager and renewDuration

Posted by Itai Frenkel <it...@gigaspaces.com>.
I agree with your analysis for long network disconnections. The mitigation for long two-way network disconnections is for the client to periodically try to connect to the Registrar regardless of the renewal process, with a predefined number of retries before discarding the Registrar. 

The scenario below is different:
1. Short/sporadic network disconnections or short periods in which a specific client is unavailable (due to GC, or virtualization issues). 
2. There is more than one registrar for high availability, but both could fail to send a notification to the listener and both would cancel the lease.
3. The client needs to get the notifications eventually. Where "eventually" should be configurable regardless of the server maxEventLease (assuming desiredExpiration=Lease.FOREVER). 
  30 seconds is a reasonable response time for a notification. maxEventLease/2 in our case is 15 minutes which is not a reasonable response time for a notification.
 Hence the suggestion for the client to renew the lease at least once every 30 seconds.


It is true that if many clients, try to perform full recovery at the same time, it could cause the Registrar to be with high load (or worse, all Registrars). More so, if a nasty firewall rule is crafted to allow one-way connection from the listener to the Registrar but not the other way around. The rabbit hole goes deep :) Nevertheless, these scenarios are much less likely than the sporadic network failures described in 1 above.

Itai


-----Original Message-----
From: Dan Creswell [mailto:dan.creswell@gmail.com] 
Sent: Tuesday, July 10, 2012 2:35 PM
To: dev@river.apache.org
Subject: Re: Question about LeaseRenewalManager and renewDuration

Hey,

Thanks for including the background information, that makes it much easier to figure out how to answer the question.

In this case, I'm not sure that increasing the frequency of lease renewals will help you. The same network problems that cause the Registrar to drop a listener can also foul up the lease renewal process such that it can take a long time for a renewal request to be processed.

Basically, even though you make a call after about 20 seconds (the LRM takes some time off the overall lease renewal duration to account for network roundtrip) it could take substantial time to complete such that you aren't informed for much longer than the 30 seconds you are after.

I guess the question then is: Why is it important to "know with certainty"
that the lease has expired as soon as possible?

Ultimately, we can't know precisely when the lease expires and when we figure out that expiry occurred we still have to:

(1) Contact the registrar and recover state.
(2) Register for events that update state recovered in (1).

So our response is always the same, it can just be a little slow hence my question above: Why do you want to know "more quickly"?

Best,

Dan.

On 10 July 2012 11:41, Itai Frenkel <it...@gigaspaces.com> wrote:

> Hello,
>
> I would like to use the LeaseRenewalManager to renew the lease every 
> 30 seconds (desiredExpiration=Lease.FOREVER, renewDuration=30000).
> I notice that the first renewal is delayed based on the server's 
> maxEventLease and the renewDuration kicks in only after subsequent renewals.
> Below is the output of the reproduction code (notice how the lease is 
> first renewed after 2.5 minutes instead of 30 seconds). In this case 
> the mock maxEventLease is 5 minutes thus the lease is renewed after 
> 5/2=2.5 minutes.
> The question is - what is the best way to add this functionality to 
> the LeaseRenewalManager.
>
> 10/07/2012 13:18:51 Main main
> INFO: Starting... Press any key to abort
> 10/07/2012 13:23:14 Main$MockEventLease doRenew
> INFO: doRenew(duration=30000) returns 30000
> 10/07/2012 13:23:40 Main$MockEventLease doRenew
> INFO: doRenew(duration=30000) returns 30000
> 10/07/2012 13:24:06 Main$MockEventLease doRenew
> INFO: doRenew(duration=30000) returns 30000
> 10/07/2012 13:24:33 Main$MockEventLease doRenew
> INFO: doRenew(duration=30000) returns 30000
> 10/07/2012 13:24:59 Main$MockEventLease doRenew
> INFO: doRenew(duration=30000) returns 30000
> 10/07/2012 13:25:25 Main$MockEventLease doRenew
> INFO: doRenew(duration=30000) returns 30000
> 10/07/2012 13:25:51 Main$MockEventLease doRenew
> INFO: doRenew(duration=30000) returns 30000
>
> Background Information:
> The motivation for this is the way the Registrar handles event 
> notifications.
> When the Registrar fails to send a notification to a listener due to a 
> temporary network glitch, it assumes the listener is no longer 
> available and cancels the event lease.
> The listener may not detect the temporary network glitch and would 
> remain oblivious to the fact that it is no longer registered for events.
> The fix is for the listener to send lease renew requests more often to 
> the Registrar (and to get an UnknkownLeaseException).
> Thus the motivation for setting renewDuration to 30 seconds.
>
> Reproduction code for the LeaseRenewalManager renewDuration behavior 
> is pasted below.
>
> Any help would be appreciated,
> Itai
>
> import java.io.IOException;
> import java.rmi.RemoteException;
> import java.util.HashMap;
> import java.util.Map;
> import java.util.concurrent.TimeUnit;
> import java.util.logging.Logger;
>
> import net.jini.config.AbstractConfiguration;
> import net.jini.config.ConfigurationException;
> import net.jini.core.lease.Lease;
> import net.jini.core.lease.UnknownLeaseException;
> import net.jini.core.lookup.ServiceID; import net.jini.id.Uuid; import 
> net.jini.lease.DesiredExpirationListener;
> import net.jini.lease.LeaseListener;
> import net.jini.lease.LeaseRenewalEvent; import 
> net.jini.lease.LeaseRenewalManager;
>
> import com.sun.jini.reggie.EventLease; import 
> com.sun.jini.reggie.Registrar; import com.sun.jini.thread.TaskManager;
>
> public class Main {
>
>        private static final Logger logger = Logger.getLogger("test-renew");
>        private static final long MAX_EVENT_LEASE = 
> TimeUnit.MINUTES.toMillis(5);
>     private static final long RENEW_BATCH_TIME_WINDOW = 
> TimeUnit.MINUTES.toMillis(5);
>        private static final long ROUND_TRIP_TIME = 
> TimeUnit.SECONDS.toMillis(3);
>        private static final long RENEW_DURATION = 
> TimeUnit.SECONDS.toMillis(30);
>
>        public static void main(String[] args) throws IOException, 
> ConfigurationException {
>
>              LeaseRenewalManager lrm = new LeaseRenewalManager(new 
> ConfigurationMock());
>
>              Lease lease =
> MockEventLease.getInstance(System.currentTimeMillis() + 
> MAX_EVENT_LEASE);
>
>              long desiredDuration = Lease.FOREVER;
>              long renewDuration = RENEW_DURATION;
>              lrm.renewFor(lease,desiredDuration, renewDuration, new 
> LeaseListenerMock());
>              logger.info("Starting... Press any key to abort");
>              System.in.read();
>        }
>
>        private final static class MockEventLease extends EventLease {
>
>              MockEventLease(Registrar server, ServiceID registrarID, 
> long eventID,
>                            Uuid leaseID, long expiration) {
>                     super(server, registrarID, eventID, leaseID, 
> expiration);
>              }
>
>              private static final long serialVersionUID = 1L;
>
>              public void cancel() throws UnknownLeaseException, 
> RemoteException {
>                     logger.info("cancel()");
>              }
>
>              protected long doRenew(long duration)
>                            throws UnknownLeaseException, RemoteException
>            {
>                     long actualDuration = Math.min(duration, 
> MAX_EVENT_LEASE);
>                     logger.info("doRenew(duration="+duration+") returns "
> + actualDuration);
>               return actualDuration;
>            }
>
>              static EventLease getInstance(long expiration)
>                {
>                     return new MockEventLease(null, new 
> ServiceID(1,1),1,new Uuid(1,1),expiration);
>                }
>        }
>
>        private final static class LeaseListenerMock implements 
> LeaseListener , DesiredExpirationListener {
>
>              /* When lease renewal fails, we discard the proxy  */
>              public void notify(LeaseRenewalEvent e) {
>                     logger.info("notify(e="+e+")");
>              }
>
>              @Override
>              public void expirationReached(LeaseRenewalEvent e) {
>                     logger.info("expirationReached(e="+e+")");
>
>              }
>        }
>
>        private final static class ConfigurationMock extends 
> AbstractConfiguration {
>
>              private static final String LRM = 
> "net.jini.lease.LeaseRenewalManager";
>
>              Map<String,Object> properties = new 
> HashMap<String,Object>();
>
>              ConfigurationMock() {
>                     setEntry(LRM, "renewBatchTimeWindow", new 
> Primitive(RENEW_BATCH_TIME_WINDOW));
>                     setEntry(LRM, "roundTripTime", new 
> Primitive(ROUND_TRIP_TIME));
>                     setEntry(LRM, "taskManager", new TaskManager(11, 
> 1000
> * 15, 1.0f));
>              }
>
>              @Override
>              protected Object getEntryInternal(String component, 
> String name,
>                            Class type, Object data) throws 
> ConfigurationException {
>
>                     String key = key(component, name);
>                     if (properties.containsKey(key)) {
>                            return properties.get(key);
>                     }
>                     return data;
>              }
>
>              private void setEntry(String component, String name, 
> Object
> value) {
>                     properties.put(key(component, name),value);
>              }
>
>              private String key(String component, String name) {
>                     return component+"."+name;
>              }
>
>
>        }
> }
>


Re: Question about LeaseRenewalManager and renewDuration

Posted by Dan Creswell <da...@gmail.com>.
Hey,

Thanks for including the background information, that makes it much easier
to figure out how to answer the question.

In this case, I'm not sure that increasing the frequency of lease renewals
will help you. The same network problems that cause the Registrar to drop a
listener can also foul up the lease renewal process such that it can take a
long time for a renewal request to be processed.

Basically, even though you make a call after about 20 seconds (the LRM
takes some time off the overall lease renewal duration to account for
network roundtrip) it could take substantial time to complete such that you
aren't informed for much longer than the 30 seconds you are after.

I guess the question then is: Why is it important to "know with certainty"
that the lease has expired as soon as possible?

Ultimately, we can't know precisely when the lease expires and when we
figure out that expiry occurred we still have to:

(1) Contact the registrar and recover state.
(2) Register for events that update state recovered in (1).

So our response is always the same, it can just be a little slow hence my
question above: Why do you want to know "more quickly"?

Best,

Dan.

On 10 July 2012 11:41, Itai Frenkel <it...@gigaspaces.com> wrote:

> Hello,
>
> I would like to use the LeaseRenewalManager to renew the lease every 30
> seconds (desiredExpiration=Lease.FOREVER, renewDuration=30000).
> I notice that the first renewal is delayed based on the server's
> maxEventLease and the renewDuration kicks in only after subsequent renewals.
> Below is the output of the reproduction code (notice how the lease is
> first renewed after 2.5 minutes instead of 30 seconds). In this case the
> mock maxEventLease is 5 minutes thus the lease is renewed after 5/2=2.5
> minutes.
> The question is - what is the best way to add this functionality to the
> LeaseRenewalManager.
>
> 10/07/2012 13:18:51 Main main
> INFO: Starting... Press any key to abort
> 10/07/2012 13:23:14 Main$MockEventLease doRenew
> INFO: doRenew(duration=30000) returns 30000
> 10/07/2012 13:23:40 Main$MockEventLease doRenew
> INFO: doRenew(duration=30000) returns 30000
> 10/07/2012 13:24:06 Main$MockEventLease doRenew
> INFO: doRenew(duration=30000) returns 30000
> 10/07/2012 13:24:33 Main$MockEventLease doRenew
> INFO: doRenew(duration=30000) returns 30000
> 10/07/2012 13:24:59 Main$MockEventLease doRenew
> INFO: doRenew(duration=30000) returns 30000
> 10/07/2012 13:25:25 Main$MockEventLease doRenew
> INFO: doRenew(duration=30000) returns 30000
> 10/07/2012 13:25:51 Main$MockEventLease doRenew
> INFO: doRenew(duration=30000) returns 30000
>
> Background Information:
> The motivation for this is the way the Registrar handles event
> notifications.
> When the Registrar fails to send a notification to a listener due to a
> temporary network glitch, it assumes the listener is no longer available
> and cancels the event lease.
> The listener may not detect the temporary network glitch and would remain
> oblivious to the fact that it is no longer registered for events.
> The fix is for the listener to send lease renew requests more often to the
> Registrar (and to get an UnknkownLeaseException).
> Thus the motivation for setting renewDuration to 30 seconds.
>
> Reproduction code for the LeaseRenewalManager renewDuration behavior is
> pasted below.
>
> Any help would be appreciated,
> Itai
>
> import java.io.IOException;
> import java.rmi.RemoteException;
> import java.util.HashMap;
> import java.util.Map;
> import java.util.concurrent.TimeUnit;
> import java.util.logging.Logger;
>
> import net.jini.config.AbstractConfiguration;
> import net.jini.config.ConfigurationException;
> import net.jini.core.lease.Lease;
> import net.jini.core.lease.UnknownLeaseException;
> import net.jini.core.lookup.ServiceID;
> import net.jini.id.Uuid;
> import net.jini.lease.DesiredExpirationListener;
> import net.jini.lease.LeaseListener;
> import net.jini.lease.LeaseRenewalEvent;
> import net.jini.lease.LeaseRenewalManager;
>
> import com.sun.jini.reggie.EventLease;
> import com.sun.jini.reggie.Registrar;
> import com.sun.jini.thread.TaskManager;
>
> public class Main {
>
>        private static final Logger logger = Logger.getLogger("test-renew");
>        private static final long MAX_EVENT_LEASE =
> TimeUnit.MINUTES.toMillis(5);
>     private static final long RENEW_BATCH_TIME_WINDOW =
> TimeUnit.MINUTES.toMillis(5);
>        private static final long ROUND_TRIP_TIME =
> TimeUnit.SECONDS.toMillis(3);
>        private static final long RENEW_DURATION =
> TimeUnit.SECONDS.toMillis(30);
>
>        public static void main(String[] args) throws IOException,
> ConfigurationException {
>
>              LeaseRenewalManager lrm = new LeaseRenewalManager(new
> ConfigurationMock());
>
>              Lease lease =
> MockEventLease.getInstance(System.currentTimeMillis() + MAX_EVENT_LEASE);
>
>              long desiredDuration = Lease.FOREVER;
>              long renewDuration = RENEW_DURATION;
>              lrm.renewFor(lease,desiredDuration, renewDuration, new
> LeaseListenerMock());
>              logger.info("Starting... Press any key to abort");
>              System.in.read();
>        }
>
>        private final static class MockEventLease extends EventLease {
>
>              MockEventLease(Registrar server, ServiceID registrarID, long
> eventID,
>                            Uuid leaseID, long expiration) {
>                     super(server, registrarID, eventID, leaseID,
> expiration);
>              }
>
>              private static final long serialVersionUID = 1L;
>
>              public void cancel() throws UnknownLeaseException,
> RemoteException {
>                     logger.info("cancel()");
>              }
>
>              protected long doRenew(long duration)
>                            throws UnknownLeaseException, RemoteException
>            {
>                     long actualDuration = Math.min(duration,
> MAX_EVENT_LEASE);
>                     logger.info("doRenew(duration="+duration+") returns "
> + actualDuration);
>               return actualDuration;
>            }
>
>              static EventLease getInstance(long expiration)
>                {
>                     return new MockEventLease(null, new
> ServiceID(1,1),1,new Uuid(1,1),expiration);
>                }
>        }
>
>        private final static class LeaseListenerMock implements
> LeaseListener , DesiredExpirationListener {
>
>              /* When lease renewal fails, we discard the proxy  */
>              public void notify(LeaseRenewalEvent e) {
>                     logger.info("notify(e="+e+")");
>              }
>
>              @Override
>              public void expirationReached(LeaseRenewalEvent e) {
>                     logger.info("expirationReached(e="+e+")");
>
>              }
>        }
>
>        private final static class ConfigurationMock extends
> AbstractConfiguration {
>
>              private static final String LRM =
> "net.jini.lease.LeaseRenewalManager";
>
>              Map<String,Object> properties = new HashMap<String,Object>();
>
>              ConfigurationMock() {
>                     setEntry(LRM, "renewBatchTimeWindow", new
> Primitive(RENEW_BATCH_TIME_WINDOW));
>                     setEntry(LRM, "roundTripTime", new
> Primitive(ROUND_TRIP_TIME));
>                     setEntry(LRM, "taskManager", new TaskManager(11, 1000
> * 15, 1.0f));
>              }
>
>              @Override
>              protected Object getEntryInternal(String component, String
> name,
>                            Class type, Object data) throws
> ConfigurationException {
>
>                     String key = key(component, name);
>                     if (properties.containsKey(key)) {
>                            return properties.get(key);
>                     }
>                     return data;
>              }
>
>              private void setEntry(String component, String name, Object
> value) {
>                     properties.put(key(component, name),value);
>              }
>
>              private String key(String component, String name) {
>                     return component+"."+name;
>              }
>
>
>        }
> }
>