// This software is released into the Public Domain. See copying.txt for details. package org.openstreetmap.osmosis.replicationhttp.v0_6; import java.io.File; import java.net.InetSocketAddress; import java.net.MalformedURLException; import org.openstreetmap.osmosis.core.OsmosisRuntimeException; import org.openstreetmap.osmosis.core.task.common.RunnableTask; import org.openstreetmap.osmosis.replication.common.ServerStateReader; import org.openstreetmap.osmosis.replicationhttp.v0_6.impl.ReplicationDataServerChannelPipelineFactory; import org.openstreetmap.osmosis.replicationhttp.v0_6.impl.SequenceClient; import org.openstreetmap.osmosis.replicationhttp.v0_6.impl.SequenceClientRestartManager; import org.openstreetmap.osmosis.replicationhttp.v0_6.impl.SequenceNumberClientChannelPipelineFactory; import org.openstreetmap.osmosis.replicationhttp.v0_6.impl.SequenceNumberClientListener; import org.openstreetmap.osmosis.replicationhttp.v0_6.impl.SequenceServer; /** * This task creates a HTTP server that sends updated replication data to * clients. It is notified of updated sequence numbers as they occur by * connecting to a replication sequence server. * * @author Brett Henderson */ public class ReplicationDataServer implements RunnableTask { private int notificationPort; private File dataDirectory; private int port; /** * Creates a new instance. * * @param notificationPort * The port to connect to for notification updates. * @param dataDirectory * The location of the replication data and state files. * @param port * The port to listen on. */ public ReplicationDataServer(int notificationPort, File dataDirectory, int port) { this.notificationPort = notificationPort; this.dataDirectory = dataDirectory; this.port = port; } /** * Returns the port that is being used to listen for new connections. * * @return The port number. */ public int getPort() { return port; } private long getCurrentSequenceNumber() { try { return new ServerStateReader().getServerState(dataDirectory.toURI().toURL()).getSequenceNumber(); } catch (MalformedURLException e) { throw new OsmosisRuntimeException("Unable to get the current sequence number", e); } } @Override public void run() { // Instantiate the replication data server. final SequenceServer server = new SequenceServer(port, new ReplicationDataServerChannelPipelineFactory( dataDirectory)); // Configure a listener to send sequence number events from the // client to the server. SequenceNumberClientListener numberListener = new SequenceNumberClientListener() { @Override public void notifySequenceNumber(long sequenceNumber) { server.update(sequenceNumber); } }; // Create a sequence client restart manager so that our sequence // client continues processing in the face of temporary connectivity // issues. SequenceClientRestartManager clientRestartManager = new SequenceClientRestartManager(); // Create the client for receiving updated sequence numbers.. SequenceNumberClientChannelPipelineFactory channelPipelineFactory = new SequenceNumberClientChannelPipelineFactory( clientRestartManager.getControl(), numberListener, "localhost"); SequenceClient client = new SequenceClient(new InetSocketAddress(notificationPort), channelPipelineFactory); try { // Start the server with the current replication number. server.start(getCurrentSequenceNumber()); // Update the port. It may have been allocated dynamically if the // port was specified as 0. port = server.getPort(); // Run the client and perform restarts if it fails. This call will // block. clientRestartManager.manageClient(client); } finally { server.stop(); } } }