use of de.hpi.bpt.scylla.simulation.SimulationModel in project scylla by bptlab.
the class TaskTerminateEvent method addToLog.
@Override
protected void addToLog(ProcessInstance processInstance) {
long timestamp = Math.round(getModel().presentTime().getTimeRounded(DateTimeUtils.getReferenceTimeUnit()));
String taskName = displayName;
Set<String> resources = new HashSet<String>();
Set<ResourceObject> resourceObjects = processInstance.getAssignedResources().get(source).getResourceObjects();
for (ResourceObject res : resourceObjects) {
String resourceName = res.getResourceType() + "_" + res.getId();
resources.add(resourceName);
}
ProcessNodeTransitionType transition = ProcessNodeTransitionType.TERMINATE;
SimulationModel model = (SimulationModel) getModel();
if (!alreadyCanceled(model)) {
ProcessModel processModel = processInstance.getProcessModel();
String processScopeNodeId = SimulationUtils.getProcessScopeNodeId(processModel, nodeId);
ProcessNodeInfo info = new ProcessNodeInfo(nodeId, processScopeNodeId, source, timestamp, taskName, resources, transition);
model.addNodeInfo(processModel, processInstance, info);
}
}
use of de.hpi.bpt.scylla.simulation.SimulationModel in project scylla by bptlab.
the class DateTimeUtils method getTaskTerminationTime.
/**
* Calculates the relative end time of a task. Consideres timetables of resources instances. If any resource
* instance is idle, the duration is extended by the idle time.
*
* @param timeSpan
* the original duration of the task without any interruptions
* @param presentTime
* current simulation time
* @param tuple
* resource instances assigned to the task
* @param event
* source event (for logging purposes)
* @return the end time of the task
*/
public static TimeInstant getTaskTerminationTime(TimeSpan timeSpan, TimeInstant presentTime, ResourceObjectTuple tuple, ScyllaEvent event) {
SimulationModel model = (SimulationModel) event.getModel();
ProcessInstance processInstance = event.getProcessInstance();
ProcessModel processModel = processInstance.getProcessModel();
String source = event.getSource();
String taskName = event.getDisplayName();
int nodeId = event.getNodeId();
String processScopeNodeId = SimulationUtils.getProcessScopeNodeId(processModel, nodeId);
Set<String> resources = new HashSet<String>();
Set<ResourceObject> resourceObjects = tuple.getResourceObjects();
for (ResourceObject res : resourceObjects) {
String resourceName = res.getResourceType() + "_" + res.getId();
resources.add(resourceName);
}
// start
long duration = timeSpan.getTimeRounded(timeUnit);
if (duration == 0) {
return presentTime;
}
ZonedDateTime dateTime = DateTimeUtils.getDateTime(presentTime);
List<TimetableItem> timetable = tuple.getSharedTimetable();
if (timetable == null) {
return new TimeInstant(presentTime.getTimeRounded(timeUnit) + duration);
}
Integer index = null;
for (int i = 0; i < timetable.size(); i++) {
TimetableItem item = timetable.get(i);
if (isWithin(dateTime, item)) {
index = i;
break;
}
}
long timePassed = 0;
while (timePassed < duration) {
TimetableItem item = timetable.get(index);
DayOfWeek untilWeekday = item.getWeekdayTo();
LocalTime untilTime = item.getEndTime();
ZonedDateTime dateTimeUntilEnd = getNextOrSameZonedDateTime(dateTime, untilWeekday, untilTime);
long durationUntilEnd = chronoUnit.between(dateTime, dateTimeUntilEnd);
long amountToAdd;
if (timePassed + durationUntilEnd >= duration) {
// task completes in current timetable item
amountToAdd = duration - timePassed;
} else {
// until end of timetable item
amountToAdd = durationUntilEnd;
}
timePassed += amountToAdd;
dateTime = dateTime.plus(amountToAdd, chronoUnit);
if (timePassed + durationUntilEnd < duration) {
// task is not completed in current timetable item, so jump to the start of the next timetable item
if (model.isOutputLoggingOn()) {
// log idle during use
ResourceStatus status = ResourceStatus.IN_USE_IDLE;
long timeRelativeToStart = getTimeInstant(dateTime).getTimeRounded(timeUnit);
ResourceInfo info = new ResourceInfo(timeRelativeToStart, status, processInstance, nodeId);
for (ResourceObject obj : tuple.getResourceObjects()) {
String resourceType = obj.getResourceType();
String resourceId = obj.getId();
model.addResourceInfo(resourceType, resourceId, info);
}
ProcessNodeTransitionType transition = ProcessNodeTransitionType.PAUSE;
ProcessNodeInfo nodeInfo = new ProcessNodeInfo(nodeId, processScopeNodeId, source, timeRelativeToStart, taskName, resources, transition);
model.addNodeInfo(processModel, processInstance, nodeInfo);
}
index++;
if (index == timetable.size()) {
index = 0;
}
TimetableItem nextItem = timetable.get(index);
untilWeekday = nextItem.getWeekdayFrom();
untilTime = nextItem.getBeginTime();
dateTime = getNextZonedDateTime(dateTime, untilWeekday, untilTime);
if (model.isOutputLoggingOn()) {
// log back to work
ResourceStatus status = ResourceStatus.IN_USE;
long timeRelativeToStart = getTimeInstant(dateTime).getTimeRounded(timeUnit);
ResourceInfo info = new ResourceInfo(timeRelativeToStart, status, processInstance, nodeId);
for (ResourceObject obj : tuple.getResourceObjects()) {
String resourceType = obj.getResourceType();
String resourceId = obj.getId();
model.addResourceInfo(resourceType, resourceId, info);
}
ProcessNodeTransitionType transition = ProcessNodeTransitionType.RESUME;
ProcessNodeInfo nodeInfo = new ProcessNodeInfo(nodeId, processScopeNodeId, source, timeRelativeToStart, taskName, resources, transition);
model.addNodeInfo(processModel, processInstance, nodeInfo);
}
}
}
TimeInstant timeInstant = getTimeInstant(dateTime);
return timeInstant;
}
use of de.hpi.bpt.scylla.simulation.SimulationModel in project scylla by bptlab.
the class SimulationManager method run.
/**
* parses input, runs DesmoJ simulation experiment, writes BPS output logs
*/
public String run() {
try {
SAXBuilder builder = new SAXBuilder();
if (globalConfigurationFilename == null || globalConfigurationFilename.isEmpty()) {
throw new ScyllaValidationException("No global configuration provided.");
} else {
// parse global configuration XML
Document gcDoc = builder.build(globalConfigurationFilename);
Element gcRootElement = gcDoc.getRootElement();
GlobalConfigurationParser globalConfigurationParser = new GlobalConfigurationParser(this);
globalConfiguration = globalConfigurationParser.parse(gcDoc.getRootElement());
String fileNameWithoutExtension = // filename.lastIndexOf("\\") +
globalConfigurationFilename.substring(// 1,
globalConfigurationFilename.lastIndexOf(Scylla.FILEDELIM) + 1, globalConfigurationFilename.lastIndexOf(".xml"));
globalConfiguration.setFileNameWithoutExtension(fileNameWithoutExtension);
// plugins to parse global configuration
GlobalConfigurationParserPluggable.runPlugins(this, globalConfiguration, gcRootElement);
DateTimeUtils.setZoneId(globalConfiguration.getZoneId());
}
CommonProcessElementsParser cpeParser = new CommonProcessElementsParser(this);
for (String filename : processModelFilenames) {
Document pmDoc = builder.build(filename);
Element pmRootElement = pmDoc.getRootElement();
// parse common process elements from XML (BPMN)
CommonProcessElements commonProcessElementsFromFile = cpeParser.parse(pmRootElement);
String fileNameWithoutExtension = // filename.lastIndexOf("\\") + 1,
filename.substring(filename.lastIndexOf(Scylla.FILEDELIM) + 1, filename.lastIndexOf(".bpmn"));
commonProcessElementsFromFile.setBpmnFileNameWithoutExtension(fileNameWithoutExtension);
// plugins to parse common process elements
CommonProcessElementsParserPluggable.runPlugins(this, commonProcessElementsFromFile, pmRootElement);
// parse process model(s) from XML (BPMN)
ProcessModelParser pmParser = new ProcessModelParser(this);
pmParser.setCommonProcessElements(commonProcessElementsFromFile);
ProcessModel processModelFromFile = pmParser.parse(pmDoc.getRootElement());
String processId = processModelFromFile.getId();
if (processModels.containsKey(processId)) {
throw new ScyllaValidationException("Duplicate process model with id " + processId + ".");
}
// plugins to parse process model(s)
ProcessModelParserPluggable.runPlugins(this, processModelFromFile, pmRootElement);
processModels.put(processId, processModelFromFile);
commonProcessElements.put(processId, commonProcessElementsFromFile);
}
SimulationConfigurationParser simParser = new SimulationConfigurationParser(this);
// parse each simulation configuration XML
for (String filename : simulationConfigurationFilenames) {
Document scDoc = builder.build(filename);
SimulationConfiguration simulationConfigurationFromFile = simParser.parse(scDoc.getRootElement());
String processId = simulationConfigurationFromFile.getProcessModel().getId();
if (simulationConfigurations.containsKey(processId)) {
throw new ScyllaValidationException("Multiple simulation configurations for process with id " + processId + ".");
}
// plugins to parse simulation configuration
SimulationConfigurationParserPluggable.runPlugins(this, simulationConfigurationFromFile, scDoc);
simulationConfigurations.put(processId, simulationConfigurationFromFile);
}
} catch (JDOMException | IOException | ScyllaValidationException e) {
DebugLogger.error(e.getMessage());
e.printStackTrace();
}
// TODO validate resources in process models (i.e. check if they are all covered in resource data)
TimeUnit epsilon = TimeUnit.SECONDS;
DateTimeUtils.setReferenceTimeUnit(epsilon);
String experimentName = Long.toString((new Date()).getTime());
Experiment.setEpsilon(epsilon);
Experiment exp = new Experiment(experimentName, experimentOutputFolder);
exp.setShowProgressBar(false);
// XXX each simulation configuration may have its own seed
Long randomSeed = globalConfiguration.getRandomSeed();
if (randomSeed != null) {
exp.setSeedGenerator(randomSeed);
} else {
exp.setSeedGenerator((new Random()).nextLong());
}
SimulationModel sm = new SimulationModel(null, globalConfiguration, commonProcessElements, processModels, simulationConfigurations, enableBpsLogging, enableDesLogging);
sm.connectToExperiment(exp);
int lambda = 1;
if (sm.getEndDateTime() != null) {
// have to use time which is slightly after intended end time (epsilon)
// otherwise the AbortProcessSimulationEvent(s) may not fire
long simulationDuration = DateTimeUtils.getDuration(sm.getStartDateTime(), sm.getEndDateTime());
TimeInstant simulationTimeInstant = new TimeInstant(simulationDuration + lambda, epsilon);
exp.stop(simulationTimeInstant);
exp.tracePeriod(new TimeInstant(0), simulationTimeInstant);
exp.debugPeriod(new TimeInstant(0), simulationTimeInstant);
} else {
exp.traceOn(new TimeInstant(0));
exp.debugOn(new TimeInstant(0));
}
if (!enableDesLogging) {
exp.debugOff(new TimeInstant(0));
exp.traceOff(new TimeInstant(0));
}
exp.start();
exp.report();
exp.finish();
try {
// log process execution
// log resources, process, tasks
StringBuilder strb = new StringBuilder(globalConfigurationFilename.substring(0, globalConfigurationFilename.lastIndexOf(Scylla.FILEDELIM) + 1));
outputPath = strb.substring(0, strb.lastIndexOf(Scylla.FILEDELIM) + 1) + "output_" + new SimpleDateFormat("yy_MM_dd_HH_mm_ss").format(new Date()) + Scylla.FILEDELIM;
File outputPathFolder = new File(outputPath);
if (!outputPathFolder.exists())
outputPathFolder.mkdir();
OutputLoggerPluggable.runPlugins(sm, outputPath);
} catch (IOException e) {
e.printStackTrace();
}
return outputPath;
}
use of de.hpi.bpt.scylla.simulation.SimulationModel in project scylla by bptlab.
the class BatchPluginUtils method logTaskEventForNonResponsiblePI.
// If the execution type is parallel this makes the entry for the not really simulated process instances for tasks
void logTaskEventForNonResponsiblePI(TaskEvent event, ProcessInstance processInstance) throws ScyllaRuntimeException {
ProcessInstance parentProcessInstance = processInstance.getParent();
if (parentProcessInstance != null) {
ProcessModel processModel = processInstance.getProcessModel();
int parentNodeId = processModel.getNodeIdInParent();
BatchPluginUtils pluginInstance = BatchPluginUtils.getInstance();
BatchCluster cluster = pluginInstance.getRunningCluster(parentProcessInstance, parentNodeId);
if (cluster != null && cluster.getBatchActivity().getExecutionType().equals(BatchClusterExecutionType.PARALLEL)) {
SimulationModel model = (SimulationModel) event.getModel();
long timestamp = Math.round(model.presentTime().getTimeRounded(DateTimeUtils.getReferenceTimeUnit()));
String taskName = event.getDisplayName();
int nodeId = event.getNodeId();
String processScopeNodeId = SimulationUtils.getProcessScopeNodeId(processModel, nodeId);
String source = event.getSource();
ProcessNodeTransitionType transition;
Set<String> resources = new HashSet<String>();
if (event instanceof TaskEnableEvent) {
transition = ProcessNodeTransitionType.ENABLE;
} else if (event instanceof TaskBeginEvent) {
transition = ProcessNodeTransitionType.BEGIN;
Set<ResourceObject> resourceObjects = processInstance.getAssignedResources().get(source).getResourceObjects();
for (ResourceObject res : resourceObjects) {
String resourceName = res.getResourceType() + "_" + res.getId();
resources.add(resourceName);
}
tasksAndResources.put(source, resources);
} else if (event instanceof TaskCancelEvent) {
transition = ProcessNodeTransitionType.CANCEL;
resources = tasksAndResources.get(source);
tasksAndResources.remove(source);
} else if (event instanceof TaskTerminateEvent) {
transition = ProcessNodeTransitionType.TERMINATE;
resources = tasksAndResources.get(source);
tasksAndResources.remove(source);
} else {
throw new ScyllaRuntimeException("Task event type not supported.");
}
int sourceSuffix = 0;
List<ProcessInstance> processInstances = cluster.getProcessInstances();
for (ProcessInstance pi : processInstances) {
if (!processInstance.getParent().equals(pi)) {
// the source attribute comes from an event, but we did not really simulate the events for the
// non-responsible process instances, so we mock a source attribute value
String mockSource = source + "##" + ++sourceSuffix;
ProcessNodeInfo info;
info = new ProcessNodeInfo(nodeId, processScopeNodeId, mockSource, timestamp, taskName, resources, transition);
model.addNodeInfo(processModel, pi, info);
}
}
}
}
}
use of de.hpi.bpt.scylla.simulation.SimulationModel in project scylla by bptlab.
the class BatchPluginUtils method logBPMNEventForNonResponsiblePI.
// If the execution type is parallel this makes the entry for the not really simulated process instances for events
void logBPMNEventForNonResponsiblePI(BPMNEvent event, ProcessInstance processInstance) {
ProcessInstance parentProcessInstance = processInstance.getParent();
if (parentProcessInstance != null) {
ProcessModel processModel = processInstance.getProcessModel();
int parentNodeId = processModel.getNodeIdInParent();
BatchPluginUtils pluginInstance = BatchPluginUtils.getInstance();
BatchCluster cluster = pluginInstance.getRunningCluster(parentProcessInstance, parentNodeId);
if (cluster != null && cluster.hasExecutionType(BatchClusterExecutionType.PARALLEL)) {
SimulationModel model = (SimulationModel) event.getModel();
long timestamp = Math.round(model.presentTime().getTimeRounded(DateTimeUtils.getReferenceTimeUnit()));
Set<String> resources = new HashSet<String>();
String taskName = event.getDisplayName();
int nodeId = event.getNodeId();
String processScopeNodeId = SimulationUtils.getProcessScopeNodeId(processModel, nodeId);
String source = event.getSource();
int sourceSuffix = 0;
List<ProcessInstance> processInstances = cluster.getProcessInstances();
for (ProcessInstance pi : processInstances) {
if (!processInstance.getParent().equals(pi)) {
// the source attribute comes from an event, but we did not really simulate the events for the
// non-responsible process instances, so we mock a source attribute value
String mockSource = source + "##" + ++sourceSuffix;
ProcessNodeInfo info;
info = new ProcessNodeInfo(nodeId, processScopeNodeId, mockSource, timestamp, taskName, resources, ProcessNodeTransitionType.EVENT_BEGIN);
model.addNodeInfo(processModel, pi, info);
info = new ProcessNodeInfo(nodeId, processScopeNodeId, mockSource, timestamp, taskName, resources, ProcessNodeTransitionType.EVENT_TERMINATE);
model.addNodeInfo(processModel, pi, info);
}
}
}
}
}
Aggregations