blob: 9feca7c03b8f7f0a7c79c1382992b9f5d26f41a4 [file] [log] [blame]
Scott Baker2d897982019-09-24 11:50:08 -07001// Copyright 2015 The etcd Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package raft
16
17import (
18 "fmt"
19
20 pb "go.etcd.io/etcd/raft/raftpb"
21)
22
23type Status struct {
24 ID uint64
25
26 pb.HardState
27 SoftState
28
29 Applied uint64
30 Progress map[uint64]Progress
31
32 LeadTransferee uint64
33}
34
35func getProgressCopy(r *raft) map[uint64]Progress {
36 prs := make(map[uint64]Progress)
37 for id, p := range r.prs {
38 prs[id] = *p
39 }
40
41 for id, p := range r.learnerPrs {
42 prs[id] = *p
43 }
44 return prs
45}
46
47func getStatusWithoutProgress(r *raft) Status {
48 s := Status{
49 ID: r.id,
50 LeadTransferee: r.leadTransferee,
51 }
52 s.HardState = r.hardState()
53 s.SoftState = *r.softState()
54 s.Applied = r.raftLog.applied
55 return s
56}
57
58// getStatus gets a copy of the current raft status.
59func getStatus(r *raft) Status {
60 s := getStatusWithoutProgress(r)
61 if s.RaftState == StateLeader {
62 s.Progress = getProgressCopy(r)
63 }
64 return s
65}
66
67// MarshalJSON translates the raft status into JSON.
68// TODO: try to simplify this by introducing ID type into raft
69func (s Status) MarshalJSON() ([]byte, error) {
70 j := fmt.Sprintf(`{"id":"%x","term":%d,"vote":"%x","commit":%d,"lead":"%x","raftState":%q,"applied":%d,"progress":{`,
71 s.ID, s.Term, s.Vote, s.Commit, s.Lead, s.RaftState, s.Applied)
72
73 if len(s.Progress) == 0 {
74 j += "},"
75 } else {
76 for k, v := range s.Progress {
77 subj := fmt.Sprintf(`"%x":{"match":%d,"next":%d,"state":%q},`, k, v.Match, v.Next, v.State)
78 j += subj
79 }
80 // remove the trailing ","
81 j = j[:len(j)-1] + "},"
82 }
83
84 j += fmt.Sprintf(`"leadtransferee":"%x"}`, s.LeadTransferee)
85 return []byte(j), nil
86}
87
88func (s Status) String() string {
89 b, err := s.MarshalJSON()
90 if err != nil {
91 raftLogger.Panicf("unexpected error: %v", err)
92 }
93 return string(b)
94}