Browse Source

adds VolumeEcGenerateSlices, VolumeEcCopy

pull/991/head
Chris Lu 6 years ago
parent
commit
fbbc74abb4
  1. 22
      weed/pb/volume_server.proto
  2. 344
      weed/pb/volume_server_pb/volume_server.pb.go
  3. 62
      weed/server/volume_grpc_copy.go
  4. 82
      weed/server/volume_grpc_erasure_coding.go
  5. 128
      weed/storage/erasure_coding/ec_encoder.go
  6. 106
      weed/storage/erasure_coding/ec_test.go

22
weed/pb/volume_server.proto

@ -47,6 +47,13 @@ service VolumeServer {
rpc VolumeTailReceiver (VolumeTailReceiverRequest) returns (VolumeTailReceiverResponse) {
}
// erasure coding
rpc VolumeEcGenerateSlices (VolumeEcGenerateSlicesRequest) returns (VolumeEcGenerateSlicesResponse) {
}
rpc VolumeEcCopy (VolumeEcCopyRequest) returns (VolumeEcCopyResponse) {
}
}
//////////////////////////////////////////////////
@ -190,6 +197,21 @@ message VolumeTailReceiverRequest {
message VolumeTailReceiverResponse {
}
message VolumeEcGenerateSlicesRequest {
uint32 volume_id = 1;
}
message VolumeEcGenerateSlicesResponse {
}
message VolumeEcCopyRequest {
uint32 volume_id = 1;
string collection = 2;
repeated uint32 ec_indexes = 3;
string source_data_node = 5;
}
message VolumeEcCopyResponse {
}
message ReadVolumeFileStatusRequest {
uint32 volume_id = 1;
}

344
weed/pb/volume_server_pb/volume_server.pb.go

@ -43,6 +43,10 @@ It has these top-level messages:
VolumeTailSenderResponse
VolumeTailReceiverRequest
VolumeTailReceiverResponse
VolumeEcGenerateSlicesRequest
VolumeEcGenerateSlicesResponse
VolumeEcCopyRequest
VolumeEcCopyResponse
ReadVolumeFileStatusRequest
ReadVolumeFileStatusResponse
DiskStatus
@ -766,6 +770,78 @@ func (m *VolumeTailReceiverResponse) String() string { return proto.C
func (*VolumeTailReceiverResponse) ProtoMessage() {}
func (*VolumeTailReceiverResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{33} }
type VolumeEcGenerateSlicesRequest struct {
VolumeId uint32 `protobuf:"varint,1,opt,name=volume_id,json=volumeId" json:"volume_id,omitempty"`
}
func (m *VolumeEcGenerateSlicesRequest) Reset() { *m = VolumeEcGenerateSlicesRequest{} }
func (m *VolumeEcGenerateSlicesRequest) String() string { return proto.CompactTextString(m) }
func (*VolumeEcGenerateSlicesRequest) ProtoMessage() {}
func (*VolumeEcGenerateSlicesRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{34} }
func (m *VolumeEcGenerateSlicesRequest) GetVolumeId() uint32 {
if m != nil {
return m.VolumeId
}
return 0
}
type VolumeEcGenerateSlicesResponse struct {
}
func (m *VolumeEcGenerateSlicesResponse) Reset() { *m = VolumeEcGenerateSlicesResponse{} }
func (m *VolumeEcGenerateSlicesResponse) String() string { return proto.CompactTextString(m) }
func (*VolumeEcGenerateSlicesResponse) ProtoMessage() {}
func (*VolumeEcGenerateSlicesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{35} }
type VolumeEcCopyRequest struct {
VolumeId uint32 `protobuf:"varint,1,opt,name=volume_id,json=volumeId" json:"volume_id,omitempty"`
Collection string `protobuf:"bytes,2,opt,name=collection" json:"collection,omitempty"`
EcIndexes []uint32 `protobuf:"varint,3,rep,packed,name=ec_indexes,json=ecIndexes" json:"ec_indexes,omitempty"`
SourceDataNode string `protobuf:"bytes,5,opt,name=source_data_node,json=sourceDataNode" json:"source_data_node,omitempty"`
}
func (m *VolumeEcCopyRequest) Reset() { *m = VolumeEcCopyRequest{} }
func (m *VolumeEcCopyRequest) String() string { return proto.CompactTextString(m) }
func (*VolumeEcCopyRequest) ProtoMessage() {}
func (*VolumeEcCopyRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{36} }
func (m *VolumeEcCopyRequest) GetVolumeId() uint32 {
if m != nil {
return m.VolumeId
}
return 0
}
func (m *VolumeEcCopyRequest) GetCollection() string {
if m != nil {
return m.Collection
}
return ""
}
func (m *VolumeEcCopyRequest) GetEcIndexes() []uint32 {
if m != nil {
return m.EcIndexes
}
return nil
}
func (m *VolumeEcCopyRequest) GetSourceDataNode() string {
if m != nil {
return m.SourceDataNode
}
return ""
}
type VolumeEcCopyResponse struct {
}
func (m *VolumeEcCopyResponse) Reset() { *m = VolumeEcCopyResponse{} }
func (m *VolumeEcCopyResponse) String() string { return proto.CompactTextString(m) }
func (*VolumeEcCopyResponse) ProtoMessage() {}
func (*VolumeEcCopyResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{37} }
type ReadVolumeFileStatusRequest struct {
VolumeId uint32 `protobuf:"varint,1,opt,name=volume_id,json=volumeId" json:"volume_id,omitempty"`
}
@ -773,7 +849,7 @@ type ReadVolumeFileStatusRequest struct {
func (m *ReadVolumeFileStatusRequest) Reset() { *m = ReadVolumeFileStatusRequest{} }
func (m *ReadVolumeFileStatusRequest) String() string { return proto.CompactTextString(m) }
func (*ReadVolumeFileStatusRequest) ProtoMessage() {}
func (*ReadVolumeFileStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{34} }
func (*ReadVolumeFileStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{38} }
func (m *ReadVolumeFileStatusRequest) GetVolumeId() uint32 {
if m != nil {
@ -796,7 +872,7 @@ type ReadVolumeFileStatusResponse struct {
func (m *ReadVolumeFileStatusResponse) Reset() { *m = ReadVolumeFileStatusResponse{} }
func (m *ReadVolumeFileStatusResponse) String() string { return proto.CompactTextString(m) }
func (*ReadVolumeFileStatusResponse) ProtoMessage() {}
func (*ReadVolumeFileStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{35} }
func (*ReadVolumeFileStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{39} }
func (m *ReadVolumeFileStatusResponse) GetVolumeId() uint32 {
if m != nil {
@ -864,7 +940,7 @@ type DiskStatus struct {
func (m *DiskStatus) Reset() { *m = DiskStatus{} }
func (m *DiskStatus) String() string { return proto.CompactTextString(m) }
func (*DiskStatus) ProtoMessage() {}
func (*DiskStatus) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{36} }
func (*DiskStatus) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{40} }
func (m *DiskStatus) GetDir() string {
if m != nil {
@ -907,7 +983,7 @@ type MemStatus struct {
func (m *MemStatus) Reset() { *m = MemStatus{} }
func (m *MemStatus) String() string { return proto.CompactTextString(m) }
func (*MemStatus) ProtoMessage() {}
func (*MemStatus) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{37} }
func (*MemStatus) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{41} }
func (m *MemStatus) GetGoroutines() int32 {
if m != nil {
@ -993,6 +1069,10 @@ func init() {
proto.RegisterType((*VolumeTailSenderResponse)(nil), "volume_server_pb.VolumeTailSenderResponse")
proto.RegisterType((*VolumeTailReceiverRequest)(nil), "volume_server_pb.VolumeTailReceiverRequest")
proto.RegisterType((*VolumeTailReceiverResponse)(nil), "volume_server_pb.VolumeTailReceiverResponse")
proto.RegisterType((*VolumeEcGenerateSlicesRequest)(nil), "volume_server_pb.VolumeEcGenerateSlicesRequest")
proto.RegisterType((*VolumeEcGenerateSlicesResponse)(nil), "volume_server_pb.VolumeEcGenerateSlicesResponse")
proto.RegisterType((*VolumeEcCopyRequest)(nil), "volume_server_pb.VolumeEcCopyRequest")
proto.RegisterType((*VolumeEcCopyResponse)(nil), "volume_server_pb.VolumeEcCopyResponse")
proto.RegisterType((*ReadVolumeFileStatusRequest)(nil), "volume_server_pb.ReadVolumeFileStatusRequest")
proto.RegisterType((*ReadVolumeFileStatusResponse)(nil), "volume_server_pb.ReadVolumeFileStatusResponse")
proto.RegisterType((*DiskStatus)(nil), "volume_server_pb.DiskStatus")
@ -1029,6 +1109,9 @@ type VolumeServerClient interface {
CopyFile(ctx context.Context, in *CopyFileRequest, opts ...grpc.CallOption) (VolumeServer_CopyFileClient, error)
VolumeTailSender(ctx context.Context, in *VolumeTailSenderRequest, opts ...grpc.CallOption) (VolumeServer_VolumeTailSenderClient, error)
VolumeTailReceiver(ctx context.Context, in *VolumeTailReceiverRequest, opts ...grpc.CallOption) (*VolumeTailReceiverResponse, error)
// erasure coding
VolumeEcGenerateSlices(ctx context.Context, in *VolumeEcGenerateSlicesRequest, opts ...grpc.CallOption) (*VolumeEcGenerateSlicesResponse, error)
VolumeEcCopy(ctx context.Context, in *VolumeEcCopyRequest, opts ...grpc.CallOption) (*VolumeEcCopyResponse, error)
}
type volumeServerClient struct {
@ -1261,6 +1344,24 @@ func (c *volumeServerClient) VolumeTailReceiver(ctx context.Context, in *VolumeT
return out, nil
}
func (c *volumeServerClient) VolumeEcGenerateSlices(ctx context.Context, in *VolumeEcGenerateSlicesRequest, opts ...grpc.CallOption) (*VolumeEcGenerateSlicesResponse, error) {
out := new(VolumeEcGenerateSlicesResponse)
err := grpc.Invoke(ctx, "/volume_server_pb.VolumeServer/VolumeEcGenerateSlices", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *volumeServerClient) VolumeEcCopy(ctx context.Context, in *VolumeEcCopyRequest, opts ...grpc.CallOption) (*VolumeEcCopyResponse, error) {
out := new(VolumeEcCopyResponse)
err := grpc.Invoke(ctx, "/volume_server_pb.VolumeServer/VolumeEcCopy", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for VolumeServer service
type VolumeServerServer interface {
@ -1283,6 +1384,9 @@ type VolumeServerServer interface {
CopyFile(*CopyFileRequest, VolumeServer_CopyFileServer) error
VolumeTailSender(*VolumeTailSenderRequest, VolumeServer_VolumeTailSenderServer) error
VolumeTailReceiver(context.Context, *VolumeTailReceiverRequest) (*VolumeTailReceiverResponse, error)
// erasure coding
VolumeEcGenerateSlices(context.Context, *VolumeEcGenerateSlicesRequest) (*VolumeEcGenerateSlicesResponse, error)
VolumeEcCopy(context.Context, *VolumeEcCopyRequest) (*VolumeEcCopyResponse, error)
}
func RegisterVolumeServerServer(s *grpc.Server, srv VolumeServerServer) {
@ -1604,6 +1708,42 @@ func _VolumeServer_VolumeTailReceiver_Handler(srv interface{}, ctx context.Conte
return interceptor(ctx, in, info, handler)
}
func _VolumeServer_VolumeEcGenerateSlices_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(VolumeEcGenerateSlicesRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(VolumeServerServer).VolumeEcGenerateSlices(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/volume_server_pb.VolumeServer/VolumeEcGenerateSlices",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(VolumeServerServer).VolumeEcGenerateSlices(ctx, req.(*VolumeEcGenerateSlicesRequest))
}
return interceptor(ctx, in, info, handler)
}
func _VolumeServer_VolumeEcCopy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(VolumeEcCopyRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(VolumeServerServer).VolumeEcCopy(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/volume_server_pb.VolumeServer/VolumeEcCopy",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(VolumeServerServer).VolumeEcCopy(ctx, req.(*VolumeEcCopyRequest))
}
return interceptor(ctx, in, info, handler)
}
var _VolumeServer_serviceDesc = grpc.ServiceDesc{
ServiceName: "volume_server_pb.VolumeServer",
HandlerType: (*VolumeServerServer)(nil),
@ -1664,6 +1804,14 @@ var _VolumeServer_serviceDesc = grpc.ServiceDesc{
MethodName: "VolumeTailReceiver",
Handler: _VolumeServer_VolumeTailReceiver_Handler,
},
{
MethodName: "VolumeEcGenerateSlices",
Handler: _VolumeServer_VolumeEcGenerateSlices_Handler,
},
{
MethodName: "VolumeEcCopy",
Handler: _VolumeServer_VolumeEcCopy_Handler,
},
},
Streams: []grpc.StreamDesc{
{
@ -1688,95 +1836,101 @@ var _VolumeServer_serviceDesc = grpc.ServiceDesc{
func init() { proto.RegisterFile("volume_server.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 1436 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xc4, 0x58, 0x4b, 0x73, 0xd4, 0xc6,
0x13, 0xb7, 0xd8, 0xb5, 0xbd, 0xee, 0x5d, 0x9b, 0x65, 0x6c, 0xf0, 0x7a, 0x79, 0x19, 0xc1, 0x1f,
0x96, 0xc7, 0xdf, 0x10, 0xa8, 0x24, 0x24, 0x39, 0x24, 0x60, 0x92, 0x0a, 0x55, 0x01, 0xaa, 0x64,
0xa0, 0x92, 0x4a, 0xaa, 0x54, 0x63, 0xa9, 0x8d, 0x55, 0xd6, 0x4a, 0x42, 0x33, 0x72, 0x70, 0x2a,
0xb7, 0xe4, 0x13, 0xe4, 0x2b, 0xe4, 0xc6, 0x21, 0xd7, 0x7c, 0xaa, 0x7c, 0x82, 0x5c, 0x52, 0xf3,
0x90, 0x76, 0xf5, 0xf2, 0x8a, 0x70, 0xc8, 0x6d, 0xb6, 0xa7, 0xdf, 0xea, 0xee, 0xf9, 0xf5, 0xc2,
0xea, 0x61, 0xe8, 0x27, 0x63, 0xb4, 0x19, 0xc6, 0x87, 0x18, 0x6f, 0x45, 0x71, 0xc8, 0x43, 0xd2,
0xcf, 0x11, 0xed, 0x68, 0xd7, 0xbc, 0x0d, 0xe4, 0x21, 0xe5, 0xce, 0xfe, 0x23, 0xf4, 0x91, 0xa3,
0x85, 0xaf, 0x13, 0x64, 0x9c, 0x6c, 0x40, 0x67, 0xcf, 0xf3, 0xd1, 0xf6, 0x5c, 0x36, 0x30, 0x36,
0x5b, 0xa3, 0x25, 0x6b, 0x51, 0xfc, 0x7e, 0xec, 0x32, 0xf3, 0x19, 0xac, 0xe6, 0x04, 0x58, 0x14,
0x06, 0x0c, 0xc9, 0x7d, 0x58, 0x8c, 0x91, 0x25, 0x3e, 0x57, 0x02, 0xdd, 0xbb, 0x17, 0xb6, 0x8a,
0xb6, 0xb6, 0x32, 0x91, 0xc4, 0xe7, 0x56, 0xca, 0x6e, 0x7a, 0xd0, 0x9b, 0xbe, 0x20, 0xeb, 0xb0,
0xa8, 0x6d, 0x0f, 0x8c, 0x4d, 0x63, 0xb4, 0x64, 0x2d, 0x28, 0xd3, 0xe4, 0x0c, 0x2c, 0x30, 0x4e,
0x79, 0xc2, 0x06, 0x27, 0x36, 0x8d, 0xd1, 0xbc, 0xa5, 0x7f, 0x91, 0x35, 0x98, 0xc7, 0x38, 0x0e,
0xe3, 0x41, 0x4b, 0xb2, 0xab, 0x1f, 0x84, 0x40, 0x9b, 0x79, 0x3f, 0xe1, 0xa0, 0xbd, 0x69, 0x8c,
0x96, 0x2d, 0x79, 0x36, 0x17, 0x61, 0xfe, 0xcb, 0x71, 0xc4, 0x8f, 0xcc, 0x8f, 0x61, 0xf0, 0x92,
0x3a, 0x49, 0x32, 0x7e, 0x29, 0x7d, 0xdc, 0xde, 0x47, 0xe7, 0x20, 0x8d, 0xfd, 0x2c, 0x2c, 0x69,
0xcf, 0xb5, 0x07, 0xcb, 0x56, 0x47, 0x11, 0x1e, 0xbb, 0xe6, 0x17, 0xb0, 0x51, 0x21, 0xa8, 0x73,
0x70, 0x19, 0x96, 0x5f, 0xd1, 0x78, 0x97, 0xbe, 0x42, 0x3b, 0xa6, 0xdc, 0x0b, 0xa5, 0xb4, 0x61,
0xf5, 0x34, 0xd1, 0x12, 0x34, 0xf3, 0x7b, 0x18, 0xe6, 0x34, 0x84, 0xe3, 0x88, 0x3a, 0xbc, 0x89,
0x71, 0xb2, 0x09, 0xdd, 0x28, 0x46, 0xea, 0xfb, 0xa1, 0x43, 0x39, 0xca, 0x2c, 0xb4, 0xac, 0x69,
0x92, 0x79, 0x1e, 0xce, 0x56, 0x2a, 0x57, 0x0e, 0x9a, 0xf7, 0x0b, 0xde, 0x87, 0xe3, 0xb1, 0xd7,
0xc8, 0xb4, 0x79, 0xae, 0xe4, 0xb5, 0x94, 0xd4, 0x7a, 0x3f, 0x29, 0xdc, 0xfa, 0x48, 0x83, 0x24,
0x6a, 0xa4, 0xb8, 0xe8, 0x71, 0x2a, 0x9a, 0x69, 0x5e, 0x57, 0xc5, 0xb1, 0x1d, 0xfa, 0x3e, 0x3a,
0xdc, 0x0b, 0x83, 0x54, 0xed, 0x05, 0x00, 0x27, 0x23, 0xea, 0x52, 0x99, 0xa2, 0x98, 0x43, 0x18,
0x94, 0x45, 0xb5, 0xda, 0xb7, 0x06, 0x9c, 0x7e, 0xa0, 0x93, 0xa6, 0x0c, 0x37, 0xfa, 0x00, 0x79,
0x93, 0x27, 0x8a, 0x26, 0x8b, 0x1f, 0xa8, 0x55, 0xfa, 0x40, 0x82, 0x23, 0xc6, 0xc8, 0xf7, 0x1c,
0x2a, 0x55, 0xb4, 0xa5, 0x8a, 0x69, 0x12, 0xe9, 0x43, 0x8b, 0x73, 0x7f, 0x30, 0x2f, 0x6f, 0xc4,
0xd1, 0x1c, 0xc0, 0x99, 0xa2, 0xaf, 0x3a, 0x8c, 0x8f, 0x60, 0x5d, 0x51, 0x76, 0x8e, 0x02, 0x67,
0x47, 0x76, 0x43, 0xa3, 0xa4, 0xff, 0x6d, 0xc0, 0xa0, 0x2c, 0xa8, 0xab, 0xf8, 0x7d, 0x33, 0xf0,
0xae, 0xf1, 0x91, 0x8b, 0xd0, 0xe5, 0xd4, 0xf3, 0xed, 0x70, 0x6f, 0x8f, 0x21, 0x1f, 0x2c, 0x6c,
0x1a, 0xa3, 0xb6, 0x05, 0x82, 0xf4, 0x4c, 0x52, 0xc8, 0x75, 0xe8, 0x3b, 0xaa, 0x92, 0xed, 0x18,
0x0f, 0x3d, 0x26, 0x34, 0x2f, 0x4a, 0xc7, 0x4e, 0x3a, 0x69, 0x85, 0x2b, 0x32, 0x31, 0x61, 0xd9,
0x73, 0xdf, 0xd8, 0x72, 0x80, 0xc8, 0xf6, 0xef, 0x48, 0x6d, 0x5d, 0xcf, 0x7d, 0xf3, 0x95, 0xe7,
0xe3, 0x8e, 0x98, 0x02, 0x2f, 0xe1, 0x9c, 0x0a, 0xfe, 0x71, 0xe0, 0xc4, 0x38, 0xc6, 0x80, 0x53,
0x7f, 0x3b, 0x8c, 0x8e, 0x1a, 0x95, 0xc0, 0x06, 0x74, 0x98, 0x17, 0x38, 0x68, 0x07, 0x6a, 0x0c,
0xb5, 0xad, 0x45, 0xf9, 0xfb, 0x29, 0x33, 0x1f, 0xc2, 0xf9, 0x1a, 0xbd, 0x3a, 0xb3, 0x97, 0xa0,
0x27, 0x1d, 0x73, 0xc2, 0x80, 0x63, 0xc0, 0xa5, 0xee, 0x9e, 0xd5, 0x15, 0xb4, 0x6d, 0x45, 0x32,
0x3f, 0x00, 0xa2, 0x74, 0x3c, 0x09, 0x93, 0xa0, 0x59, 0x6b, 0x9e, 0x86, 0xd5, 0x9c, 0x88, 0xae,
0x8d, 0x7b, 0xb0, 0xa6, 0xc8, 0x2f, 0x82, 0x71, 0x63, 0x5d, 0xeb, 0x70, 0xba, 0x20, 0xa4, 0xb5,
0xdd, 0x4d, 0x8d, 0xe4, 0xdf, 0x89, 0x63, 0x95, 0x9d, 0x49, 0x3d, 0xc8, 0x3f, 0x15, 0xe6, 0x1f,
0x06, 0x9c, 0x4a, 0xc7, 0x48, 0xc3, 0xac, 0xbf, 0x63, 0xd9, 0xb5, 0x6a, 0xcb, 0xae, 0x3d, 0x29,
0xbb, 0x11, 0xf4, 0x59, 0x98, 0xc4, 0x0e, 0xda, 0x2e, 0xe5, 0xd4, 0x0e, 0x42, 0x17, 0x75, 0x55,
0xae, 0x28, 0xfa, 0x23, 0xca, 0xe9, 0xd3, 0xd0, 0x45, 0xf3, 0xf3, 0xf4, 0xa3, 0xe4, 0xbe, 0xe6,
0x75, 0x38, 0xe5, 0x53, 0xc6, 0x6d, 0x1a, 0x45, 0x18, 0xb8, 0x36, 0xe5, 0xa2, 0x24, 0x0c, 0x59,
0x12, 0x2b, 0xe2, 0xe2, 0x81, 0xa4, 0x3f, 0xe0, 0x4f, 0x99, 0xf9, 0x9b, 0x01, 0x27, 0x85, 0xac,
0x28, 0xc1, 0x46, 0xf1, 0xf6, 0xa1, 0x85, 0x6f, 0xb8, 0x0e, 0x54, 0x1c, 0xc9, 0x6d, 0x58, 0xd5,
0xb5, 0xee, 0x85, 0xc1, 0xa4, 0x0d, 0x5a, 0x52, 0x90, 0x4c, 0xae, 0xb2, 0x4e, 0xb8, 0x08, 0x5d,
0xc6, 0xc3, 0x28, 0xed, 0xaa, 0xb6, 0xea, 0x2a, 0x41, 0x52, 0x5d, 0x65, 0x7e, 0x08, 0xfd, 0x89,
0x4f, 0xcd, 0x2b, 0xf4, 0x17, 0x23, 0x1d, 0x3a, 0xcf, 0xa9, 0xe7, 0xef, 0x60, 0xe0, 0x62, 0xfc,
0x9e, 0x9d, 0x43, 0xee, 0xc0, 0x9a, 0xe7, 0xfa, 0x68, 0x73, 0x6f, 0x8c, 0x61, 0xc2, 0x6d, 0x86,
0x4e, 0x18, 0xb8, 0x2c, 0x8d, 0x4e, 0xdc, 0x3d, 0x57, 0x57, 0x3b, 0xea, 0xc6, 0xfc, 0x35, 0x9b,
0x60, 0xd3, 0x5e, 0x4c, 0xde, 0xe1, 0x00, 0x51, 0x28, 0xdc, 0x47, 0xea, 0x62, 0xac, 0xc3, 0xe8,
0x29, 0xe2, 0xd7, 0x92, 0x26, 0xf2, 0xa3, 0x99, 0x76, 0x43, 0xf7, 0x48, 0x7a, 0xd4, 0xb3, 0x40,
0x91, 0x1e, 0x86, 0xee, 0x91, 0x1c, 0x25, 0xcc, 0x96, 0x9f, 0xd8, 0xd9, 0x4f, 0x82, 0x03, 0xe9,
0x4d, 0xc7, 0xea, 0x7a, 0xec, 0x1b, 0xca, 0xf8, 0xb6, 0x20, 0x99, 0x7f, 0x1a, 0xb0, 0x31, 0x71,
0xc3, 0x42, 0x07, 0xbd, 0xc3, 0xff, 0x20, 0x1d, 0x42, 0x42, 0xd7, 0x72, 0x0e, 0x74, 0xe9, 0x72,
0x27, 0xea, 0x4e, 0x4f, 0x7c, 0x79, 0x23, 0x1f, 0xf4, 0x0a, 0xc7, 0x75, 0x8b, 0x7e, 0x0a, 0x67,
0x2d, 0xa4, 0xae, 0xe2, 0x90, 0x83, 0xb3, 0xf9, 0xe3, 0xf2, 0xd7, 0x09, 0x38, 0x57, 0x2d, 0xdc,
0xe4, 0x81, 0xf9, 0x0c, 0x86, 0xd9, 0x00, 0x17, 0xf1, 0x33, 0x4e, 0xc7, 0x51, 0x96, 0x01, 0x95,
0xa8, 0x75, 0x3d, 0xcd, 0x9f, 0xa7, 0xf7, 0x69, 0x1a, 0x4a, 0xd3, 0xbf, 0x55, 0x9a, 0xfe, 0xc2,
0x80, 0x4b, 0x79, 0x9d, 0x01, 0xd5, 0x26, 0xeb, 0x2e, 0xe5, 0x75, 0x06, 0x32, 0x61, 0x69, 0x60,
0x5e, 0x19, 0xd0, 0xfc, 0xd2, 0xc0, 0x79, 0x00, 0xdd, 0x43, 0x49, 0x90, 0xbe, 0x66, 0x4b, 0xaa,
0x83, 0x92, 0xa0, 0xb6, 0x91, 0x17, 0x6b, 0x1b, 0x39, 0x3f, 0xfb, 0x3a, 0x25, 0x9c, 0xf3, 0x2d,
0xc0, 0x23, 0x8f, 0x1d, 0xa8, 0x24, 0x8b, 0xc9, 0xe1, 0x7a, 0xb1, 0x86, 0x43, 0xe2, 0x28, 0x28,
0xd4, 0xf7, 0x75, 0xea, 0xc4, 0x51, 0x40, 0xe3, 0x84, 0xa1, 0xab, 0xb3, 0x23, 0xcf, 0x82, 0xb6,
0x17, 0x23, 0xea, 0x04, 0xc8, 0xb3, 0xf9, 0xbb, 0x01, 0x4b, 0x4f, 0x70, 0xac, 0x35, 0x5f, 0x00,
0x78, 0x15, 0xc6, 0x61, 0xc2, 0xbd, 0x00, 0xd5, 0xa0, 0x9b, 0xb7, 0xa6, 0x28, 0xff, 0xde, 0x8e,
0x84, 0xea, 0xe8, 0xef, 0xe9, 0x64, 0xca, 0xb3, 0xa0, 0xed, 0x23, 0x8d, 0x74, 0xfe, 0xe4, 0x59,
0x00, 0x7d, 0xc6, 0xa9, 0x73, 0x20, 0x93, 0xd5, 0xb6, 0xd4, 0x8f, 0xbb, 0x6f, 0x57, 0xa0, 0x37,
0x5d, 0xda, 0xe4, 0x07, 0xe8, 0x4e, 0x6d, 0x28, 0xe4, 0x4a, 0x79, 0x11, 0x29, 0x6f, 0x3c, 0xc3,
0xff, 0xcd, 0xe0, 0xd2, 0x8d, 0x31, 0x47, 0x02, 0x38, 0x55, 0xda, 0x00, 0xc8, 0x8d, 0xb2, 0x74,
0xdd, 0x7e, 0x31, 0xbc, 0xd9, 0x88, 0x37, 0xb3, 0xc7, 0x61, 0xb5, 0x02, 0xd2, 0x93, 0x5b, 0x33,
0xb4, 0xe4, 0xd6, 0x8a, 0xe1, 0xff, 0x1b, 0x72, 0x67, 0x56, 0x5f, 0x03, 0x29, 0xe3, 0x7d, 0x72,
0x73, 0xa6, 0x9a, 0xc9, 0x3e, 0x31, 0xbc, 0xd5, 0x8c, 0xb9, 0x36, 0x50, 0xb5, 0x09, 0xcc, 0x0c,
0x34, 0xb7, 0x6b, 0xcc, 0x0c, 0xb4, 0xb0, 0x5e, 0xcc, 0x91, 0x03, 0xe8, 0x17, 0xb7, 0x04, 0x72,
0xbd, 0x6e, 0x75, 0x2d, 0x2d, 0x21, 0xc3, 0x1b, 0x4d, 0x58, 0x33, 0x63, 0x08, 0x2b, 0x79, 0x24,
0x4f, 0xae, 0x95, 0xe5, 0x2b, 0xf7, 0x92, 0xe1, 0x68, 0x36, 0xe3, 0x74, 0x4c, 0x45, 0x74, 0x5f,
0x15, 0x53, 0xcd, 0xea, 0x50, 0x15, 0x53, 0xdd, 0xb2, 0x60, 0xce, 0x91, 0x9f, 0x53, 0xc8, 0x58,
0x40, 0xbd, 0x64, 0xab, 0x4e, 0x4d, 0x35, 0xec, 0x1e, 0xde, 0x6e, 0xcc, 0x9f, 0xda, 0xbe, 0x63,
0x88, 0x5e, 0x9f, 0x02, 0xbf, 0x55, 0xbd, 0x5e, 0x86, 0xd3, 0x55, 0xbd, 0x5e, 0x85, 0xa0, 0xe7,
0xc8, 0x2e, 0x2c, 0xe7, 0xe0, 0x30, 0xb9, 0x5a, 0x27, 0x99, 0x07, 0xd9, 0xc3, 0x6b, 0x33, 0xf9,
0x32, 0x1b, 0x76, 0x3a, 0xbd, 0xf4, 0xb8, 0xaa, 0x75, 0x2e, 0x3f, 0xaf, 0xae, 0xce, 0x62, 0xcb,
0x0c, 0x7c, 0x07, 0x30, 0x41, 0xaf, 0xe4, 0x72, 0x9d, 0xdc, 0xf4, 0xa7, 0xb8, 0x72, 0x3c, 0x53,
0xa6, 0xfa, 0x47, 0x58, 0xab, 0x7a, 0xe9, 0x49, 0x45, 0x17, 0x1e, 0x03, 0x27, 0x86, 0x5b, 0x4d,
0xd9, 0x33, 0xc3, 0x2f, 0xa0, 0x93, 0x62, 0x57, 0x72, 0xa9, 0x2c, 0x5d, 0xc0, 0xda, 0x43, 0xf3,
0x38, 0x96, 0xa9, 0x6a, 0x1a, 0xa7, 0x8d, 0x33, 0x01, 0x95, 0xf5, 0x8d, 0x53, 0x82, 0xbf, 0xf5,
0x8d, 0x53, 0xc6, 0xa8, 0xd2, 0xdc, 0xeb, 0x74, 0xaf, 0x98, 0xc6, 0x60, 0x95, 0x43, 0xb6, 0x0e,
0x62, 0x56, 0x0e, 0xd9, 0x7a, 0x58, 0x37, 0xb7, 0xbb, 0x20, 0xff, 0x07, 0xbc, 0xf7, 0x4f, 0x00,
0x00, 0x00, 0xff, 0xff, 0x5d, 0xbf, 0x08, 0x06, 0x1e, 0x14, 0x00, 0x00,
// 1534 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xc4, 0x58, 0xcb, 0x6f, 0xd4, 0xd6,
0x1a, 0x8f, 0x99, 0xc9, 0xeb, 0x9b, 0x04, 0x86, 0x93, 0x90, 0x4c, 0x0c, 0x09, 0x83, 0xe1, 0xc2,
0xf0, 0xb8, 0x81, 0x0b, 0xba, 0xf7, 0xd2, 0x87, 0xd4, 0x42, 0xa0, 0x6d, 0xa4, 0x02, 0x92, 0x03,
0xa8, 0x55, 0x2b, 0x59, 0x27, 0xf6, 0x17, 0x62, 0xc5, 0x63, 0x1b, 0xfb, 0x38, 0x4d, 0xaa, 0x76,
0xd5, 0xae, 0xba, 0xec, 0xb6, 0xcb, 0xee, 0xba, 0xe8, 0xb6, 0x7f, 0x55, 0xff, 0x82, 0x6e, 0xaa,
0xf3, 0xb0, 0x67, 0xfc, 0xca, 0x98, 0x52, 0xa9, 0xbb, 0x33, 0xdf, 0xf9, 0x5e, 0xe7, 0xf3, 0xf7,
0xfa, 0x0d, 0x2c, 0x1d, 0x06, 0x5e, 0x32, 0x44, 0x2b, 0xc6, 0xe8, 0x10, 0xa3, 0xcd, 0x30, 0x0a,
0x58, 0x40, 0xba, 0x39, 0xa2, 0x15, 0xee, 0x1a, 0xb7, 0x81, 0x3c, 0xa4, 0xcc, 0xde, 0x7f, 0x84,
0x1e, 0x32, 0x34, 0xf1, 0x75, 0x82, 0x31, 0x23, 0x6b, 0x30, 0xb7, 0xe7, 0x7a, 0x68, 0xb9, 0x4e,
0xdc, 0xd3, 0xfa, 0xad, 0xc1, 0xbc, 0x39, 0xcb, 0x7f, 0x6f, 0x3b, 0xb1, 0xf1, 0x0c, 0x96, 0x72,
0x02, 0x71, 0x18, 0xf8, 0x31, 0x92, 0xfb, 0x30, 0x1b, 0x61, 0x9c, 0x78, 0x4c, 0x0a, 0x74, 0xee,
0x6e, 0x6c, 0x16, 0x6d, 0x6d, 0x66, 0x22, 0x89, 0xc7, 0xcc, 0x94, 0xdd, 0x70, 0x61, 0x61, 0xfc,
0x82, 0xac, 0xc2, 0xac, 0xb2, 0xdd, 0xd3, 0xfa, 0xda, 0x60, 0xde, 0x9c, 0x91, 0xa6, 0xc9, 0x0a,
0xcc, 0xc4, 0x8c, 0xb2, 0x24, 0xee, 0x9d, 0xea, 0x6b, 0x83, 0x69, 0x53, 0xfd, 0x22, 0xcb, 0x30,
0x8d, 0x51, 0x14, 0x44, 0xbd, 0x96, 0x60, 0x97, 0x3f, 0x08, 0x81, 0x76, 0xec, 0x7e, 0x8d, 0xbd,
0x76, 0x5f, 0x1b, 0x2c, 0x9a, 0xe2, 0x6c, 0xcc, 0xc2, 0xf4, 0xe3, 0x61, 0xc8, 0x8e, 0x8d, 0xff,
0x43, 0xef, 0x25, 0xb5, 0x93, 0x64, 0xf8, 0x52, 0xf8, 0xb8, 0xb5, 0x8f, 0xf6, 0x41, 0xfa, 0xf6,
0xf3, 0x30, 0xaf, 0x3c, 0x57, 0x1e, 0x2c, 0x9a, 0x73, 0x92, 0xb0, 0xed, 0x18, 0x1f, 0xc2, 0x5a,
0x85, 0xa0, 0x8a, 0xc1, 0x65, 0x58, 0x7c, 0x45, 0xa3, 0x5d, 0xfa, 0x0a, 0xad, 0x88, 0x32, 0x37,
0x10, 0xd2, 0x9a, 0xb9, 0xa0, 0x88, 0x26, 0xa7, 0x19, 0x5f, 0x80, 0x9e, 0xd3, 0x10, 0x0c, 0x43,
0x6a, 0xb3, 0x26, 0xc6, 0x49, 0x1f, 0x3a, 0x61, 0x84, 0xd4, 0xf3, 0x02, 0x9b, 0x32, 0x14, 0x51,
0x68, 0x99, 0xe3, 0x24, 0x63, 0x1d, 0xce, 0x57, 0x2a, 0x97, 0x0e, 0x1a, 0xf7, 0x0b, 0xde, 0x07,
0xc3, 0xa1, 0xdb, 0xc8, 0xb4, 0x71, 0xa1, 0xe4, 0xb5, 0x90, 0x54, 0x7a, 0xdf, 0x29, 0xdc, 0x7a,
0x48, 0xfd, 0x24, 0x6c, 0xa4, 0xb8, 0xe8, 0x71, 0x2a, 0x9a, 0x69, 0x5e, 0x95, 0xc9, 0xb1, 0x15,
0x78, 0x1e, 0xda, 0xcc, 0x0d, 0xfc, 0x54, 0xed, 0x06, 0x80, 0x9d, 0x11, 0x55, 0xaa, 0x8c, 0x51,
0x0c, 0x1d, 0x7a, 0x65, 0x51, 0xa5, 0xf6, 0x17, 0x0d, 0xce, 0x3d, 0x50, 0x41, 0x93, 0x86, 0x1b,
0x7d, 0x80, 0xbc, 0xc9, 0x53, 0x45, 0x93, 0xc5, 0x0f, 0xd4, 0x2a, 0x7d, 0x20, 0xce, 0x11, 0x61,
0xe8, 0xb9, 0x36, 0x15, 0x2a, 0xda, 0x42, 0xc5, 0x38, 0x89, 0x74, 0xa1, 0xc5, 0x98, 0xd7, 0x9b,
0x16, 0x37, 0xfc, 0x68, 0xf4, 0x60, 0xa5, 0xe8, 0xab, 0x7a, 0xc6, 0xff, 0x60, 0x55, 0x52, 0x76,
0x8e, 0x7d, 0x7b, 0x47, 0x54, 0x43, 0xa3, 0xa0, 0xff, 0xa1, 0x41, 0xaf, 0x2c, 0xa8, 0xb2, 0xf8,
0x6d, 0x23, 0xf0, 0xa6, 0xef, 0x23, 0x17, 0xa1, 0xc3, 0xa8, 0xeb, 0x59, 0xc1, 0xde, 0x5e, 0x8c,
0xac, 0x37, 0xd3, 0xd7, 0x06, 0x6d, 0x13, 0x38, 0xe9, 0x99, 0xa0, 0x90, 0xeb, 0xd0, 0xb5, 0x65,
0x26, 0x5b, 0x11, 0x1e, 0xba, 0x31, 0xd7, 0x3c, 0x2b, 0x1c, 0x3b, 0x63, 0xa7, 0x19, 0x2e, 0xc9,
0xc4, 0x80, 0x45, 0xd7, 0x39, 0xb2, 0x44, 0x03, 0x11, 0xe5, 0x3f, 0x27, 0xb4, 0x75, 0x5c, 0xe7,
0xe8, 0x23, 0xd7, 0xc3, 0x1d, 0xde, 0x05, 0x5e, 0xc2, 0x05, 0xf9, 0xf8, 0x6d, 0xdf, 0x8e, 0x70,
0x88, 0x3e, 0xa3, 0xde, 0x56, 0x10, 0x1e, 0x37, 0x4a, 0x81, 0x35, 0x98, 0x8b, 0x5d, 0xdf, 0x46,
0xcb, 0x97, 0x6d, 0xa8, 0x6d, 0xce, 0x8a, 0xdf, 0x4f, 0x63, 0xe3, 0x21, 0xac, 0xd7, 0xe8, 0x55,
0x91, 0xbd, 0x04, 0x0b, 0xc2, 0x31, 0x3b, 0xf0, 0x19, 0xfa, 0x4c, 0xe8, 0x5e, 0x30, 0x3b, 0x9c,
0xb6, 0x25, 0x49, 0xc6, 0x7f, 0x80, 0x48, 0x1d, 0x4f, 0x82, 0xc4, 0x6f, 0x56, 0x9a, 0xe7, 0x60,
0x29, 0x27, 0xa2, 0x72, 0xe3, 0x1e, 0x2c, 0x4b, 0xf2, 0x0b, 0x7f, 0xd8, 0x58, 0xd7, 0x2a, 0x9c,
0x2b, 0x08, 0x29, 0x6d, 0x77, 0x53, 0x23, 0xf9, 0x39, 0x71, 0xa2, 0xb2, 0x95, 0xd4, 0x83, 0xfc,
0xa8, 0x30, 0x7e, 0xd5, 0xe0, 0x6c, 0xda, 0x46, 0x1a, 0x46, 0xfd, 0x0d, 0xd3, 0xae, 0x55, 0x9b,
0x76, 0xed, 0x51, 0xda, 0x0d, 0xa0, 0x1b, 0x07, 0x49, 0x64, 0xa3, 0xe5, 0x50, 0x46, 0x2d, 0x3f,
0x70, 0x50, 0x65, 0xe5, 0x69, 0x49, 0x7f, 0x44, 0x19, 0x7d, 0x1a, 0x38, 0x68, 0x7c, 0x90, 0x7e,
0x94, 0xdc, 0xd7, 0xbc, 0x0e, 0x67, 0x3d, 0x1a, 0x33, 0x8b, 0x86, 0x21, 0xfa, 0x8e, 0x45, 0x19,
0x4f, 0x09, 0x4d, 0xa4, 0xc4, 0x69, 0x7e, 0xf1, 0x40, 0xd0, 0x1f, 0xb0, 0xa7, 0xb1, 0xf1, 0xa3,
0x06, 0x67, 0xb8, 0x2c, 0x4f, 0xc1, 0x46, 0xef, 0xed, 0x42, 0x0b, 0x8f, 0x98, 0x7a, 0x28, 0x3f,
0x92, 0xdb, 0xb0, 0xa4, 0x72, 0xdd, 0x0d, 0xfc, 0x51, 0x19, 0xb4, 0x84, 0x20, 0x19, 0x5d, 0x65,
0x95, 0x70, 0x11, 0x3a, 0x31, 0x0b, 0xc2, 0xb4, 0xaa, 0xda, 0xb2, 0xaa, 0x38, 0x49, 0x56, 0x95,
0xf1, 0x5f, 0xe8, 0x8e, 0x7c, 0x6a, 0x9e, 0xa1, 0xdf, 0x69, 0x69, 0xd3, 0x79, 0x4e, 0x5d, 0x6f,
0x07, 0x7d, 0x07, 0xa3, 0xb7, 0xac, 0x1c, 0x72, 0x07, 0x96, 0x5d, 0xc7, 0x43, 0x8b, 0xb9, 0x43,
0x0c, 0x12, 0x66, 0xc5, 0x68, 0x07, 0xbe, 0x13, 0xa7, 0xaf, 0xe3, 0x77, 0xcf, 0xe5, 0xd5, 0x8e,
0xbc, 0x31, 0xbe, 0xcf, 0x3a, 0xd8, 0xb8, 0x17, 0xa3, 0x39, 0xec, 0x23, 0x72, 0x85, 0xfb, 0x48,
0x1d, 0x8c, 0xd4, 0x33, 0x16, 0x24, 0xf1, 0x13, 0x41, 0xe3, 0xf1, 0x51, 0x4c, 0xbb, 0x81, 0x73,
0x2c, 0x3c, 0x5a, 0x30, 0x41, 0x92, 0x1e, 0x06, 0xce, 0xb1, 0x68, 0x25, 0xb1, 0x25, 0x3e, 0xb1,
0xbd, 0x9f, 0xf8, 0x07, 0xc2, 0x9b, 0x39, 0xb3, 0xe3, 0xc6, 0x9f, 0xd2, 0x98, 0x6d, 0x71, 0x92,
0xf1, 0x9b, 0x06, 0x6b, 0x23, 0x37, 0x4c, 0xb4, 0xd1, 0x3d, 0xfc, 0x07, 0xc2, 0xc1, 0x25, 0x54,
0x2e, 0xe7, 0x96, 0x2e, 0x95, 0xee, 0x44, 0xde, 0xa9, 0x8e, 0x2f, 0x6e, 0xc4, 0x40, 0xaf, 0x70,
0x5c, 0x95, 0xe8, 0xfb, 0x69, 0x2b, 0x7b, 0x6c, 0x7f, 0x8c, 0x3e, 0x46, 0x94, 0xe1, 0x8e, 0xe7,
0xda, 0xd8, 0x6c, 0xbc, 0xf4, 0x61, 0xa3, 0x4e, 0x5a, 0xe9, 0xff, 0x49, 0x4b, 0xfb, 0xc9, 0x63,
0xfb, 0x6f, 0x6b, 0x02, 0xeb, 0x00, 0x68, 0x5b, 0xae, 0xef, 0xe0, 0x11, 0xf2, 0x60, 0xb5, 0x06,
0x8b, 0xe6, 0x3c, 0xda, 0xdb, 0x92, 0xf0, 0x06, 0xf5, 0x9e, 0x35, 0xae, 0xd4, 0x39, 0xe5, 0xf5,
0xbb, 0x70, 0xde, 0x44, 0xea, 0xc8, 0x3b, 0x31, 0x4e, 0x9a, 0x8f, 0xdc, 0xdf, 0x4f, 0xc1, 0x85,
0x6a, 0xe1, 0x26, 0x63, 0xf7, 0x3d, 0xd0, 0xb3, 0xb1, 0xc6, 0xb3, 0x22, 0x66, 0x74, 0x18, 0x66,
0x79, 0x21, 0xd3, 0x67, 0x55, 0xcd, 0xb8, 0xe7, 0xe9, 0x7d, 0x9a, 0x1c, 0xa5, 0x99, 0xd8, 0x2a,
0xcd, 0x44, 0x6e, 0xc0, 0xa1, 0xac, 0xce, 0x80, 0x6c, 0x1e, 0xab, 0x0e, 0x65, 0x75, 0x06, 0x32,
0x61, 0x61, 0x60, 0x5a, 0x1a, 0x50, 0xfc, 0xc2, 0xc0, 0x3a, 0x80, 0xea, 0x2c, 0x89, 0x9f, 0xce,
0xf8, 0x79, 0xd9, 0x57, 0x12, 0xbf, 0xb6, 0xbd, 0xcd, 0xd6, 0xb6, 0xb7, 0x7c, 0x32, 0xcc, 0x95,
0xb6, 0xbf, 0xcf, 0x00, 0x1e, 0xb9, 0xf1, 0x81, 0x0c, 0x32, 0xef, 0xa7, 0x8e, 0x1b, 0xa9, 0x25,
0x91, 0x1f, 0x39, 0x85, 0x7a, 0x9e, 0x0a, 0x1d, 0x3f, 0x72, 0xc0, 0x90, 0xc4, 0xe8, 0xa8, 0xe8,
0x88, 0x33, 0xa7, 0xed, 0x45, 0x88, 0x2a, 0x00, 0xe2, 0x6c, 0xfc, 0xac, 0xc1, 0xfc, 0x13, 0x1c,
0x2a, 0xcd, 0x1b, 0x00, 0xaf, 0x82, 0x28, 0x48, 0x98, 0xeb, 0xa3, 0x6c, 0xff, 0xd3, 0xe6, 0x18,
0xe5, 0xaf, 0xdb, 0x11, 0x00, 0x06, 0xbd, 0x3d, 0x15, 0x4c, 0x71, 0xe6, 0xb4, 0x7d, 0xa4, 0xa1,
0x8a, 0x9f, 0x38, 0x73, 0xf8, 0x13, 0x33, 0x6a, 0x1f, 0x88, 0x60, 0xb5, 0x4d, 0xf9, 0xe3, 0xee,
0x0f, 0x5d, 0x58, 0x18, 0x2f, 0x78, 0xf2, 0x25, 0x74, 0xc6, 0x70, 0x1b, 0xb9, 0x52, 0x86, 0x67,
0x65, 0x1c, 0xa8, 0xff, 0x6b, 0x02, 0x97, 0x2a, 0x8c, 0x29, 0xe2, 0xc3, 0xd9, 0x12, 0x2e, 0x22,
0x37, 0xca, 0xd2, 0x75, 0xa8, 0x4b, 0xbf, 0xd9, 0x88, 0x37, 0xb3, 0xc7, 0x60, 0xa9, 0x02, 0xe8,
0x90, 0x5b, 0x13, 0xb4, 0xe4, 0xc0, 0x96, 0xfe, 0xef, 0x86, 0xdc, 0x99, 0xd5, 0xd7, 0x40, 0xca,
0x28, 0x88, 0xdc, 0x9c, 0xa8, 0x66, 0x84, 0xb2, 0xf4, 0x5b, 0xcd, 0x98, 0x6b, 0x1f, 0x2a, 0xf1,
0xd1, 0xc4, 0x87, 0xe6, 0x10, 0xd8, 0xc4, 0x87, 0x16, 0x40, 0xd7, 0x14, 0x39, 0x80, 0x6e, 0x11,
0x3b, 0x91, 0xeb, 0x75, 0x80, 0xbe, 0x04, 0xcd, 0xf4, 0x1b, 0x4d, 0x58, 0x33, 0x63, 0x08, 0xa7,
0xf3, 0xf8, 0x86, 0x5c, 0x2b, 0xcb, 0x57, 0xa2, 0x35, 0x7d, 0x30, 0x99, 0x71, 0xfc, 0x4d, 0x45,
0xcc, 0x53, 0xf5, 0xa6, 0x1a, 0x40, 0x55, 0xf5, 0xa6, 0x3a, 0x08, 0x65, 0x4c, 0x91, 0x6f, 0xd2,
0x45, 0xba, 0x80, 0x05, 0xc8, 0x66, 0x9d, 0x9a, 0x6a, 0x30, 0xa2, 0xdf, 0x6e, 0xcc, 0x9f, 0xda,
0xbe, 0xa3, 0xf1, 0x5a, 0x1f, 0x83, 0x04, 0x55, 0xb5, 0x5e, 0x06, 0x19, 0x55, 0xb5, 0x5e, 0x85,
0x2b, 0xa6, 0xc8, 0x2e, 0x2c, 0xe6, 0x40, 0x02, 0xb9, 0x5a, 0x27, 0x99, 0x87, 0x1e, 0xfa, 0xb5,
0x89, 0x7c, 0x99, 0x0d, 0x2b, 0xed, 0x5e, 0xaa, 0x5d, 0xd5, 0x3a, 0x97, 0xef, 0x57, 0x57, 0x27,
0xb1, 0x65, 0x06, 0x3e, 0x07, 0x18, 0xed, 0xf4, 0xe4, 0x72, 0x9d, 0xdc, 0xf8, 0xa7, 0xb8, 0x72,
0x32, 0x53, 0xa6, 0xfa, 0x2b, 0x58, 0xae, 0x9a, 0xf4, 0xa4, 0xa2, 0x0a, 0x4f, 0x58, 0x27, 0xf4,
0xcd, 0xa6, 0xec, 0x99, 0xe1, 0x17, 0x30, 0x97, 0x6e, 0xf4, 0xe4, 0x52, 0x59, 0xba, 0x80, 0x40,
0x74, 0xe3, 0x24, 0x96, 0xb1, 0x6c, 0x1a, 0xa6, 0x85, 0x33, 0x5a, 0xb5, 0xeb, 0x0b, 0xa7, 0x04,
0x0a, 0xea, 0x0b, 0xa7, 0xbc, 0xb9, 0x0b, 0x73, 0xaf, 0x53, 0xb4, 0x35, 0xbe, 0x99, 0x56, 0x36,
0xd9, 0xba, 0xc5, 0xbb, 0xb2, 0xc9, 0xd6, 0x2f, 0xbb, 0x53, 0xe4, 0x5b, 0x58, 0xa9, 0x5e, 0x58,
0x49, 0x6d, 0xf9, 0xd5, 0x2c, 0xc6, 0xfa, 0x9d, 0xe6, 0x02, 0xe5, 0x64, 0x97, 0xfb, 0x66, 0x7d,
0xb2, 0xe7, 0x96, 0xe5, 0xfa, 0x64, 0x2f, 0xac, 0xad, 0x53, 0xbb, 0x33, 0xe2, 0xdf, 0xdf, 0x7b,
0x7f, 0x06, 0x00, 0x00, 0xff, 0xff, 0x2f, 0xf9, 0x4c, 0xc9, 0x14, 0x16, 0x00, 0x00,
}

62
weed/server/volume_grpc_copy.go

@ -4,6 +4,7 @@ import (
"context"
"fmt"
"io"
"math"
"os"
"time"
@ -49,37 +50,13 @@ func (vs *VolumeServer) VolumeCopy(ctx context.Context, req *volume_server_pb.Vo
volumeFileName = storage.VolumeFileName(volFileInfoResp.Collection, location.Directory, int(req.VolumeId))
// println("source:", volFileInfoResp.String())
copyFileClient, err := client.CopyFile(ctx, &volume_server_pb.CopyFileRequest{
VolumeId: req.VolumeId,
Ext: ".idx",
CompactionRevision: volFileInfoResp.CompactionRevision,
StopOffset: volFileInfoResp.IdxFileSize,
})
if err != nil {
return fmt.Errorf("failed to start copying volume %d idx file: %v", req.VolumeId, err)
}
idxFileName = volumeFileName + ".idx"
err = writeToFile(copyFileClient, idxFileName, util.NewWriteThrottler(vs.compactionBytePerSecond))
if err != nil {
return fmt.Errorf("failed to copy volume %d idx file: %v", req.VolumeId, err)
}
copyFileClient, err = client.CopyFile(ctx, &volume_server_pb.CopyFileRequest{
VolumeId: req.VolumeId,
Ext: ".dat",
CompactionRevision: volFileInfoResp.CompactionRevision,
StopOffset: volFileInfoResp.DatFileSize,
})
if err != nil {
return fmt.Errorf("failed to start copying volume %d dat file: %v", req.VolumeId, err)
// copy ecx file
if err:=vs.doCopyFile(ctx, client, req.VolumeId, volFileInfoResp.CompactionRevision, volFileInfoResp.IdxFileSize, volumeFileName, ".idx"); err!=nil{
return err
}
datFileName = volumeFileName + ".dat"
err = writeToFile(copyFileClient, datFileName, util.NewWriteThrottler(vs.compactionBytePerSecond))
if err != nil {
return fmt.Errorf("failed to copy volume %d dat file: %v", req.VolumeId, err)
if err:=vs.doCopyFile(ctx, client, req.VolumeId, volFileInfoResp.CompactionRevision, volFileInfoResp.DatFileSize, volumeFileName, ".dat"); err!=nil{
return err
}
return nil
@ -109,6 +86,28 @@ func (vs *VolumeServer) VolumeCopy(ctx context.Context, req *volume_server_pb.Vo
}, err
}
func (vs *VolumeServer) doCopyFile(ctx context.Context, client volume_server_pb.VolumeServerClient, vid uint32,
compactRevision uint32, stopOffset uint64, baseFileName, ext string) error {
copyFileClient, err := client.CopyFile(ctx, &volume_server_pb.CopyFileRequest{
VolumeId: vid,
Ext: ext,
CompactionRevision: compactRevision,
StopOffset: stopOffset,
})
if err != nil {
return fmt.Errorf("failed to start copying volume %d %s file: %v", vid, ext, err)
}
err = writeToFile(copyFileClient, baseFileName+ext, util.NewWriteThrottler(vs.compactionBytePerSecond))
if err != nil {
return fmt.Errorf("failed to copy volume %d %s file: %v", vid, ext, err)
}
return nil
}
/**
only check the the differ of the file size
todo: maybe should check the received count and deleted count of the volume
@ -175,6 +174,9 @@ func (vs *VolumeServer) ReadVolumeFileStatus(ctx context.Context, req *volume_se
return resp, nil
}
// CopyFile client pulls the volume related file from the source server.
// if req.CompactionRevision != math.MaxUint32, it ensures the compact revision is as expected
// The copying still stop at req.StopOffset, but you can set it to math.MaxUint64 in order to read all data.
func (vs *VolumeServer) CopyFile(req *volume_server_pb.CopyFileRequest, stream volume_server_pb.VolumeServer_CopyFileServer) error {
v := vs.store.GetVolume(needle.VolumeId(req.VolumeId))
@ -182,7 +184,7 @@ func (vs *VolumeServer) CopyFile(req *volume_server_pb.CopyFileRequest, stream v
return fmt.Errorf("not found volume id %d", req.VolumeId)
}
if uint32(v.CompactionRevision) != req.CompactionRevision {
if uint32(v.CompactionRevision) != req.CompactionRevision && req.CompactionRevision != math.MaxUint32 {
return fmt.Errorf("volume %d is compacted", req.VolumeId)
}

82
weed/server/volume_grpc_erasure_coding.go

@ -0,0 +1,82 @@
package weed_server
import (
"context"
"fmt"
"math"
"github.com/chrislusf/seaweedfs/weed/operation"
"github.com/chrislusf/seaweedfs/weed/pb/volume_server_pb"
"github.com/chrislusf/seaweedfs/weed/storage"
"github.com/chrislusf/seaweedfs/weed/storage/erasure_coding"
"github.com/chrislusf/seaweedfs/weed/storage/needle"
)
/*
Steps to apply erasure coding to .dat .idx files
0. ensure the volume is readonly
1. client call VolumeEcGenerateSlices to generate the .ecx and .ec01~.ec14 files
2. client ask master for possible servers to hold the ec files, at least 4 servers
3. client call VolumeEcCopy on above target servers to copy ec files from the source server
4. target servers report the new ec files to the master
5. master stores vid -> [14]*DataNode
6. client checks master. If all 14 slices are ready, delete the original .idx, .idx files
*/
// VolumeEcGenerateSlices generates the .ecx and .ec01 ~ .ec14 files
func (vs *VolumeServer) VolumeEcGenerateSlices(ctx context.Context, req *volume_server_pb.VolumeEcGenerateSlicesRequest) (*volume_server_pb.VolumeEcGenerateSlicesResponse, error) {
v := vs.store.GetVolume(needle.VolumeId(req.VolumeId))
if v == nil {
return nil, fmt.Errorf("volume %d not found", req.VolumeId)
}
baseFileName := v.FileName()
// write .ecx file
if err := erasure_coding.WriteSortedEcxFile(baseFileName); err != nil {
return nil, fmt.Errorf("WriteSortedEcxFile %s: %v", baseFileName, err)
}
// write .ec01 ~ .ec14 files
if err := erasure_coding.WriteEcFiles(baseFileName); err != nil {
return nil, fmt.Errorf("WriteEcFiles %s: %v", baseFileName, err)
}
return &volume_server_pb.VolumeEcGenerateSlicesResponse{}, nil
}
// VolumeEcCopy copy the .ecx and some ec data slices
func (vs *VolumeServer) VolumeEcCopy(ctx context.Context, req *volume_server_pb.VolumeEcCopyRequest) (*volume_server_pb.VolumeEcCopyResponse, error) {
location := vs.store.FindFreeLocation()
if location == nil {
return nil, fmt.Errorf("no space left")
}
baseFileName := storage.VolumeFileName(req.Collection, location.Directory, int(req.VolumeId))
err := operation.WithVolumeServerClient(req.SourceDataNode, vs.grpcDialOption, func(client volume_server_pb.VolumeServerClient) error {
// copy ecx file
if err:=vs.doCopyFile(ctx, client, req.VolumeId, math.MaxUint32, math.MaxUint64, baseFileName, ".ecx"); err!=nil{
return err
}
// copy ec data slices
for _, ecIndex := range req.EcIndexes {
if err:=vs.doCopyFile(ctx, client, req.VolumeId, math.MaxUint32, math.MaxUint64, baseFileName, erasure_coding.ToExt(int(ecIndex))); err!=nil{
return err
}
}
return nil
})
if err != nil {
return nil, fmt.Errorf("VolumeEcCopy volume %d: %v", req.VolumeId, err)
}
return &volume_server_pb.VolumeEcCopyResponse{}, nil
}

128
weed/storage/erasure_coding/ec_encoder.go

@ -6,6 +6,9 @@ import (
"os"
"github.com/chrislusf/seaweedfs/weed/glog"
"github.com/chrislusf/seaweedfs/weed/storage"
"github.com/chrislusf/seaweedfs/weed/storage/needle_map"
"github.com/chrislusf/seaweedfs/weed/storage/types"
"github.com/klauspost/reedsolomon"
)
@ -16,11 +19,66 @@ const (
ErasureCodingSmallBlockSize = 1024 * 1024 // 1MB
)
// WriteSortedEcxFile generates .ecx file from existing .idx file
// all keys are sorted in ascending order
func WriteSortedEcxFile(baseFileName string) (e error) {
cm, err := readCompactMap(baseFileName)
if err != nil {
return fmt.Errorf("readCompactMap: %v", err)
}
ecxFile, err := os.OpenFile(baseFileName+".ecx", os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return fmt.Errorf("failed to open dat file: %v", err)
}
defer ecxFile.Close()
err = cm.AscendingVisit(func(value needle_map.NeedleValue) error {
bytes := value.ToBytes()
_, writeErr := ecxFile.Write(bytes)
return writeErr
})
if err != nil {
return fmt.Errorf("failed to open dat file: %v", err)
}
return nil
}
// WriteEcFiles generates .ec01 ~ .ec14 files
func WriteEcFiles(baseFileName string) error {
return generateEcFiles(baseFileName, 256*1024, ErasureCodingLargeBlockSize, ErasureCodingSmallBlockSize)
}
func ToExt(ecIndex int) string {
return fmt.Sprintf(".ec%02d", ecIndex)
}
func generateEcFiles(baseFileName string, bufferSize int, largeBlockSize int64, smallBlockSize int64) error {
file, err := os.OpenFile(baseFileName+".dat", os.O_RDONLY, 0)
if err != nil {
return fmt.Errorf("failed to open dat file: %v", err)
}
defer file.Close()
fi, err := file.Stat()
if err != nil {
return fmt.Errorf("failed to stat dat file: %v", err)
}
err = encodeDatFile(fi.Size(), err, baseFileName, bufferSize, largeBlockSize, file, smallBlockSize)
if err != nil {
return fmt.Errorf("encodeDatFile: %v", err)
}
return nil
}
func encodeData(file *os.File, enc reedsolomon.Encoder, startOffset, blockSize int64, buffers [][]byte, outputs []*os.File) error {
bufferSize := int64(len(buffers[0]))
batchCount := blockSize/bufferSize
if blockSize%bufferSize!=0 {
batchCount := blockSize / bufferSize
if blockSize%bufferSize != 0 {
glog.Fatalf("unexpected block size %d buffer size %d", blockSize, bufferSize)
}
@ -34,10 +92,10 @@ func encodeData(file *os.File, enc reedsolomon.Encoder, startOffset, blockSize i
return nil
}
func openEcFiles(baseFileName string, forRead bool) (files []*os.File, err error){
for i := 0; i< DataShardsCount+ParityShardsCount; i++{
fname := fmt.Sprintf("%s.ec%02d", baseFileName, i+1)
openOption := os.O_TRUNC|os.O_CREATE|os.O_WRONLY
func openEcFiles(baseFileName string, forRead bool) (files []*os.File, err error) {
for i := 0; i < DataShardsCount+ParityShardsCount; i++ {
fname := baseFileName + ToExt(i+1)
openOption := os.O_TRUNC | os.O_CREATE | os.O_WRONLY
if forRead {
openOption = os.O_RDONLY
}
@ -50,15 +108,14 @@ func openEcFiles(baseFileName string, forRead bool) (files []*os.File, err error
return
}
func closeEcFiles(files []*os.File){
for _, f := range files{
func closeEcFiles(files []*os.File) {
for _, f := range files {
if f != nil {
f.Close()
}
}
}
func encodeDataOneBatch(file *os.File, enc reedsolomon.Encoder, startOffset, blockSize int64, buffers [][]byte, outputs []*os.File) error {
// read data into buffers
@ -90,3 +147,56 @@ func encodeDataOneBatch(file *os.File, enc reedsolomon.Encoder, startOffset, blo
return nil
}
func encodeDatFile(remainingSize int64, err error, baseFileName string, bufferSize int, largeBlockSize int64, file *os.File, smallBlockSize int64) error {
var processedSize int64
enc, err := reedsolomon.New(DataShardsCount, ParityShardsCount)
if err != nil {
return fmt.Errorf("failed to create encoder: %v", err)
}
buffers := make([][]byte, DataShardsCount+ParityShardsCount)
outputs, err := openEcFiles(baseFileName, false)
defer closeEcFiles(outputs)
if err != nil {
return fmt.Errorf("failed to open dat file: %v", err)
}
for i, _ := range buffers {
buffers[i] = make([]byte, bufferSize)
}
for remainingSize > largeBlockSize*DataShardsCount {
err = encodeData(file, enc, processedSize, largeBlockSize, buffers, outputs)
if err != nil {
return fmt.Errorf("failed to encode large chunk data: %v", err)
}
remainingSize -= largeBlockSize * DataShardsCount
processedSize += largeBlockSize * DataShardsCount
}
for remainingSize > 0 {
encodeData(file, enc, processedSize, smallBlockSize, buffers, outputs)
if err != nil {
return fmt.Errorf("failed to encode small chunk data: %v", err)
}
remainingSize -= smallBlockSize * DataShardsCount
processedSize += smallBlockSize * DataShardsCount
}
return nil
}
func readCompactMap(baseFileName string) (*needle_map.CompactMap, error) {
indexFile, err := os.OpenFile(baseFileName+".idx", os.O_RDONLY, 0644)
if err != nil {
return nil, fmt.Errorf("cannot read Volume Index %s.idx: %v", baseFileName, err)
}
defer indexFile.Close()
cm := needle_map.NewCompactMap()
err = storage.WalkIndexFile(indexFile, func(key types.NeedleId, offset types.Offset, size uint32) error {
if !offset.IsZero() && size != types.TombstoneFileSize {
cm.Set(key, offset, size)
} else {
cm.Delete(key)
}
return nil
})
return cm, err
}

106
weed/storage/erasure_coding/ec_test.go

@ -7,7 +7,6 @@ import (
"os"
"testing"
"github.com/chrislusf/seaweedfs/weed/storage"
"github.com/chrislusf/seaweedfs/weed/storage/needle_map"
"github.com/chrislusf/seaweedfs/weed/storage/types"
"github.com/klauspost/reedsolomon"
@ -27,98 +26,20 @@ func TestEncodingDecoding(t *testing.T) {
t.Logf("generateEcFiles: %v", err)
}
err = writeSortedEcxFiles(baseFileName)
err = WriteSortedEcxFile(baseFileName)
if err != nil {
t.Logf("writeSortedEcxFiles: %v", err)
t.Logf("WriteSortedEcxFile: %v", err)
}
err = validateFiles(baseFileName)
if err != nil {
t.Logf("writeSortedEcxFiles: %v", err)
t.Logf("WriteSortedEcxFile: %v", err)
}
removeGeneratedFiles(baseFileName)
}
func generateEcFiles(baseFileName string, bufferSize int, largeBlockSize int64, smallBlockSize int64) error {
file, err := os.OpenFile(baseFileName+".dat", os.O_RDONLY, 0)
if err != nil {
return fmt.Errorf("failed to open dat file: %v", err)
}
defer file.Close()
fi, err := file.Stat()
if err != nil {
return fmt.Errorf("failed to stat dat file: %v", err)
}
err = encodeDatFile(fi.Size(), err, baseFileName, bufferSize, largeBlockSize, file, smallBlockSize)
if err != nil {
return fmt.Errorf("encodeDatFile: %v", err)
}
return nil
}
func encodeDatFile(remainingSize int64, err error, baseFileName string, bufferSize int, largeBlockSize int64, file *os.File, smallBlockSize int64) error {
var processedSize int64
enc, err := reedsolomon.New(DataShardsCount, ParityShardsCount)
if err != nil {
return fmt.Errorf("failed to create encoder: %v", err)
}
buffers := make([][]byte, DataShardsCount+ParityShardsCount)
outputs, err := openEcFiles(baseFileName, false)
defer closeEcFiles(outputs)
if err != nil {
return fmt.Errorf("failed to open dat file: %v", err)
}
for i, _ := range buffers {
buffers[i] = make([]byte, bufferSize)
}
for remainingSize > largeBlockSize*DataShardsCount {
err = encodeData(file, enc, processedSize, largeBlockSize, buffers, outputs)
if err != nil {
return fmt.Errorf("failed to encode large chunk data: %v", err)
}
remainingSize -= largeBlockSize * DataShardsCount
processedSize += largeBlockSize * DataShardsCount
}
for remainingSize > 0 {
encodeData(file, enc, processedSize, smallBlockSize, buffers, outputs)
if err != nil {
return fmt.Errorf("failed to encode small chunk data: %v", err)
}
remainingSize -= smallBlockSize * DataShardsCount
processedSize += smallBlockSize * DataShardsCount
}
return nil
}
func writeSortedEcxFiles(baseFileName string) (e error) {
cm, err := readCompactMap(baseFileName)
if err != nil {
return fmt.Errorf("readCompactMap: %v", err)
}
ecxFile, err := os.OpenFile(baseFileName+".ecx", os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return fmt.Errorf("failed to open dat file: %v", err)
}
defer ecxFile.Close()
err = cm.AscendingVisit(func(value needle_map.NeedleValue) error {
bytes := value.ToBytes()
_, writeErr := ecxFile.Write(bytes)
return writeErr
})
if err != nil {
return fmt.Errorf("failed to open dat file: %v", err)
}
return nil
}
func validateFiles(baseFileName string) error {
cm, err := readCompactMap(baseFileName)
if err != nil {
@ -148,25 +69,6 @@ func validateFiles(baseFileName string) error {
return nil
}
func readCompactMap(baseFileName string) (*needle_map.CompactMap, error) {
indexFile, err := os.OpenFile(baseFileName+".idx", os.O_RDONLY, 0644)
if err != nil {
return nil, fmt.Errorf("cannot read Volume Index %s.idx: %v", baseFileName, err)
}
defer indexFile.Close()
cm := needle_map.NewCompactMap()
err = storage.WalkIndexFile(indexFile, func(key types.NeedleId, offset types.Offset, size uint32) error {
if !offset.IsZero() && size != types.TombstoneFileSize {
cm.Set(key, offset, size)
} else {
cm.Delete(key)
}
return nil
})
return cm, err
}
func assertSame(datFile *os.File, datSize int64, ecFiles []*os.File, offset types.Offset, size uint32) error {
data, err := readDatFile(datFile, offset, size)
@ -288,7 +190,7 @@ func removeGeneratedFiles(baseFileName string) {
fname := fmt.Sprintf("%s.ec%02d", baseFileName, i+1)
os.Remove(fname)
}
os.Remove(baseFileName+".ecx")
os.Remove(baseFileName + ".ecx")
}
func TestLocateData(t *testing.T) {

Loading…
Cancel
Save