summaryrefslogtreecommitdiff
path: root/src/main/java/events
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/events')
-rw-r--r--src/main/java/events/VSAbstractEvent.java98
-rw-r--r--src/main/java/events/implementations/VSLamportTimestampEvent.java119
-rw-r--r--src/main/java/events/implementations/VSProcessCrashEvent.java11
-rw-r--r--src/main/java/events/implementations/VSProcessRecoverEvent.java11
-rw-r--r--src/main/java/events/implementations/VSTimestampMonitorEvent.java184
-rw-r--r--src/main/java/events/implementations/VSTimestampTriggeredEvent.java264
-rw-r--r--src/main/java/events/implementations/VSVectorClockMonitor.java136
-rw-r--r--src/main/java/events/implementations/VSVectorTimestampEvent.java142
-rw-r--r--src/main/java/events/internal/VSAbstractInternalEvent.java5
-rw-r--r--src/main/java/events/internal/VSMessageReceiveEvent.java15
-rw-r--r--src/main/java/events/internal/VSProtocolEvent.java10
11 files changed, 992 insertions, 3 deletions
diff --git a/src/main/java/events/VSAbstractEvent.java b/src/main/java/events/VSAbstractEvent.java
index d11ccbd..37c3d59 100644
--- a/src/main/java/events/VSAbstractEvent.java
+++ b/src/main/java/events/VSAbstractEvent.java
@@ -19,6 +19,16 @@ import serialize.VSSerialize;
* @author Paul C. Buetow
*/
abstract public class VSAbstractEvent extends VSSerializablePrefs {
+ /** Event priority constants for task ordering */
+ public static final int PRIORITY_HIGHEST = -3; // Process recover events
+ public static final int PRIORITY_HIGH = -2; // Process crash events
+ public static final int PRIORITY_MEDIUM = -1; // Protocol events
+ public static final int PRIORITY_NORMAL = 0; // All other events
+
+ /** Class name prefix used by Java reflection */
+ private static final String CLASS_PREFIX = "class ";
+ private static final int CLASS_PREFIX_LENGTH = 6;
+
/** The prefs. */
public VSPrefs prefs;
@@ -32,6 +42,88 @@ abstract public class VSAbstractEvent extends VSSerializablePrefs {
private String eventClassname;
/**
+ * Check if this event is an internal event.
+ *
+ * @return true if this is an internal event
+ */
+ public boolean isInternalEvent() {
+ return false;
+ }
+
+ /**
+ * Check if this event is serializable.
+ *
+ * @return true if this event is serializable
+ */
+ public boolean isSerializable() {
+ return true;
+ }
+
+ /**
+ * Check if this event is a message receive event.
+ *
+ * @return true if this is a message receive event
+ */
+ public boolean isMessageReceiveEvent() {
+ return false;
+ }
+
+ /**
+ * Check if this event is a process recover event.
+ *
+ * @return true if this is a process recover event
+ */
+ public boolean isProcessRecoverEvent() {
+ return false;
+ }
+
+ /**
+ * Check if this event is a process crash event.
+ *
+ * @return true if this is a process crash event
+ */
+ public boolean isProcessCrashEvent() {
+ return false;
+ }
+
+ /**
+ * Check if this event is a protocol event.
+ *
+ * @return true if this is a protocol event
+ */
+ public boolean isProtocolEvent() {
+ return false;
+ }
+
+ /**
+ * Check if this event should trigger timestamp increases when executed.
+ *
+ * @return true if timestamps should be increased
+ */
+ public boolean shouldIncreaseTimestamps() {
+ return true;
+ }
+
+ /**
+ * Get the priority of this event for ordering in VSTask comparisons.
+ * Lower values have higher priority.
+ *
+ * @return the event priority
+ */
+ public int getEventPriority() {
+ return PRIORITY_NORMAL;
+ }
+
+ /**
+ * Check if this event is copyable.
+ *
+ * @return true if this event can be copied
+ */
+ public boolean isCopyable() {
+ return this instanceof VSCopyableEvent;
+ }
+
+ /**
* Creates a copy of the event and using a new process.
*
* @param theProcess The new process
@@ -43,7 +135,7 @@ abstract public class VSAbstractEvent extends VSSerializablePrefs {
if (theProcess == null)
theProcess = (VSInternalProcess) process;
- if (!(this instanceof VSCopyableEvent))
+ if (!isCopyable())
throw new VSEventNotCopyableException(
eventShortname + " (" + eventClassname + ")");
@@ -93,8 +185,8 @@ abstract public class VSAbstractEvent extends VSSerializablePrefs {
* @param eventClassname the new classname
*/
public final void setClassname(String eventClassname) {
- if (eventClassname.startsWith("class "))
- eventClassname = eventClassname.substring(6);
+ if (eventClassname.startsWith(CLASS_PREFIX))
+ eventClassname = eventClassname.substring(CLASS_PREFIX_LENGTH);
this.eventClassname = eventClassname;
}
diff --git a/src/main/java/events/implementations/VSLamportTimestampEvent.java b/src/main/java/events/implementations/VSLamportTimestampEvent.java
new file mode 100644
index 0000000..272ea06
--- /dev/null
+++ b/src/main/java/events/implementations/VSLamportTimestampEvent.java
@@ -0,0 +1,119 @@
+package events.implementations;
+
+import core.VSInternalProcess;
+
+/**
+ * Concrete implementation of a Lamport timestamp-triggered event.
+ * This event fires when a specific Lamport timestamp condition is met.
+ *
+ * Example usage:
+ * - Fire when Lamport time equals 10
+ * - Fire when Lamport time reaches 50 or greater
+ * - Fire when Lamport time is less than 5
+ *
+ * @author Paul C. Buetow
+ */
+public class VSLamportTimestampEvent extends VSTimestampTriggeredEvent {
+
+ private String actionDescription;
+ private Runnable customAction;
+
+ /**
+ * Constructor for basic Lamport timestamp event
+ */
+ public VSLamportTimestampEvent(long targetLamport, ComparisonOperator op) {
+ super(targetLamport, op);
+ this.actionDescription = "Lamport timestamp condition met";
+ }
+
+ /**
+ * Constructor with custom action description
+ */
+ public VSLamportTimestampEvent(long targetLamport, ComparisonOperator op, String description) {
+ super(targetLamport, op);
+ this.actionDescription = description;
+ }
+
+ /**
+ * Constructor with custom action
+ */
+ public VSLamportTimestampEvent(long targetLamport, ComparisonOperator op, String description, Runnable action) {
+ super(targetLamport, op);
+ this.actionDescription = description;
+ this.customAction = action;
+ }
+
+ /**
+ * Default constructor for serialization
+ */
+ public VSLamportTimestampEvent() {
+ super();
+ this.actionDescription = "Lamport timestamp event";
+ }
+
+ @Override
+ public void onInit() {
+ super.onInit();
+ }
+
+ @Override
+ protected void onTimestampReached() {
+ VSInternalProcess internalProcess = (VSInternalProcess) process;
+
+ // Log the event
+ String message = String.format("Lamport timestamp event triggered: %s (current: %d, target: %d %s)",
+ actionDescription,
+ internalProcess.getLamportTime(),
+ targetLamportTime,
+ operator);
+
+ internalProcess.log(message);
+
+ // Execute custom action if provided
+ if (customAction != null) {
+ try {
+ customAction.run();
+ } catch (Exception e) {
+ internalProcess.log("Error executing custom action: " + e.getMessage());
+ }
+ }
+
+ // Default behavior: change process color to indicate trigger
+ changeProcessColor();
+ }
+
+ /**
+ * Change process color to indicate the timestamp event has been triggered
+ */
+ protected void changeProcessColor() {
+ if (process instanceof VSInternalProcess) {
+ VSInternalProcess internalProcess = (VSInternalProcess) process;
+ // Change to highlight color temporarily
+ internalProcess.highlightOn();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return String.format(" [LamportTrigger: %d %s - %s]",
+ targetLamportTime, operator, actionDescription);
+ }
+
+ // Getters and setters
+ public String getActionDescription() {
+ return actionDescription;
+ }
+
+ public void setActionDescription(String description) {
+ this.actionDescription = description;
+ }
+
+ public void setCustomAction(Runnable action) {
+ this.customAction = action;
+ }
+
+ @Override
+ protected String createShortname(String savedShortname) {
+ return "LamportTrigger";
+ }
+} \ No newline at end of file
diff --git a/src/main/java/events/implementations/VSProcessCrashEvent.java b/src/main/java/events/implementations/VSProcessCrashEvent.java
index a68e8a1..1f9fc49 100644
--- a/src/main/java/events/implementations/VSProcessCrashEvent.java
+++ b/src/main/java/events/implementations/VSProcessCrashEvent.java
@@ -11,6 +11,17 @@ import simulator.VSMain;
*/
public class VSProcessCrashEvent extends VSAbstractEvent
implements VSCopyableEvent {
+
+ @Override
+ public boolean isProcessCrashEvent() {
+ return true;
+ }
+
+ @Override
+ public int getEventPriority() {
+ return PRIORITY_HIGH;
+ }
+
/* (non-Javadoc)
* @see events.VSCopyableEvent#initCopy(events.VSAbstractEvent)
*/
diff --git a/src/main/java/events/implementations/VSProcessRecoverEvent.java b/src/main/java/events/implementations/VSProcessRecoverEvent.java
index 2aa5758..fc57ca4 100644
--- a/src/main/java/events/implementations/VSProcessRecoverEvent.java
+++ b/src/main/java/events/implementations/VSProcessRecoverEvent.java
@@ -12,6 +12,17 @@ import simulator.VSMain;
*/
public class VSProcessRecoverEvent extends VSAbstractEvent
implements VSCopyableEvent {
+
+ @Override
+ public boolean isProcessRecoverEvent() {
+ return true;
+ }
+
+ @Override
+ public int getEventPriority() {
+ return PRIORITY_HIGHEST;
+ }
+
/* (non-Javadoc)
* @see events.VSCopyableEvent#initCopy(events.VSAbstractEvent)
*/
diff --git a/src/main/java/events/implementations/VSTimestampMonitorEvent.java b/src/main/java/events/implementations/VSTimestampMonitorEvent.java
new file mode 100644
index 0000000..c795fe9
--- /dev/null
+++ b/src/main/java/events/implementations/VSTimestampMonitorEvent.java
@@ -0,0 +1,184 @@
+package events.implementations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import core.VSInternalProcess;
+import core.VSTask;
+import events.VSAbstractEvent;
+import events.VSCopyableEvent;
+
+/**
+ * A monitoring event that checks for Lamport timestamp conditions.
+ * Vector timestamp events should use VSVectorClockMonitor instead,
+ * as they need to be checked when vector clocks change, not on time intervals.
+ *
+ * This event reschedules itself to run periodically, monitoring only
+ * Lamport timestamp events for the process.
+ *
+ * @author Paul C. Buetow
+ */
+public class VSTimestampMonitorEvent extends VSAbstractEvent implements VSCopyableEvent {
+
+ private List<VSTimestampTriggeredEvent> lamportEvents;
+ private long monitorInterval;
+ private boolean isActive;
+
+ /**
+ * Constructor with default monitoring interval
+ */
+ public VSTimestampMonitorEvent() {
+ this.lamportEvents = new ArrayList<>();
+ this.monitorInterval = constants.VSConstants.DEFAULT_MONITOR_INTERVAL;
+ this.isActive = true;
+ }
+
+ /**
+ * Constructor with custom monitoring interval
+ */
+ public VSTimestampMonitorEvent(long interval) {
+ this.lamportEvents = new ArrayList<>();
+ this.monitorInterval = interval;
+ this.isActive = true;
+ }
+
+ @Override
+ public void onInit() {
+ setClassname(getClass().getName());
+ }
+
+ @Override
+ public void onStart() {
+ if (!isActive) {
+ return;
+ }
+
+ VSInternalProcess internalProcess = (VSInternalProcess) process;
+
+ // Check only Lamport timestamp events (vector events are handled separately)
+ List<VSTimestampTriggeredEvent> triggeredEvents = new ArrayList<>();
+
+ for (VSTimestampTriggeredEvent event : lamportEvents) {
+ if (!event.hasTriggered() &&
+ event.getTimestampType() == VSTimestampTriggeredEvent.TimestampType.LAMPORT) {
+
+ // Initialize the event if needed
+ if (event.getProcess() == null) {
+ event.init(internalProcess);
+ }
+
+ // Check if condition is met
+ if (event.checkCondition(internalProcess)) {
+ event.onStart(); // This will trigger the event
+ triggeredEvents.add(event);
+ }
+ }
+ }
+
+ // Remove triggered events from monitoring list
+ lamportEvents.removeAll(triggeredEvents);
+
+ // Reschedule this monitor if there are still events to monitor
+ if (!lamportEvents.isEmpty()) {
+ rescheduleMonitor();
+ }
+ }
+
+ /**
+ * Add a Lamport timestamp event to monitor
+ */
+ public void addLamportEvent(VSTimestampTriggeredEvent event) {
+ if (event.getTimestampType() == VSTimestampTriggeredEvent.TimestampType.LAMPORT &&
+ !lamportEvents.contains(event)) {
+ lamportEvents.add(event);
+
+ // If this is the first event, start monitoring
+ if (lamportEvents.size() == 1 && process != null) {
+ rescheduleMonitor();
+ }
+ }
+ }
+
+ /**
+ * Remove a Lamport timestamp event from monitoring
+ */
+ public void removeLamportEvent(VSTimestampTriggeredEvent event) {
+ lamportEvents.remove(event);
+ }
+
+ /**
+ * Schedule the next monitoring check
+ */
+ private void rescheduleMonitor() {
+ if (process instanceof VSInternalProcess) {
+ VSInternalProcess internalProcess = (VSInternalProcess) process;
+
+ // Create a new monitor task for the next interval
+ VSTimestampMonitorEvent nextMonitor = new VSTimestampMonitorEvent(monitorInterval);
+ nextMonitor.lamportEvents = new ArrayList<>(this.lamportEvents);
+ nextMonitor.isActive = this.isActive;
+
+ // Schedule as local timed task
+ long nextTime = internalProcess.getTime() + monitorInterval;
+ VSTask monitorTask = new VSTask(nextTime, internalProcess, nextMonitor, VSTask.LOCAL);
+
+ internalProcess.getSimulatorCanvas().getTaskManager().addTask(monitorTask);
+ }
+ }
+
+ /**
+ * Stop monitoring
+ */
+ public void stopMonitoring() {
+ isActive = false;
+ lamportEvents.clear();
+ }
+
+ /**
+ * Get count of Lamport events being monitored
+ */
+ public int getLamportEventCount() {
+ return lamportEvents.size();
+ }
+
+ /**
+ * Check if monitoring is active
+ */
+ public boolean isActive() {
+ return isActive && !lamportEvents.isEmpty();
+ }
+
+ @Override
+ public void initCopy(VSAbstractEvent copy) {
+ if (copy instanceof VSTimestampMonitorEvent) {
+ VSTimestampMonitorEvent copyEvent = (VSTimestampMonitorEvent) copy;
+ copyEvent.monitorInterval = this.monitorInterval;
+ copyEvent.isActive = this.isActive;
+ copyEvent.lamportEvents = new ArrayList<>(this.lamportEvents);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return String.format(" [LamportMonitor: %d events, interval=%d]",
+ lamportEvents.size(), monitorInterval);
+ }
+
+ // Getters and setters
+ public long getMonitorInterval() {
+ return monitorInterval;
+ }
+
+ public void setMonitorInterval(long interval) {
+ this.monitorInterval = interval;
+ }
+
+ public List<VSTimestampTriggeredEvent> getLamportEvents() {
+ return new ArrayList<>(lamportEvents);
+ }
+
+ @Override
+ protected String createShortname(String savedShortname) {
+ return "TimestampMonitor";
+ }
+} \ No newline at end of file
diff --git a/src/main/java/events/implementations/VSTimestampTriggeredEvent.java b/src/main/java/events/implementations/VSTimestampTriggeredEvent.java
new file mode 100644
index 0000000..16d552d
--- /dev/null
+++ b/src/main/java/events/implementations/VSTimestampTriggeredEvent.java
@@ -0,0 +1,264 @@
+package events.implementations;
+
+import core.VSInternalProcess;
+import core.time.VSLamportTime;
+import core.time.VSVectorTime;
+import events.VSAbstractEvent;
+import events.VSCopyableEvent;
+
+/**
+ * Abstract base class for timestamp-triggered events that fire when specific
+ * Lamport or vector clock conditions are met.
+ *
+ * @author Paul C. Buetow
+ */
+public abstract class VSTimestampTriggeredEvent extends VSAbstractEvent implements VSCopyableEvent {
+
+ public enum TimestampType {
+ LAMPORT,
+ VECTOR
+ }
+
+ public enum ComparisonOperator {
+ EQUAL,
+ GREATER_THAN,
+ LESS_THAN,
+ GREATER_EQUAL,
+ LESS_EQUAL
+ }
+
+ protected TimestampType timestampType;
+ protected ComparisonOperator operator;
+ protected boolean hasTriggered;
+
+ protected long targetLamportTime;
+ protected VSVectorTime targetVectorTime;
+
+ /**
+ * Constructor for Lamport timestamp events
+ */
+ public VSTimestampTriggeredEvent(long targetLamport, ComparisonOperator op) {
+ this.timestampType = TimestampType.LAMPORT;
+ this.targetLamportTime = targetLamport;
+ this.operator = op;
+ this.hasTriggered = false;
+ }
+
+ /**
+ * Constructor for Vector timestamp events
+ */
+ public VSTimestampTriggeredEvent(VSVectorTime targetVector, ComparisonOperator op) {
+ this.timestampType = TimestampType.VECTOR;
+ this.targetVectorTime = targetVector.getCopy();
+ this.operator = op;
+ this.hasTriggered = false;
+ }
+
+ /**
+ * Default constructor for serialization
+ */
+ public VSTimestampTriggeredEvent() {
+ this.hasTriggered = false;
+ }
+
+ @Override
+ public void onInit() {
+ setClassname(getClass().getName());
+ }
+
+ @Override
+ public void onStart() {
+ if (hasTriggered) {
+ return;
+ }
+
+ VSInternalProcess internalProcess = (VSInternalProcess) process;
+ boolean conditionMet = false;
+
+ if (timestampType == TimestampType.LAMPORT) {
+ conditionMet = checkLamportCondition(internalProcess);
+ } else if (timestampType == TimestampType.VECTOR) {
+ conditionMet = checkVectorCondition(internalProcess);
+ }
+
+ if (conditionMet) {
+ hasTriggered = true;
+ onTimestampReached();
+ }
+ }
+
+ /**
+ * Check timestamp condition without triggering the event.
+ * Used by monitoring systems to test conditions.
+ */
+ public boolean checkCondition(VSInternalProcess process) {
+ if (hasTriggered) {
+ return false;
+ }
+
+ if (timestampType == TimestampType.LAMPORT) {
+ return checkLamportCondition(process);
+ } else if (timestampType == TimestampType.VECTOR) {
+ return checkVectorCondition(process);
+ }
+
+ return false;
+ }
+
+ /**
+ * Check if Lamport timestamp condition is met
+ */
+ protected boolean checkLamportCondition(VSInternalProcess process) {
+ long currentLamport = process.getLamportTime();
+
+ switch (operator) {
+ case EQUAL:
+ return currentLamport == targetLamportTime;
+ case GREATER_THAN:
+ return currentLamport > targetLamportTime;
+ case LESS_THAN:
+ return currentLamport < targetLamportTime;
+ case GREATER_EQUAL:
+ return currentLamport >= targetLamportTime;
+ case LESS_EQUAL:
+ return currentLamport <= targetLamportTime;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Check if Vector timestamp condition is met
+ */
+ protected boolean checkVectorCondition(VSInternalProcess process) {
+ VSVectorTime currentVector = process.getVectorTime();
+
+ if (currentVector == null || targetVectorTime == null) {
+ return false;
+ }
+
+ switch (operator) {
+ case EQUAL:
+ return vectorTimesEqual(currentVector, targetVectorTime);
+ case GREATER_THAN:
+ return vectorTimeGreater(currentVector, targetVectorTime, false);
+ case LESS_THAN:
+ return vectorTimeGreater(targetVectorTime, currentVector, false);
+ case GREATER_EQUAL:
+ return vectorTimeGreater(currentVector, targetVectorTime, true);
+ case LESS_EQUAL:
+ return vectorTimeGreater(targetVectorTime, currentVector, true);
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Check if two vector times are equal
+ */
+ protected boolean vectorTimesEqual(VSVectorTime v1, VSVectorTime v2) {
+ int maxSize = Math.max(v1.size(), v2.size());
+
+ for (int i = 0; i < maxSize; i++) {
+ long val1 = i < v1.size() ? v1.get(i) : 0;
+ long val2 = i < v2.size() ? v2.get(i) : 0;
+
+ if (val1 != val2) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Check if v1 > v2 (or >= if allowEqual is true) using vector clock ordering
+ */
+ protected boolean vectorTimeGreater(VSVectorTime v1, VSVectorTime v2, boolean allowEqual) {
+ int maxSize = Math.max(v1.size(), v2.size());
+ boolean hasGreater = false;
+
+ for (int i = 0; i < maxSize; i++) {
+ long val1 = i < v1.size() ? v1.get(i) : 0;
+ long val2 = i < v2.size() ? v2.get(i) : 0;
+
+ if (val1 < val2) {
+ return false;
+ } else if (val1 > val2) {
+ hasGreater = true;
+ }
+ }
+
+ return hasGreater || (allowEqual && vectorTimesEqual(v1, v2));
+ }
+
+ /**
+ * This method is called when the timestamp condition is met.
+ * Subclasses should override this to define the actual behavior.
+ */
+ protected abstract void onTimestampReached();
+
+ @Override
+ protected String createShortname(String savedShortname) {
+ return "TimestampTrigger";
+ }
+
+ @Override
+ public void initCopy(VSAbstractEvent copy) {
+ if (copy instanceof VSTimestampTriggeredEvent) {
+ VSTimestampTriggeredEvent copyEvent = (VSTimestampTriggeredEvent) copy;
+ copyEvent.timestampType = this.timestampType;
+ copyEvent.operator = this.operator;
+ copyEvent.targetLamportTime = this.targetLamportTime;
+ copyEvent.hasTriggered = this.hasTriggered;
+
+ if (this.targetVectorTime != null) {
+ copyEvent.targetVectorTime = this.targetVectorTime.getCopy();
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(" [TimestampTrigger: ");
+
+ if (timestampType == TimestampType.LAMPORT) {
+ sb.append("Lamport ").append(operator).append(" ").append(targetLamportTime);
+ } else {
+ sb.append("Vector ").append(operator).append(" ").append(targetVectorTime);
+ }
+
+ if (hasTriggered) {
+ sb.append(" (TRIGGERED)");
+ }
+
+ sb.append("]");
+ return sb.toString();
+ }
+
+ // Getters and setters
+ public TimestampType getTimestampType() {
+ return timestampType;
+ }
+
+ public ComparisonOperator getOperator() {
+ return operator;
+ }
+
+ public long getTargetLamportTime() {
+ return targetLamportTime;
+ }
+
+ public VSVectorTime getTargetVectorTime() {
+ return targetVectorTime != null ? targetVectorTime.getCopy() : null;
+ }
+
+ public boolean hasTriggered() {
+ return hasTriggered;
+ }
+
+ public void reset() {
+ hasTriggered = false;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/events/implementations/VSVectorClockMonitor.java b/src/main/java/events/implementations/VSVectorClockMonitor.java
new file mode 100644
index 0000000..05a15f5
--- /dev/null
+++ b/src/main/java/events/implementations/VSVectorClockMonitor.java
@@ -0,0 +1,136 @@
+package events.implementations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import core.VSInternalProcess;
+import core.time.VSVectorTime;
+
+/**
+ * A monitor that tracks vector clock changes and triggers events when
+ * vector timestamp conditions are met. This monitor is integrated into
+ * the process's vector clock update mechanism rather than being time-based.
+ *
+ * @author Paul C. Buetow
+ */
+public class VSVectorClockMonitor {
+
+ private List<VSTimestampTriggeredEvent> vectorEvents;
+ private VSInternalProcess process;
+ private VSVectorTime lastCheckedVector;
+
+ /**
+ * Constructor
+ */
+ public VSVectorClockMonitor(VSInternalProcess process) {
+ this.process = process;
+ this.vectorEvents = new ArrayList<>();
+ this.lastCheckedVector = null;
+ }
+
+ /**
+ * Add a vector timestamp event to monitor
+ */
+ public void addVectorEvent(VSTimestampTriggeredEvent event) {
+ if (event.getTimestampType() == VSTimestampTriggeredEvent.TimestampType.VECTOR &&
+ !vectorEvents.contains(event)) {
+ vectorEvents.add(event);
+ }
+ }
+
+ /**
+ * Remove a vector timestamp event from monitoring
+ */
+ public void removeVectorEvent(VSTimestampTriggeredEvent event) {
+ vectorEvents.remove(event);
+ }
+
+ /**
+ * Check all vector events when the vector clock changes.
+ * This should be called whenever the process's vector clock is updated.
+ */
+ public void checkVectorEvents() {
+ if (vectorEvents.isEmpty()) {
+ return;
+ }
+
+ VSVectorTime currentVector = process.getVectorTime();
+
+ // Only check if vector clock actually changed
+ if (currentVector == null || vectorClockEquals(currentVector, lastCheckedVector)) {
+ return;
+ }
+
+ List<VSTimestampTriggeredEvent> triggeredEvents = new ArrayList<>();
+
+ for (VSTimestampTriggeredEvent event : vectorEvents) {
+ if (!event.hasTriggered()) {
+ // Initialize event if needed
+ if (event.getProcess() == null) {
+ event.init(process);
+ }
+
+ // Check condition
+ if (event.checkCondition(process)) {
+ event.onStart(); // This will trigger the event
+ triggeredEvents.add(event);
+
+ process.log("Vector timestamp event triggered: " + event.toString());
+ }
+ }
+ }
+
+ // Remove triggered events
+ vectorEvents.removeAll(triggeredEvents);
+
+ // Update last checked vector
+ lastCheckedVector = currentVector != null ? currentVector.getCopy() : null;
+ }
+
+ /**
+ * Check if two vector clocks are equal
+ */
+ private boolean vectorClockEquals(VSVectorTime v1, VSVectorTime v2) {
+ if (v1 == null && v2 == null) {
+ return true;
+ }
+ if (v1 == null || v2 == null) {
+ return false;
+ }
+
+ int maxSize = Math.max(v1.size(), v2.size());
+
+ for (int i = 0; i < maxSize; i++) {
+ long val1 = i < v1.size() ? v1.get(i) : 0;
+ long val2 = i < v2.size() ? v2.get(i) : 0;
+
+ if (val1 != val2) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Get the number of vector events being monitored
+ */
+ public int getVectorEventCount() {
+ return vectorEvents.size();
+ }
+
+ /**
+ * Clear all vector events
+ */
+ public void clearVectorEvents() {
+ vectorEvents.clear();
+ lastCheckedVector = null;
+ }
+
+ /**
+ * Get a copy of the monitored events list
+ */
+ public List<VSTimestampTriggeredEvent> getVectorEvents() {
+ return new ArrayList<>(vectorEvents);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/events/implementations/VSVectorTimestampEvent.java b/src/main/java/events/implementations/VSVectorTimestampEvent.java
new file mode 100644
index 0000000..4d3b327
--- /dev/null
+++ b/src/main/java/events/implementations/VSVectorTimestampEvent.java
@@ -0,0 +1,142 @@
+package events.implementations;
+
+import core.VSInternalProcess;
+import core.time.VSVectorTime;
+
+/**
+ * Concrete implementation of a Vector timestamp-triggered event.
+ * This event fires when a specific Vector timestamp condition is met.
+ *
+ * Example usage:
+ * - Fire when vector clock equals [3,2,1]
+ * - Fire when vector clock is greater than or equal to [5,0,2]
+ * - Fire when any element in vector clock reaches a threshold
+ *
+ * @author Paul C. Buetow
+ */
+public class VSVectorTimestampEvent extends VSTimestampTriggeredEvent {
+
+ private String actionDescription;
+ private Runnable customAction;
+
+ /**
+ * Constructor for basic Vector timestamp event
+ */
+ public VSVectorTimestampEvent(VSVectorTime targetVector, ComparisonOperator op) {
+ super(targetVector, op);
+ this.actionDescription = "Vector timestamp condition met";
+ }
+
+ /**
+ * Constructor with custom action description
+ */
+ public VSVectorTimestampEvent(VSVectorTime targetVector, ComparisonOperator op, String description) {
+ super(targetVector, op);
+ this.actionDescription = description;
+ }
+
+ /**
+ * Constructor with custom action
+ */
+ public VSVectorTimestampEvent(VSVectorTime targetVector, ComparisonOperator op, String description, Runnable action) {
+ super(targetVector, op);
+ this.actionDescription = description;
+ this.customAction = action;
+ }
+
+ /**
+ * Default constructor for serialization
+ */
+ public VSVectorTimestampEvent() {
+ super();
+ this.actionDescription = "Vector timestamp event";
+ }
+
+ @Override
+ public void onInit() {
+ super.onInit();
+ }
+
+ @Override
+ protected void onTimestampReached() {
+ VSInternalProcess internalProcess = (VSInternalProcess) process;
+
+ // Log the event
+ String message = String.format("Vector timestamp event triggered: %s (current: %s, target: %s %s)",
+ actionDescription,
+ internalProcess.getVectorTime(),
+ targetVectorTime,
+ operator);
+
+ internalProcess.log(message);
+
+ // Execute custom action if provided
+ if (customAction != null) {
+ try {
+ customAction.run();
+ } catch (Exception e) {
+ internalProcess.log("Error executing custom action: " + e.getMessage());
+ }
+ }
+
+ // Default behavior: change process color to indicate trigger
+ changeProcessColor();
+ }
+
+ /**
+ * Change process color to indicate the timestamp event has been triggered
+ */
+ protected void changeProcessColor() {
+ if (process instanceof VSInternalProcess) {
+ VSInternalProcess internalProcess = (VSInternalProcess) process;
+ // Change to highlight color temporarily
+ internalProcess.highlightOn();
+ }
+ }
+
+ /**
+ * Convenience method to create event that triggers when any vector element reaches threshold
+ */
+ public static VSVectorTimestampEvent createThresholdEvent(int processCount, long threshold, String description) {
+ VSVectorTime targetVector = new VSVectorTime(0);
+ for (int i = 0; i < processCount; i++) {
+ targetVector.add(threshold);
+ }
+ return new VSVectorTimestampEvent(targetVector, ComparisonOperator.GREATER_EQUAL, description);
+ }
+
+ /**
+ * Convenience method to create event that triggers when specific process element reaches value
+ */
+ public static VSVectorTimestampEvent createProcessThresholdEvent(int processCount, int processIndex, long threshold, String description) {
+ VSVectorTime targetVector = new VSVectorTime(0);
+ for (int i = 0; i < processCount; i++) {
+ targetVector.add(i == processIndex ? threshold : 0L);
+ }
+ return new VSVectorTimestampEvent(targetVector, ComparisonOperator.GREATER_EQUAL, description);
+ }
+
+ @Override
+ public String toString() {
+ return String.format(" [VectorTrigger: %s %s - %s]",
+ targetVectorTime, operator, actionDescription);
+ }
+
+ // Getters and setters
+ public String getActionDescription() {
+ return actionDescription;
+ }
+
+ public void setActionDescription(String description) {
+ this.actionDescription = description;
+ }
+
+ public void setCustomAction(Runnable action) {
+ this.customAction = action;
+ }
+
+ @Override
+ protected String createShortname(String savedShortname) {
+ return "VectorTrigger";
+ }
+} \ No newline at end of file
diff --git a/src/main/java/events/internal/VSAbstractInternalEvent.java b/src/main/java/events/internal/VSAbstractInternalEvent.java
index 33e3763..2988be9 100644
--- a/src/main/java/events/internal/VSAbstractInternalEvent.java
+++ b/src/main/java/events/internal/VSAbstractInternalEvent.java
@@ -14,6 +14,11 @@ import serialize.VSSerialize;
* @author Paul C. Buetow
*/
abstract public class VSAbstractInternalEvent extends VSAbstractEvent {
+ @Override
+ public boolean isInternalEvent() {
+ return true;
+ }
+
/* (non-Javadoc)
* @see events.VSAbstractEvent#createShortname()()
*/
diff --git a/src/main/java/events/internal/VSMessageReceiveEvent.java b/src/main/java/events/internal/VSMessageReceiveEvent.java
index 51ae926..54f2c94 100644
--- a/src/main/java/events/internal/VSMessageReceiveEvent.java
+++ b/src/main/java/events/internal/VSMessageReceiveEvent.java
@@ -24,6 +24,21 @@ public class VSMessageReceiveEvent extends VSAbstractInternalEvent
public VSMessageReceiveEvent(VSMessage message) {
this.message = message;
}
+
+ @Override
+ public boolean isMessageReceiveEvent() {
+ return true;
+ }
+
+ @Override
+ public boolean isSerializable() {
+ return false;
+ }
+
+ @Override
+ public boolean shouldIncreaseTimestamps() {
+ return false;
+ }
/* (non-Javadoc)
* @see events.VSAbstractEvent#onInit()
diff --git a/src/main/java/events/internal/VSProtocolEvent.java b/src/main/java/events/internal/VSProtocolEvent.java
index caf8b15..0cd6db4 100644
--- a/src/main/java/events/internal/VSProtocolEvent.java
+++ b/src/main/java/events/internal/VSProtocolEvent.java
@@ -27,6 +27,16 @@ public class VSProtocolEvent extends VSAbstractInternalEvent
/** The event is a client protocol if true. Else it is a server protocol */
private boolean isClientProtocol;
+
+ @Override
+ public boolean isProtocolEvent() {
+ return true;
+ }
+
+ @Override
+ public int getEventPriority() {
+ return PRIORITY_MEDIUM;
+ }
/** The event is a protocol activation if true. Else it is a deactivation */
private boolean isProtocolActivation;