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: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ leader_directed_ring_example:
go run example/leader_directed_ring_sync.go 10 peterson
go run example/leader_directed_ring_async.go 10 higham_przytycka
go run example/leader_directed_ring_async.go 10 itai_rodeh
go run example/leader_directed_ring_async_hirschberg_sinclair.go 10

leader_undirected_ring_example:
go run example/leader_undirected_ring_sync_hirschberg_sinclair.go 10
go run example/leader_undirected_ring_sync_franklin.go 10
go run example/leader_undirected_ring_sync_prob_as_far.go 10
go run example/leader_undirected_ring_async_hirschberg_sinclair.go 10
go run example/leader_undirected_ring_async_hirschberg_sinclair_2.go 10
go run example/leader_undirected_ring_async_stages_with_feedback.go 10
go run example/leader_undirected_ring_async_franklin.go 10
go run example/leader_undirected_ring_async_probabilistic_franklin.go 10 3
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ A collection of algorithms for _Distributed Systems_ course (winter semesters 20
1. Dolev-Klawe-Rodeh algorithm B
1. Itai-Rodeh algorithm
1. Higham-Przytycka algorithm
1. Hirschberg-Sinclair algorithm

#### Asynchronous undirected ring
1. Franklin algorithm
Expand Down
13 changes: 13 additions & 0 deletions example/leader_directed_ring_async_hirschberg_sinclair.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package main

import (
"os"
"strconv"

"github.com/krzysztof-turowski/distributed-framework/leader/directed_ring/async_hirschberg_sinclair"
)

func main() {
n, _ := strconv.Atoi(os.Args[len(os.Args)-1])
async_hirschberg_sinclair.Run(n)
}
13 changes: 13 additions & 0 deletions example/leader_undirected_ring_async_hirschberg_sinclair_2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package main

import (
"os"
"strconv"

"github.com/krzysztof-turowski/distributed-framework/leader/undirected_ring/async_hirschberg_sinclair_2"
)

func main() {
n, _ := strconv.Atoi(os.Args[len(os.Args)-1])
async_hirschberg_sinclair_2.Run(n)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
package async_hirschberg_sinclair

import (
"encoding/json"
"fmt"
"github.com/krzysztof-turowski/distributed-framework/lib"
"log"
)

type ElectionStatus string
type MessageType string

const (
CandidateStatus ElectionStatus = "candidate"
LostStatus ElectionStatus = "lost"
WonStatus ElectionStatus = "won"
)
const (
No MessageType = "no"
Ok MessageType = "ok"
From MessageType = "from"
End MessageType = "end"
)

type message struct {
MessageType MessageType
Value int
Num uint64
Maxnum uint64
}

type state struct {
MyStatus ElectionStatus
}

func initialize(v lib.Node) bool {
s := state{MyStatus: CandidateStatus}
sEncoded, _ := json.Marshal(s)
v.SetState(sEncoded)

data := message{From, v.GetIndex(), 0, 1}
initiateSendingDataClockwise(v, data)
return false
}

func process(v lib.Node) bool {
maxnum := uint64(1)
var jsonReceived []byte
var chanIndex int
var receivedData message
//counter := 0
final := false
var s state
for {
chanIndex, jsonReceived = v.ReceiveAnyMessage()
_ = json.Unmarshal(jsonReceived, &receivedData)
_ = json.Unmarshal(v.GetState(), &s)

switch receivedData.MessageType {
case From:
receivedMessageIsFrom(v, receivedData, chanIndex)
_ = json.Unmarshal(v.GetState(), &s)
if s.MyStatus == WonStatus {
dataToSend := message{End, v.GetIndex(), 0, maxnum}
sendPassClockwise(v, &dataToSend, chanIndex)
}

case No, Ok:
receivedMessageIsOkOrNo(v, receivedData, chanIndex)
_ = json.Unmarshal(v.GetState(), &s)
if receivedData.MessageType == No {
s.MyStatus = LostStatus
}
if receivedData.Value == v.GetIndex() {
if s.MyStatus == CandidateStatus {
maxnum *= 2
dataToSend := initSendingData(From, v.GetIndex(), 0, maxnum)
initiateSendingDataClockwise(v, dataToSend)
}
}
case End:
if s.MyStatus == LostStatus {
sendPassClockwise(v, &receivedData, chanIndex)
}
final = true

default:
//nothing to do
}

sEncoded, _ := json.Marshal(s)
v.SetState(sEncoded)

if final {
break
}
}

if s.MyStatus == WonStatus {
log.Println("The Leader has index ", v.GetIndex())
}
return true
}

func run(v lib.Node) {
v.StartProcessing()
isFinished := initialize(v)

isFinished = process(v)
v.FinishProcessing(isFinished)
}

func check(vertices []lib.Node) {
var leader lib.Node
var s state
for _, v := range vertices {
_ = json.Unmarshal(v.GetState(), &s)
if s.MyStatus == WonStatus {
leader = v
break
}
}
if leader == nil {
panic("There is no Leader on the undirected ring")
}
for _, v := range vertices {
_ = json.Unmarshal(v.GetState(), &s)
if v != leader {
if s.MyStatus == WonStatus {
panic(fmt.Sprint(
"There is more then one Leader on the undirected ring"))
}
if s.MyStatus == CandidateStatus {
panic(fmt.Sprint("Node ", v.GetIndex(), " has state ", CandidateStatus))
}
} else {
if s.MyStatus != WonStatus {
panic("There is more then one Leader on the undirected ring")
}
}
}
}

func Run(n int) (int, int) {
vertices, synchronizer := lib.BuildSynchronizedRingWithOriginalTopology(n)
for _, v := range vertices {
log.Println("Node", v.GetIndex(), "about to run")
go run(v)
}
synchronizer.Synchronize(0)
check(vertices)

return synchronizer.GetStats()
}

func initiateSendingDataClockwise(v lib.Node, dataToSend message) {
jsonToSend, _ := json.Marshal(dataToSend)
v.SendMessage(1, jsonToSend)
}

func abs(n int) int {
if n < 0 {
return -n
}
return n
}

func getChanToPrev(chanIndex int) int {
return chanIndex
}

func getChanToNext(chanIndex int) int {
return abs(chanIndex - 1)
}

func sendReplyCounterclockwise(v lib.Node, dataToSend *message, chanIndex int) {
channel := getChanToPrev(chanIndex)
jsonToSend, _ := json.Marshal(dataToSend)
v.SendMessage(channel, jsonToSend)
}

func sendPassClockwise(v lib.Node, dataToSend *message, chanIndex int) {
channel := getChanToNext(chanIndex)
jsonToSend, _ := json.Marshal(dataToSend)
v.SendMessage(channel, jsonToSend)
}

func receivedMessageIsFrom(v lib.Node, receivedData message, chanIndex int) {
if receivedData.Value < v.GetIndex() {
dataToSend := initSendingData(No, receivedData.Value, 0, 0)
sendReplyCounterclockwise(v, &dataToSend, chanIndex)
return
}
var s state
_ = json.Unmarshal(v.GetState(), &s)
if receivedData.Value > v.GetIndex() {
s.MyStatus = LostStatus
sEncoded, _ := json.Marshal(s)
v.SetState(sEncoded)
if receivedData.Num+1 < receivedData.Maxnum {
dataToSend := receivedData
dataToSend.Num += 1
sendPassClockwise(v, &dataToSend, chanIndex)
} else {
dataToSend := initSendingData(Ok, receivedData.Value, 0, 0)
sendReplyCounterclockwise(v, &dataToSend, chanIndex)
}
return
}

//value == v.GetIndex()
s.MyStatus = WonStatus
sEncoded, _ := json.Marshal(s)
v.SetState(sEncoded)
}

func receivedMessageIsOkOrNo(v lib.Node, receivedData message, chanIndex int) {
if receivedData.Value != v.GetIndex() {
sendPassClockwise(v, &receivedData, chanIndex)
} else {
//nice to see you back, my message!
}
}

func initSendingData(messageType MessageType, value int, num uint64, maxnum uint64) message {
return message{
MessageType: messageType,
Value: value,
Num: num,
Maxnum: maxnum,
}
}
Loading