package org.zbus.client.broker;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.zbus.common.json.JSON;
import org.zbus.common.logging.Logger;
import org.zbus.common.logging.LoggerFactory;
import org.zbus.common.protocol.Proto;
import org.zbus.common.protocol.TrackTable;
import org.zbus.common.remoting.ClientDispatcherManager;
import org.zbus.common.remoting.Message;
import org.zbus.common.remoting.RemotingClient;
import org.zbus.common.remoting.callback.ErrorCallback;
import org.zbus.common.remoting.callback.MessageCallback;
import org.zbus.common.remoting.nio.Session;
import org.zbus.common.remoting.ticket.ResultCallback;
interface TrackListener{
void onTrackTableUpdated(TrackTable trackTable);
}
public class TrackAgent {
private static final Logger log = LoggerFactory.getLogger(TrackAgent.class);
private String trackServerList="127.0.0.1:16666";
private final List<RemotingClient> clients = new ArrayList<RemotingClient>();
private ClientDispatcherManager clientMgr;
private CountDownLatch tableReady = new CountDownLatch(1);
private ExecutorService executor = new ThreadPoolExecutor(4, 16, 120, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
private List<TrackListener> trackListeners = new ArrayList<TrackListener>();
public TrackAgent(String trackServerList) throws IOException{
this(trackServerList, null);
}
public TrackAgent(String trackServerList, ClientDispatcherManager clientMgr) throws IOException {
this.clientMgr = clientMgr;
this.connectToTrackServers();
}
public void waitForReady(long timeout){
try {
this.tableReady.await(timeout, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
}
}
public void addTrackListener(TrackListener listener){
this.trackListeners.add(listener);
}
public void removeTrackListener(TrackListener listener){
this.trackListeners.remove(listener);
}
public void printSessions(){
for(RemotingClient client : this.clients){
log.info("client session: "+client.getSession());
}
}
private void connectToTrackServers(){
String[] serverAddrs = this.trackServerList.split("[;]");
for(String addr : serverAddrs){
addr = addr.trim();
if( addr.isEmpty() ) continue;
final RemotingClient client = new RemotingClient(addr, this.clientMgr);
clients.add(client);
executor.submit(new Runnable() {
@Override
public void run() {
try {
initTrackClient(client);
} catch (IOException e) {
//log.error(e.getMessage(), e);
}
}
});
}
}
private void initTrackClient(final RemotingClient client) throws IOException{
client.onMessage(new MessageCallback() {
@Override
public void onMessage(Message msg, Session sess) throws IOException {
final TrackTable trackTable = JSON.parseObject(msg.getBody(), TrackTable.class);
for(TrackListener listener : trackListeners){
listener.onTrackTableUpdated(trackTable);
}
tableReady.countDown();
}
});
client.onError(new ErrorCallback() {
@Override
public void onError(IOException e, Session sess) throws IOException {
executor.submit(new Runnable() {
@Override
public void run() {
doTrackSub(client);
}
});
}
});
doTrackSub(client);
}
private void doTrackSub(final RemotingClient client){
try {
Message msg = new Message();
msg.setCommand(Proto.TrackSub);
client.invokeAsync(msg, new ResultCallback() {
@Override
public void onCompleted(Message result) {
final TrackTable trackTable = JSON.parseObject(result.getBody(), TrackTable.class);
for(TrackListener listener : trackListeners){
listener.onTrackTableUpdated(trackTable);
}
tableReady.countDown();
}
});
} catch (IOException e) {
log.debug(e.getMessage(), e);;
}
}
}