package cgl.iotcloud.transport.kestrel; import org.apache.thrift.TException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; import java.util.concurrent.BlockingQueue; public class KestrelProducer { private Logger LOG = LoggerFactory.getLogger(KestrelProducer.class); private BlockingQueue outQueue; private KestrelThriftClient client; private int expirationTime = 30000; private boolean run = true; private KestrelDestination destination; private long blackListTime = 30000; private long sleepTime = 0; public KestrelProducer(KestrelDestination destination, BlockingQueue outQueue) { this.destination = destination; this.outQueue = outQueue; } public void setExpirationTime(int expirationTime) { this.expirationTime = expirationTime; } public void open() { Thread t = new Thread(new Worker()); t.start(); } public void close() { run = false; } private KestrelThriftClient getValidClient() throws TException { if (client == null) { client = new KestrelThriftClient(destination.getHost(), destination.getPort()); } return client; } private void closeClient() { if (client != null) { client.close(); } } public void setBlackListTime(long blackListTime) { this.blackListTime = blackListTime; } private class Worker implements Runnable { @Override public void run() { int errorCount = 0; while (run) { try { if (System.currentTimeMillis() > sleepTime) { try { getValidClient(); } catch (TException e) { closeClient(); sleepTime = System.currentTimeMillis() + blackListTime; continue; } try { List<ByteBuffer> messages = new ArrayList<ByteBuffer>(); // get the number of items in the outQUeue int size = outQueue.size(); if (size > 0) { for (int i = 0; i < size; i++) { Object input = outQueue.take(); if (input instanceof byte []) { ByteBuffer byteBuffer = ByteBuffer.wrap((byte[]) input); messages.add(byteBuffer); } else { throw new RuntimeException("Expepected byte array after conversion"); } } } else { Object input = outQueue.take(); if (input instanceof byte []) { ByteBuffer byteBuffer = ByteBuffer.wrap((byte[]) input); messages.add(byteBuffer); } else { throw new RuntimeException("Expepected byte array after conversion"); } } if (messages.size() > 0) { try { client.put(destination.getQueue(), messages, expirationTime); } catch (TException e) { closeClient(); sleepTime = System.currentTimeMillis() + blackListTime; } } } catch (InterruptedException e) { LOG.error("Exception occurred in the worker listening for consumer changes", e); } } else { try { Thread.sleep(100); } catch (InterruptedException ignored) { } } } catch (Throwable t) { errorCount++; if (errorCount <= 3) { LOG.error("Error occurred " + errorCount + " times.. trying to continue the worker"); } else { LOG.error("Error occurred " + errorCount + " times.. terminating the worker"); run = false; } } } String message = "Unexpected notification type"; LOG.error(message); throw new RuntimeException(message); } } }