Update godeps for etcd 3.0.4
This commit is contained in:
2
vendor/github.com/coreos/etcd/rafthttp/coder.go
generated
vendored
2
vendor/github.com/coreos/etcd/rafthttp/coder.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
2
vendor/github.com/coreos/etcd/rafthttp/doc.go
generated
vendored
2
vendor/github.com/coreos/etcd/rafthttp/doc.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
13
vendor/github.com/coreos/etcd/rafthttp/http.go
generated
vendored
13
vendor/github.com/coreos/etcd/rafthttp/http.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -106,12 +106,16 @@ func (h *pipelineHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "error reading raft message", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var m raftpb.Message
|
||||
if err := m.Unmarshal(b); err != nil {
|
||||
plog.Errorf("failed to unmarshal raft message (%v)", err)
|
||||
http.Error(w, "error unmarshaling raft message", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
receivedBytes.WithLabelValues(types.ID(m.From).String()).Add(float64(len(b)))
|
||||
|
||||
if err := h.r.Process(context.TODO(), m); err != nil {
|
||||
switch v := err.(type) {
|
||||
case writerToResponse:
|
||||
@@ -181,6 +185,9 @@ func (h *snapshotHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, msg, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
receivedBytes.WithLabelValues(types.ID(m.From).String()).Add(float64(m.Size()))
|
||||
|
||||
if m.Type != raftpb.MsgSnap {
|
||||
plog.Errorf("unexpected raft message type %s on snapshot path", m.Type)
|
||||
http.Error(w, "wrong raft message type", http.StatusBadRequest)
|
||||
@@ -189,12 +196,14 @@ func (h *snapshotHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
plog.Infof("receiving database snapshot [index:%d, from %s] ...", m.Snapshot.Metadata.Index, types.ID(m.From))
|
||||
// save incoming database snapshot.
|
||||
if err := h.snapshotter.SaveDBFrom(r.Body, m.Snapshot.Metadata.Index); err != nil {
|
||||
n, err := h.snapshotter.SaveDBFrom(r.Body, m.Snapshot.Metadata.Index)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("failed to save KV snapshot (%v)", err)
|
||||
plog.Error(msg)
|
||||
http.Error(w, msg, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
receivedBytes.WithLabelValues(types.ID(m.From).String()).Add(float64(n))
|
||||
plog.Infof("received and saved database snapshot [index: %d, from: %s] successfully", m.Snapshot.Metadata.Index, types.ID(m.From))
|
||||
|
||||
if err := h.r.Process(context.TODO(), m); err != nil {
|
||||
|
||||
72
vendor/github.com/coreos/etcd/rafthttp/metrics.go
generated
vendored
72
vendor/github.com/coreos/etcd/rafthttp/metrics.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -14,57 +14,41 @@
|
||||
|
||||
package rafthttp
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/coreos/etcd/pkg/types"
|
||||
"github.com/coreos/etcd/raft/raftpb"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
import "github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
// TODO: record write/recv failures.
|
||||
var (
|
||||
// TODO: create a separate histogram for recording
|
||||
// snapshot sending metric. snapshot can be large and
|
||||
// take a long time to send. So it needs a different
|
||||
// time range than other type of messages.
|
||||
msgSentDuration = prometheus.NewHistogramVec(
|
||||
prometheus.HistogramOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "rafthttp",
|
||||
Name: "message_sent_latency_seconds",
|
||||
Help: "message sent latency distributions.",
|
||||
Buckets: prometheus.ExponentialBuckets(0.0005, 2, 13),
|
||||
},
|
||||
[]string{"sendingType", "remoteID", "msgType"},
|
||||
sentBytes = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "network",
|
||||
Name: "peer_sent_bytes_total",
|
||||
Help: "The total number of bytes sent to peers.",
|
||||
},
|
||||
[]string{"To"},
|
||||
)
|
||||
|
||||
msgSentFailed = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
receivedBytes = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "rafthttp",
|
||||
Name: "message_sent_failed_total",
|
||||
Help: "The total number of failed messages sent.",
|
||||
Subsystem: "network",
|
||||
Name: "peer_received_bytes_total",
|
||||
Help: "The total number of bytes received from peers.",
|
||||
},
|
||||
[]string{"sendingType", "remoteID", "msgType"},
|
||||
[]string{"From"},
|
||||
)
|
||||
|
||||
rtts = prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "network",
|
||||
Name: "peer_round_trip_time_seconds",
|
||||
Help: "Round-Trip-Time histogram between peers.",
|
||||
Buckets: prometheus.ExponentialBuckets(0.0001, 2, 14),
|
||||
},
|
||||
[]string{"To"},
|
||||
)
|
||||
)
|
||||
|
||||
func init() {
|
||||
prometheus.MustRegister(msgSentDuration)
|
||||
prometheus.MustRegister(msgSentFailed)
|
||||
}
|
||||
|
||||
func reportSentDuration(sendingType string, m raftpb.Message, duration time.Duration) {
|
||||
typ := m.Type.String()
|
||||
if isLinkHeartbeatMessage(m) {
|
||||
typ = "MsgLinkHeartbeat"
|
||||
}
|
||||
msgSentDuration.WithLabelValues(sendingType, types.ID(m.To).String(), typ).Observe(float64(duration) / float64(time.Second))
|
||||
}
|
||||
|
||||
func reportSentFailure(sendingType string, m raftpb.Message) {
|
||||
typ := m.Type.String()
|
||||
if isLinkHeartbeatMessage(m) {
|
||||
typ = "MsgLinkHeartbeat"
|
||||
}
|
||||
msgSentFailed.WithLabelValues(sendingType, types.ID(m.To).String(), typ).Inc()
|
||||
prometheus.MustRegister(sentBytes)
|
||||
prometheus.MustRegister(receivedBytes)
|
||||
prometheus.MustRegister(rtts)
|
||||
}
|
||||
|
||||
2
vendor/github.com/coreos/etcd/rafthttp/msg_codec.go
generated
vendored
2
vendor/github.com/coreos/etcd/rafthttp/msg_codec.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
4
vendor/github.com/coreos/etcd/rafthttp/msgappv2_codec.go
generated
vendored
4
vendor/github.com/coreos/etcd/rafthttp/msgappv2_codec.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -58,7 +58,7 @@ const (
|
||||
// Data format of MsgApp:
|
||||
// | offset | bytes | description |
|
||||
// +--------+-------+-------------+
|
||||
// | 0 | 1 | \x01 |
|
||||
// | 0 | 1 | \x02 |
|
||||
// | 1 | 8 | length of encoded message |
|
||||
// | 9 | n | encoded message |
|
||||
type msgAppV2Encoder struct {
|
||||
|
||||
59
vendor/github.com/coreos/etcd/rafthttp/peer.go
generated
vendored
59
vendor/github.com/coreos/etcd/rafthttp/peer.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -117,18 +117,34 @@ type peer struct {
|
||||
stopc chan struct{}
|
||||
}
|
||||
|
||||
func startPeer(transport *Transport, urls types.URLs, local, to, cid types.ID, r Raft, fs *stats.FollowerStats, errorc chan error) *peer {
|
||||
status := newPeerStatus(to)
|
||||
func startPeer(transport *Transport, urls types.URLs, peerID types.ID, fs *stats.FollowerStats) *peer {
|
||||
plog.Infof("starting peer %s...", peerID)
|
||||
defer plog.Infof("started peer %s", peerID)
|
||||
|
||||
status := newPeerStatus(peerID)
|
||||
picker := newURLPicker(urls)
|
||||
errorc := transport.ErrorC
|
||||
r := transport.Raft
|
||||
pipeline := &pipeline{
|
||||
peerID: peerID,
|
||||
tr: transport,
|
||||
picker: picker,
|
||||
status: status,
|
||||
followerStats: fs,
|
||||
raft: r,
|
||||
errorc: errorc,
|
||||
}
|
||||
pipeline.start()
|
||||
|
||||
p := &peer{
|
||||
id: to,
|
||||
id: peerID,
|
||||
r: r,
|
||||
status: status,
|
||||
picker: picker,
|
||||
msgAppV2Writer: startStreamWriter(to, status, fs, r),
|
||||
writer: startStreamWriter(to, status, fs, r),
|
||||
pipeline: newPipeline(transport, picker, local, to, cid, status, fs, r, errorc),
|
||||
snapSender: newSnapshotSender(transport, picker, local, to, cid, status, r, errorc),
|
||||
msgAppV2Writer: startStreamWriter(peerID, status, fs, r),
|
||||
writer: startStreamWriter(peerID, status, fs, r),
|
||||
pipeline: pipeline,
|
||||
snapSender: newSnapshotSender(transport, picker, peerID, status),
|
||||
sendc: make(chan raftpb.Message),
|
||||
recvc: make(chan raftpb.Message, recvBufSize),
|
||||
propc: make(chan raftpb.Message, maxPendingProposals),
|
||||
@@ -166,8 +182,26 @@ func startPeer(transport *Transport, urls types.URLs, local, to, cid types.ID, r
|
||||
}
|
||||
}()
|
||||
|
||||
p.msgAppV2Reader = startStreamReader(transport, picker, streamTypeMsgAppV2, local, to, cid, status, p.recvc, p.propc, errorc)
|
||||
p.msgAppReader = startStreamReader(transport, picker, streamTypeMessage, local, to, cid, status, p.recvc, p.propc, errorc)
|
||||
p.msgAppV2Reader = &streamReader{
|
||||
peerID: peerID,
|
||||
typ: streamTypeMsgAppV2,
|
||||
tr: transport,
|
||||
picker: picker,
|
||||
status: status,
|
||||
recvc: p.recvc,
|
||||
propc: p.propc,
|
||||
}
|
||||
p.msgAppReader = &streamReader{
|
||||
peerID: peerID,
|
||||
typ: streamTypeMessage,
|
||||
tr: transport,
|
||||
picker: picker,
|
||||
status: status,
|
||||
recvc: p.recvc,
|
||||
propc: p.propc,
|
||||
}
|
||||
p.msgAppV2Reader.start()
|
||||
p.msgAppReader.start()
|
||||
|
||||
return p
|
||||
}
|
||||
@@ -219,7 +253,7 @@ func (p *peer) attachOutgoingConn(conn *outgoingConn) {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *peer) activeSince() time.Time { return p.status.activeSince }
|
||||
func (p *peer) activeSince() time.Time { return p.status.activeSince() }
|
||||
|
||||
// Pause pauses the peer. The peer will simply drops all incoming
|
||||
// messages without returning an error.
|
||||
@@ -241,6 +275,9 @@ func (p *peer) Resume() {
|
||||
}
|
||||
|
||||
func (p *peer) stop() {
|
||||
plog.Infof("stopping peer %s...", p.id)
|
||||
defer plog.Infof("stopped peer %s", p.id)
|
||||
|
||||
close(p.stopc)
|
||||
p.cancel()
|
||||
p.msgAppV2Writer.stop()
|
||||
|
||||
24
vendor/github.com/coreos/etcd/rafthttp/peer_status.go
generated
vendored
24
vendor/github.com/coreos/etcd/rafthttp/peer_status.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -28,10 +28,10 @@ type failureType struct {
|
||||
}
|
||||
|
||||
type peerStatus struct {
|
||||
id types.ID
|
||||
mu sync.Mutex // protect variables below
|
||||
active bool
|
||||
activeSince time.Time
|
||||
id types.ID
|
||||
mu sync.Mutex // protect variables below
|
||||
active bool
|
||||
since time.Time
|
||||
}
|
||||
|
||||
func newPeerStatus(id types.ID) *peerStatus {
|
||||
@@ -44,9 +44,9 @@ func (s *peerStatus) activate() {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if !s.active {
|
||||
plog.Infof("the connection with %s became active", s.id)
|
||||
plog.Infof("peer %s became active", s.id)
|
||||
s.active = true
|
||||
s.activeSince = time.Now()
|
||||
s.since = time.Now()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,9 +56,9 @@ func (s *peerStatus) deactivate(failure failureType, reason string) {
|
||||
msg := fmt.Sprintf("failed to %s %s on %s (%s)", failure.action, s.id, failure.source, reason)
|
||||
if s.active {
|
||||
plog.Errorf(msg)
|
||||
plog.Infof("the connection with %s became inactive", s.id)
|
||||
plog.Infof("peer %s became inactive", s.id)
|
||||
s.active = false
|
||||
s.activeSince = time.Time{}
|
||||
s.since = time.Time{}
|
||||
return
|
||||
}
|
||||
plog.Debugf(msg)
|
||||
@@ -69,3 +69,9 @@ func (s *peerStatus) isActive() bool {
|
||||
defer s.mu.Unlock()
|
||||
return s.active
|
||||
}
|
||||
|
||||
func (s *peerStatus) activeSince() time.Time {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.since
|
||||
}
|
||||
|
||||
51
vendor/github.com/coreos/etcd/rafthttp/pipeline.go
generated
vendored
51
vendor/github.com/coreos/etcd/rafthttp/pipeline.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -41,15 +41,15 @@ const (
|
||||
var errStopped = errors.New("stopped")
|
||||
|
||||
type pipeline struct {
|
||||
from, to types.ID
|
||||
cid types.ID
|
||||
peerID types.ID
|
||||
|
||||
tr *Transport
|
||||
picker *urlPicker
|
||||
status *peerStatus
|
||||
fs *stats.FollowerStats
|
||||
r Raft
|
||||
raft Raft
|
||||
errorc chan error
|
||||
// deprecate when we depercate v2 API
|
||||
followerStats *stats.FollowerStats
|
||||
|
||||
msgc chan raftpb.Message
|
||||
// wait for the handling routines
|
||||
@@ -57,30 +57,20 @@ type pipeline struct {
|
||||
stopc chan struct{}
|
||||
}
|
||||
|
||||
func newPipeline(tr *Transport, picker *urlPicker, from, to, cid types.ID, status *peerStatus, fs *stats.FollowerStats, r Raft, errorc chan error) *pipeline {
|
||||
p := &pipeline{
|
||||
from: from,
|
||||
to: to,
|
||||
cid: cid,
|
||||
tr: tr,
|
||||
picker: picker,
|
||||
status: status,
|
||||
fs: fs,
|
||||
r: r,
|
||||
errorc: errorc,
|
||||
stopc: make(chan struct{}),
|
||||
msgc: make(chan raftpb.Message, pipelineBufSize),
|
||||
}
|
||||
func (p *pipeline) start() {
|
||||
p.stopc = make(chan struct{})
|
||||
p.msgc = make(chan raftpb.Message, pipelineBufSize)
|
||||
p.wg.Add(connPerPipeline)
|
||||
for i := 0; i < connPerPipeline; i++ {
|
||||
go p.handle()
|
||||
}
|
||||
return p
|
||||
plog.Infof("started HTTP pipelining with peer %s", p.peerID)
|
||||
}
|
||||
|
||||
func (p *pipeline) stop() {
|
||||
close(p.stopc)
|
||||
p.wg.Wait()
|
||||
plog.Infof("stopped HTTP pipelining with peer %s", p.peerID)
|
||||
}
|
||||
|
||||
func (p *pipeline) handle() {
|
||||
@@ -96,25 +86,24 @@ func (p *pipeline) handle() {
|
||||
if err != nil {
|
||||
p.status.deactivate(failureType{source: pipelineMsg, action: "write"}, err.Error())
|
||||
|
||||
reportSentFailure(pipelineMsg, m)
|
||||
if m.Type == raftpb.MsgApp && p.fs != nil {
|
||||
p.fs.Fail()
|
||||
if m.Type == raftpb.MsgApp && p.followerStats != nil {
|
||||
p.followerStats.Fail()
|
||||
}
|
||||
p.r.ReportUnreachable(m.To)
|
||||
p.raft.ReportUnreachable(m.To)
|
||||
if isMsgSnap(m) {
|
||||
p.r.ReportSnapshot(m.To, raft.SnapshotFailure)
|
||||
p.raft.ReportSnapshot(m.To, raft.SnapshotFailure)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
p.status.activate()
|
||||
if m.Type == raftpb.MsgApp && p.fs != nil {
|
||||
p.fs.Succ(end.Sub(start))
|
||||
if m.Type == raftpb.MsgApp && p.followerStats != nil {
|
||||
p.followerStats.Succ(end.Sub(start))
|
||||
}
|
||||
if isMsgSnap(m) {
|
||||
p.r.ReportSnapshot(m.To, raft.SnapshotFinish)
|
||||
p.raft.ReportSnapshot(m.To, raft.SnapshotFinish)
|
||||
}
|
||||
reportSentDuration(pipelineMsg, m, time.Since(start))
|
||||
sentBytes.WithLabelValues(types.ID(m.To).String()).Add(float64(m.Size()))
|
||||
case <-p.stopc:
|
||||
return
|
||||
}
|
||||
@@ -125,7 +114,7 @@ func (p *pipeline) handle() {
|
||||
// error on any failure.
|
||||
func (p *pipeline) post(data []byte) (err error) {
|
||||
u := p.picker.pick()
|
||||
req := createPostRequest(u, RaftPrefix, bytes.NewBuffer(data), "application/protobuf", p.tr.URLs, p.from, p.cid)
|
||||
req := createPostRequest(u, RaftPrefix, bytes.NewBuffer(data), "application/protobuf", p.tr.URLs, p.tr.ID, p.tr.ClusterID)
|
||||
|
||||
done := make(chan struct{}, 1)
|
||||
cancel := httputil.RequestCanceler(p.tr.pipelineRt, req)
|
||||
@@ -151,7 +140,7 @@ func (p *pipeline) post(data []byte) (err error) {
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
err = checkPostResponse(resp, b, req, p.to)
|
||||
err = checkPostResponse(resp, b, req, p.peerID)
|
||||
if err != nil {
|
||||
p.picker.unreachable(u)
|
||||
// errMemberRemoved is a critical error since a removed member should
|
||||
|
||||
5
vendor/github.com/coreos/etcd/rafthttp/probing_status.go
generated
vendored
5
vendor/github.com/coreos/etcd/rafthttp/probing_status.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -48,11 +48,12 @@ func monitorProbingStatus(s probing.Status, id string) {
|
||||
select {
|
||||
case <-time.After(statusMonitoringInterval):
|
||||
if !s.Health() {
|
||||
plog.Warningf("the connection to peer %s is unhealthy", id)
|
||||
plog.Warningf("health check for peer %s failed", id)
|
||||
}
|
||||
if s.ClockDiff() > time.Second {
|
||||
plog.Warningf("the clock difference against peer %s is too high [%v > %v]", id, s.ClockDiff(), time.Second)
|
||||
}
|
||||
rtts.WithLabelValues(id).Observe(s.SRTT().Seconds())
|
||||
case <-s.StopNotify():
|
||||
return
|
||||
}
|
||||
|
||||
20
vendor/github.com/coreos/etcd/rafthttp/remote.go
generated
vendored
20
vendor/github.com/coreos/etcd/rafthttp/remote.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -25,13 +25,23 @@ type remote struct {
|
||||
pipeline *pipeline
|
||||
}
|
||||
|
||||
func startRemote(tr *Transport, urls types.URLs, local, to, cid types.ID, r Raft, errorc chan error) *remote {
|
||||
func startRemote(tr *Transport, urls types.URLs, id types.ID) *remote {
|
||||
picker := newURLPicker(urls)
|
||||
status := newPeerStatus(to)
|
||||
status := newPeerStatus(id)
|
||||
pipeline := &pipeline{
|
||||
peerID: id,
|
||||
tr: tr,
|
||||
picker: picker,
|
||||
status: status,
|
||||
raft: tr.Raft,
|
||||
errorc: tr.ErrorC,
|
||||
}
|
||||
pipeline.start()
|
||||
|
||||
return &remote{
|
||||
id: to,
|
||||
id: id,
|
||||
status: status,
|
||||
pipeline: newPipeline(tr, picker, local, to, cid, status, nil, r, errorc),
|
||||
pipeline: pipeline,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
18
vendor/github.com/coreos/etcd/rafthttp/snapshot_sender.go
generated
vendored
18
vendor/github.com/coreos/etcd/rafthttp/snapshot_sender.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -46,16 +46,16 @@ type snapshotSender struct {
|
||||
stopc chan struct{}
|
||||
}
|
||||
|
||||
func newSnapshotSender(tr *Transport, picker *urlPicker, from, to, cid types.ID, status *peerStatus, r Raft, errorc chan error) *snapshotSender {
|
||||
func newSnapshotSender(tr *Transport, picker *urlPicker, to types.ID, status *peerStatus) *snapshotSender {
|
||||
return &snapshotSender{
|
||||
from: from,
|
||||
from: tr.ID,
|
||||
to: to,
|
||||
cid: cid,
|
||||
cid: tr.ClusterID,
|
||||
tr: tr,
|
||||
picker: picker,
|
||||
status: status,
|
||||
r: r,
|
||||
errorc: errorc,
|
||||
r: tr.Raft,
|
||||
errorc: tr.ErrorC,
|
||||
stopc: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
@@ -65,8 +65,6 @@ func (s *snapshotSender) stop() { close(s.stopc) }
|
||||
func (s *snapshotSender) send(merged snap.Message) {
|
||||
m := merged.Message
|
||||
|
||||
start := time.Now()
|
||||
|
||||
body := createSnapBody(merged)
|
||||
defer body.Close()
|
||||
|
||||
@@ -87,7 +85,6 @@ func (s *snapshotSender) send(merged snap.Message) {
|
||||
}
|
||||
|
||||
s.picker.unreachable(u)
|
||||
reportSentFailure(sendSnap, m)
|
||||
s.status.deactivate(failureType{source: sendSnap, action: "post"}, err.Error())
|
||||
s.r.ReportUnreachable(m.To)
|
||||
// report SnapshotFailure to raft state machine. After raft state
|
||||
@@ -96,10 +93,11 @@ func (s *snapshotSender) send(merged snap.Message) {
|
||||
s.r.ReportSnapshot(m.To, raft.SnapshotFailure)
|
||||
return
|
||||
}
|
||||
reportSentDuration(sendSnap, m, time.Since(start))
|
||||
s.status.activate()
|
||||
s.r.ReportSnapshot(m.To, raft.SnapshotFinish)
|
||||
plog.Infof("database snapshot [index: %d, to: %s] sent out successfully", m.Snapshot.Metadata.Index, types.ID(m.To))
|
||||
|
||||
sentBytes.WithLabelValues(types.ID(m.To).String()).Add(float64(merged.TotalSize))
|
||||
}
|
||||
|
||||
// post posts the given request.
|
||||
|
||||
116
vendor/github.com/coreos/etcd/rafthttp/stream.go
generated
vendored
116
vendor/github.com/coreos/etcd/rafthttp/stream.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -97,7 +97,7 @@ type outgoingConn struct {
|
||||
|
||||
// streamWriter writes messages to the attached outgoingConn.
|
||||
type streamWriter struct {
|
||||
id types.ID
|
||||
peerID types.ID
|
||||
status *peerStatus
|
||||
fs *stats.FollowerStats
|
||||
r Raft
|
||||
@@ -116,7 +116,7 @@ type streamWriter struct {
|
||||
// messages and writes to the attached outgoing connection.
|
||||
func startStreamWriter(id types.ID, status *peerStatus, fs *stats.FollowerStats, r Raft) *streamWriter {
|
||||
w := &streamWriter{
|
||||
id: id,
|
||||
peerID: id,
|
||||
status: status,
|
||||
fs: fs,
|
||||
r: r,
|
||||
@@ -139,47 +139,56 @@ func (cw *streamWriter) run() {
|
||||
batched int
|
||||
)
|
||||
tickc := time.Tick(ConnReadTimeout / 3)
|
||||
unflushed := 0
|
||||
|
||||
plog.Infof("started streaming with peer %s (writer)", cw.peerID)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-heartbeatc:
|
||||
start := time.Now()
|
||||
err := enc.encode(linkHeartbeatMessage)
|
||||
unflushed += linkHeartbeatMessage.Size()
|
||||
if err == nil {
|
||||
flusher.Flush()
|
||||
batched = 0
|
||||
reportSentDuration(string(t), linkHeartbeatMessage, time.Since(start))
|
||||
sentBytes.WithLabelValues(cw.peerID.String()).Add(float64(unflushed))
|
||||
unflushed = 0
|
||||
continue
|
||||
}
|
||||
|
||||
reportSentFailure(string(t), linkHeartbeatMessage)
|
||||
cw.status.deactivate(failureType{source: t.String(), action: "heartbeat"}, err.Error())
|
||||
|
||||
cw.close()
|
||||
plog.Warningf("lost the TCP streaming connection with peer %s (%s writer)", cw.peerID, t)
|
||||
heartbeatc, msgc = nil, nil
|
||||
|
||||
case m := <-msgc:
|
||||
start := time.Now()
|
||||
err := enc.encode(m)
|
||||
if err == nil {
|
||||
unflushed += m.Size()
|
||||
|
||||
if len(msgc) == 0 || batched > streamBufSize/2 {
|
||||
flusher.Flush()
|
||||
sentBytes.WithLabelValues(cw.peerID.String()).Add(float64(unflushed))
|
||||
unflushed = 0
|
||||
batched = 0
|
||||
} else {
|
||||
batched++
|
||||
}
|
||||
|
||||
reportSentDuration(string(t), m, time.Since(start))
|
||||
continue
|
||||
}
|
||||
|
||||
reportSentFailure(string(t), m)
|
||||
cw.status.deactivate(failureType{source: t.String(), action: "write"}, err.Error())
|
||||
cw.close()
|
||||
plog.Warningf("lost the TCP streaming connection with peer %s (%s writer)", cw.peerID, t)
|
||||
heartbeatc, msgc = nil, nil
|
||||
cw.r.ReportUnreachable(m.To)
|
||||
|
||||
case conn := <-cw.connc:
|
||||
cw.close()
|
||||
if cw.close() {
|
||||
plog.Warningf("closed an existing TCP streaming connection with peer %s (%s writer)", cw.peerID, t)
|
||||
}
|
||||
t = conn.t
|
||||
switch conn.t {
|
||||
case streamTypeMsgAppV2:
|
||||
@@ -190,15 +199,20 @@ func (cw *streamWriter) run() {
|
||||
plog.Panicf("unhandled stream type %s", conn.t)
|
||||
}
|
||||
flusher = conn.Flusher
|
||||
unflushed = 0
|
||||
cw.mu.Lock()
|
||||
cw.status.activate()
|
||||
cw.closer = conn.Closer
|
||||
cw.working = true
|
||||
cw.mu.Unlock()
|
||||
plog.Infof("established a TCP streaming connection with peer %s (%s writer)", cw.peerID, t)
|
||||
heartbeatc, msgc = tickc, cw.msgc
|
||||
case <-cw.stopc:
|
||||
cw.close()
|
||||
if cw.close() {
|
||||
plog.Infof("closed the TCP streaming connection with peer %s (%s writer)", cw.peerID, t)
|
||||
}
|
||||
close(cw.done)
|
||||
plog.Infof("stopped streaming with peer %s (writer)", cw.peerID)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -210,18 +224,19 @@ func (cw *streamWriter) writec() (chan<- raftpb.Message, bool) {
|
||||
return cw.msgc, cw.working
|
||||
}
|
||||
|
||||
func (cw *streamWriter) close() {
|
||||
func (cw *streamWriter) close() bool {
|
||||
cw.mu.Lock()
|
||||
defer cw.mu.Unlock()
|
||||
if !cw.working {
|
||||
return
|
||||
return false
|
||||
}
|
||||
cw.closer.Close()
|
||||
if len(cw.msgc) > 0 {
|
||||
cw.r.ReportUnreachable(uint64(cw.id))
|
||||
cw.r.ReportUnreachable(uint64(cw.peerID))
|
||||
}
|
||||
cw.msgc = make(chan raftpb.Message, streamBufSize)
|
||||
cw.working = false
|
||||
return true
|
||||
}
|
||||
|
||||
func (cw *streamWriter) attach(conn *outgoingConn) bool {
|
||||
@@ -241,46 +256,40 @@ func (cw *streamWriter) stop() {
|
||||
// streamReader is a long-running go-routine that dials to the remote stream
|
||||
// endpoint and reads messages from the response body returned.
|
||||
type streamReader struct {
|
||||
tr *Transport
|
||||
picker *urlPicker
|
||||
t streamType
|
||||
local, remote types.ID
|
||||
cid types.ID
|
||||
status *peerStatus
|
||||
recvc chan<- raftpb.Message
|
||||
propc chan<- raftpb.Message
|
||||
errorc chan<- error
|
||||
peerID types.ID
|
||||
typ streamType
|
||||
|
||||
tr *Transport
|
||||
picker *urlPicker
|
||||
status *peerStatus
|
||||
recvc chan<- raftpb.Message
|
||||
propc chan<- raftpb.Message
|
||||
|
||||
errorc chan<- error
|
||||
|
||||
mu sync.Mutex
|
||||
paused bool
|
||||
cancel func()
|
||||
closer io.Closer
|
||||
stopc chan struct{}
|
||||
done chan struct{}
|
||||
|
||||
stopc chan struct{}
|
||||
done chan struct{}
|
||||
}
|
||||
|
||||
func startStreamReader(tr *Transport, picker *urlPicker, t streamType, local, remote, cid types.ID, status *peerStatus, recvc chan<- raftpb.Message, propc chan<- raftpb.Message, errorc chan<- error) *streamReader {
|
||||
r := &streamReader{
|
||||
tr: tr,
|
||||
picker: picker,
|
||||
t: t,
|
||||
local: local,
|
||||
remote: remote,
|
||||
cid: cid,
|
||||
status: status,
|
||||
recvc: recvc,
|
||||
propc: propc,
|
||||
errorc: errorc,
|
||||
stopc: make(chan struct{}),
|
||||
done: make(chan struct{}),
|
||||
func (r *streamReader) start() {
|
||||
r.stopc = make(chan struct{})
|
||||
r.done = make(chan struct{})
|
||||
if r.errorc == nil {
|
||||
r.errorc = r.tr.ErrorC
|
||||
}
|
||||
|
||||
go r.run()
|
||||
return r
|
||||
}
|
||||
|
||||
func (cr *streamReader) run() {
|
||||
t := cr.typ
|
||||
plog.Infof("started streaming with peer %s (%s reader)", cr.peerID, t)
|
||||
for {
|
||||
t := cr.t
|
||||
rc, err := cr.dial(t)
|
||||
if err != nil {
|
||||
if err != errUnsupportedStreamType {
|
||||
@@ -288,7 +297,9 @@ func (cr *streamReader) run() {
|
||||
}
|
||||
} else {
|
||||
cr.status.activate()
|
||||
plog.Infof("established a TCP streaming connection with peer %s (%s reader)", cr.peerID, cr.typ)
|
||||
err := cr.decodeLoop(rc, t)
|
||||
plog.Warningf("lost the TCP streaming connection with peer %s (%s reader)", cr.peerID, cr.typ)
|
||||
switch {
|
||||
// all data is read out
|
||||
case err == io.EOF:
|
||||
@@ -304,6 +315,7 @@ func (cr *streamReader) run() {
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
case <-cr.stopc:
|
||||
close(cr.done)
|
||||
plog.Infof("stopped streaming with peer %s (%s reader)", cr.peerID, t)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -314,7 +326,7 @@ func (cr *streamReader) decodeLoop(rc io.ReadCloser, t streamType) error {
|
||||
cr.mu.Lock()
|
||||
switch t {
|
||||
case streamTypeMsgAppV2:
|
||||
dec = newMsgAppV2Decoder(rc, cr.local, cr.remote)
|
||||
dec = newMsgAppV2Decoder(rc, cr.tr.ID, cr.peerID)
|
||||
case streamTypeMessage:
|
||||
dec = &messageDecoder{r: rc}
|
||||
default:
|
||||
@@ -332,6 +344,8 @@ func (cr *streamReader) decodeLoop(rc io.ReadCloser, t streamType) error {
|
||||
return err
|
||||
}
|
||||
|
||||
receivedBytes.WithLabelValues(types.ID(m.From).String()).Add(float64(m.Size()))
|
||||
|
||||
cr.mu.Lock()
|
||||
paused := cr.paused
|
||||
cr.mu.Unlock()
|
||||
@@ -377,18 +391,18 @@ func (cr *streamReader) stop() {
|
||||
func (cr *streamReader) dial(t streamType) (io.ReadCloser, error) {
|
||||
u := cr.picker.pick()
|
||||
uu := u
|
||||
uu.Path = path.Join(t.endpoint(), cr.local.String())
|
||||
uu.Path = path.Join(t.endpoint(), cr.tr.ID.String())
|
||||
|
||||
req, err := http.NewRequest("GET", uu.String(), nil)
|
||||
if err != nil {
|
||||
cr.picker.unreachable(u)
|
||||
return nil, fmt.Errorf("failed to make http request to %s (%v)", u, err)
|
||||
return nil, fmt.Errorf("failed to make http request to %v (%v)", u, err)
|
||||
}
|
||||
req.Header.Set("X-Server-From", cr.local.String())
|
||||
req.Header.Set("X-Server-From", cr.tr.ID.String())
|
||||
req.Header.Set("X-Server-Version", version.Version)
|
||||
req.Header.Set("X-Min-Cluster-Version", version.MinClusterVersion)
|
||||
req.Header.Set("X-Etcd-Cluster-ID", cr.cid.String())
|
||||
req.Header.Set("X-Raft-To", cr.remote.String())
|
||||
req.Header.Set("X-Etcd-Cluster-ID", cr.tr.ClusterID.String())
|
||||
req.Header.Set("X-Raft-To", cr.peerID.String())
|
||||
|
||||
setPeerURLsHeader(req, cr.tr.URLs)
|
||||
|
||||
@@ -431,7 +445,7 @@ func (cr *streamReader) dial(t streamType) (io.ReadCloser, error) {
|
||||
case http.StatusNotFound:
|
||||
httputil.GracefulClose(resp)
|
||||
cr.picker.unreachable(u)
|
||||
return nil, fmt.Errorf("remote member %s could not recognize local member", cr.remote)
|
||||
return nil, fmt.Errorf("peer %s faild to fine local node %s", cr.peerID, cr.tr.ID)
|
||||
case http.StatusPreconditionFailed:
|
||||
b, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
@@ -443,11 +457,11 @@ func (cr *streamReader) dial(t streamType) (io.ReadCloser, error) {
|
||||
|
||||
switch strings.TrimSuffix(string(b), "\n") {
|
||||
case errIncompatibleVersion.Error():
|
||||
plog.Errorf("request sent was ignored by peer %s (server version incompatible)", cr.remote)
|
||||
plog.Errorf("request sent was ignored by peer %s (server version incompatible)", cr.peerID)
|
||||
return nil, errIncompatibleVersion
|
||||
case errClusterIDMismatch.Error():
|
||||
plog.Errorf("request sent was ignored (cluster ID mismatch: remote[%s]=%s, local=%s)",
|
||||
cr.remote, resp.Header.Get("X-Etcd-Cluster-ID"), cr.cid)
|
||||
plog.Errorf("request sent was ignored (cluster ID mismatch: peer[%s]=%s, local=%s)",
|
||||
cr.peerID, resp.Header.Get("X-Etcd-Cluster-ID"), cr.tr.ClusterID)
|
||||
return nil, errClusterIDMismatch
|
||||
default:
|
||||
return nil, fmt.Errorf("unhandled error %q when precondition failed", string(b))
|
||||
|
||||
22
vendor/github.com/coreos/etcd/rafthttp/transport.go
generated
vendored
22
vendor/github.com/coreos/etcd/rafthttp/transport.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -202,11 +202,19 @@ func (t *Transport) Stop() {
|
||||
if tr, ok := t.pipelineRt.(*http.Transport); ok {
|
||||
tr.CloseIdleConnections()
|
||||
}
|
||||
t.peers = nil
|
||||
t.remotes = nil
|
||||
}
|
||||
|
||||
func (t *Transport) AddRemote(id types.ID, us []string) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
if t.remotes == nil {
|
||||
// there's no clean way to shutdown the golang http server
|
||||
// (see: https://github.com/golang/go/issues/4674) before
|
||||
// stopping the transport; ignore any new connections.
|
||||
return
|
||||
}
|
||||
if _, ok := t.peers[id]; ok {
|
||||
return
|
||||
}
|
||||
@@ -217,12 +225,16 @@ func (t *Transport) AddRemote(id types.ID, us []string) {
|
||||
if err != nil {
|
||||
plog.Panicf("newURLs %+v should never fail: %+v", us, err)
|
||||
}
|
||||
t.remotes[id] = startRemote(t, urls, t.ID, id, t.ClusterID, t.Raft, t.ErrorC)
|
||||
t.remotes[id] = startRemote(t, urls, id)
|
||||
}
|
||||
|
||||
func (t *Transport) AddPeer(id types.ID, us []string) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
if t.peers == nil {
|
||||
panic("transport stopped")
|
||||
}
|
||||
if _, ok := t.peers[id]; ok {
|
||||
return
|
||||
}
|
||||
@@ -231,8 +243,10 @@ func (t *Transport) AddPeer(id types.ID, us []string) {
|
||||
plog.Panicf("newURLs %+v should never fail: %+v", us, err)
|
||||
}
|
||||
fs := t.LeaderStats.Follower(id.String())
|
||||
t.peers[id] = startPeer(t, urls, t.ID, id, t.ClusterID, t.Raft, fs, t.ErrorC)
|
||||
t.peers[id] = startPeer(t, urls, id, fs)
|
||||
addPeerToProber(t.prober, id.String(), us)
|
||||
|
||||
plog.Infof("added peer %s", id)
|
||||
}
|
||||
|
||||
func (t *Transport) RemovePeer(id types.ID) {
|
||||
@@ -259,6 +273,7 @@ func (t *Transport) removePeer(id types.ID) {
|
||||
delete(t.peers, id)
|
||||
delete(t.LeaderStats.Followers, id.String())
|
||||
t.prober.Remove(id.String())
|
||||
plog.Infof("removed peer %s", id)
|
||||
}
|
||||
|
||||
func (t *Transport) UpdatePeer(id types.ID, us []string) {
|
||||
@@ -276,6 +291,7 @@ func (t *Transport) UpdatePeer(id types.ID, us []string) {
|
||||
|
||||
t.prober.Remove(id.String())
|
||||
addPeerToProber(t.prober, id.String(), us)
|
||||
plog.Infof("updated peer %s", id)
|
||||
}
|
||||
|
||||
func (t *Transport) ActiveSince(id types.ID) time.Time {
|
||||
|
||||
2
vendor/github.com/coreos/etcd/rafthttp/urlpick.go
generated
vendored
2
vendor/github.com/coreos/etcd/rafthttp/urlpick.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
8
vendor/github.com/coreos/etcd/rafthttp/util.go
generated
vendored
8
vendor/github.com/coreos/etcd/rafthttp/util.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -197,9 +197,9 @@ func setPeerURLsHeader(req *http.Request, urls types.URLs) {
|
||||
// often not set in unit tests
|
||||
return
|
||||
}
|
||||
var peerURLs []string
|
||||
for _, url := range urls {
|
||||
peerURLs = append(peerURLs, url.String())
|
||||
peerURLs := make([]string, urls.Len())
|
||||
for i := range urls {
|
||||
peerURLs[i] = urls[i].String()
|
||||
}
|
||||
req.Header.Set("X-PeerURLs", strings.Join(peerURLs, ","))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user