use of de.hpi.bpt.scylla.simulation.event.ScyllaEvent in project scylla by bptlab.
the class EventbasedGatewayEventPlugin method eventRoutine.
/**
* Handles a gateway event, if it is an event based gateway
* Changes scheduling behavior by already scheduling the next events of the given gateway event (if event based)
*/
@Override
public void eventRoutine(GatewayEvent desmojEvent, ProcessInstance processInstance) throws ScyllaRuntimeException {
SimulationModel model = (SimulationModel) desmojEvent.getModel();
ProcessModel processModel = processInstance.getProcessModel();
int nodeId = desmojEvent.getNodeId();
GatewayType type = processModel.getGateways().get(nodeId);
try {
Set<Integer> idsOfNextNodes = processModel.getIdsOfNextNodes(nodeId);
if (type == GatewayType.EVENT_BASED && idsOfNextNodes.size() > 1) {
// Schedule all following events
List<ScyllaEvent> nextEvents = new ArrayList<ScyllaEvent>(desmojEvent.getNextEventMap().values());
desmojEvent.scheduleNextEvents();
// and look which is scheduled first.
ScyllaEvent first = nextEvents.get(0);
for (ScyllaEvent e : nextEvents) {
if (TimeInstant.isBefore(e.scheduledNext(), first.scheduledNext())) {
first = e;
}
}
// Cancel all other events except the one that is scheduled first.
nextEvents.remove(first);
for (ScyllaEvent e : nextEvents) {
e.cancel();
}
}
} catch (NodeNotFoundException | ScyllaValidationException | SuspendExecution e) {
e.printStackTrace();
// Critical error (following nodes not found or validation error), abort the instance.
SimulationUtils.abort(model, processInstance, nodeId, desmojEvent.traceIsOn());
}
}
use of de.hpi.bpt.scylla.simulation.event.ScyllaEvent 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.event.ScyllaEvent 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.event.ScyllaEvent in project scylla by bptlab.
the class QueueManager method getEventFromQueueReadyForSchedule.
/**
* Returns eventwhich is ready to be scheduled for immediate execution from event queues.
*
* @param model
* the simulation model
* @param resourceQueuesUpdated
* resource queues which have been updated recently -> only the events which require resources from these
* queues are considered
* @return the DesmoJ event which is ready to be scheduled for immediate execution
*/
public static ScyllaEvent getEventFromQueueReadyForSchedule(SimulationModel model, Set<String> resourceQueuesUpdated) {
List<ScyllaEvent> eventCandidates = new ArrayList<ScyllaEvent>();
int accumulatedIndex = Integer.MAX_VALUE;
for (String resourceId : resourceQueuesUpdated) {
ScyllaEventQueue eventQueue = model.getEventQueues().get(resourceId);
for (int i = 0; i < eventQueue.size(); i++) {
ScyllaEvent eventFromQueue = eventQueue.peek(i);
if (eventCandidates.contains(eventFromQueue)) {
continue;
}
int index = 0;
boolean eventIsEligible = hasResourcesForEvent(model, eventFromQueue);
if (eventIsEligible) {
ProcessSimulationComponents desmojObjects = eventFromQueue.getDesmojObjects();
int nodeId = eventFromQueue.getNodeId();
Set<ResourceReference> resourceReferences = desmojObjects.getSimulationConfiguration().getResourceReferenceSet(nodeId);
for (ResourceReference ref : resourceReferences) {
// add position in queue and add to index
String resId = ref.getResourceId();
ScyllaEventQueue eventQ = model.getEventQueues().get(resId);
index += eventQ.getIndex(eventFromQueue);
}
if (accumulatedIndex < index) {
break;
} else if (accumulatedIndex == index) {
eventCandidates.add(eventFromQueue);
} else if (accumulatedIndex > index) {
accumulatedIndex = index;
eventCandidates.clear();
eventCandidates.add(eventFromQueue);
}
}
}
}
if (eventCandidates.isEmpty()) {
return null;
} else {
Collections.sort(eventCandidates, new Comparator<ScyllaEvent>() {
@Override
public int compare(ScyllaEvent e1, ScyllaEvent e2) {
return e1.getSimulationTimeOfSource().compareTo(e2.getSimulationTimeOfSource());
}
});
ScyllaEvent event = eventCandidates.get(0);
// get and assign resources
ResourceObjectTuple resourcesObjectTuple = getResourcesForEvent(model, event);
assignResourcesToEvent(model, event, resourcesObjectTuple);
ProcessSimulationComponents desmojObjects = event.getDesmojObjects();
int nodeId = event.getNodeId();
Set<ResourceReference> resourceReferences = desmojObjects.getSimulationConfiguration().getResourceReferenceSet(nodeId);
for (ResourceReference ref : resourceReferences) {
// remove from event queues
String resourceId = ref.getResourceId();
ScyllaEventQueue eventQueue = model.getEventQueues().get(resourceId);
eventQueue.remove(event);
}
return event;
}
}
use of de.hpi.bpt.scylla.simulation.event.ScyllaEvent in project scylla by bptlab.
the class QueueManager method releaseResourcesAndScheduleQueuedEvents.
/**
* Releases the resource instances assigned to the given event, selects event(s) from the event queues which are due
* next and schedules them immediately.
*
* @param model
* the simulation model
* @param releasingEvent
* the DesmoJ event whose resource instances may be released
* @throws ScyllaRuntimeException
*/
public static void releaseResourcesAndScheduleQueuedEvents(SimulationModel model, ScyllaEvent releasingEvent) throws ScyllaRuntimeException {
ProcessInstance processInstance = releasingEvent.getProcessInstance();
int nodeId = releasingEvent.getNodeId();
String nameOfResponsibleEvent = releasingEvent.getSource();
// release resources
Set<String> resourceQueuesUpdated = new HashSet<String>();
Set<ResourceObject> assignedResources = new HashSet<ResourceObject>();
if (nameOfResponsibleEvent == null) {
// release all resources of process instance
for (ResourceObjectTuple tuple : processInstance.getAssignedResources().values()) {
assignedResources.addAll(tuple.getResourceObjects());
}
} else {
assignedResources.addAll(processInstance.getAssignedResources().get(nameOfResponsibleEvent).getResourceObjects());
}
Map<String, ResourceQueue> resourceObjects = model.getResourceObjects();
TimeInstant presentTime = model.presentTime();
for (ResourceObject resourceObject : assignedResources) {
String resourceId = resourceObject.getResourceType();
resourceObjects.get(resourceId).offer(presentTime, resourceObject, processInstance, nodeId);
String traceNote = "Dissociate resource " + resourceId + " (" + resourceObject.getId() + ") from process instance " + processInstance.getName();
if (nameOfResponsibleEvent != null) {
traceNote += ", source: " + nameOfResponsibleEvent;
}
model.sendTraceNote(traceNote);
resourceQueuesUpdated.add(resourceId);
}
if (nameOfResponsibleEvent == null) {
processInstance.getAssignedResources().clear();
} else {
processInstance.getAssignedResources().remove(nameOfResponsibleEvent);
}
// ... and schedule next task if there are any in the queue
/**
* there may be no event ready for schedule, especially if they rely on resources that are together not
* available at the moment, so we have to check "later" again ? (whatever later means)
*
* --> solved by introduction of ResourceAvailableEvent
*/
ScyllaEvent eventFromQueue = getEventFromQueueReadyForSchedule(model, resourceQueuesUpdated);
while (eventFromQueue != null) {
SimulationUtils.scheduleEvent(eventFromQueue, new TimeSpan(0));
eventFromQueue = getEventFromQueueReadyForSchedule(model, resourceQueuesUpdated);
}
}
Aggregations