Skip to content

Commit 47a7fb2

Browse files
committed
added Lamport's logical clock syncronization in Go lang
1 parent cb34f6f commit 47a7fb2

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
Simulation of Lamport's Logical Clock Syncronization
3+
Sample Output Simulation : https://www.showterm.io/556636ec7caa4687680c0
4+
References : Distributed systems: Principles and Paradigms, Andrew S. Tanenbaum
5+
6+
The program takes the following input :
7+
nProcesses : total no. of processes in the system
8+
nIterations : no. of counter/clock iterations for which the output is generated
9+
clockConstant : the constant rate by which counter/clock is incremented on each tick
10+
11+
Output :
12+
The program randomly generates a message between any two distinct processes in the system on every 3rd iteration. The message is added to a message queue and read by the recipient on the next iteration. Based on the timestamp at which the message was sent and current time on the receiver, clock time of receiver is adjusted if timestamp of message is >= receiver time else left the same. >= because it will take a finite amount of time to send the message always.
13+
*/
14+
15+
package main
16+
17+
import (
18+
"fmt" //for println,scanf
19+
"math/rand" //for random number generator
20+
"time" //for sleep
21+
)
22+
23+
func main() {
24+
var nProcesses, nIterations int // Number of processes, Number of iterations
25+
fmt.Printf("Enter number of Processes and iterations you want to simulate : ")
26+
_, err := fmt.Scanf("%d %d", &nProcesses, &nIterations) // _ is blank identifier
27+
if err != nil {
28+
fmt.Println("Error : " + err.Error())
29+
}
30+
clockTable := [][]int{} //table to store final counter/logical clock values
31+
var clockConstants []int //slice to store values by which clock are incremented on each iteration
32+
clockConstants = make([]int, nProcesses, nProcesses)
33+
34+
fmt.Printf("Enter the clock constants for each process : ") //user input for clock constants
35+
for i := 0; i < nProcesses; i++ {
36+
_, err := fmt.Scanf("%d", &clockConstants[i])
37+
if err != nil {
38+
fmt.Println("Error : " + err.Error())
39+
}
40+
}
41+
42+
var initClock []int
43+
initClock = make([]int, nProcesses, nProcesses)
44+
clockTable = append(clockTable, initClock)
45+
var msgQueue []int //used to queue messages between processes.
46+
47+
//Print 1st iteration
48+
for i := 0; i < nProcesses; i++ {
49+
fmt.Printf(" P%d", i)
50+
}
51+
fmt.Println()
52+
for j := 1; j <= nProcesses; j++ {
53+
fmt.Printf("%4d", clockTable[0][j-1])
54+
}
55+
fmt.Println()
56+
57+
//Print other iterations
58+
for i := 1; i < nIterations; i++ { //first iteration already passed so start from 2nd
59+
60+
time.Sleep(2000 * time.Millisecond) //sleep to slow the program down
61+
62+
var temp []int
63+
temp = make([]int, nProcesses, nProcesses)
64+
for j := 1; j <= nProcesses; j++ {
65+
temp[j-1] = clockTable[i-1][j-1] + clockConstants[j-1]
66+
}
67+
clockTable = append(clockTable, temp)
68+
/* generate messages to be sent in every 3rd iteration */
69+
if (i+1)%3 == 0 {
70+
var senderID, receiverID int
71+
r := rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
72+
senderID = r.Intn(nProcesses)
73+
receiverID = r.Intn(nProcesses)
74+
/*if receiver turns out to be same as sender, find new receiver*/
75+
for receiverID == senderID {
76+
receiverID = r.Intn(nProcesses)
77+
}
78+
msgQueue = append(msgQueue, senderID, receiverID) // add message to queue
79+
fmt.Printf("Message sent by P%d to P%d at time t=%d at P1.\n", senderID, receiverID, clockTable[i-1][senderID])
80+
}
81+
for j := 0; j < nProcesses; j++ { //display clock values
82+
fmt.Printf("%4d", clockTable[i][j])
83+
}
84+
fmt.Println()
85+
86+
for len(msgQueue) >= 2 {
87+
var senderID, receiverID int = msgQueue[0], msgQueue[1]
88+
var sendTime, recTime int = clockTable[i-1][senderID], clockTable[i][receiverID]
89+
if clockTable[i-1][senderID] >= clockTable[i][receiverID] {
90+
fmt.Printf("Message received by P%d at time=%d. Since %d <= %d , we adjust time from %d to %d.\n", receiverID, recTime, recTime, sendTime, recTime, (sendTime + 1))
91+
for j := 0; j < nProcesses; j++ {
92+
fmt.Printf("%4d", clockTable[i][j])
93+
}
94+
fmt.Printf(" -->") //display changed clock values
95+
clockTable[i][receiverID] = clockTable[i-1][senderID] + 1
96+
for j := 0; j < nProcesses; j++ {
97+
fmt.Printf("%4d", clockTable[i][j])
98+
}
99+
fmt.Printf("\n")
100+
101+
} else {
102+
fmt.Printf("Message received by P%d at time=%d. Since %d >= %d , no time adjustment needed.\n", receiverID, recTime, recTime, sendTime)
103+
for j := 0; j < nProcesses; j++ {
104+
fmt.Printf("%4d", clockTable[i][j])
105+
}
106+
fmt.Printf(" =") //display clock values without change
107+
for j := 0; j < nProcesses; j++ {
108+
fmt.Printf("%4d", clockTable[i][j])
109+
}
110+
fmt.Printf("\n")
111+
}
112+
msgQueue = append(msgQueue[:0], msgQueue[2:]...) //remove sender and receiver from msg queue
113+
time.Sleep(2000 * time.Millisecond)
114+
}
115+
}
116+
}

0 commit comments

Comments
 (0)