diff options
author | eea1 <eea1@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1999-08-24 23:12:37 +0000 |
---|---|---|
committer | eea1 <eea1@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1999-08-24 23:12:37 +0000 |
commit | 85b7a05af21aad014e51c6944d794e73fcc68554 (patch) | |
tree | ec567c584c3d5aa77cc2ca9340c9680a45b3a66a /java | |
parent | 06e70dfaca9d8a9c2b3d6699678c8fe1ea08623b (diff) | |
download | ATCD-85b7a05af21aad014e51c6944d794e73fcc68554.tar.gz |
Updated source files for netsvcs/Time.
Diffstat (limited to 'java')
-rw-r--r-- | java/JACE/netsvcs/Time/TSClerkHandler.java | 195 | ||||
-rw-r--r-- | java/JACE/netsvcs/Time/TSClerkProcessor.java | 307 | ||||
-rw-r--r-- | java/JACE/netsvcs/Time/TSServerAcceptor.java | 116 | ||||
-rw-r--r-- | java/JACE/netsvcs/Time/TSServerHandler.java | 53 | ||||
-rw-r--r-- | java/JACE/netsvcs/Time/TimeInfo.java | 90 | ||||
-rw-r--r-- | java/JACE/netsvcs/Time/TimeRequest.java | 121 | ||||
-rw-r--r-- | java/JACE/netsvcs/Time/c.bat | 1 | ||||
-rw-r--r-- | java/JACE/netsvcs/Time/package.html | 10 | ||||
-rw-r--r-- | java/JACE/netsvcs/Time/r.bat | 1 |
9 files changed, 894 insertions, 0 deletions
diff --git a/java/JACE/netsvcs/Time/TSClerkHandler.java b/java/JACE/netsvcs/Time/TSClerkHandler.java new file mode 100644 index 00000000000..e0a2290d81b --- /dev/null +++ b/java/JACE/netsvcs/Time/TSClerkHandler.java @@ -0,0 +1,195 @@ +package JACE.netsvcs.Time; + +import java.io.*; +import java.net.*; + +import JACE.OS.*; +import JACE.Connection.*; +import JACE.ASX.*; + +/** + * Requests a time update from a time server. This is used by the + * TSClerkProcessor to query a server. + */ +public class TSClerkHandler extends SvcHandler +{ + /** + * Constructor. + * + *@param parent TSClerkProcessor which is creating this instance + *@param host name of the machine this handler is connected to + *@param port port on the time server to connect to + */ + public TSClerkHandler (TSClerkProcessor parent, + String host, + int port) + { + parent_ = parent; + host_ = host; + port_ = port; + } + + /** + * Initialize this handler. Called automatically by Connector when a + * successful connection is made. + * + *@return -1 on failure, 0 on success + */ + public int open (Object obj) + { + ACE.DEBUG ("Successful connection to " + host ()); + connected (true); + return 0; + } + + /** + * Safely shut down this handler, closing the socket. + * + *@return -1 on failure, 0 on success + */ + public synchronized int close () + { + if (!connected ()) + return 0; + + ACE.DEBUG ("Shutting down connection to " + host ()); + try { + peer ().close (); + } catch (IOException e) { + return -1; + } finally { + connected (false); + } + + return 0; + } + + /** + * Accessor for the port number of the server. + */ + public int port () + { + return port_; + } + + /** + * Accessor for the host name of the server. + */ + public String host () + { + return host_; + } + + /** + * Check to see if this handler is currently connected to a server. + */ + public synchronized boolean connected () + { + return connected_; + } + + /** + * Set the connected state. + * + *@param state true if connected, false if not + */ + protected synchronized void connected (boolean state) + { + connected_ = state; + } + + /** + * (Isn't used, just fulfills the interface. Returns -1 by + * default) + */ + public int handleTimeout (TimeValue tv, Object obj) + { + return -1; + } + + /** + * (Isn't used, just fulfills the interface.) + */ + public void run () + { + ACE.ERROR ("TSClerkHandler is not setup to run in its own thread"); + } + + /** + * Sends a request to the server and waits for a reply. This is called + * by TSClerkProcessor. + * + *@return -1 on failure, 0 on success + */ + public int sendRequest () + { + // Ask the clerk processor to connect this handler if it isn't + // already. Thus, it tries to reconnect if the server has gone + // down. + if (!connected ()) + parent_.connectHandler (this, host_, port_); + + TimeRequest request = new TimeRequest (); + + long start, stop; + try { + + start = System.currentTimeMillis (); + request.streamOutTo (peer().outputStream ()); + + request.streamInFrom (peer().inputStream ()); + stop = System.currentTimeMillis (); + + } catch (NullPointerException e) { + close (); + return -1; + } catch (IOException e) { + close (); + return -1; + } + + // Compute the difference in the local time and the server time + // (in seconds) + long difference = request.time () - (stop / 1000); + + // Calculate the transmission time (in seconds) + long oneWayTime = (stop - start) / 2000; + + difference += oneWayTime; + + /* + ACE.DEBUG (host() + " reports:"); + ACE.DEBUG (" time difference: " + difference); + ACE.DEBUG (" trans. delay: " + oneWayTime); + */ + + // Set the time difference for this handler + delta (difference); + + return 0; + } + + /** + * Returns the current time difference between local time and + * the server (in seconds). + */ + public synchronized long delta () + { + return delta_; + } + + /** + * Sets the current time difference between local time and the + * server (in seconds). + */ + protected synchronized void delta (long delta) + { + delta_ = delta; + } + + private long delta_; + private TSClerkProcessor parent_; + private boolean connected_ = false; + private String host_; + private int port_; +} diff --git a/java/JACE/netsvcs/Time/TSClerkProcessor.java b/java/JACE/netsvcs/Time/TSClerkProcessor.java new file mode 100644 index 00000000000..bec3bd417df --- /dev/null +++ b/java/JACE/netsvcs/Time/TSClerkProcessor.java @@ -0,0 +1,307 @@ +package JACE.netsvcs.Time; + +import java.net.*; +import java.io.*; +import java.util.*; + +import JACE.ASX.TimeValue; +import JACE.Connection.*; +import JACE.OS.*; +import JACE.Reactor.*; +import JACE.Misc.*; + +/** + * Clerk used to query a number of time servers, compute the average + * of the time differences, and report it with a sequence number. This + * can be used to adjust the current local time accordingly. + * <P> + * <B>Valid command line arguments:</B> + * <PRE> + * -h (host name:port) Specify a time server to contact + * -t (time in seconds) Specify how often to query the servers + * (Defaults to five minutes) + * -d Enable debugging messages + * </PRE> + */ +public class TSClerkProcessor implements EventHandler, Runnable +{ + /** + * Prints out the valid command line arguments. See the class + * description for more information. + */ + public void printUsage () + { + ACE.ERROR ("Valid options:"); + ACE.ERROR ("-h <host name>:<port> Specify a time server to contact"); + ACE.ERROR ("-t <time in seconds> How often to query the servers"); + ACE.ERROR ("-d Enable debugging messages"); + } + + /** + * Parses the command line arguments. See the class description + * for more information. + */ + protected int parseArgs (String args[]) + { + GetOpt opt = new GetOpt (args, "h:t:d", true); + for (int c; (c = opt.next ()) != -1; ) + { + switch (c) + { + // Specify a hostname:port pair to query + case 'h': + if (newHandler (opt.optarg ()) == -1) { + printUsage (); + return -1; + } + break; + // Specify time interval to query servers + case 't': + int sec = Integer.parseInt (opt.optarg ()); + updateInterval_ = new TimeValue (sec); + break; + case 'd': + ACE.enableDebugging (); + ACE.DEBUG ("Debugging is enabled"); + break; + default: + ACE.ERROR ("Unknown argument: " + (char)c); + printUsage (); + return -1; + } + } + return 0; + } + + /** + * Safely shut down the clerk and all its handlers. + */ + public synchronized void close () + { + if (!done_) { + done_ = true; + tq_.cancelTimer (this); + + for (int i = 0; i < handlerSet_.size (); i++) { + TSClerkHandler h = (TSClerkHandler)handlerSet_.elementAt (i); + + h.close (); + } + } + } + + /** + * Called by the JVM when the clerk is run in its own thread. If the + * TimerQueue provided to (or created by) this TSClerkProcessor isn't + * running its event loop, it will be run in this thread (by calling + * handleEvents ()). + * + *@see JACE.Reactor.TimerQueue + */ + public void run () + { + if (handlerSet_.size () == 0) { + ACE.DEBUG ("No servers are registered. Call init first."); + return; + } + + if (!tq_.eventLoopRunning ()) + tq_.handleEvents (); + } + + /** + * Initialize this TSClerkProcessor with command line arguments. See + * the class description for more information. This also schedules + * a timeout with the timer queue for when to query the servers. + * + *@return -1 on failure, 0 on success + */ + public int init (String args[]) + { + if (args.length < 2) { + printUsage (); + return -1; + } + + if (parseArgs (args) == -1) + return -1; + + if (handlerSet_.size () == 0) { + ACE.ERROR ("No servers are registered."); + done_ = true; + return -1; + } + + if (tq_ == null) + tq_ = new TimerQueue (true); + + tq_.scheduleTimer (this, + "Time Service Processor", + TimeValue.zero, + updateInterval_); + + return 0; + } + + /** + * Called by TSClerkHandler instances when they need to connect + * (or reconnect) to a server. This uses Connector to make the + * connection. + * + *@param handler TSClerkHandler to connect to the server + *@param host name of the service + *@param port port to connect to on the server + */ + void connectHandler (TSClerkHandler handler, + String host, + int port) + { + // Don't let handlers reconnect if we are in the process of closing + if (done_) + return; + + ACE.DEBUG ("Connecting handler to " + host + " on port " + port); + try { + + Connector c = new Connector (); + c.open (host, port); + c.connect (handler); + + } catch (UnknownHostException e) { + synchronized (this) { + handlerSet_.removeElement (handler); + } + ACE.ERROR (e); + } catch (SocketException e) { + ACE.ERROR (e); + } catch (InstantiationException e) { + ACE.ERROR (e); + } catch (IllegalAccessException e) { + ACE.ERROR (e); + } catch (IOException e) { + ACE.ERROR (e); + } + } + + /** + * Create a new TSClerkHandler for the given (host name):(port) + * combination. See the class description for more information about + * providing a host names and ports on the command line. + * + *@param hostAndPort String with the host name and port separated by + * a colon. + *@return -1 on failure, 0 on success + */ + protected int newHandler (String hostAndPort) + { + int colon = hostAndPort.lastIndexOf (':'); + + if (colon < 1) { + ACE.ERROR ("Invalid -h <host>:<port> parameter: " + hostAndPort); + return -1; + } + + int port = Integer.parseInt (hostAndPort.substring (colon + 1)); + String host = hostAndPort.substring (0, colon); + + ACE.DEBUG ("New handler for server " + host + " on port " + port); + + TSClerkHandler handler = new TSClerkHandler (this, host, port); + handlerSet_.addElement (handler); + + return 0; + } + + /** + * Have each TSClerkHandler query its time server, average the results, + * and set the timeStatus accordingly. This is called by the + * TimerQueue when appropriate. The interval can be specified on the + * command line. + */ + public synchronized int handleTimeout (TimeValue tv, Object obj) + { + if (done_) + return -1; + + // Increment the sequence number + int sequenceNumber = status_.sequenceNumber () + 1; + Enumeration handlers = handlerSet_.elements (); + + long total = 0; + int count = 0; + + // Use each handler to query its server, collecting the time + // difference information. + while (handlers.hasMoreElements ()) { + TSClerkHandler h = (TSClerkHandler)handlers.nextElement (); + + if (h.sendRequest () < 0) + continue; + + total += h.delta (); + count++; + } + + if (count == 0) { + ACE.ERROR ("Could not reach any time servers, will keep trying."); + return 0; + } + + timeStatus (new TimeInfo (sequenceNumber, total / count)); + + ACE.DEBUG ("Status: " + timeStatus ()); + + return 0; + } + + /** + * Return the current sequence number and time difference pair. + */ + public synchronized TimeInfo timeStatus () + { + return status_; + } + + /** + * Set the current sequence number and time difference pair. + */ + protected synchronized void timeStatus (TimeInfo status) + { + status_ = status; + } + + /** + * Default constructor. Results in this TSClerkProcessor creating + * a new timer queue which runs in its own thread. Thus, this + * TSClerkProcessor runs in its own thread. + */ + public TSClerkProcessor () + { + // Effectively runs in its own thread because of the timer queue + } + + /** + * Constructor allowing the timer queue to be specified. If the timer + * queue isn't already running, the caller is responsible for calling + * handleEvents to start the clerk. Be careful since the querying + * process for the servers may take a while. + * + *@param queue TimerQueue to register with + */ + public TSClerkProcessor (TimerQueue queue) + { + tq_ = queue; + } + + private boolean done_ = false; + + // List of the TSClerkHandlers this uses to maintain its + // server connections. + private Vector handlerSet_ = new Vector (); + private TimerQueue tq_ = null; + + // Default is every five minutes + private TimeValue updateInterval_ = new TimeValue (300, 0); + + TimeInfo status_ = new TimeInfo (); +} diff --git a/java/JACE/netsvcs/Time/TSServerAcceptor.java b/java/JACE/netsvcs/Time/TSServerAcceptor.java new file mode 100644 index 00000000000..7e8b9476c19 --- /dev/null +++ b/java/JACE/netsvcs/Time/TSServerAcceptor.java @@ -0,0 +1,116 @@ +package JACE.netsvcs.Time; + +import java.io.*; +import java.net.*; +import java.util.*; +import JACE.OS.*; +import JACE.Misc.*; +import JACE.Connection.*; +import JACE.Reactor.*; +import JACE.ASX.TimeValue; +import JACE.Concurrency.ThreadManager; +import JACE.netsvcs.Server; + +/** + * Server for the time service. Creates TSServerHandlers as necessary + * to handle the requests. + * <P> + * <B>Valid command line arguments:</B> + * <PRE> + * -p (port) Port to listen on for clients"); + * -d Enable debugging messages"); + * -a (class name) Specify ActivateStrategy"); + * (Default is multi-threaded"); + * </PRE> + * + */ +public class TSServerAcceptor extends Server +{ + public TSServerAcceptor () + { + // Set the name in case we're not using the service configurator + name ("Time Service"); + } + + /** + * Simple main program for running the logging service without the + * service configurator. + * + *@param args command line arguments + */ + public static void main (String [] args) + { + // Simple main program to get things rolling + TSServerAcceptor ta = new TSServerAcceptor(); + + ta.init (args); + } + + /** + * Creates a new TSServerHandler instance. + */ + protected SvcHandler makeSvcHandler () + { + return new TSServerHandler (); + } + + /** + * Prints out the valid command line arguments. See the class + * description for more information. Called by Server.init when + * parseArgs returns -1. + */ + protected void printUsage () + { + ACE.ERROR ("Valid options:\n"); + ACE.ERROR ("-p <port> Port to listen on for clients"); + ACE.ERROR ("-d Enable debugging messages"); + ACE.ERROR ("-a <class name> Specify ActivateStrategy"); + ACE.ERROR (" (Default is multi-threaded"); + } + + /** + * Parses the command line arguments. See the class description + * for more information. + * + *@param args command line arguments + *@return -1 on failure, 0 on success + */ + protected int parseArgs (String [] args) + { + int c = 0; + GetOpt opt = new GetOpt(args, "p:da:", true); + + try { + + while ((c = opt.next ()) != -1) { + switch (c) + { + case 'd': + ACE.enableDebugging (); + ACE.DEBUG ("Debugging is enabled"); + break; + case 'p': + if (!port (opt.optarg ())) + return -1; + break; + case 'a': + Object strategy = newStrategyInstance (opt.optarg (), + "ActivateStrategy"); + if (strategy == null) + return -1; + + activateStrategy ((ActivateStrategy) strategy); + break; + default: + ACE.ERROR("Unknown argument: " + (char)c); + return -1; + } + } + } catch (ArrayIndexOutOfBoundsException e) { + ACE.ERROR ("Option -" + (char)c + " requires an argument"); + return -1; + } + + return 0; + } +} diff --git a/java/JACE/netsvcs/Time/TSServerHandler.java b/java/JACE/netsvcs/Time/TSServerHandler.java new file mode 100644 index 00000000000..69bf4239280 --- /dev/null +++ b/java/JACE/netsvcs/Time/TSServerHandler.java @@ -0,0 +1,53 @@ +package JACE.netsvcs.Time; + +import java.io.*; +import java.util.*; +import java.net.*; +import JACE.OS.*; +import JACE.Connection.*; +import JACE.Reactor.*; +import JACE.SOCK_SAP.*; +import JACE.netsvcs.Handler; + +/** + * Created by TSServerAcceptor to handle time update requests. Currently, + * this simply sends back the current time (in seconds). + * + * @see JACE.netsvcs.Logger.ServerLoggingAcceptor + */ +public class TSServerHandler extends Handler +{ + /** + * Reads in the given TimeRequest request and calls dispatch. + * + *@param request TimeRequest instance to use + */ + public void processRequest (Object requestObject) + throws SocketException, EOFException, IOException + { + TimeRequest request = (TimeRequest)requestObject; + + request.streamInFrom (peer ().dataInputStream ()); + + this.dispatch (request); + } + + /** + * Sets the time value of the request to be the local time (in sec) + * and sends it back to the client. + */ + void dispatch(TimeRequest request) throws IOException + { + request.time ((int)(System.currentTimeMillis () / 1000)); + + request.streamOutTo (peer().outputStream ()); + } + + /** + * Creates a new instance of TimeRequest. + */ + public Object newRequest () + { + return new TimeRequest (); + } +} diff --git a/java/JACE/netsvcs/Time/TimeInfo.java b/java/JACE/netsvcs/Time/TimeInfo.java new file mode 100644 index 00000000000..4ebfc793adb --- /dev/null +++ b/java/JACE/netsvcs/Time/TimeInfo.java @@ -0,0 +1,90 @@ +package JACE.netsvcs.Time; + +/** + * Wrapper for use with the clerk, containing a sequence number and + * time offset pair. + */ +public class TimeInfo +{ + /** + * Default constructor. + */ + public TimeInfo () + { + this (0, 0); + } + + /** + * Constructor. + * + *@param seqNum sequence number + *@param delta time offset in seconds + */ + public TimeInfo (int seqNum, long delta) + { + sequenceNumber_ = seqNum; + delta_ = delta; + } + + /** + * Returns this TimeInfo's sequence number. + */ + public int sequenceNumber () + { + return sequenceNumber_; + } + + /** + * Sets this TimeInfo's sequence number. + */ + public void sequenceNumber (int num) + { + sequenceNumber_ = num; + } + + /** + * Returns the time offset represented by this TimeInfo instance. + * (in sec) + */ + public long delta () + { + return delta_; + } + + /** + * Sets the time offset (in sec). + */ + public void delta (long num) + { + delta_ = num; + } + + /** + * Returns an informative String about the time difference represented + * by this TimeInfo instance. The sequence number is included in + * brackets. + * <P> + * Example: + * <PRE> + * Local time is 3 sec slower [57] + * </PRE> + */ + public String toString () + { + String result = "Local time is "; + if (delta_ > 0) { + result += (delta_ + " sec slower"); + } else + if (delta_ < 0) { + result += (delta_ + " sec faster"); + } else + result += "the same as the average"; + + result += " [" + sequenceNumber_ + "]"; + + return result; + } + + private long delta_; + private int sequenceNumber_; +} diff --git a/java/JACE/netsvcs/Time/TimeRequest.java b/java/JACE/netsvcs/Time/TimeRequest.java new file mode 100644 index 00000000000..1b0e691398a --- /dev/null +++ b/java/JACE/netsvcs/Time/TimeRequest.java @@ -0,0 +1,121 @@ +package JACE.netsvcs.Time; + +import java.io.*; +import java.net.*; + +/** + * Request for a time update (and its reply). This is compatible with + * C++ ACE_Time_Request. Currently, the Java version always specifies to + * block forever for requests. + */ +public class TimeRequest +{ + /** + * Type for requesting updates. + */ + public static int TIME_UPDATE = 01; + + /** + * Default constructor, specifies block forever for an update. + */ + public TimeRequest () + { + messageType_ = TIME_UPDATE; + blockForever_ = 1; + } + + /** + * Constructor specifying the type of request, the current + * time, and to block forever. + */ + public TimeRequest (int messageType, + int timeSec) + { + time_ = timeSec; + messageType_ = messageType; + blockForever_ = 1; + } + + /** + * Dump all class information to a String. + */ + public String toString () + { + return "TimeRequest (" + messageType_ + + ", " + blockForever_ + ", " + secTimeout_ + ", " + + usecTimeout_ + ", " + time_ + ")"; + } + + /** + * Read the TimeRequest in from a given InputStream. + */ + public void streamInFrom (InputStream is) + throws IOException, EOFException + { + BufferedInputStream bis = new BufferedInputStream (is, 25); + DataInputStream dis = new DataInputStream (bis); + + streamInFrom (dis); + } + + /** + * Read the TimeRequest in from a given DataInputStream. + */ + public void streamInFrom (DataInputStream dis) + throws IOException, EOFException + { + messageType_ = dis.readInt (); + blockForever_ = dis.readInt (); + secTimeout_ = dis.readInt (); + usecTimeout_ = dis.readInt (); + time_ = dis.readInt (); + } + + /** + * Write this TimeRequest out to a given OutputStream. + */ + public void streamOutTo (OutputStream os) + throws IOException + { + BufferedOutputStream bos = new BufferedOutputStream (os, 25); + DataOutputStream dos = new DataOutputStream (bos); + + streamOutTo (dos); + } + + /** + * Write this TimeRequest out to a given DataOutputStream. + */ + public void streamOutTo (DataOutputStream dos) throws IOException + { + dos.writeInt (messageType_); + dos.writeInt (blockForever_); + dos.writeInt (secTimeout_); + dos.writeInt (usecTimeout_); + dos.writeInt (time_); + + dos.flush (); + } + + /** + * Return the time value in seconds. + */ + public int time () + { + return time_; + } + + /** + * Set the time value in seconds. + */ + public void time (int value) + { + time_ = value; + } + + private int messageType_; + private int blockForever_; + private int secTimeout_; + private int usecTimeout_; + private int time_; +} diff --git a/java/JACE/netsvcs/Time/c.bat b/java/JACE/netsvcs/Time/c.bat new file mode 100644 index 00000000000..5e9e99f5807 --- /dev/null +++ b/java/JACE/netsvcs/Time/c.bat @@ -0,0 +1 @@ +javac -d C:\Everett\JACE\classes *.java diff --git a/java/JACE/netsvcs/Time/package.html b/java/JACE/netsvcs/Time/package.html new file mode 100644 index 00000000000..96fff45b643 --- /dev/null +++ b/java/JACE/netsvcs/Time/package.html @@ -0,0 +1,10 @@ +<!-- $Id$ --> +<HTML> +<BODY> +Time Service for synchronizing clocks of collaborating network computers. +<P> +A simple test client is available under the tests directory in netsvcs\Time. + +@see <a href="http://www.cs.wustl.edu/~schmidt/ACE-netsvcs.html">ACE Network Services</a> +</BODY> +</HTML> diff --git a/java/JACE/netsvcs/Time/r.bat b/java/JACE/netsvcs/Time/r.bat new file mode 100644 index 00000000000..7c89fbddd77 --- /dev/null +++ b/java/JACE/netsvcs/Time/r.bat @@ -0,0 +1 @@ +java JACE.netsvcs.Time.%1 %2 %3 %4 %5 %6 %7 %8 %9 |