/* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.test.framework.clocksynch; import org.apache.qpid.junit.extensions.ShutdownHookable; import java.io.IOException; import java.net.*; import java.nio.ByteBuffer; /** * UDPClockReference supplies a refernce clock signal (generated from System.nanoTime()). * *

*
CRC Card
Responsibilities Collaborations *
Supply a reference clock signal. *
* * @todo Port hard coded. Make configurable. * * @todo Errors rethrown as runtimes, or silently terminate the service. Could add better error handling if needed. */ public class UDPClockReference implements Runnable, ShutdownHookable { /** Used for debugging. */ // private static final Logger log = Logger.getLogger(UDPClockReference.class); /** Defines the timeout to use when polling the socket for time requests. */ private static final int TIMEOUT = 200; /** Defines the port to run the clock reference on. */ public static final int REFERENCE_PORT = 4444; /** Holds the socket to receive clock reference requests on. */ protected DatagramSocket socket = null; /** Flag used to indicate that the time server should keep running. Set to false to terminate. */ protected boolean publish = true; /** * Creates a clock reference service on the standard port. */ public UDPClockReference() { try { socket = new DatagramSocket(REFERENCE_PORT); socket.setSoTimeout(TIMEOUT); } catch (SocketException e) { throw new RuntimeException(e); } } /** * Implements the run loop for this reference time server. This waits for incoming time requests, and replies to * any, with a message with the local time stamp in it. Periodically (controlled by {@link #TIMEOUT}), the run * loop will check if the {@link #publish} flag has been cleared, and terminate the reference time service if so. */ public void run() { byte[] buf = new byte[256]; ByteBuffer bbuf = ByteBuffer.wrap(buf); while (publish) { try { // Wait for a reference time request. DatagramPacket packet = new DatagramPacket(buf, buf.length); boolean timedOut = false; try { socket.receive(packet); } catch (SocketTimeoutException e) { timedOut = true; } if (!timedOut) { // Work out from the received packet, where to reply to. InetAddress address = packet.getAddress(); int port = packet.getPort(); // Respond to the time request by sending back the local clock as the reference time. bbuf.putLong(System.nanoTime()); bbuf.flip(); packet = new DatagramPacket(bbuf.array(), bbuf.capacity(), address, port); socket.send(packet); } } catch (IOException e) { publish = false; } } socket.close(); } /** * Supplies a shutdown hook. * * @return The shut down hook. */ public Thread getShutdownHook() { return new Thread(new Runnable() { public void run() { publish = false; } }); } /** * For testing purposes. Runs a reference clock on the default port. * * @param args None. */ public static void main(String[] args) { try { // Create the clock reference service. UDPClockReference clock = new UDPClockReference(); // Set up a shutdown hook for it. Runtime.getRuntime().addShutdownHook(clock.getShutdownHook()); // Start the service. clock.run(); } catch (Exception e) { e.printStackTrace(); System.exit(1); } } }