Search in sources :

Example 16 with TimeInstant

use of desmoj.core.simulator.TimeInstant in project scylla by bptlab.

the class TaskBeginEvent method eventRoutine.

@Override
public void eventRoutine(ProcessInstance processInstance) throws SuspendExecution {
    super.eventRoutine(processInstance);
    SimulationModel model = (SimulationModel) getModel();
    TimeInstant currentSimulationTime = model.presentTime();
    ProcessModel processModel = processInstance.getProcessModel();
    ProcessModel subProcess = processModel.getSubProcesses().get(nodeId);
    TaskType type = processModel.getTasks().get(nodeId);
    String message = null;
    if (subProcess != null) {
        message = "Begin Subprocess: " + displayName;
    } else if (type == TaskType.DEFAULT) {
        message = "Begin Default Task: " + displayName;
    } else if (type == TaskType.SERVICE) {
        message = "Begin Service Task: " + displayName;
    } else if (type == TaskType.SEND) {
        message = "Begin Send Task: " + displayName;
    } else if (type == TaskType.RECEIVE) {
        message = "Begin Receive Task: " + displayName;
    } else if (type == TaskType.USER) {
        message = "Begin User Task: " + displayName;
    } else if (type == TaskType.MANUAL) {
        message = "Begin Manual Task: " + displayName;
    } else if (type == TaskType.BUSINESS_RULE) {
        message = "Begin Business Rule: " + displayName;
    } else if (type == TaskType.SCRIPT) {
        message = "Begin Script Task: " + displayName;
    } else {
        SimulationUtils.sendElementNotSupportedTraceNote(model, processModel, displayName, nodeId);
        SimulationUtils.abort(model, processInstance, nodeId, traceIsOn());
        return;
    }
    sendTraceNote(message);
    try {
        double duration = pSimComponents.getDistributionSample(nodeId);
        TimeUnit unit = pSimComponents.getDistributionTimeUnit(nodeId);
        ScyllaEvent event = new TaskTerminateEvent(model, source, currentSimulationTime, pSimComponents, processInstance, nodeId);
        TimeSpan timeSpan = new TimeSpan(duration, unit);
        ResourceObjectTuple tuple = processInstance.getAssignedResources().get(source);
        TimeInstant nextEventTime = DateTimeUtils.getTaskTerminationTime(timeSpan, currentSimulationTime, tuple, event);
        timeSpan = new TimeSpan(nextEventTime.getTimeAsDouble() - currentSimulationTime.getTimeAsDouble());
        int index = getNewEventIndex();
        nextEventMap.put(index, event);
        timeSpanToNextEventMap.put(index, timeSpan);
        TaskBeginEventPluggable.runPlugins(this, processInstance);
        scheduleNextEvents();
    } catch (ScyllaRuntimeException e) {
        System.err.println(e.getMessage());
        e.printStackTrace();
        SimulationUtils.abort(model, processInstance, nodeId, traceIsOn());
        return;
    }
}
Also used : ScyllaRuntimeException(de.hpi.bpt.scylla.exception.ScyllaRuntimeException) ProcessModel(de.hpi.bpt.scylla.model.process.ProcessModel) TimeSpan(desmoj.core.simulator.TimeSpan) ResourceObjectTuple(de.hpi.bpt.scylla.simulation.ResourceObjectTuple) TaskType(de.hpi.bpt.scylla.model.process.node.TaskType) TimeUnit(java.util.concurrent.TimeUnit) SimulationModel(de.hpi.bpt.scylla.simulation.SimulationModel) TimeInstant(desmoj.core.simulator.TimeInstant)

Example 17 with TimeInstant

use of desmoj.core.simulator.TimeInstant in project scylla by bptlab.

the class TaskEnableEvent method eventRoutine.

@Override
public void eventRoutine(ProcessInstance processInstance) throws SuspendExecution {
    super.eventRoutine(processInstance);
    SimulationModel model = (SimulationModel) getModel();
    source = getName();
    TimeInstant currentSimulationTime = model.presentTime();
    ProcessModel processModel = processInstance.getProcessModel();
    // int processInstanceId = processInstance.getId();
    ProcessModel subProcess = processModel.getSubProcesses().get(nodeId);
    TaskType type = processModel.getTasks().get(nodeId);
    String message = null;
    if (subProcess != null) {
        message = "Enable Subprocess: " + displayName;
    } else if (type == TaskType.DEFAULT) {
        message = "Enable Default Task: " + displayName;
    } else if (type == TaskType.SERVICE) {
        message = "Enable Service Task: " + displayName;
    } else if (type == TaskType.SEND) {
        message = "Enable Send Task: " + displayName;
    } else if (type == TaskType.RECEIVE) {
        message = "Enable Receive Task: " + displayName;
    } else if (type == TaskType.USER) {
        message = "Enable User Task: " + displayName;
    } else if (type == TaskType.MANUAL) {
        message = "Enable Manual Task: " + displayName;
    } else if (type == TaskType.BUSINESS_RULE) {
        message = "Enable Business Rule: " + displayName;
    } else if (type == TaskType.SCRIPT) {
        message = "Enable Script Task: " + displayName;
    } else {
        SimulationUtils.sendElementNotSupportedTraceNote(model, processModel, displayName, nodeId);
        SimulationUtils.abort(model, processInstance, nodeId, traceIsOn());
        return;
    }
    sendTraceNote(message);
    try {
        // poll available resources and if not available, put TaskBeginEvent on hold
        ScyllaEvent event = new TaskBeginEvent(model, source, currentSimulationTime, pSimComponents, processInstance, nodeId);
        ResourceObjectTuple resources = QueueManager.getResourcesForEvent(model, event);
        if (resources == null) {
            QueueManager.addToEventQueues(model, event);
            sendTraceNote("Not enough resources available, task " + displayName + " is put in a queue.");
        } else {
            QueueManager.assignResourcesToEvent(model, event, resources);
            TimeSpan timeSpan = new TimeSpan(0);
            int index = getNewEventIndex();
            nextEventMap.put(index, event);
            timeSpanToNextEventMap.put(index, timeSpan);
        }
        TaskEnableEventPluggable.runPlugins(this, processInstance);
        scheduleNextEvents();
    } catch (ScyllaRuntimeException e) {
        DebugLogger.error(e.getMessage());
        DebugLogger.log("Simulation aborted.");
    }
}
Also used : ResourceObjectTuple(de.hpi.bpt.scylla.simulation.ResourceObjectTuple) TimeSpan(desmoj.core.simulator.TimeSpan) ScyllaRuntimeException(de.hpi.bpt.scylla.exception.ScyllaRuntimeException) ProcessModel(de.hpi.bpt.scylla.model.process.ProcessModel) TaskType(de.hpi.bpt.scylla.model.process.node.TaskType) SimulationModel(de.hpi.bpt.scylla.simulation.SimulationModel) TimeInstant(desmoj.core.simulator.TimeInstant)

Example 18 with TimeInstant

use of desmoj.core.simulator.TimeInstant in project scylla by bptlab.

the class DateTimeUtils method getTimeInstant.

public static TimeInstant getTimeInstant(ZonedDateTime dateTime) {
    long timeRelativeToStart = chronoUnit.between(startDateTime, dateTime);
    TimeInstant timeInstant = new TimeInstant(timeRelativeToStart, timeUnit);
    return timeInstant;
}
Also used : TimeInstant(desmoj.core.simulator.TimeInstant)

Example 19 with TimeInstant

use of desmoj.core.simulator.TimeInstant 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;
}
Also used : ProcessModel(de.hpi.bpt.scylla.model.process.ProcessModel) ResourceObject(de.hpi.bpt.scylla.simulation.ResourceObject) DayOfWeek(java.time.DayOfWeek) ResourceInfo(de.hpi.bpt.scylla.logger.ResourceInfo) LocalTime(java.time.LocalTime) ProcessNodeInfo(de.hpi.bpt.scylla.logger.ProcessNodeInfo) ZonedDateTime(java.time.ZonedDateTime) ProcessNodeTransitionType(de.hpi.bpt.scylla.logger.ProcessNodeTransitionType) ResourceStatus(de.hpi.bpt.scylla.logger.ResourceStatus) ProcessInstance(de.hpi.bpt.scylla.simulation.ProcessInstance) TimetableItem(de.hpi.bpt.scylla.model.global.resource.TimetableItem) SimulationModel(de.hpi.bpt.scylla.simulation.SimulationModel) TimeInstant(desmoj.core.simulator.TimeInstant) HashSet(java.util.HashSet)

Example 20 with TimeInstant

use of desmoj.core.simulator.TimeInstant 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;
}
Also used : ProcessModel(de.hpi.bpt.scylla.model.process.ProcessModel) Element(org.jdom2.Element) Document(org.jdom2.Document) ScyllaValidationException(de.hpi.bpt.scylla.exception.ScyllaValidationException) Random(java.util.Random) TimeUnit(java.util.concurrent.TimeUnit) SimulationConfigurationParser(de.hpi.bpt.scylla.parser.SimulationConfigurationParser) CommonProcessElements(de.hpi.bpt.scylla.model.process.CommonProcessElements) SAXBuilder(org.jdom2.input.SAXBuilder) Experiment(desmoj.core.simulator.Experiment) IOException(java.io.IOException) JDOMException(org.jdom2.JDOMException) CommonProcessElementsParser(de.hpi.bpt.scylla.parser.CommonProcessElementsParser) Date(java.util.Date) SimulationConfiguration(de.hpi.bpt.scylla.model.configuration.SimulationConfiguration) ProcessModelParser(de.hpi.bpt.scylla.parser.ProcessModelParser) GlobalConfigurationParser(de.hpi.bpt.scylla.parser.GlobalConfigurationParser) SimpleDateFormat(java.text.SimpleDateFormat) File(java.io.File) SimulationModel(de.hpi.bpt.scylla.simulation.SimulationModel) TimeInstant(desmoj.core.simulator.TimeInstant)

Aggregations

TimeInstant (desmoj.core.simulator.TimeInstant)21 ProcessModel (de.hpi.bpt.scylla.model.process.ProcessModel)12 SimulationModel (de.hpi.bpt.scylla.simulation.SimulationModel)12 TimeSpan (desmoj.core.simulator.TimeSpan)10 TimeUnit (java.util.concurrent.TimeUnit)10 ScyllaRuntimeException (de.hpi.bpt.scylla.exception.ScyllaRuntimeException)8 ProcessInstance (de.hpi.bpt.scylla.simulation.ProcessInstance)8 ProcessSimulationComponents (de.hpi.bpt.scylla.simulation.ProcessSimulationComponents)6 List (java.util.List)6 ScyllaEvent (de.hpi.bpt.scylla.simulation.event.ScyllaEvent)5 ArrayList (java.util.ArrayList)5 HashSet (java.util.HashSet)5 Map (java.util.Map)5 ResourceObject (de.hpi.bpt.scylla.simulation.ResourceObject)4 HashMap (java.util.HashMap)4 ProcessNodeInfo (de.hpi.bpt.scylla.logger.ProcessNodeInfo)3 ProcessNodeTransitionType (de.hpi.bpt.scylla.logger.ProcessNodeTransitionType)3 ResourceInfo (de.hpi.bpt.scylla.logger.ResourceInfo)3 ResourceStatus (de.hpi.bpt.scylla.logger.ResourceStatus)3 MultipleStartNodesException (de.hpi.bpt.scylla.model.process.graph.exception.MultipleStartNodesException)3