From: Bryan T. <tho...@us...> - 2007-03-23 18:42:53
|
Update of /cvsroot/cweb/bigdata/src/java/com/bigdata/service In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv32506/src/java/com/bigdata/service Modified Files: AbstractServer.java DataServer.java Log Message: Working on service admin and service starter. Index: DataServer.java =================================================================== RCS file: /cvsroot/cweb/bigdata/src/java/com/bigdata/service/DataServer.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** DataServer.java 22 Mar 2007 21:11:23 -0000 1.1 --- DataServer.java 23 Mar 2007 18:42:45 -0000 1.2 *************** *** 49,54 **** --- 49,57 ---- import java.rmi.Remote; + import java.rmi.RemoteException; import java.util.Properties; + import com.sun.jini.start.LifeCycle; + /** * The bigdata data server. *************** *** 67,70 **** --- 70,79 ---- } + + public DataServer(String[] args, LifeCycle lifeCycle) { + + super( args, lifeCycle ); + + } public static void main(String[] args) { *************** *** 76,80 **** protected Remote newService(Properties properties) { ! return new DataService(properties); } --- 85,271 ---- protected Remote newService(Properties properties) { ! return new AdministrableDataService(this,properties); ! ! } ! ! /** ! * Adds jini administration interfaces to the basic {@link DataService}. ! * ! * @author <a href="mailto:tho...@us...">Bryan Thompson</a> ! * @version $Id$ ! */ ! public static class AdministrableDataService extends DataService implements ! RemoteAdministrable, RemoteDestroyAdmin { ! ! protected AbstractServer server; ! ! public AdministrableDataService(AbstractServer server,Properties properties) { ! ! super(properties); ! ! this.server = server; ! ! } ! ! public Object getAdmin() throws RemoteException { ! ! log.info(""); ! ! return server.proxy; ! ! } ! ! /* ! * DestroyAdmin ! */ ! ! /** ! * Destroy the service and deletes any files containing resources (<em>application data</em>) ! * that was in use by that service. ! * ! * @throws RemoteException ! */ ! public void destroy() throws RemoteException { ! ! log.info(""); ! ! boolean destroyEnabled = true; ! ! if (destroyEnabled) { ! ! new Thread() { ! ! public void run() { ! ! server.shutdownNow(); ! ! try { ! ! journal.closeAndDelete(); ! ! log.info("Journal deleted."); ! ! } catch (Throwable t) { ! ! log.warn("Could not delete persistent state: " + t, ! t); ! ! } ! ! if (!server.serviceIdFile.delete()) { ! ! log.warn("Could not delete file: " ! + server.serviceIdFile); ! ! } ! ! try { ! Thread.sleep(3); ! } catch (InterruptedException ex) { ! } ! ! log.info("Service Stop requested"); ! ! System.exit(1); ! ! } ! ! }.start(); ! ! } else { ! ! throw new RemoteException( ! "Service Destroy Not Enabled, Operation Ignored"); ! } ! ! } ! ! // /* ! // * JoinAdmin ! // */ ! // ! // public void addLookupAttributes(Entry[] arg0) throws RemoteException { ! // ! // log.info(""); ! // ! // // TODO Auto-generated method stub ! // ! // } ! // ! // public void addLookupGroups(String[] arg0) throws RemoteException { ! // ! // log.info(""); ! // ! // // TODO Auto-generated method stub ! // ! // } ! // ! // public void addLookupLocators(LookupLocator[] arg0) throws RemoteException { ! // ! // log.info(""); ! // ! // // TODO Auto-generated method stub ! // ! // } ! // ! // public Entry[] getLookupAttributes() throws RemoteException { ! // ! // log.info(""); ! // ! // // TODO Auto-generated method stub ! // return null; ! // } ! // ! // public String[] getLookupGroups() throws RemoteException { ! // ! // log.info(""); ! // ! // // TODO Auto-generated method stub ! // return null; ! // } ! // ! // public LookupLocator[] getLookupLocators() throws RemoteException { ! // ! // log.info(""); ! // ! // // TODO Auto-generated method stub ! // return null; ! // } ! // ! // public void modifyLookupAttributes(Entry[] arg0, Entry[] arg1) throws RemoteException { ! // ! // log.info(""); ! // ! // // TODO Auto-generated method stub ! // ! // } ! // ! // public void removeLookupGroups(String[] arg0) throws RemoteException { ! // log.info(""); ! // ! // // TODO Auto-generated method stub ! // ! // } ! // ! // public void removeLookupLocators(LookupLocator[] arg0) throws RemoteException { ! // log.info(""); ! // ! // // TODO Auto-generated method stub ! // ! // } ! // ! // public void setLookupGroups(String[] arg0) throws RemoteException { ! // log.info(""); ! // ! // // TODO Auto-generated method stub ! // ! // } ! // ! // public void setLookupLocators(LookupLocator[] arg0) throws RemoteException { ! // log.info(""); ! // ! // // TODO Auto-generated method stub ! // ! // } } Index: AbstractServer.java =================================================================== RCS file: /cvsroot/cweb/bigdata/src/java/com/bigdata/service/AbstractServer.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** AbstractServer.java 22 Mar 2007 21:11:23 -0000 1.1 --- AbstractServer.java 23 Mar 2007 18:42:45 -0000 1.2 *************** *** 60,63 **** --- 60,64 ---- import java.util.Properties; + import net.jini.admin.Administrable; import net.jini.admin.JoinAdmin; import net.jini.config.Configuration; *************** *** 74,77 **** --- 75,79 ---- import net.jini.lease.LeaseRenewalEvent; import net.jini.lease.LeaseRenewalManager; + import net.jini.lookup.DiscoveryAdmin; import net.jini.lookup.JoinManager; import net.jini.lookup.ServiceIDListener; *************** *** 79,97 **** import org.apache.log4j.Logger; ! import sun.misc.Signal; ! import sun.misc.SignalHandler; /** * Abstract base class for configurable services discoverable using JINI. ! * Services are started using a <code>main</code> routine: * <pre> ! public static void main(String[] args) { ! ! new MyServer(args).run(); ! ! } ! * </pre> ! * ! * * @author <a href="mailto:tho...@us...">Bryan Thompson</a> * @version $Id$ --- 81,120 ---- import org.apache.log4j.Logger; ! import com.sun.jini.admin.DestroyAdmin; ! import com.sun.jini.admin.StorageLocationAdmin; ! import com.sun.jini.start.LifeCycle; ! import com.sun.jini.start.NonActivatableServiceDescriptor; ! import com.sun.jini.start.ServiceDescriptor; ! import com.sun.jini.start.ServiceStarter; /** * Abstract base class for configurable services discoverable using JINI. ! * <p> ! * The recommended way to start a server is using the {@link ServiceStarter}. ! * <p> ! * The server MAY be started using a <code>main</code> routine: ! * * <pre> ! * public static void main(String[] args) { ! * ! * new MyServer(args).run(); ! * ! * } ! * </pre> ! * ! * The service may be <em>terminated</em> by terminating the server process. ! * <p> ! * Services are <em>destroyed</em> using {@link DestroyAdmin}, e.g., through ! * the Jini service browser. Note that this tends to imply that all persistent ! * data associated with that service is also destroyed! ! * ! * @see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6380355, which ! * describes a bug in the service browser that will display a ! * "NullPointerException" dialog box if you destroy a service which ! * implements {@link DestroyAdmin} but not {@link JoinAdmin}. ! * ! * @see http://java.sun.com/products/jini/2.0/doc/api/com/sun/jini/start/ServiceStarter.html ! * for documentation on how to use the ServiceStarter. ! * * @author <a href="mailto:tho...@us...">Bryan Thompson</a> * @version $Id$ *************** *** 102,106 **** public static final transient Logger log = Logger .getLogger(AbstractServer.class); ! private ServiceID serviceID; private DiscoveryManagement discoveryManager; --- 125,141 ---- public static final transient Logger log = Logger .getLogger(AbstractServer.class); ! ! /** ! * The label in the {@link Configuration} file for the service ! * description. ! */ ! protected final static transient String SERVICE_LABEL = "ServiceDescription"; ! ! /** ! * The label in the {@link Configuration} file for the service advertisment ! * data. ! */ ! protected final static transient String ADVERT_LABEL = "AdvertDescription"; ! private ServiceID serviceID; private DiscoveryManagement discoveryManager; *************** *** 110,114 **** * The file where the {@link ServiceID} will be written/read. */ ! private File serviceIdFile; /** * Responsible for exporting a proxy for the service. --- 145,149 ---- * The file where the {@link ServiceID} will be written/read. */ ! protected File serviceIdFile; /** * Responsible for exporting a proxy for the service. *************** *** 122,128 **** * The exported proxy for the service implementation object. */ ! private Remote proxy; /** * Server startup reads {@link Configuration} data from the file(s) named by * <i>args</i>, starts the service, and advertises the service for --- 157,171 ---- * The exported proxy for the service implementation object. */ ! protected Remote proxy; /** + * The object used to inform the hosting environment that the server is + * unregistering (terminating). A fake object is used when the server is run + * from the command line, otherwise the object is supplied by the + * {@link NonActivatableServiceDescriptor}. + */ + private LifeCycle lifeCycle; + + /** * Server startup reads {@link Configuration} data from the file(s) named by * <i>args</i>, starts the service, and advertises the service for *************** *** 135,142 **** protected AbstractServer(String[] args) { ! final String SERVICE_LABEL = "ServiceDescription"; ! final String ADVERT_LABEL = "AdvertDescription"; Entry[] entries = null; LookupLocator[] unicastLocators = null; --- 178,205 ---- protected AbstractServer(String[] args) { ! this( args, new FakeLifeCycle() ); ! ! } ! /** ! * Server startup invoked by the ServerStarter ! * ! * @param args ! * Arguments from the {@link ServiceDescriptor}. ! * @param lifeCycle ! * The life cycle object. ! * ! * @see NonActivatableServiceDescriptor ! */ ! protected AbstractServer(String[] args, LifeCycle lifeCycle ) { ! ! if (lifeCycle == null) ! throw new IllegalArgumentException(); ! ! this.lifeCycle = lifeCycle; + // @todo verify that this belongs here. + System.setSecurityManager(new SecurityManager()); + Entry[] entries = null; LookupLocator[] unicastLocators = null; *************** *** 148,154 **** /* ! * Extract how the service will perform service discovery. */ groups = (String[]) config.getEntry(ADVERT_LABEL, "groups", String[].class, LookupDiscovery.ALL_GROUPS/* default */); --- 211,221 ---- /* ! * Extract how the service will advertise itself from the ! * Configuration. */ + entries = (Entry[]) config.getEntry(ADVERT_LABEL, "entries", + Entry[].class, null/* default */); + groups = (String[]) config.getEntry(ADVERT_LABEL, "groups", String[].class, LookupDiscovery.ALL_GROUPS/* default */); *************** *** 159,170 **** /* ! * Extract how the service will advertise itself from the * Configuration. */ ! entries = (Entry[]) config.getEntry(ADVERT_LABEL, "entries", ! Entry[].class, null/* default */); ! serviceIdFile = (File) config.getEntry(ADVERT_LABEL, "serviceIdFile", File.class); // default --- 226,242 ---- /* ! * Extract how the service will provision itself from the * Configuration. */ ! // The exporter used to expose the service proxy. ! exporter = (Exporter) config.getEntry(// ! SERVICE_LABEL, // component ! "exporter", // name ! Exporter.class // type (of the return object) ! ); ! // The file on which the ServiceID will be written. ! serviceIdFile = (File) config.getEntry(SERVICE_LABEL, "serviceIdFile", File.class); // default *************** *** 189,208 **** } - - /* - * Extract how the service will provision itself from the - * Configuration. - */ ! // use the configuration to construct an exporter ! exporter = (Exporter) config.getEntry(// ! SERVICE_LABEL, // component ! "exporter", // name ! Exporter.class // type (of the return object) ! ); ! ! /* ! * Access the properties file used to configure the service. ! */ File propertyFile = (File) config.getEntry(SERVICE_LABEL, --- 261,266 ---- } ! // The properties file used to configure the service. File propertyFile = (File) config.getEntry(SERVICE_LABEL, *************** *** 408,465 **** /** - * Run the server (this should be invoked from <code>main</code>. - * - * FIXME work through the install a signal handler that will shutdown the - * service politely when it is invoked. Do we need -Xrs on the command - * line for this to work? Which signals should be trapped? Does this - * vary by OS? - * - * SIGINT Interactive attention (CTRL-C). JVM will exit normally. Yes <br> - * SIGTERM Termination request. JVM will exit normally. Yes <br> - * SIGHUP Hang up. JVM will exit normally. Yes - * - * @see http://www-128.ibm.com/developerworks/java/library/i-signalhandling/ - */ - protected void run() { - - log.info("Started server."); - - /* - * Install signal handlers. - */ - - ServerShutdownSignalHandler.install("SIGINT",this); - - // ServerShutdownSignalHandler.install("SIGTERM",this); - - /* - * Wait until the server is terminated. - */ - - Object keepAlive = new Object(); - - synchronized (keepAlive) { - - try { - - keepAlive.wait(); - - } catch (InterruptedException ex) { - - log.info(""+ex); - - } - - } - - } - - /** * Shutdown the server taking time only to unregister it from jini. - * - * @todo make this extensible? provide for normal shutdown vs this? support - * the jini Admin interface. */ ! private void shutdownNow() { /* --- 466,472 ---- /** * Shutdown the server taking time only to unregister it from jini. */ ! public void shutdownNow() { /* *************** *** 470,473 **** --- 477,485 ---- log.info("Terminating manager threads."); + + /* + * Hand-shaking with the NonActivableServiceDescriptor. + */ + lifeCycle.unregister(this); joinManager.terminate(); *************** *** 495,566 **** /** ! * Signal handler shuts down the server politely. ! * ! * @author <a href="mailto:tho...@us...">Bryan Thompson</a> ! * @version $Id$ */ ! static class ServerShutdownSignalHandler implements SignalHandler { ! private final AbstractServer server; ! private SignalHandler oldHandler; ! protected ServerShutdownSignalHandler(AbstractServer server) { ! if(server == null) throw new IllegalArgumentException(); ! this.server = server; } ! /** ! * Install the signal handler. ! */ ! public static SignalHandler install(String signalName, ! AbstractServer server) { ! ! Signal signal = new Signal(signalName); ! ! ServerShutdownSignalHandler newHandler = new ServerShutdownSignalHandler( ! server); ! ! newHandler.oldHandler = Signal.handle(signal, newHandler); ! ! log.info("Installed handler: " + signal + ", oldHandler=" ! + newHandler.oldHandler); ! ! return newHandler; } ! public void handle(Signal sig) { - log.warn("Signal: "+sig); - - /* - * Handle signal. - */ server.shutdownNow(); - try { - - // Chain back to previous handler, if one exists - if ( oldHandler != SIG_DFL && oldHandler != SIG_IGN ) { - - oldHandler.handle(sig); - - } - - } catch (Exception ex) { - - log.fatal("Signal handler failed, reason "+ex); - - System.exit(1); - - } - } } /** --- 507,683 ---- /** ! * Run the server (this should be invoked from <code>main</code>. You can ! * stop the server using ^C (Windows) and possibly <code>kill</code> (Un*x). ! * You can record the PID of the process running the server when you start ! * it under Un*x using a shell script. ! * <p> ! * Note: If you want to DESTROY a service (and its state), then you can do ! * that from the Jini Service Browser. */ ! protected void run() { ! log.info("Started server."); ! ! /* ! * Note: I have found the Runtime shutdown hook to be much more robust ! * than attempting to install a signal handler. ! */ ! // /* ! // * Install signal handlers. ! // * SIGINT Interactive attention (CTRL-C). JVM will exit normally. <br> ! // * SIGTERM Termination request. JVM will exit normally. <br> ! // * SIGHUP Hang up. JVM will exit normally.<br> ! // * ! // * @see http://www-128.ibm.com/developerworks/java/library/i-signalhandling/ ! // * ! // * @see http://forum.java.sun.com/thread.jspa?threadID=514860&messageID=2451429 ! // * for the use of {@link Runtime#addShutdownHook(Thread)}. ! // * ! // */ ! // ! // try { ! // ServerShutdownSignalHandler.install("SIGINT",this); ! // } catch(IllegalArgumentException ex) { ! // log.info("Signal handled not installed: "+ex); ! // } ! // ! // try { ! // ServerShutdownSignalHandler.install("SIGTERM",this); ! // } catch(IllegalArgumentException ex) { ! // log.info("Signal handled not installed: "+ex); ! // } ! // ! // try { ! // ServerShutdownSignalHandler.install("SIGHUP",this); ! // } catch(IllegalArgumentException ex) { ! // log.info("Signal handled not installed: "+ex); ! // } ! /* ! * The runtime shutdown hook appears to be a bit more robust. ! */ ! Runtime.getRuntime().addShutdownHook(new ShutdownThread(this)); ! /* ! * Wait until the server is terminated. ! */ ! ! Object keepAlive = new Object(); ! ! synchronized (keepAlive) { ! try { ! ! keepAlive.wait(); ! ! } catch (InterruptedException ex) { ! ! log.info(""+ex); ! ! } } + + } ! /** ! * Runs {@link AbstractServer#shutdownNow()}. ! * ! * @author <a href="mailto:tho...@us...">Bryan Thompson</a> ! * @version $Id$ ! */ ! static class ShutdownThread extends Thread { ! ! final AbstractServer server; ! ! public ShutdownThread(AbstractServer server) { ! ! if (server == null) ! throw new IllegalArgumentException(); ! ! this.server = server; } + + public void run() { ! log.info("Runing shutdown."); server.shutdownNow(); } } + + // /** + // * Signal handler shuts down the server politely. + // * + // * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + // * @version $Id$ + // */ + // static class ServerShutdownSignalHandler implements SignalHandler { + // + // private final AbstractServer server; + // + // private SignalHandler oldHandler; + // + // protected ServerShutdownSignalHandler(AbstractServer server) { + // + // if(server == null) throw new IllegalArgumentException(); + // + // this.server = server; + // + // } + // + // /** + // * Install the signal handler. + // */ + // public static SignalHandler install(String signalName, + // AbstractServer server) { + // + // Signal signal = new Signal(signalName); + // + // ServerShutdownSignalHandler newHandler = new ServerShutdownSignalHandler( + // server); + // + // newHandler.oldHandler = Signal.handle(signal, newHandler); + // + // log.info("Installed handler: " + signal + ", oldHandler=" + // + newHandler.oldHandler); + // + // return newHandler; + // + // } + // + // public void handle(Signal sig) { + // + // log.warn("Processing signal: "+sig); + // + // /* + // * Handle signal. + // */ + // server.shutdownNow(); + // + // try { + // + // // Chain back to previous handler, if one exists + // if ( oldHandler != SIG_DFL && oldHandler != SIG_IGN ) { + // + // oldHandler.handle(sig); + // + // } + // + // } catch (Exception ex) { + // + // log.fatal("Signal handler failed, reason "+ex); + // + // System.exit(1); + // + // } + // + // } + // + // } /** *************** *** 621,623 **** --- 738,777 ---- // } + + /* + * Note: You need to extend Remote in order for these APIs to be exported! + */ + + public static interface RemoteAdministrable extends Remote, Administrable { + + } + + public static interface RemoteDestroyAdmin extends Remote, DestroyAdmin { + + } + + public static interface RemoteJoinAdmin extends Remote, JoinAdmin { + + } + + public static interface RemoteDiscoveryAdmin extends Remote, DiscoveryAdmin { + + } + + public static interface RemoteStorageLocationAdmin extends Remote, StorageLocationAdmin { + + } + + private static class FakeLifeCycle implements LifeCycle { + + public boolean unregister(Object arg0) { + + log.info(""); + + return true; + + } + + } + } |