From b67f9ed652ac776be6f75ef0a4498cfab2a8c57f Mon Sep 17 00:00:00 2001 From: Tessa Date: Fri, 26 May 2023 11:35:03 +0200 Subject: [PATCH 1/5] Token ring, Lamport clock and Vector clock added --- gradle/wrapper/gradle-wrapper.properties | 2 +- .../java/dev/oxoo2a/sim4da/LamportTime.java | 33 ++++++++ .../java/dev/oxoo2a/sim4da/NodeEvent.java | 74 +++++++++++++++++ .../java/dev/oxoo2a/sim4da/NodeWithTime.java | 79 +++++++++++++++++++ src/main/java/dev/oxoo2a/sim4da/Time.java | 21 +++++ .../java/dev/oxoo2a/sim4da/TokenRingNode.java | 33 ++++++++ .../java/dev/oxoo2a/sim4da/VectorTime.java | 45 +++++++++++ .../dev/oxoo2a/sim4da/NodeWithTimeRandom.java | 73 +++++++++++++++++ .../dev/oxoo2a/sim4da/NodeWithTimeTest.java | 53 +++++++++++++ .../java/dev/oxoo2a/sim4da/TokenRingTest.java | 30 +++++++ 10 files changed, 442 insertions(+), 1 deletion(-) create mode 100644 src/main/java/dev/oxoo2a/sim4da/LamportTime.java create mode 100644 src/main/java/dev/oxoo2a/sim4da/NodeEvent.java create mode 100644 src/main/java/dev/oxoo2a/sim4da/NodeWithTime.java create mode 100644 src/main/java/dev/oxoo2a/sim4da/Time.java create mode 100644 src/main/java/dev/oxoo2a/sim4da/TokenRingNode.java create mode 100644 src/main/java/dev/oxoo2a/sim4da/VectorTime.java create mode 100644 src/test/java/dev/oxoo2a/sim4da/NodeWithTimeRandom.java create mode 100644 src/test/java/dev/oxoo2a/sim4da/NodeWithTimeTest.java create mode 100644 src/test/java/dev/oxoo2a/sim4da/TokenRingTest.java diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index aa991fc..fae0804 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/dev/oxoo2a/sim4da/LamportTime.java b/src/main/java/dev/oxoo2a/sim4da/LamportTime.java new file mode 100644 index 0000000..a765a21 --- /dev/null +++ b/src/main/java/dev/oxoo2a/sim4da/LamportTime.java @@ -0,0 +1,33 @@ +package dev.oxoo2a.sim4da; + +/*** + * Implements the rules of the lamport time + */ +public class LamportTime implements Time{ + + private int time; + + public LamportTime(){ + time = 0; + } + + @Override + public void incrementMyTime() { + time++; + } + + @Override + public String toString() { + return time+""; + } + + @Override + public void updateTime(String time_sender) { + int time_s_i = Integer.parseInt(time_sender); + // max function + if(time_s_i > time) + time = time_s_i; + // increment local time + incrementMyTime(); + } +} diff --git a/src/main/java/dev/oxoo2a/sim4da/NodeEvent.java b/src/main/java/dev/oxoo2a/sim4da/NodeEvent.java new file mode 100644 index 0000000..379247f --- /dev/null +++ b/src/main/java/dev/oxoo2a/sim4da/NodeEvent.java @@ -0,0 +1,74 @@ +package dev.oxoo2a.sim4da; + +import java.util.ArrayList; + +/*** + * Nodes withing the network can perform two kinds of events: An inner event or sending a message. + * This class collects all the information for a event that is performed by a node, so that it can be analysed later. + * The class only has the function to collect data with no logic. + */ +public class NodeEvent { + + public enum EventType { INNER, SEND_MESSAGE } + // All events within the simulation + private static ArrayList events = new ArrayList<>(); + + private final int eventOrderId; + private String performedTime; + private final EventType type; + /*** + * node that performed the event + */ + private int executorNode; + /*** + * only given for send_message. The node that received the message + */ + private final int receiverNode; + + public NodeEvent(EventType type, int receiverNode){ + if(type == EventType.SEND_MESSAGE && receiverNode < 0) + throw new IllegalArgumentException("No node given for message"); + this.type = type; + this.receiverNode = receiverNode; + this.eventOrderId = events.size(); + events.add(this); + } + + /*** + * The event was performed -> update data in this class + * @param executorNode - node that performed the event + * @param time - local time of the performing node + */ + public void performed(int executorNode, String time){ + this.executorNode = executorNode; + this.performedTime = time; + } + + public EventType getType() { + return type; + } + + public int getReceiverNode() { + return receiverNode; + } + + @Override + public String toString() { + return "ExampleEvent{" + + "eventOrderId=" + eventOrderId + + ", performedTime=" + performedTime + + ", type=" + type + + ", executorNode=" + executorNode + + ", recieverNode=" + receiverNode + + '}'; + } + + /*** + * prints all events within the simulation to the console + */ + public static void printAllEvents(){ + for (NodeEvent e: events) { + System.out.println(e.toString()); + } + } +} diff --git a/src/main/java/dev/oxoo2a/sim4da/NodeWithTime.java b/src/main/java/dev/oxoo2a/sim4da/NodeWithTime.java new file mode 100644 index 0000000..6023229 --- /dev/null +++ b/src/main/java/dev/oxoo2a/sim4da/NodeWithTime.java @@ -0,0 +1,79 @@ +package dev.oxoo2a.sim4da; + +/*** + * Node in the network that has a logic clock + * @author Tessa Steinigke + */ +public abstract class NodeWithTime extends Node { + + private Time time; // manages the time according to the rules in the class of the logic clock + + public NodeWithTime(int my_id, Time time) { + super(my_id); + this.time = time; + } + + /*** + * An event is triggered and executed + * @param event - event to execute + */ + public void performEvent(NodeEvent event){ + // Update the time + time.incrementMyTime(); + event.performed(myId, time.toString()); + // Execute event + if(event.getType() == NodeEvent.EventType.SEND_MESSAGE){ + // Send Message + emit("%d: perform send_message at %s",myId,time.toString()); + Message m = new Message(); + m.add("time",time.toString()); // In each message the time needs to be send + sendUnicast(event.getReceiverNode(),m); + }else{ + // Do some inner event + emit("%d: perform inner_event at %s",myId,time.toString()); + handleInnerEvent(); + } + } + + // Nodes within the network can handle events differently. + // That's why this class is abstract and child classes can define their own reactions to events. + + /*** + * Defines the inner event of the node + */ + protected abstract void handleInnerEvent(); + + /*** + * Defines what happens after a message was received + */ + protected abstract void handleReceivingMessage(); + + /*** + * Defines what happens at the start of the simulation + */ + protected abstract void handleStart(); + + /*** + * A message was received from a different node + * @param m - Message from the network + */ + private void receivedMessage(Message m){ + // Update the time with the new time information given in the message + time.updateTime(m.query("time")); + + // Do something with message + handleReceivingMessage(); + } + + @Override + protected void main() { + handleStart(); + while (true) { + // Listen for messages + Network.Message m_raw = receive(); + if (m_raw == null) break; + Message m = Message.fromJson(m_raw.payload); + receivedMessage(m); + } + } +} diff --git a/src/main/java/dev/oxoo2a/sim4da/Time.java b/src/main/java/dev/oxoo2a/sim4da/Time.java new file mode 100644 index 0000000..2dcb3cf --- /dev/null +++ b/src/main/java/dev/oxoo2a/sim4da/Time.java @@ -0,0 +1,21 @@ +package dev.oxoo2a.sim4da; + +public interface Time { + /*** + * Increment the time of the local node + */ + void incrementMyTime(); + + /*** + * String representation of the time + * @return - time as string + */ + String toString(); + + /*** + * New time was received by a different node (sender). + * Now the time of the local node must be updated. + * @param time_sender - time of the sender node in the string representation + */ + void updateTime(String time_sender); +} diff --git a/src/main/java/dev/oxoo2a/sim4da/TokenRingNode.java b/src/main/java/dev/oxoo2a/sim4da/TokenRingNode.java new file mode 100644 index 0000000..78e6ad4 --- /dev/null +++ b/src/main/java/dev/oxoo2a/sim4da/TokenRingNode.java @@ -0,0 +1,33 @@ +package dev.oxoo2a.sim4da; + +public class TokenRingNode extends Node { + + public TokenRingNode(int my_id) { + super(my_id); + } + + @Override + protected void main() { + Message m = new Message(); + if (myId == 0) { + // Send first message + m.add("counter",0); + sendUnicast(1,m); + } + while (true) { + // Listen for messages + Network.Message m_raw = receive(); + if (m_raw == null) break; + // Message received + m = Message.fromJson(m_raw.payload); + int counter = Integer.parseInt(m.query("counter")); + emit("%d: counter==%d",myId,counter); + // Token increased + counter++; + m.add("counter",counter); + // Next message send + sendUnicast((myId+1) % numberOfNodes(),m); + } + } + +} diff --git a/src/main/java/dev/oxoo2a/sim4da/VectorTime.java b/src/main/java/dev/oxoo2a/sim4da/VectorTime.java new file mode 100644 index 0000000..9e78a32 --- /dev/null +++ b/src/main/java/dev/oxoo2a/sim4da/VectorTime.java @@ -0,0 +1,45 @@ +package dev.oxoo2a.sim4da; + +import java.util.Arrays; + +/*** + * Implements the rules of the vector time + */ +public class VectorTime implements Time { + + private int[] time; + private final int myId; + + public VectorTime(int myId, int n_nodes){ + time = new int[n_nodes]; + for(int i = 0; i < n_nodes; i++){ + time[i] = 0; + } + this.myId = myId; + } + + @Override + public void incrementMyTime() { + time[myId]++; + } + + @Override + public String toString() { + return Arrays.toString(time); + } + + @Override + public void updateTime(String time_sender) { + // increment local time + incrementMyTime(); + + time_sender = time_sender.substring(1, time_sender.length()-1); + String[] arr = time_sender.split(", "); + // max function + for(int i = 0; i < arr.length; i++){ + int sender_i_int = Integer.parseInt(arr[i]); + if(sender_i_int > time[i]) + time[i] = sender_i_int; + } + } +} diff --git a/src/test/java/dev/oxoo2a/sim4da/NodeWithTimeRandom.java b/src/test/java/dev/oxoo2a/sim4da/NodeWithTimeRandom.java new file mode 100644 index 0000000..fc99c0f --- /dev/null +++ b/src/test/java/dev/oxoo2a/sim4da/NodeWithTimeRandom.java @@ -0,0 +1,73 @@ +package dev.oxoo2a.sim4da; + +import java.util.Random; + +/*** + * A node with a logic clock that performs some random actions when a event is triggered + */ +public class NodeWithTimeRandom extends NodeWithTime{ + + private final int n_nodes; + + public NodeWithTimeRandom(int id, Time time, int n_nodes){ + super(id, time); + this.n_nodes = n_nodes; + } + + /*** + * when the simulation starts the first node sends a message to the second + */ + @Override + protected void handleStart() { + if (myId == 0) { + performEvent(new NodeEvent(NodeEvent.EventType.SEND_MESSAGE, 1)); + } + } + + /*** + * The inner event of the node is sleeping/pausing for some milliseconds + */ + @Override + protected void handleInnerEvent() { + try { + Thread.sleep(2 * 100L); + } + catch (InterruptedException ignored) {} + } + + /*** + * When a message is received a random number of events are performed. + * By random the events can be INNER or SEND_MESSAGE. + * At leased one SEND_MESSAGE must be performed so that the network continuous to do something. + */ + @Override + protected void handleReceivingMessage() { + boolean sendPerformed = false; + + Random rand = new Random(); + // Execute a random number of events + int numberOfRandomEvents = rand.nextInt(3); + for(int i = 0; i <= numberOfRandomEvents; i++) { + // Get a random event type + int randEvent_i = rand.nextInt(4); + if (randEvent_i == 1){ + // send message to a random receiving node + int randReceiverNodeId = rand.nextInt(n_nodes); + if(randReceiverNodeId != myId){ + performEvent(new NodeEvent(NodeEvent.EventType.SEND_MESSAGE, randReceiverNodeId)); + sendPerformed = true; + } + }else{ + // do inner event + performEvent(new NodeEvent(NodeEvent.EventType.INNER, -1)); + } + } + + // Make sure that at leased one message was send + if(!sendPerformed){ + performEvent(new NodeEvent(NodeEvent.EventType.SEND_MESSAGE, (myId+1) % n_nodes)); + } + } + + +} diff --git a/src/test/java/dev/oxoo2a/sim4da/NodeWithTimeTest.java b/src/test/java/dev/oxoo2a/sim4da/NodeWithTimeTest.java new file mode 100644 index 0000000..a1d4fb3 --- /dev/null +++ b/src/test/java/dev/oxoo2a/sim4da/NodeWithTimeTest.java @@ -0,0 +1,53 @@ +package dev.oxoo2a.sim4da; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.fail; + +/*** + * Test nodes with logic clocks + */ +public class NodeWithTimeTest { + + public enum TimeType { LAMPORT, VECTOR } + + private static final int n_nodes = 3; + + /*** + * Same test for both clocks. Just the Time instances are different. + * @param type - Type of logic clock + */ + private static void test(TimeType type){ + Simulator s = Simulator.createDefaultSimulator(n_nodes); + NodeWithTime[] nodes = new NodeWithTime[n_nodes]; + for (int id=0; id Date: Wed, 5 Jul 2023 16:36:32 +0200 Subject: [PATCH 2/5] Time handling changed --- src/main/java/dev/oxoo2a/sim4da/Message.java | 4 +- .../dev/oxoo2a/sim4da/MessageWithTime.java | 45 ++++++++++ .../java/dev/oxoo2a/sim4da/NodeEvent.java | 74 ---------------- .../java/dev/oxoo2a/sim4da/NodeWithTime.java | 84 +++++++------------ src/main/java/dev/oxoo2a/sim4da/Time.java | 8 ++ .../sim4da/{ => times}/LamportTime.java | 17 +++- .../oxoo2a/sim4da/{ => times}/VectorTime.java | 15 +++- .../dev/oxoo2a/sim4da/NodeWithTimeTest.java | 7 +- .../java/dev/oxoo2a/sim4da/SimulatorTest.java | 3 +- .../java/dev/oxoo2a/sim4da/TokenRingTest.java | 2 +- .../sim4da/{ => nodes}/BroadcastNode.java | 6 +- .../{ => nodes}/NodeWithTimeRandom.java | 45 ++++++---- .../oxoo2a/sim4da/nodes}/TokenRingNode.java | 6 +- 13 files changed, 156 insertions(+), 160 deletions(-) create mode 100644 src/main/java/dev/oxoo2a/sim4da/MessageWithTime.java delete mode 100644 src/main/java/dev/oxoo2a/sim4da/NodeEvent.java rename src/main/java/dev/oxoo2a/sim4da/{ => times}/LamportTime.java (52%) rename src/main/java/dev/oxoo2a/sim4da/{ => times}/VectorTime.java (68%) rename src/test/java/dev/oxoo2a/sim4da/{ => nodes}/BroadcastNode.java (93%) rename src/test/java/dev/oxoo2a/sim4da/{ => nodes}/NodeWithTimeRandom.java (65%) rename src/{main/java/dev/oxoo2a/sim4da => test/java/dev/oxoo2a/sim4da/nodes}/TokenRingNode.java (86%) diff --git a/src/main/java/dev/oxoo2a/sim4da/Message.java b/src/main/java/dev/oxoo2a/sim4da/Message.java index 0f5da9b..322a95c 100644 --- a/src/main/java/dev/oxoo2a/sim4da/Message.java +++ b/src/main/java/dev/oxoo2a/sim4da/Message.java @@ -48,6 +48,6 @@ private static synchronized String serialize ( Map content ) { return serializer.toJson(content); // Not sure about thread safety of Gson } - private final HashMap content; - private static final Gson serializer = new Gson(); + protected final HashMap content; + protected static final Gson serializer = new Gson(); } diff --git a/src/main/java/dev/oxoo2a/sim4da/MessageWithTime.java b/src/main/java/dev/oxoo2a/sim4da/MessageWithTime.java new file mode 100644 index 0000000..1ddcef2 --- /dev/null +++ b/src/main/java/dev/oxoo2a/sim4da/MessageWithTime.java @@ -0,0 +1,45 @@ +package dev.oxoo2a.sim4da; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; + +public class MessageWithTime extends Message{ + + private final String time; + + public MessageWithTime(Time time){ + super(); + this.time = time.toString(); + } + public MessageWithTime(HashMap content, Time time){ + super(content); + this.time = time.toString(); + } + public MessageWithTime(Message m, Time time){ + this(m.content, time); + } + + public String getTime(){return time;} + + public String toJson () { + return serialize(this); + } + + public static MessageWithTime fromJson ( String s ) { + //Type contentType = new TypeToken>() {}.getType(); + //return new Message(serializer.fromJson(s,contentType)); + return serializer.fromJson(s, MessageWithTime.class); + } + + private static synchronized String serialize ( MessageWithTime m ) { + //HashMap, > + String s = serializer.toJson(m); // Not sure about thread safety of Gson + return s; + } + + +} diff --git a/src/main/java/dev/oxoo2a/sim4da/NodeEvent.java b/src/main/java/dev/oxoo2a/sim4da/NodeEvent.java deleted file mode 100644 index 379247f..0000000 --- a/src/main/java/dev/oxoo2a/sim4da/NodeEvent.java +++ /dev/null @@ -1,74 +0,0 @@ -package dev.oxoo2a.sim4da; - -import java.util.ArrayList; - -/*** - * Nodes withing the network can perform two kinds of events: An inner event or sending a message. - * This class collects all the information for a event that is performed by a node, so that it can be analysed later. - * The class only has the function to collect data with no logic. - */ -public class NodeEvent { - - public enum EventType { INNER, SEND_MESSAGE } - // All events within the simulation - private static ArrayList events = new ArrayList<>(); - - private final int eventOrderId; - private String performedTime; - private final EventType type; - /*** - * node that performed the event - */ - private int executorNode; - /*** - * only given for send_message. The node that received the message - */ - private final int receiverNode; - - public NodeEvent(EventType type, int receiverNode){ - if(type == EventType.SEND_MESSAGE && receiverNode < 0) - throw new IllegalArgumentException("No node given for message"); - this.type = type; - this.receiverNode = receiverNode; - this.eventOrderId = events.size(); - events.add(this); - } - - /*** - * The event was performed -> update data in this class - * @param executorNode - node that performed the event - * @param time - local time of the performing node - */ - public void performed(int executorNode, String time){ - this.executorNode = executorNode; - this.performedTime = time; - } - - public EventType getType() { - return type; - } - - public int getReceiverNode() { - return receiverNode; - } - - @Override - public String toString() { - return "ExampleEvent{" + - "eventOrderId=" + eventOrderId + - ", performedTime=" + performedTime + - ", type=" + type + - ", executorNode=" + executorNode + - ", recieverNode=" + receiverNode + - '}'; - } - - /*** - * prints all events within the simulation to the console - */ - public static void printAllEvents(){ - for (NodeEvent e: events) { - System.out.println(e.toString()); - } - } -} diff --git a/src/main/java/dev/oxoo2a/sim4da/NodeWithTime.java b/src/main/java/dev/oxoo2a/sim4da/NodeWithTime.java index 6023229..2d00c47 100644 --- a/src/main/java/dev/oxoo2a/sim4da/NodeWithTime.java +++ b/src/main/java/dev/oxoo2a/sim4da/NodeWithTime.java @@ -6,74 +6,46 @@ */ public abstract class NodeWithTime extends Node { - private Time time; // manages the time according to the rules in the class of the logic clock + protected final Time time; // manages the time according to the rules in the class of the logic clock public NodeWithTime(int my_id, Time time) { super(my_id); this.time = time; } - /*** - * An event is triggered and executed - * @param event - event to execute - */ - public void performEvent(NodeEvent event){ - // Update the time - time.incrementMyTime(); - event.performed(myId, time.toString()); - // Execute event - if(event.getType() == NodeEvent.EventType.SEND_MESSAGE){ - // Send Message - emit("%d: perform send_message at %s",myId,time.toString()); - Message m = new Message(); - m.add("time",time.toString()); // In each message the time needs to be send - sendUnicast(event.getReceiverNode(),m); - }else{ - // Do some inner event - emit("%d: perform inner_event at %s",myId,time.toString()); - handleInnerEvent(); - } + protected void sendUnicast ( int receiver_id, String m ) { + //time.incrementMyTime(); + //super.sendUnicast(receiver_id, m); } - // Nodes within the network can handle events differently. - // That's why this class is abstract and child classes can define their own reactions to events. - - /*** - * Defines the inner event of the node - */ - protected abstract void handleInnerEvent(); - - /*** - * Defines what happens after a message was received - */ - protected abstract void handleReceivingMessage(); - - /*** - * Defines what happens at the start of the simulation - */ - protected abstract void handleStart(); + protected void sendUnicast ( int receiver_id, Message m ) { + time.incrementMyTime(); + emit("%d: perform Unicast at %s",myId,time.toString()); + super.sendUnicast(receiver_id, new MessageWithTime(m, time)); + } - /*** - * A message was received from a different node - * @param m - Message from the network - */ - private void receivedMessage(Message m){ - // Update the time with the new time information given in the message - time.updateTime(m.query("time")); + protected void sendBroadcast ( String m ) { + //time.incrementMyTime(); + //super.sendBroadcast(m); + } - // Do something with message - handleReceivingMessage(); + protected void sendBroadcast ( Message m ) { + time.incrementMyTime(); + emit("%d: perform Broadcast at %s",myId,time.toString()); + super.sendBroadcast(new MessageWithTime(m, time)); } - @Override - protected void main() { - handleStart(); - while (true) { - // Listen for messages - Network.Message m_raw = receive(); - if (m_raw == null) break; - Message m = Message.fromJson(m_raw.payload); - receivedMessage(m); + protected Network.Message receive () { + Network.Message m_raw = super.receive(); + if (m_raw != null) { + MessageWithTime m = MessageWithTime.fromJson(m_raw.payload); + // Update the time with the new time information given in the message + time.updateTime(m.getTime()); + + String m_type = m_raw.type == Network.MessageType.BROADCAST ? "Broadcast" : "Unicast"; + emit("%d: recieve %s at %s", myId, m_type,time.toString()); } + return m_raw; } + } diff --git a/src/main/java/dev/oxoo2a/sim4da/Time.java b/src/main/java/dev/oxoo2a/sim4da/Time.java index 2dcb3cf..095e4c3 100644 --- a/src/main/java/dev/oxoo2a/sim4da/Time.java +++ b/src/main/java/dev/oxoo2a/sim4da/Time.java @@ -18,4 +18,12 @@ public interface Time { * @param time_sender - time of the sender node in the string representation */ void updateTime(String time_sender); + + + /*** + * New time was received by a different node (sender). + * Now the time of the local node must be updated. + * @param time_sender - time of the sender node + */ + void updateTime(Time time_sender); } diff --git a/src/main/java/dev/oxoo2a/sim4da/LamportTime.java b/src/main/java/dev/oxoo2a/sim4da/times/LamportTime.java similarity index 52% rename from src/main/java/dev/oxoo2a/sim4da/LamportTime.java rename to src/main/java/dev/oxoo2a/sim4da/times/LamportTime.java index a765a21..f9496c3 100644 --- a/src/main/java/dev/oxoo2a/sim4da/LamportTime.java +++ b/src/main/java/dev/oxoo2a/sim4da/times/LamportTime.java @@ -1,9 +1,11 @@ -package dev.oxoo2a.sim4da; +package dev.oxoo2a.sim4da.times; + +import dev.oxoo2a.sim4da.Time; /*** * Implements the rules of the lamport time */ -public class LamportTime implements Time{ +public class LamportTime implements Time { private int time; @@ -30,4 +32,15 @@ public void updateTime(String time_sender) { // increment local time incrementMyTime(); } + + @Override + public void updateTime(Time time_sender) { + if(!( time_sender instanceof LamportTime)) + throw new IllegalArgumentException("Wrong time format"); + LamportTime l_time_sender = (LamportTime) time_sender; + if(l_time_sender.time > time) + time = l_time_sender.time; + // increment local time + incrementMyTime(); + } } diff --git a/src/main/java/dev/oxoo2a/sim4da/VectorTime.java b/src/main/java/dev/oxoo2a/sim4da/times/VectorTime.java similarity index 68% rename from src/main/java/dev/oxoo2a/sim4da/VectorTime.java rename to src/main/java/dev/oxoo2a/sim4da/times/VectorTime.java index 9e78a32..1fb049c 100644 --- a/src/main/java/dev/oxoo2a/sim4da/VectorTime.java +++ b/src/main/java/dev/oxoo2a/sim4da/times/VectorTime.java @@ -1,4 +1,6 @@ -package dev.oxoo2a.sim4da; +package dev.oxoo2a.sim4da.times; + +import dev.oxoo2a.sim4da.Time; import java.util.Arrays; @@ -42,4 +44,15 @@ public void updateTime(String time_sender) { time[i] = sender_i_int; } } + + @Override + public void updateTime(Time time_sender) { + if(!( time_sender instanceof VectorTime)) + throw new IllegalArgumentException("Wrong time format"); + VectorTime v_time_sender = (VectorTime) time_sender; + for(int i = 0; i < time.length; i++){ + if(v_time_sender.time[i] > time[i]) + time[i] = v_time_sender.time[i]; + } + } } diff --git a/src/test/java/dev/oxoo2a/sim4da/NodeWithTimeTest.java b/src/test/java/dev/oxoo2a/sim4da/NodeWithTimeTest.java index a1d4fb3..9a1d688 100644 --- a/src/test/java/dev/oxoo2a/sim4da/NodeWithTimeTest.java +++ b/src/test/java/dev/oxoo2a/sim4da/NodeWithTimeTest.java @@ -1,5 +1,8 @@ package dev.oxoo2a.sim4da; +import dev.oxoo2a.sim4da.nodes.NodeWithTimeRandom; +import dev.oxoo2a.sim4da.times.LamportTime; +import dev.oxoo2a.sim4da.times.VectorTime; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.fail; @@ -31,13 +34,11 @@ private static void test(TimeType type){ nodes[id] = n; } try { - s.runSimulation(3); - nodes[0].performEvent(new NodeEvent(NodeEvent.EventType.INNER, -1)); + s.runSimulation(2); } catch (InstantiationException ignored) { fail("Not all nodes instantiated"); } - NodeEvent.printAllEvents(); } @Test diff --git a/src/test/java/dev/oxoo2a/sim4da/SimulatorTest.java b/src/test/java/dev/oxoo2a/sim4da/SimulatorTest.java index 7476fdc..c17a709 100644 --- a/src/test/java/dev/oxoo2a/sim4da/SimulatorTest.java +++ b/src/test/java/dev/oxoo2a/sim4da/SimulatorTest.java @@ -2,8 +2,7 @@ import static org.junit.jupiter.api.Assertions.*; -import java.beans.Transient; - +import dev.oxoo2a.sim4da.nodes.BroadcastNode; import org.junit.jupiter.api.Test; public class SimulatorTest { diff --git a/src/test/java/dev/oxoo2a/sim4da/TokenRingTest.java b/src/test/java/dev/oxoo2a/sim4da/TokenRingTest.java index bbe47d0..86c49e5 100644 --- a/src/test/java/dev/oxoo2a/sim4da/TokenRingTest.java +++ b/src/test/java/dev/oxoo2a/sim4da/TokenRingTest.java @@ -1,6 +1,6 @@ package dev.oxoo2a.sim4da; -import dev.oxoo2a.sim4da.Simulator; +import dev.oxoo2a.sim4da.nodes.TokenRingNode; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.fail; diff --git a/src/test/java/dev/oxoo2a/sim4da/BroadcastNode.java b/src/test/java/dev/oxoo2a/sim4da/nodes/BroadcastNode.java similarity index 93% rename from src/test/java/dev/oxoo2a/sim4da/BroadcastNode.java rename to src/test/java/dev/oxoo2a/sim4da/nodes/BroadcastNode.java index 0f73569..ce0ca2b 100644 --- a/src/test/java/dev/oxoo2a/sim4da/BroadcastNode.java +++ b/src/test/java/dev/oxoo2a/sim4da/nodes/BroadcastNode.java @@ -1,4 +1,8 @@ -package dev.oxoo2a.sim4da; +package dev.oxoo2a.sim4da.nodes; + +import dev.oxoo2a.sim4da.Message; +import dev.oxoo2a.sim4da.Network; +import dev.oxoo2a.sim4da.Node; import java.util.Random; diff --git a/src/test/java/dev/oxoo2a/sim4da/NodeWithTimeRandom.java b/src/test/java/dev/oxoo2a/sim4da/nodes/NodeWithTimeRandom.java similarity index 65% rename from src/test/java/dev/oxoo2a/sim4da/NodeWithTimeRandom.java rename to src/test/java/dev/oxoo2a/sim4da/nodes/NodeWithTimeRandom.java index fc99c0f..e3b7b43 100644 --- a/src/test/java/dev/oxoo2a/sim4da/NodeWithTimeRandom.java +++ b/src/test/java/dev/oxoo2a/sim4da/nodes/NodeWithTimeRandom.java @@ -1,11 +1,16 @@ -package dev.oxoo2a.sim4da; +package dev.oxoo2a.sim4da.nodes; + +import dev.oxoo2a.sim4da.Message; +import dev.oxoo2a.sim4da.Network; +import dev.oxoo2a.sim4da.NodeWithTime; +import dev.oxoo2a.sim4da.Time; import java.util.Random; /*** * A node with a logic clock that performs some random actions when a event is triggered */ -public class NodeWithTimeRandom extends NodeWithTime{ +public class NodeWithTimeRandom extends NodeWithTime { private final int n_nodes; @@ -14,21 +19,14 @@ public NodeWithTimeRandom(int id, Time time, int n_nodes){ this.n_nodes = n_nodes; } - /*** - * when the simulation starts the first node sends a message to the second - */ - @Override - protected void handleStart() { - if (myId == 0) { - performEvent(new NodeEvent(NodeEvent.EventType.SEND_MESSAGE, 1)); - } - } + /*** * The inner event of the node is sleeping/pausing for some milliseconds */ - @Override - protected void handleInnerEvent() { + protected void innerEvent() { + time.incrementMyTime(); + emit("%d: perform Inner Event at %s",myId,time.toString()); try { Thread.sleep(2 * 100L); } @@ -40,7 +38,6 @@ protected void handleInnerEvent() { * By random the events can be INNER or SEND_MESSAGE. * At leased one SEND_MESSAGE must be performed so that the network continuous to do something. */ - @Override protected void handleReceivingMessage() { boolean sendPerformed = false; @@ -54,20 +51,34 @@ protected void handleReceivingMessage() { // send message to a random receiving node int randReceiverNodeId = rand.nextInt(n_nodes); if(randReceiverNodeId != myId){ - performEvent(new NodeEvent(NodeEvent.EventType.SEND_MESSAGE, randReceiverNodeId)); + sendUnicast(randReceiverNodeId, new Message()); sendPerformed = true; } }else{ // do inner event - performEvent(new NodeEvent(NodeEvent.EventType.INNER, -1)); + innerEvent(); } } // Make sure that at leased one message was send if(!sendPerformed){ - performEvent(new NodeEvent(NodeEvent.EventType.SEND_MESSAGE, (myId+1) % n_nodes)); + sendUnicast((myId+1) % n_nodes, new Message()); } } + @Override + protected void main() { + //Message m = new Message(); + if (myId == 0) { + sendUnicast(1, new Message()); + } + while (true) { + // Listen for messages + Network.Message m_raw = receive(); + if (m_raw == null) break; + // Message received + handleReceivingMessage(); + } + } } diff --git a/src/main/java/dev/oxoo2a/sim4da/TokenRingNode.java b/src/test/java/dev/oxoo2a/sim4da/nodes/TokenRingNode.java similarity index 86% rename from src/main/java/dev/oxoo2a/sim4da/TokenRingNode.java rename to src/test/java/dev/oxoo2a/sim4da/nodes/TokenRingNode.java index 78e6ad4..8f0c65a 100644 --- a/src/main/java/dev/oxoo2a/sim4da/TokenRingNode.java +++ b/src/test/java/dev/oxoo2a/sim4da/nodes/TokenRingNode.java @@ -1,4 +1,8 @@ -package dev.oxoo2a.sim4da; +package dev.oxoo2a.sim4da.nodes; + +import dev.oxoo2a.sim4da.Message; +import dev.oxoo2a.sim4da.Network; +import dev.oxoo2a.sim4da.Node; public class TokenRingNode extends Node { From 439217637bc80d5610c0addfa96c12b6a71a5519 Mon Sep 17 00:00:00 2001 From: Tessa Date: Thu, 6 Jul 2023 18:44:03 +0200 Subject: [PATCH 3/5] MessageWithTime included in Message --- src/main/java/dev/oxoo2a/sim4da/Message.java | 39 +++++++++++----- .../dev/oxoo2a/sim4da/MessageWithTime.java | 45 ------------------- .../java/dev/oxoo2a/sim4da/NodeWithTime.java | 36 ++++++++++----- .../dev/oxoo2a/sim4da/NodeWithTimeTest.java | 3 +- .../sim4da/nodes/NodeWithTimeRandom.java | 2 +- 5 files changed, 55 insertions(+), 70 deletions(-) delete mode 100644 src/main/java/dev/oxoo2a/sim4da/MessageWithTime.java diff --git a/src/main/java/dev/oxoo2a/sim4da/Message.java b/src/main/java/dev/oxoo2a/sim4da/Message.java index 322a95c..aaf164e 100644 --- a/src/main/java/dev/oxoo2a/sim4da/Message.java +++ b/src/main/java/dev/oxoo2a/sim4da/Message.java @@ -1,21 +1,42 @@ package dev.oxoo2a.sim4da; -import java.lang.reflect.Type; import java.util.HashMap; import java.util.Map; import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; public class Message { + private final String time; + public Message () { - content = new HashMap<>(); + this(new HashMap<>(), ""); } - protected Message ( HashMap content ) { + this(content, ""); + } + public Message(Time time){ + this(new HashMap<>(), time.toString()); + } + public Message(Message m, Time time){ + this(m.content, time); + } + public Message(HashMap content, Time time){ + this(content, time.toString()); + } + public Message(HashMap content, String time){ this.content = content; + this.time = time; } + + public boolean hasTime(){ + return !time.equals(""); + } + + public String getTime(){ + return time; + } + public Message add ( String key, String value ) { content.put(key,value); return this; @@ -24,7 +45,6 @@ public Message add ( String key, String value ) { public Message add ( String key, int value ) { content.put(key,String.valueOf(value)); return this; - } public String query ( String key ) { @@ -36,16 +56,15 @@ public Map getMap () { } public String toJson () { - return serialize(content); + return serialize(this); } public static Message fromJson ( String s ) { - Type contentType = new TypeToken>() {}.getType(); - return new Message(serializer.fromJson(s,contentType)); + return serializer.fromJson(s, Message.class); } - private static synchronized String serialize ( Map content ) { - return serializer.toJson(content); // Not sure about thread safety of Gson + private static synchronized String serialize ( Message m ) { + return serializer.toJson(m); // Not sure about thread safety of Gson } protected final HashMap content; diff --git a/src/main/java/dev/oxoo2a/sim4da/MessageWithTime.java b/src/main/java/dev/oxoo2a/sim4da/MessageWithTime.java deleted file mode 100644 index 1ddcef2..0000000 --- a/src/main/java/dev/oxoo2a/sim4da/MessageWithTime.java +++ /dev/null @@ -1,45 +0,0 @@ -package dev.oxoo2a.sim4da; - -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; - -import java.lang.reflect.Type; -import java.util.HashMap; -import java.util.Map; - -public class MessageWithTime extends Message{ - - private final String time; - - public MessageWithTime(Time time){ - super(); - this.time = time.toString(); - } - public MessageWithTime(HashMap content, Time time){ - super(content); - this.time = time.toString(); - } - public MessageWithTime(Message m, Time time){ - this(m.content, time); - } - - public String getTime(){return time;} - - public String toJson () { - return serialize(this); - } - - public static MessageWithTime fromJson ( String s ) { - //Type contentType = new TypeToken>() {}.getType(); - //return new Message(serializer.fromJson(s,contentType)); - return serializer.fromJson(s, MessageWithTime.class); - } - - private static synchronized String serialize ( MessageWithTime m ) { - //HashMap, > - String s = serializer.toJson(m); // Not sure about thread safety of Gson - return s; - } - - -} diff --git a/src/main/java/dev/oxoo2a/sim4da/NodeWithTime.java b/src/main/java/dev/oxoo2a/sim4da/NodeWithTime.java index 2d00c47..bcf9ab4 100644 --- a/src/main/java/dev/oxoo2a/sim4da/NodeWithTime.java +++ b/src/main/java/dev/oxoo2a/sim4da/NodeWithTime.java @@ -7,43 +7,55 @@ public abstract class NodeWithTime extends Node { protected final Time time; // manages the time according to the rules in the class of the logic clock + private final boolean logTime; public NodeWithTime(int my_id, Time time) { + this(my_id, time, false); + } + public NodeWithTime(int my_id, Time time, boolean logTime) { super(my_id); this.time = time; + this.logTime = logTime; } protected void sendUnicast ( int receiver_id, String m ) { - //time.incrementMyTime(); - //super.sendUnicast(receiver_id, m); + time.incrementMyTime(); + emit("Warning: Can not update time in message!"); + if(logTime) emit("%d: perform Unicast at %s",myId,time.toString()); + super.sendUnicast(receiver_id, m); // WARNING: can not update time in message } protected void sendUnicast ( int receiver_id, Message m ) { time.incrementMyTime(); - emit("%d: perform Unicast at %s",myId,time.toString()); - super.sendUnicast(receiver_id, new MessageWithTime(m, time)); + if(logTime) emit("%d: perform Unicast at %s",myId,time.toString()); + super.sendUnicast(receiver_id, new Message(m, time)); } protected void sendBroadcast ( String m ) { - //time.incrementMyTime(); - //super.sendBroadcast(m); + time.incrementMyTime(); + emit("Warning: Can not update time in message!"); + if(logTime) emit("%d: perform Broadcast at %s",myId,time.toString()); + super.sendBroadcast(m); // WARNING: can not update time in message } protected void sendBroadcast ( Message m ) { time.incrementMyTime(); - emit("%d: perform Broadcast at %s",myId,time.toString()); - super.sendBroadcast(new MessageWithTime(m, time)); + if(logTime) emit("%d: perform Broadcast at %s",myId,time.toString()); + super.sendBroadcast(new Message(m, time)); } protected Network.Message receive () { Network.Message m_raw = super.receive(); if (m_raw != null) { - MessageWithTime m = MessageWithTime.fromJson(m_raw.payload); + Message m = Message.fromJson(m_raw.payload); // Update the time with the new time information given in the message - time.updateTime(m.getTime()); + if(m.hasTime()) + time.updateTime(m.getTime()); - String m_type = m_raw.type == Network.MessageType.BROADCAST ? "Broadcast" : "Unicast"; - emit("%d: recieve %s at %s", myId, m_type,time.toString()); + if(logTime) { + String m_type = m_raw.type == Network.MessageType.BROADCAST ? "Broadcast" : "Unicast"; + emit("%d: receive %s at %s", myId, m_type,time.toString()); + } } return m_raw; } diff --git a/src/test/java/dev/oxoo2a/sim4da/NodeWithTimeTest.java b/src/test/java/dev/oxoo2a/sim4da/NodeWithTimeTest.java index 9a1d688..e7bcb32 100644 --- a/src/test/java/dev/oxoo2a/sim4da/NodeWithTimeTest.java +++ b/src/test/java/dev/oxoo2a/sim4da/NodeWithTimeTest.java @@ -9,6 +9,7 @@ /*** * Test nodes with logic clocks + * @author Tessa Steinigke */ public class NodeWithTimeTest { @@ -22,7 +23,6 @@ public enum TimeType { LAMPORT, VECTOR } */ private static void test(TimeType type){ Simulator s = Simulator.createDefaultSimulator(n_nodes); - NodeWithTime[] nodes = new NodeWithTime[n_nodes]; for (int id=0; id Date: Thu, 6 Jul 2023 18:48:01 +0200 Subject: [PATCH 4/5] Simulation of a terminating process with watchers --- .../dev/oxoo2a/sim4da/TerminationTest.java | 45 ++++++++ .../sim4da/nodes/PassAlongRandomNode.java | 107 ++++++++++++++++++ .../nodes/TerminatorControlVectorNode.java | 64 +++++++++++ .../nodes/TerminatorDoubleCountingNode.java | 94 +++++++++++++++ 4 files changed, 310 insertions(+) create mode 100644 src/test/java/dev/oxoo2a/sim4da/TerminationTest.java create mode 100644 src/test/java/dev/oxoo2a/sim4da/nodes/PassAlongRandomNode.java create mode 100644 src/test/java/dev/oxoo2a/sim4da/nodes/TerminatorControlVectorNode.java create mode 100644 src/test/java/dev/oxoo2a/sim4da/nodes/TerminatorDoubleCountingNode.java diff --git a/src/test/java/dev/oxoo2a/sim4da/TerminationTest.java b/src/test/java/dev/oxoo2a/sim4da/TerminationTest.java new file mode 100644 index 0000000..2631a69 --- /dev/null +++ b/src/test/java/dev/oxoo2a/sim4da/TerminationTest.java @@ -0,0 +1,45 @@ +package dev.oxoo2a.sim4da; + +import dev.oxoo2a.sim4da.nodes.PassAlongRandomNode; +import dev.oxoo2a.sim4da.nodes.TerminatorControlVectorNode; +import dev.oxoo2a.sim4da.nodes.TerminatorDoubleCountingNode; +import dev.oxoo2a.sim4da.times.LamportTime; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.fail; + +/** + * Test PassAlongRandomNode with TerminatorControlVectorNode and TerminatorDoubleCountingNode + * @author Tessa Steinigke + */ +public class TerminationTest { + + private static final int n_nodes = 10; + private static final int p_prob = 1; + + /*** + * Tests the token Ring + */ + @Test + public void termination() { + Simulator s = Simulator.createDefaultSimulator(n_nodes+2); + // Init nodes + for (int id=0; id 0) running = true; + } + + // Check termination + if(!running){ + // TERMINATED + emit("!! TERMINATION DETECTED BY FOLLOWING-VECTOR-METHODE"); + }else{ + // Not terminated + send_request(); + } + } + + @Override + protected void main() { + send_request(); + while (true) { + // Listen for messages + Network.Message m_raw = receive(); + if (m_raw == null) break; + // Message received + receive_status(Message.fromJson(m_raw.payload)); + } + } +} diff --git a/src/test/java/dev/oxoo2a/sim4da/nodes/TerminatorDoubleCountingNode.java b/src/test/java/dev/oxoo2a/sim4da/nodes/TerminatorDoubleCountingNode.java new file mode 100644 index 0000000..41528ff --- /dev/null +++ b/src/test/java/dev/oxoo2a/sim4da/nodes/TerminatorDoubleCountingNode.java @@ -0,0 +1,94 @@ +package dev.oxoo2a.sim4da.nodes; + +import dev.oxoo2a.sim4da.*; + +/** + * Doppelzählverfahren zur Bestimmung der Terminierung + * @author Tessa Steinigke + */ +public class TerminatorDoubleCountingNode extends Node { + + private int n_nodes; + + /** + * [Interval 1: sums of send|received|active], + * [Interval 2: sums of send|received|active] + */ + private int[][] statistics; + private int statistics_interval = 0; + private int c_statistics_missing = n_nodes; + + public TerminatorDoubleCountingNode(int my_id, int n_nodes) { + super(my_id); + this.n_nodes = n_nodes; + statistics = new int[2][3]; + } + + private void send_request(){ + c_statistics_missing = n_nodes; + Message m = new Message(); + m.add("request","send/received"); + sendBroadcast(m); + } + + private void receive_status(Message m){ + if(m.query("request")!= null) return; // Ignore requests + + c_statistics_missing--; + // Add statistics + statistics[statistics_interval][0] += Integer.parseInt(m.query("send")); + statistics[statistics_interval][1] += Integer.parseInt(m.query("received")); + statistics[statistics_interval][2] += (m.query("status").equals("active") ? 1 : 0 ); + + // Analyse + if(c_statistics_missing == 0){ + // All answers received + if(statistics_interval == 0) { + // first loop + statistics_interval = 1; + send_request(); + return; + } + + //emit("0 missing: (%d,%d,%d),(%d,%d,%d)", stati[0][0], stati[0][1], stati[0][2], stati[1][0], stati[1][1], stati[1][2]); + + // Check terminated + // 1. check all passive + boolean terminated = (statistics[0][2] + statistics[1][2] == 0); + if(terminated){ + //2. Check values + int val = statistics[0][0]; + terminated = (val == statistics[0][1]) & (val == statistics[1][0]) & (val == statistics[1][1]); + if(terminated){ + // TERMINATED + emit("!! TERMINATION DETECTED BY DOUBLE-COUNTING-METHODE"); + return; + } + } + + // Not terminated + if(statistics[1][0] == statistics[1][1]){ + // Last attempt could indicate termination + statistics[0] = statistics[1]; // shift last to new first + statistics[1] = new int[3]; // empty new last + }else{ + // Last attempt already indicates no termination -> can be deleted + statistics = new int[2][3]; + statistics_interval = 0; + } + send_request(); + } + } + + @Override + protected void main() { + send_request(); + while (true) { + // Listen for messages + Network.Message m_raw = receive(); + if (m_raw == null) break; + // Message received + receive_status(Message.fromJson(m_raw.payload)); + } + } +} From bc9202449cd6dbb6e8737f43bc71ca6711e1a3b1 Mon Sep 17 00:00:00 2001 From: Tessa Date: Thu, 6 Jul 2023 18:59:57 +0200 Subject: [PATCH 5/5] Terminator more elegant --- .../dev/oxoo2a/sim4da/TerminationTest.java | 7 +++- .../dev/oxoo2a/sim4da/nodes/Terminator.java | 39 +++++++++++++++++++ .../nodes/TerminatorControlVectorNode.java | 23 +++-------- .../nodes/TerminatorDoubleCountingNode.java | 23 +++-------- 4 files changed, 55 insertions(+), 37 deletions(-) create mode 100644 src/test/java/dev/oxoo2a/sim4da/nodes/Terminator.java diff --git a/src/test/java/dev/oxoo2a/sim4da/TerminationTest.java b/src/test/java/dev/oxoo2a/sim4da/TerminationTest.java index 2631a69..db810be 100644 --- a/src/test/java/dev/oxoo2a/sim4da/TerminationTest.java +++ b/src/test/java/dev/oxoo2a/sim4da/TerminationTest.java @@ -18,7 +18,7 @@ public class TerminationTest { private static final int p_prob = 1; /*** - * Tests the token Ring + * Tests the termination */ @Test public void termination() { @@ -40,6 +40,11 @@ public void termination() { catch (InstantiationException ignored) { fail("Not all nodes instantiated"); } + + if(!w_dd.hasTermination_detected()) + fail("Double counting methode did not detect termination"); + if(!w_cv.hasTermination_detected()) + fail("Following vector methode did not detect termination"); } } diff --git a/src/test/java/dev/oxoo2a/sim4da/nodes/Terminator.java b/src/test/java/dev/oxoo2a/sim4da/nodes/Terminator.java new file mode 100644 index 0000000..1304222 --- /dev/null +++ b/src/test/java/dev/oxoo2a/sim4da/nodes/Terminator.java @@ -0,0 +1,39 @@ +package dev.oxoo2a.sim4da.nodes; + +import dev.oxoo2a.sim4da.Message; +import dev.oxoo2a.sim4da.Network; +import dev.oxoo2a.sim4da.Node; + +public abstract class Terminator extends Node { + + protected final int n_nodes; + + protected boolean termination_detected = false; + + public Terminator(int my_id, int n_nodes) { + super(my_id); + this.n_nodes = n_nodes; + } + + protected abstract void send_request(); + + protected abstract void receive_status(Message m); + + public boolean hasTermination_detected(){ + return termination_detected; + } + + @Override + protected void main() { + send_request(); + while (true) { + if(termination_detected) break; + // Listen for messages + Network.Message m_raw = receive(); + if (m_raw == null) break; + // Message received + receive_status(Message.fromJson(m_raw.payload)); + } + } + +} diff --git a/src/test/java/dev/oxoo2a/sim4da/nodes/TerminatorControlVectorNode.java b/src/test/java/dev/oxoo2a/sim4da/nodes/TerminatorControlVectorNode.java index 8cccd03..c25de7d 100644 --- a/src/test/java/dev/oxoo2a/sim4da/nodes/TerminatorControlVectorNode.java +++ b/src/test/java/dev/oxoo2a/sim4da/nodes/TerminatorControlVectorNode.java @@ -8,27 +8,24 @@ * Nachlaufender Kontrollvector zur Bestimmung der Terminierung * @author Tessa Steinigke */ -public class TerminatorControlVectorNode extends Node { - - private final int n_nodes; +public class TerminatorControlVectorNode extends Terminator { private final int[] statistics; private int node_request_next_statistics = 0; public TerminatorControlVectorNode(int my_id, int n_nodes) { - super(my_id); - this.n_nodes = n_nodes; + super(my_id, n_nodes); statistics = new int[n_nodes]; } - private void send_request(){ + protected void send_request(){ Message m = new Message(); m.add("request","vector"); sendUnicast(node_request_next_statistics, m); node_request_next_statistics = (node_request_next_statistics +1) % n_nodes; } - private void receive_status(Message m){ + protected void receive_status(Message m){ if(m.query("request")!= null) return; // Ignore requests String sender_v_s = m.query("vector"); @@ -43,6 +40,7 @@ private void receive_status(Message m){ // Check termination if(!running){ // TERMINATED + termination_detected = true; emit("!! TERMINATION DETECTED BY FOLLOWING-VECTOR-METHODE"); }else{ // Not terminated @@ -50,15 +48,4 @@ private void receive_status(Message m){ } } - @Override - protected void main() { - send_request(); - while (true) { - // Listen for messages - Network.Message m_raw = receive(); - if (m_raw == null) break; - // Message received - receive_status(Message.fromJson(m_raw.payload)); - } - } } diff --git a/src/test/java/dev/oxoo2a/sim4da/nodes/TerminatorDoubleCountingNode.java b/src/test/java/dev/oxoo2a/sim4da/nodes/TerminatorDoubleCountingNode.java index 41528ff..1249ea2 100644 --- a/src/test/java/dev/oxoo2a/sim4da/nodes/TerminatorDoubleCountingNode.java +++ b/src/test/java/dev/oxoo2a/sim4da/nodes/TerminatorDoubleCountingNode.java @@ -6,9 +6,7 @@ * Doppelzählverfahren zur Bestimmung der Terminierung * @author Tessa Steinigke */ -public class TerminatorDoubleCountingNode extends Node { - - private int n_nodes; +public class TerminatorDoubleCountingNode extends Terminator { /** * [Interval 1: sums of send|received|active], @@ -19,19 +17,18 @@ public class TerminatorDoubleCountingNode extends Node { private int c_statistics_missing = n_nodes; public TerminatorDoubleCountingNode(int my_id, int n_nodes) { - super(my_id); - this.n_nodes = n_nodes; + super(my_id, n_nodes); statistics = new int[2][3]; } - private void send_request(){ + protected void send_request(){ c_statistics_missing = n_nodes; Message m = new Message(); m.add("request","send/received"); sendBroadcast(m); } - private void receive_status(Message m){ + protected void receive_status(Message m){ if(m.query("request")!= null) return; // Ignore requests c_statistics_missing--; @@ -61,6 +58,7 @@ private void receive_status(Message m){ terminated = (val == statistics[0][1]) & (val == statistics[1][0]) & (val == statistics[1][1]); if(terminated){ // TERMINATED + termination_detected = true; emit("!! TERMINATION DETECTED BY DOUBLE-COUNTING-METHODE"); return; } @@ -80,15 +78,4 @@ private void receive_status(Message m){ } } - @Override - protected void main() { - send_request(); - while (true) { - // Listen for messages - Network.Message m_raw = receive(); - if (m_raw == null) break; - // Message received - receive_status(Message.fromJson(m_raw.payload)); - } - } }