-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
151 lines (130 loc) · 3.52 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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package main
import (
"errors"
"flag"
"fmt"
"log"
"net"
"os"
"os/signal"
"strings"
"syscall"
"time"
"dyno-raft/dynonode"
)
// Command line defaults
const (
DefaultHTTPAddr = ":11000"
DefaultRaftAddr = ":12000"
BroadcastPort = 13000
)
// Command line parameters
var httpAddr string
var raftAddr string
var joinAddr string
var token string
var raftDir string
var nodeName string
var minNodes int
func init() {
flag.StringVar(&httpAddr, "haddr", DefaultHTTPAddr, "Set the HTTP bind address")
flag.StringVar(&raftAddr, "raddr", DefaultRaftAddr, "Set Raft bind address")
flag.StringVar(&raftDir, "dir", "", "Set the Raft data path")
flag.StringVar(&joinAddr, "joinaddr", "", "Set join address, if any")
flag.StringVar(&token, "jointoken", "", "Join Raft by UDP discovery mechamism using token")
flag.IntVar(&minNodes, "quorum", 1, "Set the minimum nodes in raft cluster for quorum")
flag.StringVar(&nodeName, "name", "", "Set the node name (label)")
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: %s [options] \n", os.Args[0])
flag.PrintDefaults()
}
}
func formBindAddr(addr string) (string, error) {
host, port, err := net.SplitHostPort(addr)
if err != nil {
return "", err
}
if host == "" {
return fmt.Sprintf("127.0.0.1:%s", port), nil
}
if len(host) > 2 && host[0] == '_' {
reqIface := host[1 : len(host)-1]
ifaces, err := net.Interfaces()
if err != nil {
return "", err
}
for _, iface := range ifaces {
if iface.Name != reqIface {
continue
}
addrs, _ := iface.Addrs()
if len(addrs) == 0 {
return "", errors.New(fmt.Sprintf("No IP address on interface %s", reqIface))
}
host := strings.Split(addrs[0].String(), "/")[0] //FIXME
return fmt.Sprintf("%s:%s", host, port), nil
}
return "", errors.New(fmt.Sprintf("Interface %s does not found", reqIface))
}
return addr, nil
}
func main() {
flag.Parse()
if raftDir == "" {
fmt.Fprintf(os.Stderr, "No Raft storage directory specified\n")
os.Exit(1)
}
os.MkdirAll(raftDir, 0700)
raftAddr, err := formBindAddr(raftAddr)
if err != nil {
log.Fatalf("failed to parse raft addr: %s", err.Error())
}
httpAddr, err = formBindAddr(httpAddr)
if err != nil {
log.Fatalf("failed to parse http addr: %s", err.Error())
}
logger := log.New(dynonode.NewLogWriter(0), fmt.Sprintf("[%s] ", nodeName), log.LstdFlags)
node := dynonode.NewDynoNode(httpAddr, raftAddr, raftDir, nodeName, minNodes, logger)
if err := node.Start(); err != nil {
log.Fatalf("failed to start HTTP service: %s", err.Error())
}
if token != "" {
discovery := NewDiscovery(BroadcastPort, token, httpAddr)
joinAddr, err = discoveryPeer(discovery)
if err != nil {
logger.Println("Can't discovery peer over UDP broadcast")
} else {
logger.Printf("[INFO] discovered peer at %s", joinAddr)
}
}
if joinAddr != "" {
for {
if err := node.JoinToRaft(joinAddr); err != nil {
//log.Fatalf("failed to join Raft: %s", err.Error())
time.Sleep(1 * time.Second) //FIXME
continue
}
break
}
}
logger.Println("[INFO] dyno-raft started successfully")
terminate := make(chan os.Signal, 1)
//signal.Notify(terminate, os.Interrupt)
signal.Notify(terminate, syscall.SIGINT, syscall.SIGTERM)
<-terminate
logger.Println("[INFO] dyno-raft exiting")
}
func discoveryPeer(d *Discovery) (string, error) {
var err error
var peer string
for i := 0; i < 10; i++ {
peer, err = d.PeerDiscover()
if err != nil {
fmt.Println("failed peer discovery:", err.Error())
} else {
return peer, nil
}
time.Sleep(1 * time.Second)
}
return "", err
}