*: return updated member list in v3 rpcs

Now it's possible to atomically know the new member configuration from
issuing a membership change RPC.
This commit is contained in:
Anthony Romano 2017-04-12 15:27:28 -07:00
parent 2046d66927
commit d9ec6b4d22
10 changed files with 498 additions and 279 deletions

View File

@ -557,6 +557,7 @@ Empty field.
| ----- | ----------- | ---- | | ----- | ----------- | ---- |
| header | | ResponseHeader | | header | | ResponseHeader |
| member | member is the member information for the added member. | Member | | member | member is the member information for the added member. | Member |
| members | members is a list of all members after adding the new member. | (slice of) Member |
@ -588,6 +589,7 @@ Empty field.
| Field | Description | Type | | Field | Description | Type |
| ----- | ----------- | ---- | | ----- | ----------- | ---- |
| header | | ResponseHeader | | header | | ResponseHeader |
| members | members is a list of all members after removing the member. | (slice of) Member |
@ -605,6 +607,7 @@ Empty field.
| Field | Description | Type | | Field | Description | Type |
| ----- | ----------- | ---- | | ----- | ----------- | ---- |
| header | | ResponseHeader | | header | | ResponseHeader |
| members | members is a list of all members after updating the member. | (slice of) Member |

View File

@ -1713,6 +1713,13 @@
"member": { "member": {
"$ref": "#/definitions/etcdserverpbMember", "$ref": "#/definitions/etcdserverpbMember",
"description": "member is the member information for the added member." "description": "member is the member information for the added member."
},
"members": {
"type": "array",
"items": {
"$ref": "#/definitions/etcdserverpbMember"
},
"description": "members is a list of all members after adding the new member."
} }
} }
}, },
@ -1749,6 +1756,13 @@
"properties": { "properties": {
"header": { "header": {
"$ref": "#/definitions/etcdserverpbResponseHeader" "$ref": "#/definitions/etcdserverpbResponseHeader"
},
"members": {
"type": "array",
"items": {
"$ref": "#/definitions/etcdserverpbMember"
},
"description": "members is a list of all members after removing the member."
} }
} }
}, },
@ -1774,6 +1788,13 @@
"properties": { "properties": {
"header": { "header": {
"$ref": "#/definitions/etcdserverpbResponseHeader" "$ref": "#/definitions/etcdserverpbResponseHeader"
},
"members": {
"type": "array",
"items": {
"$ref": "#/definitions/etcdserverpbMember"
},
"description": "members is a list of all members after updating the member."
} }
} }
}, },

View File

@ -234,7 +234,7 @@ func (h *membersHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
} }
now := h.clock.Now() now := h.clock.Now()
m := membership.NewMember("", req.PeerURLs, "", &now) m := membership.NewMember("", req.PeerURLs, "", &now)
err := h.server.AddMember(ctx, *m) _, err := h.server.AddMember(ctx, *m)
switch { switch {
case err == membership.ErrIDExists || err == membership.ErrPeerURLexists: case err == membership.ErrIDExists || err == membership.ErrPeerURLexists:
writeError(w, r, httptypes.NewHTTPError(http.StatusConflict, err.Error())) writeError(w, r, httptypes.NewHTTPError(http.StatusConflict, err.Error()))
@ -255,7 +255,7 @@ func (h *membersHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if !ok { if !ok {
return return
} }
err := h.server.RemoveMember(ctx, uint64(id)) _, err := h.server.RemoveMember(ctx, uint64(id))
switch { switch {
case err == membership.ErrIDRemoved: case err == membership.ErrIDRemoved:
writeError(w, r, httptypes.NewHTTPError(http.StatusGone, fmt.Sprintf("Member permanently removed: %s", id))) writeError(w, r, httptypes.NewHTTPError(http.StatusGone, fmt.Sprintf("Member permanently removed: %s", id)))
@ -280,7 +280,7 @@ func (h *membersHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ID: id, ID: id,
RaftAttributes: membership.RaftAttributes{PeerURLs: req.PeerURLs.StringSlice()}, RaftAttributes: membership.RaftAttributes{PeerURLs: req.PeerURLs.StringSlice()},
} }
err := h.server.UpdateMember(ctx, m) _, err := h.server.UpdateMember(ctx, m)
switch { switch {
case err == membership.ErrPeerURLexists: case err == membership.ErrPeerURLexists:
writeError(w, r, httptypes.NewHTTPError(http.StatusConflict, err.Error())) writeError(w, r, httptypes.NewHTTPError(http.StatusConflict, err.Error()))

View File

@ -104,18 +104,18 @@ func (s *serverRecorder) Process(_ context.Context, m raftpb.Message) error {
s.actions = append(s.actions, action{name: "Process", params: []interface{}{m}}) s.actions = append(s.actions, action{name: "Process", params: []interface{}{m}})
return nil return nil
} }
func (s *serverRecorder) AddMember(_ context.Context, m membership.Member) error { func (s *serverRecorder) AddMember(_ context.Context, m membership.Member) ([]*membership.Member, error) {
s.actions = append(s.actions, action{name: "AddMember", params: []interface{}{m}}) s.actions = append(s.actions, action{name: "AddMember", params: []interface{}{m}})
return nil return nil, nil
} }
func (s *serverRecorder) RemoveMember(_ context.Context, id uint64) error { func (s *serverRecorder) RemoveMember(_ context.Context, id uint64) ([]*membership.Member, error) {
s.actions = append(s.actions, action{name: "RemoveMember", params: []interface{}{id}}) s.actions = append(s.actions, action{name: "RemoveMember", params: []interface{}{id}})
return nil return nil, nil
} }
func (s *serverRecorder) UpdateMember(_ context.Context, m membership.Member) error { func (s *serverRecorder) UpdateMember(_ context.Context, m membership.Member) ([]*membership.Member, error) {
s.actions = append(s.actions, action{name: "UpdateMember", params: []interface{}{m}}) s.actions = append(s.actions, action{name: "UpdateMember", params: []interface{}{m}})
return nil return nil, nil
} }
func (s *serverRecorder) ClusterVersion() *semver.Version { return nil } func (s *serverRecorder) ClusterVersion() *semver.Version { return nil }
@ -149,11 +149,17 @@ func (rs *resServer) Leader() types.ID { return types.ID(1) }
func (rs *resServer) Do(_ context.Context, _ etcdserverpb.Request) (etcdserver.Response, error) { func (rs *resServer) Do(_ context.Context, _ etcdserverpb.Request) (etcdserver.Response, error) {
return rs.res, nil return rs.res, nil
} }
func (rs *resServer) Process(_ context.Context, _ raftpb.Message) error { return nil } func (rs *resServer) Process(_ context.Context, _ raftpb.Message) error { return nil }
func (rs *resServer) AddMember(_ context.Context, _ membership.Member) error { return nil } func (rs *resServer) AddMember(_ context.Context, _ membership.Member) ([]*membership.Member, error) {
func (rs *resServer) RemoveMember(_ context.Context, _ uint64) error { return nil } return nil, nil
func (rs *resServer) UpdateMember(_ context.Context, _ membership.Member) error { return nil } }
func (rs *resServer) ClusterVersion() *semver.Version { return nil } func (rs *resServer) RemoveMember(_ context.Context, _ uint64) ([]*membership.Member, error) {
return nil, nil
}
func (rs *resServer) UpdateMember(_ context.Context, _ membership.Member) ([]*membership.Member, error) {
return nil, nil
}
func (rs *resServer) ClusterVersion() *semver.Version { return nil }
func boolp(b bool) *bool { return &b } func boolp(b bool) *bool { return &b }

View File

@ -67,14 +67,14 @@ func (fs *errServer) Do(ctx context.Context, r etcdserverpb.Request) (etcdserver
func (fs *errServer) Process(ctx context.Context, m raftpb.Message) error { func (fs *errServer) Process(ctx context.Context, m raftpb.Message) error {
return fs.err return fs.err
} }
func (fs *errServer) AddMember(ctx context.Context, m membership.Member) error { func (fs *errServer) AddMember(ctx context.Context, m membership.Member) ([]*membership.Member, error) {
return fs.err return nil, fs.err
} }
func (fs *errServer) RemoveMember(ctx context.Context, id uint64) error { func (fs *errServer) RemoveMember(ctx context.Context, id uint64) ([]*membership.Member, error) {
return fs.err return nil, fs.err
} }
func (fs *errServer) UpdateMember(ctx context.Context, m membership.Member) error { func (fs *errServer) UpdateMember(ctx context.Context, m membership.Member) ([]*membership.Member, error) {
return fs.err return nil, fs.err
} }
func (fs *errServer) ClusterVersion() *semver.Version { return nil } func (fs *errServer) ClusterVersion() *semver.Version { return nil }

View File

@ -48,21 +48,24 @@ func (cs *ClusterServer) MemberAdd(ctx context.Context, r *pb.MemberAddRequest)
now := time.Now() now := time.Now()
m := membership.NewMember("", urls, "", &now) m := membership.NewMember("", urls, "", &now)
if err = cs.server.AddMember(ctx, *m); err != nil { membs, merr := cs.server.AddMember(ctx, *m)
return nil, togRPCError(err) if merr != nil {
return nil, togRPCError(merr)
} }
return &pb.MemberAddResponse{ return &pb.MemberAddResponse{
Header: cs.header(), Header: cs.header(),
Member: &pb.Member{ID: uint64(m.ID), PeerURLs: m.PeerURLs}, Member: &pb.Member{ID: uint64(m.ID), PeerURLs: m.PeerURLs},
Members: membersToProtoMembers(membs),
}, nil }, nil
} }
func (cs *ClusterServer) MemberRemove(ctx context.Context, r *pb.MemberRemoveRequest) (*pb.MemberRemoveResponse, error) { func (cs *ClusterServer) MemberRemove(ctx context.Context, r *pb.MemberRemoveRequest) (*pb.MemberRemoveResponse, error) {
if err := cs.server.RemoveMember(ctx, r.ID); err != nil { membs, err := cs.server.RemoveMember(ctx, r.ID)
if err != nil {
return nil, togRPCError(err) return nil, togRPCError(err)
} }
return &pb.MemberRemoveResponse{Header: cs.header()}, nil return &pb.MemberRemoveResponse{Header: cs.header(), Members: membersToProtoMembers(membs)}, nil
} }
func (cs *ClusterServer) MemberUpdate(ctx context.Context, r *pb.MemberUpdateRequest) (*pb.MemberUpdateResponse, error) { func (cs *ClusterServer) MemberUpdate(ctx context.Context, r *pb.MemberUpdateRequest) (*pb.MemberUpdateResponse, error) {
@ -70,15 +73,23 @@ func (cs *ClusterServer) MemberUpdate(ctx context.Context, r *pb.MemberUpdateReq
ID: types.ID(r.ID), ID: types.ID(r.ID),
RaftAttributes: membership.RaftAttributes{PeerURLs: r.PeerURLs}, RaftAttributes: membership.RaftAttributes{PeerURLs: r.PeerURLs},
} }
if err := cs.server.UpdateMember(ctx, m); err != nil { membs, err := cs.server.UpdateMember(ctx, m)
if err != nil {
return nil, togRPCError(err) return nil, togRPCError(err)
} }
return &pb.MemberUpdateResponse{Header: cs.header()}, nil return &pb.MemberUpdateResponse{Header: cs.header(), Members: membersToProtoMembers(membs)}, nil
} }
func (cs *ClusterServer) MemberList(ctx context.Context, r *pb.MemberListRequest) (*pb.MemberListResponse, error) { func (cs *ClusterServer) MemberList(ctx context.Context, r *pb.MemberListRequest) (*pb.MemberListResponse, error) {
membs := cs.cluster.Members() membs := membersToProtoMembers(cs.cluster.Members())
return &pb.MemberListResponse{Header: cs.header(), Members: membs}, nil
}
func (cs *ClusterServer) header() *pb.ResponseHeader {
return &pb.ResponseHeader{ClusterId: uint64(cs.cluster.ID()), MemberId: uint64(cs.server.ID()), RaftTerm: cs.raftTimer.Term()}
}
func membersToProtoMembers(membs []*membership.Member) []*pb.Member {
protoMembs := make([]*pb.Member, len(membs)) protoMembs := make([]*pb.Member, len(membs))
for i := range membs { for i := range membs {
protoMembs[i] = &pb.Member{ protoMembs[i] = &pb.Member{
@ -88,10 +99,5 @@ func (cs *ClusterServer) MemberList(ctx context.Context, r *pb.MemberListRequest
ClientURLs: membs[i].ClientURLs, ClientURLs: membs[i].ClientURLs,
} }
} }
return protoMembs
return &pb.MemberListResponse{Header: cs.header(), Members: protoMembs}, nil
}
func (cs *ClusterServer) header() *pb.ResponseHeader {
return &pb.ResponseHeader{ClusterId: uint64(cs.cluster.ID()), MemberId: uint64(cs.server.ID()), RaftTerm: cs.raftTimer.Term()}
} }

View File

@ -1413,6 +1413,8 @@ type MemberAddResponse struct {
Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"` Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
// member is the member information for the added member. // member is the member information for the added member.
Member *Member `protobuf:"bytes,2,opt,name=member" json:"member,omitempty"` Member *Member `protobuf:"bytes,2,opt,name=member" json:"member,omitempty"`
// members is a list of all members after adding the new member.
Members []*Member `protobuf:"bytes,3,rep,name=members" json:"members,omitempty"`
} }
func (m *MemberAddResponse) Reset() { *m = MemberAddResponse{} } func (m *MemberAddResponse) Reset() { *m = MemberAddResponse{} }
@ -1434,6 +1436,13 @@ func (m *MemberAddResponse) GetMember() *Member {
return nil return nil
} }
func (m *MemberAddResponse) GetMembers() []*Member {
if m != nil {
return m.Members
}
return nil
}
type MemberRemoveRequest struct { type MemberRemoveRequest struct {
// ID is the member ID of the member to remove. // ID is the member ID of the member to remove.
ID uint64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"` ID uint64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
@ -1446,6 +1455,8 @@ func (*MemberRemoveRequest) Descriptor() ([]byte, []int) { return fileDescriptor
type MemberRemoveResponse struct { type MemberRemoveResponse struct {
Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"` Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
// members is a list of all members after removing the member.
Members []*Member `protobuf:"bytes,2,rep,name=members" json:"members,omitempty"`
} }
func (m *MemberRemoveResponse) Reset() { *m = MemberRemoveResponse{} } func (m *MemberRemoveResponse) Reset() { *m = MemberRemoveResponse{} }
@ -1460,6 +1471,13 @@ func (m *MemberRemoveResponse) GetHeader() *ResponseHeader {
return nil return nil
} }
func (m *MemberRemoveResponse) GetMembers() []*Member {
if m != nil {
return m.Members
}
return nil
}
type MemberUpdateRequest struct { type MemberUpdateRequest struct {
// ID is the member ID of the member to update. // ID is the member ID of the member to update.
ID uint64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"` ID uint64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
@ -1474,6 +1492,8 @@ func (*MemberUpdateRequest) Descriptor() ([]byte, []int) { return fileDescriptor
type MemberUpdateResponse struct { type MemberUpdateResponse struct {
Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"` Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
// members is a list of all members after updating the member.
Members []*Member `protobuf:"bytes,2,rep,name=members" json:"members,omitempty"`
} }
func (m *MemberUpdateResponse) Reset() { *m = MemberUpdateResponse{} } func (m *MemberUpdateResponse) Reset() { *m = MemberUpdateResponse{} }
@ -1488,6 +1508,13 @@ func (m *MemberUpdateResponse) GetHeader() *ResponseHeader {
return nil return nil
} }
func (m *MemberUpdateResponse) GetMembers() []*Member {
if m != nil {
return m.Members
}
return nil
}
type MemberListRequest struct { type MemberListRequest struct {
} }
@ -5186,6 +5213,18 @@ func (m *MemberAddResponse) MarshalTo(dAtA []byte) (int, error) {
} }
i += n29 i += n29
} }
if len(m.Members) > 0 {
for _, msg := range m.Members {
dAtA[i] = 0x1a
i++
i = encodeVarintRpc(dAtA, i, uint64(msg.Size()))
n, err := msg.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n
}
}
return i, nil return i, nil
} }
@ -5237,6 +5276,18 @@ func (m *MemberRemoveResponse) MarshalTo(dAtA []byte) (int, error) {
} }
i += n30 i += n30
} }
if len(m.Members) > 0 {
for _, msg := range m.Members {
dAtA[i] = 0x12
i++
i = encodeVarintRpc(dAtA, i, uint64(msg.Size()))
n, err := msg.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n
}
}
return i, nil return i, nil
} }
@ -5303,6 +5354,18 @@ func (m *MemberUpdateResponse) MarshalTo(dAtA []byte) (int, error) {
} }
i += n31 i += n31
} }
if len(m.Members) > 0 {
for _, msg := range m.Members {
dAtA[i] = 0x12
i++
i = encodeVarintRpc(dAtA, i, uint64(msg.Size()))
n, err := msg.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n
}
}
return i, nil return i, nil
} }
@ -7176,6 +7239,12 @@ func (m *MemberAddResponse) Size() (n int) {
l = m.Member.Size() l = m.Member.Size()
n += 1 + l + sovRpc(uint64(l)) n += 1 + l + sovRpc(uint64(l))
} }
if len(m.Members) > 0 {
for _, e := range m.Members {
l = e.Size()
n += 1 + l + sovRpc(uint64(l))
}
}
return n return n
} }
@ -7195,6 +7264,12 @@ func (m *MemberRemoveResponse) Size() (n int) {
l = m.Header.Size() l = m.Header.Size()
n += 1 + l + sovRpc(uint64(l)) n += 1 + l + sovRpc(uint64(l))
} }
if len(m.Members) > 0 {
for _, e := range m.Members {
l = e.Size()
n += 1 + l + sovRpc(uint64(l))
}
}
return n return n
} }
@ -7220,6 +7295,12 @@ func (m *MemberUpdateResponse) Size() (n int) {
l = m.Header.Size() l = m.Header.Size()
n += 1 + l + sovRpc(uint64(l)) n += 1 + l + sovRpc(uint64(l))
} }
if len(m.Members) > 0 {
for _, e := range m.Members {
l = e.Size()
n += 1 + l + sovRpc(uint64(l))
}
}
return n return n
} }
@ -11949,6 +12030,37 @@ func (m *MemberAddResponse) Unmarshal(dAtA []byte) error {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Members", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthRpc
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Members = append(m.Members, &Member{})
if err := m.Members[len(m.Members)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipRpc(dAtA[iNdEx:]) skippy, err := skipRpc(dAtA[iNdEx:])
@ -12101,6 +12213,37 @@ func (m *MemberRemoveResponse) Unmarshal(dAtA []byte) error {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Members", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthRpc
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Members = append(m.Members, &Member{})
if err := m.Members[len(m.Members)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipRpc(dAtA[iNdEx:]) skippy, err := skipRpc(dAtA[iNdEx:])
@ -12282,6 +12425,37 @@ func (m *MemberUpdateResponse) Unmarshal(dAtA []byte) error {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Members", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthRpc
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Members = append(m.Members, &Member{})
if err := m.Members[len(m.Members)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipRpc(dAtA[iNdEx:]) skippy, err := skipRpc(dAtA[iNdEx:])
@ -16114,220 +16288,220 @@ var (
func init() { proto.RegisterFile("rpc.proto", fileDescriptorRpc) } func init() { proto.RegisterFile("rpc.proto", fileDescriptorRpc) }
var fileDescriptorRpc = []byte{ var fileDescriptorRpc = []byte{
// 3431 bytes of a gzipped FileDescriptorProto // 3436 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x5b, 0xcd, 0x73, 0x1b, 0xc7, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x3b, 0x5b, 0x6f, 0x1b, 0xc7,
0xb1, 0xe7, 0x02, 0x04, 0x40, 0x34, 0x3e, 0x08, 0x0d, 0x29, 0x09, 0x84, 0x24, 0x8a, 0x1a, 0x7d, 0xb9, 0x5a, 0x5e, 0xc5, 0x8f, 0x17, 0xd1, 0x23, 0xd9, 0xa6, 0x68, 0x5b, 0x96, 0xc7, 0x37, 0xd9,
0x51, 0x92, 0x4d, 0xda, 0xb4, 0xdf, 0x3b, 0xe8, 0xb9, 0x5c, 0x8f, 0x22, 0x61, 0x91, 0x8f, 0x14, 0x4e, 0xa4, 0x44, 0xc9, 0x39, 0x0f, 0x3e, 0x41, 0x70, 0x64, 0x89, 0xb1, 0x74, 0x24, 0x4b, 0xce,
0x29, 0x2f, 0x29, 0xd9, 0xaf, 0xca, 0x15, 0xd4, 0x12, 0x18, 0x81, 0x5b, 0x04, 0x76, 0xe1, 0xdd, 0x4a, 0x76, 0x72, 0x80, 0xa0, 0xc4, 0x8a, 0x1c, 0x53, 0x0b, 0x91, 0xbb, 0xcc, 0xee, 0x92, 0x96,
0x05, 0x44, 0x3a, 0x49, 0x55, 0xca, 0xb1, 0x2b, 0x95, 0x1c, 0xe3, 0x43, 0xbe, 0x8e, 0xa9, 0x1c, 0xd2, 0x14, 0x28, 0xd2, 0x04, 0x45, 0xfb, 0xd8, 0x3c, 0xf4, 0xf6, 0x58, 0x14, 0x45, 0x7e, 0x40,
0xfc, 0x07, 0xe4, 0x96, 0x3f, 0x20, 0x95, 0x4b, 0x52, 0x95, 0x7f, 0x20, 0xe5, 0xe4, 0x90, 0x43, 0xdf, 0xfa, 0x03, 0x8a, 0xbe, 0xb4, 0x40, 0xff, 0x40, 0x91, 0xf6, 0xa1, 0x0f, 0x7d, 0xef, 0x53,
0xee, 0x39, 0xa5, 0x92, 0x9a, 0xaf, 0xdd, 0xd9, 0xc5, 0x2e, 0x28, 0x67, 0xe3, 0x8b, 0xb8, 0xd3, 0xd1, 0x62, 0x6e, 0xbb, 0xb3, 0xcb, 0x5d, 0x4a, 0x29, 0x9b, 0xbc, 0x58, 0x3b, 0xdf, 0x7c, 0xf3,
0xd3, 0xd3, 0xbf, 0x9e, 0x9e, 0xe9, 0x9e, 0x9e, 0x1e, 0x08, 0x8a, 0xce, 0xa0, 0xbd, 0x32, 0x70, 0xdd, 0x66, 0xbe, 0xcb, 0x7c, 0x43, 0x43, 0xc1, 0xe9, 0xb7, 0x96, 0xfb, 0x8e, 0xed, 0xd9, 0xa8,
0x6c, 0xcf, 0x46, 0x65, 0xe2, 0xb5, 0x3b, 0x2e, 0x71, 0x46, 0xc4, 0x19, 0x1c, 0x35, 0xe6, 0xbb, 0x44, 0xbc, 0x56, 0xdb, 0x25, 0xce, 0x90, 0x38, 0xfd, 0xc3, 0xfa, 0x5c, 0xc7, 0xee, 0xd8, 0x6c,
0x76, 0xd7, 0x66, 0x1d, 0xab, 0xf4, 0x8b, 0xf3, 0x34, 0x16, 0x28, 0xcf, 0x6a, 0x7f, 0xd4, 0x6e, 0x62, 0x85, 0x7e, 0x71, 0x9c, 0xfa, 0x3c, 0xc5, 0x59, 0xe9, 0x0d, 0x5b, 0x2d, 0xf6, 0x4f, 0xff,
0xb3, 0x7f, 0x06, 0x47, 0xab, 0x27, 0x23, 0xd1, 0x75, 0x85, 0x75, 0x19, 0x43, 0xef, 0x98, 0xfd, 0x70, 0xe5, 0x78, 0x28, 0xa6, 0xae, 0xb0, 0x29, 0x63, 0xe0, 0x1d, 0xb1, 0x7f, 0xfa, 0x87, 0xec,
0x33, 0x38, 0x62, 0x7f, 0x44, 0xe7, 0xd5, 0xae, 0x6d, 0x77, 0x7b, 0x64, 0xd5, 0x18, 0x98, 0xab, 0x8f, 0x98, 0xbc, 0xda, 0xb1, 0xed, 0x4e, 0x97, 0xac, 0x18, 0x7d, 0x73, 0xc5, 0xb0, 0x2c, 0xdb,
0x86, 0x65, 0xd9, 0x9e, 0xe1, 0x99, 0xb6, 0xe5, 0xf2, 0x5e, 0xfc, 0xb9, 0x06, 0x55, 0x9d, 0xb8, 0x33, 0x3c, 0xd3, 0xb6, 0x5c, 0x3e, 0x8b, 0x3f, 0xd3, 0xa0, 0xa2, 0x13, 0xb7, 0x6f, 0x5b, 0x2e,
0x03, 0xdb, 0x72, 0xc9, 0x16, 0x31, 0x3a, 0xc4, 0x41, 0xd7, 0x00, 0xda, 0xbd, 0xa1, 0xeb, 0x11, 0xd9, 0x24, 0x46, 0x9b, 0x38, 0xe8, 0x1a, 0x40, 0xab, 0x3b, 0x70, 0x3d, 0xe2, 0x34, 0xcd, 0x76,
0xa7, 0x65, 0x76, 0xea, 0xda, 0x92, 0xb6, 0x3c, 0xad, 0x17, 0x05, 0x65, 0xbb, 0x83, 0xae, 0x40, 0x4d, 0x5b, 0xd4, 0x96, 0x32, 0x7a, 0x41, 0x40, 0xb6, 0xda, 0xe8, 0x0a, 0x14, 0x7a, 0xa4, 0x77,
0xb1, 0x4f, 0xfa, 0x47, 0xbc, 0x37, 0xc3, 0x7a, 0x67, 0x38, 0x61, 0xbb, 0x83, 0x1a, 0x30, 0xe3, 0xc8, 0x67, 0x53, 0x6c, 0x76, 0x9a, 0x03, 0xb6, 0xda, 0xa8, 0x0e, 0xd3, 0x0e, 0x19, 0x9a, 0xae,
0x90, 0x91, 0xe9, 0x9a, 0xb6, 0x55, 0xcf, 0x2e, 0x69, 0xcb, 0x59, 0xdd, 0x6f, 0xd3, 0x81, 0x8e, 0x69, 0x5b, 0xb5, 0xf4, 0xa2, 0xb6, 0x94, 0xd6, 0xfd, 0x31, 0x5d, 0xe8, 0x18, 0x2f, 0xbc, 0xa6,
0xf1, 0xc2, 0x6b, 0x79, 0xc4, 0xe9, 0xd7, 0xa7, 0xf9, 0x40, 0x4a, 0x38, 0x24, 0x4e, 0x1f, 0x7f, 0x47, 0x9c, 0x5e, 0x2d, 0xc3, 0x17, 0x52, 0xc0, 0x01, 0x71, 0x7a, 0xf8, 0xd3, 0x2c, 0x94, 0x74,
0x96, 0x83, 0xb2, 0x6e, 0x58, 0x5d, 0xa2, 0x93, 0x8f, 0x87, 0xc4, 0xf5, 0x50, 0x0d, 0xb2, 0x27, 0xc3, 0xea, 0x10, 0x9d, 0x7c, 0x38, 0x20, 0xae, 0x87, 0xaa, 0x90, 0x3e, 0x26, 0xa7, 0x8c, 0x7d,
0xe4, 0x8c, 0xc1, 0x97, 0x75, 0xfa, 0xc9, 0xc7, 0x5b, 0x5d, 0xd2, 0x22, 0x16, 0x07, 0x2e, 0xd3, 0x49, 0xa7, 0x9f, 0x7c, 0xbd, 0xd5, 0x21, 0x4d, 0x62, 0x71, 0xc6, 0x25, 0xba, 0xde, 0xea, 0x90,
0xf1, 0x56, 0x97, 0x34, 0xad, 0x0e, 0x9a, 0x87, 0x5c, 0xcf, 0xec, 0x9b, 0x9e, 0x40, 0xe5, 0x8d, 0x86, 0xd5, 0x46, 0x73, 0x90, 0xed, 0x9a, 0x3d, 0xd3, 0x13, 0x5c, 0xf9, 0x20, 0x24, 0x4e, 0x26,
0x90, 0x3a, 0xd3, 0x11, 0x75, 0x36, 0x00, 0x5c, 0xdb, 0xf1, 0x5a, 0xb6, 0xd3, 0x21, 0x4e, 0x3d, 0x22, 0xce, 0x3a, 0x80, 0x6b, 0x3b, 0x5e, 0xd3, 0x76, 0xda, 0xc4, 0xa9, 0x65, 0x17, 0xb5, 0xa5,
0xb7, 0xa4, 0x2d, 0x57, 0xd7, 0x6e, 0xad, 0xa8, 0x0b, 0xb1, 0xa2, 0x2a, 0xb4, 0x72, 0x60, 0x3b, 0xca, 0xea, 0xad, 0x65, 0x75, 0x23, 0x96, 0x55, 0x81, 0x96, 0xf7, 0x6d, 0xc7, 0xdb, 0xa3, 0xb8,
0xde, 0x3e, 0xe5, 0xd5, 0x8b, 0xae, 0xfc, 0x44, 0xef, 0x41, 0x89, 0x09, 0xf1, 0x0c, 0xa7, 0x4b, 0x7a, 0xc1, 0x95, 0x9f, 0xe8, 0x1d, 0x28, 0x32, 0x22, 0x9e, 0xe1, 0x74, 0x88, 0x57, 0xcb, 0x31,
0xbc, 0x7a, 0x9e, 0x49, 0xb9, 0x7d, 0x8e, 0x94, 0x43, 0xc6, 0xac, 0x33, 0x78, 0xfe, 0x8d, 0x30, 0x2a, 0xb7, 0xcf, 0xa0, 0x72, 0xc0, 0x90, 0x75, 0xc6, 0x9e, 0x7f, 0x23, 0x0c, 0x25, 0x97, 0x38,
0x94, 0x5d, 0xe2, 0x98, 0x46, 0xcf, 0xfc, 0xc4, 0x38, 0xea, 0x91, 0x7a, 0x61, 0x49, 0x5b, 0x9e, 0xa6, 0xd1, 0x35, 0x3f, 0x32, 0x0e, 0xbb, 0xa4, 0x96, 0x5f, 0xd4, 0x96, 0xa6, 0xf5, 0x10, 0x8c,
0xd1, 0x43, 0x34, 0x3a, 0xff, 0x13, 0x72, 0xe6, 0xb6, 0x6c, 0xab, 0x77, 0x56, 0x9f, 0x61, 0x0c, 0xea, 0x7f, 0x4c, 0x4e, 0xdd, 0xa6, 0x6d, 0x75, 0x4f, 0x6b, 0xd3, 0x0c, 0x61, 0x9a, 0x02, 0xf6,
0x33, 0x94, 0xb0, 0x6f, 0xf5, 0xce, 0xd8, 0xa2, 0xd9, 0x43, 0xcb, 0xe3, 0xbd, 0x45, 0xd6, 0x5b, 0xac, 0xee, 0x29, 0xdb, 0x34, 0x7b, 0x60, 0x79, 0x7c, 0xb6, 0xc0, 0x66, 0x0b, 0x0c, 0xc2, 0xa6,
0x64, 0x14, 0xd6, 0xbd, 0x0c, 0xb5, 0xbe, 0x69, 0xb5, 0xfa, 0x76, 0xa7, 0xe5, 0x1b, 0x04, 0x98, 0x97, 0xa0, 0xda, 0x33, 0xad, 0x66, 0xcf, 0x6e, 0x37, 0x7d, 0x83, 0x00, 0x33, 0x48, 0xa5, 0x67,
0x41, 0xaa, 0x7d, 0xd3, 0x7a, 0x62, 0x77, 0x74, 0x69, 0x16, 0xca, 0x69, 0x9c, 0x86, 0x39, 0x4b, 0x5a, 0x4f, 0xec, 0xb6, 0x2e, 0xcd, 0x42, 0x31, 0x8d, 0x93, 0x30, 0x66, 0x51, 0x60, 0x1a, 0x27,
0x82, 0xd3, 0x38, 0x55, 0x39, 0x57, 0x60, 0x8e, 0xca, 0x6c, 0x3b, 0xc4, 0xf0, 0x48, 0xc0, 0x5c, 0x2a, 0xe6, 0x32, 0xcc, 0x52, 0x9a, 0x2d, 0x87, 0x18, 0x1e, 0x09, 0x90, 0x4b, 0x0c, 0xf9, 0x42,
0x66, 0xcc, 0x17, 0xfa, 0xa6, 0xb5, 0xc1, 0x7a, 0x42, 0xfc, 0xc6, 0xe9, 0x18, 0x7f, 0x45, 0xf0, 0xcf, 0xb4, 0xd6, 0xd9, 0x4c, 0x08, 0xdf, 0x38, 0x19, 0xc1, 0x2f, 0x0b, 0x7c, 0xe3, 0x24, 0x8c,
0x1b, 0xa7, 0x61, 0x7e, 0xbc, 0x02, 0x45, 0xdf, 0xe6, 0x68, 0x06, 0xa6, 0xf7, 0xf6, 0xf7, 0x9a, 0x8f, 0x97, 0xa1, 0xe0, 0xdb, 0x1c, 0x4d, 0x43, 0x66, 0x77, 0x6f, 0xb7, 0x51, 0x9d, 0x42, 0x00,
0xb5, 0x29, 0x04, 0x90, 0x5f, 0x3f, 0xd8, 0x68, 0xee, 0x6d, 0xd6, 0x34, 0x54, 0x82, 0xc2, 0x66, 0xb9, 0xb5, 0xfd, 0xf5, 0xc6, 0xee, 0x46, 0x55, 0x43, 0x45, 0xc8, 0x6f, 0x34, 0xf8, 0x20, 0x85,
0x93, 0x37, 0x32, 0xf8, 0x11, 0x40, 0x60, 0x5d, 0x54, 0x80, 0xec, 0x4e, 0xf3, 0xff, 0x6b, 0x53, 0x1f, 0x01, 0x04, 0xd6, 0x45, 0x79, 0x48, 0x6f, 0x37, 0xfe, 0xbf, 0x3a, 0x45, 0x71, 0x9e, 0x37,
0x94, 0xe7, 0x79, 0x53, 0x3f, 0xd8, 0xde, 0xdf, 0xab, 0x69, 0x74, 0xf0, 0x86, 0xde, 0x5c, 0x3f, 0xf4, 0xfd, 0xad, 0xbd, 0xdd, 0xaa, 0x46, 0x17, 0xaf, 0xeb, 0x8d, 0xb5, 0x83, 0x46, 0x35, 0x45,
0x6c, 0xd6, 0x32, 0x94, 0xe3, 0xc9, 0xfe, 0x66, 0x2d, 0x8b, 0x8a, 0x90, 0x7b, 0xbe, 0xbe, 0xfb, 0x31, 0x9e, 0xec, 0x6d, 0x54, 0xd3, 0xa8, 0x00, 0xd9, 0xe7, 0x6b, 0x3b, 0xcf, 0x1a, 0xd5, 0x0c,
0xac, 0x59, 0x9b, 0xc6, 0x5f, 0x68, 0x50, 0x11, 0xeb, 0xc5, 0x7d, 0x02, 0xbd, 0x0d, 0xf9, 0x63, 0xfe, 0x5c, 0x83, 0xb2, 0xd8, 0x2f, 0xee, 0x13, 0xe8, 0x4d, 0xc8, 0x1d, 0x31, 0xbf, 0x60, 0x47,
0xe6, 0x17, 0x6c, 0x2b, 0x96, 0xd6, 0xae, 0x46, 0x16, 0x37, 0xe4, 0x3b, 0xba, 0xe0, 0x45, 0x18, 0xb1, 0xb8, 0x7a, 0x35, 0xb2, 0xb9, 0x21, 0xdf, 0xd1, 0x05, 0x2e, 0xc2, 0x90, 0x3e, 0x1e, 0xba,
0xb2, 0x27, 0x23, 0xb7, 0x9e, 0x59, 0xca, 0x2e, 0x97, 0xd6, 0x6a, 0x2b, 0xdc, 0x61, 0x57, 0x76, 0xb5, 0xd4, 0x62, 0x7a, 0xa9, 0xb8, 0x5a, 0x5d, 0xe6, 0x0e, 0xbb, 0xbc, 0x4d, 0x4e, 0x9f, 0x1b,
0xc8, 0xd9, 0x73, 0xa3, 0x37, 0x24, 0x3a, 0xed, 0x44, 0x08, 0xa6, 0xfb, 0xb6, 0x43, 0xd8, 0x8e, 0xdd, 0x01, 0xd1, 0xe9, 0x24, 0x42, 0x90, 0xe9, 0xd9, 0x0e, 0x61, 0x27, 0x76, 0x5a, 0x67, 0xdf,
0x9d, 0xd1, 0xd9, 0x37, 0xdd, 0xc6, 0x6c, 0xd1, 0xc4, 0x6e, 0xe5, 0x0d, 0xfc, 0xa5, 0x06, 0xf0, 0xf4, 0x18, 0xb3, 0x4d, 0x13, 0xa7, 0x95, 0x0f, 0xf0, 0x17, 0x1a, 0xc0, 0xd3, 0x81, 0x97, 0xec,
0x74, 0xe8, 0x25, 0xbb, 0xc6, 0x3c, 0xe4, 0x46, 0x54, 0xb0, 0x70, 0x0b, 0xde, 0x60, 0x3e, 0x41, 0x1a, 0x73, 0x90, 0x1d, 0x52, 0xc2, 0xc2, 0x2d, 0xf8, 0x80, 0xf9, 0x04, 0x31, 0x5c, 0xe2, 0xfb,
0x0c, 0x97, 0xf8, 0x3e, 0x41, 0x1b, 0xe8, 0x32, 0x14, 0x06, 0x0e, 0x19, 0xb5, 0x4e, 0x46, 0x0c, 0x04, 0x1d, 0xa0, 0xcb, 0x90, 0xef, 0x3b, 0x64, 0xd8, 0x3c, 0x1e, 0x32, 0x26, 0xd3, 0x7a, 0x8e,
0x64, 0x46, 0xcf, 0xd3, 0xe6, 0xce, 0x08, 0xdd, 0x80, 0xb2, 0xd9, 0xb5, 0x6c, 0x87, 0xb4, 0xb8, 0x0e, 0xb7, 0x87, 0xe8, 0x06, 0x94, 0xcc, 0x8e, 0x65, 0x3b, 0xa4, 0xc9, 0x69, 0x65, 0xd9, 0x6c,
0xac, 0x1c, 0xeb, 0x2d, 0x71, 0x1a, 0xd3, 0x5b, 0x61, 0xe1, 0x82, 0xf3, 0x2a, 0xcb, 0x2e, 0x25, 0x91, 0xc3, 0x98, 0xdc, 0x0a, 0x0a, 0x27, 0x9c, 0x53, 0x51, 0x76, 0x28, 0x08, 0x5b, 0x50, 0x64,
0x61, 0x0b, 0x4a, 0x4c, 0xd5, 0x54, 0xe6, 0xbb, 0x17, 0xe8, 0x98, 0x61, 0xc3, 0xc6, 0x4d, 0x28, 0xa2, 0x4e, 0x64, 0xbe, 0x7b, 0x81, 0x8c, 0x29, 0xb6, 0x6c, 0xd4, 0x84, 0x42, 0x6a, 0xfc, 0x01,
0xb4, 0xc6, 0x1f, 0x01, 0xda, 0x24, 0x3d, 0xe2, 0x91, 0x34, 0xd1, 0x43, 0xb1, 0x49, 0x56, 0xb5, 0xa0, 0x0d, 0xd2, 0x25, 0x1e, 0x99, 0x24, 0x7a, 0x28, 0x36, 0x49, 0xab, 0x36, 0xc1, 0x3f, 0xd2,
0x09, 0xfe, 0xb1, 0x06, 0x73, 0x21, 0xf1, 0xa9, 0xa6, 0x55, 0x87, 0x42, 0x87, 0x09, 0xe3, 0x1a, 0x60, 0x36, 0x44, 0x7e, 0x22, 0xb5, 0x6a, 0x90, 0x6f, 0x33, 0x62, 0x5c, 0x82, 0xb4, 0x2e, 0x87,
0x64, 0x75, 0xd9, 0x44, 0x0f, 0x60, 0x46, 0x28, 0xe0, 0xd6, 0xb3, 0x09, 0x9b, 0xa6, 0xc0, 0x75, 0xe8, 0x01, 0x4c, 0x0b, 0x01, 0xdc, 0x5a, 0x3a, 0xe1, 0xd0, 0xe4, 0xb9, 0x4c, 0x2e, 0xfe, 0x9b,
0x72, 0xf1, 0xdf, 0x34, 0x28, 0x8a, 0x89, 0xee, 0x0f, 0xd0, 0x3a, 0x54, 0x1c, 0xde, 0x68, 0xb1, 0x06, 0x05, 0xa1, 0xe8, 0x5e, 0x1f, 0xad, 0x41, 0xd9, 0xe1, 0x83, 0x26, 0xd3, 0x47, 0x48, 0x54,
0xf9, 0x08, 0x8d, 0x1a, 0xc9, 0x41, 0x68, 0x6b, 0x4a, 0x2f, 0x8b, 0x21, 0x8c, 0x8c, 0xfe, 0x07, 0x4f, 0x0e, 0x42, 0x9b, 0x53, 0x7a, 0x49, 0x2c, 0x61, 0x60, 0xf4, 0x3f, 0x50, 0x94, 0x24, 0xfa,
0x4a, 0x52, 0xc4, 0x60, 0xe8, 0x09, 0x93, 0xd7, 0xc3, 0x02, 0x82, 0xfd, 0xb7, 0x35, 0xa5, 0x83, 0x03, 0x4f, 0x98, 0xbc, 0x16, 0x26, 0x10, 0x9c, 0xbf, 0xcd, 0x29, 0x1d, 0x04, 0xfa, 0xd3, 0x81,
0x60, 0x7f, 0x3a, 0xf4, 0xd0, 0x21, 0xcc, 0xcb, 0xc1, 0x7c, 0x36, 0x42, 0x8d, 0x2c, 0x93, 0xb2, 0x87, 0x0e, 0x60, 0x4e, 0x2e, 0xe6, 0xda, 0x08, 0x31, 0xd2, 0x8c, 0xca, 0x62, 0x98, 0xca, 0xe8,
0x14, 0x96, 0x32, 0xbe, 0x54, 0x5b, 0x53, 0x3a, 0x12, 0xe3, 0x95, 0xce, 0x47, 0x45, 0x28, 0x08, 0x56, 0x6d, 0x4e, 0xe9, 0x48, 0xac, 0x57, 0x26, 0x1f, 0x15, 0x20, 0x2f, 0xa0, 0xf8, 0xef, 0x1a,
0x2a, 0xfe, 0xbb, 0x06, 0x20, 0x0d, 0xba, 0x3f, 0x40, 0x9b, 0x50, 0x75, 0x44, 0x2b, 0x34, 0xe1, 0x80, 0x34, 0xe8, 0x5e, 0x1f, 0x6d, 0x40, 0xc5, 0x11, 0xa3, 0x90, 0xc2, 0x57, 0x62, 0x15, 0x16,
0x2b, 0xb1, 0x13, 0x16, 0xeb, 0x30, 0xa5, 0x57, 0xe4, 0x20, 0x3e, 0xe5, 0x77, 0xa1, 0xec, 0x4b, 0xfb, 0x30, 0xa5, 0x97, 0xe5, 0x22, 0xae, 0xf2, 0xdb, 0x50, 0xf2, 0xa9, 0x04, 0x3a, 0xcf, 0xc7,
0x09, 0xe6, 0xbc, 0x10, 0x33, 0x67, 0x5f, 0x42, 0x49, 0x0e, 0xa0, 0xb3, 0xfe, 0x00, 0x2e, 0xfa, 0xe8, 0xec, 0x53, 0x28, 0xca, 0x05, 0x54, 0xeb, 0xf7, 0xe0, 0xa2, 0xbf, 0x3e, 0x46, 0xed, 0x1b,
0xe3, 0x63, 0xa6, 0x7d, 0x63, 0xc2, 0xb4, 0x7d, 0x81, 0x73, 0x52, 0x82, 0x3a, 0x71, 0xa0, 0x47, 0x63, 0xd4, 0xf6, 0x09, 0xce, 0x4a, 0x0a, 0xaa, 0xe2, 0x40, 0x53, 0x16, 0x07, 0xe3, 0x2f, 0xd2,
0x16, 0x27, 0xe3, 0x2f, 0xb3, 0x50, 0xd8, 0xb0, 0xfb, 0x03, 0xc3, 0xa1, 0x6b, 0x94, 0x77, 0x88, 0x90, 0x5f, 0xb7, 0x7b, 0x7d, 0xc3, 0xa1, 0x7b, 0x94, 0x73, 0x88, 0x3b, 0xe8, 0x7a, 0x4c, 0xdd,
0x3b, 0xec, 0x79, 0x6c, 0xba, 0xd5, 0xb5, 0x9b, 0x61, 0x04, 0xc1, 0x26, 0xff, 0xea, 0x8c, 0x55, 0xca, 0xea, 0xcd, 0x30, 0x07, 0x81, 0x26, 0xff, 0xea, 0x0c, 0x55, 0x17, 0x4b, 0xe8, 0x62, 0x91,
0x17, 0x43, 0xe8, 0x60, 0x71, 0x42, 0x65, 0x5e, 0x61, 0xb0, 0x38, 0x9f, 0xc4, 0x10, 0xe9, 0x4b, 0xa1, 0x52, 0xe7, 0x58, 0x2c, 0xf2, 0x93, 0x58, 0x22, 0x7d, 0x29, 0x1d, 0xf8, 0x52, 0x1d, 0xf2,
0xd9, 0xc0, 0x97, 0x1a, 0x50, 0x18, 0x11, 0x27, 0x38, 0x55, 0xb7, 0xa6, 0x74, 0x49, 0x40, 0xf7, 0x43, 0xe2, 0x04, 0x59, 0x75, 0x73, 0x4a, 0x97, 0x00, 0x74, 0x0f, 0x66, 0xa2, 0x11, 0x3e, 0x2b,
0x60, 0x36, 0x1a, 0xe1, 0x73, 0x82, 0xa7, 0xda, 0x0e, 0x1f, 0x08, 0x37, 0xa1, 0x1c, 0x3a, 0x66, 0x70, 0x2a, 0xad, 0x70, 0x42, 0xb8, 0x09, 0xa5, 0x50, 0x9a, 0xc9, 0x09, 0xbc, 0x62, 0x4f, 0xc9,
0xf2, 0x82, 0xaf, 0xd4, 0x57, 0x4e, 0x99, 0x4b, 0x32, 0xb4, 0xd1, 0x23, 0xb1, 0xbc, 0x35, 0x25, 0x32, 0x97, 0x64, 0x68, 0xa3, 0x29, 0xb1, 0xb4, 0x39, 0x25, 0x82, 0x1b, 0xfe, 0x5f, 0x28, 0x87,
0x82, 0x1b, 0xfe, 0x5f, 0xa8, 0x84, 0xe6, 0x4a, 0xa3, 0x78, 0xf3, 0xfd, 0x67, 0xeb, 0xbb, 0x3c, 0x74, 0xa5, 0x51, 0xbc, 0xf1, 0xee, 0xb3, 0xb5, 0x1d, 0x1e, 0xf2, 0x1f, 0xb3, 0x28, 0xaf, 0x57,
0xe4, 0x3f, 0x66, 0x51, 0x5e, 0xaf, 0x69, 0xf4, 0xe4, 0xd8, 0x6d, 0x1e, 0x1c, 0xd4, 0x32, 0xa8, 0x35, 0x9a, 0x39, 0x76, 0x1a, 0xfb, 0xfb, 0xd5, 0x14, 0x2a, 0x43, 0x61, 0x77, 0xef, 0xa0, 0xc9,
0x02, 0xc5, 0xbd, 0xfd, 0xc3, 0x16, 0xe7, 0xca, 0xe2, 0x77, 0x7c, 0x09, 0xe2, 0xc8, 0x50, 0x4e, 0xb1, 0xd2, 0xf8, 0x2d, 0x9f, 0x82, 0x48, 0x19, 0x4a, 0xa6, 0x98, 0x52, 0x32, 0x85, 0x26, 0x33,
0x8a, 0x29, 0xe5, 0xa4, 0xd0, 0xe4, 0x49, 0x91, 0x09, 0x4e, 0x8a, 0xec, 0xa3, 0x2a, 0x94, 0xb9, 0x45, 0x2a, 0xc8, 0x14, 0xe9, 0x47, 0x15, 0x28, 0x71, 0xfb, 0x34, 0x07, 0x16, 0xcd, 0x56, 0xbf,
0x7d, 0x5a, 0x43, 0x8b, 0x9e, 0x56, 0xbf, 0xd4, 0x00, 0x0e, 0x4f, 0x2d, 0x19, 0x80, 0x56, 0xa1, 0xd0, 0x00, 0x0e, 0x4e, 0x2c, 0x19, 0x80, 0x56, 0x20, 0xdf, 0xe2, 0xc4, 0x6b, 0x1a, 0xf3, 0xe7,
0xd0, 0xe6, 0xc2, 0xeb, 0x1a, 0xf3, 0xe7, 0x8b, 0xb1, 0x26, 0xd7, 0x25, 0x17, 0x7a, 0x13, 0x0a, 0x8b, 0xb1, 0x26, 0xd7, 0x25, 0x16, 0x7a, 0x1d, 0xf2, 0xee, 0xa0, 0xd5, 0x22, 0xae, 0xcc, 0x1a,
0xee, 0xb0, 0xdd, 0x26, 0xae, 0x3c, 0x35, 0x2e, 0x47, 0x43, 0x8a, 0x70, 0x78, 0x5d, 0xf2, 0xd1, 0x97, 0xa3, 0x21, 0x45, 0x38, 0xbc, 0x2e, 0xf1, 0xe8, 0x92, 0x17, 0x86, 0xd9, 0x1d, 0xb0, 0x1c,
0x21, 0x2f, 0x0c, 0xb3, 0x37, 0x64, 0x67, 0xc8, 0xe4, 0x21, 0x82, 0x0f, 0xff, 0x4c, 0x83, 0x12, 0x32, 0x7e, 0x89, 0xc0, 0xc3, 0x3f, 0xd5, 0xa0, 0xc8, 0xa4, 0x9c, 0x28, 0x8e, 0x5d, 0x85, 0x02,
0xd3, 0x32, 0x55, 0x1c, 0xbb, 0x0a, 0x45, 0xa6, 0x03, 0xe9, 0x88, 0x48, 0x36, 0xa3, 0x07, 0x04, 0x93, 0x81, 0xb4, 0x45, 0x24, 0x9b, 0xd6, 0x03, 0x00, 0xfa, 0x6f, 0x28, 0xc8, 0x13, 0x2c, 0x83,
0xf4, 0xdf, 0x50, 0x94, 0x3b, 0x58, 0x06, 0xb3, 0x7a, 0xbc, 0xd8, 0xfd, 0x81, 0x1e, 0xb0, 0xe2, 0x59, 0x2d, 0x9e, 0xec, 0x5e, 0x5f, 0x0f, 0x50, 0xf1, 0x36, 0x5c, 0x60, 0x56, 0x69, 0xd1, 0xfa,
0x1d, 0xb8, 0xc0, 0xac, 0xd2, 0xa6, 0xf9, 0xa9, 0xb4, 0xa3, 0x9a, 0xc1, 0x69, 0x91, 0x0c, 0xae, 0x54, 0xda, 0x51, 0xad, 0xe0, 0xb4, 0x48, 0x05, 0x57, 0x87, 0xe9, 0xfe, 0xd1, 0xa9, 0x6b, 0xb6,
0x01, 0x33, 0x83, 0xe3, 0x33, 0xd7, 0x6c, 0x1b, 0x3d, 0xa1, 0x85, 0xdf, 0xc6, 0xff, 0x07, 0x48, 0x8c, 0xae, 0x90, 0xc2, 0x1f, 0xe3, 0xff, 0x03, 0xa4, 0x12, 0x9b, 0x44, 0x5d, 0x5c, 0x86, 0xe2,
0x15, 0x96, 0x66, 0xba, 0xb8, 0x02, 0xa5, 0x2d, 0xc3, 0x3d, 0x16, 0x2a, 0xe1, 0x0f, 0xa1, 0xcc, 0xa6, 0xe1, 0x1e, 0x09, 0x91, 0xf0, 0xfb, 0x50, 0xe2, 0xc3, 0x89, 0x6c, 0x88, 0x20, 0x73, 0x64,
0x9b, 0xa9, 0x6c, 0x88, 0x60, 0xfa, 0xd8, 0x70, 0x8f, 0x99, 0xe2, 0x15, 0x9d, 0x7d, 0xe3, 0x0b, 0xb8, 0x47, 0x4c, 0xf0, 0xb2, 0xce, 0xbe, 0xf1, 0x05, 0x98, 0xd9, 0xb7, 0x8c, 0xbe, 0x7b, 0x64,
0x30, 0x7b, 0x60, 0x19, 0x03, 0xf7, 0xd8, 0x96, 0xb1, 0x96, 0xe6, 0xe7, 0xb5, 0x80, 0x96, 0x0a, 0xcb, 0x58, 0x4b, 0xeb, 0xf3, 0x6a, 0x00, 0x9b, 0x88, 0xe3, 0x5d, 0x98, 0x71, 0x48, 0xcf, 0x30,
0xf1, 0x2e, 0xcc, 0x3a, 0xa4, 0x6f, 0x98, 0x96, 0x69, 0x75, 0x5b, 0x47, 0x67, 0x1e, 0x71, 0x45, 0x2d, 0xd3, 0xea, 0x34, 0x0f, 0x4f, 0x3d, 0xe2, 0x8a, 0xf2, 0xbd, 0xe2, 0x83, 0x1f, 0x51, 0x28,
0xfa, 0x5e, 0xf5, 0xc9, 0x8f, 0x28, 0x95, 0xaa, 0x76, 0xd4, 0xb3, 0x8f, 0x84, 0xc7, 0xb3, 0x6f, 0x15, 0xed, 0xb0, 0x6b, 0x1f, 0x0a, 0x8f, 0x67, 0xdf, 0xf8, 0xd7, 0x1a, 0x94, 0xde, 0x33, 0xbc,
0xfc, 0x6b, 0x0d, 0xca, 0x1f, 0x18, 0x5e, 0x5b, 0x5a, 0x01, 0x6d, 0x43, 0xd5, 0xf7, 0x73, 0x46, 0x96, 0xb4, 0x02, 0xda, 0x82, 0x8a, 0xef, 0xe7, 0x0c, 0x22, 0x64, 0x89, 0x04, 0x7c, 0xb6, 0x46,
0x11, 0xba, 0x44, 0x02, 0x3e, 0x1b, 0x23, 0x13, 0x3b, 0x19, 0xf0, 0x2b, 0x6d, 0x95, 0xc0, 0x44, 0x16, 0x76, 0x32, 0xe0, 0x97, 0x5b, 0x2a, 0x80, 0x91, 0x32, 0xac, 0x16, 0xe9, 0xfa, 0xa4, 0x52,
0x19, 0x56, 0x9b, 0xf4, 0x7c, 0x51, 0x99, 0x64, 0x51, 0x8c, 0x51, 0x15, 0xa5, 0x12, 0x1e, 0xcd, 0xc9, 0xa4, 0x18, 0xa2, 0x4a, 0x4a, 0x05, 0x3c, 0x9a, 0x09, 0x92, 0x21, 0x77, 0xcb, 0x9f, 0xa5,
0x06, 0x87, 0x21, 0x77, 0xcb, 0x9f, 0x67, 0x00, 0x8d, 0xeb, 0xf0, 0x75, 0xf3, 0x83, 0xdb, 0x50, 0x00, 0x8d, 0xca, 0xf0, 0x55, 0xeb, 0x83, 0xdb, 0x50, 0x71, 0x3d, 0xc3, 0xf1, 0x9a, 0x91, 0xcb,
0x75, 0x3d, 0xc3, 0xf1, 0x5a, 0x91, 0xcb, 0x4d, 0x85, 0x51, 0xfd, 0x58, 0x75, 0x17, 0x66, 0x07, 0x4d, 0x99, 0x41, 0xfd, 0x58, 0x75, 0x17, 0x66, 0xfa, 0x8e, 0xdd, 0x71, 0x88, 0xeb, 0x36, 0x2d,
0x8e, 0xdd, 0x75, 0x88, 0xeb, 0xb6, 0x2c, 0xdb, 0x33, 0x5f, 0x9c, 0x89, 0x14, 0xab, 0x2a, 0xc9, 0xdb, 0x33, 0x5f, 0x9c, 0x8a, 0x12, 0xab, 0x22, 0xc1, 0xbb, 0x0c, 0x8a, 0x1a, 0x90, 0x7f, 0x61,
0x7b, 0x8c, 0x8a, 0x9a, 0x50, 0x78, 0x61, 0xf6, 0x3c, 0xe2, 0xb8, 0xf5, 0xdc, 0x52, 0x76, 0xb9, 0x76, 0x3d, 0xe2, 0xb8, 0xb5, 0xec, 0x62, 0x7a, 0xa9, 0xb2, 0xfa, 0xe0, 0x2c, 0xab, 0x2d, 0xbf,
0xba, 0xf6, 0xe0, 0x3c, 0xab, 0xad, 0xbc, 0xc7, 0xf8, 0x0f, 0xcf, 0x06, 0x44, 0x97, 0x63, 0xd5, 0xc3, 0xf0, 0x0f, 0x4e, 0xfb, 0x44, 0x97, 0x6b, 0xd5, 0xb2, 0x25, 0x17, 0x2a, 0x5b, 0x6e, 0x03,
0xb4, 0x25, 0x1f, 0x4a, 0x5b, 0x6e, 0x03, 0x04, 0xfc, 0x34, 0x6a, 0xed, 0xed, 0x3f, 0x7d, 0x76, 0x04, 0xf8, 0x34, 0x6a, 0xed, 0xee, 0x3d, 0x7d, 0x76, 0x50, 0x9d, 0x42, 0x25, 0x98, 0xde, 0xdd,
0x58, 0x9b, 0x42, 0x65, 0x98, 0xd9, 0xdb, 0xdf, 0x6c, 0xee, 0x36, 0x69, 0x5c, 0xc3, 0xab, 0xd2, 0xdb, 0x68, 0xec, 0x34, 0x68, 0x5c, 0xc3, 0x2b, 0xd2, 0x36, 0xaa, 0x0d, 0xd1, 0x3c, 0x4c, 0xbf,
0x36, 0xaa, 0x0d, 0xd1, 0x02, 0xcc, 0xbc, 0xa4, 0x54, 0x79, 0xfb, 0xcb, 0xea, 0x05, 0xd6, 0xde, 0xa4, 0x50, 0x79, 0xfb, 0x4b, 0xeb, 0x79, 0x36, 0xde, 0x6a, 0xe3, 0xbf, 0x6a, 0x50, 0x16, 0xa7,
0xee, 0xe0, 0xbf, 0x6a, 0x50, 0x11, 0xbb, 0x20, 0xd5, 0x56, 0x54, 0x21, 0x32, 0x21, 0x08, 0x9a, 0x60, 0xa2, 0xa3, 0xa8, 0xb2, 0x48, 0x85, 0x58, 0xd0, 0x1a, 0x89, 0x9f, 0x8e, 0xb6, 0x28, 0xc5,
0x23, 0xf1, 0xdd, 0xd1, 0x11, 0xa9, 0x98, 0x6c, 0x52, 0x77, 0xe7, 0x8b, 0x4d, 0x3a, 0xc2, 0xac, 0xe4, 0x90, 0xba, 0x3b, 0xdf, 0x6c, 0xd2, 0x16, 0x66, 0xf5, 0xc7, 0xe8, 0x1e, 0x54, 0x5b, 0xdc,
0x7e, 0x1b, 0xdd, 0x83, 0x5a, 0x9b, 0xbb, 0x7b, 0xe4, 0xd8, 0xd1, 0x67, 0x05, 0xdd, 0x5f, 0xa4, 0xdd, 0x23, 0x69, 0x47, 0x9f, 0x11, 0x70, 0x7f, 0x93, 0x6e, 0x43, 0x8e, 0x0c, 0x89, 0xe5, 0xb9,
0xdb, 0x90, 0x27, 0x23, 0x62, 0x79, 0x6e, 0xbd, 0xc4, 0x62, 0x53, 0x45, 0x26, 0x5a, 0x4d, 0x4a, 0xb5, 0x22, 0x8b, 0x4d, 0x65, 0x59, 0x68, 0x35, 0x28, 0x54, 0x17, 0x93, 0xf8, 0xbf, 0xe0, 0x02,
0xd5, 0x45, 0x27, 0xfe, 0x2f, 0xb8, 0xc0, 0x12, 0xda, 0xc7, 0x8e, 0x61, 0xa9, 0x99, 0xf7, 0xe1, 0x2b, 0x68, 0x1f, 0x3b, 0x86, 0xa5, 0x56, 0xde, 0x07, 0x07, 0x3b, 0xc2, 0x2a, 0xf4, 0x13, 0x55,
0xe1, 0xae, 0xb0, 0x0a, 0xfd, 0x44, 0x55, 0xc8, 0x6c, 0x6f, 0x8a, 0x39, 0x64, 0xb6, 0x37, 0xf1, 0x20, 0xb5, 0xb5, 0x21, 0x74, 0x48, 0x6d, 0x6d, 0xe0, 0x4f, 0x34, 0x40, 0xea, 0xba, 0x89, 0xcc,
0xa7, 0x1a, 0x20, 0x75, 0x5c, 0x2a, 0x33, 0x45, 0x84, 0x4b, 0xf8, 0x6c, 0x00, 0x3f, 0x0f, 0x39, 0x14, 0x21, 0x2e, 0xd9, 0xa7, 0x03, 0xf6, 0x73, 0x90, 0x25, 0x8e, 0x63, 0x3b, 0xcc, 0x20, 0x05,
0xe2, 0x38, 0xb6, 0xc3, 0x0c, 0x52, 0xd4, 0x79, 0x03, 0xdf, 0x12, 0x3a, 0xe8, 0x64, 0x64, 0x9f, 0x9d, 0x0f, 0xf0, 0x2d, 0x21, 0x83, 0x4e, 0x86, 0xf6, 0xb1, 0x7f, 0xe6, 0x39, 0x35, 0xcd, 0x17,
0xf8, 0x7b, 0x9e, 0x4b, 0xd3, 0x7c, 0x55, 0x77, 0x60, 0x2e, 0xc4, 0x95, 0x2a, 0x46, 0xde, 0x85, 0x75, 0x1b, 0x66, 0x43, 0x58, 0x13, 0xc5, 0xc8, 0xbb, 0x70, 0x91, 0x11, 0xdb, 0x26, 0xa4, 0xbf,
0x8b, 0x4c, 0xd8, 0x0e, 0x21, 0x83, 0xf5, 0x9e, 0x39, 0x4a, 0x44, 0x1d, 0xc0, 0xa5, 0x28, 0xe3, 0xd6, 0x35, 0x87, 0x89, 0x5c, 0xfb, 0x70, 0x29, 0x8a, 0xf8, 0xf5, 0xda, 0x08, 0xbf, 0x25, 0x38,
0x37, 0x6b, 0x23, 0xfc, 0x8e, 0x40, 0x3c, 0x34, 0xfb, 0xe4, 0xd0, 0xde, 0x4d, 0xd6, 0x8d, 0x06, 0x1e, 0x98, 0x3d, 0x72, 0x60, 0xef, 0x24, 0xcb, 0x46, 0x03, 0x1f, 0xbd, 0x50, 0x8b, 0x64, 0xc2,
0x3e, 0x7a, 0xa1, 0x16, 0x87, 0x09, 0xfb, 0xc6, 0xbf, 0xd2, 0xe0, 0xf2, 0xd8, 0xf0, 0x6f, 0x78, 0xbe, 0xf1, 0x2f, 0x35, 0xb8, 0x3c, 0xb2, 0xfc, 0x6b, 0xde, 0xd5, 0x05, 0x80, 0x0e, 0x3d, 0x3e,
0x55, 0x17, 0x01, 0xba, 0x74, 0xfb, 0x90, 0x0e, 0xed, 0xe0, 0x57, 0x41, 0x85, 0xe2, 0xeb, 0x49, 0xa4, 0x4d, 0x27, 0xf8, 0x55, 0x50, 0x81, 0xf8, 0x72, 0xd2, 0xd8, 0x51, 0x12, 0x72, 0x1e, 0x41,
0x63, 0x47, 0x59, 0xe8, 0x79, 0x0c, 0xf9, 0x27, 0xac, 0x0a, 0xa3, 0xcc, 0x6a, 0x5a, 0xce, 0xca, 0xee, 0x09, 0xeb, 0xc2, 0x28, 0x5a, 0x65, 0xa4, 0x56, 0x96, 0xd1, 0xe3, 0x77, 0xc3, 0x82, 0xce,
0x32, 0xfa, 0xfc, 0x6e, 0x58, 0xd4, 0xd9, 0x37, 0x3b, 0x3a, 0x09, 0x71, 0x9e, 0xe9, 0xbb, 0xfc, 0xbe, 0x59, 0xea, 0x24, 0xc4, 0x79, 0xa6, 0xef, 0xf0, 0x14, 0x5d, 0xd0, 0xfd, 0x31, 0xe5, 0xde,
0x88, 0x2e, 0xea, 0x7e, 0x9b, 0xa2, 0xb7, 0x7b, 0x26, 0xb1, 0x3c, 0xd6, 0x3b, 0xcd, 0x7a, 0x15, 0xea, 0x9a, 0xc4, 0xf2, 0xd8, 0x6c, 0x86, 0xcd, 0x2a, 0x10, 0xbc, 0x0c, 0x55, 0xce, 0x69, 0xad,
0x0a, 0x5e, 0x81, 0x1a, 0x47, 0x5a, 0xef, 0x74, 0x94, 0x63, 0xda, 0x97, 0xa7, 0x85, 0xe5, 0xe1, 0xdd, 0x56, 0xd2, 0xb4, 0x4f, 0x4f, 0x0b, 0xd3, 0xc3, 0xbf, 0xd2, 0xe0, 0x82, 0xb2, 0x60, 0x22,
0x97, 0x70, 0x41, 0xe1, 0x4f, 0x65, 0xba, 0xd7, 0x20, 0xcf, 0x4b, 0x4d, 0xe2, 0x84, 0x98, 0x0f, 0xdb, 0xbd, 0x02, 0x39, 0xde, 0x6b, 0x12, 0x29, 0x62, 0x2e, 0xbc, 0x8a, 0xb3, 0xd1, 0x05, 0x0e,
0x8f, 0xe2, 0x30, 0xba, 0xe0, 0xc1, 0xb7, 0x61, 0x4e, 0x50, 0x48, 0xdf, 0x8e, 0x5b, 0x75, 0x66, 0x5a, 0x86, 0x3c, 0xff, 0x92, 0x75, 0x48, 0x3c, 0xba, 0x44, 0xc2, 0xb7, 0x61, 0x56, 0x80, 0x48,
0x1f, 0xbc, 0x0b, 0xf3, 0x61, 0xb6, 0x54, 0x8e, 0xb0, 0x2e, 0x41, 0x9f, 0x0d, 0x3a, 0xca, 0x81, 0xcf, 0x8e, 0x3b, 0x26, 0xcc, 0xa0, 0xf8, 0x63, 0x98, 0x0b, 0xa3, 0x4d, 0xa4, 0x92, 0x22, 0x64,
0x13, 0x5d, 0x14, 0xd5, 0x60, 0x99, 0x88, 0xc1, 0x7c, 0x85, 0xa4, 0x88, 0x54, 0x0a, 0xcd, 0x49, 0xea, 0x3c, 0x42, 0xae, 0x49, 0x21, 0x9f, 0xf5, 0xdb, 0x4a, 0x46, 0x8b, 0xee, 0xba, 0xba, 0x23,
0xf3, 0xef, 0x9a, 0xae, 0x9f, 0x56, 0x7c, 0x02, 0x48, 0x25, 0xa6, 0x5a, 0x94, 0x15, 0x28, 0x70, 0xa9, 0xc8, 0x8e, 0xf8, 0x0a, 0x48, 0x12, 0xdf, 0xa8, 0x02, 0xb3, 0xf2, 0x38, 0xec, 0x98, 0xae,
0x83, 0xcb, 0xcc, 0x35, 0x7e, 0x55, 0x24, 0x13, 0x55, 0x68, 0x93, 0xbc, 0x70, 0x8c, 0x6e, 0x9f, 0x5f, 0xe7, 0x7c, 0x04, 0x48, 0x05, 0x7e, 0xd3, 0x02, 0x6d, 0x90, 0x17, 0x8e, 0xd1, 0xe9, 0x11,
0xf8, 0x91, 0x95, 0xe6, 0x6b, 0x2a, 0x31, 0xd5, 0x8c, 0x7f, 0xaf, 0x41, 0x79, 0xbd, 0x67, 0x38, 0x3f, 0xd4, 0xd3, 0x02, 0x52, 0x05, 0x4e, 0x14, 0x1c, 0x7f, 0xaf, 0x41, 0x69, 0xad, 0x6b, 0x38,
0x7d, 0x69, 0xfc, 0x77, 0x21, 0xcf, 0x13, 0x41, 0x71, 0x77, 0xba, 0x13, 0x16, 0xa3, 0xf2, 0xf2, 0x3d, 0xb9, 0x59, 0x6f, 0x43, 0x8e, 0x57, 0xa6, 0xe2, 0x32, 0x77, 0x27, 0x4c, 0x46, 0xc5, 0xe5,
0xc6, 0x3a, 0x4f, 0x1b, 0xc5, 0x28, 0xba, 0x58, 0xa2, 0xc2, 0xb9, 0x19, 0xa9, 0x78, 0x6e, 0xa2, 0x83, 0x35, 0x5e, 0xc7, 0x8a, 0x55, 0x74, 0x73, 0x45, 0xcb, 0x75, 0x23, 0xd2, 0x82, 0xdd, 0x40,
0xd7, 0x21, 0x67, 0xd0, 0x21, 0xcc, 0x7f, 0xab, 0xd1, 0x14, 0x9c, 0x49, 0x63, 0x87, 0x36, 0xe7, 0xaf, 0x42, 0xd6, 0xa0, 0x4b, 0x58, 0x40, 0xa9, 0x44, 0xef, 0x04, 0x8c, 0x1a, 0xab, 0x22, 0x38,
0xc2, 0x6f, 0x43, 0x49, 0x41, 0xa0, 0x37, 0x8b, 0xc7, 0x4d, 0x71, 0x30, 0xaf, 0x6f, 0x1c, 0x6e, 0x16, 0x7e, 0x13, 0x8a, 0x0a, 0x07, 0x7a, 0xd5, 0x79, 0xdc, 0x10, 0x95, 0xc2, 0xda, 0xfa, 0xc1,
0x3f, 0xe7, 0x17, 0x8e, 0x2a, 0xc0, 0x66, 0xd3, 0x6f, 0x67, 0xf0, 0x87, 0x62, 0x94, 0xf0, 0x70, 0xd6, 0x73, 0x7e, 0x03, 0xaa, 0x00, 0x6c, 0x34, 0xfc, 0x71, 0x0a, 0xbf, 0x2f, 0x56, 0x89, 0x90,
0x55, 0x1f, 0x2d, 0x49, 0x9f, 0xcc, 0x2b, 0xe9, 0x73, 0x0a, 0x15, 0x31, 0xfd, 0x54, 0x7b, 0xe0, 0xa3, 0xca, 0xa3, 0x25, 0xc9, 0x93, 0x3a, 0x97, 0x3c, 0x27, 0x50, 0x16, 0xea, 0x4f, 0x74, 0x06,
0x4d, 0xc8, 0x33, 0x79, 0x72, 0x0b, 0x2c, 0xc4, 0xc0, 0x4a, 0xef, 0xe4, 0x8c, 0x78, 0x16, 0x2a, 0x5e, 0x87, 0x1c, 0xa3, 0x27, 0x8f, 0xc0, 0x7c, 0x0c, 0x5b, 0x19, 0x2d, 0x38, 0x22, 0x9e, 0x81,
0x07, 0x9e, 0xe1, 0x0d, 0x5d, 0xb9, 0x05, 0x7e, 0xa7, 0x41, 0x55, 0x52, 0xd2, 0x96, 0x59, 0xe4, 0xf2, 0xbe, 0x67, 0x78, 0x03, 0x57, 0x1e, 0x81, 0xdf, 0x69, 0x50, 0x91, 0x90, 0x49, 0xfb, 0x3e,
0xf5, 0x94, 0xc7, 0x3c, 0xff, 0x72, 0x7a, 0x09, 0xf2, 0x9d, 0xa3, 0x03, 0xf3, 0x13, 0x59, 0x12, 0xf2, 0xbe, 0xcc, 0x83, 0xb0, 0x7f, 0x5b, 0xbe, 0x04, 0xb9, 0xf6, 0xe1, 0xbe, 0xf9, 0x91, 0xec,
0x13, 0x2d, 0x4a, 0xef, 0x71, 0x1c, 0x5e, 0x97, 0x16, 0x2d, 0x7a, 0xd1, 0x71, 0x8c, 0x17, 0xde, 0xd1, 0x89, 0x11, 0x85, 0x77, 0x39, 0x1f, 0xde, 0x28, 0x17, 0x23, 0x7a, 0xf3, 0x72, 0x8c, 0x17,
0xb6, 0xd5, 0x21, 0xa7, 0x2c, 0x9f, 0x98, 0xd6, 0x03, 0x02, 0xbb, 0x9b, 0x88, 0xfa, 0x35, 0xcb, 0xde, 0x96, 0xd5, 0x26, 0x27, 0xac, 0xc0, 0xc9, 0xe8, 0x01, 0x80, 0x5d, 0x96, 0x44, 0x43, 0x9d,
0xbf, 0xd4, 0x7a, 0xf6, 0x1c, 0x5c, 0x58, 0x1f, 0x7a, 0xc7, 0x4d, 0xcb, 0x38, 0xea, 0xc9, 0x20, 0x15, 0x84, 0x6a, 0x83, 0x7d, 0x16, 0x2e, 0xac, 0x0d, 0xbc, 0xa3, 0x86, 0x65, 0x1c, 0x76, 0x65,
0x80, 0xe7, 0x01, 0x51, 0xe2, 0xa6, 0xe9, 0xaa, 0xd4, 0x26, 0xcc, 0x51, 0x2a, 0xb1, 0x3c, 0xb3, 0xd0, 0xc0, 0x73, 0x80, 0x28, 0x70, 0xc3, 0x74, 0x55, 0x68, 0x03, 0x66, 0x29, 0x94, 0x58, 0x9e,
0xad, 0x44, 0x0c, 0x19, 0xb6, 0xb5, 0x48, 0xd8, 0x36, 0x5c, 0xf7, 0xa5, 0xed, 0x74, 0xc4, 0xd4, 0xd9, 0x52, 0x22, 0x8c, 0xcc, 0x23, 0x5a, 0x24, 0x8f, 0x18, 0xae, 0xfb, 0xd2, 0x76, 0xda, 0x42,
0xfc, 0x36, 0xde, 0xe4, 0xc2, 0x9f, 0xb9, 0xa1, 0xc0, 0xfc, 0x75, 0xa5, 0x2c, 0x07, 0x52, 0x1e, 0x35, 0x7f, 0x8c, 0x37, 0x38, 0xf1, 0x67, 0x6e, 0x28, 0x53, 0x7c, 0x55, 0x2a, 0x4b, 0x01, 0x95,
0x13, 0x6f, 0x82, 0x14, 0xfc, 0x00, 0x2e, 0x4a, 0x4e, 0x51, 0xbf, 0x98, 0xc0, 0xbc, 0x0f, 0xd7, 0xc7, 0xc4, 0x1b, 0x43, 0x05, 0x3f, 0x80, 0x8b, 0x12, 0x53, 0x34, 0x54, 0xc6, 0x20, 0xef, 0xc1,
0x24, 0xf3, 0xc6, 0x31, 0xcd, 0xaa, 0x9f, 0x0a, 0xc0, 0x7f, 0x57, 0xcf, 0x47, 0x50, 0xf7, 0xf5, 0x35, 0x89, 0xbc, 0x7e, 0x44, 0xcb, 0xfc, 0xa7, 0x82, 0xe1, 0xbf, 0x2b, 0xe7, 0x23, 0xa8, 0xf9,
0x64, 0x99, 0x96, 0xdd, 0x53, 0x15, 0x18, 0xba, 0x62, 0xcf, 0x14, 0x75, 0xf6, 0x4d, 0x69, 0x8e, 0x72, 0xb2, 0xd2, 0xcf, 0xee, 0xaa, 0x02, 0x0c, 0x5c, 0x71, 0x66, 0x0a, 0x3a, 0xfb, 0xa6, 0x30,
0xdd, 0xf3, 0x0f, 0x41, 0xfa, 0x8d, 0x37, 0x60, 0x41, 0xca, 0x10, 0x39, 0x50, 0x58, 0xc8, 0x98, 0xc7, 0xee, 0xfa, 0x59, 0x99, 0x7e, 0xe3, 0x75, 0x98, 0x97, 0x34, 0x44, 0x51, 0x16, 0x26, 0x32,
0x42, 0x71, 0x42, 0x84, 0xc1, 0xe8, 0xd0, 0xc9, 0x66, 0x57, 0x39, 0xc3, 0xa6, 0x65, 0x32, 0x35, 0x22, 0x50, 0x1c, 0x11, 0x61, 0x30, 0xba, 0x74, 0xbc, 0xd9, 0x55, 0xcc, 0xb0, 0x69, 0x19, 0x4d,
0x45, 0xe6, 0x45, 0xbe, 0x23, 0xa8, 0x62, 0x6a, 0xd0, 0x16, 0x64, 0x2a, 0x40, 0x25, 0x8b, 0x85, 0x4d, 0xa1, 0x79, 0x91, 0x9f, 0x08, 0x2a, 0x98, 0x1a, 0xb4, 0x05, 0x98, 0x12, 0x50, 0xc1, 0x62,
0xa0, 0xe4, 0xb1, 0x85, 0x18, 0x13, 0xfd, 0x11, 0x2c, 0xfa, 0x4a, 0x50, 0xbb, 0x3d, 0x25, 0x4e, 0x23, 0x28, 0x78, 0x64, 0x23, 0x46, 0x48, 0x7f, 0x00, 0x0b, 0xbe, 0x10, 0xd4, 0x6e, 0x4f, 0x89,
0xdf, 0x74, 0x5d, 0xe5, 0xc6, 0x1d, 0x37, 0xf1, 0x3b, 0x30, 0x3d, 0x20, 0x22, 0xa6, 0x94, 0xd6, 0xd3, 0x33, 0x5d, 0x57, 0x69, 0x01, 0xc4, 0x29, 0x7e, 0x07, 0x32, 0x7d, 0x22, 0x62, 0x4a, 0x71,
0xd0, 0x0a, 0x7f, 0x65, 0x5a, 0x51, 0x06, 0xb3, 0x7e, 0xdc, 0x81, 0xeb, 0x52, 0x3a, 0xb7, 0x68, 0x15, 0x2d, 0xf3, 0x67, 0xaf, 0x65, 0x65, 0x31, 0x9b, 0xc7, 0x6d, 0xb8, 0x2e, 0xa9, 0x73, 0x8b,
0xac, 0xf8, 0xa8, 0x52, 0xf2, 0x36, 0xc6, 0xcd, 0x3a, 0x7e, 0x1b, 0xcb, 0xf2, 0xb5, 0x97, 0xb7, 0xc6, 0x92, 0x8f, 0x0a, 0x25, 0xaf, 0x87, 0xdc, 0xac, 0xa3, 0xd7, 0xc3, 0x34, 0xdf, 0x7b, 0x79,
0x31, 0x7a, 0x56, 0xa8, 0xbe, 0x95, 0xea, 0xac, 0xd8, 0xe1, 0x36, 0xf5, 0x5d, 0x32, 0x95, 0xb0, 0x3d, 0xa4, 0xb9, 0x42, 0xf5, 0xad, 0x89, 0x72, 0xc5, 0x36, 0xb7, 0xa9, 0xef, 0x92, 0x13, 0x11,
0x23, 0x98, 0x0f, 0x7b, 0x72, 0xaa, 0x30, 0x36, 0x0f, 0x39, 0xcf, 0x3e, 0x21, 0x32, 0x88, 0xf1, 0x3b, 0x84, 0xb9, 0xb0, 0x27, 0x4f, 0x14, 0xc6, 0xe6, 0x20, 0xeb, 0xd9, 0xc7, 0x44, 0x06, 0x31,
0x86, 0x54, 0xd8, 0x77, 0xf3, 0x54, 0x0a, 0x1b, 0x81, 0x30, 0xb6, 0x25, 0xd3, 0xea, 0x4b, 0x57, 0x3e, 0x90, 0x02, 0xfb, 0x6e, 0x3e, 0x91, 0xc0, 0x46, 0x40, 0x8c, 0x1d, 0xc9, 0x49, 0xe5, 0xa5,
0x53, 0xe6, 0x33, 0xbc, 0x81, 0xf7, 0xe0, 0x52, 0x34, 0x4c, 0xa4, 0x52, 0xf9, 0x39, 0xdf, 0xc0, 0xbb, 0x29, 0xeb, 0x1f, 0x3e, 0xc0, 0xbb, 0x70, 0x29, 0x1a, 0x26, 0x26, 0x12, 0xf9, 0x39, 0x3f,
0x71, 0x91, 0x24, 0x95, 0xdc, 0xf7, 0x83, 0x60, 0xa0, 0x04, 0x94, 0x54, 0x22, 0x75, 0x68, 0xc4, 0xc0, 0x71, 0x91, 0x64, 0x22, 0xba, 0xef, 0x06, 0xc1, 0x40, 0x09, 0x28, 0x13, 0x91, 0xd4, 0xa1,
0xc5, 0x97, 0xff, 0xc4, 0x7e, 0xf5, 0xc3, 0x4d, 0x2a, 0x61, 0x6e, 0x20, 0x2c, 0xfd, 0xf2, 0x07, 0x1e, 0x17, 0x5f, 0xfe, 0x13, 0xe7, 0xd5, 0x0f, 0x37, 0x13, 0x11, 0x73, 0x03, 0x62, 0x93, 0x6f,
0x31, 0x22, 0x3b, 0x31, 0x46, 0x08, 0x27, 0x09, 0xa2, 0xd8, 0x37, 0xb0, 0xe9, 0x04, 0x46, 0x10, 0x7f, 0x10, 0x23, 0xd2, 0x63, 0x63, 0x84, 0x70, 0x92, 0x20, 0x8a, 0x7d, 0x0d, 0x87, 0x4e, 0xf0,
0x40, 0xd3, 0x62, 0xd0, 0x33, 0xc4, 0xc7, 0x60, 0x0d, 0xb9, 0xb1, 0xd5, 0xb0, 0x9b, 0x6a, 0x31, 0x08, 0x02, 0xe8, 0xa4, 0x3c, 0x68, 0x0e, 0xf1, 0x79, 0xb0, 0x81, 0x3c, 0xd8, 0x6a, 0xd8, 0x9d,
0x3e, 0x08, 0x62, 0xe7, 0x58, 0x64, 0x4e, 0x25, 0xf8, 0x43, 0x58, 0x4a, 0x0e, 0xca, 0x69, 0x24, 0x68, 0x33, 0xde, 0x0b, 0x62, 0xe7, 0x48, 0x64, 0x9e, 0x88, 0xf0, 0xfb, 0xb0, 0x98, 0x1c, 0x94,
0xdf, 0xc7, 0x50, 0xf4, 0x13, 0x4a, 0xe5, 0x85, 0xb6, 0x04, 0x85, 0xbd, 0xfd, 0x83, 0xa7, 0xeb, 0x27, 0xa1, 0x7c, 0x1f, 0x43, 0xc1, 0x2f, 0x28, 0x95, 0x27, 0xe3, 0x22, 0xe4, 0x77, 0xf7, 0xf6,
0x1b, 0xcd, 0x9a, 0xb6, 0xf6, 0x8f, 0x2c, 0x64, 0x76, 0x9e, 0xa3, 0x6f, 0x41, 0x8e, 0x3f, 0xbc, 0x9f, 0xae, 0xad, 0x37, 0xaa, 0xda, 0xea, 0x3f, 0xd2, 0x90, 0xda, 0x7e, 0x8e, 0xbe, 0x05, 0x59,
0x4c, 0x78, 0x97, 0x6a, 0x4c, 0x7a, 0xc2, 0xc1, 0x57, 0x3f, 0xfd, 0xe3, 0x5f, 0xbe, 0xc8, 0x5c, 0xfe, 0x12, 0x34, 0xe6, 0xa1, 0xac, 0x3e, 0xee, 0x4d, 0x09, 0x5f, 0xfd, 0xe4, 0x8f, 0x7f, 0xf9,
0xc2, 0x17, 0x56, 0x47, 0x6f, 0x19, 0xbd, 0xc1, 0xb1, 0xb1, 0x7a, 0x32, 0x5a, 0x65, 0x67, 0xc2, 0x3c, 0x75, 0x09, 0x5f, 0x58, 0x19, 0xbe, 0x61, 0x74, 0xfb, 0x47, 0xc6, 0xca, 0xf1, 0x70, 0x85,
0x43, 0xed, 0x3e, 0x7a, 0x0e, 0xd9, 0xa7, 0x43, 0x0f, 0x25, 0x3e, 0x5a, 0x35, 0x92, 0x9f, 0x76, 0xe5, 0x84, 0x87, 0xda, 0x7d, 0xf4, 0x1c, 0xd2, 0x4f, 0x07, 0x1e, 0x4a, 0x7c, 0x45, 0xab, 0x27,
0x70, 0x83, 0x49, 0x9e, 0xc7, 0xb3, 0xaa, 0xe4, 0xc1, 0xd0, 0xa3, 0x72, 0x47, 0x50, 0x52, 0x5e, 0xbf, 0x35, 0xe1, 0x3a, 0xa3, 0x3c, 0x87, 0x67, 0x54, 0xca, 0xfd, 0x81, 0x47, 0xe9, 0x0e, 0xa1,
0x67, 0xd0, 0xb9, 0xcf, 0x59, 0x8d, 0xf3, 0x5f, 0x7e, 0x30, 0x66, 0x78, 0x57, 0xf1, 0x65, 0x15, 0xa8, 0x3c, 0x17, 0xa1, 0x33, 0xdf, 0xd7, 0xea, 0x67, 0x3f, 0x45, 0x61, 0xcc, 0xf8, 0x5d, 0xc5,
0x8f, 0x3f, 0x22, 0xa9, 0xf3, 0x39, 0x3c, 0xb5, 0xa2, 0xf3, 0x09, 0x1e, 0x18, 0xa2, 0xf3, 0x51, 0x97, 0x55, 0x7e, 0xfc, 0x55, 0x4b, 0xd5, 0xe7, 0xe0, 0xc4, 0x8a, 0xea, 0x13, 0xbc, 0x78, 0x44,
0x8a, 0xfa, 0xf1, 0xf3, 0xf1, 0x4e, 0x2d, 0x2a, 0xd7, 0x16, 0x2f, 0x4a, 0x6d, 0x0f, 0x5d, 0x8f, 0xf5, 0x51, 0x5e, 0x19, 0xe2, 0xf5, 0xf1, 0x4e, 0x2c, 0x4a, 0xd7, 0x16, 0x4f, 0x5c, 0x2d, 0x0f,
0x79, 0x91, 0x50, 0x6b, 0xef, 0x8d, 0xa5, 0x64, 0x06, 0x81, 0x74, 0x83, 0x21, 0x5d, 0xc1, 0x97, 0x5d, 0x8f, 0x79, 0x22, 0x51, 0x1f, 0x03, 0xea, 0x8b, 0xc9, 0x08, 0x82, 0xd3, 0x0d, 0xc6, 0xe9,
0x54, 0xa4, 0xb6, 0xcf, 0xf7, 0x50, 0xbb, 0xbf, 0x76, 0x0c, 0x39, 0x56, 0x31, 0x44, 0x2d, 0xf9, 0x0a, 0xbe, 0xa4, 0x72, 0x6a, 0xf9, 0x78, 0x0f, 0xb5, 0xfb, 0xab, 0x47, 0x90, 0x65, 0x2d, 0x4c,
0xd1, 0x88, 0xa9, 0x75, 0x26, 0xec, 0x80, 0x50, 0xad, 0x11, 0x2f, 0x30, 0xb4, 0x39, 0x5c, 0xf5, 0xd4, 0x94, 0x1f, 0xf5, 0x98, 0xe6, 0x6b, 0xc2, 0x09, 0x08, 0x35, 0x3f, 0xf1, 0x3c, 0xe3, 0x36,
0xd1, 0x58, 0xd1, 0xf0, 0xa1, 0x76, 0x7f, 0x59, 0x7b, 0x43, 0x5b, 0xfb, 0xfe, 0x34, 0xe4, 0x58, 0x8b, 0x2b, 0x3e, 0x37, 0xd6, 0xc5, 0x7c, 0xa8, 0xdd, 0x5f, 0xd2, 0x5e, 0xd3, 0x56, 0xbf, 0x97,
0xa5, 0x06, 0x0d, 0x00, 0x82, 0x1a, 0x5c, 0x74, 0x9e, 0x63, 0x55, 0xbd, 0xe8, 0x3c, 0xc7, 0xcb, 0x81, 0x2c, 0x6b, 0x1d, 0xa1, 0x3e, 0x40, 0xd0, 0x14, 0x8c, 0xea, 0x39, 0xd2, 0x66, 0x8c, 0xea,
0x77, 0xf8, 0x3a, 0x43, 0x5e, 0xc0, 0xf3, 0x3e, 0x32, 0x7b, 0xff, 0x5e, 0x65, 0x35, 0x19, 0x6a, 0x39, 0xda, 0x4f, 0xc4, 0xd7, 0x19, 0xe7, 0x79, 0x3c, 0xe7, 0x73, 0x66, 0x0f, 0xf2, 0x2b, 0xac,
0xd6, 0x97, 0x50, 0x52, 0x6a, 0x69, 0x28, 0x4e, 0x62, 0xa8, 0x18, 0x17, 0xdd, 0x26, 0x31, 0x85, 0x49, 0x44, 0xcd, 0xfa, 0x12, 0x8a, 0x4a, 0x73, 0x0f, 0xc5, 0x51, 0x0c, 0x75, 0x07, 0xa3, 0xc7,
0x38, 0x7c, 0x93, 0x81, 0x5e, 0xc3, 0x75, 0xd5, 0xb8, 0x1c, 0xd7, 0x61, 0x9c, 0x14, 0xf8, 0x33, 0x24, 0xa6, 0x33, 0x88, 0x6f, 0x32, 0xa6, 0xd7, 0x70, 0x4d, 0x35, 0x2e, 0xe7, 0xeb, 0x30, 0x4c,
0x0d, 0xaa, 0xe1, 0x7a, 0x1a, 0xba, 0x19, 0x23, 0x3a, 0x5a, 0x96, 0x6b, 0xdc, 0x9a, 0xcc, 0x94, 0xca, 0xf8, 0x53, 0x0d, 0x2a, 0xe1, 0x06, 0x1f, 0xba, 0x19, 0x43, 0x3a, 0xda, 0x27, 0xac, 0xdf,
0xa8, 0x02, 0xc7, 0x3f, 0x21, 0x64, 0x60, 0x50, 0x4e, 0x61, 0x7b, 0xf4, 0x03, 0x0d, 0x66, 0x23, 0x1a, 0x8f, 0x94, 0x28, 0x02, 0xe7, 0x7f, 0x4c, 0x48, 0xdf, 0xa0, 0x98, 0xc2, 0xf6, 0xe8, 0xfb,
0x55, 0x32, 0x14, 0x07, 0x31, 0x56, 0x83, 0x6b, 0xdc, 0x3e, 0x87, 0x4b, 0x68, 0x72, 0x97, 0x69, 0x1a, 0xcc, 0x44, 0xda, 0x76, 0x28, 0x8e, 0xc5, 0x48, 0x53, 0xb0, 0x7e, 0xfb, 0x0c, 0x2c, 0x21,
0x72, 0x03, 0x5f, 0x1d, 0x37, 0x86, 0x67, 0xf6, 0x89, 0x67, 0x0b, 0x6d, 0xd6, 0xfe, 0x99, 0x85, 0xc9, 0x5d, 0x26, 0xc9, 0x0d, 0x7c, 0x75, 0xd4, 0x18, 0x9e, 0xd9, 0x23, 0x9e, 0x2d, 0xa4, 0x59,
0xc2, 0x06, 0xff, 0xb1, 0x12, 0xf2, 0xa0, 0xe8, 0x57, 0x9e, 0xd0, 0x62, 0x5c, 0x55, 0x22, 0x48, 0xfd, 0x67, 0x1a, 0xf2, 0xeb, 0xfc, 0xd7, 0x53, 0xc8, 0x83, 0x82, 0xdf, 0x09, 0x43, 0x0b, 0x71,
0xd9, 0x1b, 0xd7, 0x13, 0xfb, 0x85, 0x0a, 0x77, 0x98, 0x0a, 0x4b, 0xf8, 0x8a, 0xaf, 0x82, 0xf8, 0x5d, 0x89, 0xa0, 0x64, 0xaf, 0x5f, 0x4f, 0x9c, 0x17, 0x22, 0xdc, 0x61, 0x22, 0x2c, 0xe2, 0x2b,
0x51, 0xd4, 0x2a, 0xbf, 0x7c, 0xaf, 0x1a, 0x9d, 0x0e, 0x5d, 0x92, 0xef, 0x69, 0x50, 0x56, 0x0b, 0xbe, 0x08, 0xe2, 0x57, 0x5a, 0x2b, 0xfc, 0xf2, 0xbd, 0x62, 0xb4, 0xdb, 0x74, 0x4b, 0xbe, 0xab,
0x4a, 0xe8, 0x46, 0x6c, 0x3d, 0x44, 0xad, 0x49, 0x35, 0xf0, 0x24, 0x16, 0x81, 0x7f, 0x8f, 0xe1, 0x41, 0x49, 0x6d, 0x58, 0xa1, 0x1b, 0xb1, 0xfd, 0x10, 0xb5, 0xe7, 0x55, 0xc7, 0xe3, 0x50, 0x04,
0xdf, 0xc4, 0x8b, 0x49, 0xf8, 0x0e, 0xe3, 0x0f, 0xab, 0xc0, 0x4b, 0x48, 0xf1, 0x2a, 0x84, 0x2a, 0xff, 0x7b, 0x8c, 0xff, 0x4d, 0xbc, 0x90, 0xc4, 0xdf, 0x61, 0xf8, 0x61, 0x11, 0x78, 0xcb, 0x29,
0x54, 0xf1, 0x2a, 0x84, 0x2b, 0x50, 0xe7, 0xab, 0x30, 0x64, 0xfc, 0x54, 0x85, 0x53, 0x80, 0xa0, 0x5e, 0x84, 0x50, 0x47, 0x2b, 0x5e, 0x84, 0x70, 0xc7, 0xea, 0x6c, 0x11, 0x06, 0x0c, 0x9f, 0x8a,
0xc2, 0x84, 0x62, 0x8d, 0xab, 0x5c, 0x62, 0xa2, 0x3e, 0x38, 0x5e, 0x9c, 0x8a, 0xd9, 0x01, 0x11, 0x70, 0x02, 0x10, 0x74, 0x98, 0x50, 0xac, 0x71, 0x95, 0x4b, 0x4c, 0xd4, 0x07, 0x47, 0x9b, 0x53,
0xec, 0x9e, 0xe9, 0x52, 0x5f, 0x5c, 0xfb, 0xcd, 0x34, 0x94, 0x9e, 0x18, 0xa6, 0xe5, 0x11, 0xcb, 0x31, 0x27, 0x20, 0xc2, 0xbb, 0x6b, 0xba, 0xd4, 0x17, 0x57, 0x7f, 0x93, 0x81, 0xe2, 0x13, 0xc3,
0xb0, 0xda, 0x04, 0x75, 0x21, 0xc7, 0x4e, 0xa9, 0x68, 0xe0, 0x51, 0xcb, 0x3e, 0xd1, 0xc0, 0x13, 0xb4, 0x3c, 0x62, 0x19, 0x56, 0x8b, 0xa0, 0x0e, 0x64, 0x59, 0x96, 0x8a, 0x06, 0x1e, 0xb5, 0xed,
0xaa, 0x89, 0xe0, 0xdb, 0x0c, 0xfa, 0x3a, 0x6e, 0xf8, 0xd0, 0xfd, 0x40, 0xfe, 0x2a, 0xab, 0x67, 0x13, 0x0d, 0x3c, 0xa1, 0x9e, 0x08, 0xbe, 0xcd, 0x58, 0x5f, 0xc7, 0x75, 0x9f, 0x75, 0x2f, 0xa0,
0xd0, 0x29, 0x9f, 0x40, 0x9e, 0xd7, 0x2f, 0x50, 0x44, 0x5a, 0xa8, 0xce, 0xd1, 0xb8, 0x1a, 0xdf, 0xbf, 0xc2, 0xfa, 0x19, 0x54, 0xe5, 0x63, 0xc8, 0xf1, 0xfe, 0x05, 0x8a, 0x50, 0x0b, 0xf5, 0x39,
0x99, 0xb8, 0xcb, 0x54, 0x2c, 0x97, 0x31, 0x53, 0xb0, 0x6f, 0x03, 0x04, 0x05, 0xb3, 0xa8, 0x7d, 0xea, 0x57, 0xe3, 0x27, 0x13, 0x4f, 0x99, 0xca, 0xcb, 0x65, 0xc8, 0x94, 0xd9, 0xb7, 0x01, 0x82,
0xc7, 0xea, 0x6b, 0x8d, 0xa5, 0x64, 0x06, 0x01, 0x7c, 0x9f, 0x01, 0xdf, 0xc2, 0xd7, 0x63, 0x81, 0x86, 0x59, 0xd4, 0xbe, 0x23, 0xfd, 0xb5, 0xfa, 0x62, 0x32, 0x82, 0x60, 0x7c, 0x9f, 0x31, 0xbe,
0x3b, 0xfe, 0x00, 0x0a, 0xde, 0x86, 0xe9, 0x2d, 0xc3, 0x3d, 0x46, 0x91, 0x43, 0x48, 0x79, 0x25, 0x85, 0xaf, 0xc7, 0x32, 0x6e, 0xfb, 0x0b, 0x28, 0xf3, 0x16, 0x64, 0x36, 0x0d, 0xf7, 0x08, 0x45,
0x6d, 0x34, 0xe2, 0xba, 0x04, 0xd4, 0x2d, 0x06, 0xb5, 0x88, 0x17, 0x62, 0xa1, 0x8e, 0x0d, 0x97, 0x92, 0x90, 0xf2, 0x6c, 0x5b, 0xaf, 0xc7, 0x4d, 0x09, 0x56, 0xb7, 0x18, 0xab, 0x05, 0x3c, 0x1f,
0xc6, 0x74, 0x34, 0x84, 0x19, 0xf9, 0xf2, 0x89, 0xae, 0x45, 0x6c, 0x16, 0x7e, 0x25, 0x6d, 0x2c, 0xcb, 0xea, 0xc8, 0x70, 0x69, 0x4c, 0x47, 0x03, 0x98, 0x96, 0x4f, 0xb1, 0xe8, 0x5a, 0xc4, 0x66,
0x26, 0x75, 0x0b, 0xc0, 0x65, 0x06, 0x88, 0xf1, 0xb5, 0x78, 0xa3, 0x0a, 0xf6, 0x87, 0xda, 0xfd, 0xe1, 0x67, 0xdb, 0xfa, 0x42, 0xd2, 0xb4, 0x60, 0xb8, 0xc4, 0x18, 0x62, 0x7c, 0x2d, 0xde, 0xa8,
0x37, 0xb4, 0xb5, 0x1f, 0xd5, 0x60, 0x9a, 0xe6, 0x4b, 0xf4, 0x14, 0x09, 0xae, 0x99, 0x51, 0x0b, 0x02, 0xfd, 0xa1, 0x76, 0xff, 0x35, 0x6d, 0xf5, 0x87, 0x55, 0xc8, 0xd0, 0x7a, 0x89, 0x66, 0x91,
0x8f, 0x15, 0x77, 0xa2, 0x16, 0x1e, 0xbf, 0xa1, 0xc6, 0x9c, 0x22, 0xec, 0x27, 0x9b, 0x84, 0x71, 0xe0, 0x9a, 0x19, 0xb5, 0xf0, 0x48, 0x73, 0x27, 0x6a, 0xe1, 0xd1, 0x1b, 0x6a, 0x4c, 0x16, 0x61,
0xd1, 0x19, 0x7b, 0x50, 0x52, 0x2e, 0xa3, 0x28, 0x46, 0x62, 0xb8, 0x74, 0x14, 0x3d, 0x45, 0x62, 0xbf, 0x21, 0x25, 0x0c, 0x8b, 0x6a, 0xec, 0x41, 0x51, 0xb9, 0x8c, 0xa2, 0x18, 0x8a, 0xe1, 0xd6,
0x6e, 0xb2, 0x78, 0x89, 0x81, 0x36, 0xf0, 0xc5, 0x30, 0x68, 0x87, 0xb3, 0x51, 0xd4, 0xef, 0x40, 0x51, 0x34, 0x8b, 0xc4, 0xdc, 0x64, 0xf1, 0x22, 0x63, 0x5a, 0xc7, 0x17, 0xc3, 0x4c, 0xdb, 0x1c,
0x59, 0xbd, 0xb5, 0xa2, 0x18, 0xa1, 0x91, 0xda, 0x54, 0x34, 0x56, 0xc4, 0x5d, 0x7a, 0x63, 0x9c, 0x8d, 0x72, 0xfd, 0x18, 0x4a, 0xea, 0xad, 0x15, 0xc5, 0x10, 0x8d, 0xf4, 0xa6, 0xa2, 0xb1, 0x22,
0xc6, 0xff, 0x81, 0xaa, 0xe4, 0xa5, 0xe8, 0x1f, 0x43, 0x41, 0xdc, 0x65, 0xe3, 0xe6, 0x1b, 0xae, 0xee, 0xd2, 0x1b, 0xe3, 0x34, 0xfe, 0x2f, 0x66, 0x25, 0x2e, 0xe5, 0xfe, 0x21, 0xe4, 0xc5, 0x5d,
0x66, 0xc5, 0xcd, 0x37, 0x72, 0x11, 0x8e, 0x49, 0x49, 0x18, 0x2c, 0xcd, 0xd9, 0x65, 0x80, 0x16, 0x36, 0x4e, 0xdf, 0x70, 0x37, 0x2b, 0x4e, 0xdf, 0xc8, 0x45, 0x38, 0xa6, 0x24, 0x61, 0x6c, 0x69,
0x90, 0x8f, 0x89, 0x97, 0x04, 0x19, 0xd4, 0x67, 0x92, 0x20, 0x95, 0xfb, 0xd2, 0x44, 0xc8, 0x2e, 0xcd, 0x2e, 0x03, 0xb4, 0x60, 0xf9, 0x98, 0x78, 0x49, 0x2c, 0x83, 0xfe, 0x4c, 0x12, 0x4b, 0xe5,
0xf1, 0xc4, 0x5e, 0x96, 0x97, 0x11, 0x94, 0x20, 0x51, 0x8d, 0x86, 0x78, 0x12, 0x4b, 0x62, 0x16, 0xbe, 0x34, 0x96, 0x65, 0x87, 0x78, 0xe2, 0x2c, 0xcb, 0xcb, 0x08, 0x4a, 0xa0, 0xa8, 0x46, 0x43,
0x19, 0xa0, 0x8a, 0x50, 0x88, 0xbe, 0x0b, 0x10, 0x5c, 0xbc, 0xa3, 0x89, 0x41, 0x6c, 0xf5, 0x2e, 0x3c, 0x0e, 0x25, 0xb1, 0x8a, 0x0c, 0xb8, 0x8a, 0x50, 0x88, 0xbe, 0x03, 0x10, 0x5c, 0xbc, 0xa3,
0x9a, 0x18, 0xc4, 0xdf, 0xdd, 0x63, 0x3c, 0x38, 0x00, 0xe7, 0x99, 0x2c, 0x85, 0xff, 0x89, 0x06, 0x85, 0x41, 0x6c, 0xf7, 0x2e, 0x5a, 0x18, 0xc4, 0xdf, 0xdd, 0x63, 0x3c, 0x38, 0x60, 0xce, 0x2b,
0x68, 0xfc, 0xa2, 0x8e, 0x1e, 0xc4, 0x43, 0xc4, 0x16, 0x06, 0x1b, 0xaf, 0xbd, 0x1a, 0x73, 0x62, 0x59, 0xca, 0xfe, 0xc7, 0x1a, 0xa0, 0xd1, 0x8b, 0x3a, 0x7a, 0x10, 0xcf, 0x22, 0xb6, 0x31, 0x58,
0xf4, 0x0c, 0xf4, 0x6a, 0xb3, 0x21, 0x83, 0x97, 0x54, 0xb3, 0xcf, 0x35, 0xa8, 0x84, 0xae, 0xfa, 0x7f, 0xe5, 0x7c, 0xc8, 0x89, 0xd1, 0x33, 0x90, 0xab, 0xc5, 0x96, 0xf4, 0x5f, 0x52, 0xc9, 0x3e,
0xe8, 0x4e, 0xc2, 0x3a, 0x47, 0x8a, 0x8b, 0x8d, 0xbb, 0xe7, 0xf2, 0x25, 0xe6, 0x4e, 0xca, 0xae, 0xd3, 0xa0, 0x1c, 0xba, 0xea, 0xa3, 0x3b, 0x09, 0xfb, 0x1c, 0x69, 0x2e, 0xd6, 0xef, 0x9e, 0x89,
0x90, 0x79, 0xe3, 0x0f, 0x35, 0xa8, 0x86, 0xeb, 0x03, 0x28, 0x01, 0x60, 0xac, 0x42, 0xd9, 0x58, 0x97, 0x58, 0x3b, 0x29, 0xa7, 0x42, 0xd6, 0x8d, 0x3f, 0xd0, 0xa0, 0x12, 0xee, 0x0f, 0xa0, 0x04,
0x3e, 0x9f, 0xf1, 0x15, 0x56, 0x2b, 0x48, 0x25, 0x3f, 0x86, 0x82, 0x28, 0x2b, 0xc4, 0xb9, 0x45, 0x06, 0x23, 0x1d, 0xca, 0xfa, 0xd2, 0xd9, 0x88, 0xe7, 0xd8, 0xad, 0xa0, 0x94, 0xfc, 0x10, 0xf2,
0xb8, 0xc0, 0x19, 0xe7, 0x16, 0x91, 0x9a, 0x44, 0x92, 0x5b, 0xd0, 0x1b, 0xba, 0xe2, 0x89, 0xa2, 0xa2, 0xad, 0x10, 0xe7, 0x16, 0xe1, 0x06, 0x67, 0x9c, 0x5b, 0x44, 0x7a, 0x12, 0x49, 0x6e, 0x41,
0xf8, 0x90, 0x04, 0x39, 0xd9, 0x13, 0x23, 0x95, 0x8b, 0x89, 0x90, 0x81, 0x27, 0xca, 0xd2, 0x03, 0x6f, 0xe8, 0x8a, 0x27, 0x8a, 0xe6, 0x43, 0x12, 0xcb, 0xf1, 0x9e, 0x18, 0xe9, 0x5c, 0x8c, 0x65,
0x4a, 0x90, 0x78, 0x8e, 0x27, 0x46, 0x2b, 0x17, 0x49, 0x9e, 0xc8, 0x50, 0x15, 0x4f, 0x0c, 0x2a, 0x19, 0x78, 0xa2, 0x6c, 0x3d, 0xa0, 0x04, 0x8a, 0x67, 0x78, 0x62, 0xb4, 0x73, 0x91, 0xe4, 0x89,
0x05, 0x71, 0x9e, 0x38, 0x56, 0xbe, 0x8d, 0xf3, 0xc4, 0xf1, 0x62, 0x43, 0xd2, 0xda, 0x32, 0xf0, 0x8c, 0xab, 0xe2, 0x89, 0x41, 0xa7, 0x20, 0xce, 0x13, 0x47, 0xda, 0xb7, 0x71, 0x9e, 0x38, 0xda,
0x90, 0x27, 0xce, 0xc5, 0x54, 0x16, 0xd0, 0x6b, 0x09, 0x36, 0x8d, 0x2d, 0x0d, 0x37, 0x5e, 0x7f, 0x6c, 0x48, 0xda, 0x5b, 0xc6, 0x3c, 0xe4, 0x89, 0xb3, 0x31, 0x9d, 0x05, 0xf4, 0x4a, 0x82, 0x4d,
0x45, 0xee, 0xc9, 0x1e, 0xc0, 0x57, 0x43, 0x7a, 0xc0, 0x2f, 0x34, 0x98, 0x8f, 0x2b, 0x4d, 0xa0, 0x63, 0x5b, 0xc3, 0xf5, 0x57, 0xcf, 0x89, 0x3d, 0xde, 0x03, 0xf8, 0x6e, 0x48, 0x0f, 0xf8, 0xb9,
0x04, 0xb0, 0x84, 0xba, 0x72, 0x63, 0xe5, 0x55, 0xd9, 0x5f, 0xc1, 0x6e, 0xbe, 0x4f, 0x3c, 0xaa, 0x06, 0x73, 0x71, 0xad, 0x09, 0x94, 0xc0, 0x2c, 0xa1, 0xaf, 0x5c, 0x5f, 0x3e, 0x2f, 0xfa, 0x39,
0xfd, 0xf6, 0xab, 0x45, 0xed, 0x0f, 0x5f, 0x2d, 0x6a, 0x7f, 0xfa, 0x6a, 0x51, 0xfb, 0xe9, 0x9f, 0xec, 0xe6, 0xfb, 0xc4, 0xa3, 0xea, 0x6f, 0xbf, 0x5c, 0xd0, 0xfe, 0xf0, 0xe5, 0x82, 0xf6, 0xa7,
0x17, 0xa7, 0x8e, 0xf2, 0xec, 0xff, 0x4d, 0xbc, 0xf5, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x10, 0x2f, 0x17, 0xb4, 0x9f, 0xfc, 0x79, 0x61, 0xea, 0x30, 0xc7, 0xfe, 0x23, 0xc7, 0x1b, 0xff, 0x0a,
0xb3, 0xfb, 0x25, 0xbe, 0x31, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x71, 0x5f, 0x47, 0x71, 0x4f, 0x32, 0x00, 0x00,
} }

View File

@ -734,6 +734,8 @@ message MemberAddResponse {
ResponseHeader header = 1; ResponseHeader header = 1;
// member is the member information for the added member. // member is the member information for the added member.
Member member = 2; Member member = 2;
// members is a list of all members after adding the new member.
repeated Member members = 3;
} }
message MemberRemoveRequest { message MemberRemoveRequest {
@ -743,6 +745,8 @@ message MemberRemoveRequest {
message MemberRemoveResponse { message MemberRemoveResponse {
ResponseHeader header = 1; ResponseHeader header = 1;
// members is a list of all members after removing the member.
repeated Member members = 2;
} }
message MemberUpdateRequest { message MemberUpdateRequest {
@ -754,6 +758,8 @@ message MemberUpdateRequest {
message MemberUpdateResponse{ message MemberUpdateResponse{
ResponseHeader header = 1; ResponseHeader header = 1;
// members is a list of all members after updating the member.
repeated Member members = 2;
} }
message MemberListRequest { message MemberListRequest {

View File

@ -135,15 +135,15 @@ type Server interface {
// AddMember attempts to add a member into the cluster. It will return // AddMember attempts to add a member into the cluster. It will return
// ErrIDRemoved if member ID is removed from the cluster, or return // ErrIDRemoved if member ID is removed from the cluster, or return
// ErrIDExists if member ID exists in the cluster. // ErrIDExists if member ID exists in the cluster.
AddMember(ctx context.Context, memb membership.Member) error AddMember(ctx context.Context, memb membership.Member) ([]*membership.Member, error)
// RemoveMember attempts to remove a member from the cluster. It will // RemoveMember attempts to remove a member from the cluster. It will
// return ErrIDRemoved if member ID is removed from the cluster, or return // return ErrIDRemoved if member ID is removed from the cluster, or return
// ErrIDNotFound if member ID is not in the cluster. // ErrIDNotFound if member ID is not in the cluster.
RemoveMember(ctx context.Context, id uint64) error RemoveMember(ctx context.Context, id uint64) ([]*membership.Member, error)
// UpdateMember attempts to update an existing member in the cluster. It will // UpdateMember attempts to update an existing member in the cluster. It will
// return ErrIDNotFound if the member ID does not exist. // return ErrIDNotFound if the member ID does not exist.
UpdateMember(ctx context.Context, updateMemb membership.Member) error UpdateMember(ctx context.Context, updateMemb membership.Member) ([]*membership.Member, error)
// ClusterVersion is the cluster-wide minimum major.minor version. // ClusterVersion is the cluster-wide minimum major.minor version.
// Cluster version is set to the min version that an etcd member is // Cluster version is set to the min version that an etcd member is
@ -1053,27 +1053,27 @@ func (s *EtcdServer) checkMembershipOperationPermission(ctx context.Context) err
return s.AuthStore().IsAdminPermitted(authInfo) return s.AuthStore().IsAdminPermitted(authInfo)
} }
func (s *EtcdServer) AddMember(ctx context.Context, memb membership.Member) error { func (s *EtcdServer) AddMember(ctx context.Context, memb membership.Member) ([]*membership.Member, error) {
if err := s.checkMembershipOperationPermission(ctx); err != nil { if err := s.checkMembershipOperationPermission(ctx); err != nil {
return err return nil, err
} }
if s.Cfg.StrictReconfigCheck { if s.Cfg.StrictReconfigCheck {
// by default StrictReconfigCheck is enabled; reject new members if unhealthy // by default StrictReconfigCheck is enabled; reject new members if unhealthy
if !s.cluster.IsReadyToAddNewMember() { if !s.cluster.IsReadyToAddNewMember() {
plog.Warningf("not enough started members, rejecting member add %+v", memb) plog.Warningf("not enough started members, rejecting member add %+v", memb)
return ErrNotEnoughStartedMembers return nil, ErrNotEnoughStartedMembers
} }
if !isConnectedFullySince(s.r.transport, time.Now().Add(-HealthInterval), s.ID(), s.cluster.Members()) { if !isConnectedFullySince(s.r.transport, time.Now().Add(-HealthInterval), s.ID(), s.cluster.Members()) {
plog.Warningf("not healthy for reconfigure, rejecting member add %+v", memb) plog.Warningf("not healthy for reconfigure, rejecting member add %+v", memb)
return ErrUnhealthy return nil, ErrUnhealthy
} }
} }
// TODO: move Member to protobuf type // TODO: move Member to protobuf type
b, err := json.Marshal(memb) b, err := json.Marshal(memb)
if err != nil { if err != nil {
return err return nil, err
} }
cc := raftpb.ConfChange{ cc := raftpb.ConfChange{
Type: raftpb.ConfChangeAddNode, Type: raftpb.ConfChangeAddNode,
@ -1083,14 +1083,14 @@ func (s *EtcdServer) AddMember(ctx context.Context, memb membership.Member) erro
return s.configure(ctx, cc) return s.configure(ctx, cc)
} }
func (s *EtcdServer) RemoveMember(ctx context.Context, id uint64) error { func (s *EtcdServer) RemoveMember(ctx context.Context, id uint64) ([]*membership.Member, error) {
if err := s.checkMembershipOperationPermission(ctx); err != nil { if err := s.checkMembershipOperationPermission(ctx); err != nil {
return err return nil, err
} }
// by default StrictReconfigCheck is enabled; reject removal if leads to quorum loss // by default StrictReconfigCheck is enabled; reject removal if leads to quorum loss
if err := s.mayRemoveMember(types.ID(id)); err != nil { if err := s.mayRemoveMember(types.ID(id)); err != nil {
return err return nil, err
} }
cc := raftpb.ConfChange{ cc := raftpb.ConfChange{
@ -1126,14 +1126,14 @@ func (s *EtcdServer) mayRemoveMember(id types.ID) error {
return nil return nil
} }
func (s *EtcdServer) UpdateMember(ctx context.Context, memb membership.Member) error { func (s *EtcdServer) UpdateMember(ctx context.Context, memb membership.Member) ([]*membership.Member, error) {
b, merr := json.Marshal(memb) b, merr := json.Marshal(memb)
if merr != nil { if merr != nil {
return merr return nil, merr
} }
if err := s.checkMembershipOperationPermission(ctx); err != nil { if err := s.checkMembershipOperationPermission(ctx); err != nil {
return err return nil, err
} }
cc := raftpb.ConfChange{ cc := raftpb.ConfChange{
Type: raftpb.ConfChangeUpdateNode, Type: raftpb.ConfChangeUpdateNode,
@ -1156,31 +1156,34 @@ func (s *EtcdServer) Lead() uint64 { return atomic.LoadUint64(&s.r.lead) }
func (s *EtcdServer) Leader() types.ID { return types.ID(s.Lead()) } func (s *EtcdServer) Leader() types.ID { return types.ID(s.Lead()) }
type confChangeResponse struct {
membs []*membership.Member
err error
}
// configure sends a configuration change through consensus and // configure sends a configuration change through consensus and
// then waits for it to be applied to the server. It // then waits for it to be applied to the server. It
// will block until the change is performed or there is an error. // will block until the change is performed or there is an error.
func (s *EtcdServer) configure(ctx context.Context, cc raftpb.ConfChange) error { func (s *EtcdServer) configure(ctx context.Context, cc raftpb.ConfChange) ([]*membership.Member, error) {
cc.ID = s.reqIDGen.Next() cc.ID = s.reqIDGen.Next()
ch := s.w.Register(cc.ID) ch := s.w.Register(cc.ID)
start := time.Now() start := time.Now()
if err := s.r.ProposeConfChange(ctx, cc); err != nil { if err := s.r.ProposeConfChange(ctx, cc); err != nil {
s.w.Trigger(cc.ID, nil) s.w.Trigger(cc.ID, nil)
return err return nil, err
} }
select { select {
case x := <-ch: case x := <-ch:
if err, ok := x.(error); ok { if x == nil {
return err plog.Panicf("configure trigger value should never be nil")
} }
if x != nil { resp := x.(*confChangeResponse)
plog.Panicf("return type should always be error") return resp.membs, resp.err
}
return nil
case <-ctx.Done(): case <-ctx.Done():
s.w.Trigger(cc.ID, nil) // GC wait s.w.Trigger(cc.ID, nil) // GC wait
return s.parseProposeCtxErr(ctx.Err(), start) return nil, s.parseProposeCtxErr(ctx.Err(), start)
case <-s.stopping: case <-s.stopping:
return ErrStopped return nil, ErrStopped
} }
} }
@ -1276,7 +1279,7 @@ func (s *EtcdServer) apply(es []raftpb.Entry, confState *raftpb.ConfState) (appl
pbutil.MustUnmarshal(&cc, e.Data) pbutil.MustUnmarshal(&cc, e.Data)
removedSelf, err := s.applyConfChange(cc, confState) removedSelf, err := s.applyConfChange(cc, confState)
shouldStop = shouldStop || removedSelf shouldStop = shouldStop || removedSelf
s.w.Trigger(cc.ID, err) s.w.Trigger(cc.ID, &confChangeResponse{s.cluster.Members(), err})
default: default:
plog.Panicf("entry type should be either EntryNormal or EntryConfChange") plog.Panicf("entry type should be either EntryNormal or EntryConfChange")
} }

View File

@ -1085,7 +1085,7 @@ func TestAddMember(t *testing.T) {
} }
s.start() s.start()
m := membership.Member{ID: 1234, RaftAttributes: membership.RaftAttributes{PeerURLs: []string{"foo"}}} m := membership.Member{ID: 1234, RaftAttributes: membership.RaftAttributes{PeerURLs: []string{"foo"}}}
err := s.AddMember(context.TODO(), m) _, err := s.AddMember(context.TODO(), m)
gaction := n.Action() gaction := n.Action()
s.Stop() s.Stop()
@ -1126,7 +1126,7 @@ func TestRemoveMember(t *testing.T) {
SyncTicker: &time.Ticker{}, SyncTicker: &time.Ticker{},
} }
s.start() s.start()
err := s.RemoveMember(context.TODO(), 1234) _, err := s.RemoveMember(context.TODO(), 1234)
gaction := n.Action() gaction := n.Action()
s.Stop() s.Stop()
@ -1167,7 +1167,7 @@ func TestUpdateMember(t *testing.T) {
} }
s.start() s.start()
wm := membership.Member{ID: 1234, RaftAttributes: membership.RaftAttributes{PeerURLs: []string{"http://127.0.0.1:1"}}} wm := membership.Member{ID: 1234, RaftAttributes: membership.RaftAttributes{PeerURLs: []string{"http://127.0.0.1:1"}}}
err := s.UpdateMember(context.TODO(), wm) _, err := s.UpdateMember(context.TODO(), wm)
gaction := n.Action() gaction := n.Action()
s.Stop() s.Stop()