diff options
Diffstat (limited to 'src/main/java/events')
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; |
