Skip to content

Commit ac630f9

Browse files
Initial commit
1 parent a3ea636 commit ac630f9

File tree

9 files changed

+1357
-0
lines changed

9 files changed

+1357
-0
lines changed

array/array.go

+407
Large diffs are not rendered by default.

bfs/bfs.go

+209
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
//
2+
// bfs.go
3+
//
4+
// Created by Adrian Zubarev.
5+
// Copyright © 2016 Adrian Zubarev.
6+
// All rights reserved.
7+
//
8+
9+
package bfs
10+
11+
import . "fmt"
12+
import . "./command"
13+
import . "./../array"
14+
15+
import "sync"
16+
import "strings"
17+
18+
type Host interface {
19+
SendMessage(sender string, receiver string, command uint8, value interface{})
20+
}
21+
22+
type Node struct {
23+
once sync.Once
24+
guard sync.Mutex
25+
host Host
26+
id string
27+
parentID string
28+
treeLevel int64
29+
labeled bool
30+
neighbors *Array
31+
sendTo *Array
32+
children *Array
33+
echoedFrom map[string]bool
34+
}
35+
36+
func NodeWith(host Host, id string, neighbors []string) *Node {
37+
38+
var node = new(Node)
39+
node.Set(host, id, neighbors)
40+
return node
41+
}
42+
43+
func (node *Node) Set(host Host, id string, neighbors []string) *Node {
44+
45+
node.guard.Lock()
46+
var onceBody = func() {
47+
48+
node.host = host
49+
node.id = id
50+
node.parentID = ""
51+
node.treeLevel = -1
52+
node.labeled = false
53+
node.neighbors = ArrayOfType("string")
54+
55+
for _, neighborID := range neighbors {
56+
57+
node.neighbors.AppendUnique(neighborID)
58+
}
59+
60+
node.sendTo = ArrayOfType("string")
61+
node.children = ArrayOfType("string")
62+
node.echoedFrom = make(map[string]bool)
63+
}
64+
node.once.Do(onceBody)
65+
node.guard.Unlock()
66+
67+
return node
68+
}
69+
70+
func (node *Node) IsRoot() bool {
71+
72+
return strings.Compare(node.parentID, node.id) == 0
73+
}
74+
75+
func (node *Node) HandleMessage(sender string, receiver string, command uint8, value interface{}) {
76+
77+
node.guard.Lock()
78+
switch command {
79+
80+
case InitCommand:
81+
node.labeled = true
82+
node.parentID = node.id
83+
node.treeLevel = 0
84+
node.sendTo = node.neighbors.Clone()
85+
node.children.RemoveAll() // making array empty
86+
87+
if node.sendTo.IsEmpty() {
88+
89+
node.host.SendMessage(node.id, "server", CompleteCommand, nil)
90+
91+
} else {
92+
93+
for i := 0; i < node.sendTo.Count(); i++ {
94+
95+
var id = node.sendTo.ElementAtIndex(i).(string)
96+
node.echoedFrom[id] = false
97+
node.host.SendMessage(node.id, id, LabelCommand, node.treeLevel)
98+
}
99+
}
100+
101+
case LabelCommand:
102+
if node.labeled == false {
103+
104+
node.labeled = true
105+
node.parentID = sender
106+
node.treeLevel = value.(int64) + 1
107+
108+
node.sendTo = node.neighbors.Clone()
109+
node.sendTo.Remove(sender)
110+
node.children.RemoveAll()
111+
112+
if node.sendTo.IsEmpty() {
113+
114+
node.host.SendMessage(node.id, node.parentID, EndCommand, nil)
115+
116+
} else {
117+
118+
node.host.SendMessage(node.id, node.parentID, KeeponCommand, nil)
119+
}
120+
121+
} else {
122+
123+
if strings.Compare(node.parentID, sender) == 0 {
124+
125+
for i := 0; i < node.sendTo.Count(); i++ {
126+
127+
var id = node.sendTo.ElementAtIndex(i).(string)
128+
node.echoedFrom[id] = false
129+
node.host.SendMessage(node.id, id, LabelCommand, node.treeLevel)
130+
}
131+
} else {
132+
133+
node.host.SendMessage(node.id, sender, StopCommand, nil)
134+
}
135+
}
136+
137+
case KeeponCommand, StopCommand, EndCommand:
138+
139+
node.echoedFrom[sender] = true
140+
141+
switch command {
142+
143+
case KeeponCommand:
144+
node.children.AppendUnique(sender)
145+
146+
case StopCommand:
147+
node.sendTo.Remove(sender)
148+
149+
case EndCommand:
150+
node.children.AppendUnique(sender)
151+
node.sendTo.Remove(sender)
152+
}
153+
154+
if node.sendTo.IsEmpty() {
155+
156+
if node.IsRoot() {
157+
node.host.SendMessage(node.id, "server", CompleteCommand, nil)
158+
} else {
159+
node.host.SendMessage(node.id, node.parentID, EndCommand, nil)
160+
}
161+
} else {
162+
163+
var everyNodeEchoed = true
164+
165+
for i := 0; i < node.sendTo.Count(); i++ {
166+
167+
var id = node.sendTo.ElementAtIndex(i).(string)
168+
if node.echoedFrom[id] == false {
169+
170+
everyNodeEchoed = false
171+
break // found a node that not yet echoed
172+
}
173+
}
174+
175+
if everyNodeEchoed {
176+
177+
if node.IsRoot() {
178+
179+
for i := 0; i < node.sendTo.Count(); i++ {
180+
181+
var id = node.sendTo.ElementAtIndex(i).(string)
182+
183+
node.echoedFrom[id] = false
184+
185+
node.host.SendMessage(node.id, id, LabelCommand, node.treeLevel)
186+
}
187+
} else {
188+
node.host.SendMessage(node.id, node.parentID, KeeponCommand, nil)
189+
}
190+
}
191+
}
192+
default:
193+
Printf("[BFS Algorithm]: Unknown command \"%d\"- do nothing\n", command)
194+
}
195+
node.guard.Unlock()
196+
}
197+
198+
func (node *Node) Children() []string {
199+
200+
node.guard.Lock()
201+
var children []string
202+
for i := 0; i < node.children.Count(); i++ {
203+
204+
var childID = node.children.ElementAtIndex(i).(string)
205+
children = append(children, childID)
206+
}
207+
node.guard.Unlock()
208+
return children
209+
}

bfs/command/command.go

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//
2+
// command.go
3+
//
4+
// Created by Adrian Zubarev.
5+
// Copyright © 2016 Adrian Zubarev.
6+
// All rights reserved.
7+
//
8+
9+
package command
10+
11+
const /* Message Command constants */ (
12+
NewNeighborCommand uint8 = iota
13+
StopListeningCommand uint8 = iota
14+
InitCommand uint8 = iota
15+
LabelCommand uint8 = iota
16+
EndCommand uint8 = iota
17+
KeeponCommand uint8 = iota
18+
StopCommand uint8 = iota
19+
CompleteCommand uint8 = iota
20+
FinalCommand uint8 = iota
21+
)
22+
23+
func StringFor(command uint8) string {
24+
25+
switch command {
26+
case NewNeighborCommand:
27+
return "New Neighbor"
28+
case StopListeningCommand:
29+
return "Stop Listening"
30+
case InitCommand:
31+
return "Init"
32+
case LabelCommand:
33+
return "Label"
34+
case EndCommand:
35+
return "End"
36+
case KeeponCommand:
37+
return "Keepon"
38+
case StopCommand:
39+
return "Stop"
40+
case CompleteCommand:
41+
return "Complete"
42+
case FinalCommand:
43+
return "Final"
44+
}
45+
return "Unknown Command"
46+
}

0 commit comments

Comments
 (0)