package eu.play_project.dcep.distributedetalis.measurement;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import eu.play_project.dcep.api.measurement.NodeMeasurementResult;
import eu.play_project.dcep.distributedetalis.DistributedEtalis;
import eu.play_project.dcep.distributedetalis.JtalisInputProvider;
import eu.play_project.dcep.distributedetalis.PlayJplEngineWrapper;
import eu.play_project.dcep.distributedetalis.PrologSemWebLib;
import eu.play_project.dcep.distributedetalis.measurement.fsm.MeasureProcessingTime;
import eu.play_project.dcep.distributedetalis.measurement.fsm.MeasurementState;
import eu.play_project.dcep.distributedetalis.measurement.fsm.MeasuremnetFinished;
import eu.play_project.dcep.distributedetalis.measurement.fsm.Ready;
import eu.play_project.dcep.distributedetalis.measurement.fsm.WaitForComplexMeasurementEvent;
import eu.play_project.dcep.distributedetalis.measurement.fsm.WaitForMeasuredData;
import fr.inria.eventcloud.api.CompoundEvent;
/**
* Measure performance for a dEtalis node.
* @author sobermeier
*/
public class MeasurementUnit implements MeasurementState{
private final Logger logger;
private MeasurementState state; // State for the measurement.
private final PrologSemWebLib semWebLib;
private final DistributedEtalis cepEngine;
PlayJplEngineWrapper etalis;
private int numberOfInputEvents = 0;
private int numberOfOutputEvents = 0;
private long totalInputEvents = 0;
private long totalOutputEvents = 0;
private boolean inMeasurementMode = false;
private List<Long> singleEventTime; // Time for one event.
private NodeMeasurementResult measuredValues; //Statistics data from cepEngine.
//Config
public static int mEvents = 1; //Defines the number of events used to measure the performance. How often eventsPeriod is sent.
public static int eventsPeriod = 100; // Defines the number of events send in one measuring period. Default 5
public void sendMeasureEvents(){
state.sendMeasuringEvent();
}
public MeasurementUnit(DistributedEtalis cepEngine, PlayJplEngineWrapper etalis, PrologSemWebLib semWebLib){
this.logger = LoggerFactory.getLogger(MeasurementUnit.class);
this.cepEngine = cepEngine;
this.etalis = etalis;
this.semWebLib = semWebLib;
this.state = createMeasurementState("Start");
this.singleEventTime = new ArrayList<Long>();
}
@Override
public void startMeasurement(int period) {
logger.debug("Measurement request: " + period + "ms.");
//Clear counters
numberOfInputEvents =0;
numberOfOutputEvents = 0;
singleEventTime = new ArrayList<Long>();
this.setInMeasurementMode(true);
state.startMeasurement(period);
}
@Override
public void eventReceived() {
totalInputEvents++;
state.eventReceived();
}
@Override
public void eventProduced(CompoundEvent event, String patternId) {
totalOutputEvents++;
state.eventProduced(event, patternId);
}
public MeasurementState createMeasurementState(String name){
MeasurementState state = null;
if(name.equals("Start")){
state = new Ready(etalis, this);
}else if (name.equals("MeasureProcessingTime")){
state = new MeasureProcessingTime(this, cepEngine, semWebLib);
System.out.println("New state: " + state.getName());
}else if (name.equals("WaitForComplexMeasurementEvents")){
state = new WaitForComplexMeasurementEvent(this, 0);
}else if (name.equals("WaitForMeasuredData")){
state = new WaitForMeasuredData(this);
logger.info("Create WaitForMeasuredData");
}else if(name.equals("MeasurementFinished")){
state = new MeasuremnetFinished(this);
}
if(state==null){
throw new RuntimeException("It is not possible to generate a objet for the name: " + name);
}
return state;
}
public boolean inMeasurementMode() {
return inMeasurementMode;
}
public long getTotalEventsProduced() {
return totalOutputEvents;
}
public MeasurementState getState() {
return state;
}
public void setState(MeasurementState state) {
logger.info("setState. State is " + this.state.getName() );
this.state = state;
logger.info("setState: " + this.state.getName() );
}
@Override
public NodeMeasurementResult getMeasuringResults() {
logger.debug("Request measured data.");
logger.debug("State: " + state.getName());
NodeMeasurementResult n = state.getMeasuringResults();
return n;
}
@Override
public void setMeasuredData(NodeMeasurementResult measuredValues) {
state.setMeasuredData(measuredValues);
}
/**
* Return average singele event time.
* @return
*/
public long getSingleEventTime() {
long singelEventTimeResult =0;
for (Long time : singleEventTime ) {
singelEventTimeResult += time;
}
singelEventTimeResult /=singleEventTime.size();
singleEventTime= new ArrayList<Long>();
return singelEventTimeResult;
}
public void addSingleEventTime(long singleEventTime) {
logger.info(" Single event time: " + singleEventTime);
this.singleEventTime.add(singleEventTime);
}
public int getNumberOfInputEvents() {
return numberOfInputEvents;
}
public void setNumberOfInputEvents(int numberOfInputEvents) {
this.numberOfInputEvents = numberOfInputEvents;
}
public int getNumberOfOutputEvents() {
return numberOfOutputEvents;
}
public void setNumberOfOutputEvents(int numberOfOutputEvents) {
this.numberOfOutputEvents = numberOfOutputEvents;
}
public synchronized void setMeasuredValues(NodeMeasurementResult measuredValues) {
state.setMeasuredData(measuredValues);
this.measuredValues = measuredValues;
}
public void setInMeasurementMode(boolean inMeasurementMode) {
this.inMeasurementMode = inMeasurementMode;
}
public NodeMeasurementResult getMeasurementData() {
// If the measurement finished, publish the result. Else null.
if (measuredValues != null) {
measuredValues.setNumberOfComponentInputEvetns(numberOfInputEvents);
measuredValues.setNumberOfOutputEvents(numberOfOutputEvents);
measuredValues.setProcessingTimeForOneEvent(this.getSingleEventTime());
measuredValues.setNumberOfEventsProcessedSinceStartUp(totalInputEvents);
measuredValues.setNumberOfEtalisInputEvents(JtalisInputProvider.getEventCounter());
//measuredValues.setCompontenQueue(cepEngine.getService().getRequestCount());
measuredValues.setEtalisInputQueue(cepEngine.getEventInputProvider().getInputQueueSize());
return measuredValues;
} else {
logger.debug("No measured data.");
return null;
}
}
@Override
public String getName() {
return "MeasurementUnit";
}
@Override
public void sendMeasuringEvent() {
}
@Override
public void measuringPeriodIsUp() {
state.measuringPeriodIsUp();
}
}