FileDocCategorySizeDatePackage
ConvertServiceImpl.javaAPI DocExample20982Thu Mar 16 11:52:48 GMT 2000None

ConvertServiceImpl

public 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.Stringconvert(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 voidfindLookupDiscoveryService()

        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 ConvertServiceRegistrationgetInstance(long duration)

        Hashtable ht = new Hashtable(13);
        Lease l = lord.newLease(ht, duration);
        startWaitThread();
        return new ConvertServiceRegistrationImpl(this, l);
    
private synchronized longgetNextSeq()

        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 voidmain(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 voidnotify(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 voidregister(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 voidrenewLease(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 voidresyncHashtable(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 voidstartWaitThread()

        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 EventRegistrationtrackConversions(long duration, RemoteEventListener rel, java.rmi.MarshalledObject key)

        return sender.addListener(rel, duration, key, seqNo);
    
private voidunregister(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);