ConvertServiceImplpublic class ConvertServiceImpl extends Activatable implements RemoteEventListener, ConvertServiceProxy
Fields Summary |
---|
private ServerLandlord | lord | private ServerDelivery | sender | private ConvertServiceLogHandler | handler | private ReliableLog | log | private long | seqNo | private ServiceID | serviceID | private ActivationID | activeID | private LookupDiscoveryRegistration | lookupReg | private LeaseRenewalSet | leaseRenewal | private String[] | groups | private Hashtable | leases | private Thread | waitThread | private long | lastLookupSeqNo | private ServiceItem | serviceItem |
Constructors Summary |
---|
public ConvertServiceImpl(ActivationID id, MarshalledObject data)
super(id, 0);
System.out.println("classpath " + System.getProperty("java.class.path"));
System.out.println("codebase " + System.getProperty("java.rmi.server.codebase"));
activeID = id;
try {
String logDir = (String) data.get();
handler = new ConvertServiceLogHandler();
log = new ReliableLog(logDir, handler);
log.recover();
lord = new ServerLandlord();
sender = new ServerDelivery(this, lord);
if (lookupReg == null) {
// First time we've run, so there is no
// lookup discovery service yet
leases = new Hashtable();
findLookupDiscoveryService();
}
log.snapshot();
} catch (Exception e) {
throw new RemoteException("Can't construct service", e);
}
|
Methods Summary |
---|
public java.lang.String | convert(Lease l, int i)
Hashtable cache = (Hashtable) lord.getSessionData(l);
if (cache == null)
throw new LeaseDeniedException("Lease expired");
Integer I = new Integer(i);
String s;
s = (String) cache.get(I);
if (s == null) {
s = I.toString();
cache.put(I, s);
}
sender.deliver(i, getNextSeq());
return s;
| private void | findLookupDiscoveryService()
ServiceFinder sf = new ServiceFinder(LookupDiscoveryService.class);
LookupDiscoveryService lds = (LookupDiscoveryService) sf.getObject();
lookupReg = lds.register(groups, null, this,
new MarshalledObject("dummy"), Lease.FOREVER);
EventRegistration er = lookupReg.getEventRegistration();
lastLookupSeqNo = er.getSequenceNumber();
renewLease(lookupReg.getLease());
| public ConvertServiceRegistration | getInstance(long duration)
Hashtable ht = new Hashtable(13);
Lease l = lord.newLease(ht, duration);
startWaitThread();
return new ConvertServiceRegistrationImpl(this, l);
| private synchronized long | getNextSeq()
seqNo++;
try {
// Update the log with the new seq no; we must wrap
// this into an object for the update method
ConvertServiceUpdateRecord csur = new ConvertServiceUpdateRecord();
csur.seqNo = this.seqNo;
log.update(csur, true);
} catch (Exception e) {
e.printStackTrace();
}
return seqNo;
| public static void | main(java.lang.String[] args)
System.setSecurityManager(new RMISecurityManager());
Properties props = new Properties();
props.put("java.security.policy", args[1]);
props.put("java.class.path", System.getProperty("java.class.path"));
props.put("java.rmi.server.codebase", args[0]);
ActivationGroupDesc agd = new ActivationGroupDesc(props, null);
ActivationGroupID agi = ActivationGroup.getSystem().registerGroup(agd);
ActivationGroup.createGroup(agi, agd, 0);
ActivationDesc ad = new ActivationDesc("ConvertServiceImpl",
args[0], new MarshalledObject(args[2]));
ConvertService cs = (ConvertService) Activatable.register(ad);
cs.getInstance(0);
System.exit(0);
| public synchronized void | notify(RemoteEvent re)
if (re instanceof ExpirationWarningEvent) {
try {
ExpirationWarningEvent ewe = (ExpirationWarningEvent) re;
Lease l = ewe.getLease();
l.renew(TimeConstants.DAYS);
} catch (Exception e) {
// We should take over lease renewal ourselves, using a
// lease renewal manager.
}
startWaitThread();
return;
}
if (!(re instanceof RemoteDiscoveryEvent)) {
System.out.println("Unexpected event " + re);
throw new UnknownEventException("ConvertServiceImpl");
}
RemoteDiscoveryEvent rde = (RemoteDiscoveryEvent) re;
long seq = rde.getSequenceNumber();
if (seq <= lastLookupSeqNo) {
// This event was delivered out of order. We noticed at
// the time that we had dropped it, so we can just ignore it.
return;
}
if (seq != lastLookupSeqNo + 1) {
// We may have dropped an event. In order to tell, we have
// to check with the lookup discovery service. Since we're
// in a callback from that service, we can't call it in this
// thread or deadlock will occur.
class runResync implements Runnable {
long seq;
runResync(long l) {
seq = l;
}
public void run() {
resyncHashtable(seq);
}
};
new Thread(new runResync(seq)).start();
return;
}
else {
// Else the sequence number was as expected; get the registrars
// and process them
ServiceRegistrar[] sr = null;
try {
sr = rde.getRegistrars();
} catch (LookupUnmarshalException lue) {
// Get the ones that we can; ignore the rest
sr = lue.getUnmarshalledRegs();
}
if (rde.isDiscarded()) {
for (int i = 0; i < sr.length; i++) {
if (leases.containsKey(sr[i])) {
unregister(sr[i]);
}
}
}
else {
for (int i = 0; i < sr.length; i++) {
if (leases.containsKey(sr[i]) == false) {
register(sr[i]);
}
}
// else we were already registered in this service
}
}
// All done -- update the log with the new leases and seq no
lastLookupSeqNo = seq;
try {
log.update(new ConvertServiceUpdateLeases(leases, lastLookupSeqNo), true);
} catch (Exception e) {
System.out.println("Update failed " + e);
}
startWaitThread();
| private void | register(ServiceRegistrar sr)
try {
if (serviceItem == null)
serviceItem = new ServiceItem(serviceID, this, null);
ServiceRegistration ret = sr.register(serviceItem, Lease.FOREVER);
if (serviceID == null) {
serviceID = ret.getServiceID();
try {
log.snapshot();
} catch (Exception e) {
System.out.println("Can't take snapshot" + e);
}
}
// Save this registration
try {
leases.put(sr, ret.getLease());
renewLease(ret.getLease());
} catch (IOException ioe) {
// Can't really happen -- renewLease only throws IOException
// when it finds the service, and we already know the service
// has been found
}
} catch (RemoteException rex) {
System.out.println("Can't register with service " + rex);
try {
lookupReg.discard(sr);
} catch (RemoteException rExp) {
}
}
| private void | renewLease(Lease l)
ServiceFinder sf = null;
LeaseRenewalService lrs = null;
while (true) {
// If leaseRenewal is null, we have to find one. It will be
// null the first time we run the code; if we get an error
// talking to a leaseRenewal object, we set it to null so
// that we find another one here.
// If we've just be re-activated, then leaseRenewal will be set
// from the log.
if (leaseRenewal == null) {
// Only set sf the first time we need it.
if (sf == null)
sf = new ServiceFinder(LeaseRenewalService.class);
lrs = (LeaseRenewalService) sf.getObject();
leaseRenewal = lrs.createLeaseRenewalSet(TimeConstants.DAYS);
leaseRenewal.setExpirationWarningListener(this, TimeConstants.HOURS, null);
}
try {
leaseRenewal.renewFor(l, Lease.FOREVER);
break;
} catch (RemoteException re) {
// If we were talking to a leaseRenewal from a previous
// activation, sf will be null. We'll create the sf the
// next time through the loop.
if (sf != null)
sf.errored(lrs);
leaseRenewal = null;
}
}
| private synchronized void | resyncHashtable(long seq)
// Because this runs in another thread, it's conceivable that
// the another event has superceded this.
if (seq <= lastLookupSeqNo)
return;
ServiceRegistrar[] current = new ServiceRegistrar[0];
try {
current = lookupReg.getRegistrars();
} catch (Exception exp) {
// There's no way in the LookupDiscoveryService interface
// to find just the successful ones -- best we can do
// is to drop the event and try again when the next
// event comes.
return;
}
Hashtable newLeases = new Hashtable();
for (int i = 0; i < current.length; i++) {
Object o = leases.get(current[i]);
if (o == null) {
// We haven't registered this one yet
register(current[i]);
}
else {
// We have registered; just move the registration
newLeases.put(current[i], o);
leases.remove(current[i]);
}
}
for (Enumeration e = leases.keys(); e.hasMoreElements(); ) {
unregister((ServiceRegistrar) e.nextElement());
}
leases = newLeases;
lastLookupSeqNo = seq;
try {
log.update(new ConvertServiceUpdateLeases(leases, seq), true);
} catch (IOException ioe) {
System.out.println("Update failed " + ioe);
}
startWaitThread();
| private synchronized void | startWaitThread()
if (waitThread != null)
return;
Runnable doWait = new Runnable() {
public void run() {
while (true) {
// There's a possibility that the client is connecting,
// but has not yet been granted a lease (or isn't even
// getting a lease if we became active as a result of
// a lookup discovery service event).
// Wait a bit to let that settle down, and
// then wait for the lease to be empty again.
try {
Thread.sleep(60 * 1000);
} catch (Exception e) {}
// Wait until there are no clients with an active lease
// and then exit when that happens
lord.waitForEmpty();
try {
if (Activatable.inactive(activeID)) {
try {
log.snapshot();
} catch (Exception e) {
}
System.exit(0);
}
} catch (Exception e) {
// inactive() threw an exception -- simply exit,
// because rmid is confused, but it will restart
// and recover (and then restart us if needed)
System.exit(0);
}
}
}
};
waitThread = new Thread(doWait);
waitThread.start();
| public synchronized EventRegistration | trackConversions(long duration, RemoteEventListener rel, java.rmi.MarshalledObject key)
return sender.addListener(rel, duration, key, seqNo);
| private void | unregister(ServiceRegistrar sr)
// Remove the registration. If the lookup service comes
// back later, we'll re-register at that time.
// Tell the lease renewal to let the lease expire
// and remove it from our internal table too.
try {
leaseRenewal.remove((Lease) leases.get(sr));
} catch (Exception cnfe) {
}
leases.remove(sr);
|
|