use of de.hpi.bpt.scylla.simulation.ProcessSimulationComponents in project scylla by bptlab.
the class EventArrivalRateSchedulingPlugin method scheduleEvent.
/**
* Gets a sample of the arrival rate distribution for this event, if existing,
* and schedules the event displaced by this value.
*/
@Override
public boolean scheduleEvent(ScyllaEvent event, TimeSpan timeSpan) throws ScyllaRuntimeException {
ProcessSimulationComponents pSimComponents = event.getDesmojObjects();
Map<Integer, Object> arrivalRates = pSimComponents.getExtensionDistributions().get(getName());
@SuppressWarnings("unchecked") SimpleEntry<NumericalDist<?>, TimeUnit> arrivalRate = (SimpleEntry<NumericalDist<?>, TimeUnit>) arrivalRates.get(event.getNodeId());
if (arrivalRate != null) {
NumericalDist<?> distribution = arrivalRate.getKey();
TimeUnit timeUnit = arrivalRate.getValue();
ProcessInstance processInstance = event.getProcessInstance();
TimeSpan offset = new TimeSpan(distribution.sample().doubleValue(), timeUnit);
TimeSpan newTime = new TimeSpan(timeSpan.getTimeAsDouble() + offset.getTimeAsDouble());
event.schedule(processInstance, newTime);
return false;
}
return true;
}
use of de.hpi.bpt.scylla.simulation.ProcessSimulationComponents in project scylla by bptlab.
the class SubprocessBPMNEEPlugin method eventRoutine.
@Override
public void eventRoutine(BPMNEndEvent desmojEvent, ProcessInstance processInstance) throws ScyllaRuntimeException {
ProcessModel processModel = processInstance.getProcessModel();
if (processModel.getParent() != null && processInstanceIsCompleted(processInstance)) {
// works
try {
ProcessSimulationComponents desmojObjects = desmojEvent.getDesmojObjects();
ProcessSimulationComponents parentDesmojObjects = desmojObjects.getParent();
ProcessModel parentModel = processModel.getParent();
int nodeIdInParent = processModel.getNodeIdInParent();
ProcessInstance parentProcessInstance = processInstance.getParent();
// behavior when sub-process sends events:
// none -> back to normal flow
// message -> "send it"
// error -> to parent
// escalation -> to parent
// cancel -> nonono!
// compensation -> ... not now
// signal -> ... not now
// terminate -> terminate sub-process (kill all events of sub-process instance (MI sub-process
// not affected))
// ...
// timer -> special treatment
Set<Integer> idsOfNextNodes = parentModel.getIdsOfNextNodes(nodeIdInParent);
// normal flow: must not have more than one successor
if (idsOfNextNodes.size() != 1) {
int nodeId = desmojEvent.getNodeId();
throw new ScyllaValidationException("Subprocess " + nodeId + " does not have 1 successor, but " + idsOfNextNodes.size() + ".");
}
Integer nextNodeId = idsOfNextNodes.iterator().next();
// TODO let the parent create the next node, so remove the lines below
List<ScyllaEvent> events = SimulationUtils.createEventsForNextNode(desmojEvent, parentDesmojObjects, parentProcessInstance, nextNodeId);
// next event occurs immediately after start event
TimeSpan timeSpan = new TimeSpan(0);
String parentProcessInstanceName = parentProcessInstance.getName();
SubprocessPluginUtils pluginInstance = SubprocessPluginUtils.getInstance();
TaskTerminateEvent eventOfParent = pluginInstance.getEventsOnHold().get(parentProcessInstanceName).get(nodeIdInParent);
if (eventOfParent != null) {
events.add(eventOfParent);
pluginInstance.getEventsOnHold().get(parentProcessInstanceName).remove(nodeIdInParent);
pluginInstance.getNameOfEventsThatWereOnHold().add(eventOfParent.getName());
}
for (ScyllaEvent event : events) {
int index = desmojEvent.getNewEventIndex();
desmojEvent.getNextEventMap().put(index, event);
desmojEvent.getTimeSpanToNextEventMap().put(index, timeSpan);
}
} catch (NodeNotFoundException | ScyllaValidationException | ScyllaRuntimeException e) {
SimulationModel model = (SimulationModel) desmojEvent.getModel();
int nodeId = desmojEvent.getNodeId();
boolean showInTrace = model.traceIsOn();
DebugLogger.error(e.getMessage());
e.printStackTrace();
SimulationUtils.abort(model, processInstance, nodeId, showInTrace);
}
}
}
use of de.hpi.bpt.scylla.simulation.ProcessSimulationComponents in project scylla by bptlab.
the class SubprocessTBPlugin method eventRoutine.
@Override
public void eventRoutine(TaskBeginEvent desmojEvent, ProcessInstance processInstance) throws ScyllaRuntimeException {
ProcessModel processModel = processInstance.getProcessModel();
int nodeId = desmojEvent.getNodeId();
ProcessModel subProcess = processModel.getSubProcesses().get(nodeId);
if (subProcess != null) {
int indexOfTaskTerminateEvent = 0;
desmojEvent.getTimeSpanToNextEventMap().remove(indexOfTaskTerminateEvent);
TaskTerminateEvent event = (TaskTerminateEvent) desmojEvent.getNextEventMap().get(indexOfTaskTerminateEvent);
String name = processInstance.getName();
SubprocessPluginUtils pluginInstance = SubprocessPluginUtils.getInstance();
Map<Integer, TaskTerminateEvent> eventsOnHoldMap = pluginInstance.getEventsOnHold().get(name);
if (eventsOnHoldMap == null) {
pluginInstance.getEventsOnHold().put(name, new HashMap<Integer, TaskTerminateEvent>());
}
pluginInstance.getEventsOnHold().get(name).put(nodeId, event);
desmojEvent.getNextEventMap().remove(indexOfTaskTerminateEvent);
String source = desmojEvent.getSource();
ProcessSimulationComponents desmojObjects = desmojEvent.getDesmojObjects();
SimulationModel model = (SimulationModel) desmojEvent.getModel();
TimeInstant currentSimulationTime = model.presentTime();
boolean showInTrace = model.traceIsOn();
int processInstanceId = processInstance.getId();
try {
ProcessSimulationComponents desmojObjectsOfSubProcess = desmojObjects.getChildren().get(nodeId);
Integer startNodeId = subProcess.getStartNode();
ProcessInstance subProcessInstance = new ProcessInstance(model, subProcess, processInstanceId, showInTrace);
subProcessInstance.setParent(processInstance);
ScyllaEvent subProcessEvent = new BPMNStartEvent(model, source, currentSimulationTime, desmojObjectsOfSubProcess, subProcessInstance, startNodeId);
TimeSpan timeSpan = new TimeSpan(0);
int index = desmojEvent.getNewEventIndex();
desmojEvent.getNextEventMap().put(index, subProcessEvent);
desmojEvent.getTimeSpanToNextEventMap().put(index, timeSpan);
} catch (NodeNotFoundException | MultipleStartNodesException | NoStartNodeException e) {
DebugLogger.error(e.getMessage());
DebugLogger.log("Start node of process model " + subProcess.getId() + " not found.");
throw new ScyllaRuntimeException("Start node of process model " + subProcess.getId() + " not found.");
}
}
}
use of de.hpi.bpt.scylla.simulation.ProcessSimulationComponents in project scylla by bptlab.
the class ProcessInstanceGenerationEvent method eventRoutine.
// TODO XSD validation
// TODO fixed cost per task
@Override
public void eventRoutine(ProcessInstance processInstance) throws SuspendExecution {
this.processInstance = processInstance;
SimulationModel model = (SimulationModel) getModel();
TimeInstant currentSimulationTime = model.presentTime();
TimeUnit timeUnit = DateTimeUtils.getReferenceTimeUnit();
long currentTime = currentSimulationTime.getTimeRounded(timeUnit);
if (currentTime >= endTimeRelativeToGlobalStart) {
// if the end time is reached
return;
}
boolean showInTrace = traceIsOn();
String name = getName();
ProcessSimulationComponents desmojObjects = model.getDesmojObjectsMap().get(processId);
ProcessModel processModel = desmojObjects.getProcessModel();
try {
Integer startNodeId = processModel.getStartNode();
timeSpanToStartEvent = new TimeSpan(0);
ProcessInstanceGenerationEventPluggable.runPlugins(this, processInstance);
BPMNStartEvent event = new BPMNStartEvent(model, name, currentSimulationTime, desmojObjects, processInstance, startNodeId);
int processInstanceId = desmojObjects.incrementProcessInstancesStarted();
// schedule next process instance start event
if (processInstanceId <= desmojObjects.getSimulationConfiguration().getNumberOfProcessInstances()) {
double duration = desmojObjects.getDistributionSample(startNodeId);
TimeUnit unit = desmojObjects.getDistributionTimeUnit(startNodeId);
ProcessInstance nextProcessInstance = new ProcessInstance(model, processModel, processInstanceId, showInTrace);
timeSpanToNextProcessInstance = new TimeSpan(duration, unit);
ProcessInstanceGenerationEvent nextEvent = new ProcessInstanceGenerationEvent(model, processId, endTimeRelativeToGlobalStart, showInTrace);
nextEvent.schedule(nextProcessInstance, timeSpanToNextProcessInstance);
}
// schedule for start of simulation
event.schedule(processInstance, timeSpanToStartEvent);
} catch (NodeNotFoundException | MultipleStartNodesException | NoStartNodeException | ScyllaRuntimeException e) {
DebugLogger.error(e.getMessage());
e.printStackTrace();
DebugLogger.log("Error during instantiation of process model " + processModel.getId() + ".");
// no node initialized, use zero
int nodeId = 0;
SimulationUtils.abort(model, processInstance, nodeId, showInTrace);
}
}
use of de.hpi.bpt.scylla.simulation.ProcessSimulationComponents in project scylla by bptlab.
the class BatchPluginUtils method assignToBatchCluster.
@SuppressWarnings("unchecked")
void assignToBatchCluster(ProcessInstance processInstance, int nodeId, TaskBeginEvent parentalBeginEvent) {
ProcessModel processModel = processInstance.getProcessModel();
ProcessSimulationComponents pSimComponents = parentalBeginEvent.getDesmojObjects();
/*Map<Integer, BatchActivity> batchActivities_old = (Map<Integer, BatchActivity>) pSimComponents.getSimulationConfiguration()
.getExtensionValue(PLUGIN_NAME, "batchActivities");*/
Map<Integer, BatchActivity> batchActivities = processModel.getBatchActivities();
BatchActivity activity = batchActivities.get(nodeId);
BatchCluster cluster = null;
// (1) select the right batch cluster
// (1a) check if there is already a batch with the data view
String processId = processModel.getId();
Map<Integer, List<BatchCluster>> batchClustersOfProcess = batchClusters.get(processId);
if (batchClustersOfProcess != null) {
List<BatchCluster> clusters = batchClustersOfProcess.get(nodeId);
if (clusters != null) {
for (BatchCluster bc : clusters) {
if (batchClusterHasNotStarted(bc.getState()) && isProcessInstanceMatchingToDataView(parentalBeginEvent, processInstance, bc)) {
cluster = bc;
// clusters.remove(bc);
break;
}
}
}
}
// (1b) if not, create a new one
if (cluster == null) {
Model model = processInstance.getModel();
boolean showInTrace = processInstance.traceIsOn();
Map<String, Object> dataView = this.getDataViewOfInstance(parentalBeginEvent, processInstance, activity);
TimeInstant currentSimulationTime = processInstance.presentTime();
cluster = new BatchCluster(model, currentSimulationTime, pSimComponents, activity, nodeId, dataView, showInTrace);
// schedule BatchClusterStart at current time plus maximum timeout
BatchClusterStartEvent clusterStartEvent = new BatchClusterStartEvent(model, cluster.getName(), showInTrace);
Duration timeout = activity.getActivationRule().getTimeOut(parentalBeginEvent, processInstance);
cluster.setCurrentTimeOut(timeout);
long timeoutInSeconds = timeout.get(ChronoUnit.SECONDS);
TimeSpan timeSpan = new TimeSpan(timeoutInSeconds, TimeUnit.SECONDS);
clusterStartEvent.schedule(cluster, timeSpan);
if (batchClustersOfProcess == null) {
batchClustersOfProcess = new HashMap<Integer, List<BatchCluster>>();
batchClusters.put(processId, batchClustersOfProcess);
List<BatchCluster> clusters = batchClustersOfProcess.get(nodeId);
if (clusters == null) {
clusters = new ArrayList<BatchCluster>();
batchClustersOfProcess.put(nodeId, clusters);
}
}
batchClustersOfProcess.get(nodeId).add(cluster);
}
// (2) add process instance to cluster
cluster.addProcessInstance(processInstance, parentalBeginEvent);
// TODO check whether timeout should be updated
if (cluster.getState() == BatchClusterState.INIT && cluster.getProcessInstances().size() > 1) {
// if the dueDate of the current instance is earlier as of the instances added before, the cluster begin event is rescheduled
Duration timeoutForCurrentInstance = activity.getActivationRule().getTimeOut(parentalBeginEvent, processInstance);
// testing
TimeUnit epsilon = TimeUnit.SECONDS;
Duration durationBtwClusterStartAndInstanceTaskBegin = Duration.ofSeconds((long) (parentalBeginEvent.getSimulationTimeOfSource().getTimeAsDouble(epsilon) - cluster.getCreationTime().getTimeAsDouble(epsilon)));
// System.out.println("InstanceEnable: "+parentalBeginEvent.getSimulationTimeOfSource().getTimeAsDouble(epsilon)+" ClusterCreation: "+cluster.getCreationTime().getTimeAsDouble(epsilon)+" Duration "+durationBtwClusterStartAndInstanceTaskBegin);
if (timeoutForCurrentInstance.plus(durationBtwClusterStartAndInstanceTaskBegin).compareTo(cluster.getCurrentTimeOut()) < 0) {
// set new timeout for the cluster for comparison
cluster.setCurrentTimeOut(timeoutForCurrentInstance);
// reschedule the cluster beginEvent
long timeoutInSeconds = timeoutForCurrentInstance.get(ChronoUnit.SECONDS);
TimeSpan timeSpan = new TimeSpan(timeoutInSeconds, TimeUnit.SECONDS);
BatchClusterStartEvent clusterStartEvent = (BatchClusterStartEvent) cluster.getScheduledEvents().get(0);
cluster.cancel();
clusterStartEvent.schedule(cluster, timeSpan);
}
}
if (cluster.getState() == BatchClusterState.MAXLOADED) {
// (2a) if bc is maxloaded, reschedule BatchClusterStart
// there is only one event already scheduled for the cluster which is the BatchClusterStart
BatchClusterStartEvent clusterStartEvent = (BatchClusterStartEvent) cluster.getScheduledEvents().get(0);
cluster.cancel();
// schedule for immediate execution
clusterStartEvent.schedule(cluster);
}
}
Aggregations