package vroom.optimization.online.jmsa.utils;
import vroom.optimization.online.jmsa.IDistinguishedSolution;
import vroom.optimization.online.jmsa.MSABase;
import vroom.optimization.online.jmsa.events.MSACallbackBase;
import vroom.optimization.online.jmsa.events.MSACallbackEvent;
import vroom.optimization.online.jmsa.events.MSACallbackEvent.EventTypes;
import vroom.optimization.online.jmsa.events.MSAEvent;
import vroom.optimization.online.jmsa.events.NewRequestEvent;
import vroom.optimization.online.jmsa.events.ResourceEvent;
import vroom.optimization.online.jmsa.utils.MSASimulator.ResourceState;
import vroom.optimization.online.jmsa.utils.MSASimulator.ResourceStates;
/**
* The class <code>MSASimulationCallback</code> is designed to simplify the design of a simulation scheme around MSA. It
* contains default cases that are useful when doing a simulation.
* <p>
* Creation date: Mar 15, 2012 - 5:30:05 PM
*
* @author Victor Pillac, <a href="http://uniandes.edu.co">Universidad de Los Andes</a>-<a
* href="http://copa.uniandes.edu.co">Copa</a> <a href="http://www.emn.fr">Ecole des Mines de Nantes</a>-<a
* href="http://www.irccyn.ec-nantes.fr/irccyn/d/en/equipes/Slp">SLP</a>
* @version 1.0
*/
/**
* <p>
* Creation date: Mar 15, 2012 - 5:36:20 PM
*
* @author Victor Pillac, <a href="http://uniandes.edu.co">Universidad de Los Andes</a>-<a
* href="http://copa.uniandes.edu.co">Copa</a> <a href="http://www.emn.fr">Ecole des Mines de Nantes</a>-<a
* href="http://www.irccyn.ec-nantes.fr/irccyn/d/en/equipes/Slp">SLP</a>
* @version 1.0
*/
public abstract class MSASimulationCallback extends MSACallbackBase {
protected final MSASimulator mSimulator;
/**
* Creates a new <code>MSASimulationCallback</code>
*
* @param simulator
* the {@link MSASimulator} to which this simulation callback is linked
*/
public MSASimulationCallback(MSASimulator simulator) {
super();
mSimulator = simulator;
}
/**
* Returns the {@link MSASimulator} to which this simulation callback is linked
*
* @return the {@link MSASimulator} to which this simulation callback is linked
*/
public MSASimulator getSimulator() {
return mSimulator;
}
@Override
public int getPriority() {
return Integer.MIN_VALUE;
}
@Override
public boolean isExecutedSynchronously() {
return true;
}
/**
* Register this instance as a callback on all {@linkplain EventTypes event types}
*
* @param msa
* the procedure in which this instance will be registered
*/
public void registerAsCallback(MSABase<?, ?> msa) {
for (EventTypes t : EventTypes.values())
msa.registerCallback(t, this);
}
@Override
public void execute(MSACallbackEvent event) {
MSALogging.getBaseLogger()
.debug("SimulationCallback.execute: handling event %s", event);
beforeExecute(event);
switch (event.getType()) {
case EVENTS_RESOURCE:
ResourceEvent e = (ResourceEvent) event.getParams()[0];
switch (e.getType()) {
case START:
resourceStarted(event, e);
break;
case STOP:
resourceStopped(event, e);
break;
case REQUEST_ASSIGNED:
requestAssigned(event, e);
break;
case START_OF_SERVICE:
startOfService(event, e);
break;
case END_OF_SERVICE:
endOfService(event, e);
break;
}
break;
case MSA_NEW_DISTINGUISHED_SOLUTION:
IDistinguishedSolution oldS = event.getParams()[0] != null ? (IDistinguishedSolution) event
.getParams()[0] : null;
IDistinguishedSolution newS = event.getParams()[1] != null ? (IDistinguishedSolution) event
.getParams()[1] : null;
newDistinguishedSolution(event, oldS, newS);
break;
case MSA_START:
msaStarted(event);
break;
case MSA_END:
msaEnded(event);
break;
case MSA_NEW_EVENT:
MSAEvent ev = (MSAEvent) event.getParams()[0];
if (NewRequestEvent.class.isInstance(ev))
newRequest(event, (NewRequestEvent) ev);
break;
default: // Do nothing
break;
}
afterExecture(event);
}
/**
* This method will be called at the beginning of {@link #execute(vroom.common.utilities.callbacks.ICallbackEvent)}
* <p>
* The default behavior of this method is to acquire the lock on the attached {@link #getSimulator() simulator}
* </p>
*
* @param event
* the event that triggered the callback
*/
protected void beforeExecute(MSACallbackEvent event) {
getSimulator().acquireLock();
}
/**
* This method will be called at the end of {@link #execute(vroom.common.utilities.callbacks.ICallbackEvent)}, even
* if an exception was thrown
* <p>
* The default behavior of this method is to release the lock on the attached {@link #getSimulator() simulator}
* </p>
*
* @param event
* the event that triggered the callback
*/
protected void afterExecture(MSACallbackEvent event) {
getSimulator().releaseLock();
}
/**
* This method will be called when the MSA procedure has been started
*
* @param cbEvent
* the original callback event
*/
protected void msaStarted(MSACallbackEvent event) {
}
/**
* This method will be called when the MSA procedure finished
*
* @param cbEvent
* the original callback event
*/
protected void msaEnded(MSACallbackEvent event) {
}
/**
* This method will be called when a resource started its service
* <p>
* By default it will set the {@link MSASimulator#getState(int) state} of the corresponding resource to
* {@link ResourceStates#SERVICING}
* </p>
*
* @param cbEvent
* the original callback event
* @param e
* the original resource event
*/
protected void startOfService(MSACallbackEvent cbEvent, ResourceEvent e) {
getSimulator().getState(e.getResourceId()).setState(ResourceStates.SERVICING);
}
/**
* This method will be called when a resource finished its service
* <p>
* By default it will set the {@link MSASimulator#getState(int) state} of the corresponding resource to
* {@link ResourceStates#IDLE}, remove the request from the resource's
* {@linkplain ResourceState#getAssignedRequests() list of assigned requests}, and add the request to the resource's
* {@linkplain ResourceState#getServedRequests() list of served requests}
* </p>
*
* @param cbEvent
* the original callback event
* @param e
* the original resource event
*/
protected void endOfService(MSACallbackEvent cbEvent, ResourceEvent e) {
ResourceState state = getSimulator().getState(e.getResourceId());
state.setState(ResourceStates.IDLE);
state.addServedRequest(e.getRequest());
state.removeAssignedRequest(e.getRequest());
}
/**
* This method will be called when a resource is assigned a request
* <p>
* By default it will set the {@link MSASimulator#getState(int) state} of the corresponding resource to
* {@link ResourceStates#BUSY} and add the request to the resource's
* {@linkplain ResourceState#getAssignedRequests() list of assigned requests}
* </p>
*
* @param cbEvent
* the original callback event
* @param e
* the original resource event
*/
protected void requestAssigned(MSACallbackEvent cbEvent, ResourceEvent e) {
ResourceState state = getSimulator().getState(e.getResourceId());
state.setState(ResourceStates.BUSY);
state.addAssignedRequest(e.getRequest());
}
/**
* This method will be called when a resource has started
* <p>
* By default it will set the {@link MSASimulator#getState(int) state} of the corresponding resource to
* {@link ResourceStates#IDLE}
* </p>
*
* @param cbEvent
* the original callback event
* @param e
* the original resource event
*/
protected void resourceStarted(MSACallbackEvent cbEvent, ResourceEvent e) {
getSimulator().getState(e.getResourceId()).setState(ResourceStates.IDLE);
}
/**
* This method will be called when a resource has stopped
* <p>
* By default it will set the {@link MSASimulator#getState(int) state} of the corresponding resource to
* {@link ResourceStates#STOPPED}
* </p>
*
* @param cbEvent
* the original callback event
* @param e
* the original resource event
*/
protected void resourceStopped(MSACallbackEvent cbEvent, ResourceEvent e) {
getSimulator().getState(e.getResourceId()).setState(ResourceStates.STOPPED);
}
/**
* This method will be called when a new distinguished solution has been produced
*
* @param cbEvent
* the original callback event
*/
protected void newDistinguishedSolution(MSACallbackEvent event, IDistinguishedSolution oldSol,
IDistinguishedSolution newSol) {
}
/**
* This method will be called when a new request event is retrieved by the jMSA procedure
*
* @param event
* the original callback event
* @param ev
* the new request event
*/
protected void newRequest(MSACallbackEvent event, NewRequestEvent e) {
}
}