package org.bigbluebutton.red5.monitoring;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.bigbluebutton.common.messages.MessageHeader;
import org.bigbluebutton.common.messages.MessagingConstants;
import org.bigbluebutton.common.messages.PubSubPingMessage;
import org.bigbluebutton.common.messages.payload.PubSubPingMessagePayload;
import org.bigbluebutton.red5.client.messaging.ConnectionInvokerService;
import org.bigbluebutton.red5.client.messaging.DisconnectAllMessage;
import org.bigbluebutton.red5.pubsub.redis.MessageSender;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
public class BbbAppsIsAliveMonitorService {
private static Logger log = LoggerFactory.getLogger(BbbAppsIsAliveMonitorService.class);
private static final Executor msgSenderExec = Executors.newFixedThreadPool(1);
private static final Executor runExec = Executors.newFixedThreadPool(1);
private ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(1);
private BlockingQueue<IKeepAliveMessage> messages = new LinkedBlockingQueue<IKeepAliveMessage>();
private volatile boolean processMessages = false;
private KeepAliveTask task = new KeepAliveTask();
private ConnectionInvokerService service;
private Long lastKeepAliveMessage = 0L;
private MessageSender sender;
private final String SYSTEM_NAME = "BbbAppsRed5";
public void setMessageSender(MessageSender sender) {
this.sender = sender;
}
public void setConnectionInvokerService(ConnectionInvokerService s) {
this.service = s;
}
public void start() {
scheduledThreadPool.scheduleWithFixedDelay(task, 5000, 10000, TimeUnit.MILLISECONDS);
processKeepAliveMessage();
}
public void stop() {
processMessages = false;
scheduledThreadPool.shutdownNow();
}
public void handleKeepAliveMessage(String system, Long timestamp) {
if (system.equals(SYSTEM_NAME)) {
queueMessage(new KeepAliveMessage(system, timestamp));
}
}
private void queueMessage(IKeepAliveMessage msg) {
messages.add(msg);
}
private void processKeepAliveMessage() {
processMessages = true;
Runnable sender = new Runnable() {
public void run() {
while (processMessages) {
IKeepAliveMessage message;
try {
message = messages.take();
processMessage(message);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
//log.error("Catching exception [{}]", e.toString());
}
}
}
};
msgSenderExec.execute(sender);
}
private void processMessage(final IKeepAliveMessage msg) {
Runnable task = new Runnable() {
public void run() {
if (msg instanceof KeepAliveMessage) {
processKeepAliveMessage((KeepAliveMessage) msg);
} else if (msg instanceof CheckIsAliveTimer) {
processCheckIsAliveTimer((CheckIsAliveTimer) msg);
}
}
};
runExec.execute(task);
}
private void processKeepAliveMessage(KeepAliveMessage msg) {
//log.info("BBB Apps Red5 pubsub pong!" + msg.system);
lastKeepAliveMessage = System.currentTimeMillis();
}
private void processCheckIsAliveTimer(CheckIsAliveTimer msg) {
Long now = System.currentTimeMillis();
if (lastKeepAliveMessage != 0 && (now - lastKeepAliveMessage > 30000)) {
log.error("BBB Apps Red5 pubsub error!");
service.sendMessage(new DisconnectAllMessage());
}
}
class KeepAliveTask implements Runnable {
public void run() {
CheckIsAliveTimer ping = new CheckIsAliveTimer();
queueMessage(ping);
PubSubPingMessage msg = new PubSubPingMessage();
MessageHeader header = new MessageHeader();
header.name = PubSubPingMessage.PUBSUB_PING;
header.timestamp = System.nanoTime();
header.replyTo = "BbbRed5";
header.version = "0.0.1";
PubSubPingMessagePayload payload = new PubSubPingMessagePayload();
payload.system = SYSTEM_NAME;
payload.timestamp = System.currentTimeMillis();
msg.header = header;
msg.payload = payload;
Gson gson = new Gson();
sender.send(MessagingConstants.TO_SYSTEM_CHANNEL, gson.toJson(msg));
}
}
}