// This software is released into the Public Domain. See copying.txt for details.
package org.openstreetmap.osmosis.replicationhttp.v0_6.impl;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.openstreetmap.osmosis.core.OsmosisRuntimeException;
/**
* This class creates a HTTP client that connects to a sequence server, listens
* for updated sequences as they are received, and notifies any configured
* listeners.
*
* @author Brett Henderson
*/
public class SequenceClient {
private InetSocketAddress serverAddress;
private SequenceClientChannelPipelineFactory channelPipelineFactory;
/**
* A flag used only by the external control thread to remember if the server
* has been started or not.
*/
private boolean masterRunning;
/**
* The factory for all processing threads.
*/
private ChannelFactory factory;
/**
* The channel used to receive sequence updates from the server.
*/
private Channel channel;
/**
* Creates a new instance.
*
* @param serverAddress
* The address of the sequence server providing notification of
* updated sequence numbers.
* @param channelPipelineFactory
* The factory for creating channel pipelines for new client
* connections.
*/
public SequenceClient(InetSocketAddress serverAddress,
SequenceClientChannelPipelineFactory channelPipelineFactory) {
this.serverAddress = serverAddress;
this.channelPipelineFactory = channelPipelineFactory;
}
/**
* Starts the client.
*/
public void start() {
if (masterRunning) {
throw new OsmosisRuntimeException("The server has already been started");
}
// Mark the client as running.
masterRunning = true;
// Create the processing thread pools.
factory = new NioClientSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool());
ClientBootstrap bootstrap = new ClientBootstrap(factory);
bootstrap.setPipelineFactory(channelPipelineFactory);
bootstrap.setOption("tcpNoDelay", true);
bootstrap.setOption("keepAlive", true);
ChannelFuture future = bootstrap.connect(serverAddress);
// Get a reference to the channel.
channel = future.getChannel();
// Wait for the connection attempt to complete.
future.awaitUninterruptibly();
// Abort if the startup failed.
if (!future.isSuccess()) {
throw new OsmosisRuntimeException("Unable to launch sequence client.");
}
}
/**
* Stops the client. This must be called in all cases even if start failed.
*/
public void stop() {
if (masterRunning) {
channel.close().awaitUninterruptibly();
factory.releaseExternalResources();
masterRunning = false;
}
}
}