From e6cb997b2baadec318357d48ee8fb3e2835ce437 Mon Sep 17 00:00:00 2001 From: Jaroslav Keznikl Date: Thu, 6 Feb 2014 14:54:21 +0100 Subject: [PATCH] support for non-periodic events & property-based jdeeco setup in the sim --- .../cuni/mff/d3s/deeco/DeecoProperties.java | 13 ++ .../deeco/model/runtime/api/TimeTrigger.java | 78 +++++++ .../model/runtime/impl/TimeTriggerImpl.java | 217 ++++++++++++++++++ .../mff/d3s/deeco/network/PublisherTask.java | 4 +- .../scheduler/SingleThreadedScheduler.java | 14 -- .../d3s/jdeeco/simulation/demo/Leader.java | 1 - .../mff/d3s/jdeeco/simulation/demo/Main.java | 12 +- .../demo/MemberDataAggregation.java | 3 - .../d3s/jdeeco/simulation/jni/JNITest.java | 8 +- .../cuni/mff/d3s/deeco/simulation/Host.java | 9 +- .../mff/d3s/deeco/simulation/Simulation.java | 6 +- .../simulation/SimulationRuntimeBuilder.java | 18 +- .../scheduler/SimulationScheduler.java | 46 ++-- 13 files changed, 370 insertions(+), 59 deletions(-) create mode 100644 jdeeco-core/src/cz/cuni/mff/d3s/deeco/DeecoProperties.java create mode 100644 jdeeco-core/src/cz/cuni/mff/d3s/deeco/model/runtime/api/TimeTrigger.java create mode 100644 jdeeco-core/src/cz/cuni/mff/d3s/deeco/model/runtime/impl/TimeTriggerImpl.java diff --git a/jdeeco-core/src/cz/cuni/mff/d3s/deeco/DeecoProperties.java b/jdeeco-core/src/cz/cuni/mff/d3s/deeco/DeecoProperties.java new file mode 100644 index 000000000..10521cb35 --- /dev/null +++ b/jdeeco-core/src/cz/cuni/mff/d3s/deeco/DeecoProperties.java @@ -0,0 +1,13 @@ +package cz.cuni.mff.d3s.deeco; + +public final class DeecoProperties { + public static final String PACKET_SIZE = "deeco.publish.packetsize"; + public static final String PUBLISHING_PERIOD = "deeco.publish.period"; + public static final String USE_INDIVIDUAL_KNOWLEDGE_PUBLISHING = "deeco.publish.individual"; + public static final String DISABLE_BOUNDARY_CONDITIONS = "deeco.boundary.disable"; + public static final String DISABLE_GOSSIP_CONDITION = "deeco.gossipcnd.disable"; + public static final String GOSSIP_CONDITION_RSSI = "deeco.gossipcnd.rssi"; + public static final String MESSAGE_CACHE_DEADLINE = "deeco.receive.cache.deadline"; + public static final String MESSAGE_CACHE_WIPE_PERIOD = "deeco.receive.cache.period"; + +} diff --git a/jdeeco-core/src/cz/cuni/mff/d3s/deeco/model/runtime/api/TimeTrigger.java b/jdeeco-core/src/cz/cuni/mff/d3s/deeco/model/runtime/api/TimeTrigger.java new file mode 100644 index 000000000..869af8b6d --- /dev/null +++ b/jdeeco-core/src/cz/cuni/mff/d3s/deeco/model/runtime/api/TimeTrigger.java @@ -0,0 +1,78 @@ +/** + */ +package cz.cuni.mff.d3s.deeco.model.runtime.api; + + +/** + * + * A representation of the model object 'Time Trigger'. + * + * + *

+ * The following features are supported: + *

+ *

+ * + * @see cz.cuni.mff.d3s.deeco.model.runtime.meta.RuntimeMetadataPackage#getTimeTrigger() + * @model + * @generated + */ +public interface TimeTrigger extends Trigger { + /** + * Returns the value of the 'Period' attribute. + * The default value is "0". + * + *

+ * If the meaning of the 'Period' attribute isn't clear, + * there really should be more of a description here... + *

+ * + * @return the value of the 'Period' attribute. + * @see #setPeriod(long) + * @see cz.cuni.mff.d3s.deeco.model.runtime.meta.RuntimeMetadataPackage#getTimeTrigger_Period() + * @model default="0" required="true" + * @generated + */ + long getPeriod(); + + /** + * Sets the value of the '{@link cz.cuni.mff.d3s.deeco.model.runtime.api.TimeTrigger#getPeriod Period}' attribute. + * + * + * @param value the new value of the 'Period' attribute. + * @see #getPeriod() + * @generated + */ + void setPeriod(long value); + + /** + * Returns the value of the 'Offset' attribute. + * The default value is "0". + * + *

+ * If the meaning of the 'Offset' attribute isn't clear, + * there really should be more of a description here... + *

+ * + * @return the value of the 'Offset' attribute. + * @see #setOffset(long) + * @see cz.cuni.mff.d3s.deeco.model.runtime.meta.RuntimeMetadataPackage#getTimeTrigger_Offset() + * @model default="0" required="true" + * @generated + */ + long getOffset(); + + /** + * Sets the value of the '{@link cz.cuni.mff.d3s.deeco.model.runtime.api.TimeTrigger#getOffset Offset}' attribute. + * + * + * @param value the new value of the 'Offset' attribute. + * @see #getOffset() + * @generated + */ + void setOffset(long value); + +} // TimeTrigger diff --git a/jdeeco-core/src/cz/cuni/mff/d3s/deeco/model/runtime/impl/TimeTriggerImpl.java b/jdeeco-core/src/cz/cuni/mff/d3s/deeco/model/runtime/impl/TimeTriggerImpl.java new file mode 100644 index 000000000..aa1ed3813 --- /dev/null +++ b/jdeeco-core/src/cz/cuni/mff/d3s/deeco/model/runtime/impl/TimeTriggerImpl.java @@ -0,0 +1,217 @@ +/** + */ +package cz.cuni.mff.d3s.deeco.model.runtime.impl; + +import cz.cuni.mff.d3s.deeco.model.runtime.api.TimeTrigger; + +import cz.cuni.mff.d3s.deeco.model.runtime.meta.RuntimeMetadataPackage; + +import org.eclipse.emf.common.notify.Notification; + +import org.eclipse.emf.ecore.EClass; + +import org.eclipse.emf.ecore.impl.ENotificationImpl; + +/** + * + * An implementation of the model object 'Time Trigger'. + * + *

+ * The following features are implemented: + *

+ *

+ * + * @generated + */ +public class TimeTriggerImpl extends TriggerImpl implements TimeTrigger { + /** + * The default value of the '{@link #getPeriod() Period}' attribute. + * + * + * @see #getPeriod() + * @generated + * @ordered + */ + protected static final long PERIOD_EDEFAULT = 0L; + + /** + * The cached value of the '{@link #getPeriod() Period}' attribute. + * + * + * @see #getPeriod() + * @generated + * @ordered + */ + protected long period = PERIOD_EDEFAULT; + + /** + * The default value of the '{@link #getOffset() Offset}' attribute. + * + * + * @see #getOffset() + * @generated + * @ordered + */ + protected static final long OFFSET_EDEFAULT = 0L; + + /** + * The cached value of the '{@link #getOffset() Offset}' attribute. + * + * + * @see #getOffset() + * @generated + * @ordered + */ + protected long offset = OFFSET_EDEFAULT; + + /** + * + * + * @generated + */ + protected TimeTriggerImpl() { + super(); + } + + /** + * + * + * @generated + */ + @Override + protected EClass eStaticClass() { + return RuntimeMetadataPackage.Literals.TIME_TRIGGER; + } + + /** + * + * + * @generated + */ + public long getPeriod() { + return period; + } + + /** + * + * + * @generated + */ + public void setPeriod(long newPeriod) { + long oldPeriod = period; + period = newPeriod; + if (eNotificationRequired()) + eNotify(new ENotificationImpl(this, Notification.SET, RuntimeMetadataPackage.TIME_TRIGGER__PERIOD, oldPeriod, period)); + } + + /** + * + * + * @generated + */ + public long getOffset() { + return offset; + } + + /** + * + * + * @generated + */ + public void setOffset(long newOffset) { + long oldOffset = offset; + offset = newOffset; + if (eNotificationRequired()) + eNotify(new ENotificationImpl(this, Notification.SET, RuntimeMetadataPackage.TIME_TRIGGER__OFFSET, oldOffset, offset)); + } + + /** + * + * + * @generated + */ + @Override + public Object eGet(int featureID, boolean resolve, boolean coreType) { + switch (featureID) { + case RuntimeMetadataPackage.TIME_TRIGGER__PERIOD: + return getPeriod(); + case RuntimeMetadataPackage.TIME_TRIGGER__OFFSET: + return getOffset(); + } + return super.eGet(featureID, resolve, coreType); + } + + /** + * + * + * @generated + */ + @Override + public void eSet(int featureID, Object newValue) { + switch (featureID) { + case RuntimeMetadataPackage.TIME_TRIGGER__PERIOD: + setPeriod((Long)newValue); + return; + case RuntimeMetadataPackage.TIME_TRIGGER__OFFSET: + setOffset((Long)newValue); + return; + } + super.eSet(featureID, newValue); + } + + /** + * + * + * @generated + */ + @Override + public void eUnset(int featureID) { + switch (featureID) { + case RuntimeMetadataPackage.TIME_TRIGGER__PERIOD: + setPeriod(PERIOD_EDEFAULT); + return; + case RuntimeMetadataPackage.TIME_TRIGGER__OFFSET: + setOffset(OFFSET_EDEFAULT); + return; + } + super.eUnset(featureID); + } + + /** + * + * + * @generated + */ + @Override + public boolean eIsSet(int featureID) { + switch (featureID) { + case RuntimeMetadataPackage.TIME_TRIGGER__PERIOD: + return period != PERIOD_EDEFAULT; + case RuntimeMetadataPackage.TIME_TRIGGER__OFFSET: + return offset != OFFSET_EDEFAULT; + } + return super.eIsSet(featureID); + } + + /** + * + * + * @generated + */ + @Override + public String toString() { + if (eIsProxy()) return super.toString(); + + StringBuffer result = new StringBuffer(super.toString()); + result.append(" (period: "); + result.append(period); + result.append(", offset: "); + result.append(offset); + result.append(')'); + return result.toString(); + } + +} //TimeTriggerImpl diff --git a/jdeeco-core/src/cz/cuni/mff/d3s/deeco/network/PublisherTask.java b/jdeeco-core/src/cz/cuni/mff/d3s/deeco/network/PublisherTask.java index 15fb71472..eb2aca6d9 100644 --- a/jdeeco-core/src/cz/cuni/mff/d3s/deeco/network/PublisherTask.java +++ b/jdeeco-core/src/cz/cuni/mff/d3s/deeco/network/PublisherTask.java @@ -43,8 +43,10 @@ private static class PublisherTrigger extends TimeTriggerExt { public PublisherTrigger(long period, long seed) { super(); setPeriod(period); - setOffset(0); random = new Random(seed); + // for experiments, publisher task has a random start offset up to its period + setOffset(random.nextInt((int) period)); + } @Override diff --git a/jdeeco-core/src/cz/cuni/mff/d3s/deeco/scheduler/SingleThreadedScheduler.java b/jdeeco-core/src/cz/cuni/mff/d3s/deeco/scheduler/SingleThreadedScheduler.java index fb9c507bf..435f888e0 100644 --- a/jdeeco-core/src/cz/cuni/mff/d3s/deeco/scheduler/SingleThreadedScheduler.java +++ b/jdeeco-core/src/cz/cuni/mff/d3s/deeco/scheduler/SingleThreadedScheduler.java @@ -233,20 +233,6 @@ void scheduleAfter(SchedulerEvent event, long delay) { queue.notify(); } -// -// /** -// * Note that this method has to be explicitly protected by queue's monitor! -// */ -// void scheduleNow(SchedulerEvent event, long period) { -// event.nextExecutionTime = System.currentTimeMillis(); // start immediately -// event.period = period; -// event.state = SchedulerEvent.SCHEDULED; -// -// queue.add(event); -// if (queue.getMin() == event) -// queue.notify(); -// } - @Override public void removeTask(Task task) { diff --git a/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/Leader.java b/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/Leader.java index f46cd96c9..395db02fd 100644 --- a/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/Leader.java +++ b/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/Leader.java @@ -22,7 +22,6 @@ import cz.cuni.mff.d3s.deeco.annotations.In; import cz.cuni.mff.d3s.deeco.annotations.InOut; -import cz.cuni.mff.d3s.deeco.annotations.Out; import cz.cuni.mff.d3s.deeco.annotations.PeriodicScheduling; import cz.cuni.mff.d3s.deeco.annotations.Process; import cz.cuni.mff.d3s.deeco.annotations.TriggerOnChange; diff --git a/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/Main.java b/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/Main.java index 83a65d645..50f214a20 100644 --- a/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/Main.java +++ b/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/Main.java @@ -28,10 +28,6 @@ */ public class Main { - static double POSITION_FACTOR = 1; - static int PACKET_SIZE = 2000; - static int PUBLISHING_PERIOD = 1000; - static String OMNET_CONFIG_TEMPLATE = "omnetpp.ini.templ"; static String OMNET_CONFIG_PATH = "omnetpp.ini"; @@ -80,22 +76,22 @@ public static void main(String[] args) throws AnnotationProcessorException, IOEx omnetConfig.append(String.format( "**.node[%s].mobility.initialX = %dm\n", - i, (int) (component.position.x * POSITION_FACTOR))); + i, (int) (component.position.x))); omnetConfig.append(String.format( "**.node[%s].mobility.initialY = %dm\n", - i, (int) (component.position.y * POSITION_FACTOR))); + i, (int) (component.position.y))); omnetConfig.append(String.format( "**.node[%s].mobility.initialZ = 0m\n", i)); omnetConfig.append(String.format( "**.node[%s].appl.id = \"%s\"\n\n", i, component.id)); - Host host = sim.getHost(component.id, PACKET_SIZE); + Host host = sim.getHost(component.id); hosts.add(host); // there is only one component instance model.getComponentInstances().get(0).getInternalData().put(PositionAwareComponent.HOST_REFERENCE, host); - RuntimeFramework runtime = builder.build(host, model, PUBLISHING_PERIOD); + RuntimeFramework runtime = builder.build(host, model); runtimes.add(runtime); runtime.start(); i++; diff --git a/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/MemberDataAggregation.java b/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/MemberDataAggregation.java index 9f18a78e5..f1da0fd72 100644 --- a/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/MemberDataAggregation.java +++ b/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/MemberDataAggregation.java @@ -41,8 +41,6 @@ @PeriodicScheduling(1000) public class MemberDataAggregation { - private static final long serialVersionUID = 5991804902054860542L; - @Membership public static boolean membership( @In("member.teamId") String mteamId, @@ -70,7 +68,6 @@ public static void map(@In("member.id") String mId, @CommunicationBoundary public static boolean boundary(KnowledgeData data, ReadOnlyKnowledgeManager sender) throws KnowledgeNotFoundException { -// return true; KnowledgePath kpPosition = KnowledgePathBuilder.buildSimplePath("position"); KnowledgePath kpTeam = KnowledgePathBuilder.buildSimplePath("teamId"); //Position ownerPos = (Position) data.getKnowledge().getValue(kpPosition); diff --git a/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/jni/JNITest.java b/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/jni/JNITest.java index ca7f202b0..ad5f3b977 100644 --- a/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/jni/JNITest.java +++ b/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/jni/JNITest.java @@ -12,17 +12,17 @@ public static void main(String[] args) throws Exception { simulation.initialize(); //loads Library - Host h0 = simulation.getHost("0", 1000); + Host h0 = simulation.getHost("0"); KnowledgeDataManager kr = new KnowledgeDataManager(h0); kr.sendDummyData(); - Host h1 = simulation.getHost("1", 1000); + Host h1 = simulation.getHost("1"); kr = new KnowledgeDataManager(h1); - Host h2 = simulation.getHost("2", 1000); + Host h2 = simulation.getHost("2"); kr = new KnowledgeDataManager(h2); - Host h3 = simulation.getHost("3", 1000); + Host h3 = simulation.getHost("3"); kr = new KnowledgeDataManager(h3); simulation.run("Cmdenv", "omnetpp-jni.ini"); diff --git a/jdeeco-simulation/src/cz/cuni/mff/d3s/deeco/simulation/Host.java b/jdeeco-simulation/src/cz/cuni/mff/d3s/deeco/simulation/Host.java index 1992d0d95..ec3a0e6e1 100644 --- a/jdeeco-simulation/src/cz/cuni/mff/d3s/deeco/simulation/Host.java +++ b/jdeeco-simulation/src/cz/cuni/mff/d3s/deeco/simulation/Host.java @@ -13,6 +13,7 @@ * */ public class Host extends PacketSender implements CurrentTimeProvider { + private SimulationTimeEventListener timeEventListener = null; @@ -20,14 +21,16 @@ public class Host extends PacketSender implements CurrentTimeProvider { private final Simulation simulation; private final String id; - protected Host(Simulation simulation, String id, int packetSize) { - super(id, packetSize); + protected Host(Simulation simulation, String id) { + super(id); this.simulation = simulation; this.id = id; - this.packetReceiver = new PacketReceiver(id, packetSize); + this.packetReceiver = new PacketReceiver(id); this.packetReceiver.setCurrentTimeProvider(this); simulation.register(this, id); } + + public PacketReceiver getPacketReceiver() { return packetReceiver; diff --git a/jdeeco-simulation/src/cz/cuni/mff/d3s/deeco/simulation/Simulation.java b/jdeeco-simulation/src/cz/cuni/mff/d3s/deeco/simulation/Simulation.java index cd3d03b73..582d9ef22 100644 --- a/jdeeco-simulation/src/cz/cuni/mff/d3s/deeco/simulation/Simulation.java +++ b/jdeeco-simulation/src/cz/cuni/mff/d3s/deeco/simulation/Simulation.java @@ -62,13 +62,15 @@ public void initialize() { System.loadLibrary("libintegration"); } + + /** * Creates new instance of the {@link Host}. * * @return new host instance */ - public Host getHost(String id, int packetSize) { - return new Host(this, id, packetSize); + public Host getHost(String id) { + return new Host(this, id); } // Wrapper methods we may need them. diff --git a/jdeeco-simulation/src/cz/cuni/mff/d3s/deeco/simulation/SimulationRuntimeBuilder.java b/jdeeco-simulation/src/cz/cuni/mff/d3s/deeco/simulation/SimulationRuntimeBuilder.java index 234194815..1c29d85e3 100644 --- a/jdeeco-simulation/src/cz/cuni/mff/d3s/deeco/simulation/SimulationRuntimeBuilder.java +++ b/jdeeco-simulation/src/cz/cuni/mff/d3s/deeco/simulation/SimulationRuntimeBuilder.java @@ -3,9 +3,7 @@ import cz.cuni.mff.d3s.deeco.executor.Executor; import cz.cuni.mff.d3s.deeco.executor.SameThreadExecutor; import cz.cuni.mff.d3s.deeco.knowledge.KnowledgeManagerContainer; -import cz.cuni.mff.d3s.deeco.model.runtime.api.PeriodicTrigger; import cz.cuni.mff.d3s.deeco.model.runtime.api.RuntimeMetadata; -import cz.cuni.mff.d3s.deeco.model.runtime.meta.RuntimeMetadataFactory; import cz.cuni.mff.d3s.deeco.network.KnowledgeDataManager; import cz.cuni.mff.d3s.deeco.network.PublisherTask; import cz.cuni.mff.d3s.deeco.runtime.RuntimeFramework; @@ -15,8 +13,7 @@ public class SimulationRuntimeBuilder { - public RuntimeFramework build(Host host, RuntimeMetadata model, - long publishingPeriod) { + public RuntimeFramework build(Host host, RuntimeMetadata model) { if (model == null) { throw new IllegalArgumentException("Model must not be null"); } @@ -31,13 +28,22 @@ public RuntimeFramework build(Host host, RuntimeMetadata model, // Set up the host container KnowledgeManagerContainer container = new KnowledgeManagerContainer(); - KnowledgeDataManager kdManager = new KnowledgeDataManager(container, host, model.getEnsembleDefinitions(), host.getId(), scheduler); + KnowledgeDataManager kdManager = new KnowledgeDataManager( + container, + host, + model.getEnsembleDefinitions(), + host.getId(), + scheduler); // Bind KnowledgeDataReceiver with PacketDataReceiver host.getPacketReceiver().setKnowledgeDataReceiver(kdManager); // Set up the publisher task - PublisherTask publisherTask = new PublisherTask(scheduler, kdManager, publishingPeriod, host.getId()); + PublisherTask publisherTask = new PublisherTask( + scheduler, + kdManager, + host.getId()); + // Add publisher task to the scheduler scheduler.addTask(publisherTask); diff --git a/jdeeco-simulation/src/cz/cuni/mff/d3s/deeco/simulation/scheduler/SimulationScheduler.java b/jdeeco-simulation/src/cz/cuni/mff/d3s/deeco/simulation/scheduler/SimulationScheduler.java index cd3da56e4..62981fbf4 100644 --- a/jdeeco-simulation/src/cz/cuni/mff/d3s/deeco/simulation/scheduler/SimulationScheduler.java +++ b/jdeeco-simulation/src/cz/cuni/mff/d3s/deeco/simulation/scheduler/SimulationScheduler.java @@ -74,16 +74,12 @@ public void addTask(Task task) { throw new IllegalArgumentException("The task cannot be null"); if (allTasks.contains(task)) return; - if (task.getPeriodicTrigger() != null) { + if (task.getTimeTrigger() != null) { SchedulerEvent event = new SchedulerEvent(task, - task.getPeriodicTrigger()); - - // TODO: for experiments, every periodic task has a random start delay up to its period - long lastProcessExecutionTimeBackup = lastProcessExecutionTime; - lastProcessExecutionTime = rnd.nextInt((int) task.getPeriodicTrigger().getPeriod()); - scheduleNow(event, task.getPeriodicTrigger().getPeriod()); - lastProcessExecutionTime = lastProcessExecutionTimeBackup; + task.getTimeTrigger()); + scheduleAfter(event, task.getTimeTrigger().getOffset()); + periodicEvents.put(task, event); } task.setTriggerListener(new TaskTriggerListener() { @@ -96,7 +92,9 @@ public void triggered(Task task, Trigger trigger) { } if (isScheduled) { measureExecutionTime(); - scheduleNow(new SchedulerEvent(task, trigger), 0); + // schedule immediately, regardless the actual runtime of + // the process that triggered this trigger + scheduleAfter(new SchedulerEvent(task, trigger), 0); } } }); @@ -130,8 +128,12 @@ public void executionFailed(Task task, Exception e) { @Override public void executionCompleted(Task task) { measureExecutionTime(); - if (task.getPeriodicTrigger() != null && lastProcessExecutionTime > task.getPeriodicTrigger().getPeriod()) { - Log.e("Task " + task.toString() + " has greater actual execution time than its period (" + task.getPeriodicTrigger().getPeriod() + ")"); + if ((task.getTimeTrigger() != null) + && (task.getTimeTrigger().getPeriod() > 0) + && (lastProcessExecutionTime > task.getTimeTrigger().getPeriod())) { + Log.e("Periodic task " + task.toString() + + " has greater actual execution time than its period (" + + task.getTimeTrigger().getPeriod() + ")"); } registerNextExecution(); } @@ -153,17 +155,18 @@ public void at(long time) { //System.out.println("Scheduler " +host.getId()+" at: "+time+" called with queue: " + Arrays.toString(queue.toArray())); SchedulerEvent event; while ((event = queue.first()) != null) { - // if notified too early + // if notified too early (or already processed all events scheduled + // for the current time) if (event.nextExecutionTime > time) break; // The time is right to execute the next task pop(); - if (event.period != 0) { + if (event.periodic) { // schedule for the next period (the period might be variable, // that's we query the trigger) event.nextExecutionTime = event.nextExecutionTime - + event.executable.getPeriodicTrigger().getPeriod(); + + event.executable.getTimeTrigger().getPeriod(); push(event); } if (executor != null) { @@ -185,10 +188,19 @@ public long getCurrentTime() { // ------Private methods-------- - private void scheduleNow(SchedulerEvent event, long period) { - event.period = period; - event.nextExecutionTime = host.getCurrentTime() + lastProcessExecutionTime; +// private void scheduleNow(SchedulerEvent event, long period) { +// event.period = period; +// event.nextExecutionTime = host.getCurrentTime() + lastProcessExecutionTime; +// push(event); +// } + + /** + * Note that this method has to be explicitly protected by queue's monitor! + */ + void scheduleAfter(SchedulerEvent event, long delay) { + event.nextExecutionTime = host.getCurrentTime() + delay; push(event); + } private void registerNextExecution() {