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;
}
}
}