Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -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
43 changes: 31 additions & 12 deletions src/main/java/dev/oxoo2a/sim4da/Message.java
Original file line number Diff line number Diff line change
@@ -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<String,String> 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<String,String> content, Time time){
this(content, time.toString());
}
public Message(HashMap<String,String> 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;
Expand All @@ -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 ) {
Expand All @@ -36,18 +56,17 @@ public Map<String,String> getMap () {
}

public String toJson () {
return serialize(content);
return serialize(this);
}

public static Message fromJson ( String s ) {
Type contentType = new TypeToken<HashMap<String,String>>() {}.getType();
return new Message(serializer.fromJson(s,contentType));
return serializer.fromJson(s, Message.class);
}

private static synchronized String serialize ( Map<String,String> 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
}

private final HashMap<String,String> content;
private static final Gson serializer = new Gson();
protected final HashMap<String,String> content;
protected static final Gson serializer = new Gson();
}
63 changes: 63 additions & 0 deletions src/main/java/dev/oxoo2a/sim4da/NodeWithTime.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package dev.oxoo2a.sim4da;

/***
* Node in the network that has a logic clock
* @author Tessa Steinigke
*/
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();
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();
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();
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();
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) {
Message m = Message.fromJson(m_raw.payload);
// Update the time with the new time information given in the message
if(m.hasTime())
time.updateTime(m.getTime());

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;
}

}
29 changes: 29 additions & 0 deletions src/main/java/dev/oxoo2a/sim4da/Time.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
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);


/***
* 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);
}
46 changes: 46 additions & 0 deletions src/main/java/dev/oxoo2a/sim4da/times/LamportTime.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package dev.oxoo2a.sim4da.times;

import dev.oxoo2a.sim4da.Time;

/***
* 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();
}

@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();
}
}
58 changes: 58 additions & 0 deletions src/main/java/dev/oxoo2a/sim4da/times/VectorTime.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package dev.oxoo2a.sim4da.times;

import dev.oxoo2a.sim4da.Time;

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;
}
}

@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];
}
}
}
53 changes: 53 additions & 0 deletions src/test/java/dev/oxoo2a/sim4da/NodeWithTimeTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
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;

/***
* Test nodes with logic clocks
* @author Tessa Steinigke
*/
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);
for (int id=0; id<n_nodes; id++) {
Time time;
if(type == TimeType.LAMPORT)
time = new LamportTime();
else
time = new VectorTime(id, n_nodes);
NodeWithTime n = new NodeWithTimeRandom(id, time, n_nodes);
s.attachNode(id,n);
}
try {
s.runSimulation(2);
}
catch (InstantiationException ignored) {
fail("Not all nodes instantiated");
}
}

@Test
public void testLamportTime(){
test(TimeType.LAMPORT);
}

@Test
public void testVectorTime() {
test(TimeType.VECTOR);
}

}
3 changes: 1 addition & 2 deletions src/test/java/dev/oxoo2a/sim4da/SimulatorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Loading