package com.intrbiz.bergamot.result; import java.util.LinkedList; import java.util.List; import java.util.UUID; import org.apache.log4j.Logger; import com.intrbiz.bergamot.model.ActiveCheck; import com.intrbiz.bergamot.model.Alert; import com.intrbiz.bergamot.model.Check; import com.intrbiz.bergamot.model.Group; import com.intrbiz.bergamot.model.Location; import com.intrbiz.bergamot.model.message.check.ExecuteCheck; import com.intrbiz.bergamot.model.message.notification.Notification; import com.intrbiz.bergamot.model.message.result.ResultMO; import com.intrbiz.bergamot.model.message.scheduler.RescheduleCheck; import com.intrbiz.bergamot.model.message.scheduler.SchedulerAction; import com.intrbiz.bergamot.model.message.update.AlertUpdate; import com.intrbiz.bergamot.model.message.update.CheckUpdate; import com.intrbiz.bergamot.model.message.update.GroupUpdate; import com.intrbiz.bergamot.model.message.update.LocationUpdate; import com.intrbiz.bergamot.model.message.update.Update; import com.intrbiz.bergamot.queue.NotificationQueue; import com.intrbiz.bergamot.queue.SchedulerQueue; import com.intrbiz.bergamot.queue.UpdateQueue; import com.intrbiz.bergamot.queue.WorkerQueue; import com.intrbiz.bergamot.queue.key.ActiveResultKey; import com.intrbiz.bergamot.queue.key.AdhocResultKey; import com.intrbiz.bergamot.queue.key.NotificationKey; import com.intrbiz.bergamot.queue.key.PassiveResultKey; import com.intrbiz.bergamot.queue.key.ResultKey; import com.intrbiz.bergamot.queue.key.SchedulerKey; import com.intrbiz.bergamot.queue.key.UpdateKey; import com.intrbiz.bergamot.queue.key.UpdateKey.UpdateType; import com.intrbiz.queue.Consumer; import com.intrbiz.queue.RoutedProducer; import com.intrbiz.queue.name.NullKey; public abstract class AbstractResultProcessor implements ResultProcessor { private Logger logger = Logger.getLogger(AbstractResultProcessor.class); private UUID instanceId = UUID.randomUUID(); private WorkerQueue workerQueue; private List<Consumer<ResultMO, ResultKey>> resultConsumers = new LinkedList<Consumer<ResultMO, ResultKey>>(); private List<Consumer<ResultMO, ResultKey>> fallbackConsumers = new LinkedList<Consumer<ResultMO, ResultKey>>(); private List<Consumer<ExecuteCheck, NullKey>> deadConsumers = new LinkedList<Consumer<ExecuteCheck, NullKey>>(); private List<Consumer<ExecuteCheck, NullKey>> deadAgentConsumers = new LinkedList<Consumer<ExecuteCheck, NullKey>>(); private SchedulerQueue schedulerQueue; private RoutedProducer<SchedulerAction, SchedulerKey> schedulerActionProducer; private NotificationQueue notificationsQueue; private RoutedProducer<Notification, NotificationKey> notificationsProducer; private UpdateQueue updateQueue; private RoutedProducer<Update, UpdateKey> updateProducer; private RoutedProducer<ResultMO, AdhocResultKey> adhocProducer; private int threads = Runtime.getRuntime().availableProcessors(); public AbstractResultProcessor() { super(); } @Override public int getThreads() { return threads; } @Override public void setThreads(int threads) { this.threads = threads; } @Override public void ownPool(UUID site, int pool) { /* * Own a pool by adding bindings to our queue */ for (Consumer<ResultMO, ResultKey> consumer : this.resultConsumers) { consumer.addBinding(new ActiveResultKey(site, pool)); consumer.addBinding(new PassiveResultKey(site)); // Note: we only need to update the queue once, so break break; } } @Override public void disownPool(UUID site, int pool) { /* * Disown a pool by removing bindings from our queue */ for (Consumer<ResultMO, ResultKey> consumer : this.resultConsumers) { consumer.removeBinding(new ActiveResultKey(site, pool)); consumer.removeBinding(new PassiveResultKey(site)); // Note: we only need to update the queue once, so break break; } } @Override public void start() { // setup the consumer logger.info("Creating result consumer"); this.workerQueue = WorkerQueue.open(); // create the consumers for (int i = 0; i < this.getThreads(); i++) { // consume results, currently for all sites this.resultConsumers.add(this.workerQueue.consumeResults((h, r) -> { if (logger.isTraceEnabled()) logger.trace("Processing pooled/site result: " + r); processExecuted(r); }, this.instanceId.toString())); // consume results, currently for all sites this.fallbackConsumers.add(this.workerQueue.consumeFallbackResults((h, r) -> { if (logger.isDebugEnabled()) logger.debug("Processing fallback result: " + r); processExecuted(r); })); // consume dead checks, currently for all sites this.deadConsumers.add(this.workerQueue.consumeDeadChecks((h, e) -> { processDead(e); })); // consume dead agent checks, currently for all sites this.deadAgentConsumers.add(this.workerQueue.consumeDeadAgentChecks((h, e) -> { processDeadAgent(e); })); } // scheduler queue this.schedulerQueue = SchedulerQueue.open(); this.schedulerActionProducer = this.schedulerQueue.publishSchedulerActions(); // notifications queue this.notificationsQueue = NotificationQueue.open(); this.notificationsProducer = this.notificationsQueue.publishNotifications(); // updates this.updateQueue = UpdateQueue.open(); this.updateProducer = this.updateQueue.publishUpdates(); // adhoc this.adhocProducer = this.workerQueue.publishAdhocResults(); } protected void publishAdhocResult(ResultMO result) { if (logger.isTraceEnabled()) logger.trace("Publishing adhoc result to " + result.getAdhocId() + " with message " + result); this.adhocProducer.publish(new AdhocResultKey(result.getAdhocId()), result); } protected void rescheduleCheck(ActiveCheck<?, ?> check, long interval) { if (logger.isTraceEnabled()) logger.trace("Rescheduling " + check.getType() + "::" + check.getId() + " [" + check.getName() + "]" + " with new interval " + interval + " due to state change"); this.schedulerActionProducer.publish(new SchedulerKey(check.getSiteId(), check.getPool()), new RescheduleCheck(check.getId(), interval)); } protected void publishNotification(Check<?, ?> check, Notification notification) { if (logger.isTraceEnabled()) logger.trace("Sending notification:\r\n" + notification); this.notificationsProducer.publish(new NotificationKey(check.getSiteId()), notification); } protected void publishAlertUpdate(Alert alert, AlertUpdate update) { if (logger.isTraceEnabled()) logger.trace("Sending alert update:\r\n" + update); this.updateProducer.publish(new UpdateKey(UpdateType.ALERT, alert.getSiteId(), alert.getId()), update); } protected void publishCheckUpdate(Check<?, ?> check, CheckUpdate update) { if (logger.isTraceEnabled()) logger.trace("Sending check update:\r\n" + update); this.updateProducer.publish(new UpdateKey(UpdateType.CHECK, check.getSiteId(), check.getId()), update); } protected void publishGroupUpdate(Group group, GroupUpdate update) { if (logger.isTraceEnabled()) logger.trace("Sending group update:\r\n" + update); this.updateProducer.publish(new UpdateKey(UpdateType.GROUP, group.getSiteId(), group.getId()), update); } protected void publishLocationUpdate(Location location, LocationUpdate update) { if (logger.isTraceEnabled()) logger.trace("Sending location update:\r\n" + update); this.updateProducer.publish(new UpdateKey(UpdateType.LOCATION, location.getSiteId(), location.getId()), update); } }