/* Copyright (c) 2011 Danish Maritime Authority.
*
* Licensed 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 dk.dma.ais.bus.consumer;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import net.jcip.annotations.ThreadSafe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import dk.dma.ais.bus.AisBusConsumer;
import dk.dma.ais.bus.AisBusElement;
import dk.dma.ais.bus.OverflowLogger;
import dk.dma.ais.bus.tcp.IClientStoppedListener;
import dk.dma.ais.bus.tcp.TcpClient;
import dk.dma.ais.bus.tcp.TcpClientConf;
import dk.dma.ais.bus.tcp.TcpWriteClient;
/**
* TCP client that connects to host/port and sends data. Will reconnect on connection error.
*/
@ThreadSafe
public class TcpWriterConsumer extends AisBusConsumer implements Runnable, IClientStoppedListener {
private static final Logger LOG = LoggerFactory.getLogger(TcpWriterConsumer.class);
private final OverflowLogger overflowLogger = new OverflowLogger(LOG);
private TcpWriteClient writeClient;
private TcpClientConf clientConf = new TcpClientConf();
private int reconnectInterval = 10;
private String host;
private int port;
public TcpWriterConsumer() {
}
@Override
public void receiveFiltered(AisBusElement queueElement) {
if (status.isConnected()) {
if (!writeClient.send(queueElement.getPacket().getStringMessage())) {
status.overflow();
overflowLogger.log("Overflow writing to client");
}
}
}
/**
* Connect and reconnect
*/
@Override
public void run() {
setNotConnected();
while (true) {
try(Socket socket = new Socket()) {
// Connect
InetSocketAddress address = new InetSocketAddress(host, port);
LOG.info("Connecting to " + host + ":" + port + " ...");
socket.connect(address);
socket.setKeepAlive(true);
// Start client
writeClient = new TcpWriteClient(this, socket, clientConf);
setConnected();
writeClient.start();
// Wait for client to loose connection
writeClient.join();
} catch (IOException e) {
LOG.info(getName() + ": connection error: " + e.getMessage());
} catch (InterruptedException e) {
break;
}
setNotConnected();
try {
LOG.info("Waiting to reconnect");
Thread.sleep(reconnectInterval * 1000);
} catch (InterruptedException e) {
break;
}
}
if (writeClient != null) {
writeClient.cancel();
}
setStopped();
LOG.info("Stopped");
}
@Override
public void start() {
Thread t = new Thread(this);
setThread(t);
t.start();
super.start();
}
@Override
public void cancel() {
getThread().interrupt();
try {
getThread().join(THREAD_STOP_WAIT_MAX);
} catch (InterruptedException e) {
e.printStackTrace();
}
super.cancel();
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getReconnectInterval() {
return reconnectInterval;
}
public void setReconnectInterval(int reconnectInterval) {
this.reconnectInterval = reconnectInterval;
}
public TcpClientConf getClientConf() {
return clientConf;
}
public void setClientConf(TcpClientConf clientConf) {
this.clientConf = clientConf;
}
@Override
public void clientStopped(TcpClient client) {
setNotConnected();
}
}