-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
122 lines (103 loc) · 2.85 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package main
import (
"fmt"
"log"
"net/http"
"os"
"strconv"
"sync"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/axelniklasson/self-stabilizing-uniform-reliable-broadcast/api"
"github.com/axelniklasson/self-stabilizing-uniform-reliable-broadcast/helpers"
"github.com/axelniklasson/self-stabilizing-uniform-reliable-broadcast/ssurb"
)
func getNodeIDs() []int {
return []int{0, 1, 2, 3, 4, 5}
}
func getID() int {
idStr, exists := os.LookupEnv("ID")
if !exists {
log.Fatal("Environment variable ID missing, aborting")
}
id, err := strconv.Atoi(idStr)
if err != nil {
log.Fatal("Badly formatted ID env var")
}
return id
}
func main() {
id := getID()
// setup logging
log.SetPrefix(fmt.Sprintf("[Node %d]: ", id))
log.SetFlags(log.Lshortfile | log.Ldate | log.Ltime)
log.Printf("Instance %d starting\n", id)
// parse hosts and build P which is a essentially a slice of all node ids
hosts, _ := helpers.ParseHostsFile()
P := []int{}
for _, p := range hosts {
P = append(P, p.ID)
}
resolver := ssurb.Resolver{}
// init module
urbModule := &ssurb.UrbModule{ID: id, P: P, Resolver: &resolver}
urbModule.Init()
hbfdModule := &ssurb.HbfdModule{ID: id, P: P, Resolver: &resolver}
hbfdModule.Init()
thetafdModule := &ssurb.ThetafdModule{ID: id, P: P, Resolver: &resolver}
thetafdModule.Init()
// init resolver and attach modules
resolver.Modules = make(map[ssurb.ModuleType]interface{})
resolver.Modules[ssurb.URB] = urbModule
resolver.Modules[ssurb.HBFD] = hbfdModule
resolver.Modules[ssurb.THETAFD] = thetafdModule
// init waitgroup to keep track of all goroutines
var wg sync.WaitGroup
// setup communication
ip := helpers.IPStringToSlice(helpers.GetIP())
server := ssurb.Server{IP: ip, Port: 4000 + id, Resolver: &resolver}
wg.Add(1)
go func(s *ssurb.Server) {
defer wg.Done()
err := s.Start()
if err != nil {
log.Fatal(err)
}
s.Listen()
}(&server)
// launch hbfd module
wg.Add(1)
go func(module *ssurb.HbfdModule) {
defer wg.Done()
module.DoForever()
}(hbfdModule)
// launch thetafd module
wg.Add(1)
go func(module *ssurb.ThetafdModule) {
defer wg.Done()
module.DoForever()
}(thetafdModule)
// launch urb module
wg.Add(1)
go func(module *ssurb.UrbModule) {
defer wg.Done()
module.DoForever()
}(urbModule)
// launch API
wg.Add(1)
go func() {
defer wg.Done()
api.SetUp(id, &resolver)
}()
// instrument application with prometheus metrics
// let metrics port be 2112 for id = 0, 2113 for id = 1 and upwards
// official doc recommend 2112, so got it from there
go func() {
port := 2112 + id
ipString := helpers.GetIP()
http.Handle("/metrics", promhttp.Handler())
log.Printf("Launching Prometheus server on port %d", port)
http.ListenAndServe(fmt.Sprintf("%s:%d", ipString, port), nil)
}()
// wait forever and allow modules and communication to run concurrently
wg.Wait()
}