From fc4f4d471fa3a68b80517c0ff112f0f05434e310 Mon Sep 17 00:00:00 2001 From: Max Englander Date: Wed, 10 Jul 2019 08:02:31 -0400 Subject: [PATCH] etcdserver: add ability to auto-promote learners to voters It looks as though the etcd team was planning to implement "auto promote" (see #10537). This commit attempts to lay the groundwork for auto-promoting learners to voters by adding an --auto-promote flag to the add member command. One reason for having the ability to automatically promote learners to voters is that it would enable implementing the Raft paper's recommendation handle reconfiguration changes by first adding new members as non-voters until they have caught up with the leader. --- clientv3/cluster.go | 25 +- clientv3/example_cluster_test.go | 2 +- clientv3/integration/cluster_test.go | 8 +- clientv3/snapshot/member_test.go | 2 +- etcdctl/ctlv3/command/member_command.go | 10 +- etcdserver/api/membership/cluster.go | 5 +- etcdserver/api/membership/member.go | 29 +- etcdserver/api/membership/member_test.go | 14 +- etcdserver/api/v2http/client.go | 2 +- etcdserver/api/v2v3/server.go | 2 +- etcdserver/api/v3rpc/member.go | 8 +- etcdserver/etcdserverpb/rpc.pb.go | 624 ++++++++++++++--------- etcdserver/etcdserverpb/rpc.proto | 9 + etcdserver/server.go | 54 +- etcdserver/server_test.go | 16 +- proxy/grpcproxy/cluster.go | 18 +- raft/raft.go | 34 +- raft/raft_test.go | 2 +- raft/raftpb/raft.pb.go | 200 +++++--- raft/raftpb/raft.proto | 10 +- raft/tracker/progress.go | 5 + raft/tracker/tracker.go | 35 +- 22 files changed, 739 insertions(+), 375 deletions(-) diff --git a/clientv3/cluster.go b/clientv3/cluster.go index ce97e5c85b8..7d3fe54f08f 100644 --- a/clientv3/cluster.go +++ b/clientv3/cluster.go @@ -36,8 +36,12 @@ type Cluster interface { // MemberList lists the current cluster membership. MemberList(ctx context.Context) (*MemberListResponse, error) - // MemberAdd adds a new member into the cluster. - MemberAdd(ctx context.Context, peerAddrs []string) (*MemberAddResponse, error) + // MemberAddAsAutoPromoting adds a new member as a learner that is + // automatically promoted to a node upon catching up with the leader into the cluster. + MemberAddAsAutoPromotingNode(ctx context.Context, peerAddrs []string) (*MemberAddResponse, error) + + // MemberAddAsNode adds a new member as a node into the cluster. + MemberAddAsNode(ctx context.Context, peerAddrs []string) (*MemberAddResponse, error) // MemberAddAsLearner adds a new learner member into the cluster. MemberAddAsLearner(ctx context.Context, peerAddrs []string) (*MemberAddResponse, error) @@ -73,23 +77,28 @@ func NewClusterFromClusterClient(remote pb.ClusterClient, c *Client) Cluster { return api } -func (c *cluster) MemberAdd(ctx context.Context, peerAddrs []string) (*MemberAddResponse, error) { - return c.memberAdd(ctx, peerAddrs, false) +func (c *cluster) MemberAddAsAutoPromotingNode(ctx context.Context, peerAddrs []string) (*MemberAddResponse, error) { + return c.memberAdd(ctx, peerAddrs, true, true) +} + +func (c *cluster) MemberAddAsNode(ctx context.Context, peerAddrs []string) (*MemberAddResponse, error) { + return c.memberAdd(ctx, peerAddrs, false, false) } func (c *cluster) MemberAddAsLearner(ctx context.Context, peerAddrs []string) (*MemberAddResponse, error) { - return c.memberAdd(ctx, peerAddrs, true) + return c.memberAdd(ctx, peerAddrs, true, false) } -func (c *cluster) memberAdd(ctx context.Context, peerAddrs []string, isLearner bool) (*MemberAddResponse, error) { +func (c *cluster) memberAdd(ctx context.Context, peerAddrs []string, isLearner bool, autoPromote bool) (*MemberAddResponse, error) { // fail-fast before panic in rafthttp if _, err := types.NewURLs(peerAddrs); err != nil { return nil, err } r := &pb.MemberAddRequest{ - PeerURLs: peerAddrs, - IsLearner: isLearner, + PeerURLs: peerAddrs, + IsLearner: isLearner, + AutoPromote: autoPromote, } resp, err := c.remote.MemberAdd(ctx, r, c.callOpts...) if err != nil { diff --git a/clientv3/example_cluster_test.go b/clientv3/example_cluster_test.go index 6a9a7c2ac56..f2260382dab 100644 --- a/clientv3/example_cluster_test.go +++ b/clientv3/example_cluster_test.go @@ -51,7 +51,7 @@ func ExampleCluster_memberAdd() { defer cli.Close() peerURLs := endpoints[2:] - mresp, err := cli.MemberAdd(context.Background(), peerURLs) + mresp, err := cli.MemberAddAsNode(context.Background(), peerURLs) if err != nil { log.Fatal(err) } diff --git a/clientv3/integration/cluster_test.go b/clientv3/integration/cluster_test.go index a5cf5d51a5a..9e4d3694059 100644 --- a/clientv3/integration/cluster_test.go +++ b/clientv3/integration/cluster_test.go @@ -54,7 +54,7 @@ func TestMemberAdd(t *testing.T) { capi := clus.RandClient() urls := []string{"http://127.0.0.1:1234"} - resp, err := capi.MemberAdd(context.Background(), urls) + resp, err := capi.MemberAddAsNode(context.Background(), urls) if err != nil { t.Fatalf("failed to add member %v", err) } @@ -78,7 +78,7 @@ func TestMemberAddWithExistingURLs(t *testing.T) { } existingURL := resp.Members[0].PeerURLs[0] - _, err = capi.MemberAdd(context.Background(), []string{existingURL}) + _, err = capi.MemberAddAsNode(context.Background(), []string{existingURL}) expectedErrKeywords := "Peer URLs already exists" if err == nil { t.Fatalf("expecting add member to fail, got no error") @@ -176,7 +176,7 @@ func TestMemberAddUpdateWrongURLs(t *testing.T) { {"localhost:1234"}, } for i := range tt { - _, err := capi.MemberAdd(context.Background(), tt[i]) + _, err := capi.MemberAddAsNode(context.Background(), tt[i]) if err == nil { t.Errorf("#%d: MemberAdd err = nil, but error", i) } @@ -412,7 +412,7 @@ func TestMaxLearnerInCluster(t *testing.T) { } // 4. cluster has 3 voting member and 1 learner, adding a voting member should succeed - _, err = clus.Client(0).MemberAdd(context.Background(), []string{"http://127.0.0.1:3456"}) + _, err = clus.Client(0).MemberAddAsNode(context.Background(), []string{"http://127.0.0.1:3456"}) if err != nil { t.Errorf("failed to add member %v", err) } diff --git a/clientv3/snapshot/member_test.go b/clientv3/snapshot/member_test.go index a42066a5637..4d9368c4d73 100644 --- a/clientv3/snapshot/member_test.go +++ b/clientv3/snapshot/member_test.go @@ -55,7 +55,7 @@ func TestSnapshotV3RestoreMultiMemberAdd(t *testing.T) { urls := newEmbedURLs(2) newCURLs, newPURLs := urls[:1], urls[1:] - if _, err = cli.MemberAdd(context.Background(), []string{newPURLs[0].String()}); err != nil { + if _, err = cli.MemberAddAsNode(context.Background(), []string{newPURLs[0].String()}); err != nil { t.Fatal(err) } diff --git a/etcdctl/ctlv3/command/member_command.go b/etcdctl/ctlv3/command/member_command.go index 182ff8ef722..cb72b8d3dab 100644 --- a/etcdctl/ctlv3/command/member_command.go +++ b/etcdctl/ctlv3/command/member_command.go @@ -27,6 +27,7 @@ import ( var ( memberPeerURLs string isLearner bool + autoPromote bool ) // NewMemberCommand returns the cobra command for "member". @@ -56,6 +57,7 @@ func NewMemberAddCommand() *cobra.Command { cc.Flags().StringVar(&memberPeerURLs, "peer-urls", "", "comma separated peer URLs for the new member.") cc.Flags().BoolVar(&isLearner, "learner", false, "indicates if the new member is raft learner") + cc.Flags().BoolVar(&autoPromote, "auto-promote", false, "indicates if the new learner member will be auto-promoted to voter") return cc } @@ -143,9 +145,13 @@ func memberAddCommandFunc(cmd *cobra.Command, args []string) { err error ) if isLearner { - resp, err = cli.MemberAddAsLearner(ctx, urls) + if autoPromote { + resp, err = cli.MemberAddAsAutoPromotingNode(ctx, urls) + } else { + resp, err = cli.MemberAddAsLearner(ctx, urls) + } } else { - resp, err = cli.MemberAdd(ctx, urls) + resp, err = cli.MemberAddAsNode(ctx, urls) } cancel() if err != nil { diff --git a/etcdserver/api/membership/cluster.go b/etcdserver/api/membership/cluster.go index 81f515d2f39..ff5851e9c7e 100644 --- a/etcdserver/api/membership/cluster.go +++ b/etcdserver/api/membership/cluster.go @@ -75,7 +75,7 @@ type ConfigChangeContext struct { func NewClusterFromURLsMap(lg *zap.Logger, token string, urlsmap types.URLsMap) (*RaftCluster, error) { c := NewCluster(lg, token) for name, urls := range urlsmap { - m := NewMember(name, urls, token, nil) + m := NewMemberAsNode(name, urls, token, nil) if _, ok := c.members[m.ID]; ok { return nil, fmt.Errorf("member exists with identical ID %v", m) } @@ -285,7 +285,7 @@ func (c *RaftCluster) ValidateConfigurationChange(cc raftpb.ConfChange) error { return ErrIDRemoved } switch cc.Type { - case raftpb.ConfChangeAddNode, raftpb.ConfChangeAddLearnerNode: + case raftpb.ConfChangeAddAutoPromotingNode, raftpb.ConfChangeAddNode, raftpb.ConfChangeAddLearnerNode: confChangeContext := new(ConfigChangeContext) if err := json.Unmarshal(cc.Context, confChangeContext); err != nil { if c.lg != nil { @@ -486,6 +486,7 @@ func (c *RaftCluster) PromoteMember(id types.ID) { defer c.Unlock() c.members[id].RaftAttributes.IsLearner = false + c.members[id].RaftAttributes.AutoPromote = false if c.v2store != nil { mustUpdateMemberInStore(c.v2store, c.members[id]) } diff --git a/etcdserver/api/membership/member.go b/etcdserver/api/membership/member.go index 896cb36aa45..b31eb7fafef 100644 --- a/etcdserver/api/membership/member.go +++ b/etcdserver/api/membership/member.go @@ -37,6 +37,9 @@ type RaftAttributes struct { PeerURLs []string `json:"peerURLs"` // IsLearner indicates if the member is raft learner. IsLearner bool `json:"isLearner,omitempty"` + // AutoPromote indicates whether the learner should be + // promoted to a voter upon catching up with leader. + AutoPromote bool `json:"autoPromote,omitempty"` } // Attributes represents all the non-raft related attributes of an etcd member. @@ -51,23 +54,32 @@ type Member struct { Attributes } -// NewMember creates a Member without an ID and generates one based on the +// NewMember creates a node Member without an ID and generates one based on the // cluster name, peer URLs, and time. This is used for bootstrapping/adding new member. -func NewMember(name string, peerURLs types.URLs, clusterName string, now *time.Time) *Member { - return newMember(name, peerURLs, clusterName, now, false) +func NewMemberAsNode(name string, peerURLs types.URLs, clusterName string, now *time.Time) *Member { + return newMember(name, peerURLs, clusterName, now, false /* isLearner */, false /* autoPromote */) +} + +// NewMemberAsAutoPromotingNode creates a learner Member without an ID and generates one +// based on the cluster name, peer URLs, and time. This is used for bootstrapping/adding +// new member. Auto-promoting learner members are automatically promoted to nodes upon +// catching up with the master. +func NewMemberAsAutoPromotingNode(name string, peerURLs types.URLs, clusterName string, now *time.Time) *Member { + return newMember(name, peerURLs, clusterName, now, true /* isLearner */, true /* autoPromote */) } // NewMemberAsLearner creates a learner Member without an ID and generates one based on the // cluster name, peer URLs, and time. This is used for adding new learner member. func NewMemberAsLearner(name string, peerURLs types.URLs, clusterName string, now *time.Time) *Member { - return newMember(name, peerURLs, clusterName, now, true) + return newMember(name, peerURLs, clusterName, now, true /* isLearner */, false /* autoPromote */) } -func newMember(name string, peerURLs types.URLs, clusterName string, now *time.Time, isLearner bool) *Member { +func newMember(name string, peerURLs types.URLs, clusterName string, now *time.Time, isLearner bool, autoPromote bool) *Member { m := &Member{ RaftAttributes: RaftAttributes{ - PeerURLs: peerURLs.StringSlice(), - IsLearner: isLearner, + PeerURLs: peerURLs.StringSlice(), + IsLearner: isLearner, + AutoPromote: autoPromote, }, Attributes: Attributes{Name: name}, } @@ -104,7 +116,8 @@ func (m *Member) Clone() *Member { mm := &Member{ ID: m.ID, RaftAttributes: RaftAttributes{ - IsLearner: m.IsLearner, + IsLearner: m.IsLearner, + AutoPromote: m.AutoPromote, }, Attributes: Attributes{ Name: m.Name, diff --git a/etcdserver/api/membership/member_test.go b/etcdserver/api/membership/member_test.go index e9de530eedf..979d9c72e3f 100644 --- a/etcdserver/api/membership/member_test.go +++ b/etcdserver/api/membership/member_test.go @@ -36,17 +36,17 @@ func TestMemberTime(t *testing.T) { mem *Member id types.ID }{ - {NewMember("mem1", []url.URL{{Scheme: "http", Host: "10.0.0.8:2379"}}, "", nil), 14544069596553697298}, + {NewMemberAsNode("mem1", []url.URL{{Scheme: "http", Host: "10.0.0.8:2379"}}, "", nil), 14544069596553697298}, // Same ID, different name (names shouldn't matter) - {NewMember("memfoo", []url.URL{{Scheme: "http", Host: "10.0.0.8:2379"}}, "", nil), 14544069596553697298}, + {NewMemberAsNode("memfoo", []url.URL{{Scheme: "http", Host: "10.0.0.8:2379"}}, "", nil), 14544069596553697298}, // Same ID, different Time - {NewMember("mem1", []url.URL{{Scheme: "http", Host: "10.0.0.8:2379"}}, "", timeParse("1984-12-23T15:04:05Z")), 2448790162483548276}, + {NewMemberAsNode("mem1", []url.URL{{Scheme: "http", Host: "10.0.0.8:2379"}}, "", timeParse("1984-12-23T15:04:05Z")), 2448790162483548276}, // Different cluster name - {NewMember("mcm1", []url.URL{{Scheme: "http", Host: "10.0.0.8:2379"}}, "etcd", timeParse("1984-12-23T15:04:05Z")), 6973882743191604649}, - {NewMember("mem1", []url.URL{{Scheme: "http", Host: "10.0.0.1:2379"}}, "", timeParse("1984-12-23T15:04:05Z")), 1466075294948436910}, + {NewMemberAsNode("mcm1", []url.URL{{Scheme: "http", Host: "10.0.0.8:2379"}}, "etcd", timeParse("1984-12-23T15:04:05Z")), 6973882743191604649}, + {NewMemberAsNode("mem1", []url.URL{{Scheme: "http", Host: "10.0.0.1:2379"}}, "", timeParse("1984-12-23T15:04:05Z")), 1466075294948436910}, // Order shouldn't matter - {NewMember("mem1", []url.URL{{Scheme: "http", Host: "10.0.0.1:2379"}, {Scheme: "http", Host: "10.0.0.2:2379"}}, "", nil), 16552244735972308939}, - {NewMember("mem1", []url.URL{{Scheme: "http", Host: "10.0.0.2:2379"}, {Scheme: "http", Host: "10.0.0.1:2379"}}, "", nil), 16552244735972308939}, + {NewMemberAsNode("mem1", []url.URL{{Scheme: "http", Host: "10.0.0.1:2379"}, {Scheme: "http", Host: "10.0.0.2:2379"}}, "", nil), 16552244735972308939}, + {NewMemberAsNode("mem1", []url.URL{{Scheme: "http", Host: "10.0.0.2:2379"}, {Scheme: "http", Host: "10.0.0.1:2379"}}, "", nil), 16552244735972308939}, } for i, tt := range tests { if tt.mem.ID != tt.id { diff --git a/etcdserver/api/v2http/client.go b/etcdserver/api/v2http/client.go index 1d1e592b25d..f158ead9ac3 100644 --- a/etcdserver/api/v2http/client.go +++ b/etcdserver/api/v2http/client.go @@ -238,7 +238,7 @@ func (h *membersHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } now := h.clock.Now() - m := membership.NewMember("", req.PeerURLs, "", &now) + m := membership.NewMemberAsNode("", req.PeerURLs, "", &now) _, err := h.server.AddMember(ctx, *m) switch { case err == membership.ErrIDExists || err == membership.ErrPeerURLexists: diff --git a/etcdserver/api/v2v3/server.go b/etcdserver/api/v2v3/server.go index 5ff9b96c0c4..2f5f8906e9e 100644 --- a/etcdserver/api/v2v3/server.go +++ b/etcdserver/api/v2v3/server.go @@ -64,7 +64,7 @@ func (s *v2v3Server) Leader() types.ID { func (s *v2v3Server) AddMember(ctx context.Context, memb membership.Member) ([]*membership.Member, error) { // adding member as learner is not supported by V2 Server. - resp, err := s.c.MemberAdd(ctx, memb.PeerURLs) + resp, err := s.c.MemberAddAsNode(ctx, memb.PeerURLs) if err != nil { return nil, err } diff --git a/etcdserver/api/v3rpc/member.go b/etcdserver/api/v3rpc/member.go index b2ebc989840..62baf0a5d59 100644 --- a/etcdserver/api/v3rpc/member.go +++ b/etcdserver/api/v3rpc/member.go @@ -47,9 +47,13 @@ func (cs *ClusterServer) MemberAdd(ctx context.Context, r *pb.MemberAddRequest) now := time.Now() var m *membership.Member if r.IsLearner { - m = membership.NewMemberAsLearner("", urls, "", &now) + if r.AutoPromote { + m = membership.NewMemberAsAutoPromotingNode("", urls, "", &now) + } else { + m = membership.NewMemberAsLearner("", urls, "", &now) + } } else { - m = membership.NewMember("", urls, "", &now) + m = membership.NewMemberAsNode("", urls, "", &now) } membs, merr := cs.server.AddMember(ctx, *m) if merr != nil { diff --git a/etcdserver/etcdserverpb/rpc.pb.go b/etcdserver/etcdserverpb/rpc.pb.go index 73efc3040fb..d0e37d78811 100644 --- a/etcdserver/etcdserverpb/rpc.pb.go +++ b/etcdserver/etcdserverpb/rpc.pb.go @@ -2188,6 +2188,9 @@ type Member struct { ClientURLs []string `protobuf:"bytes,4,rep,name=clientURLs" json:"clientURLs,omitempty"` // isLearner indicates if the member is raft learner. IsLearner bool `protobuf:"varint,5,opt,name=isLearner,proto3" json:"isLearner,omitempty"` + // autoPromote indicates whether the learner should be automatically promoted to a node + // when it has caught up with the leader + AutoPromote bool `protobuf:"varint,6,opt,name=autoPromote,proto3" json:"autoPromote,omitempty"` } func (m *Member) Reset() { *m = Member{} } @@ -2230,11 +2233,21 @@ func (m *Member) GetIsLearner() bool { return false } +func (m *Member) GetAutoPromote() bool { + if m != nil { + return m.AutoPromote + } + return false +} + type MemberAddRequest struct { // peerURLs is the list of URLs the added member will use to communicate with the cluster. PeerURLs []string `protobuf:"bytes,1,rep,name=peerURLs" json:"peerURLs,omitempty"` // isLearner indicates if the added member is raft learner. IsLearner bool `protobuf:"varint,2,opt,name=isLearner,proto3" json:"isLearner,omitempty"` + // autoPromote indicates whether the added learner should be automatically promoted to a node + // when it has caught up with the leader + AutoPromote bool `protobuf:"varint,3,opt,name=autoPromote,proto3" json:"autoPromote,omitempty"` } func (m *MemberAddRequest) Reset() { *m = MemberAddRequest{} } @@ -2256,6 +2269,13 @@ func (m *MemberAddRequest) GetIsLearner() bool { return false } +func (m *MemberAddRequest) GetAutoPromote() bool { + if m != nil { + return m.AutoPromote + } + return false +} + type MemberAddResponse struct { Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"` // member is the member information for the added member. @@ -2632,6 +2652,9 @@ type StatusResponse struct { DbSizeInUse int64 `protobuf:"varint,9,opt,name=dbSizeInUse,proto3" json:"dbSizeInUse,omitempty"` // isLearner indicates if the member is raft learner. IsLearner bool `protobuf:"varint,10,opt,name=isLearner,proto3" json:"isLearner,omitempty"` + // autoPromote indicates if learner is configured to be automatically promoted + // to a node upon catching up with the leader. + AutoPromote bool `protobuf:"varint,11,opt,name=autoPromote,proto3" json:"autoPromote,omitempty"` } func (m *StatusResponse) Reset() { *m = StatusResponse{} } @@ -2709,6 +2732,13 @@ func (m *StatusResponse) GetIsLearner() bool { return false } +func (m *StatusResponse) GetAutoPromote() bool { + if m != nil { + return m.AutoPromote + } + return false +} + type AuthEnableRequest struct { } @@ -6865,6 +6895,16 @@ func (m *Member) MarshalTo(dAtA []byte) (int, error) { } i++ } + if m.AutoPromote { + dAtA[i] = 0x30 + i++ + if m.AutoPromote { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ + } return i, nil } @@ -6908,6 +6948,16 @@ func (m *MemberAddRequest) MarshalTo(dAtA []byte) (int, error) { } i++ } + if m.AutoPromote { + dAtA[i] = 0x18 + i++ + if m.AutoPromote { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ + } return i, nil } @@ -7525,6 +7575,16 @@ func (m *StatusResponse) MarshalTo(dAtA []byte) (int, error) { } i++ } + if m.AutoPromote { + dAtA[i] = 0x58 + i++ + if m.AutoPromote { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ + } return i, nil } @@ -9236,6 +9296,9 @@ func (m *Member) Size() (n int) { if m.IsLearner { n += 2 } + if m.AutoPromote { + n += 2 + } return n } @@ -9251,6 +9314,9 @@ func (m *MemberAddRequest) Size() (n int) { if m.IsLearner { n += 2 } + if m.AutoPromote { + n += 2 + } return n } @@ -9499,6 +9565,9 @@ func (m *StatusResponse) Size() (n int) { if m.IsLearner { n += 2 } + if m.AutoPromote { + n += 2 + } return n } @@ -14904,6 +14973,26 @@ func (m *Member) Unmarshal(dAtA []byte) error { } } m.IsLearner = bool(v != 0) + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AutoPromote", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.AutoPromote = bool(v != 0) default: iNdEx = preIndex skippy, err := skipRpc(dAtA[iNdEx:]) @@ -15003,6 +15092,26 @@ func (m *MemberAddRequest) Unmarshal(dAtA []byte) error { } } m.IsLearner = bool(v != 0) + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AutoPromote", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.AutoPromote = bool(v != 0) default: iNdEx = preIndex skippy, err := skipRpc(dAtA[iNdEx:]) @@ -16811,6 +16920,26 @@ func (m *StatusResponse) Unmarshal(dAtA []byte) error { } } m.IsLearner = bool(v != 0) + case 11: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AutoPromote", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.AutoPromote = bool(v != 0) default: iNdEx = preIndex skippy, err := skipRpc(dAtA[iNdEx:]) @@ -19836,251 +19965,252 @@ var ( func init() { proto.RegisterFile("rpc.proto", fileDescriptorRpc) } var fileDescriptorRpc = []byte{ - // 3928 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5b, 0x5b, 0x6f, 0x23, 0xc9, - 0x75, 0x56, 0x93, 0xe2, 0xed, 0xf0, 0x22, 0xaa, 0x74, 0x19, 0x0e, 0x67, 0x46, 0xa3, 0xad, 0xd9, - 0xd9, 0xd5, 0xce, 0xec, 0x8a, 0x6b, 0xd9, 0x4e, 0x80, 0x49, 0xe2, 0x58, 0x23, 0x71, 0x67, 0xb4, - 0xd2, 0x88, 0xda, 0x16, 0x67, 0xf6, 0x02, 0x23, 0x42, 0x8b, 0x2c, 0x49, 0x1d, 0x91, 0xdd, 0x74, - 0x77, 0x93, 0x23, 0x6d, 0x2e, 0x0e, 0x0c, 0xc7, 0x40, 0xf2, 0x68, 0x03, 0x41, 0xf2, 0x90, 0xa7, - 0x20, 0x08, 0xfc, 0x90, 0xe7, 0x00, 0xf9, 0x05, 0x79, 0xca, 0x05, 0xf9, 0x03, 0xc1, 0xc6, 0x2f, - 0xc9, 0xaf, 0x30, 0xea, 0xd6, 0x5d, 0x7d, 0xa3, 0xc6, 0xa6, 0x77, 0x5f, 0xa4, 0xae, 0x53, 0xa7, - 0xce, 0x39, 0x75, 0xaa, 0xea, 0x9c, 0xd3, 0x5f, 0x17, 0xa1, 0xe4, 0x8c, 0x7a, 0x9b, 0x23, 0xc7, - 0xf6, 0x6c, 0x54, 0x21, 0x5e, 0xaf, 0xef, 0x12, 0x67, 0x42, 0x9c, 0xd1, 0x69, 0x73, 0xf9, 0xdc, - 0x3e, 0xb7, 0x59, 0x47, 0x8b, 0x3e, 0x71, 0x9e, 0xe6, 0x6d, 0xca, 0xd3, 0x1a, 0x4e, 0x7a, 0x3d, - 0xf6, 0x67, 0x74, 0xda, 0xba, 0x9c, 0x88, 0xae, 0x3b, 0xac, 0xcb, 0x18, 0x7b, 0x17, 0xec, 0xcf, - 0xe8, 0x94, 0xfd, 0x13, 0x9d, 0x77, 0xcf, 0x6d, 0xfb, 0x7c, 0x40, 0x5a, 0xc6, 0xc8, 0x6c, 0x19, - 0x96, 0x65, 0x7b, 0x86, 0x67, 0xda, 0x96, 0xcb, 0x7b, 0xf1, 0x5f, 0x6a, 0x50, 0xd3, 0x89, 0x3b, - 0xb2, 0x2d, 0x97, 0x3c, 0x27, 0x46, 0x9f, 0x38, 0xe8, 0x1e, 0x40, 0x6f, 0x30, 0x76, 0x3d, 0xe2, - 0x9c, 0x98, 0xfd, 0x86, 0xb6, 0xae, 0x6d, 0xcc, 0xeb, 0x25, 0x41, 0xd9, 0xeb, 0xa3, 0x3b, 0x50, - 0x1a, 0x92, 0xe1, 0x29, 0xef, 0xcd, 0xb0, 0xde, 0x22, 0x27, 0xec, 0xf5, 0x51, 0x13, 0x8a, 0x0e, - 0x99, 0x98, 0xae, 0x69, 0x5b, 0x8d, 0xec, 0xba, 0xb6, 0x91, 0xd5, 0xfd, 0x36, 0x1d, 0xe8, 0x18, - 0x67, 0xde, 0x89, 0x47, 0x9c, 0x61, 0x63, 0x9e, 0x0f, 0xa4, 0x84, 0x2e, 0x71, 0x86, 0xf8, 0x27, - 0x39, 0xa8, 0xe8, 0x86, 0x75, 0x4e, 0x74, 0xf2, 0xc3, 0x31, 0x71, 0x3d, 0x54, 0x87, 0xec, 0x25, - 0xb9, 0x66, 0xea, 0x2b, 0x3a, 0x7d, 0xe4, 0xe3, 0xad, 0x73, 0x72, 0x42, 0x2c, 0xae, 0xb8, 0x42, - 0xc7, 0x5b, 0xe7, 0xa4, 0x6d, 0xf5, 0xd1, 0x32, 0xe4, 0x06, 0xe6, 0xd0, 0xf4, 0x84, 0x56, 0xde, - 0x08, 0x99, 0x33, 0x1f, 0x31, 0x67, 0x07, 0xc0, 0xb5, 0x1d, 0xef, 0xc4, 0x76, 0xfa, 0xc4, 0x69, - 0xe4, 0xd6, 0xb5, 0x8d, 0xda, 0xd6, 0xdb, 0x9b, 0xea, 0x42, 0x6c, 0xaa, 0x06, 0x6d, 0x1e, 0xdb, - 0x8e, 0xd7, 0xa1, 0xbc, 0x7a, 0xc9, 0x95, 0x8f, 0xe8, 0x23, 0x28, 0x33, 0x21, 0x9e, 0xe1, 0x9c, - 0x13, 0xaf, 0x91, 0x67, 0x52, 0x1e, 0xde, 0x20, 0xa5, 0xcb, 0x98, 0x75, 0xa6, 0x9e, 0x3f, 0x23, - 0x0c, 0x15, 0x97, 0x38, 0xa6, 0x31, 0x30, 0xbf, 0x34, 0x4e, 0x07, 0xa4, 0x51, 0x58, 0xd7, 0x36, - 0x8a, 0x7a, 0x88, 0x46, 0xe7, 0x7f, 0x49, 0xae, 0xdd, 0x13, 0xdb, 0x1a, 0x5c, 0x37, 0x8a, 0x8c, - 0xa1, 0x48, 0x09, 0x1d, 0x6b, 0x70, 0xcd, 0x16, 0xcd, 0x1e, 0x5b, 0x1e, 0xef, 0x2d, 0xb1, 0xde, - 0x12, 0xa3, 0xb0, 0xee, 0x0d, 0xa8, 0x0f, 0x4d, 0xeb, 0x64, 0x68, 0xf7, 0x4f, 0x7c, 0x87, 0x00, - 0x73, 0x48, 0x6d, 0x68, 0x5a, 0x2f, 0xec, 0xbe, 0x2e, 0xdd, 0x42, 0x39, 0x8d, 0xab, 0x30, 0x67, - 0x59, 0x70, 0x1a, 0x57, 0x2a, 0xe7, 0x26, 0x2c, 0x51, 0x99, 0x3d, 0x87, 0x18, 0x1e, 0x09, 0x98, - 0x2b, 0x8c, 0x79, 0x71, 0x68, 0x5a, 0x3b, 0xac, 0x27, 0xc4, 0x6f, 0x5c, 0xc5, 0xf8, 0xab, 0x82, - 0xdf, 0xb8, 0x0a, 0xf3, 0xe3, 0x4d, 0x28, 0xf9, 0x3e, 0x47, 0x45, 0x98, 0x3f, 0xec, 0x1c, 0xb6, - 0xeb, 0x73, 0x08, 0x20, 0xbf, 0x7d, 0xbc, 0xd3, 0x3e, 0xdc, 0xad, 0x6b, 0xa8, 0x0c, 0x85, 0xdd, - 0x36, 0x6f, 0x64, 0xf0, 0x53, 0x80, 0xc0, 0xbb, 0xa8, 0x00, 0xd9, 0xfd, 0xf6, 0xe7, 0xf5, 0x39, - 0xca, 0xf3, 0xaa, 0xad, 0x1f, 0xef, 0x75, 0x0e, 0xeb, 0x1a, 0x1d, 0xbc, 0xa3, 0xb7, 0xb7, 0xbb, - 0xed, 0x7a, 0x86, 0x72, 0xbc, 0xe8, 0xec, 0xd6, 0xb3, 0xa8, 0x04, 0xb9, 0x57, 0xdb, 0x07, 0x2f, - 0xdb, 0xf5, 0x79, 0xfc, 0x73, 0x0d, 0xaa, 0x62, 0xbd, 0xf8, 0x99, 0x40, 0xdf, 0x81, 0xfc, 0x05, - 0x3b, 0x17, 0x6c, 0x2b, 0x96, 0xb7, 0xee, 0x46, 0x16, 0x37, 0x74, 0x76, 0x74, 0xc1, 0x8b, 0x30, - 0x64, 0x2f, 0x27, 0x6e, 0x23, 0xb3, 0x9e, 0xdd, 0x28, 0x6f, 0xd5, 0x37, 0xf9, 0x81, 0xdd, 0xdc, - 0x27, 0xd7, 0xaf, 0x8c, 0xc1, 0x98, 0xe8, 0xb4, 0x13, 0x21, 0x98, 0x1f, 0xda, 0x0e, 0x61, 0x3b, - 0xb6, 0xa8, 0xb3, 0x67, 0xba, 0x8d, 0xd9, 0xa2, 0x89, 0xdd, 0xca, 0x1b, 0xf8, 0x17, 0x1a, 0xc0, - 0xd1, 0xd8, 0x4b, 0x3f, 0x1a, 0xcb, 0x90, 0x9b, 0x50, 0xc1, 0xe2, 0x58, 0xf0, 0x06, 0x3b, 0x13, - 0xc4, 0x70, 0x89, 0x7f, 0x26, 0x68, 0x03, 0xdd, 0x82, 0xc2, 0xc8, 0x21, 0x93, 0x93, 0xcb, 0x09, - 0x53, 0x52, 0xd4, 0xf3, 0xb4, 0xb9, 0x3f, 0x41, 0x6f, 0x41, 0xc5, 0x3c, 0xb7, 0x6c, 0x87, 0x9c, - 0x70, 0x59, 0x39, 0xd6, 0x5b, 0xe6, 0x34, 0x66, 0xb7, 0xc2, 0xc2, 0x05, 0xe7, 0x55, 0x96, 0x03, - 0x4a, 0xc2, 0x16, 0x94, 0x99, 0xa9, 0x33, 0xb9, 0xef, 0xbd, 0xc0, 0xc6, 0x0c, 0x1b, 0x16, 0x77, - 0xa1, 0xb0, 0x1a, 0xff, 0x00, 0xd0, 0x2e, 0x19, 0x10, 0x8f, 0xcc, 0x12, 0x3d, 0x14, 0x9f, 0x64, - 0x55, 0x9f, 0xe0, 0x9f, 0x69, 0xb0, 0x14, 0x12, 0x3f, 0xd3, 0xb4, 0x1a, 0x50, 0xe8, 0x33, 0x61, - 0xdc, 0x82, 0xac, 0x2e, 0x9b, 0xe8, 0x31, 0x14, 0x85, 0x01, 0x6e, 0x23, 0x9b, 0xb2, 0x69, 0x0a, - 0xdc, 0x26, 0x17, 0xff, 0x22, 0x03, 0x25, 0x31, 0xd1, 0xce, 0x08, 0x6d, 0x43, 0xd5, 0xe1, 0x8d, - 0x13, 0x36, 0x1f, 0x61, 0x51, 0x33, 0x3d, 0x08, 0x3d, 0x9f, 0xd3, 0x2b, 0x62, 0x08, 0x23, 0xa3, - 0xdf, 0x83, 0xb2, 0x14, 0x31, 0x1a, 0x7b, 0xc2, 0xe5, 0x8d, 0xb0, 0x80, 0x60, 0xff, 0x3d, 0x9f, - 0xd3, 0x41, 0xb0, 0x1f, 0x8d, 0x3d, 0xd4, 0x85, 0x65, 0x39, 0x98, 0xcf, 0x46, 0x98, 0x91, 0x65, - 0x52, 0xd6, 0xc3, 0x52, 0xe2, 0x4b, 0xf5, 0x7c, 0x4e, 0x47, 0x62, 0xbc, 0xd2, 0xa9, 0x9a, 0xe4, - 0x5d, 0xf1, 0xe0, 0x1d, 0x33, 0xa9, 0x7b, 0x65, 0xc5, 0x4d, 0xea, 0x5e, 0x59, 0x4f, 0x4b, 0x50, - 0x10, 0x2d, 0xfc, 0x2f, 0x19, 0x00, 0xb9, 0x1a, 0x9d, 0x11, 0xda, 0x85, 0x9a, 0x23, 0x5a, 0x21, - 0x6f, 0xdd, 0x49, 0xf4, 0x96, 0x58, 0xc4, 0x39, 0xbd, 0x2a, 0x07, 0x71, 0xe3, 0xbe, 0x07, 0x15, - 0x5f, 0x4a, 0xe0, 0xb0, 0xdb, 0x09, 0x0e, 0xf3, 0x25, 0x94, 0xe5, 0x00, 0xea, 0xb2, 0x4f, 0x61, - 0xc5, 0x1f, 0x9f, 0xe0, 0xb3, 0xb7, 0xa6, 0xf8, 0xcc, 0x17, 0xb8, 0x24, 0x25, 0xa8, 0x5e, 0x53, - 0x0d, 0x0b, 0xdc, 0x76, 0x3b, 0xc1, 0x6d, 0x71, 0xc3, 0xa8, 0xe3, 0x80, 0xe6, 0x4b, 0xde, 0xc4, - 0xff, 0x97, 0x85, 0xc2, 0x8e, 0x3d, 0x1c, 0x19, 0x0e, 0x5d, 0x8d, 0xbc, 0x43, 0xdc, 0xf1, 0xc0, - 0x63, 0xee, 0xaa, 0x6d, 0x3d, 0x08, 0x4b, 0x14, 0x6c, 0xf2, 0xbf, 0xce, 0x58, 0x75, 0x31, 0x84, - 0x0e, 0x16, 0xe9, 0x31, 0xf3, 0x06, 0x83, 0x45, 0x72, 0x14, 0x43, 0xe4, 0x41, 0xce, 0x06, 0x07, - 0xb9, 0x09, 0x85, 0x09, 0x71, 0x82, 0x94, 0xfe, 0x7c, 0x4e, 0x97, 0x04, 0xf4, 0x1e, 0x2c, 0x44, - 0xd3, 0x4b, 0x4e, 0xf0, 0xd4, 0x7a, 0xe1, 0x6c, 0xf4, 0x00, 0x2a, 0xa1, 0x1c, 0x97, 0x17, 0x7c, - 0xe5, 0xa1, 0x92, 0xe2, 0x56, 0x65, 0x5c, 0xa5, 0xf9, 0xb8, 0xf2, 0x7c, 0x4e, 0x46, 0xd6, 0x55, - 0x19, 0x59, 0x8b, 0x62, 0x94, 0x88, 0xad, 0xa1, 0x20, 0xf3, 0xfd, 0x70, 0x90, 0xc1, 0xdf, 0x87, - 0x6a, 0xc8, 0x41, 0x34, 0xef, 0xb4, 0x3f, 0x79, 0xb9, 0x7d, 0xc0, 0x93, 0xd4, 0x33, 0x96, 0x97, - 0xf4, 0xba, 0x46, 0x73, 0xdd, 0x41, 0xfb, 0xf8, 0xb8, 0x9e, 0x41, 0x55, 0x28, 0x1d, 0x76, 0xba, - 0x27, 0x9c, 0x2b, 0x8b, 0x9f, 0xf9, 0x12, 0x44, 0x92, 0x53, 0x72, 0xdb, 0x9c, 0x92, 0xdb, 0x34, - 0x99, 0xdb, 0x32, 0x41, 0x6e, 0x63, 0x69, 0xee, 0xa0, 0xbd, 0x7d, 0xdc, 0xae, 0xcf, 0x3f, 0xad, - 0x41, 0x85, 0xfb, 0xf7, 0x64, 0x6c, 0xd1, 0x54, 0xfb, 0x0f, 0x1a, 0x40, 0x70, 0x9a, 0x50, 0x0b, - 0x0a, 0x3d, 0xae, 0xa7, 0xa1, 0xb1, 0x60, 0xb4, 0x92, 0xb8, 0x64, 0xba, 0xe4, 0x42, 0xdf, 0x82, - 0x82, 0x3b, 0xee, 0xf5, 0x88, 0x2b, 0x53, 0xde, 0xad, 0x68, 0x3c, 0x14, 0xd1, 0x4a, 0x97, 0x7c, - 0x74, 0xc8, 0x99, 0x61, 0x0e, 0xc6, 0x2c, 0x01, 0x4e, 0x1f, 0x22, 0xf8, 0xf0, 0xdf, 0x69, 0x50, - 0x56, 0x36, 0xef, 0x6f, 0x18, 0x84, 0xef, 0x42, 0x89, 0xd9, 0x40, 0xfa, 0x22, 0x0c, 0x17, 0xf5, - 0x80, 0x80, 0x7e, 0x07, 0x4a, 0xf2, 0x04, 0xc8, 0x48, 0xdc, 0x48, 0x16, 0xdb, 0x19, 0xe9, 0x01, - 0x2b, 0xde, 0x87, 0x45, 0xe6, 0x95, 0x1e, 0x2d, 0xae, 0xa5, 0x1f, 0xd5, 0xf2, 0x53, 0x8b, 0x94, - 0x9f, 0x4d, 0x28, 0x8e, 0x2e, 0xae, 0x5d, 0xb3, 0x67, 0x0c, 0x84, 0x15, 0x7e, 0x1b, 0x7f, 0x0c, - 0x48, 0x15, 0x36, 0xcb, 0x74, 0x71, 0x15, 0xca, 0xcf, 0x0d, 0xf7, 0x42, 0x98, 0x84, 0x1f, 0x43, - 0x95, 0x36, 0xf7, 0x5f, 0xbd, 0x81, 0x8d, 0xec, 0xe5, 0x40, 0x72, 0xcf, 0xe4, 0x73, 0x04, 0xf3, - 0x17, 0x86, 0x7b, 0xc1, 0x26, 0x5a, 0xd5, 0xd9, 0x33, 0x7a, 0x0f, 0xea, 0x3d, 0x3e, 0xc9, 0x93, - 0xc8, 0x2b, 0xc3, 0x82, 0xa0, 0xfb, 0x95, 0xe0, 0x67, 0x50, 0xe1, 0x73, 0xf8, 0x6d, 0x1b, 0x81, - 0x17, 0x61, 0xe1, 0xd8, 0x32, 0x46, 0xee, 0x85, 0x2d, 0xb3, 0x1b, 0x9d, 0x74, 0x3d, 0xa0, 0xcd, - 0xa4, 0xf1, 0x5d, 0x58, 0x70, 0xc8, 0xd0, 0x30, 0x2d, 0xd3, 0x3a, 0x3f, 0x39, 0xbd, 0xf6, 0x88, - 0x2b, 0x5e, 0x98, 0x6a, 0x3e, 0xf9, 0x29, 0xa5, 0x52, 0xd3, 0x4e, 0x07, 0xf6, 0xa9, 0x08, 0x73, - 0xec, 0x19, 0xff, 0x34, 0x03, 0x95, 0x4f, 0x0d, 0xaf, 0x27, 0x97, 0x0e, 0xed, 0x41, 0xcd, 0x0f, - 0x6e, 0x8c, 0x22, 0x6c, 0x89, 0xa4, 0x58, 0x36, 0x46, 0x96, 0xd2, 0x32, 0x3b, 0x56, 0x7b, 0x2a, - 0x81, 0x89, 0x32, 0xac, 0x1e, 0x19, 0xf8, 0xa2, 0x32, 0xe9, 0xa2, 0x18, 0xa3, 0x2a, 0x4a, 0x25, - 0xa0, 0x0e, 0xd4, 0x47, 0x8e, 0x7d, 0xee, 0x10, 0xd7, 0xf5, 0x85, 0xf1, 0x34, 0x86, 0x13, 0x84, - 0x1d, 0x09, 0xd6, 0x40, 0xdc, 0xc2, 0x28, 0x4c, 0x7a, 0xba, 0x10, 0xd4, 0x33, 0x3c, 0x38, 0xfd, - 0x57, 0x06, 0x50, 0x7c, 0x52, 0xbf, 0x6e, 0x89, 0xf7, 0x10, 0x6a, 0xae, 0x67, 0x38, 0xb1, 0xcd, - 0x56, 0x65, 0x54, 0x3f, 0xe2, 0xbf, 0x0b, 0xbe, 0x41, 0x27, 0x96, 0xed, 0x99, 0x67, 0xd7, 0xa2, - 0x4a, 0xae, 0x49, 0xf2, 0x21, 0xa3, 0xa2, 0x36, 0x14, 0xce, 0xcc, 0x81, 0x47, 0x1c, 0xb7, 0x91, - 0x5b, 0xcf, 0x6e, 0xd4, 0xb6, 0x1e, 0xdf, 0xb4, 0x0c, 0x9b, 0x1f, 0x31, 0xfe, 0xee, 0xf5, 0x88, - 0xe8, 0x72, 0xac, 0x5a, 0x79, 0xe6, 0x43, 0xd5, 0xf8, 0x6d, 0x28, 0xbe, 0xa6, 0x22, 0xe8, 0x5b, - 0x76, 0x81, 0x17, 0x8b, 0xac, 0xcd, 0x5f, 0xb2, 0xcf, 0x1c, 0xe3, 0x7c, 0x48, 0x2c, 0x4f, 0xbe, - 0x07, 0xca, 0x36, 0x7e, 0x08, 0x10, 0xa8, 0xa1, 0x21, 0xff, 0xb0, 0x73, 0xf4, 0xb2, 0x5b, 0x9f, - 0x43, 0x15, 0x28, 0x1e, 0x76, 0x76, 0xdb, 0x07, 0x6d, 0x9a, 0x1f, 0x70, 0x4b, 0xba, 0x34, 0xb4, - 0x96, 0xaa, 0x4e, 0x2d, 0xa4, 0x13, 0xaf, 0xc2, 0x72, 0xd2, 0x02, 0xd2, 0x5a, 0xb4, 0x2a, 0x76, - 0xe9, 0x4c, 0x47, 0x45, 0x55, 0x9d, 0x09, 0x4f, 0xb7, 0x01, 0x05, 0xbe, 0x7b, 0xfb, 0xa2, 0x38, - 0x97, 0x4d, 0xea, 0x08, 0xbe, 0x19, 0x49, 0x5f, 0xac, 0x92, 0xdf, 0x4e, 0x0c, 0x2f, 0xb9, 0xc4, - 0xf0, 0x82, 0x1e, 0x40, 0xd5, 0x3f, 0x0d, 0x86, 0x2b, 0x6a, 0x81, 0x92, 0x5e, 0x91, 0x1b, 0x9d, - 0xd2, 0x42, 0x4e, 0x2f, 0x84, 0x9d, 0x8e, 0x1e, 0x42, 0x9e, 0x4c, 0x88, 0xe5, 0xb9, 0x8d, 0x32, - 0xcb, 0x18, 0x55, 0x59, 0xbb, 0xb7, 0x29, 0x55, 0x17, 0x9d, 0xf8, 0xbb, 0xb0, 0xc8, 0xde, 0x91, - 0x9e, 0x39, 0x86, 0xa5, 0xbe, 0xcc, 0x75, 0xbb, 0x07, 0xc2, 0xdd, 0xf4, 0x11, 0xd5, 0x20, 0xb3, - 0xb7, 0x2b, 0x9c, 0x90, 0xd9, 0xdb, 0xc5, 0x3f, 0xd6, 0x00, 0xa9, 0xe3, 0x66, 0xf2, 0x73, 0x44, - 0xb8, 0x54, 0x9f, 0x0d, 0xd4, 0x2f, 0x43, 0x8e, 0x38, 0x8e, 0xed, 0x30, 0x8f, 0x96, 0x74, 0xde, - 0xc0, 0x6f, 0x0b, 0x1b, 0x74, 0x32, 0xb1, 0x2f, 0xfd, 0x33, 0xc8, 0xa5, 0x69, 0xbe, 0xa9, 0xfb, - 0xb0, 0x14, 0xe2, 0x9a, 0x29, 0x73, 0x7d, 0x04, 0x0b, 0x4c, 0xd8, 0xce, 0x05, 0xe9, 0x5d, 0x8e, - 0x6c, 0xd3, 0x8a, 0xe9, 0xa3, 0x2b, 0x17, 0x04, 0x58, 0x3a, 0x0f, 0x3e, 0xb1, 0x8a, 0x4f, 0xec, - 0x76, 0x0f, 0xf0, 0xe7, 0xb0, 0x1a, 0x91, 0x23, 0xcd, 0xff, 0x43, 0x28, 0xf7, 0x7c, 0xa2, 0x2b, - 0x6a, 0x9d, 0x7b, 0x61, 0xe3, 0xa2, 0x43, 0xd5, 0x11, 0xb8, 0x03, 0xb7, 0x62, 0xa2, 0x67, 0x9a, - 0xf3, 0xbb, 0xb0, 0xc2, 0x04, 0xee, 0x13, 0x32, 0xda, 0x1e, 0x98, 0x93, 0x54, 0x4f, 0x8f, 0xc4, - 0xa4, 0x14, 0xc6, 0xaf, 0x77, 0x5f, 0xe0, 0xdf, 0x17, 0x1a, 0xbb, 0xe6, 0x90, 0x74, 0xed, 0x83, - 0x74, 0xdb, 0x68, 0x36, 0xbb, 0x24, 0xd7, 0xae, 0x28, 0x6b, 0xd8, 0x33, 0xfe, 0x47, 0x4d, 0xb8, - 0x4a, 0x1d, 0xfe, 0x35, 0xef, 0xe4, 0x35, 0x80, 0x73, 0x7a, 0x64, 0x48, 0x9f, 0x76, 0x70, 0x44, - 0x45, 0xa1, 0xf8, 0x76, 0xd2, 0xf8, 0x5d, 0x11, 0x76, 0x2e, 0x8b, 0x7d, 0xce, 0xfe, 0xf8, 0x51, - 0xee, 0x1e, 0x94, 0x19, 0xe1, 0xd8, 0x33, 0xbc, 0xb1, 0x1b, 0x5b, 0x8c, 0x3f, 0x17, 0xdb, 0x5e, - 0x0e, 0x9a, 0x69, 0x5e, 0xdf, 0x82, 0x3c, 0x7b, 0x99, 0x90, 0xa5, 0xf4, 0xed, 0x84, 0xfd, 0xc8, - 0xed, 0xd0, 0x05, 0x23, 0xfe, 0xa9, 0x06, 0xf9, 0x17, 0x0c, 0x82, 0x55, 0x4c, 0x9b, 0x97, 0x6b, - 0x61, 0x19, 0x43, 0x0e, 0x0c, 0x95, 0x74, 0xf6, 0xcc, 0x4a, 0x4f, 0x42, 0x9c, 0x97, 0xfa, 0x01, - 0x2f, 0x71, 0x4b, 0xba, 0xdf, 0xa6, 0x3e, 0xeb, 0x0d, 0x4c, 0x62, 0x79, 0xac, 0x77, 0x9e, 0xf5, - 0x2a, 0x14, 0x5a, 0x3d, 0x9b, 0xee, 0x01, 0x31, 0x1c, 0x4b, 0x80, 0xa6, 0x45, 0x3d, 0x20, 0xe0, - 0x03, 0xa8, 0x73, 0x3b, 0xb6, 0xfb, 0x7d, 0xa5, 0xc0, 0xf4, 0xb5, 0x69, 0x11, 0x6d, 0x21, 0x69, - 0x99, 0xa8, 0xb4, 0x7f, 0xd2, 0x60, 0x51, 0x11, 0x37, 0x93, 0x57, 0xdf, 0x87, 0x3c, 0x07, 0xa9, - 0x45, 0xa5, 0xb3, 0x1c, 0x1e, 0xc5, 0xd5, 0xe8, 0x82, 0x07, 0x6d, 0x42, 0x81, 0x3f, 0xc9, 0x77, - 0x80, 0x64, 0x76, 0xc9, 0x84, 0x1f, 0xc2, 0x92, 0x20, 0x91, 0xa1, 0x9d, 0x74, 0x30, 0xd8, 0x62, - 0xe0, 0x3f, 0x85, 0xe5, 0x30, 0xdb, 0x4c, 0x53, 0x52, 0x8c, 0xcc, 0xbc, 0x89, 0x91, 0xdb, 0xd2, - 0xc8, 0x97, 0xa3, 0xbe, 0x52, 0x47, 0x45, 0x77, 0x8c, 0xba, 0x5e, 0x99, 0xf0, 0x7a, 0x05, 0x13, - 0x90, 0x22, 0xbe, 0xd1, 0x09, 0x2c, 0xc9, 0xed, 0x70, 0x60, 0xba, 0x7e, 0xb9, 0xfe, 0x25, 0x20, - 0x95, 0xf8, 0x8d, 0x1a, 0xf4, 0x8e, 0x74, 0xc7, 0x91, 0x63, 0x0f, 0xed, 0x54, 0x97, 0xe2, 0x3f, - 0x83, 0x95, 0x08, 0xdf, 0x37, 0xed, 0xb7, 0x5d, 0x22, 0x8b, 0x15, 0xe9, 0xb7, 0x8f, 0x01, 0xa9, - 0xc4, 0x99, 0xb2, 0x56, 0x0b, 0x16, 0x5f, 0xd8, 0x13, 0x1a, 0xfe, 0x28, 0x35, 0x38, 0xf7, 0x1c, - 0x63, 0xf0, 0x5d, 0xe1, 0xb7, 0xa9, 0x72, 0x75, 0xc0, 0x4c, 0xca, 0xff, 0x43, 0x83, 0xca, 0xf6, - 0xc0, 0x70, 0x86, 0x52, 0xf1, 0xf7, 0x20, 0xcf, 0xdf, 0x9c, 0x05, 0x58, 0xf5, 0x4e, 0x58, 0x8c, - 0xca, 0xcb, 0x1b, 0xdb, 0xfc, 0x3d, 0x5b, 0x8c, 0xa2, 0x86, 0x8b, 0xef, 0x59, 0xbb, 0x91, 0xef, - 0x5b, 0xbb, 0xe8, 0x03, 0xc8, 0x19, 0x74, 0x08, 0x4b, 0x33, 0xb5, 0x28, 0x66, 0xc1, 0xa4, 0xb1, - 0xfa, 0x9e, 0x73, 0xe1, 0xef, 0x40, 0x59, 0xd1, 0x80, 0x0a, 0x90, 0x7d, 0xd6, 0x16, 0xc5, 0xf8, - 0xf6, 0x4e, 0x77, 0xef, 0x15, 0x07, 0x6b, 0x6a, 0x00, 0xbb, 0x6d, 0xbf, 0x9d, 0xc1, 0x9f, 0x89, - 0x51, 0x22, 0xa4, 0xab, 0xf6, 0x68, 0x69, 0xf6, 0x64, 0xde, 0xc8, 0x9e, 0x2b, 0xa8, 0x8a, 0xe9, - 0xcf, 0x9a, 0xa2, 0x98, 0xbc, 0x94, 0x14, 0xa5, 0x18, 0xaf, 0x0b, 0x46, 0xbc, 0x00, 0x55, 0x91, - 0xb4, 0xc4, 0xfe, 0xfb, 0xf7, 0x0c, 0xd4, 0x24, 0x65, 0x56, 0x50, 0x5d, 0xe2, 0x81, 0x3c, 0xc9, - 0xf9, 0x68, 0xe0, 0x2a, 0xe4, 0xfb, 0xa7, 0xc7, 0xe6, 0x97, 0xf2, 0x03, 0x88, 0x68, 0x51, 0xfa, - 0x80, 0xeb, 0xe1, 0x5f, 0x21, 0x45, 0x8b, 0x66, 0x23, 0xc7, 0x38, 0xf3, 0xf6, 0xac, 0x3e, 0xb9, - 0x62, 0xb9, 0x6d, 0x5e, 0x0f, 0x08, 0x0c, 0x28, 0x11, 0x5f, 0x2b, 0xd9, 0x0b, 0x82, 0xf2, 0xf5, - 0x12, 0x3d, 0x82, 0x3a, 0x7d, 0xde, 0x1e, 0x8d, 0x06, 0x26, 0xe9, 0x73, 0x01, 0x05, 0xc6, 0x13, - 0xa3, 0x53, 0xed, 0xac, 0xa4, 0x76, 0x1b, 0x45, 0x16, 0x5d, 0x45, 0x0b, 0xad, 0x43, 0x99, 0xdb, - 0xb7, 0x67, 0xbd, 0x74, 0x09, 0xfb, 0x84, 0x97, 0xd5, 0x55, 0x52, 0x38, 0x5b, 0x42, 0x34, 0x5b, - 0x2e, 0xc1, 0xe2, 0xf6, 0xd8, 0xbb, 0x68, 0x5b, 0xc6, 0xe9, 0x40, 0x46, 0x22, 0x5a, 0xce, 0x50, - 0xe2, 0xae, 0xe9, 0xaa, 0xd4, 0x36, 0x2c, 0x51, 0x2a, 0xb1, 0x3c, 0xb3, 0xa7, 0x64, 0x02, 0x59, - 0x2b, 0x68, 0x91, 0x5a, 0xc1, 0x70, 0xdd, 0xd7, 0xb6, 0xd3, 0x17, 0xee, 0xf5, 0xdb, 0x78, 0xc2, - 0x85, 0xbf, 0x74, 0x43, 0xf9, 0xfe, 0xd7, 0x94, 0x82, 0x3e, 0x84, 0x82, 0x3d, 0x62, 0x9f, 0xa4, - 0x05, 0x6e, 0xb0, 0xba, 0xc9, 0x3f, 0x62, 0x6f, 0x0a, 0xc1, 0x1d, 0xde, 0xab, 0x4b, 0x36, 0xbc, - 0x11, 0xe8, 0x7d, 0x46, 0xbc, 0x29, 0x7a, 0xf1, 0x63, 0x58, 0x91, 0x9c, 0x02, 0x26, 0x9f, 0xc2, - 0xdc, 0x81, 0x7b, 0x92, 0x79, 0xe7, 0xc2, 0xb0, 0xce, 0xc9, 0x91, 0x30, 0xf1, 0x37, 0xf5, 0xcf, - 0x53, 0x68, 0xf8, 0x76, 0xb2, 0x57, 0x37, 0x7b, 0xa0, 0x1a, 0x30, 0x76, 0xc5, 0x4e, 0x2f, 0xe9, - 0xec, 0x99, 0xd2, 0x1c, 0x7b, 0xe0, 0xd7, 0x6a, 0xf4, 0x19, 0xef, 0xc0, 0x6d, 0x29, 0x43, 0xbc, - 0x54, 0x85, 0x85, 0xc4, 0x0c, 0x4a, 0x12, 0x22, 0x1c, 0x46, 0x87, 0x4e, 0x5f, 0x28, 0x95, 0x33, - 0xec, 0x5a, 0x26, 0x53, 0x53, 0x64, 0xae, 0xf0, 0x3d, 0x44, 0x0d, 0x53, 0xd3, 0xb1, 0x20, 0x53, - 0x01, 0x2a, 0x59, 0x2c, 0x04, 0x25, 0xc7, 0x16, 0x22, 0x26, 0xfa, 0x07, 0xb0, 0xe6, 0x1b, 0x41, - 0xfd, 0x76, 0x44, 0x9c, 0xa1, 0xe9, 0xba, 0x0a, 0xb0, 0x9a, 0x34, 0xf1, 0x77, 0x60, 0x7e, 0x44, - 0x44, 0x24, 0x2c, 0x6f, 0x21, 0xb9, 0x89, 0x94, 0xc1, 0xac, 0x1f, 0xf7, 0xe1, 0xbe, 0x94, 0xce, - 0x3d, 0x9a, 0x28, 0x3e, 0x6a, 0x94, 0x84, 0x9b, 0x32, 0x29, 0x70, 0x53, 0x36, 0x02, 0xf6, 0x7f, - 0xcc, 0x1d, 0x29, 0x4f, 0xe3, 0x4c, 0x19, 0x6e, 0x9f, 0xfb, 0xd4, 0x3f, 0xc4, 0x33, 0x09, 0x3b, - 0x85, 0xe5, 0xf0, 0xd9, 0x9f, 0x29, 0xf8, 0x2e, 0x43, 0xce, 0xb3, 0x2f, 0x89, 0x0c, 0xbd, 0xbc, - 0x21, 0x0d, 0xf6, 0x03, 0xc3, 0x4c, 0x06, 0x1b, 0x81, 0x30, 0xb6, 0x25, 0x67, 0xb5, 0x97, 0xae, - 0xa6, 0xac, 0x6c, 0x79, 0x03, 0x1f, 0xc2, 0x6a, 0x34, 0x4c, 0xcc, 0x64, 0xf2, 0x2b, 0xbe, 0x81, - 0x93, 0x22, 0xc9, 0x4c, 0x72, 0x3f, 0x09, 0x82, 0x81, 0x12, 0x50, 0x66, 0x12, 0xa9, 0x43, 0x33, - 0x29, 0xbe, 0xfc, 0x36, 0xf6, 0xab, 0x1f, 0x6e, 0x66, 0x12, 0xe6, 0x06, 0xc2, 0x66, 0x5f, 0xfe, - 0x20, 0x46, 0x64, 0xa7, 0xc6, 0x08, 0x71, 0x48, 0x82, 0x28, 0xf6, 0x35, 0x6c, 0x3a, 0xa1, 0x23, - 0x08, 0xa0, 0xb3, 0xea, 0xa0, 0x39, 0xc4, 0xd7, 0xc1, 0x1a, 0x72, 0x63, 0xab, 0x61, 0x77, 0xa6, - 0xc5, 0xf8, 0x34, 0x88, 0x9d, 0xb1, 0xc8, 0x3c, 0x93, 0xe0, 0xcf, 0x60, 0x3d, 0x3d, 0x28, 0xcf, - 0x22, 0xf9, 0x51, 0x0b, 0x4a, 0x7e, 0x19, 0xac, 0xdc, 0x22, 0x2a, 0x43, 0xe1, 0xb0, 0x73, 0x7c, - 0xb4, 0xbd, 0xd3, 0xe6, 0xd7, 0x88, 0x76, 0x3a, 0xba, 0xfe, 0xf2, 0xa8, 0x5b, 0xcf, 0x6c, 0xfd, - 0x32, 0x0b, 0x99, 0xfd, 0x57, 0xe8, 0x73, 0xc8, 0xf1, 0x6f, 0xea, 0x53, 0x2e, 0x52, 0x34, 0xa7, - 0x5d, 0x1b, 0xc0, 0xb7, 0x7e, 0xfc, 0xdf, 0xbf, 0xfc, 0x79, 0x66, 0x11, 0x57, 0x5a, 0x93, 0x6f, - 0xb7, 0x2e, 0x27, 0x2d, 0x96, 0x1b, 0x9e, 0x68, 0x8f, 0xd0, 0x27, 0x90, 0x3d, 0x1a, 0x7b, 0x28, - 0xf5, 0x82, 0x45, 0x33, 0xfd, 0x26, 0x01, 0x5e, 0x61, 0x42, 0x17, 0x30, 0x08, 0xa1, 0xa3, 0xb1, - 0x47, 0x45, 0xfe, 0x10, 0xca, 0xea, 0x3d, 0x80, 0x1b, 0x6f, 0x5d, 0x34, 0x6f, 0xbe, 0x63, 0x80, - 0xef, 0x31, 0x55, 0xb7, 0x30, 0x12, 0xaa, 0xf8, 0x4d, 0x05, 0x75, 0x16, 0xdd, 0x2b, 0x0b, 0xa5, - 0xde, 0xc9, 0x68, 0xa6, 0x5f, 0x3b, 0x88, 0xcd, 0xc2, 0xbb, 0xb2, 0xa8, 0xc8, 0x3f, 0x16, 0x37, - 0x0e, 0x7a, 0x1e, 0xba, 0x9f, 0xf0, 0xc5, 0x59, 0xfd, 0xb6, 0xda, 0x5c, 0x4f, 0x67, 0x10, 0x4a, - 0xee, 0x32, 0x25, 0xab, 0x78, 0x51, 0x28, 0xe9, 0xf9, 0x2c, 0x4f, 0xb4, 0x47, 0x5b, 0x3d, 0xc8, - 0xb1, 0xef, 0x16, 0xe8, 0x0b, 0xf9, 0xd0, 0x4c, 0xf8, 0x80, 0x93, 0xb2, 0xd0, 0xa1, 0x2f, 0x1e, - 0x78, 0x99, 0x29, 0xaa, 0xe1, 0x12, 0x55, 0xc4, 0xbe, 0x5a, 0x3c, 0xd1, 0x1e, 0x6d, 0x68, 0x1f, - 0x6a, 0x5b, 0xff, 0x9c, 0x83, 0x1c, 0x03, 0xec, 0xd0, 0x25, 0x40, 0x80, 0xe1, 0x47, 0x67, 0x17, - 0xfb, 0x2a, 0x10, 0x9d, 0x5d, 0x1c, 0xfe, 0xc7, 0x4d, 0xa6, 0x74, 0x19, 0x2f, 0x50, 0xa5, 0x0c, - 0x07, 0x6c, 0x31, 0x68, 0x93, 0xfa, 0xf1, 0xaf, 0x34, 0x81, 0x57, 0xf2, 0xb3, 0x84, 0x92, 0xa4, - 0x85, 0x80, 0xfc, 0xe8, 0x76, 0x48, 0x00, 0xf1, 0xf1, 0x77, 0x99, 0xc2, 0x16, 0xae, 0x07, 0x0a, - 0x1d, 0xc6, 0xf1, 0x44, 0x7b, 0xf4, 0x45, 0x03, 0x2f, 0x09, 0x2f, 0x47, 0x7a, 0xd0, 0x8f, 0xa0, - 0x16, 0x06, 0xaa, 0xd1, 0x83, 0x04, 0x5d, 0x51, 0xbc, 0xbb, 0xf9, 0xf6, 0x74, 0x26, 0x61, 0xd3, - 0x1a, 0xb3, 0x49, 0x28, 0xe7, 0x9a, 0x2f, 0x09, 0x19, 0x19, 0x94, 0x49, 0xac, 0x01, 0xfa, 0x7b, - 0x4d, 0x7c, 0x47, 0x08, 0x90, 0x67, 0x94, 0x24, 0x3d, 0x86, 0x6b, 0x37, 0x1f, 0xde, 0xc0, 0x25, - 0x8c, 0xf8, 0x03, 0x66, 0xc4, 0xef, 0xe2, 0xe5, 0xc0, 0x08, 0xcf, 0x1c, 0x12, 0xcf, 0x16, 0x56, - 0x7c, 0x71, 0x17, 0xdf, 0x0a, 0x39, 0x27, 0xd4, 0x1b, 0x2c, 0x16, 0x47, 0x8f, 0x13, 0x17, 0x2b, - 0x84, 0x46, 0x27, 0x2e, 0x56, 0x18, 0x7a, 0x4e, 0x5a, 0x2c, 0x8e, 0x15, 0x27, 0x2d, 0x96, 0xdf, - 0xb3, 0xf5, 0xff, 0xf3, 0x50, 0xd8, 0xe1, 0x37, 0x7d, 0x91, 0x0d, 0x25, 0x1f, 0x7c, 0x45, 0x6b, - 0x49, 0x08, 0x53, 0xf0, 0x2e, 0xd1, 0xbc, 0x9f, 0xda, 0x2f, 0x0c, 0x7a, 0x8b, 0x19, 0x74, 0x07, - 0xaf, 0x52, 0xcd, 0xe2, 0x32, 0x71, 0x8b, 0xc3, 0x18, 0x2d, 0xa3, 0xdf, 0xa7, 0x8e, 0xf8, 0x13, - 0xa8, 0xa8, 0xe8, 0x28, 0x7a, 0x2b, 0x11, 0xd5, 0x52, 0x01, 0xd6, 0x26, 0x9e, 0xc6, 0x22, 0x34, - 0xbf, 0xcd, 0x34, 0xaf, 0xe1, 0xdb, 0x09, 0x9a, 0x1d, 0xc6, 0x1a, 0x52, 0xce, 0x91, 0xcd, 0x64, - 0xe5, 0x21, 0xe0, 0x34, 0x59, 0x79, 0x18, 0x18, 0x9d, 0xaa, 0x7c, 0xcc, 0x58, 0xa9, 0x72, 0x17, - 0x20, 0xc0, 0x30, 0x51, 0xa2, 0x2f, 0x95, 0x97, 0xa9, 0x68, 0x70, 0x88, 0xc3, 0x9f, 0x18, 0x33, - 0xb5, 0x62, 0xdf, 0x45, 0xd4, 0x0e, 0x4c, 0xd7, 0xe3, 0x07, 0xb3, 0x1a, 0x02, 0x25, 0x51, 0xe2, - 0x7c, 0xc2, 0xc8, 0x66, 0xf3, 0xc1, 0x54, 0x1e, 0xa1, 0xfd, 0x21, 0xd3, 0x7e, 0x1f, 0x37, 0x13, - 0xb4, 0x8f, 0x38, 0x2f, 0xdd, 0x6c, 0x7f, 0x9d, 0x87, 0xf2, 0x0b, 0xc3, 0xb4, 0x3c, 0x62, 0x19, - 0x56, 0x8f, 0xa0, 0x53, 0xc8, 0xb1, 0x4c, 0x1d, 0x0d, 0xc4, 0x2a, 0x60, 0x17, 0x0d, 0xc4, 0x21, - 0x34, 0x0b, 0xaf, 0x33, 0xc5, 0x4d, 0xbc, 0x42, 0x15, 0x0f, 0x03, 0xd1, 0x2d, 0x06, 0x42, 0xd1, - 0x49, 0x9f, 0x41, 0x5e, 0x7c, 0xc3, 0x89, 0x08, 0x0a, 0x81, 0x53, 0xcd, 0xbb, 0xc9, 0x9d, 0x49, - 0x7b, 0x59, 0x55, 0xe3, 0x32, 0x3e, 0xaa, 0x67, 0x02, 0x10, 0xa0, 0xab, 0xd1, 0x15, 0x8d, 0x81, - 0xb1, 0xcd, 0xf5, 0x74, 0x86, 0x24, 0x9f, 0xaa, 0x3a, 0xfb, 0x3e, 0x2f, 0xd5, 0xfb, 0x47, 0x30, - 0xff, 0xdc, 0x70, 0x2f, 0x50, 0x24, 0xf7, 0x2a, 0x37, 0x80, 0x9a, 0xcd, 0xa4, 0x2e, 0xa1, 0xe5, - 0x3e, 0xd3, 0x72, 0x9b, 0x87, 0x32, 0x55, 0xcb, 0x85, 0xe1, 0xd2, 0xa4, 0x86, 0xfa, 0x90, 0xe7, - 0x17, 0x82, 0xa2, 0xfe, 0x0b, 0x5d, 0x2a, 0x8a, 0xfa, 0x2f, 0x7c, 0x87, 0xe8, 0x66, 0x2d, 0x23, - 0x28, 0xca, 0x1b, 0x38, 0x28, 0xf2, 0x39, 0x36, 0x72, 0x5b, 0xa7, 0xb9, 0x96, 0xd6, 0x2d, 0x74, - 0x3d, 0x60, 0xba, 0xee, 0xe1, 0x46, 0x6c, 0xad, 0x04, 0xe7, 0x13, 0xed, 0xd1, 0x87, 0x1a, 0xfa, - 0x11, 0x40, 0x00, 0x48, 0xc7, 0x4e, 0x60, 0x14, 0xdb, 0x8e, 0x9d, 0xc0, 0x18, 0x96, 0x8d, 0x37, - 0x99, 0xde, 0x0d, 0xfc, 0x20, 0xaa, 0xd7, 0x73, 0x0c, 0xcb, 0x3d, 0x23, 0xce, 0x07, 0x1c, 0x74, - 0x74, 0x2f, 0xcc, 0x11, 0x3d, 0x0c, 0xff, 0xba, 0x00, 0xf3, 0xb4, 0x02, 0xa6, 0x85, 0x42, 0x00, - 0x1c, 0x44, 0x2d, 0x89, 0x01, 0x7c, 0x51, 0x4b, 0xe2, 0x98, 0x43, 0xb8, 0x50, 0x60, 0xbf, 0x11, - 0x21, 0x8c, 0x81, 0x3a, 0xda, 0x86, 0xb2, 0x82, 0x2c, 0xa0, 0x04, 0x61, 0x61, 0xe4, 0x30, 0x9a, - 0x7a, 0x12, 0x60, 0x09, 0x7c, 0x87, 0xe9, 0x5b, 0xe1, 0xa9, 0x87, 0xe9, 0xeb, 0x73, 0x0e, 0xaa, - 0xf0, 0x35, 0x54, 0x54, 0xf4, 0x01, 0x25, 0xc8, 0x8b, 0xa0, 0x92, 0xd1, 0x30, 0x9b, 0x04, 0x5e, - 0x84, 0x0f, 0xbe, 0xff, 0x3b, 0x18, 0xc9, 0x46, 0x15, 0x0f, 0xa0, 0x20, 0xe0, 0x88, 0xa4, 0x59, - 0x86, 0x21, 0xcc, 0xa4, 0x59, 0x46, 0xb0, 0x8c, 0x70, 0x71, 0xc9, 0x34, 0xd2, 0x37, 0x2e, 0x99, - 0xca, 0x84, 0xb6, 0x67, 0xc4, 0x4b, 0xd3, 0x16, 0xa0, 0x6b, 0x69, 0xda, 0x94, 0xb7, 0xdd, 0x34, - 0x6d, 0xe7, 0xc4, 0x13, 0xc7, 0x45, 0xbe, 0x45, 0xa2, 0x14, 0x61, 0x6a, 0xfa, 0xc0, 0xd3, 0x58, - 0x92, 0x6a, 0xff, 0x40, 0xa1, 0xcc, 0x1d, 0x57, 0x00, 0x01, 0x58, 0x12, 0x2d, 0xe8, 0x12, 0x11, - 0xd7, 0x68, 0x41, 0x97, 0x8c, 0xb7, 0x84, 0x43, 0x43, 0xa0, 0x97, 0xbf, 0x7a, 0x50, 0xcd, 0x3f, - 0xd3, 0x00, 0xc5, 0x71, 0x15, 0xf4, 0x38, 0x59, 0x7a, 0x22, 0x8e, 0xdb, 0x7c, 0xff, 0xcd, 0x98, - 0x93, 0xa2, 0x7d, 0x60, 0x52, 0x8f, 0x71, 0x8f, 0x5e, 0x53, 0xa3, 0xfe, 0x42, 0x83, 0x6a, 0x08, - 0x94, 0x41, 0xef, 0xa4, 0xac, 0x69, 0x04, 0x06, 0x6e, 0xbe, 0x7b, 0x23, 0x5f, 0x52, 0xa5, 0xab, - 0xec, 0x00, 0x59, 0xf2, 0xff, 0x44, 0x83, 0x5a, 0x18, 0xc4, 0x41, 0x29, 0xb2, 0x63, 0x30, 0x72, - 0x73, 0xe3, 0x66, 0xc6, 0xe9, 0xcb, 0x13, 0x54, 0xfb, 0x03, 0x28, 0x08, 0xd8, 0x27, 0x69, 0xe3, - 0x87, 0x01, 0xe8, 0xa4, 0x8d, 0x1f, 0xc1, 0x8c, 0x12, 0x36, 0xbe, 0x63, 0x0f, 0x88, 0x72, 0xcc, - 0x04, 0x2e, 0x94, 0xa6, 0x6d, 0xfa, 0x31, 0x8b, 0x80, 0x4a, 0x69, 0xda, 0x82, 0x63, 0x26, 0x01, - 0x21, 0x94, 0x22, 0xec, 0x86, 0x63, 0x16, 0xc5, 0x93, 0x12, 0x8e, 0x19, 0x53, 0xa8, 0x1c, 0xb3, - 0x00, 0xba, 0x49, 0x3a, 0x66, 0x31, 0x3c, 0x3d, 0xe9, 0x98, 0xc5, 0xd1, 0x9f, 0x84, 0x75, 0x64, - 0x7a, 0x43, 0xc7, 0x6c, 0x29, 0x01, 0xe5, 0x41, 0xef, 0xa7, 0x38, 0x31, 0x11, 0xa6, 0x6f, 0x7e, - 0xf0, 0x86, 0xdc, 0xa9, 0x7b, 0x9c, 0xbb, 0x5f, 0xee, 0xf1, 0xbf, 0xd1, 0x60, 0x39, 0x09, 0x21, - 0x42, 0x29, 0x7a, 0x52, 0xe0, 0xfd, 0xe6, 0xe6, 0x9b, 0xb2, 0x4f, 0xf7, 0x96, 0xbf, 0xeb, 0x9f, - 0xd6, 0xff, 0xed, 0xab, 0x35, 0xed, 0x3f, 0xbf, 0x5a, 0xd3, 0xfe, 0xe7, 0xab, 0x35, 0xed, 0x6f, - 0xff, 0x77, 0x6d, 0xee, 0x34, 0xcf, 0x7e, 0x5d, 0xf9, 0xed, 0x5f, 0x05, 0x00, 0x00, 0xff, 0xff, - 0x52, 0x4e, 0xd7, 0x33, 0xe4, 0x39, 0x00, 0x00, + // 3950 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5b, 0x5b, 0x73, 0x1b, 0xc9, + 0x75, 0xe6, 0x00, 0xc4, 0xed, 0xe0, 0x42, 0xb0, 0x79, 0x11, 0x04, 0x49, 0x14, 0xb7, 0xb5, 0xda, + 0xe5, 0x4a, 0xbb, 0xc4, 0x9a, 0xb6, 0x93, 0x2a, 0x25, 0x71, 0x4c, 0x91, 0x58, 0x89, 0x4b, 0x8a, + 0xe0, 0x0e, 0x21, 0xed, 0xa5, 0x5c, 0x61, 0x0d, 0x81, 0x26, 0x39, 0x21, 0x30, 0x03, 0xcf, 0x0c, + 0x20, 0x72, 0x73, 0x71, 0xca, 0xe5, 0xa4, 0x2a, 0x79, 0xb4, 0xab, 0x52, 0xc9, 0x43, 0x9e, 0x52, + 0xa9, 0xc4, 0x0f, 0x79, 0x4e, 0x55, 0x7e, 0x41, 0xde, 0x92, 0x54, 0xfe, 0x40, 0x6a, 0xe3, 0x97, + 0xe4, 0x29, 0x3f, 0xc1, 0xd5, 0xb7, 0x99, 0x9e, 0x1b, 0x28, 0x1b, 0xde, 0x7d, 0x21, 0xa7, 0x4f, + 0x9f, 0x3e, 0xe7, 0xf4, 0xe9, 0xee, 0x73, 0xce, 0x7c, 0x3d, 0x80, 0x92, 0x33, 0xea, 0x6d, 0x8e, + 0x1c, 0xdb, 0xb3, 0x51, 0x85, 0x78, 0xbd, 0xbe, 0x4b, 0x9c, 0x09, 0x71, 0x46, 0xa7, 0xcd, 0xe5, + 0x73, 0xfb, 0xdc, 0x66, 0x1d, 0x2d, 0xfa, 0xc4, 0x79, 0x9a, 0xb7, 0x29, 0x4f, 0x6b, 0x38, 0xe9, + 0xf5, 0xd8, 0x9f, 0xd1, 0x69, 0xeb, 0x72, 0x22, 0xba, 0xee, 0xb0, 0x2e, 0x63, 0xec, 0x5d, 0xb0, + 0x3f, 0xa3, 0x53, 0xf6, 0x4f, 0x74, 0xde, 0x3d, 0xb7, 0xed, 0xf3, 0x01, 0x69, 0x19, 0x23, 0xb3, + 0x65, 0x58, 0x96, 0xed, 0x19, 0x9e, 0x69, 0x5b, 0x2e, 0xef, 0xc5, 0x7f, 0xae, 0x41, 0x4d, 0x27, + 0xee, 0xc8, 0xb6, 0x5c, 0xf2, 0x9c, 0x18, 0x7d, 0xe2, 0xa0, 0x7b, 0x00, 0xbd, 0xc1, 0xd8, 0xf5, + 0x88, 0x73, 0x62, 0xf6, 0x1b, 0xda, 0xba, 0xb6, 0x31, 0xaf, 0x97, 0x04, 0x65, 0xaf, 0x8f, 0xee, + 0x40, 0x69, 0x48, 0x86, 0xa7, 0xbc, 0x37, 0xc3, 0x7a, 0x8b, 0x9c, 0xb0, 0xd7, 0x47, 0x4d, 0x28, + 0x3a, 0x64, 0x62, 0xba, 0xa6, 0x6d, 0x35, 0xb2, 0xeb, 0xda, 0x46, 0x56, 0xf7, 0xdb, 0x74, 0xa0, + 0x63, 0x9c, 0x79, 0x27, 0x1e, 0x71, 0x86, 0x8d, 0x79, 0x3e, 0x90, 0x12, 0xba, 0xc4, 0x19, 0xe2, + 0x9f, 0xe4, 0xa0, 0xa2, 0x1b, 0xd6, 0x39, 0xd1, 0xc9, 0x0f, 0xc7, 0xc4, 0xf5, 0x50, 0x1d, 0xb2, + 0x97, 0xe4, 0x9a, 0xa9, 0xaf, 0xe8, 0xf4, 0x91, 0x8f, 0xb7, 0xce, 0xc9, 0x09, 0xb1, 0xb8, 0xe2, + 0x0a, 0x1d, 0x6f, 0x9d, 0x93, 0xb6, 0xd5, 0x47, 0xcb, 0x90, 0x1b, 0x98, 0x43, 0xd3, 0x13, 0x5a, + 0x79, 0x23, 0x64, 0xce, 0x7c, 0xc4, 0x9c, 0x1d, 0x00, 0xd7, 0x76, 0xbc, 0x13, 0xdb, 0xe9, 0x13, + 0xa7, 0x91, 0x5b, 0xd7, 0x36, 0x6a, 0x5b, 0x6f, 0x6f, 0xaa, 0x0b, 0xb1, 0xa9, 0x1a, 0xb4, 0x79, + 0x6c, 0x3b, 0x5e, 0x87, 0xf2, 0xea, 0x25, 0x57, 0x3e, 0xa2, 0x8f, 0xa0, 0xcc, 0x84, 0x78, 0x86, + 0x73, 0x4e, 0xbc, 0x46, 0x9e, 0x49, 0x79, 0x78, 0x83, 0x94, 0x2e, 0x63, 0xd6, 0x99, 0x7a, 0xfe, + 0x8c, 0x30, 0x54, 0x5c, 0xe2, 0x98, 0xc6, 0xc0, 0xfc, 0xd2, 0x38, 0x1d, 0x90, 0x46, 0x61, 0x5d, + 0xdb, 0x28, 0xea, 0x21, 0x1a, 0x9d, 0xff, 0x25, 0xb9, 0x76, 0x4f, 0x6c, 0x6b, 0x70, 0xdd, 0x28, + 0x32, 0x86, 0x22, 0x25, 0x74, 0xac, 0xc1, 0x35, 0x5b, 0x34, 0x7b, 0x6c, 0x79, 0xbc, 0xb7, 0xc4, + 0x7a, 0x4b, 0x8c, 0xc2, 0xba, 0x37, 0xa0, 0x3e, 0x34, 0xad, 0x93, 0xa1, 0xdd, 0x3f, 0xf1, 0x1d, + 0x02, 0xcc, 0x21, 0xb5, 0xa1, 0x69, 0xbd, 0xb0, 0xfb, 0xba, 0x74, 0x0b, 0xe5, 0x34, 0xae, 0xc2, + 0x9c, 0x65, 0xc1, 0x69, 0x5c, 0xa9, 0x9c, 0x9b, 0xb0, 0x44, 0x65, 0xf6, 0x1c, 0x62, 0x78, 0x24, + 0x60, 0xae, 0x30, 0xe6, 0xc5, 0xa1, 0x69, 0xed, 0xb0, 0x9e, 0x10, 0xbf, 0x71, 0x15, 0xe3, 0xaf, + 0x0a, 0x7e, 0xe3, 0x2a, 0xcc, 0x8f, 0x37, 0xa1, 0xe4, 0xfb, 0x1c, 0x15, 0x61, 0xfe, 0xb0, 0x73, + 0xd8, 0xae, 0xcf, 0x21, 0x80, 0xfc, 0xf6, 0xf1, 0x4e, 0xfb, 0x70, 0xb7, 0xae, 0xa1, 0x32, 0x14, + 0x76, 0xdb, 0xbc, 0x91, 0xc1, 0x4f, 0x01, 0x02, 0xef, 0xa2, 0x02, 0x64, 0xf7, 0xdb, 0x9f, 0xd7, + 0xe7, 0x28, 0xcf, 0xab, 0xb6, 0x7e, 0xbc, 0xd7, 0x39, 0xac, 0x6b, 0x74, 0xf0, 0x8e, 0xde, 0xde, + 0xee, 0xb6, 0xeb, 0x19, 0xca, 0xf1, 0xa2, 0xb3, 0x5b, 0xcf, 0xa2, 0x12, 0xe4, 0x5e, 0x6d, 0x1f, + 0xbc, 0x6c, 0xd7, 0xe7, 0xf1, 0xcf, 0x34, 0xa8, 0x8a, 0xf5, 0xe2, 0x67, 0x02, 0x7d, 0x07, 0xf2, + 0x17, 0xec, 0x5c, 0xb0, 0xad, 0x58, 0xde, 0xba, 0x1b, 0x59, 0xdc, 0xd0, 0xd9, 0xd1, 0x05, 0x2f, + 0xc2, 0x90, 0xbd, 0x9c, 0xb8, 0x8d, 0xcc, 0x7a, 0x76, 0xa3, 0xbc, 0x55, 0xdf, 0xe4, 0x07, 0x76, + 0x73, 0x9f, 0x5c, 0xbf, 0x32, 0x06, 0x63, 0xa2, 0xd3, 0x4e, 0x84, 0x60, 0x7e, 0x68, 0x3b, 0x84, + 0xed, 0xd8, 0xa2, 0xce, 0x9e, 0xe9, 0x36, 0x66, 0x8b, 0x26, 0x76, 0x2b, 0x6f, 0xe0, 0x9f, 0x6b, + 0x00, 0x47, 0x63, 0x2f, 0xfd, 0x68, 0x2c, 0x43, 0x6e, 0x42, 0x05, 0x8b, 0x63, 0xc1, 0x1b, 0xec, + 0x4c, 0x10, 0xc3, 0x25, 0xfe, 0x99, 0xa0, 0x0d, 0x74, 0x0b, 0x0a, 0x23, 0x87, 0x4c, 0x4e, 0x2e, + 0x27, 0x4c, 0x49, 0x51, 0xcf, 0xd3, 0xe6, 0xfe, 0x04, 0xbd, 0x05, 0x15, 0xf3, 0xdc, 0xb2, 0x1d, + 0x72, 0xc2, 0x65, 0xe5, 0x58, 0x6f, 0x99, 0xd3, 0x98, 0xdd, 0x0a, 0x0b, 0x17, 0x9c, 0x57, 0x59, + 0x0e, 0x28, 0x09, 0x5b, 0x50, 0x66, 0xa6, 0xce, 0xe4, 0xbe, 0xf7, 0x02, 0x1b, 0x33, 0x6c, 0x58, + 0xdc, 0x85, 0xc2, 0x6a, 0xfc, 0x03, 0x40, 0xbb, 0x64, 0x40, 0x3c, 0x32, 0x4b, 0xf4, 0x50, 0x7c, + 0x92, 0x55, 0x7d, 0x82, 0x7f, 0xaa, 0xc1, 0x52, 0x48, 0xfc, 0x4c, 0xd3, 0x6a, 0x40, 0xa1, 0xcf, + 0x84, 0x71, 0x0b, 0xb2, 0xba, 0x6c, 0xa2, 0xc7, 0x50, 0x14, 0x06, 0xb8, 0x8d, 0x6c, 0xca, 0xa6, + 0x29, 0x70, 0x9b, 0x5c, 0xfc, 0xf3, 0x0c, 0x94, 0xc4, 0x44, 0x3b, 0x23, 0xb4, 0x0d, 0x55, 0x87, + 0x37, 0x4e, 0xd8, 0x7c, 0x84, 0x45, 0xcd, 0xf4, 0x20, 0xf4, 0x7c, 0x4e, 0xaf, 0x88, 0x21, 0x8c, + 0x8c, 0x7e, 0x07, 0xca, 0x52, 0xc4, 0x68, 0xec, 0x09, 0x97, 0x37, 0xc2, 0x02, 0x82, 0xfd, 0xf7, + 0x7c, 0x4e, 0x07, 0xc1, 0x7e, 0x34, 0xf6, 0x50, 0x17, 0x96, 0xe5, 0x60, 0x3e, 0x1b, 0x61, 0x46, + 0x96, 0x49, 0x59, 0x0f, 0x4b, 0x89, 0x2f, 0xd5, 0xf3, 0x39, 0x1d, 0x89, 0xf1, 0x4a, 0xa7, 0x6a, + 0x92, 0x77, 0xc5, 0x83, 0x77, 0xcc, 0xa4, 0xee, 0x95, 0x15, 0x37, 0xa9, 0x7b, 0x65, 0x3d, 0x2d, + 0x41, 0x41, 0xb4, 0xf0, 0xbf, 0x64, 0x00, 0xe4, 0x6a, 0x74, 0x46, 0x68, 0x17, 0x6a, 0x8e, 0x68, + 0x85, 0xbc, 0x75, 0x27, 0xd1, 0x5b, 0x62, 0x11, 0xe7, 0xf4, 0xaa, 0x1c, 0xc4, 0x8d, 0xfb, 0x1e, + 0x54, 0x7c, 0x29, 0x81, 0xc3, 0x6e, 0x27, 0x38, 0xcc, 0x97, 0x50, 0x96, 0x03, 0xa8, 0xcb, 0x3e, + 0x85, 0x15, 0x7f, 0x7c, 0x82, 0xcf, 0xde, 0x9a, 0xe2, 0x33, 0x5f, 0xe0, 0x92, 0x94, 0xa0, 0x7a, + 0x4d, 0x35, 0x2c, 0x70, 0xdb, 0xed, 0x04, 0xb7, 0xc5, 0x0d, 0xa3, 0x8e, 0x03, 0x9a, 0x2f, 0x79, + 0x13, 0xff, 0x6f, 0x16, 0x0a, 0x3b, 0xf6, 0x70, 0x64, 0x38, 0x74, 0x35, 0xf2, 0x0e, 0x71, 0xc7, + 0x03, 0x8f, 0xb9, 0xab, 0xb6, 0xf5, 0x20, 0x2c, 0x51, 0xb0, 0xc9, 0xff, 0x3a, 0x63, 0xd5, 0xc5, + 0x10, 0x3a, 0x58, 0xa4, 0xc7, 0xcc, 0x1b, 0x0c, 0x16, 0xc9, 0x51, 0x0c, 0x91, 0x07, 0x39, 0x1b, + 0x1c, 0xe4, 0x26, 0x14, 0x26, 0xc4, 0x09, 0x52, 0xfa, 0xf3, 0x39, 0x5d, 0x12, 0xd0, 0x7b, 0xb0, + 0x10, 0x4d, 0x2f, 0x39, 0xc1, 0x53, 0xeb, 0x85, 0xb3, 0xd1, 0x03, 0xa8, 0x84, 0x72, 0x5c, 0x5e, + 0xf0, 0x95, 0x87, 0x4a, 0x8a, 0x5b, 0x95, 0x71, 0x95, 0xe6, 0xe3, 0xca, 0xf3, 0x39, 0x19, 0x59, + 0x57, 0x65, 0x64, 0x2d, 0x8a, 0x51, 0x22, 0xb6, 0x86, 0x82, 0xcc, 0xf7, 0xc3, 0x41, 0x06, 0x7f, + 0x1f, 0xaa, 0x21, 0x07, 0xd1, 0xbc, 0xd3, 0xfe, 0xe4, 0xe5, 0xf6, 0x01, 0x4f, 0x52, 0xcf, 0x58, + 0x5e, 0xd2, 0xeb, 0x1a, 0xcd, 0x75, 0x07, 0xed, 0xe3, 0xe3, 0x7a, 0x06, 0x55, 0xa1, 0x74, 0xd8, + 0xe9, 0x9e, 0x70, 0xae, 0x2c, 0x7e, 0xe6, 0x4b, 0x10, 0x49, 0x4e, 0xc9, 0x6d, 0x73, 0x4a, 0x6e, + 0xd3, 0x64, 0x6e, 0xcb, 0x04, 0xb9, 0x8d, 0xa5, 0xb9, 0x83, 0xf6, 0xf6, 0x71, 0xbb, 0x3e, 0xff, + 0xb4, 0x06, 0x15, 0xee, 0xdf, 0x93, 0xb1, 0x45, 0x53, 0xed, 0xdf, 0x6b, 0x00, 0xc1, 0x69, 0x42, + 0x2d, 0x28, 0xf4, 0xb8, 0x9e, 0x86, 0xc6, 0x82, 0xd1, 0x4a, 0xe2, 0x92, 0xe9, 0x92, 0x0b, 0x7d, + 0x0b, 0x0a, 0xee, 0xb8, 0xd7, 0x23, 0xae, 0x4c, 0x79, 0xb7, 0xa2, 0xf1, 0x50, 0x44, 0x2b, 0x5d, + 0xf2, 0xd1, 0x21, 0x67, 0x86, 0x39, 0x18, 0xb3, 0x04, 0x38, 0x7d, 0x88, 0xe0, 0xc3, 0x7f, 0xab, + 0x41, 0x59, 0xd9, 0xbc, 0xbf, 0x66, 0x10, 0xbe, 0x0b, 0x25, 0x66, 0x03, 0xe9, 0x8b, 0x30, 0x5c, + 0xd4, 0x03, 0x02, 0xfa, 0x2d, 0x28, 0xc9, 0x13, 0x20, 0x23, 0x71, 0x23, 0x59, 0x6c, 0x67, 0xa4, + 0x07, 0xac, 0x78, 0x1f, 0x16, 0x99, 0x57, 0x7a, 0xb4, 0xb8, 0x96, 0x7e, 0x54, 0xcb, 0x4f, 0x2d, + 0x52, 0x7e, 0x36, 0xa1, 0x38, 0xba, 0xb8, 0x76, 0xcd, 0x9e, 0x31, 0x10, 0x56, 0xf8, 0x6d, 0xfc, + 0x31, 0x20, 0x55, 0xd8, 0x2c, 0xd3, 0xc5, 0x55, 0x28, 0x3f, 0x37, 0xdc, 0x0b, 0x61, 0x12, 0x7e, + 0x0c, 0x55, 0xda, 0xdc, 0x7f, 0xf5, 0x06, 0x36, 0xb2, 0x97, 0x03, 0xc9, 0x3d, 0x93, 0xcf, 0x11, + 0xcc, 0x5f, 0x18, 0xee, 0x05, 0x9b, 0x68, 0x55, 0x67, 0xcf, 0xe8, 0x3d, 0xa8, 0xf7, 0xf8, 0x24, + 0x4f, 0x22, 0xaf, 0x0c, 0x0b, 0x82, 0xee, 0x57, 0x82, 0x9f, 0x41, 0x85, 0xcf, 0xe1, 0x37, 0x6d, + 0x04, 0x5e, 0x84, 0x85, 0x63, 0xcb, 0x18, 0xb9, 0x17, 0xb6, 0xcc, 0x6e, 0x74, 0xd2, 0xf5, 0x80, + 0x36, 0x93, 0xc6, 0x77, 0x61, 0xc1, 0x21, 0x43, 0xc3, 0xb4, 0x4c, 0xeb, 0xfc, 0xe4, 0xf4, 0xda, + 0x23, 0xae, 0x78, 0x61, 0xaa, 0xf9, 0xe4, 0xa7, 0x94, 0x4a, 0x4d, 0x3b, 0x1d, 0xd8, 0xa7, 0x22, + 0xcc, 0xb1, 0x67, 0xfc, 0x17, 0x19, 0xa8, 0x7c, 0x6a, 0x78, 0x3d, 0xb9, 0x74, 0x68, 0x0f, 0x6a, + 0x7e, 0x70, 0x63, 0x14, 0x61, 0x4b, 0x24, 0xc5, 0xb2, 0x31, 0xb2, 0x94, 0x96, 0xd9, 0xb1, 0xda, + 0x53, 0x09, 0x4c, 0x94, 0x61, 0xf5, 0xc8, 0xc0, 0x17, 0x95, 0x49, 0x17, 0xc5, 0x18, 0x55, 0x51, + 0x2a, 0x01, 0x75, 0xa0, 0x3e, 0x72, 0xec, 0x73, 0x87, 0xb8, 0xae, 0x2f, 0x8c, 0xa7, 0x31, 0x9c, + 0x20, 0xec, 0x48, 0xb0, 0x06, 0xe2, 0x16, 0x46, 0x61, 0xd2, 0xd3, 0x85, 0xa0, 0x9e, 0xe1, 0xc1, + 0xe9, 0x3f, 0x33, 0x80, 0xe2, 0x93, 0xfa, 0x55, 0x4b, 0xbc, 0x87, 0x50, 0x73, 0x3d, 0xc3, 0x89, + 0x6d, 0xb6, 0x2a, 0xa3, 0xfa, 0x11, 0xff, 0x5d, 0xf0, 0x0d, 0x3a, 0xb1, 0x6c, 0xcf, 0x3c, 0xbb, + 0x16, 0x55, 0x72, 0x4d, 0x92, 0x0f, 0x19, 0x15, 0xb5, 0xa1, 0x70, 0x66, 0x0e, 0x3c, 0xe2, 0xb8, + 0x8d, 0xdc, 0x7a, 0x76, 0xa3, 0xb6, 0xf5, 0xf8, 0xa6, 0x65, 0xd8, 0xfc, 0x88, 0xf1, 0x77, 0xaf, + 0x47, 0x44, 0x97, 0x63, 0xd5, 0xca, 0x33, 0x1f, 0xaa, 0xc6, 0x6f, 0x43, 0xf1, 0x35, 0x15, 0x41, + 0xdf, 0xb2, 0x0b, 0xbc, 0x58, 0x64, 0x6d, 0xfe, 0x92, 0x7d, 0xe6, 0x18, 0xe7, 0x43, 0x62, 0x79, + 0xf2, 0x3d, 0x50, 0xb6, 0xf1, 0x43, 0x80, 0x40, 0x0d, 0x0d, 0xf9, 0x87, 0x9d, 0xa3, 0x97, 0xdd, + 0xfa, 0x1c, 0xaa, 0x40, 0xf1, 0xb0, 0xb3, 0xdb, 0x3e, 0x68, 0xd3, 0xfc, 0x80, 0x5b, 0xd2, 0xa5, + 0xa1, 0xb5, 0x54, 0x75, 0x6a, 0x21, 0x9d, 0x78, 0x15, 0x96, 0x93, 0x16, 0x90, 0xd6, 0xa2, 0x55, + 0xb1, 0x4b, 0x67, 0x3a, 0x2a, 0xaa, 0xea, 0x4c, 0x78, 0xba, 0x0d, 0x28, 0xf0, 0xdd, 0xdb, 0x17, + 0xc5, 0xb9, 0x6c, 0x52, 0x47, 0xf0, 0xcd, 0x48, 0xfa, 0x62, 0x95, 0xfc, 0x76, 0x62, 0x78, 0xc9, + 0x25, 0x86, 0x17, 0xf4, 0x00, 0xaa, 0xfe, 0x69, 0x30, 0x5c, 0x51, 0x0b, 0x94, 0xf4, 0x8a, 0xdc, + 0xe8, 0x94, 0x16, 0x72, 0x7a, 0x21, 0xec, 0x74, 0xf4, 0x10, 0xf2, 0x64, 0x42, 0x2c, 0xcf, 0x6d, + 0x94, 0x59, 0xc6, 0xa8, 0xca, 0xda, 0xbd, 0x4d, 0xa9, 0xba, 0xe8, 0xc4, 0xdf, 0x85, 0x45, 0xf6, + 0x8e, 0xf4, 0xcc, 0x31, 0x2c, 0xf5, 0x65, 0xae, 0xdb, 0x3d, 0x10, 0xee, 0xa6, 0x8f, 0xa8, 0x06, + 0x99, 0xbd, 0x5d, 0xe1, 0x84, 0xcc, 0xde, 0x2e, 0xfe, 0xb1, 0x06, 0x48, 0x1d, 0x37, 0x93, 0x9f, + 0x23, 0xc2, 0xa5, 0xfa, 0x6c, 0xa0, 0x7e, 0x19, 0x72, 0xc4, 0x71, 0x6c, 0x87, 0x79, 0xb4, 0xa4, + 0xf3, 0x06, 0x7e, 0x5b, 0xd8, 0xa0, 0x93, 0x89, 0x7d, 0xe9, 0x9f, 0x41, 0x2e, 0x4d, 0xf3, 0x4d, + 0xdd, 0x87, 0xa5, 0x10, 0xd7, 0x4c, 0x99, 0xeb, 0x23, 0x58, 0x60, 0xc2, 0x76, 0x2e, 0x48, 0xef, + 0x72, 0x64, 0x9b, 0x56, 0x4c, 0x1f, 0x5d, 0xb9, 0x20, 0xc0, 0xd2, 0x79, 0xf0, 0x89, 0x55, 0x7c, + 0x62, 0xb7, 0x7b, 0x80, 0x3f, 0x87, 0xd5, 0x88, 0x1c, 0x69, 0xfe, 0xef, 0x43, 0xb9, 0xe7, 0x13, + 0x5d, 0x51, 0xeb, 0xdc, 0x0b, 0x1b, 0x17, 0x1d, 0xaa, 0x8e, 0xc0, 0x1d, 0xb8, 0x15, 0x13, 0x3d, + 0xd3, 0x9c, 0xdf, 0x85, 0x15, 0x26, 0x70, 0x9f, 0x90, 0xd1, 0xf6, 0xc0, 0x9c, 0xa4, 0x7a, 0x7a, + 0x24, 0x26, 0xa5, 0x30, 0x7e, 0xbd, 0xfb, 0x02, 0xff, 0xae, 0xd0, 0xd8, 0x35, 0x87, 0xa4, 0x6b, + 0x1f, 0xa4, 0xdb, 0x46, 0xb3, 0xd9, 0x25, 0xb9, 0x76, 0x45, 0x59, 0xc3, 0x9e, 0xf1, 0x3f, 0x68, + 0xc2, 0x55, 0xea, 0xf0, 0xaf, 0x79, 0x27, 0xaf, 0x01, 0x9c, 0xd3, 0x23, 0x43, 0xfa, 0xb4, 0x83, + 0x23, 0x2a, 0x0a, 0xc5, 0xb7, 0x93, 0xc6, 0xef, 0x8a, 0xb0, 0x73, 0x59, 0xec, 0x73, 0xf6, 0xc7, + 0x8f, 0x72, 0xf7, 0xa0, 0xcc, 0x08, 0xc7, 0x9e, 0xe1, 0x8d, 0xdd, 0xd8, 0x62, 0xfc, 0xa9, 0xd8, + 0xf6, 0x72, 0xd0, 0x4c, 0xf3, 0xfa, 0x16, 0xe4, 0xd9, 0xcb, 0x84, 0x2c, 0xa5, 0x6f, 0x27, 0xec, + 0x47, 0x6e, 0x87, 0x2e, 0x18, 0xf1, 0x3f, 0x69, 0x90, 0x7f, 0xc1, 0x20, 0x58, 0xc5, 0xb4, 0x79, + 0xb9, 0x16, 0x96, 0x31, 0xe4, 0xc0, 0x50, 0x49, 0x67, 0xcf, 0xac, 0xf4, 0x24, 0xc4, 0x79, 0xa9, + 0x1f, 0xf0, 0x12, 0xb7, 0xa4, 0xfb, 0x6d, 0xea, 0xb3, 0xde, 0xc0, 0x24, 0x96, 0xc7, 0x7a, 0xe7, + 0x59, 0xaf, 0x42, 0xa1, 0xd5, 0xb3, 0xe9, 0x1e, 0x10, 0xc3, 0xb1, 0x04, 0x68, 0x5a, 0xd4, 0x03, + 0x02, 0x5a, 0x87, 0xb2, 0x31, 0xf6, 0xec, 0x23, 0xc7, 0x1e, 0xda, 0x9e, 0x0f, 0x0f, 0x29, 0x24, + 0x6c, 0x41, 0x9d, 0x5b, 0xba, 0xdd, 0xef, 0x2b, 0x25, 0xa8, 0x6f, 0x8f, 0x16, 0xb1, 0x27, 0xa4, + 0x2f, 0x73, 0x83, 0xbe, 0x6c, 0x5c, 0xdf, 0x3f, 0x6a, 0xb0, 0xa8, 0x28, 0x9c, 0x69, 0x65, 0xde, + 0x87, 0x3c, 0x07, 0xba, 0x45, 0xb5, 0xb4, 0x1c, 0x1e, 0xc5, 0xd5, 0xe8, 0x82, 0x07, 0x6d, 0x42, + 0x81, 0x3f, 0xc9, 0xf7, 0x88, 0x64, 0x76, 0xc9, 0x84, 0x1f, 0xc2, 0x92, 0x20, 0x91, 0xa1, 0x9d, + 0x74, 0xb8, 0xd8, 0x82, 0xe2, 0x3f, 0x86, 0xe5, 0x30, 0xdb, 0x4c, 0x53, 0x52, 0x8c, 0xcc, 0xbc, + 0x89, 0x91, 0xdb, 0xd2, 0xc8, 0x97, 0xa3, 0xbe, 0x52, 0x8b, 0x45, 0x77, 0x9d, 0xba, 0xa2, 0x99, + 0xf0, 0x8a, 0x06, 0x13, 0x90, 0x22, 0xbe, 0xd1, 0x09, 0x2c, 0xc9, 0xed, 0x70, 0x60, 0xba, 0x7e, + 0xc9, 0xff, 0x25, 0x20, 0x95, 0xf8, 0x8d, 0x1a, 0xf4, 0x8e, 0x74, 0x87, 0xd8, 0xb1, 0x69, 0xeb, + 0xfe, 0x27, 0xb0, 0x12, 0xe1, 0xfb, 0xa6, 0xfd, 0xb6, 0x4b, 0x64, 0xc1, 0x23, 0xfd, 0xf6, 0x31, + 0x20, 0x95, 0x38, 0x53, 0xe6, 0x6b, 0xc1, 0xe2, 0x0b, 0x7b, 0x42, 0x43, 0x28, 0xa5, 0x06, 0x91, + 0x81, 0xe3, 0x14, 0xbe, 0x2b, 0xfc, 0x36, 0x55, 0xae, 0x0e, 0x98, 0x49, 0xf9, 0xbf, 0x6b, 0x50, + 0xd9, 0x1e, 0x18, 0xce, 0x50, 0x2a, 0xfe, 0x1e, 0xe4, 0xf9, 0xdb, 0xb7, 0x00, 0xbc, 0xde, 0x09, + 0x8b, 0x51, 0x79, 0x79, 0x63, 0x9b, 0xbf, 0xab, 0x8b, 0x51, 0xd4, 0x70, 0x71, 0x27, 0xb6, 0x1b, + 0xb9, 0x23, 0xdb, 0x45, 0x1f, 0x40, 0xce, 0xa0, 0x43, 0x58, 0xb8, 0xaa, 0x45, 0x71, 0x0f, 0x26, + 0x8d, 0xbd, 0x23, 0x70, 0x2e, 0xfc, 0x1d, 0x28, 0x2b, 0x1a, 0x50, 0x01, 0xb2, 0xcf, 0xda, 0xa2, + 0xa0, 0xdf, 0xde, 0xe9, 0xee, 0xbd, 0xe2, 0x80, 0x4f, 0x0d, 0x60, 0xb7, 0xed, 0xb7, 0x33, 0xf8, + 0x33, 0x31, 0x4a, 0xa4, 0x05, 0xd5, 0x1e, 0x2d, 0xcd, 0x9e, 0xcc, 0x1b, 0xd9, 0x73, 0x05, 0x55, + 0x31, 0xfd, 0x59, 0xd3, 0x1c, 0x93, 0x97, 0x92, 0xe6, 0x14, 0xe3, 0x75, 0xc1, 0x88, 0x17, 0xa0, + 0x2a, 0x12, 0x9f, 0xd8, 0x7f, 0xff, 0x9f, 0x81, 0x9a, 0xa4, 0xcc, 0x0a, 0xcc, 0x4b, 0x4c, 0x91, + 0x27, 0x4a, 0x1f, 0x51, 0x5c, 0x85, 0x7c, 0xff, 0xf4, 0xd8, 0xfc, 0x52, 0x5e, 0xa2, 0x88, 0x16, + 0xa5, 0x0f, 0xb8, 0x1e, 0x7e, 0x93, 0x29, 0x5a, 0x34, 0x5f, 0x39, 0xc6, 0x99, 0xb7, 0x67, 0xf5, + 0xc9, 0x15, 0xcb, 0x8f, 0xf3, 0x7a, 0x40, 0x60, 0x60, 0x8b, 0xb8, 0xf1, 0x64, 0xc9, 0x51, 0xb9, + 0x01, 0x45, 0x8f, 0xa0, 0x4e, 0x9f, 0xb7, 0x47, 0xa3, 0x81, 0x49, 0xfa, 0x5c, 0x40, 0x81, 0xf1, + 0xc4, 0xe8, 0x54, 0x3b, 0x2b, 0xcb, 0xdd, 0x46, 0x91, 0x45, 0x57, 0xd1, 0xa2, 0xf9, 0x90, 0xdb, + 0xb7, 0x67, 0xbd, 0x74, 0x09, 0xbb, 0x06, 0xcc, 0xea, 0x2a, 0x29, 0x9c, 0x4f, 0xe1, 0x86, 0x7c, + 0x5a, 0x8e, 0xe7, 0xd3, 0x25, 0x58, 0xdc, 0x1e, 0x7b, 0x17, 0x6d, 0xcb, 0x38, 0x1d, 0xc8, 0x58, + 0x45, 0x8b, 0x26, 0x4a, 0xdc, 0x35, 0x5d, 0x95, 0xda, 0x86, 0x25, 0x4a, 0x25, 0x96, 0x67, 0xf6, + 0x94, 0x5c, 0x21, 0x2b, 0x12, 0x2d, 0x52, 0x91, 0x18, 0xae, 0xfb, 0xda, 0x76, 0xfa, 0x62, 0x01, + 0xfc, 0x36, 0x9e, 0x70, 0xe1, 0x2f, 0xdd, 0x50, 0xcd, 0xf0, 0x2b, 0x4a, 0x41, 0x1f, 0x42, 0xc1, + 0x1e, 0xb1, 0x8b, 0x6f, 0x81, 0x4e, 0xac, 0x6e, 0xf2, 0xab, 0xf2, 0x4d, 0x21, 0xb8, 0xc3, 0x7b, + 0x75, 0xc9, 0x86, 0x37, 0x02, 0xbd, 0xcf, 0x88, 0x37, 0x45, 0x2f, 0x7e, 0x0c, 0x2b, 0x92, 0x53, + 0x80, 0xf1, 0x53, 0x98, 0x3b, 0x70, 0x4f, 0x32, 0xef, 0x5c, 0x18, 0xd6, 0x39, 0x39, 0x12, 0x26, + 0xfe, 0xba, 0xfe, 0x79, 0x0a, 0x0d, 0xdf, 0x4e, 0xf6, 0x82, 0x68, 0x0f, 0x54, 0x03, 0xc6, 0xae, + 0x38, 0x0b, 0x25, 0x9d, 0x3d, 0x53, 0x9a, 0x63, 0x0f, 0xfc, 0x8a, 0x90, 0x3e, 0xe3, 0x1d, 0xb8, + 0x2d, 0x65, 0x88, 0x57, 0xb7, 0xb0, 0x90, 0x98, 0x41, 0x49, 0x42, 0x84, 0xc3, 0xe8, 0xd0, 0xe9, + 0x0b, 0xa5, 0x72, 0x86, 0x5d, 0xcb, 0x64, 0x6a, 0x8a, 0xcc, 0x15, 0xbe, 0x87, 0xa8, 0x61, 0x6a, + 0xc2, 0x16, 0x64, 0x2a, 0x40, 0x25, 0x8b, 0x85, 0xa0, 0xe4, 0xd8, 0x42, 0xc4, 0x44, 0xff, 0x00, + 0xd6, 0x7c, 0x23, 0xa8, 0xdf, 0x8e, 0x88, 0x33, 0x34, 0x5d, 0x57, 0x81, 0x6f, 0x93, 0x26, 0xfe, + 0x0e, 0xcc, 0x8f, 0x88, 0x88, 0x95, 0xe5, 0x2d, 0x24, 0x37, 0x91, 0x32, 0x98, 0xf5, 0xe3, 0x3e, + 0xdc, 0x97, 0xd2, 0xb9, 0x47, 0x13, 0xc5, 0x47, 0x8d, 0x92, 0xa0, 0x56, 0x26, 0x05, 0xd4, 0xca, + 0x46, 0xae, 0x14, 0x3e, 0xe6, 0x8e, 0x94, 0xa7, 0x71, 0xa6, 0x1c, 0xb8, 0xcf, 0x7d, 0xea, 0x1f, + 0xe2, 0x99, 0x84, 0x9d, 0xc2, 0x72, 0xf8, 0xec, 0xcf, 0x14, 0x9e, 0x97, 0x21, 0xe7, 0xd9, 0x97, + 0x44, 0x06, 0x67, 0xde, 0x90, 0x06, 0xfb, 0x81, 0x61, 0x26, 0x83, 0x8d, 0x40, 0x18, 0xdb, 0x92, + 0xb3, 0xda, 0x4b, 0x57, 0x53, 0xd6, 0xbe, 0xbc, 0x81, 0x0f, 0x61, 0x35, 0x1a, 0x26, 0x66, 0x32, + 0xf9, 0x15, 0xdf, 0xc0, 0x49, 0x91, 0x64, 0x26, 0xb9, 0x9f, 0x04, 0xc1, 0x40, 0x09, 0x28, 0x33, + 0x89, 0xd4, 0xa1, 0x99, 0x14, 0x5f, 0x7e, 0x13, 0xfb, 0xd5, 0x0f, 0x37, 0x33, 0x09, 0x73, 0x03, + 0x61, 0xb3, 0x2f, 0x7f, 0x10, 0x23, 0xb2, 0x53, 0x63, 0x84, 0x38, 0x24, 0x41, 0x14, 0xfb, 0x1a, + 0x36, 0x9d, 0xd0, 0x11, 0x04, 0xd0, 0x59, 0x75, 0xd0, 0x1c, 0xe2, 0xeb, 0x60, 0x0d, 0xb9, 0xb1, + 0xd5, 0xb0, 0x3b, 0xd3, 0x62, 0x7c, 0x1a, 0xc4, 0xce, 0x58, 0x64, 0x9e, 0x49, 0xf0, 0x67, 0xb0, + 0x9e, 0x1e, 0x94, 0x67, 0x91, 0xfc, 0xa8, 0x05, 0x25, 0xbf, 0x50, 0x56, 0xbe, 0x55, 0x2a, 0x43, + 0xe1, 0xb0, 0x73, 0x7c, 0xb4, 0xbd, 0xd3, 0xe6, 0x1f, 0x2b, 0xed, 0x74, 0x74, 0xfd, 0xe5, 0x51, + 0xb7, 0x9e, 0xd9, 0xfa, 0x45, 0x16, 0x32, 0xfb, 0xaf, 0xd0, 0xe7, 0x90, 0xe3, 0x37, 0xf7, 0x53, + 0x3e, 0xd7, 0x68, 0x4e, 0xfb, 0x38, 0x01, 0xdf, 0xfa, 0xf1, 0x7f, 0xfd, 0xe2, 0x67, 0x99, 0x45, + 0x5c, 0x69, 0x4d, 0xbe, 0xdd, 0xba, 0x9c, 0xb4, 0x58, 0x6e, 0x78, 0xa2, 0x3d, 0x42, 0x9f, 0x40, + 0xf6, 0x68, 0xec, 0xa1, 0xd4, 0xcf, 0x38, 0x9a, 0xe9, 0xdf, 0x2b, 0xe0, 0x15, 0x26, 0x74, 0x01, + 0x83, 0x10, 0x3a, 0x1a, 0x7b, 0x54, 0xe4, 0x0f, 0xa1, 0xac, 0x7e, 0x6d, 0x70, 0xe3, 0xb7, 0x1d, + 0xcd, 0x9b, 0xbf, 0x64, 0xc0, 0xf7, 0x98, 0xaa, 0x5b, 0x18, 0x09, 0x55, 0xfc, 0x7b, 0x08, 0x75, + 0x16, 0xdd, 0x2b, 0x0b, 0xa5, 0x7e, 0xf9, 0xd1, 0x4c, 0xff, 0xb8, 0x21, 0x36, 0x0b, 0xef, 0xca, + 0xa2, 0x22, 0xff, 0x50, 0x7c, 0xd7, 0xd0, 0xf3, 0xd0, 0xfd, 0x84, 0x7b, 0x6d, 0xf5, 0x06, 0xb7, + 0xb9, 0x9e, 0xce, 0x20, 0x94, 0xdc, 0x65, 0x4a, 0x56, 0xf1, 0xa2, 0x50, 0xd2, 0xf3, 0x59, 0x9e, + 0x68, 0x8f, 0xb6, 0x7a, 0x90, 0x63, 0xb7, 0x23, 0xe8, 0x0b, 0xf9, 0xd0, 0x4c, 0xb8, 0x26, 0x4a, + 0x59, 0xe8, 0xd0, 0xbd, 0x0a, 0x5e, 0x66, 0x8a, 0x6a, 0xb8, 0x44, 0x15, 0xb1, 0xbb, 0x91, 0x27, + 0xda, 0xa3, 0x0d, 0xed, 0x43, 0x6d, 0xeb, 0x9f, 0x73, 0x90, 0x63, 0xb0, 0x20, 0xba, 0x04, 0x08, + 0x6e, 0x0a, 0xa2, 0xb3, 0x8b, 0xdd, 0x3d, 0x44, 0x67, 0x17, 0xbf, 0x64, 0xc0, 0x4d, 0xa6, 0x74, + 0x19, 0x2f, 0x50, 0xa5, 0x0c, 0x6d, 0x6c, 0x31, 0x00, 0x95, 0xfa, 0xf1, 0x2f, 0x35, 0x81, 0x8a, + 0xf2, 0xb3, 0x84, 0x92, 0xa4, 0x85, 0xae, 0x0b, 0xa2, 0xdb, 0x21, 0xe1, 0xaa, 0x00, 0x7f, 0x97, + 0x29, 0x6c, 0xe1, 0x7a, 0xa0, 0xd0, 0x61, 0x1c, 0x4f, 0xb4, 0x47, 0x5f, 0x34, 0xf0, 0x92, 0xf0, + 0x72, 0xa4, 0x07, 0xfd, 0x08, 0x6a, 0x61, 0x38, 0x1c, 0x3d, 0x48, 0xd0, 0x15, 0x45, 0xd5, 0x9b, + 0x6f, 0x4f, 0x67, 0x12, 0x36, 0xad, 0x31, 0x9b, 0x84, 0x72, 0xae, 0xf9, 0x92, 0x90, 0x91, 0x41, + 0x99, 0xc4, 0x1a, 0xa0, 0xbf, 0xd3, 0xc4, 0x6d, 0x45, 0x80, 0x6f, 0xa3, 0x24, 0xe9, 0x31, 0xf4, + 0xbc, 0xf9, 0xf0, 0x06, 0x2e, 0x61, 0xc4, 0xef, 0x31, 0x23, 0x7e, 0x1b, 0x2f, 0x07, 0x46, 0x78, + 0xe6, 0x90, 0x78, 0xb6, 0xb0, 0xe2, 0x8b, 0xbb, 0xf8, 0x56, 0xc8, 0x39, 0xa1, 0xde, 0x60, 0xb1, + 0x38, 0x46, 0x9d, 0xb8, 0x58, 0x21, 0xcc, 0x3b, 0x71, 0xb1, 0xc2, 0x00, 0x77, 0xd2, 0x62, 0x71, + 0x44, 0x3a, 0x69, 0xb1, 0xfc, 0x9e, 0xad, 0xff, 0x9b, 0x87, 0xc2, 0x0e, 0xff, 0x9e, 0x18, 0xd9, + 0x50, 0xf2, 0xe1, 0x59, 0xb4, 0x96, 0x84, 0x41, 0x05, 0xef, 0x12, 0xcd, 0xfb, 0xa9, 0xfd, 0xc2, + 0xa0, 0xb7, 0x98, 0x41, 0x77, 0xf0, 0x2a, 0xd5, 0x2c, 0x3e, 0x59, 0x6e, 0x71, 0xa0, 0xa3, 0x65, + 0xf4, 0xfb, 0xd4, 0x11, 0x7f, 0x04, 0x15, 0x15, 0x3f, 0x45, 0x6f, 0x25, 0xe2, 0x5e, 0x2a, 0x04, + 0xdb, 0xc4, 0xd3, 0x58, 0x84, 0xe6, 0xb7, 0x99, 0xe6, 0x35, 0x7c, 0x3b, 0x41, 0xb3, 0xc3, 0x58, + 0x43, 0xca, 0x39, 0xf6, 0x99, 0xac, 0x3c, 0x04, 0xad, 0x26, 0x2b, 0x0f, 0x43, 0xa7, 0x53, 0x95, + 0x8f, 0x19, 0x2b, 0x55, 0xee, 0x02, 0x04, 0x28, 0x27, 0x4a, 0xf4, 0xa5, 0xf2, 0x32, 0x15, 0x0d, + 0x0e, 0x71, 0x80, 0x14, 0x63, 0xa6, 0x56, 0xec, 0xbb, 0x88, 0xda, 0x81, 0xe9, 0x7a, 0xfc, 0x60, + 0x56, 0x43, 0xb0, 0x25, 0x4a, 0x9c, 0x4f, 0x18, 0xfb, 0x6c, 0x3e, 0x98, 0xca, 0x23, 0xb4, 0x3f, + 0x64, 0xda, 0xef, 0xe3, 0x66, 0x82, 0xf6, 0x11, 0xe7, 0xa5, 0x9b, 0xed, 0xaf, 0xf2, 0x50, 0x7e, + 0x61, 0x98, 0x96, 0x47, 0x2c, 0xc3, 0xea, 0x11, 0x74, 0x0a, 0x39, 0x96, 0xa9, 0xa3, 0x81, 0x58, + 0x85, 0xf4, 0xa2, 0x81, 0x38, 0x84, 0x77, 0xe1, 0x75, 0xa6, 0xb8, 0x89, 0x57, 0xa8, 0xe2, 0x61, + 0x20, 0xba, 0xc5, 0x60, 0x2a, 0x3a, 0xe9, 0x33, 0xc8, 0x8b, 0x9b, 0xa2, 0x88, 0xa0, 0x10, 0x7c, + 0xd5, 0xbc, 0x9b, 0xdc, 0x99, 0xb4, 0x97, 0x55, 0x35, 0x2e, 0xe3, 0xa3, 0x7a, 0x26, 0x00, 0x01, + 0xfe, 0x1a, 0x5d, 0xd1, 0x18, 0x5c, 0xdb, 0x5c, 0x4f, 0x67, 0x48, 0xf2, 0xa9, 0xaa, 0xb3, 0xef, + 0xf3, 0x52, 0xbd, 0x7f, 0x00, 0xf3, 0xcf, 0x0d, 0xf7, 0x02, 0x45, 0x72, 0xaf, 0xf2, 0x9d, 0x51, + 0xb3, 0x99, 0xd4, 0x25, 0xb4, 0xdc, 0x67, 0x5a, 0x6e, 0xf3, 0x50, 0xa6, 0x6a, 0xb9, 0x30, 0x5c, + 0x9a, 0xd4, 0x50, 0x1f, 0xf2, 0xfc, 0xb3, 0xa3, 0xa8, 0xff, 0x42, 0x9f, 0x2e, 0x45, 0xfd, 0x17, + 0xfe, 0x52, 0xe9, 0x66, 0x2d, 0x23, 0x28, 0xca, 0xef, 0x7c, 0x50, 0xe4, 0xd2, 0x37, 0xf2, 0x4d, + 0x50, 0x73, 0x2d, 0xad, 0x5b, 0xe8, 0x7a, 0xc0, 0x74, 0xdd, 0xc3, 0x8d, 0xd8, 0x5a, 0x09, 0xce, + 0x27, 0xda, 0xa3, 0x0f, 0x35, 0xf4, 0x23, 0x80, 0x00, 0xb2, 0x8e, 0x9d, 0xc0, 0x28, 0xfa, 0x1d, + 0x3b, 0x81, 0x31, 0xb4, 0x1b, 0x6f, 0x32, 0xbd, 0x1b, 0xf8, 0x41, 0x54, 0xaf, 0xe7, 0x18, 0x96, + 0x7b, 0x46, 0x9c, 0x0f, 0x38, 0x2c, 0xe9, 0x5e, 0x98, 0x23, 0x7a, 0x18, 0xfe, 0x75, 0x01, 0xe6, + 0x69, 0x05, 0x4c, 0x0b, 0x85, 0x00, 0x38, 0x88, 0x5a, 0x12, 0x03, 0xf8, 0xa2, 0x96, 0xc4, 0x31, + 0x87, 0x70, 0xa1, 0xc0, 0x7e, 0x89, 0x42, 0x18, 0x03, 0x75, 0xb4, 0x0d, 0x65, 0x05, 0x59, 0x40, + 0x09, 0xc2, 0xc2, 0xc8, 0x61, 0x34, 0xf5, 0x24, 0xc0, 0x12, 0xf8, 0x0e, 0xd3, 0xb7, 0xc2, 0x53, + 0x0f, 0xd3, 0xd7, 0xe7, 0x1c, 0x54, 0xe1, 0x6b, 0xa8, 0xa8, 0xe8, 0x03, 0x4a, 0x90, 0x17, 0x41, + 0x25, 0xa3, 0x61, 0x36, 0x09, 0xbc, 0x08, 0x1f, 0x7c, 0xff, 0xd7, 0x36, 0x92, 0x8d, 0x2a, 0x1e, + 0x40, 0x41, 0xc0, 0x11, 0x49, 0xb3, 0x0c, 0x43, 0x98, 0x49, 0xb3, 0x8c, 0x60, 0x19, 0xe1, 0xe2, + 0x92, 0x69, 0xa4, 0x6f, 0x5c, 0x32, 0x95, 0x09, 0x6d, 0xcf, 0x88, 0x97, 0xa6, 0x2d, 0x40, 0xd7, + 0xd2, 0xb4, 0x29, 0x6f, 0xbb, 0x69, 0xda, 0xce, 0x89, 0x27, 0x8e, 0x8b, 0x7c, 0x8b, 0x44, 0x29, + 0xc2, 0xd4, 0xf4, 0x81, 0xa7, 0xb1, 0x24, 0xd5, 0xfe, 0x81, 0x42, 0x99, 0x3b, 0xae, 0x00, 0x02, + 0xb0, 0x24, 0x5a, 0xd0, 0x25, 0x22, 0xae, 0xd1, 0x82, 0x2e, 0x19, 0x6f, 0x09, 0x87, 0x86, 0x40, + 0x2f, 0x7f, 0xf5, 0xa0, 0x9a, 0x7f, 0xaa, 0x01, 0x8a, 0xe3, 0x2a, 0xe8, 0x71, 0xb2, 0xf4, 0x44, + 0x1c, 0xb7, 0xf9, 0xfe, 0x9b, 0x31, 0x27, 0x45, 0xfb, 0xc0, 0xa4, 0x1e, 0xe3, 0x1e, 0xbd, 0xa6, + 0x46, 0xfd, 0x99, 0x06, 0xd5, 0x10, 0x28, 0x83, 0xde, 0x49, 0x59, 0xd3, 0x08, 0x0c, 0xdc, 0x7c, + 0xf7, 0x46, 0xbe, 0xa4, 0x4a, 0x57, 0xd9, 0x01, 0xb2, 0xe4, 0xff, 0x89, 0x06, 0xb5, 0x30, 0x88, + 0x83, 0x52, 0x64, 0xc7, 0x60, 0xe4, 0xe6, 0xc6, 0xcd, 0x8c, 0xd3, 0x97, 0x27, 0xa8, 0xf6, 0x07, + 0x50, 0x10, 0xb0, 0x4f, 0xd2, 0xc6, 0x0f, 0x03, 0xd0, 0x49, 0x1b, 0x3f, 0x82, 0x19, 0x25, 0x6c, + 0x7c, 0xc7, 0x1e, 0x10, 0xe5, 0x98, 0x09, 0x5c, 0x28, 0x4d, 0xdb, 0xf4, 0x63, 0x16, 0x01, 0x95, + 0xd2, 0xb4, 0x05, 0xc7, 0x4c, 0x02, 0x42, 0x28, 0x45, 0xd8, 0x0d, 0xc7, 0x2c, 0x8a, 0x27, 0x25, + 0x1c, 0x33, 0xa6, 0x50, 0x39, 0x66, 0x01, 0x74, 0x93, 0x74, 0xcc, 0x62, 0x78, 0x7a, 0xd2, 0x31, + 0x8b, 0xa3, 0x3f, 0x09, 0xeb, 0xc8, 0xf4, 0x86, 0x8e, 0xd9, 0x52, 0x02, 0xca, 0x83, 0xde, 0x4f, + 0x71, 0x62, 0x22, 0x4c, 0xdf, 0xfc, 0xe0, 0x0d, 0xb9, 0x53, 0xf7, 0x38, 0x77, 0xbf, 0xdc, 0xe3, + 0x7f, 0xad, 0xc1, 0x72, 0x12, 0x42, 0x84, 0x52, 0xf4, 0xa4, 0xc0, 0xfb, 0xcd, 0xcd, 0x37, 0x65, + 0x9f, 0xee, 0x2d, 0x7f, 0xd7, 0x3f, 0xad, 0xff, 0xdb, 0x57, 0x6b, 0xda, 0x7f, 0x7c, 0xb5, 0xa6, + 0xfd, 0xf7, 0x57, 0x6b, 0xda, 0xdf, 0xfc, 0xcf, 0xda, 0xdc, 0x69, 0x9e, 0xfd, 0x86, 0xf3, 0xdb, + 0xbf, 0x0c, 0x00, 0x00, 0xff, 0xff, 0x30, 0x56, 0xbe, 0x28, 0x4a, 0x3a, 0x00, 0x00, } diff --git a/etcdserver/etcdserverpb/rpc.proto b/etcdserver/etcdserverpb/rpc.proto index 565f8fae50c..9c9a710cadb 100644 --- a/etcdserver/etcdserverpb/rpc.proto +++ b/etcdserver/etcdserverpb/rpc.proto @@ -856,6 +856,9 @@ message Member { repeated string clientURLs = 4; // isLearner indicates if the member is raft learner. bool isLearner = 5; + // autoPromote indicates whether the learner should be automatically promoted to a node + // when it has caught up with the leader + bool autoPromote = 6; } message MemberAddRequest { @@ -863,6 +866,9 @@ message MemberAddRequest { repeated string peerURLs = 1; // isLearner indicates if the added member is raft learner. bool isLearner = 2; + // autoPromote indicates whether the added learner should be automatically promoted to a node + // when it has caught up with the leader + bool autoPromote = 3; } message MemberAddResponse { @@ -992,6 +998,9 @@ message StatusResponse { int64 dbSizeInUse = 9; // isLearner indicates if the member is raft learner. bool isLearner = 10; + // autoPromote indicates if learner is configured to be automatically promoted + // to a node upon catching up with the leader. + bool autoPromote = 11; } message AuthEnableRequest { diff --git a/etcdserver/server.go b/etcdserver/server.go index 236696e8116..fd8d9952364 100644 --- a/etcdserver/server.go +++ b/etcdserver/server.go @@ -277,6 +277,8 @@ type EtcdServer struct { leadElectedTime time.Time *AccessController + + autoPromotionInProgress bool } // NewServer creates a new EtcdServer from the supplied configuration. The @@ -635,6 +637,32 @@ func NewServer(cfg ServerConfig) (srv *EtcdServer, err error) { return srv, nil } +// Get one auto-promoting learner that is caught up with leader. +func (s *EtcdServer) getAutoPromoteC() (ch <-chan uint64) { + if s.autoPromotionInProgress { + return nil + } + + rs := s.raftStatus() + + // leader's raftStatus.Progress is not nil + if rs.Progress == nil { + return nil + } + + for memberID, progress := range rs.Progress { + if progress.IsLearner && progress.AutoPromote { + if err := s.isLearnerReady(memberID); err == nil { + pmch := make(chan uint64, 1) + pmch <- memberID + return pmch + } + } + } + + return nil +} + func (s *EtcdServer) getLogger() *zap.Logger { s.lgMu.RLock() l := s.lg @@ -919,7 +947,9 @@ func (s *EtcdServer) run() { } // asynchronously accept apply packets, dispatch progress in-order - sched := schedule.NewFIFOScheduler() + apSched := schedule.NewFIFOScheduler() + // asynchronously promote learners to voters, dispatch progress in-order + pmSched := schedule.NewFIFOScheduler() var ( smu sync.RWMutex @@ -995,7 +1025,8 @@ func (s *EtcdServer) run() { s.wgMu.Unlock() s.cancel() - sched.Stop() + apSched.Stop() + pmSched.Stop() // wait for gouroutines before closing raft so wal stays open s.wg.Wait() @@ -1035,7 +1066,7 @@ func (s *EtcdServer) run() { select { case ap := <-s.r.apply(): f := func(context.Context) { s.applyAll(&ep, &ap) } - sched.Schedule(f) + apSched.Schedule(f) case leases := <-expiredLeaseC: s.goAttach(func() { // Increases throughput of expired leases deletion process through parallelization @@ -1083,6 +1114,10 @@ func (s *EtcdServer) run() { } case <-s.stop: return + case pmID := <-s.getAutoPromoteC(): + s.autoPromotionInProgress = true + f := func(c context.Context) { s.autoPromoteMember(c, pmID) } + pmSched.Schedule(f) } } } @@ -1584,6 +1619,9 @@ func (s *EtcdServer) AddMember(ctx context.Context, memb membership.Member) ([]* if memb.IsLearner { cc.Type = raftpb.ConfChangeAddLearnerNode + if memb.AutoPromote { + cc.Type = raftpb.ConfChangeAddAutoPromotingNode + } } return s.configure(ctx, cc) @@ -1684,6 +1722,12 @@ func (s *EtcdServer) PromoteMember(ctx context.Context, id uint64) ([]*membershi return nil, ErrCanceled } +func (s *EtcdServer) autoPromoteMember(ctx context.Context, id uint64) ([]*membership.Member, error) { + members, err := s.PromoteMember(ctx, id) + s.autoPromotionInProgress = false + return members, err +} + // promoteMember checks whether the to-be-promoted learner node is ready before sending the promote // request to raft. // The function returns ErrNotLeader if the local node is not raft leader (therefore does not have @@ -2237,7 +2281,7 @@ func (s *EtcdServer) applyConfChange(cc raftpb.ConfChange, confState *raftpb.Con lg := s.getLogger() *confState = *s.r.ApplyConfChange(cc) switch cc.Type { - case raftpb.ConfChangeAddNode, raftpb.ConfChangeAddLearnerNode: + case raftpb.ConfChangeAddAutoPromotingNode, raftpb.ConfChangeAddNode, raftpb.ConfChangeAddLearnerNode: confChangeContext := new(membership.ConfigChangeContext) if err := json.Unmarshal(cc.Context, confChangeContext); err != nil { if lg != nil { @@ -2269,7 +2313,7 @@ func (s *EtcdServer) applyConfChange(cc raftpb.ConfChange, confState *raftpb.Con // update the isLearner metric when this server id is equal to the id in raft member confChange if confChangeContext.Member.ID == s.id { - if cc.Type == raftpb.ConfChangeAddLearnerNode { + if cc.Type == raftpb.ConfChangeAddLearnerNode || cc.Type == raftpb.ConfChangeAddAutoPromotingNode { isLearner.Set(1) } else { isLearner.Set(0) diff --git a/etcdserver/server_test.go b/etcdserver/server_test.go index e7cde53b4b8..a8f39ff23a4 100644 --- a/etcdserver/server_test.go +++ b/etcdserver/server_test.go @@ -656,7 +656,7 @@ func TestApplyConfigChangeUpdatesConsistIndex(t *testing.T) { if err != nil { t.Fatal(err) } - m := membership.NewMember("", urls, "", &now) + m := membership.NewMemberAsNode("", urls, "", &now) m.ID = types.ID(2) b, err := json.Marshal(m) if err != nil { @@ -1586,23 +1586,23 @@ func TestGetOtherPeerURLs(t *testing.T) { }{ { []*membership.Member{ - membership.NewMember("1", types.MustNewURLs([]string{"http://10.0.0.1:1"}), "a", nil), + membership.NewMemberAsNode("1", types.MustNewURLs([]string{"http://10.0.0.1:1"}), "a", nil), }, []string{}, }, { []*membership.Member{ - membership.NewMember("1", types.MustNewURLs([]string{"http://10.0.0.1:1"}), "a", nil), - membership.NewMember("2", types.MustNewURLs([]string{"http://10.0.0.2:2"}), "a", nil), - membership.NewMember("3", types.MustNewURLs([]string{"http://10.0.0.3:3"}), "a", nil), + membership.NewMemberAsNode("1", types.MustNewURLs([]string{"http://10.0.0.1:1"}), "a", nil), + membership.NewMemberAsNode("2", types.MustNewURLs([]string{"http://10.0.0.2:2"}), "a", nil), + membership.NewMemberAsNode("3", types.MustNewURLs([]string{"http://10.0.0.3:3"}), "a", nil), }, []string{"http://10.0.0.2:2", "http://10.0.0.3:3"}, }, { []*membership.Member{ - membership.NewMember("1", types.MustNewURLs([]string{"http://10.0.0.1:1"}), "a", nil), - membership.NewMember("3", types.MustNewURLs([]string{"http://10.0.0.3:3"}), "a", nil), - membership.NewMember("2", types.MustNewURLs([]string{"http://10.0.0.2:2"}), "a", nil), + membership.NewMemberAsNode("1", types.MustNewURLs([]string{"http://10.0.0.1:1"}), "a", nil), + membership.NewMemberAsNode("3", types.MustNewURLs([]string{"http://10.0.0.3:3"}), "a", nil), + membership.NewMemberAsNode("2", types.MustNewURLs([]string{"http://10.0.0.2:2"}), "a", nil), }, []string{"http://10.0.0.2:2", "http://10.0.0.3:3"}, }, diff --git a/proxy/grpcproxy/cluster.go b/proxy/grpcproxy/cluster.go index 7e5059cfb31..09f4b859569 100644 --- a/proxy/grpcproxy/cluster.go +++ b/proxy/grpcproxy/cluster.go @@ -110,13 +110,25 @@ func (cp *clusterProxy) monitor(wa gnaming.Watcher) { func (cp *clusterProxy) MemberAdd(ctx context.Context, r *pb.MemberAddRequest) (*pb.MemberAddResponse, error) { if r.IsLearner { + if r.AutoPromote { + return cp.memberAddAsAutoPromotingNode(ctx, r.PeerURLs) + } return cp.memberAddAsLearner(ctx, r.PeerURLs) } - return cp.memberAdd(ctx, r.PeerURLs) + return cp.memberAddAsNode(ctx, r.PeerURLs) +} + +func (cp *clusterProxy) memberAddAsNode(ctx context.Context, peerURLs []string) (*pb.MemberAddResponse, error) { + mresp, err := cp.clus.MemberAddAsNode(ctx, peerURLs) + if err != nil { + return nil, err + } + resp := (pb.MemberAddResponse)(*mresp) + return &resp, err } -func (cp *clusterProxy) memberAdd(ctx context.Context, peerURLs []string) (*pb.MemberAddResponse, error) { - mresp, err := cp.clus.MemberAdd(ctx, peerURLs) +func (cp *clusterProxy) memberAddAsAutoPromotingNode(ctx context.Context, peerURLs []string) (*pb.MemberAddResponse, error) { + mresp, err := cp.clus.MemberAddAsAutoPromotingNode(ctx, peerURLs) if err != nil { return nil, err } diff --git a/raft/raft.go b/raft/raft.go index a42bb4e63db..69f7b66eb75 100644 --- a/raft/raft.go +++ b/raft/raft.go @@ -269,6 +269,11 @@ type raft struct { // isLearner is true if the local raft node is a learner. isLearner bool + // autoPromote is true if the local raft node is a learner + // that should be automatically promoted to a voter once + // caught up with the leader. + autoPromote bool + msgs []pb.Message // the leader id @@ -356,11 +361,11 @@ func newRaft(c *Config) *raft { } for _, p := range peers { // Add node to active config. - r.prs.InitProgress(p, 0 /* match */, 1 /* next */, false /* isLearner */) + r.prs.InitProgress(p, 0 /* match */, 1 /* next */, false /* isLearner */, false /* autoPromote */) } for _, p := range learners { // Add learner to active config. - r.prs.InitProgress(p, 0 /* match */, 1 /* next */, true /* isLearner */) + r.prs.InitProgress(p, 0 /* match */, 1 /* next */, true /* isLearner */, false /* autoPromote */) if r.id == p { r.isLearner = true @@ -1394,6 +1399,9 @@ func (r *raft) restore(s pb.Snapshot) bool { for _, id := range s.Metadata.ConfState.Learners { r.applyConfChange(pb.ConfChange{NodeID: id, Type: pb.ConfChangeAddLearnerNode}) } + for _, id := range s.Metadata.ConfState.Learners { + r.applyConfChange(pb.ConfChange{NodeID: id, Type: pb.ConfChangeAddAutoPromotingNode}) + } pr := r.prs.Progress[r.id] pr.MaybeUpdate(pr.Next - 1) // TODO(tbg): this is untested and likely unneeded @@ -1403,6 +1411,15 @@ func (r *raft) restore(s pb.Snapshot) bool { return true } +func (r *raft) restoreAutoPromotingNode(nodes []uint64, autoPromote bool) { + for _, n := range nodes { + if n == r.id { + r.autoPromote = autoPromote + } + r.prs.Progress[n].AutoPromote = autoPromote + } +} + // promotable indicates whether state machine can be promoted to leader, // which is true when its own id is in progress list. func (r *raft) promotable() bool { @@ -1411,12 +1428,12 @@ func (r *raft) promotable() bool { } func (r *raft) applyConfChange(cc pb.ConfChange) pb.ConfState { - addNodeOrLearnerNode := func(id uint64, isLearner bool) { + addNodeOrLearnerNode := func(id uint64, isLearner bool, autoPromote bool) { // NB: this method is intentionally hidden from view. All mutations of // the conf state must call applyConfChange directly. pr := r.prs.Progress[id] if pr == nil { - r.prs.InitProgress(id, 0, r.raftLog.lastIndex()+1, isLearner) + r.prs.InitProgress(id, 0, r.raftLog.lastIndex()+1, isLearner, autoPromote) } else { if isLearner && !pr.IsLearner { // Can only change Learner to Voter. @@ -1434,8 +1451,9 @@ func (r *raft) applyConfChange(cc pb.ConfChange) pb.ConfState { // Change Learner to Voter, use origin Learner progress. r.prs.RemoveAny(id) - r.prs.InitProgress(id, 0 /* match */, 1 /* next */, false /* isLearner */) + r.prs.InitProgress(id, 0 /* match */, 1 /* next */, false /* isLearner */, false /* autoPromote */) pr.IsLearner = false + pr.AutoPromote = false *r.prs.Progress[id] = *pr } @@ -1449,9 +1467,11 @@ func (r *raft) applyConfChange(cc pb.ConfChange) pb.ConfState { if cc.NodeID != None { switch cc.Type { case pb.ConfChangeAddNode: - addNodeOrLearnerNode(cc.NodeID, false /* isLearner */) + addNodeOrLearnerNode(cc.NodeID, false /* isLearner */, false /* autoPromote */) case pb.ConfChangeAddLearnerNode: - addNodeOrLearnerNode(cc.NodeID, true /* isLearner */) + addNodeOrLearnerNode(cc.NodeID, true /* isLearner */, false /* autoPromote */) + case pb.ConfChangeAddAutoPromotingNode: + addNodeOrLearnerNode(cc.NodeID, true /* isLearner */, true /* autoPromote */) case pb.ConfChangeRemoveNode: removed++ r.prs.RemoveAny(cc.NodeID) diff --git a/raft/raft_test.go b/raft/raft_test.go index 8fcc2f5c76d..6d66035046b 100644 --- a/raft/raft_test.go +++ b/raft/raft_test.go @@ -1142,7 +1142,7 @@ func TestCommit(t *testing.T) { sm := newTestRaft(1, []uint64{1}, 10, 2, storage) sm.prs.RemoveAny(1) for j := 0; j < len(tt.matches); j++ { - sm.prs.InitProgress(uint64(j)+1, tt.matches[j], tt.matches[j]+1, false) + sm.prs.InitProgress(uint64(j)+1, tt.matches[j], tt.matches[j]+1, false /* isLearner */, false /* autoPromote */) } sm.maybeCommit() if g := sm.raftLog.committed; g != tt.w { diff --git a/raft/raftpb/raft.pb.go b/raft/raftpb/raft.pb.go index fd9ee3729ec..f5822a9765d 100644 --- a/raft/raftpb/raft.pb.go +++ b/raft/raftpb/raft.pb.go @@ -163,10 +163,11 @@ func (MessageType) EnumDescriptor() ([]byte, []int) { return fileDescriptorRaft, type ConfChangeType int32 const ( - ConfChangeAddNode ConfChangeType = 0 - ConfChangeRemoveNode ConfChangeType = 1 - ConfChangeUpdateNode ConfChangeType = 2 - ConfChangeAddLearnerNode ConfChangeType = 3 + ConfChangeAddNode ConfChangeType = 0 + ConfChangeRemoveNode ConfChangeType = 1 + ConfChangeUpdateNode ConfChangeType = 2 + ConfChangeAddLearnerNode ConfChangeType = 3 + ConfChangeAddAutoPromotingNode ConfChangeType = 4 ) var ConfChangeType_name = map[int32]string{ @@ -174,12 +175,14 @@ var ConfChangeType_name = map[int32]string{ 1: "ConfChangeRemoveNode", 2: "ConfChangeUpdateNode", 3: "ConfChangeAddLearnerNode", + 4: "ConfChangeAddAutoPromotingNode", } var ConfChangeType_value = map[string]int32{ - "ConfChangeAddNode": 0, - "ConfChangeRemoveNode": 1, - "ConfChangeUpdateNode": 2, - "ConfChangeAddLearnerNode": 3, + "ConfChangeAddNode": 0, + "ConfChangeRemoveNode": 1, + "ConfChangeUpdateNode": 2, + "ConfChangeAddLearnerNode": 3, + "ConfChangeAddAutoPromotingNode": 4, } func (x ConfChangeType) Enum() *ConfChangeType { @@ -272,6 +275,7 @@ func (*HardState) Descriptor() ([]byte, []int) { return fileDescriptorRaft, []in type ConfState struct { Nodes []uint64 `protobuf:"varint,1,rep,name=nodes" json:"nodes,omitempty"` Learners []uint64 `protobuf:"varint,2,rep,name=learners" json:"learners,omitempty"` + AutoPromotees []uint64 `protobuf:"varint,3,rep,name=autoPromotees" json:"autoPromotees,omitempty"` XXX_unrecognized []byte `json:"-"` } @@ -549,6 +553,13 @@ func (m *ConfState) MarshalTo(dAtA []byte) (int, error) { i = encodeVarintRaft(dAtA, i, uint64(num)) } } + if len(m.AutoPromotees) > 0 { + for _, num := range m.AutoPromotees { + dAtA[i] = 0x18 + i++ + i = encodeVarintRaft(dAtA, i, uint64(num)) + } + } if m.XXX_unrecognized != nil { i += copy(dAtA[i:], m.XXX_unrecognized) } @@ -699,6 +710,11 @@ func (m *ConfState) Size() (n int) { n += 1 + sovRaft(uint64(e)) } } + if len(m.AutoPromotees) > 0 { + for _, e := range m.AutoPromotees { + n += 1 + sovRaft(uint64(e)) + } + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -1680,6 +1696,68 @@ func (m *ConfState) Unmarshal(dAtA []byte) error { } else { return fmt.Errorf("proto: wrong wireType = %d for field Learners", wireType) } + case 3: + if wireType == 0 { + var v uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRaft + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.AutoPromotees = append(m.AutoPromotees, v) + } else if wireType == 2 { + var packedLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRaft + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + packedLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if packedLen < 0 { + return ErrInvalidLengthRaft + } + postIndex := iNdEx + packedLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + for iNdEx < postIndex { + var v uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRaft + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.AutoPromotees = append(m.AutoPromotees, v) + } + } else { + return fmt.Errorf("proto: wrong wireType = %d for field AutoPromotees", wireType) + } default: iNdEx = preIndex skippy, err := skipRaft(dAtA[iNdEx:]) @@ -1949,56 +2027,58 @@ var ( func init() { proto.RegisterFile("raft.proto", fileDescriptorRaft) } var fileDescriptorRaft = []byte{ - // 815 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x54, 0xcd, 0x6e, 0x23, 0x45, - 0x10, 0xf6, 0x8c, 0xc7, 0x7f, 0x35, 0x8e, 0xd3, 0xa9, 0x35, 0xa8, 0x15, 0x45, 0xc6, 0xb2, 0x38, - 0x58, 0x41, 0x1b, 0x20, 0x07, 0x0e, 0x48, 0x1c, 0x36, 0x09, 0x52, 0x22, 0xad, 0xa3, 0xc5, 0x9b, - 0xe5, 0x80, 0x84, 0x50, 0xc7, 0x53, 0x9e, 0x18, 0x32, 0xd3, 0xa3, 0x9e, 0xf6, 0xb2, 0xb9, 0x20, - 0x1e, 0x80, 0x07, 0xe0, 0xc2, 0xfb, 0xe4, 0xb8, 0x12, 0x77, 0xc4, 0x86, 0x17, 0x41, 0xdd, 0xd3, - 0x63, 0xcf, 0x24, 0xb7, 0xae, 0xef, 0xab, 0xae, 0xfa, 0xea, 0xeb, 0x9a, 0x01, 0x50, 0x62, 0xa9, - 0x8f, 0x32, 0x25, 0xb5, 0xc4, 0xb6, 0x39, 0x67, 0xd7, 0xfb, 0xc3, 0x58, 0xc6, 0xd2, 0x42, 0x9f, - 0x9b, 0x53, 0xc1, 0x4e, 0x7e, 0x83, 0xd6, 0xb7, 0xa9, 0x56, 0x77, 0xf8, 0x19, 0x04, 0x57, 0x77, - 0x19, 0x71, 0x6f, 0xec, 0x4d, 0x07, 0xc7, 0x7b, 0x47, 0xc5, 0xad, 0x23, 0x4b, 0x1a, 0xe2, 0x24, - 0xb8, 0xff, 0xe7, 0x93, 0xc6, 0xdc, 0x26, 0x21, 0x87, 0xe0, 0x8a, 0x54, 0xc2, 0xfd, 0xb1, 0x37, - 0x0d, 0x36, 0x0c, 0xa9, 0x04, 0xf7, 0xa1, 0x75, 0x91, 0x46, 0xf4, 0x8e, 0x37, 0x2b, 0x54, 0x01, - 0x21, 0x42, 0x70, 0x26, 0xb4, 0xe0, 0xc1, 0xd8, 0x9b, 0xf6, 0xe7, 0xf6, 0x3c, 0xf9, 0xdd, 0x03, - 0xf6, 0x3a, 0x15, 0x59, 0x7e, 0x23, 0xf5, 0x8c, 0xb4, 0x88, 0x84, 0x16, 0xf8, 0x15, 0xc0, 0x42, - 0xa6, 0xcb, 0x9f, 0x72, 0x2d, 0x74, 0xa1, 0x28, 0xdc, 0x2a, 0x3a, 0x95, 0xe9, 0xf2, 0xb5, 0x21, - 0x5c, 0xf1, 0xde, 0xa2, 0x04, 0x4c, 0xf3, 0x95, 0x6d, 0x5e, 0xd5, 0x55, 0x40, 0x46, 0xb2, 0x36, - 0x92, 0xab, 0xba, 0x2c, 0x32, 0xf9, 0x01, 0xba, 0xa5, 0x02, 0x23, 0xd1, 0x28, 0xb0, 0x3d, 0xfb, - 0x73, 0x7b, 0xc6, 0xaf, 0xa1, 0x9b, 0x38, 0x65, 0xb6, 0x70, 0x78, 0xcc, 0x4b, 0x2d, 0x8f, 0x95, - 0xbb, 0xba, 0x9b, 0xfc, 0xc9, 0x5f, 0x4d, 0xe8, 0xcc, 0x28, 0xcf, 0x45, 0x4c, 0xf8, 0x1c, 0x02, - 0xbd, 0x75, 0xf8, 0x59, 0x59, 0xc3, 0xd1, 0x55, 0x8f, 0x4d, 0x1a, 0x0e, 0xc1, 0xd7, 0xb2, 0x36, - 0x89, 0xaf, 0xa5, 0x19, 0x63, 0xa9, 0xe4, 0xa3, 0x31, 0x0c, 0xb2, 0x19, 0x30, 0x78, 0x3c, 0x20, - 0x8e, 0xa0, 0x73, 0x2b, 0x63, 0xfb, 0x60, 0xad, 0x0a, 0x59, 0x82, 0x5b, 0xdb, 0xda, 0x4f, 0x6d, - 0x7b, 0x0e, 0x1d, 0x4a, 0xb5, 0x5a, 0x51, 0xce, 0x3b, 0xe3, 0xe6, 0x34, 0x3c, 0xde, 0xa9, 0x6d, - 0x46, 0x59, 0xca, 0xe5, 0xe0, 0x01, 0xb4, 0x17, 0x32, 0x49, 0x56, 0x9a, 0x77, 0x2b, 0xb5, 0x1c, - 0x86, 0xc7, 0xd0, 0xcd, 0x9d, 0x63, 0xbc, 0x67, 0x9d, 0x64, 0x8f, 0x9d, 0x2c, 0x1d, 0x2c, 0xf3, - 0x4c, 0x45, 0x45, 0x3f, 0xd3, 0x42, 0x73, 0x18, 0x7b, 0xd3, 0x6e, 0x59, 0xb1, 0xc0, 0xf0, 0x53, - 0x80, 0xe2, 0x74, 0xbe, 0x4a, 0x35, 0x0f, 0x2b, 0x3d, 0x2b, 0x38, 0x72, 0xe8, 0x2c, 0x64, 0xaa, - 0xe9, 0x9d, 0xe6, 0x7d, 0xfb, 0xb0, 0x65, 0x38, 0xf9, 0x11, 0x7a, 0xe7, 0x42, 0x45, 0xc5, 0xfa, - 0x94, 0x0e, 0x7a, 0x4f, 0x1c, 0xe4, 0x10, 0xbc, 0x95, 0x9a, 0xea, 0xfb, 0x6e, 0x90, 0xca, 0xc0, - 0xcd, 0xa7, 0x03, 0x4f, 0xbe, 0x81, 0xde, 0x66, 0x5d, 0x71, 0x08, 0xad, 0x54, 0x46, 0x94, 0x73, - 0x6f, 0xdc, 0x9c, 0x06, 0xf3, 0x22, 0xc0, 0x7d, 0xe8, 0xde, 0x92, 0x50, 0x29, 0xa9, 0x9c, 0xfb, - 0x96, 0xd8, 0xc4, 0x93, 0x3f, 0x3c, 0x00, 0x73, 0xff, 0xf4, 0x46, 0xa4, 0xb1, 0xdd, 0x88, 0x8b, - 0xb3, 0x9a, 0x3a, 0xff, 0xe2, 0x0c, 0xbf, 0x70, 0x1f, 0xae, 0x6f, 0xd7, 0xea, 0xe3, 0xea, 0x67, - 0x52, 0xdc, 0x7b, 0xf2, 0xf5, 0x1e, 0x40, 0xfb, 0x52, 0x46, 0x74, 0x71, 0x56, 0xd7, 0x5c, 0x60, - 0xc6, 0xac, 0x53, 0x67, 0x56, 0xf1, 0xa1, 0x96, 0xe1, 0xe1, 0x97, 0xd0, 0xdb, 0xfc, 0x0e, 0x70, - 0x17, 0x42, 0x1b, 0x5c, 0x4a, 0x95, 0x88, 0x5b, 0xd6, 0xc0, 0x67, 0xb0, 0x6b, 0x81, 0x6d, 0x63, - 0xe6, 0x1d, 0xfe, 0xed, 0x43, 0x58, 0x59, 0x70, 0x04, 0x68, 0xcf, 0xf2, 0xf8, 0x7c, 0x9d, 0xb1, - 0x06, 0x86, 0xd0, 0x99, 0xe5, 0xf1, 0x09, 0x09, 0xcd, 0x3c, 0x17, 0xbc, 0x52, 0x32, 0x63, 0xbe, - 0xcb, 0x7a, 0x91, 0x65, 0xac, 0x89, 0x03, 0x80, 0xe2, 0x3c, 0xa7, 0x3c, 0x63, 0x81, 0x4b, 0xfc, - 0x5e, 0x6a, 0x62, 0x2d, 0x23, 0xc2, 0x05, 0x96, 0x6d, 0x3b, 0xd6, 0x2c, 0x13, 0xeb, 0x20, 0x83, - 0xbe, 0x69, 0x46, 0x42, 0xe9, 0x6b, 0xd3, 0xa5, 0x8b, 0x43, 0x60, 0x55, 0xc4, 0x5e, 0xea, 0x21, - 0xc2, 0x60, 0x96, 0xc7, 0x6f, 0x52, 0x45, 0x62, 0x71, 0x23, 0xae, 0x6f, 0x89, 0x01, 0xee, 0xc1, - 0x8e, 0x2b, 0x64, 0x1e, 0x6f, 0x9d, 0xb3, 0xd0, 0xa5, 0x9d, 0xde, 0xd0, 0xe2, 0x97, 0xef, 0xd6, - 0x52, 0xad, 0x13, 0xd6, 0xc7, 0x8f, 0x60, 0x6f, 0x96, 0xc7, 0x57, 0x4a, 0xa4, 0xf9, 0x92, 0xd4, - 0x4b, 0x12, 0x11, 0x29, 0xb6, 0xe3, 0x6e, 0x5f, 0xad, 0x12, 0x92, 0x6b, 0x7d, 0x29, 0x7f, 0x65, - 0x03, 0x27, 0x66, 0x4e, 0x22, 0xb2, 0x3f, 0x43, 0xb6, 0xeb, 0xc4, 0x6c, 0x10, 0x2b, 0x86, 0xb9, - 0x79, 0x5f, 0x29, 0xb2, 0x23, 0xee, 0xb9, 0xae, 0x2e, 0xb6, 0x39, 0x78, 0x78, 0x07, 0x83, 0xfa, - 0xf3, 0x1a, 0x1d, 0x5b, 0xe4, 0x45, 0x14, 0x99, 0xb7, 0x64, 0x0d, 0xe4, 0x30, 0xdc, 0xc2, 0x73, - 0x4a, 0xe4, 0x5b, 0xb2, 0x8c, 0x57, 0x67, 0xde, 0x64, 0x91, 0xd0, 0x05, 0xe3, 0xe3, 0x01, 0xf0, - 0x5a, 0xa9, 0x97, 0xc5, 0x36, 0x5a, 0xb6, 0x79, 0xc2, 0xef, 0x3f, 0x8c, 0x1a, 0xef, 0x3f, 0x8c, - 0x1a, 0xf7, 0x0f, 0x23, 0xef, 0xfd, 0xc3, 0xc8, 0xfb, 0xf7, 0x61, 0xe4, 0xfd, 0xf9, 0xdf, 0xa8, - 0xf1, 0x7f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x86, 0x52, 0x5b, 0xe0, 0x74, 0x06, 0x00, 0x00, + // 844 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x54, 0xcd, 0x6e, 0xdb, 0x46, + 0x10, 0x16, 0x29, 0xea, 0x6f, 0x24, 0xcb, 0xeb, 0x89, 0x5a, 0x2c, 0x0c, 0x43, 0x15, 0x84, 0x1c, + 0x04, 0x17, 0x71, 0x5b, 0x1f, 0x7a, 0xe8, 0xcd, 0x3f, 0x05, 0x6c, 0x20, 0x32, 0x5c, 0xc5, 0xe9, + 0xa1, 0x40, 0x51, 0xac, 0xc5, 0x11, 0xad, 0xd6, 0xe4, 0x12, 0xcb, 0x55, 0x9a, 0x5c, 0x8a, 0x3e, + 0x40, 0x1f, 0xa0, 0x97, 0xbc, 0x8f, 0x8f, 0x01, 0x7a, 0x2f, 0x1a, 0xf7, 0x45, 0x82, 0x5d, 0x2e, + 0x25, 0xd2, 0xba, 0xed, 0x7c, 0xdf, 0x70, 0xe6, 0x9b, 0x6f, 0x67, 0x09, 0xa0, 0xc4, 0x42, 0x1f, + 0xa5, 0x4a, 0x6a, 0x89, 0x4d, 0x73, 0x4e, 0x6f, 0xf7, 0x07, 0x91, 0x8c, 0xa4, 0x85, 0xbe, 0x32, + 0xa7, 0x9c, 0x1d, 0xff, 0x01, 0x8d, 0xef, 0x13, 0xad, 0xde, 0xe1, 0x97, 0x10, 0xdc, 0xbc, 0x4b, + 0x89, 0x7b, 0x23, 0x6f, 0xd2, 0x3f, 0xde, 0x3b, 0xca, 0xbf, 0x3a, 0xb2, 0xa4, 0x21, 0x4e, 0x83, + 0x87, 0x7f, 0xbf, 0xa8, 0xcd, 0x6c, 0x12, 0x72, 0x08, 0x6e, 0x48, 0xc5, 0xdc, 0x1f, 0x79, 0x93, + 0x60, 0xcd, 0x90, 0x8a, 0x71, 0x1f, 0x1a, 0x97, 0x49, 0x48, 0x6f, 0x79, 0xbd, 0x44, 0xe5, 0x10, + 0x22, 0x04, 0xe7, 0x42, 0x0b, 0x1e, 0x8c, 0xbc, 0x49, 0x6f, 0x66, 0xcf, 0xe3, 0x3f, 0x3d, 0x60, + 0xaf, 0x12, 0x91, 0x66, 0x77, 0x52, 0x4f, 0x49, 0x8b, 0x50, 0x68, 0x81, 0xdf, 0x02, 0xcc, 0x65, + 0xb2, 0xf8, 0x25, 0xd3, 0x42, 0xe7, 0x8a, 0xba, 0x1b, 0x45, 0x67, 0x32, 0x59, 0xbc, 0x32, 0x84, + 0x2b, 0xde, 0x99, 0x17, 0x80, 0x69, 0xbe, 0xb4, 0xcd, 0xcb, 0xba, 0x72, 0xc8, 0x48, 0xd6, 0x46, + 0x72, 0x59, 0x97, 0x45, 0xc6, 0x3f, 0x41, 0xbb, 0x50, 0x60, 0x24, 0x1a, 0x05, 0xb6, 0x67, 0x6f, + 0x66, 0xcf, 0xf8, 0x1d, 0xb4, 0x63, 0xa7, 0xcc, 0x16, 0xee, 0x1e, 0xf3, 0x42, 0xcb, 0x53, 0xe5, + 0xae, 0xee, 0x3a, 0x7f, 0xfc, 0xbe, 0x0e, 0xad, 0x29, 0x65, 0x99, 0x88, 0x08, 0x5f, 0x40, 0xa0, + 0x37, 0x0e, 0x3f, 0x2b, 0x6a, 0x38, 0xba, 0xec, 0xb1, 0x49, 0xc3, 0x01, 0xf8, 0x5a, 0x56, 0x26, + 0xf1, 0xb5, 0x34, 0x63, 0x2c, 0x94, 0x7c, 0x32, 0x86, 0x41, 0xd6, 0x03, 0x06, 0x4f, 0x07, 0xc4, + 0x21, 0xb4, 0xee, 0x65, 0x64, 0x2f, 0xac, 0x51, 0x22, 0x0b, 0x70, 0x63, 0x5b, 0x73, 0xdb, 0xb6, + 0x17, 0xd0, 0xa2, 0x44, 0xab, 0x25, 0x65, 0xbc, 0x35, 0xaa, 0x4f, 0xba, 0xc7, 0x3b, 0x95, 0xcd, + 0x28, 0x4a, 0xb9, 0x1c, 0x3c, 0x80, 0xe6, 0x5c, 0xc6, 0xf1, 0x52, 0xf3, 0x76, 0xa9, 0x96, 0xc3, + 0xf0, 0x18, 0xda, 0x99, 0x73, 0x8c, 0x77, 0xac, 0x93, 0xec, 0xa9, 0x93, 0x85, 0x83, 0x45, 0x9e, + 0xa9, 0xa8, 0xe8, 0x57, 0x9a, 0x6b, 0x0e, 0x23, 0x6f, 0xd2, 0x2e, 0x2a, 0xe6, 0x18, 0x3e, 0x07, + 0xc8, 0x4f, 0x17, 0xcb, 0x44, 0xf3, 0x6e, 0xa9, 0x67, 0x09, 0x47, 0x0e, 0xad, 0xb9, 0x4c, 0x34, + 0xbd, 0xd5, 0xbc, 0x67, 0x2f, 0xb6, 0x08, 0xc7, 0x3f, 0x43, 0xe7, 0x42, 0xa8, 0x30, 0x5f, 0x9f, + 0xc2, 0x41, 0x6f, 0xcb, 0x41, 0x0e, 0xc1, 0x1b, 0xa9, 0xa9, 0xba, 0xef, 0x06, 0x29, 0x0d, 0x5c, + 0xdf, 0x1e, 0x78, 0x3c, 0x87, 0xce, 0x7a, 0x5d, 0x71, 0x00, 0x8d, 0x44, 0x86, 0x94, 0x71, 0x6f, + 0x54, 0x9f, 0x04, 0xb3, 0x3c, 0xc0, 0x7d, 0x68, 0xdf, 0x93, 0x50, 0x09, 0xa9, 0x8c, 0xfb, 0x96, + 0x58, 0xc7, 0xf8, 0x1c, 0x76, 0xc4, 0x4a, 0xcb, 0x6b, 0x25, 0x63, 0xa9, 0x89, 0x32, 0x5e, 0xb7, + 0x09, 0x55, 0x70, 0xfc, 0x97, 0x07, 0x60, 0xba, 0x9c, 0xdd, 0x89, 0x24, 0xb2, 0x7b, 0x73, 0x79, + 0x5e, 0x99, 0xc1, 0xbf, 0x3c, 0xc7, 0xaf, 0xdd, 0xf3, 0xf6, 0xed, 0xf2, 0x7d, 0x5e, 0x7e, 0x4c, + 0xf9, 0x77, 0x5b, 0x6f, 0xfc, 0x00, 0x9a, 0x57, 0x32, 0xa4, 0xcb, 0xf3, 0xea, 0x64, 0x39, 0x66, + 0x2c, 0x3d, 0x73, 0x96, 0xe6, 0xcf, 0xb9, 0x08, 0x0f, 0xbf, 0x81, 0xce, 0xfa, 0xa7, 0x81, 0xbb, + 0xd0, 0xb5, 0xc1, 0x95, 0x54, 0xb1, 0xb8, 0x67, 0x35, 0x7c, 0x06, 0xbb, 0x16, 0xd8, 0x34, 0x66, + 0xde, 0xe1, 0x3f, 0x3e, 0x74, 0x4b, 0xcf, 0x00, 0x01, 0x9a, 0xd3, 0x2c, 0xba, 0x58, 0xa5, 0xac, + 0x86, 0x5d, 0x68, 0x4d, 0xb3, 0xe8, 0x94, 0x84, 0x66, 0x9e, 0x0b, 0xae, 0x95, 0x4c, 0x99, 0xef, + 0xb2, 0x4e, 0xd2, 0x94, 0xd5, 0xb1, 0x0f, 0x90, 0x9f, 0x67, 0x94, 0xa5, 0x2c, 0x70, 0x89, 0x3f, + 0x4a, 0x4d, 0xac, 0x61, 0x44, 0xb8, 0xc0, 0xb2, 0x4d, 0xc7, 0x9a, 0x95, 0x63, 0x2d, 0x64, 0xd0, + 0x33, 0xcd, 0x48, 0x28, 0x7d, 0x6b, 0xba, 0xb4, 0x71, 0x00, 0xac, 0x8c, 0xd8, 0x8f, 0x3a, 0x88, + 0xd0, 0x9f, 0x66, 0xd1, 0xeb, 0x44, 0x91, 0x98, 0xdf, 0x89, 0xdb, 0x7b, 0x62, 0x80, 0x7b, 0xb0, + 0xe3, 0x0a, 0x99, 0x2b, 0x5e, 0x65, 0xac, 0xeb, 0xd2, 0xce, 0xee, 0x68, 0xfe, 0xdb, 0x0f, 0x2b, + 0xa9, 0x56, 0x31, 0xeb, 0xe1, 0x67, 0xb0, 0x37, 0xcd, 0xa2, 0x1b, 0x25, 0x92, 0x6c, 0x41, 0xea, + 0x25, 0x89, 0x90, 0x14, 0xdb, 0x71, 0x5f, 0xdf, 0x2c, 0x63, 0x92, 0x2b, 0x7d, 0x25, 0x7f, 0x67, + 0x7d, 0x27, 0x66, 0x46, 0x22, 0xb4, 0xbf, 0x4c, 0xb6, 0xeb, 0xc4, 0xac, 0x11, 0x2b, 0x86, 0xb9, + 0x79, 0xaf, 0x15, 0xd9, 0x11, 0xf7, 0x5c, 0x57, 0x17, 0xdb, 0x1c, 0x3c, 0x7c, 0xef, 0x41, 0xbf, + 0x7a, 0xbf, 0x46, 0xc8, 0x06, 0x39, 0x09, 0x43, 0x73, 0x99, 0xac, 0x86, 0x1c, 0x06, 0x1b, 0x78, + 0x46, 0xb1, 0x7c, 0x43, 0x96, 0xf1, 0xaa, 0xcc, 0xeb, 0x34, 0x14, 0x3a, 0x67, 0x7c, 0x3c, 0x00, + 0x5e, 0x29, 0xf5, 0x32, 0x5f, 0x5a, 0xcb, 0xd6, 0x71, 0x0c, 0xc3, 0x0a, 0x7b, 0xb2, 0xde, 0xd8, + 0x65, 0x12, 0xd9, 0x9c, 0xe0, 0x94, 0x3f, 0x7c, 0x1c, 0xd6, 0x3e, 0x7c, 0x1c, 0xd6, 0x1e, 0x1e, + 0x87, 0xde, 0x87, 0xc7, 0xa1, 0xf7, 0xdf, 0xe3, 0xd0, 0xfb, 0xfb, 0xff, 0x61, 0xed, 0x53, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xb0, 0x0e, 0x21, 0xd7, 0xbf, 0x06, 0x00, 0x00, } diff --git a/raft/raftpb/raft.proto b/raft/raftpb/raft.proto index 644ce7b8f2f..7ffed9df2ee 100644 --- a/raft/raftpb/raft.proto +++ b/raft/raftpb/raft.proto @@ -78,13 +78,15 @@ message HardState { message ConfState { repeated uint64 nodes = 1; repeated uint64 learners = 2; + repeated uint64 autoPromotees = 3; } enum ConfChangeType { - ConfChangeAddNode = 0; - ConfChangeRemoveNode = 1; - ConfChangeUpdateNode = 2; - ConfChangeAddLearnerNode = 3; + ConfChangeAddNode = 0; + ConfChangeRemoveNode = 1; + ConfChangeUpdateNode = 2; + ConfChangeAddLearnerNode = 3; + ConfChangeAddAutoPromotingNode = 4; } message ConfChange { diff --git a/raft/tracker/progress.go b/raft/tracker/progress.go index a7f1ab7d38f..fcc98dac4d3 100644 --- a/raft/tracker/progress.go +++ b/raft/tracker/progress.go @@ -74,6 +74,11 @@ type Progress struct { // IsLearner is true if this progress is tracked for a learner. IsLearner bool + + // When AutoPromote is enabled for a learner, the learner is + // automatically promoted to a voter once it is caught up with + // the leader. AutoPromote has no effect when enabled for voters. + AutoPromote bool } // ResetState moves the Progress into the specified State, resetting ProbeSent, diff --git a/raft/tracker/tracker.go b/raft/tracker/tracker.go index 4b3396fbe17..d99e8946aa1 100644 --- a/raft/tracker/tracker.go +++ b/raft/tracker/tracker.go @@ -70,6 +70,12 @@ type Config struct { // is caught up as soon as possible. // // NextLearners map[uint64]struct{} + + // An AutoPromotee is a Learner that is in the process of catching up with + // the leader. When an AutoPromotee has caught up with the leader, it is + // automatically promoted to a Voter. All members of AutoPromotees are also + // members of Learners, but not all Learners are also AutoPromotees. + AutoPromotees map[uint64]bool } func (c *Config) String() string { @@ -106,7 +112,8 @@ func MakeProgressTracker(maxInflight int) ProgressTracker { // in the common case. quorum.MajorityConfig{}, }, - Learners: map[uint64]struct{}{}, + Learners: map[uint64]struct{}{}, + AutoPromotees: map[uint64]bool{}, }, Votes: map[uint64]bool{}, Progress: map[uint64]*Progress{}, @@ -160,12 +167,13 @@ func (p *ProgressTracker) RemoveAny(id uint64) { delete(p.Voters[0], id) delete(p.Voters[1], id) delete(p.Learners, id) + delete(p.AutoPromotees, id) delete(p.Progress, id) } // InitProgress initializes a new progress for the given node or learner. The // node may not exist yet in either form or a panic will ensue. -func (p *ProgressTracker) InitProgress(id, match, next uint64, isLearner bool) { +func (p *ProgressTracker) InitProgress(id, match, next uint64, isLearner bool, autoPromote bool) { if pr := p.Progress[id]; pr != nil { panic(fmt.Sprintf("peer %x already tracked as node %v", id, pr)) } @@ -173,8 +181,17 @@ func (p *ProgressTracker) InitProgress(id, match, next uint64, isLearner bool) { p.Voters[0][id] = struct{}{} } else { p.Learners[id] = struct{}{} + if autoPromote { + p.AutoPromotees[id] = true + } + } + p.Progress[id] = &Progress{ + Next: next, + Match: match, + Inflights: NewInflights(p.MaxInflight), + IsLearner: isLearner, + AutoPromote: autoPromote, } - p.Progress[id] = &Progress{Next: next, Match: match, Inflights: NewInflights(p.MaxInflight), IsLearner: isLearner} } // Visit invokes the supplied closure for all tracked progresses. @@ -219,6 +236,18 @@ func (p *ProgressTracker) LearnerNodes() []uint64 { return nodes } +// AutoPromotees returns a sorted slice of learners +// that will be automatically promoted to voters +// when caught up with the leader. +func (p *ProgressTracker) AutoPromotingNodes() []uint64 { + nodes := make([]uint64, 0, len(p.AutoPromotees)) + for id := range p.AutoPromotees { + nodes = append(nodes, id) + } + sort.Slice(nodes, func(i, j int) bool { return nodes[i] < nodes[j] }) + return nodes +} + // ResetVotes prepares for a new round of vote counting via recordVote. func (p *ProgressTracker) ResetVotes() { p.Votes = map[uint64]bool{}