/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package uk.ac.imperial.lsds.seep.infrastructure.monitor.slave; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import uk.ac.imperial.lsds.seep.infrastructure.monitor.Stoppable; import uk.ac.imperial.lsds.seep.infrastructure.monitor.comm.serialization.BinaryMetricsSerializer; import uk.ac.imperial.lsds.seep.infrastructure.monitor.comm.serialization.MetricsTuple; import uk.ac.imperial.lsds.seep.infrastructure.monitor.slave.reader.DefaultMetricsReader; /** * * @author mrouaux */ public class MonitorSlave implements Runnable, Stoppable { final private Logger logger = LoggerFactory.getLogger(MonitorSlave.class); private int operatorId; private String masterHost; private int masterPort; private int freqSeconds; private int waitInterval; private boolean report; private Socket slaveSocket; /** * Convenience constructor. * @param operatorId Unique identifier of the operator for which this slave * will be reporting metrics. * @param masterHost Host where the monitoring master process is running. * @param masterPort Port on which the monitoring master is listening for * incoming TCP connections from slave monitoring processes. * @freqSeconds Frequency in seconds for the slave to report metrics back to * the master. */ public MonitorSlave(int operatorId, String masterHost, int masterPort, int freqSeconds) { this.operatorId = operatorId; this.masterHost = masterHost; this.masterPort = masterPort; this.freqSeconds = freqSeconds; this.waitInterval = (1000 * freqSeconds) - 1; this.report = true; } /** * Execute the monitoring slave process. */ @Override public void run() { try { logger.info("Slave [operatorId=" + operatorId + "] Connecting to master"); slaveSocket = new Socket(masterHost, masterPort); // Once we have an output stream to the master, we can create a processor // and initialise it accordingly. MonitorSlaveProcessor processor = createSlaveProcessor(slaveSocket.getOutputStream()); // Execute in a tight loop, requesting the processor to read from whatever // readers it is set to use and report with any configured reporters. while(report) { Thread.sleep(waitInterval); processor.process(); } slaveSocket.close(); logger.info("MonitorSlave is stopped"); } catch(IOException ex) { logger.error("Exception connecting to MonitorMaster", ex); } catch(InterruptedException ex){ logger.error("Unable to wait before sending next metrics " + "to the MonitorMaster", ex); } } /** * Stops the monitoring slave process. */ @Override public void stop() { logger.info("Stopping MonitorSlave"); report = false; try { slaveSocket.close(); } catch (IOException ex) { logger.error("Exception closing MonitorSlave client socket", ex); } } /** * Pushes tuple from the slave to the master. The push is immediate, the tuple * is not queued up until the next metric pushing cycle. * @param tuple Tuple to push to the monitoring master. */ public void pushMetricsTuple(MetricsTuple tuple) { if (slaveSocket != null) { logger.debug("Pushing tuple to master " + tuple.toString()); BinaryMetricsSerializer serializer = new BinaryMetricsSerializer(); try { serializer.initialize(slaveSocket.getOutputStream()); } catch(IOException ex) { logger.error("Exception serialising metric to push", ex); } serializer.serialize(tuple); } } /** * Creates and initialised an slave processor instance, for a given output * stream (which should terminate at the monitoring master). * @param os Output stream to the monitoring master. * @return Processor instance. */ protected MonitorSlaveProcessor createSlaveProcessor(OutputStream os) { MonitorSlaveProcessor processor = new MonitorSlaveProcessor(operatorId); processor.addReader(new DefaultMetricsReader()); BinaryMetricsSerializer serializer = new BinaryMetricsSerializer(); serializer.initialize(os); processor.addReporter(serializer); return processor; } public int getOperatorId() { return operatorId; } public void setOperatorId(int operatorId) { this.operatorId = operatorId; } }