// Copyright © 2002 // John M. Thompson // Boulder, Colorado USA // jt@iwaytechnology.com // http://www.iwaytechnology.com // // A limited right to copy this page for // individual (non-commercial) educational // use only is hereby granted. import iwaypublishing.util.IMsgPortManager; import java.io.*; import java.net.*; /********************************************************************** * A server app that requires an orderly shutdown feature. *

* * Usage (Windows): * * Start first Server app (in cmd wdw 1): * * > java -classpath . myserver 1789 sample.txt * * Start second Server app w/stop (in cmd wdw 2): * * > java -classpath . myserver 1789 stop * */ public class myserver { /** * Port number for termination communication. * 'static' implies we'll have one instance of * this server per JVM. */ private static int msgPort_ = 0; /** * IMsgPortManager portManager_ will listen for a second * instance of myserver attempting to notify us to * shutdown in orderly fashion. This communication is * achieved with IMsgPortManager.sendTerminate(). */ private static IMsgPortManager portManager_ = null; /** Where 'important work' is 'documented' */ private static PrintWriter out_ = null; // Optional upper bound on processing iterations // (demonstration purposes only, not required). private static final int INTERNAL_MAX_COUNT = 100000; /******************************************************************* * @param args String array of command line args - first one is * port number to monitor or terminate with, and if followed by * 'stop' (no quotes), attempt to terminate running server. */ public static void main( String[] args ) throws IOException, SocketException, InterruptedException { // See processArgs() for reasons it may return false if( ! processArgs( args ) ) return; // Start up a message port manager startupPortManager(); // Do work, waiting for termination request; // when returns, shutdown go(); shutdownPortManager(); shutdownPrintWriter(); // Hold up app for a response byte[] response = new byte[ 256 ]; System.out.println( "\nmyserver.main() all done. Press ." ); System.in.read( response ); } /******************************************************************* * processArgs - Handle comand line args * * @param args String array of cmd line args. * @return boolean true => continue, false => exit */ private static boolean processArgs( String[] args ) { if( args.length < 2 ) { System.out.println( "Usage: myserver ( stop | )" ); return false; } try { msgPort_ = Integer.parseInt( args[ 0 ] ); // Is second arg Stop msg or file name? if( args[ 1 ].equalsIgnoreCase( "stop" ) ) { // DEBUG System.out.println( "Attempting to stop running instance -" ); if( IMsgPortManager.sendTerminate( msgPort_ ) ) { // DEBUG System.out.println( " - Success." ); } else { // DEBUG System.out.println( " - Failure." ); } return false; } else { // Get file name arg out_ = new PrintWriter( new BufferedWriter( new FileWriter( args[ 1 ] ) ) ); } } catch( Exception e ) { System.out.println( "Usage: myserver ( stop | )" ); return false; } return true; } /* ************************************************************** */ private static void shutdownPrintWriter() throws IOException, SocketException, InterruptedException { out_.flush(); out_.close(); } /* ************************************************************** */ private static void startupPortManager() throws IOException, SocketException { portManager_ = new IMsgPortManager( msgPort_ ); portManager_.start(); } /* ************************************************************** */ private static void shutdownPortManager() throws IOException, SocketException, InterruptedException { portManager_.kill(); portManager_.join(); } /* ****************************************************************/ private static void go() throws InterruptedException { int count = 0; int workUnit = 0; while( count++ < INTERNAL_MAX_COUNT ) { // Begin important, uniterruptable work. out_.println( "Started work unit " + ++workUnit ); // Do important work (sleep to simulate passage of time) try { Thread.sleep( 3000 ); // milliseconds } catch( InterruptedException e ){ return; } out_.println( "Finished work unit " + workUnit ); // Check for termination request from a second cmd-line // instance. This should be done AT LEAST once every ten // seconds, if possible, at a "good time" for shutdown // (ie, no possible loss of data) System.out.println( "In myserver.go(), checking for termination request." ); if( portManager_.isTerminate() ) { System.out.println( "\nIn myserver.go(), handling termination request after " + workUnit + " units of work." ); return; } } } }