forked from etcd-io/etcd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
transporter.go
134 lines (108 loc) · 3.63 KB
/
transporter.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
package main
import (
"bytes"
"encoding/json"
"fmt"
"github.com/coreos/go-raft"
"io"
"io/ioutil"
"net/http"
)
// Transporter layer for communication between raft nodes
type transporter struct {
client *http.Client
// scheme
scheme string
}
// Sends AppendEntries RPCs to a peer when the server is the leader.
func (t transporter) SendAppendEntriesRequest(server *raft.Server, peer *raft.Peer, req *raft.AppendEntriesRequest) *raft.AppendEntriesResponse {
var aersp *raft.AppendEntriesResponse
var b bytes.Buffer
json.NewEncoder(&b).Encode(req)
debug("Send LogEntries to %s ", peer.Name())
resp, err := t.Post(fmt.Sprintf("%s/log/append", peer.Name()), &b)
if err != nil {
debug("Cannot send AppendEntriesRequest to %s : %s", peer.Name(), err)
}
if resp != nil {
defer resp.Body.Close()
aersp = &raft.AppendEntriesResponse{}
if err := json.NewDecoder(resp.Body).Decode(&aersp); err == nil || err == io.EOF {
return aersp
}
}
return aersp
}
// Sends RequestVote RPCs to a peer when the server is the candidate.
func (t transporter) SendVoteRequest(server *raft.Server, peer *raft.Peer, req *raft.RequestVoteRequest) *raft.RequestVoteResponse {
var rvrsp *raft.RequestVoteResponse
var b bytes.Buffer
json.NewEncoder(&b).Encode(req)
debug("Send Vote to %s", peer.Name())
resp, err := t.Post(fmt.Sprintf("%s/vote", peer.Name()), &b)
if err != nil {
debug("Cannot send VoteRequest to %s : %s", peer.Name(), err)
}
if resp != nil {
defer resp.Body.Close()
rvrsp := &raft.RequestVoteResponse{}
if err := json.NewDecoder(resp.Body).Decode(&rvrsp); err == nil || err == io.EOF {
return rvrsp
}
}
return rvrsp
}
// Sends SnapshotRequest RPCs to a peer when the server is the candidate.
func (t transporter) SendSnapshotRequest(server *raft.Server, peer *raft.Peer, req *raft.SnapshotRequest) *raft.SnapshotResponse {
var aersp *raft.SnapshotResponse
var b bytes.Buffer
json.NewEncoder(&b).Encode(req)
debug("Send Snapshot to %s [Last Term: %d, LastIndex %d]", peer.Name(),
req.LastTerm, req.LastIndex)
resp, err := t.Post(fmt.Sprintf("%s/snapshot", peer.Name()), &b)
if resp != nil {
defer resp.Body.Close()
aersp = &raft.SnapshotResponse{}
if err = json.NewDecoder(resp.Body).Decode(&aersp); err == nil || err == io.EOF {
return aersp
}
}
return aersp
}
// Sends SnapshotRecoveryRequest RPCs to a peer when the server is the candidate.
func (t transporter) SendSnapshotRecoveryRequest(server *raft.Server, peer *raft.Peer, req *raft.SnapshotRecoveryRequest) *raft.SnapshotRecoveryResponse {
var aersp *raft.SnapshotRecoveryResponse
var b bytes.Buffer
json.NewEncoder(&b).Encode(req)
debug("Send SnapshotRecovery to %s [Last Term: %d, LastIndex %d]", peer.Name(),
req.LastTerm, req.LastIndex)
resp, err := t.Post(fmt.Sprintf("%s/snapshotRecovery", peer.Name()), &b)
if resp != nil {
defer resp.Body.Close()
aersp = &raft.SnapshotRecoveryResponse{}
if err = json.NewDecoder(resp.Body).Decode(&aersp); err == nil || err == io.EOF {
return aersp
}
}
return aersp
}
// Get the client address of the leader in the cluster
func (t transporter) GetLeaderClientAddress() string {
resp, _ := t.Get(raftServer.Leader() + "/client")
if resp != nil {
body, _ := ioutil.ReadAll(resp.Body)
resp.Body.Close()
return string(body)
}
return ""
}
// Send server side POST request
func (t transporter) Post(path string, body io.Reader) (*http.Response, error) {
resp, err := t.client.Post(t.scheme+path, "application/json", body)
return resp, err
}
// Send server side GET request
func (t transporter) Get(path string) (*http.Response, error) {
resp, err := t.client.Get(t.scheme + path)
return resp, err
}