tier storage: support downloading the remote dat files

This commit is contained in:
Chris Lu 2019-12-25 09:53:13 -08:00
parent 3ebeae0c0b
commit d960b3474a
11 changed files with 775 additions and 256 deletions

View file

@ -70,7 +70,9 @@ service VolumeServer {
} }
// tiered storage // tiered storage
rpc VolumeTierCopyDatToRemote (VolumeTierCopyDatToRemoteRequest) returns (stream VolumeTierCopyDatToRemoteResponse) { rpc VolumeTierMoveDatToRemote (VolumeTierMoveDatToRemoteRequest) returns (stream VolumeTierMoveDatToRemoteResponse) {
}
rpc VolumeTierMoveDatFromRemote (VolumeTierMoveDatFromRemoteRequest) returns (stream VolumeTierMoveDatFromRemoteResponse) {
} }
// query // query
@ -352,13 +354,23 @@ message VolumeTierInfo {
repeated RemoteFile files = 1; repeated RemoteFile files = 1;
} }
message VolumeTierCopyDatToRemoteRequest { message VolumeTierMoveDatToRemoteRequest {
uint32 volume_id = 1; uint32 volume_id = 1;
string collection = 2; string collection = 2;
string destination_backend_name = 3; string destination_backend_name = 3;
bool keep_local_dat_file = 4; bool keep_local_dat_file = 4;
} }
message VolumeTierCopyDatToRemoteResponse { message VolumeTierMoveDatToRemoteResponse {
int64 processed = 1;
float processedPercentage = 2;
}
message VolumeTierMoveDatFromRemoteRequest {
uint32 volume_id = 1;
string collection = 2;
bool keep_remote_dat_file = 3;
}
message VolumeTierMoveDatFromRemoteResponse {
int64 processed = 1; int64 processed = 1;
float processedPercentage = 2; float processedPercentage = 2;
} }

View file

@ -69,8 +69,10 @@ It has these top-level messages:
MemStatus MemStatus
RemoteFile RemoteFile
VolumeTierInfo VolumeTierInfo
VolumeTierCopyDatToRemoteRequest VolumeTierMoveDatToRemoteRequest
VolumeTierCopyDatToRemoteResponse VolumeTierMoveDatToRemoteResponse
VolumeTierMoveDatFromRemoteRequest
VolumeTierMoveDatFromRemoteResponse
QueryRequest QueryRequest
QueriedStripe QueriedStripe
*/ */
@ -1521,68 +1523,128 @@ func (m *VolumeTierInfo) GetFiles() []*RemoteFile {
return nil return nil
} }
type VolumeTierCopyDatToRemoteRequest struct { type VolumeTierMoveDatToRemoteRequest struct {
VolumeId uint32 `protobuf:"varint,1,opt,name=volume_id,json=volumeId" json:"volume_id,omitempty"` 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"` Collection string `protobuf:"bytes,2,opt,name=collection" json:"collection,omitempty"`
DestinationBackendName string `protobuf:"bytes,3,opt,name=destination_backend_name,json=destinationBackendName" json:"destination_backend_name,omitempty"` DestinationBackendName string `protobuf:"bytes,3,opt,name=destination_backend_name,json=destinationBackendName" json:"destination_backend_name,omitempty"`
KeepLocalDatFile bool `protobuf:"varint,4,opt,name=keep_local_dat_file,json=keepLocalDatFile" json:"keep_local_dat_file,omitempty"` KeepLocalDatFile bool `protobuf:"varint,4,opt,name=keep_local_dat_file,json=keepLocalDatFile" json:"keep_local_dat_file,omitempty"`
} }
func (m *VolumeTierCopyDatToRemoteRequest) Reset() { *m = VolumeTierCopyDatToRemoteRequest{} } func (m *VolumeTierMoveDatToRemoteRequest) Reset() { *m = VolumeTierMoveDatToRemoteRequest{} }
func (m *VolumeTierCopyDatToRemoteRequest) String() string { return proto.CompactTextString(m) } func (m *VolumeTierMoveDatToRemoteRequest) String() string { return proto.CompactTextString(m) }
func (*VolumeTierCopyDatToRemoteRequest) ProtoMessage() {} func (*VolumeTierMoveDatToRemoteRequest) ProtoMessage() {}
func (*VolumeTierCopyDatToRemoteRequest) Descriptor() ([]byte, []int) { func (*VolumeTierMoveDatToRemoteRequest) Descriptor() ([]byte, []int) {
return fileDescriptor0, []int{60} return fileDescriptor0, []int{60}
} }
func (m *VolumeTierCopyDatToRemoteRequest) GetVolumeId() uint32 { func (m *VolumeTierMoveDatToRemoteRequest) GetVolumeId() uint32 {
if m != nil { if m != nil {
return m.VolumeId return m.VolumeId
} }
return 0 return 0
} }
func (m *VolumeTierCopyDatToRemoteRequest) GetCollection() string { func (m *VolumeTierMoveDatToRemoteRequest) GetCollection() string {
if m != nil { if m != nil {
return m.Collection return m.Collection
} }
return "" return ""
} }
func (m *VolumeTierCopyDatToRemoteRequest) GetDestinationBackendName() string { func (m *VolumeTierMoveDatToRemoteRequest) GetDestinationBackendName() string {
if m != nil { if m != nil {
return m.DestinationBackendName return m.DestinationBackendName
} }
return "" return ""
} }
func (m *VolumeTierCopyDatToRemoteRequest) GetKeepLocalDatFile() bool { func (m *VolumeTierMoveDatToRemoteRequest) GetKeepLocalDatFile() bool {
if m != nil { if m != nil {
return m.KeepLocalDatFile return m.KeepLocalDatFile
} }
return false return false
} }
type VolumeTierCopyDatToRemoteResponse struct { type VolumeTierMoveDatToRemoteResponse struct {
Processed int64 `protobuf:"varint,1,opt,name=processed" json:"processed,omitempty"` Processed int64 `protobuf:"varint,1,opt,name=processed" json:"processed,omitempty"`
ProcessedPercentage float32 `protobuf:"fixed32,2,opt,name=processedPercentage" json:"processedPercentage,omitempty"` ProcessedPercentage float32 `protobuf:"fixed32,2,opt,name=processedPercentage" json:"processedPercentage,omitempty"`
} }
func (m *VolumeTierCopyDatToRemoteResponse) Reset() { *m = VolumeTierCopyDatToRemoteResponse{} } func (m *VolumeTierMoveDatToRemoteResponse) Reset() { *m = VolumeTierMoveDatToRemoteResponse{} }
func (m *VolumeTierCopyDatToRemoteResponse) String() string { return proto.CompactTextString(m) } func (m *VolumeTierMoveDatToRemoteResponse) String() string { return proto.CompactTextString(m) }
func (*VolumeTierCopyDatToRemoteResponse) ProtoMessage() {} func (*VolumeTierMoveDatToRemoteResponse) ProtoMessage() {}
func (*VolumeTierCopyDatToRemoteResponse) Descriptor() ([]byte, []int) { func (*VolumeTierMoveDatToRemoteResponse) Descriptor() ([]byte, []int) {
return fileDescriptor0, []int{61} return fileDescriptor0, []int{61}
} }
func (m *VolumeTierCopyDatToRemoteResponse) GetProcessed() int64 { func (m *VolumeTierMoveDatToRemoteResponse) GetProcessed() int64 {
if m != nil { if m != nil {
return m.Processed return m.Processed
} }
return 0 return 0
} }
func (m *VolumeTierCopyDatToRemoteResponse) GetProcessedPercentage() float32 { func (m *VolumeTierMoveDatToRemoteResponse) GetProcessedPercentage() float32 {
if m != nil {
return m.ProcessedPercentage
}
return 0
}
type VolumeTierMoveDatFromRemoteRequest 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"`
KeepRemoteDatFile bool `protobuf:"varint,3,opt,name=keep_remote_dat_file,json=keepRemoteDatFile" json:"keep_remote_dat_file,omitempty"`
}
func (m *VolumeTierMoveDatFromRemoteRequest) Reset() { *m = VolumeTierMoveDatFromRemoteRequest{} }
func (m *VolumeTierMoveDatFromRemoteRequest) String() string { return proto.CompactTextString(m) }
func (*VolumeTierMoveDatFromRemoteRequest) ProtoMessage() {}
func (*VolumeTierMoveDatFromRemoteRequest) Descriptor() ([]byte, []int) {
return fileDescriptor0, []int{62}
}
func (m *VolumeTierMoveDatFromRemoteRequest) GetVolumeId() uint32 {
if m != nil {
return m.VolumeId
}
return 0
}
func (m *VolumeTierMoveDatFromRemoteRequest) GetCollection() string {
if m != nil {
return m.Collection
}
return ""
}
func (m *VolumeTierMoveDatFromRemoteRequest) GetKeepRemoteDatFile() bool {
if m != nil {
return m.KeepRemoteDatFile
}
return false
}
type VolumeTierMoveDatFromRemoteResponse struct {
Processed int64 `protobuf:"varint,1,opt,name=processed" json:"processed,omitempty"`
ProcessedPercentage float32 `protobuf:"fixed32,2,opt,name=processedPercentage" json:"processedPercentage,omitempty"`
}
func (m *VolumeTierMoveDatFromRemoteResponse) Reset() { *m = VolumeTierMoveDatFromRemoteResponse{} }
func (m *VolumeTierMoveDatFromRemoteResponse) String() string { return proto.CompactTextString(m) }
func (*VolumeTierMoveDatFromRemoteResponse) ProtoMessage() {}
func (*VolumeTierMoveDatFromRemoteResponse) Descriptor() ([]byte, []int) {
return fileDescriptor0, []int{63}
}
func (m *VolumeTierMoveDatFromRemoteResponse) GetProcessed() int64 {
if m != nil {
return m.Processed
}
return 0
}
func (m *VolumeTierMoveDatFromRemoteResponse) GetProcessedPercentage() float32 {
if m != nil { if m != nil {
return m.ProcessedPercentage return m.ProcessedPercentage
} }
@ -1601,7 +1663,7 @@ type QueryRequest struct {
func (m *QueryRequest) Reset() { *m = QueryRequest{} } func (m *QueryRequest) Reset() { *m = QueryRequest{} }
func (m *QueryRequest) String() string { return proto.CompactTextString(m) } func (m *QueryRequest) String() string { return proto.CompactTextString(m) }
func (*QueryRequest) ProtoMessage() {} func (*QueryRequest) ProtoMessage() {}
func (*QueryRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{62} } func (*QueryRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{64} }
func (m *QueryRequest) GetSelections() []string { func (m *QueryRequest) GetSelections() []string {
if m != nil { if m != nil {
@ -1647,7 +1709,7 @@ type QueryRequest_Filter struct {
func (m *QueryRequest_Filter) Reset() { *m = QueryRequest_Filter{} } func (m *QueryRequest_Filter) Reset() { *m = QueryRequest_Filter{} }
func (m *QueryRequest_Filter) String() string { return proto.CompactTextString(m) } func (m *QueryRequest_Filter) String() string { return proto.CompactTextString(m) }
func (*QueryRequest_Filter) ProtoMessage() {} func (*QueryRequest_Filter) ProtoMessage() {}
func (*QueryRequest_Filter) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{62, 0} } func (*QueryRequest_Filter) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{64, 0} }
func (m *QueryRequest_Filter) GetField() string { func (m *QueryRequest_Filter) GetField() string {
if m != nil { if m != nil {
@ -1682,7 +1744,7 @@ func (m *QueryRequest_InputSerialization) Reset() { *m = QueryRequest_In
func (m *QueryRequest_InputSerialization) String() string { return proto.CompactTextString(m) } func (m *QueryRequest_InputSerialization) String() string { return proto.CompactTextString(m) }
func (*QueryRequest_InputSerialization) ProtoMessage() {} func (*QueryRequest_InputSerialization) ProtoMessage() {}
func (*QueryRequest_InputSerialization) Descriptor() ([]byte, []int) { func (*QueryRequest_InputSerialization) Descriptor() ([]byte, []int) {
return fileDescriptor0, []int{62, 1} return fileDescriptor0, []int{64, 1}
} }
func (m *QueryRequest_InputSerialization) GetCompressionType() string { func (m *QueryRequest_InputSerialization) GetCompressionType() string {
@ -1730,7 +1792,7 @@ func (m *QueryRequest_InputSerialization_CSVInput) Reset() {
func (m *QueryRequest_InputSerialization_CSVInput) String() string { return proto.CompactTextString(m) } func (m *QueryRequest_InputSerialization_CSVInput) String() string { return proto.CompactTextString(m) }
func (*QueryRequest_InputSerialization_CSVInput) ProtoMessage() {} func (*QueryRequest_InputSerialization_CSVInput) ProtoMessage() {}
func (*QueryRequest_InputSerialization_CSVInput) Descriptor() ([]byte, []int) { func (*QueryRequest_InputSerialization_CSVInput) Descriptor() ([]byte, []int) {
return fileDescriptor0, []int{62, 1, 0} return fileDescriptor0, []int{64, 1, 0}
} }
func (m *QueryRequest_InputSerialization_CSVInput) GetFileHeaderInfo() string { func (m *QueryRequest_InputSerialization_CSVInput) GetFileHeaderInfo() string {
@ -1792,7 +1854,7 @@ func (m *QueryRequest_InputSerialization_JSONInput) Reset() {
func (m *QueryRequest_InputSerialization_JSONInput) String() string { return proto.CompactTextString(m) } func (m *QueryRequest_InputSerialization_JSONInput) String() string { return proto.CompactTextString(m) }
func (*QueryRequest_InputSerialization_JSONInput) ProtoMessage() {} func (*QueryRequest_InputSerialization_JSONInput) ProtoMessage() {}
func (*QueryRequest_InputSerialization_JSONInput) Descriptor() ([]byte, []int) { func (*QueryRequest_InputSerialization_JSONInput) Descriptor() ([]byte, []int) {
return fileDescriptor0, []int{62, 1, 1} return fileDescriptor0, []int{64, 1, 1}
} }
func (m *QueryRequest_InputSerialization_JSONInput) GetType() string { func (m *QueryRequest_InputSerialization_JSONInput) GetType() string {
@ -1813,7 +1875,7 @@ func (m *QueryRequest_InputSerialization_ParquetInput) String() string {
} }
func (*QueryRequest_InputSerialization_ParquetInput) ProtoMessage() {} func (*QueryRequest_InputSerialization_ParquetInput) ProtoMessage() {}
func (*QueryRequest_InputSerialization_ParquetInput) Descriptor() ([]byte, []int) { func (*QueryRequest_InputSerialization_ParquetInput) Descriptor() ([]byte, []int) {
return fileDescriptor0, []int{62, 1, 2} return fileDescriptor0, []int{64, 1, 2}
} }
type QueryRequest_OutputSerialization struct { type QueryRequest_OutputSerialization struct {
@ -1825,7 +1887,7 @@ func (m *QueryRequest_OutputSerialization) Reset() { *m = QueryRequest_O
func (m *QueryRequest_OutputSerialization) String() string { return proto.CompactTextString(m) } func (m *QueryRequest_OutputSerialization) String() string { return proto.CompactTextString(m) }
func (*QueryRequest_OutputSerialization) ProtoMessage() {} func (*QueryRequest_OutputSerialization) ProtoMessage() {}
func (*QueryRequest_OutputSerialization) Descriptor() ([]byte, []int) { func (*QueryRequest_OutputSerialization) Descriptor() ([]byte, []int) {
return fileDescriptor0, []int{62, 2} return fileDescriptor0, []int{64, 2}
} }
func (m *QueryRequest_OutputSerialization) GetCsvOutput() *QueryRequest_OutputSerialization_CSVOutput { func (m *QueryRequest_OutputSerialization) GetCsvOutput() *QueryRequest_OutputSerialization_CSVOutput {
@ -1858,7 +1920,7 @@ func (m *QueryRequest_OutputSerialization_CSVOutput) String() string {
} }
func (*QueryRequest_OutputSerialization_CSVOutput) ProtoMessage() {} func (*QueryRequest_OutputSerialization_CSVOutput) ProtoMessage() {}
func (*QueryRequest_OutputSerialization_CSVOutput) Descriptor() ([]byte, []int) { func (*QueryRequest_OutputSerialization_CSVOutput) Descriptor() ([]byte, []int) {
return fileDescriptor0, []int{62, 2, 0} return fileDescriptor0, []int{64, 2, 0}
} }
func (m *QueryRequest_OutputSerialization_CSVOutput) GetQuoteFields() string { func (m *QueryRequest_OutputSerialization_CSVOutput) GetQuoteFields() string {
@ -1908,7 +1970,7 @@ func (m *QueryRequest_OutputSerialization_JSONOutput) String() string {
} }
func (*QueryRequest_OutputSerialization_JSONOutput) ProtoMessage() {} func (*QueryRequest_OutputSerialization_JSONOutput) ProtoMessage() {}
func (*QueryRequest_OutputSerialization_JSONOutput) Descriptor() ([]byte, []int) { func (*QueryRequest_OutputSerialization_JSONOutput) Descriptor() ([]byte, []int) {
return fileDescriptor0, []int{62, 2, 1} return fileDescriptor0, []int{64, 2, 1}
} }
func (m *QueryRequest_OutputSerialization_JSONOutput) GetRecordDelimiter() string { func (m *QueryRequest_OutputSerialization_JSONOutput) GetRecordDelimiter() string {
@ -1925,7 +1987,7 @@ type QueriedStripe struct {
func (m *QueriedStripe) Reset() { *m = QueriedStripe{} } func (m *QueriedStripe) Reset() { *m = QueriedStripe{} }
func (m *QueriedStripe) String() string { return proto.CompactTextString(m) } func (m *QueriedStripe) String() string { return proto.CompactTextString(m) }
func (*QueriedStripe) ProtoMessage() {} func (*QueriedStripe) ProtoMessage() {}
func (*QueriedStripe) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{63} } func (*QueriedStripe) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{65} }
func (m *QueriedStripe) GetRecords() []byte { func (m *QueriedStripe) GetRecords() []byte {
if m != nil { if m != nil {
@ -1995,8 +2057,10 @@ func init() {
proto.RegisterType((*MemStatus)(nil), "volume_server_pb.MemStatus") proto.RegisterType((*MemStatus)(nil), "volume_server_pb.MemStatus")
proto.RegisterType((*RemoteFile)(nil), "volume_server_pb.RemoteFile") proto.RegisterType((*RemoteFile)(nil), "volume_server_pb.RemoteFile")
proto.RegisterType((*VolumeTierInfo)(nil), "volume_server_pb.VolumeTierInfo") proto.RegisterType((*VolumeTierInfo)(nil), "volume_server_pb.VolumeTierInfo")
proto.RegisterType((*VolumeTierCopyDatToRemoteRequest)(nil), "volume_server_pb.VolumeTierCopyDatToRemoteRequest") proto.RegisterType((*VolumeTierMoveDatToRemoteRequest)(nil), "volume_server_pb.VolumeTierMoveDatToRemoteRequest")
proto.RegisterType((*VolumeTierCopyDatToRemoteResponse)(nil), "volume_server_pb.VolumeTierCopyDatToRemoteResponse") proto.RegisterType((*VolumeTierMoveDatToRemoteResponse)(nil), "volume_server_pb.VolumeTierMoveDatToRemoteResponse")
proto.RegisterType((*VolumeTierMoveDatFromRemoteRequest)(nil), "volume_server_pb.VolumeTierMoveDatFromRemoteRequest")
proto.RegisterType((*VolumeTierMoveDatFromRemoteResponse)(nil), "volume_server_pb.VolumeTierMoveDatFromRemoteResponse")
proto.RegisterType((*QueryRequest)(nil), "volume_server_pb.QueryRequest") proto.RegisterType((*QueryRequest)(nil), "volume_server_pb.QueryRequest")
proto.RegisterType((*QueryRequest_Filter)(nil), "volume_server_pb.QueryRequest.Filter") proto.RegisterType((*QueryRequest_Filter)(nil), "volume_server_pb.QueryRequest.Filter")
proto.RegisterType((*QueryRequest_InputSerialization)(nil), "volume_server_pb.QueryRequest.InputSerialization") proto.RegisterType((*QueryRequest_InputSerialization)(nil), "volume_server_pb.QueryRequest.InputSerialization")
@ -2051,7 +2115,8 @@ type VolumeServerClient interface {
VolumeEcBlobDelete(ctx context.Context, in *VolumeEcBlobDeleteRequest, opts ...grpc.CallOption) (*VolumeEcBlobDeleteResponse, error) VolumeEcBlobDelete(ctx context.Context, in *VolumeEcBlobDeleteRequest, opts ...grpc.CallOption) (*VolumeEcBlobDeleteResponse, error)
VolumeEcShardsToVolume(ctx context.Context, in *VolumeEcShardsToVolumeRequest, opts ...grpc.CallOption) (*VolumeEcShardsToVolumeResponse, error) VolumeEcShardsToVolume(ctx context.Context, in *VolumeEcShardsToVolumeRequest, opts ...grpc.CallOption) (*VolumeEcShardsToVolumeResponse, error)
// tiered storage // tiered storage
VolumeTierCopyDatToRemote(ctx context.Context, in *VolumeTierCopyDatToRemoteRequest, opts ...grpc.CallOption) (VolumeServer_VolumeTierCopyDatToRemoteClient, error) VolumeTierMoveDatToRemote(ctx context.Context, in *VolumeTierMoveDatToRemoteRequest, opts ...grpc.CallOption) (VolumeServer_VolumeTierMoveDatToRemoteClient, error)
VolumeTierMoveDatFromRemote(ctx context.Context, in *VolumeTierMoveDatFromRemoteRequest, opts ...grpc.CallOption) (VolumeServer_VolumeTierMoveDatFromRemoteClient, error)
// query // query
Query(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (VolumeServer_QueryClient, error) Query(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (VolumeServer_QueryClient, error)
} }
@ -2399,12 +2464,12 @@ func (c *volumeServerClient) VolumeEcShardsToVolume(ctx context.Context, in *Vol
return out, nil return out, nil
} }
func (c *volumeServerClient) VolumeTierCopyDatToRemote(ctx context.Context, in *VolumeTierCopyDatToRemoteRequest, opts ...grpc.CallOption) (VolumeServer_VolumeTierCopyDatToRemoteClient, error) { func (c *volumeServerClient) VolumeTierMoveDatToRemote(ctx context.Context, in *VolumeTierMoveDatToRemoteRequest, opts ...grpc.CallOption) (VolumeServer_VolumeTierMoveDatToRemoteClient, error) {
stream, err := grpc.NewClientStream(ctx, &_VolumeServer_serviceDesc.Streams[4], c.cc, "/volume_server_pb.VolumeServer/VolumeTierCopyDatToRemote", opts...) stream, err := grpc.NewClientStream(ctx, &_VolumeServer_serviceDesc.Streams[4], c.cc, "/volume_server_pb.VolumeServer/VolumeTierMoveDatToRemote", opts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
x := &volumeServerVolumeTierCopyDatToRemoteClient{stream} x := &volumeServerVolumeTierMoveDatToRemoteClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil { if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err return nil, err
} }
@ -2414,17 +2479,49 @@ func (c *volumeServerClient) VolumeTierCopyDatToRemote(ctx context.Context, in *
return x, nil return x, nil
} }
type VolumeServer_VolumeTierCopyDatToRemoteClient interface { type VolumeServer_VolumeTierMoveDatToRemoteClient interface {
Recv() (*VolumeTierCopyDatToRemoteResponse, error) Recv() (*VolumeTierMoveDatToRemoteResponse, error)
grpc.ClientStream grpc.ClientStream
} }
type volumeServerVolumeTierCopyDatToRemoteClient struct { type volumeServerVolumeTierMoveDatToRemoteClient struct {
grpc.ClientStream grpc.ClientStream
} }
func (x *volumeServerVolumeTierCopyDatToRemoteClient) Recv() (*VolumeTierCopyDatToRemoteResponse, error) { func (x *volumeServerVolumeTierMoveDatToRemoteClient) Recv() (*VolumeTierMoveDatToRemoteResponse, error) {
m := new(VolumeTierCopyDatToRemoteResponse) m := new(VolumeTierMoveDatToRemoteResponse)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *volumeServerClient) VolumeTierMoveDatFromRemote(ctx context.Context, in *VolumeTierMoveDatFromRemoteRequest, opts ...grpc.CallOption) (VolumeServer_VolumeTierMoveDatFromRemoteClient, error) {
stream, err := grpc.NewClientStream(ctx, &_VolumeServer_serviceDesc.Streams[5], c.cc, "/volume_server_pb.VolumeServer/VolumeTierMoveDatFromRemote", opts...)
if err != nil {
return nil, err
}
x := &volumeServerVolumeTierMoveDatFromRemoteClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
type VolumeServer_VolumeTierMoveDatFromRemoteClient interface {
Recv() (*VolumeTierMoveDatFromRemoteResponse, error)
grpc.ClientStream
}
type volumeServerVolumeTierMoveDatFromRemoteClient struct {
grpc.ClientStream
}
func (x *volumeServerVolumeTierMoveDatFromRemoteClient) Recv() (*VolumeTierMoveDatFromRemoteResponse, error) {
m := new(VolumeTierMoveDatFromRemoteResponse)
if err := x.ClientStream.RecvMsg(m); err != nil { if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err return nil, err
} }
@ -2432,7 +2529,7 @@ func (x *volumeServerVolumeTierCopyDatToRemoteClient) Recv() (*VolumeTierCopyDat
} }
func (c *volumeServerClient) Query(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (VolumeServer_QueryClient, error) { func (c *volumeServerClient) Query(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (VolumeServer_QueryClient, error) {
stream, err := grpc.NewClientStream(ctx, &_VolumeServer_serviceDesc.Streams[5], c.cc, "/volume_server_pb.VolumeServer/Query", opts...) stream, err := grpc.NewClientStream(ctx, &_VolumeServer_serviceDesc.Streams[6], c.cc, "/volume_server_pb.VolumeServer/Query", opts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -2497,7 +2594,8 @@ type VolumeServerServer interface {
VolumeEcBlobDelete(context.Context, *VolumeEcBlobDeleteRequest) (*VolumeEcBlobDeleteResponse, error) VolumeEcBlobDelete(context.Context, *VolumeEcBlobDeleteRequest) (*VolumeEcBlobDeleteResponse, error)
VolumeEcShardsToVolume(context.Context, *VolumeEcShardsToVolumeRequest) (*VolumeEcShardsToVolumeResponse, error) VolumeEcShardsToVolume(context.Context, *VolumeEcShardsToVolumeRequest) (*VolumeEcShardsToVolumeResponse, error)
// tiered storage // tiered storage
VolumeTierCopyDatToRemote(*VolumeTierCopyDatToRemoteRequest, VolumeServer_VolumeTierCopyDatToRemoteServer) error VolumeTierMoveDatToRemote(*VolumeTierMoveDatToRemoteRequest, VolumeServer_VolumeTierMoveDatToRemoteServer) error
VolumeTierMoveDatFromRemote(*VolumeTierMoveDatFromRemoteRequest, VolumeServer_VolumeTierMoveDatFromRemoteServer) error
// query // query
Query(*QueryRequest, VolumeServer_QueryServer) error Query(*QueryRequest, VolumeServer_QueryServer) error
} }
@ -3004,24 +3102,45 @@ func _VolumeServer_VolumeEcShardsToVolume_Handler(srv interface{}, ctx context.C
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _VolumeServer_VolumeTierCopyDatToRemote_Handler(srv interface{}, stream grpc.ServerStream) error { func _VolumeServer_VolumeTierMoveDatToRemote_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(VolumeTierCopyDatToRemoteRequest) m := new(VolumeTierMoveDatToRemoteRequest)
if err := stream.RecvMsg(m); err != nil { if err := stream.RecvMsg(m); err != nil {
return err return err
} }
return srv.(VolumeServerServer).VolumeTierCopyDatToRemote(m, &volumeServerVolumeTierCopyDatToRemoteServer{stream}) return srv.(VolumeServerServer).VolumeTierMoveDatToRemote(m, &volumeServerVolumeTierMoveDatToRemoteServer{stream})
} }
type VolumeServer_VolumeTierCopyDatToRemoteServer interface { type VolumeServer_VolumeTierMoveDatToRemoteServer interface {
Send(*VolumeTierCopyDatToRemoteResponse) error Send(*VolumeTierMoveDatToRemoteResponse) error
grpc.ServerStream grpc.ServerStream
} }
type volumeServerVolumeTierCopyDatToRemoteServer struct { type volumeServerVolumeTierMoveDatToRemoteServer struct {
grpc.ServerStream grpc.ServerStream
} }
func (x *volumeServerVolumeTierCopyDatToRemoteServer) Send(m *VolumeTierCopyDatToRemoteResponse) error { func (x *volumeServerVolumeTierMoveDatToRemoteServer) Send(m *VolumeTierMoveDatToRemoteResponse) error {
return x.ServerStream.SendMsg(m)
}
func _VolumeServer_VolumeTierMoveDatFromRemote_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(VolumeTierMoveDatFromRemoteRequest)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(VolumeServerServer).VolumeTierMoveDatFromRemote(m, &volumeServerVolumeTierMoveDatFromRemoteServer{stream})
}
type VolumeServer_VolumeTierMoveDatFromRemoteServer interface {
Send(*VolumeTierMoveDatFromRemoteResponse) error
grpc.ServerStream
}
type volumeServerVolumeTierMoveDatFromRemoteServer struct {
grpc.ServerStream
}
func (x *volumeServerVolumeTierMoveDatFromRemoteServer) Send(m *VolumeTierMoveDatFromRemoteResponse) error {
return x.ServerStream.SendMsg(m) return x.ServerStream.SendMsg(m)
} }
@ -3165,8 +3284,13 @@ var _VolumeServer_serviceDesc = grpc.ServiceDesc{
ServerStreams: true, ServerStreams: true,
}, },
{ {
StreamName: "VolumeTierCopyDatToRemote", StreamName: "VolumeTierMoveDatToRemote",
Handler: _VolumeServer_VolumeTierCopyDatToRemote_Handler, Handler: _VolumeServer_VolumeTierMoveDatToRemote_Handler,
ServerStreams: true,
},
{
StreamName: "VolumeTierMoveDatFromRemote",
Handler: _VolumeServer_VolumeTierMoveDatFromRemote_Handler,
ServerStreams: true, ServerStreams: true,
}, },
{ {
@ -3181,181 +3305,185 @@ var _VolumeServer_serviceDesc = grpc.ServiceDesc{
func init() { proto.RegisterFile("volume_server.proto", fileDescriptor0) } func init() { proto.RegisterFile("volume_server.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{ var fileDescriptor0 = []byte{
// 2811 bytes of a gzipped FileDescriptorProto // 2870 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xd4, 0x3a, 0x4b, 0x73, 0xdc, 0xc6, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xd4, 0x1a, 0x4d, 0x73, 0x1c, 0x47,
0xd1, 0x5c, 0x2e, 0x1f, 0xbb, 0xbd, 0x4b, 0x91, 0x1a, 0xd2, 0xd4, 0x0a, 0x7a, 0xd1, 0xf0, 0x4b, 0x55, 0xab, 0xd5, 0xc7, 0xee, 0xdb, 0x95, 0x25, 0xb7, 0x14, 0x79, 0x33, 0xfe, 0x52, 0xc6, 0xf9,
0x92, 0x2d, 0x4a, 0xa6, 0xbf, 0x2f, 0x76, 0xec, 0xd8, 0x89, 0x44, 0x4a, 0x89, 0x62, 0x8b, 0xb2, 0xb0, 0x9d, 0x58, 0x76, 0x94, 0x84, 0x84, 0x84, 0x04, 0x6c, 0xd9, 0x06, 0x93, 0x58, 0x4e, 0x46,
0x41, 0x59, 0x71, 0x62, 0x57, 0x50, 0x43, 0x60, 0x56, 0x84, 0x09, 0x60, 0x20, 0x60, 0x96, 0xd6, 0x8e, 0x09, 0x24, 0xc5, 0x54, 0x6b, 0xa6, 0x65, 0x4d, 0x34, 0x33, 0x3d, 0x9e, 0xe9, 0x95, 0xbd,
0xaa, 0x92, 0x93, 0x73, 0xc8, 0x25, 0xb7, 0x5c, 0x72, 0xce, 0x3d, 0x97, 0x1c, 0x52, 0x95, 0x5f, 0x2e, 0x38, 0x85, 0x03, 0x17, 0x38, 0x50, 0x5c, 0x38, 0x73, 0xe7, 0x4a, 0x15, 0x67, 0x0e, 0xf9,
0xe0, 0x3f, 0x90, 0x6b, 0x2e, 0x39, 0xe4, 0x94, 0x43, 0x6e, 0xa9, 0xca, 0x25, 0x35, 0x2f, 0x2c, 0x03, 0x5c, 0xb9, 0x70, 0xe0, 0xc4, 0x81, 0x1b, 0x55, 0x5c, 0xa8, 0xfe, 0x9a, 0x9d, 0x4f, 0xed,
0x9e, 0x5c, 0xd0, 0x52, 0x55, 0x2a, 0xb7, 0x41, 0x4f, 0x3f, 0xa6, 0x7b, 0xba, 0x7b, 0xa6, 0xa7, 0x28, 0x16, 0x45, 0x71, 0xeb, 0x79, 0xfd, 0x3e, 0xfa, 0xbd, 0x7e, 0xef, 0x75, 0xbf, 0x7e, 0x03,
0x01, 0xab, 0x47, 0xd4, 0x1f, 0x05, 0xc4, 0x4e, 0x48, 0x7c, 0x44, 0xe2, 0xcd, 0x28, 0xa6, 0x8c, 0xcb, 0x07, 0xd4, 0x1f, 0x06, 0xc4, 0x4e, 0x48, 0x7c, 0x40, 0xe2, 0xf5, 0x28, 0xa6, 0x8c, 0xa2,
0xa2, 0x95, 0x1c, 0xd0, 0x8e, 0xf6, 0xcd, 0xeb, 0x80, 0x6e, 0x61, 0xe6, 0x1c, 0xec, 0x10, 0x9f, 0xa5, 0x1c, 0xd0, 0x8e, 0x76, 0xcc, 0xab, 0x80, 0x6e, 0x60, 0xe6, 0xec, 0xdd, 0x24, 0x3e, 0x61,
0x30, 0x62, 0x91, 0xc7, 0x23, 0x92, 0x30, 0x74, 0x16, 0x3a, 0x43, 0xcf, 0x27, 0xb6, 0xe7, 0x26, 0xc4, 0x22, 0x8f, 0x86, 0x24, 0x61, 0xe8, 0x79, 0xe8, 0xec, 0x7a, 0x3e, 0xb1, 0x3d, 0x37, 0x19,
0x83, 0xd6, 0x46, 0xfb, 0x72, 0xd7, 0x5a, 0xe4, 0xdf, 0x77, 0xdd, 0xc4, 0xbc, 0x0f, 0xab, 0x39, 0xb4, 0xd6, 0xda, 0x17, 0xbb, 0xd6, 0x3c, 0xff, 0xbe, 0xe3, 0x26, 0xe6, 0x3d, 0x58, 0xce, 0x11,
0x82, 0x24, 0xa2, 0x61, 0x42, 0xd0, 0x3b, 0xb0, 0x18, 0x93, 0x64, 0xe4, 0x33, 0x49, 0xd0, 0xdb, 0x24, 0x11, 0x0d, 0x13, 0x82, 0xde, 0x81, 0xf9, 0x98, 0x24, 0x43, 0x9f, 0x49, 0x82, 0xde, 0xc6,
0xba, 0xb8, 0x59, 0x94, 0xb5, 0x99, 0x92, 0x8c, 0x7c, 0x66, 0x69, 0x74, 0xf3, 0xeb, 0x16, 0xf4, 0xb9, 0xf5, 0xa2, 0xac, 0xf5, 0x94, 0x64, 0xe8, 0x33, 0x4b, 0xa3, 0x9b, 0x5f, 0xb5, 0xa0, 0x9f,
0xb3, 0x33, 0xe8, 0x0c, 0x2c, 0x2a, 0xe1, 0x83, 0xd6, 0x46, 0xeb, 0x72, 0xd7, 0x5a, 0x90, 0xb2, 0x9d, 0x41, 0xa7, 0x60, 0x5e, 0x09, 0x1f, 0xb4, 0xd6, 0x5a, 0x17, 0xbb, 0xd6, 0x9c, 0x94, 0x8d,
0xd1, 0x3a, 0x2c, 0x24, 0x0c, 0xb3, 0x51, 0x32, 0x98, 0xdd, 0x68, 0x5d, 0x9e, 0xb7, 0xd4, 0x17, 0x56, 0x61, 0x2e, 0x61, 0x98, 0x0d, 0x93, 0xc1, 0xf4, 0x5a, 0xeb, 0xe2, 0xac, 0xa5, 0xbe, 0xd0,
0x5a, 0x83, 0x79, 0x12, 0xc7, 0x34, 0x1e, 0xb4, 0x05, 0xba, 0xfc, 0x40, 0x08, 0xe6, 0x12, 0xef, 0x0a, 0xcc, 0x92, 0x38, 0xa6, 0xf1, 0xa0, 0x2d, 0xd0, 0xe5, 0x07, 0x42, 0x30, 0x93, 0x78, 0x4f,
0x29, 0x19, 0xcc, 0x6d, 0xb4, 0x2e, 0x2f, 0x59, 0x62, 0x8c, 0x06, 0xb0, 0x78, 0x44, 0xe2, 0xc4, 0xc9, 0x60, 0x66, 0xad, 0x75, 0x71, 0xc1, 0x12, 0x63, 0x34, 0x80, 0xf9, 0x03, 0x12, 0x27, 0x1e,
0xa3, 0xe1, 0x60, 0x5e, 0x80, 0xf5, 0xa7, 0xb9, 0x08, 0xf3, 0xb7, 0x83, 0x88, 0x8d, 0xcd, 0xb7, 0x0d, 0x07, 0xb3, 0x02, 0xac, 0x3f, 0xcd, 0x79, 0x98, 0xbd, 0x15, 0x44, 0x6c, 0x64, 0xbe, 0x0d,
0x61, 0xf0, 0x10, 0x3b, 0xa3, 0x51, 0xf0, 0x50, 0x2c, 0x7f, 0xfb, 0x80, 0x38, 0x87, 0xda, 0x2c, 0x83, 0x07, 0xd8, 0x19, 0x0e, 0x83, 0x07, 0x62, 0xf9, 0x9b, 0x7b, 0xc4, 0xd9, 0xd7, 0x66, 0x39,
0xe7, 0xa0, 0xab, 0x94, 0x52, 0x6b, 0x5b, 0xb2, 0x3a, 0x12, 0x70, 0xd7, 0x35, 0x7f, 0x00, 0x67, 0x0d, 0x5d, 0xa5, 0x94, 0x5a, 0xdb, 0x82, 0xd5, 0x91, 0x80, 0x3b, 0xae, 0xf9, 0x3d, 0x78, 0xbe,
0x2b, 0x08, 0x95, 0x79, 0x5e, 0x82, 0xa5, 0x47, 0x38, 0xde, 0xc7, 0x8f, 0x88, 0x1d, 0x63, 0xe6, 0x82, 0x50, 0x99, 0xe7, 0x02, 0x2c, 0x3c, 0xc4, 0xf1, 0x0e, 0x7e, 0x48, 0xec, 0x18, 0x33, 0x8f,
0x51, 0x41, 0xdd, 0xb2, 0xfa, 0x0a, 0x68, 0x71, 0x98, 0xf9, 0x39, 0x18, 0x39, 0x0e, 0x34, 0x88, 0x0a, 0xea, 0x96, 0xd5, 0x57, 0x40, 0x8b, 0xc3, 0xcc, 0xcf, 0xc1, 0xc8, 0x71, 0xa0, 0x41, 0x84,
0xb0, 0xc3, 0x9a, 0x08, 0x47, 0x1b, 0xd0, 0x8b, 0x62, 0x82, 0x7d, 0x9f, 0x3a, 0x98, 0x11, 0x61, 0x1d, 0xd6, 0x44, 0x38, 0x5a, 0x83, 0x5e, 0x14, 0x13, 0xec, 0xfb, 0xd4, 0xc1, 0x8c, 0x08, 0xfb,
0x9f, 0xb6, 0x95, 0x05, 0x99, 0x17, 0xe0, 0x5c, 0x25, 0x73, 0xb9, 0x40, 0xf3, 0x9d, 0xc2, 0xea, 0xb4, 0xad, 0x2c, 0xc8, 0x3c, 0x0b, 0xa7, 0x2b, 0x99, 0xcb, 0x05, 0x9a, 0xef, 0x14, 0x56, 0x4f,
0x69, 0x10, 0x78, 0x8d, 0x44, 0x9b, 0xe7, 0x4b, 0xab, 0x16, 0x94, 0x8a, 0xef, 0x77, 0x0b, 0xb3, 0x83, 0xc0, 0x6b, 0x24, 0xda, 0x3c, 0x53, 0x5a, 0xb5, 0xa0, 0x54, 0x7c, 0xbf, 0x5d, 0x98, 0xf5,
0x3e, 0xc1, 0xe1, 0x28, 0x6a, 0xc4, 0xb8, 0xb8, 0x62, 0x4d, 0x9a, 0x72, 0x3e, 0x23, 0xdd, 0x66, 0x09, 0x0e, 0x87, 0x51, 0x23, 0xc6, 0xc5, 0x15, 0x6b, 0xd2, 0x94, 0xf3, 0x29, 0xe9, 0x36, 0x9b,
0x9b, 0xfa, 0x3e, 0x71, 0x98, 0x47, 0x43, 0xcd, 0xf6, 0x22, 0x80, 0x93, 0x02, 0x95, 0x13, 0x65, 0xd4, 0xf7, 0x89, 0xc3, 0x3c, 0x1a, 0x6a, 0xb6, 0xe7, 0x00, 0x9c, 0x14, 0xa8, 0x9c, 0x28, 0x03,
0x20, 0xa6, 0x01, 0x83, 0x32, 0xa9, 0x62, 0xfb, 0xd7, 0x16, 0xbc, 0x70, 0x53, 0x19, 0x4d, 0x0a, 0x31, 0x0d, 0x18, 0x94, 0x49, 0x15, 0xdb, 0xbf, 0xb6, 0xe0, 0xb9, 0xeb, 0xca, 0x68, 0x52, 0x70,
0x6e, 0xb4, 0x01, 0x79, 0x91, 0xb3, 0x45, 0x91, 0xc5, 0x0d, 0x6a, 0x97, 0x36, 0x88, 0x63, 0xc4, 0xa3, 0x0d, 0xc8, 0x8b, 0x9c, 0x2e, 0x8a, 0x2c, 0x6e, 0x50, 0xbb, 0xb4, 0x41, 0x1c, 0x23, 0x26,
0x24, 0xf2, 0x3d, 0x07, 0x0b, 0x16, 0x73, 0x82, 0x45, 0x16, 0x84, 0x56, 0xa0, 0xcd, 0x98, 0x2f, 0x91, 0xef, 0x39, 0x58, 0xb0, 0x98, 0x11, 0x2c, 0xb2, 0x20, 0xb4, 0x04, 0x6d, 0xc6, 0x7c, 0xe1,
0x3c, 0xb7, 0x6b, 0xf1, 0x21, 0xda, 0x82, 0xf5, 0x80, 0x04, 0x34, 0x1e, 0xdb, 0x01, 0x8e, 0xec, 0xb9, 0x5d, 0x8b, 0x0f, 0xd1, 0x06, 0xac, 0x06, 0x24, 0xa0, 0xf1, 0xc8, 0x0e, 0x70, 0x64, 0x07,
0x00, 0x3f, 0xb1, 0xb9, 0x9b, 0xdb, 0xc1, 0xfe, 0x60, 0x41, 0xac, 0x0f, 0xc9, 0xd9, 0x7b, 0x38, 0xf8, 0x89, 0xcd, 0xdd, 0xdc, 0x0e, 0x76, 0x06, 0x73, 0x62, 0x7d, 0x48, 0xce, 0xde, 0xc5, 0xd1,
0xba, 0x87, 0x9f, 0xec, 0x79, 0x4f, 0xc9, 0xbd, 0x7d, 0x73, 0x00, 0xeb, 0x45, 0xfd, 0x94, 0xea, 0x5d, 0xfc, 0x64, 0xdb, 0x7b, 0x4a, 0xee, 0xee, 0x98, 0x03, 0x58, 0x2d, 0xea, 0xa7, 0x54, 0xff,
0xdf, 0x81, 0x33, 0x12, 0xb2, 0x37, 0x0e, 0x9d, 0x3d, 0x11, 0x5b, 0x8d, 0x36, 0xea, 0xdf, 0x2d, 0x16, 0x9c, 0x92, 0x90, 0xed, 0x51, 0xe8, 0x6c, 0x8b, 0xd8, 0x6a, 0xb4, 0x51, 0xff, 0x6e, 0xc1,
0x18, 0x94, 0x09, 0x95, 0xe7, 0x3f, 0xab, 0xd5, 0x4e, 0x6c, 0x93, 0x4b, 0xd0, 0x63, 0xd8, 0xf3, 0xa0, 0x4c, 0xa8, 0x3c, 0xff, 0x59, 0xad, 0x76, 0x64, 0x9b, 0x9c, 0x87, 0x1e, 0xc3, 0x9e, 0x6f,
0x6d, 0x3a, 0x1c, 0x26, 0x84, 0x09, 0x43, 0xcc, 0x59, 0xc0, 0x41, 0xf7, 0x05, 0x04, 0x5d, 0x81, 0xd3, 0xdd, 0xdd, 0x84, 0x30, 0x61, 0x88, 0x19, 0x0b, 0x38, 0xe8, 0x9e, 0x80, 0xa0, 0x4b, 0xb0,
0x15, 0x47, 0x7a, 0xbf, 0x1d, 0x93, 0x23, 0x4f, 0x64, 0x83, 0x45, 0xb1, 0xb0, 0x65, 0x47, 0x47, 0xe4, 0x48, 0xef, 0xb7, 0x63, 0x72, 0xe0, 0x89, 0x6c, 0x30, 0x2f, 0x16, 0xb6, 0xe8, 0xe8, 0xa8,
0x85, 0x04, 0x23, 0x13, 0x96, 0x3c, 0xf7, 0x89, 0x2d, 0xd2, 0x91, 0x48, 0x26, 0x1d, 0xc1, 0xad, 0x90, 0x60, 0x64, 0xc2, 0x82, 0xe7, 0x3e, 0xb1, 0x45, 0x3a, 0x12, 0xc9, 0xa4, 0x23, 0xb8, 0xf5,
0xe7, 0xb9, 0x4f, 0xee, 0x78, 0x3e, 0xe1, 0x16, 0x35, 0x1f, 0xc2, 0x79, 0xa9, 0xfc, 0xdd, 0xd0, 0x3c, 0xf7, 0xc9, 0x6d, 0xcf, 0x27, 0xdc, 0xa2, 0xe6, 0x03, 0x38, 0x23, 0x95, 0xbf, 0x13, 0x3a,
0x89, 0x49, 0x40, 0x42, 0x86, 0xfd, 0x6d, 0x1a, 0x8d, 0x1b, 0xb9, 0xcd, 0x59, 0xe8, 0x24, 0x5e, 0x31, 0x09, 0x48, 0xc8, 0xb0, 0xbf, 0x49, 0xa3, 0x51, 0x23, 0xb7, 0x79, 0x1e, 0x3a, 0x89, 0x17,
0xe8, 0x10, 0x3b, 0x94, 0x49, 0x6d, 0xce, 0x5a, 0x14, 0xdf, 0xbb, 0x89, 0x79, 0x0b, 0x2e, 0xd4, 0x3a, 0xc4, 0x0e, 0x65, 0x52, 0x9b, 0xb1, 0xe6, 0xc5, 0xf7, 0x56, 0x62, 0xde, 0x80, 0xb3, 0x35,
0xf0, 0x55, 0x96, 0x7d, 0x11, 0xfa, 0x62, 0x61, 0x0e, 0x0d, 0x19, 0x09, 0x99, 0xe0, 0xdd, 0xb7, 0x7c, 0x95, 0x65, 0x5f, 0x80, 0xbe, 0x58, 0x98, 0x43, 0x43, 0x46, 0x42, 0x26, 0x78, 0xf7, 0xad,
0x7a, 0x1c, 0xb6, 0x2d, 0x41, 0xe6, 0x9b, 0x80, 0x24, 0x8f, 0x7b, 0x74, 0x14, 0x36, 0x0b, 0xe7, 0x1e, 0x87, 0x6d, 0x4a, 0x90, 0xf9, 0x3a, 0x20, 0xc9, 0xe3, 0x2e, 0x1d, 0x86, 0xcd, 0xc2, 0xf9,
0x17, 0x60, 0x35, 0x47, 0xa2, 0x7c, 0xe3, 0x2d, 0x58, 0x93, 0xe0, 0x4f, 0xc3, 0xa0, 0x31, 0xaf, 0x39, 0x58, 0xce, 0x91, 0x28, 0xdf, 0x78, 0x03, 0x56, 0x24, 0xf8, 0xd3, 0x30, 0x68, 0xcc, 0xeb,
0x33, 0xf0, 0x42, 0x81, 0x48, 0x71, 0xdb, 0xd2, 0x42, 0xf2, 0xc7, 0xce, 0xb1, 0xcc, 0xd6, 0xf5, 0x14, 0x3c, 0x57, 0x20, 0x52, 0xdc, 0x36, 0xb4, 0x90, 0xfc, 0xb1, 0x73, 0x28, 0xb3, 0x55, 0xbd,
0x0a, 0xf2, 0x27, 0x8f, 0xc8, 0x5c, 0x72, 0xc1, 0x38, 0x3e, 0xb4, 0x08, 0x76, 0x69, 0xe8, 0x8f, 0x82, 0xfc, 0xc9, 0x23, 0x32, 0x97, 0x5c, 0x30, 0x8e, 0xf7, 0x2d, 0x82, 0x5d, 0x1a, 0xfa, 0xa3,
0x1b, 0x67, 0xae, 0x0a, 0x4a, 0xc5, 0xf7, 0x0f, 0x2d, 0x38, 0xad, 0x53, 0x5a, 0xc3, 0xdd, 0x3c, 0xc6, 0x99, 0xab, 0x82, 0x52, 0xf1, 0xfd, 0x43, 0x0b, 0x4e, 0xea, 0x94, 0xd6, 0x70, 0x37, 0x8f,
0xa1, 0x3b, 0xb7, 0x6b, 0xdd, 0x79, 0x6e, 0xe2, 0xce, 0x97, 0x61, 0x25, 0xa1, 0xa3, 0xd8, 0x21, 0xe8, 0xce, 0xed, 0x5a, 0x77, 0x9e, 0x19, 0xbb, 0xf3, 0x45, 0x58, 0x4a, 0xe8, 0x30, 0x76, 0x88,
0xb6, 0x8b, 0x19, 0xb6, 0x43, 0xea, 0x12, 0xe5, 0xed, 0xa7, 0x24, 0x7c, 0x07, 0x33, 0xbc, 0x4b, 0xed, 0x62, 0x86, 0xed, 0x90, 0xba, 0x44, 0x79, 0xfb, 0x09, 0x09, 0xbf, 0x89, 0x19, 0xde, 0xa2,
0x5d, 0x62, 0x7e, 0x5f, 0x6f, 0x76, 0xce, 0x4b, 0xae, 0xc0, 0x69, 0x1f, 0x27, 0xcc, 0xc6, 0x51, 0x2e, 0x31, 0xbf, 0xab, 0x37, 0x3b, 0xe7, 0x25, 0x97, 0xe0, 0xa4, 0x8f, 0x13, 0x66, 0xe3, 0x28,
0x44, 0x42, 0xd7, 0xc6, 0x8c, 0xbb, 0x5a, 0x4b, 0xb8, 0xda, 0x29, 0x3e, 0x71, 0x53, 0xc0, 0x6f, 0x22, 0xa1, 0x6b, 0x63, 0xc6, 0x5d, 0xad, 0x25, 0x5c, 0xed, 0x04, 0x9f, 0xb8, 0x2e, 0xe0, 0xd7,
0xb2, 0xdd, 0xc4, 0xfc, 0xed, 0x2c, 0x2c, 0x73, 0x5a, 0xee, 0xda, 0x8d, 0xf4, 0x5d, 0x81, 0x36, 0xd9, 0x56, 0x62, 0xfe, 0x76, 0x1a, 0x16, 0x39, 0x2d, 0x77, 0xed, 0x46, 0xfa, 0x2e, 0x41, 0x9b,
0x79, 0xc2, 0x94, 0xa2, 0x7c, 0x88, 0xae, 0xc3, 0xaa, 0x8a, 0x21, 0x8f, 0x86, 0x93, 0xf0, 0x6a, 0x3c, 0x61, 0x4a, 0x51, 0x3e, 0x44, 0x57, 0x61, 0x59, 0xc5, 0x90, 0x47, 0xc3, 0x71, 0x78, 0xb5,
0xcb, 0x6c, 0x34, 0x99, 0x4a, 0x23, 0xec, 0x12, 0xf4, 0x12, 0x46, 0x23, 0x1d, 0xad, 0x73, 0x32, 0x65, 0x36, 0x1a, 0x4f, 0xa5, 0x11, 0x76, 0x1e, 0x7a, 0x09, 0xa3, 0x91, 0x8e, 0xd6, 0x19, 0x19,
0x5a, 0x39, 0x48, 0x45, 0x6b, 0xde, 0xa6, 0xf3, 0x15, 0x36, 0xed, 0x7b, 0x89, 0x4d, 0x1c, 0x5b, 0xad, 0x1c, 0xa4, 0xa2, 0x35, 0x6f, 0xd3, 0xd9, 0x0a, 0x9b, 0xf6, 0xbd, 0xc4, 0x26, 0x8e, 0x2d,
0xae, 0x4a, 0xc4, 0x7b, 0xc7, 0x02, 0x2f, 0xb9, 0xed, 0x48, 0x6b, 0xa0, 0x0f, 0xe0, 0xbc, 0xf7, 0x57, 0x25, 0xe2, 0xbd, 0x63, 0x81, 0x97, 0xdc, 0x72, 0xa4, 0x35, 0xd0, 0x07, 0x70, 0xc6, 0x7b,
0x28, 0xa4, 0x31, 0xb1, 0x95, 0x21, 0x45, 0xd4, 0x84, 0x94, 0xd9, 0x43, 0x3a, 0x0a, 0x5d, 0x11, 0x18, 0xd2, 0x98, 0xd8, 0xca, 0x90, 0x22, 0x6a, 0x42, 0xca, 0xec, 0x5d, 0x3a, 0x0c, 0x5d, 0x11,
0xfb, 0x1d, 0x6b, 0x20, 0x71, 0xf6, 0x04, 0x0a, 0xb7, 0xc0, 0x2e, 0x65, 0x77, 0xf8, 0xbc, 0xf9, 0xfb, 0x1d, 0x6b, 0x20, 0x71, 0xb6, 0x05, 0x0a, 0xb7, 0xc0, 0x16, 0x65, 0xb7, 0xf9, 0xbc, 0xf9,
0xff, 0xb0, 0x32, 0xb1, 0x4a, 0xf3, 0xd8, 0xfb, 0xba, 0xa5, 0xd3, 0xe9, 0x03, 0xec, 0xf9, 0x7b, 0x16, 0x2c, 0x8d, 0xad, 0xd2, 0x3c, 0xf6, 0xbe, 0x6a, 0xe9, 0x74, 0x7a, 0x1f, 0x7b, 0xfe, 0x36,
0x24, 0x74, 0x49, 0xfc, 0x8c, 0x39, 0x01, 0xdd, 0x80, 0x35, 0xcf, 0xf5, 0x89, 0xcd, 0xbc, 0x80, 0x09, 0x5d, 0x12, 0x3f, 0x63, 0x4e, 0x40, 0xd7, 0x60, 0xc5, 0x73, 0x7d, 0x62, 0x33, 0x2f, 0x20,
0xd0, 0x11, 0xb3, 0x13, 0xe2, 0xd0, 0xd0, 0x4d, 0xb4, 0x7d, 0xf9, 0xdc, 0x03, 0x39, 0xb5, 0x27, 0x74, 0xc8, 0xec, 0x84, 0x38, 0x34, 0x74, 0x13, 0x6d, 0x5f, 0x3e, 0x77, 0x5f, 0x4e, 0x6d, 0xcb,
0x67, 0xcc, 0x5f, 0xa5, 0xb9, 0x39, 0xbb, 0x8a, 0xc9, 0xad, 0x24, 0x24, 0x84, 0x33, 0x3c, 0x20, 0x19, 0xf3, 0x17, 0x69, 0x6e, 0xce, 0xae, 0x62, 0x7c, 0x2b, 0x09, 0x09, 0xe1, 0x0c, 0xf7, 0x08,
0xd8, 0x25, 0xb1, 0x52, 0xa3, 0x2f, 0x81, 0x3f, 0x12, 0x30, 0xbe, 0x43, 0x0a, 0x69, 0x9f, 0xba, 0x76, 0x49, 0xac, 0xd4, 0xe8, 0x4b, 0xe0, 0x0f, 0x04, 0x8c, 0xef, 0x90, 0x42, 0xda, 0xa1, 0xee,
0x63, 0xb1, 0xa2, 0xbe, 0x05, 0x12, 0x74, 0x8b, 0xba, 0x63, 0x91, 0x24, 0x13, 0x5b, 0x38, 0x99, 0x48, 0xac, 0xa8, 0x6f, 0x81, 0x04, 0xdd, 0xa0, 0xee, 0x48, 0x24, 0xc9, 0xc4, 0x16, 0x4e, 0xe6,
0x73, 0x30, 0x0a, 0x0f, 0xc5, 0x6a, 0x3a, 0x56, 0xcf, 0x4b, 0x3e, 0xc2, 0x09, 0xdb, 0xe6, 0x20, 0xec, 0x0d, 0xc3, 0x7d, 0xb1, 0x9a, 0x8e, 0xd5, 0xf3, 0x92, 0x8f, 0x70, 0xc2, 0x36, 0x39, 0xc8,
0xf3, 0x4f, 0x2d, 0x1d, 0xa5, 0x7c, 0x19, 0x16, 0x71, 0x88, 0x77, 0xf4, 0x5f, 0x30, 0x07, 0xa7, 0xfc, 0x63, 0x4b, 0x47, 0x29, 0x5f, 0x86, 0x45, 0x1c, 0xe2, 0x1d, 0xfc, 0x0f, 0xcc, 0xc1, 0x29,
0x50, 0x4e, 0x90, 0xbb, 0x9d, 0xaa, 0x80, 0x43, 0x72, 0x4e, 0x9d, 0x65, 0x62, 0x66, 0x92, 0x24, 0x94, 0x13, 0xe4, 0x6e, 0xa7, 0x2a, 0xe0, 0x90, 0x9c, 0x53, 0x67, 0x99, 0x98, 0x19, 0x27, 0x89,
0xf2, 0x0b, 0x57, 0x49, 0xe2, 0x0b, 0x9d, 0xa4, 0x6f, 0x3b, 0x7b, 0x07, 0x38, 0x76, 0x93, 0x1f, 0xfc, 0xc2, 0x55, 0x92, 0xf8, 0x42, 0x27, 0xe9, 0x5b, 0xce, 0xf6, 0x1e, 0x8e, 0xdd, 0xe4, 0xfb,
0x92, 0x90, 0xc4, 0x98, 0x3d, 0x97, 0x4b, 0x83, 0xb9, 0x01, 0x17, 0xeb, 0xb8, 0x2b, 0xf9, 0x9f, 0x24, 0x24, 0x31, 0x66, 0xc7, 0x72, 0x69, 0x30, 0xd7, 0xe0, 0x5c, 0x1d, 0x77, 0x25, 0xff, 0x73,
0xeb, 0xc3, 0x47, 0x63, 0x58, 0x64, 0x7f, 0xe4, 0xf9, 0xee, 0x73, 0x11, 0xff, 0x61, 0x51, 0xb9, 0x7d, 0xf8, 0x68, 0x0c, 0x8b, 0xec, 0x0c, 0x3d, 0xdf, 0x3d, 0x16, 0xf1, 0x1f, 0x16, 0x95, 0x4b,
0x94, 0xb9, 0xf2, 0x9f, 0xab, 0x70, 0x3a, 0x16, 0x20, 0x66, 0x27, 0x1c, 0x21, 0xad, 0x17, 0x96, 0x99, 0x2b, 0xff, 0xb9, 0x0c, 0x27, 0x63, 0x01, 0x62, 0x76, 0xc2, 0x11, 0xd2, 0x7a, 0x61, 0xc1,
0xac, 0x65, 0x35, 0x21, 0x08, 0x79, 0xdd, 0xf0, 0xf7, 0xd4, 0x03, 0x34, 0xb7, 0xe7, 0x96, 0x56, 0x5a, 0x54, 0x13, 0x82, 0x90, 0xd7, 0x0d, 0x7f, 0x4f, 0x3d, 0x40, 0x73, 0x3b, 0xb6, 0xb4, 0x7a,
0xcf, 0x41, 0x77, 0x22, 0xbe, 0x2d, 0xc4, 0x77, 0x12, 0x25, 0x97, 0x7b, 0xa7, 0x43, 0xa3, 0xb1, 0x1a, 0xba, 0x63, 0xf1, 0x6d, 0x21, 0xbe, 0x93, 0x28, 0xb9, 0xdc, 0x3b, 0x1d, 0x1a, 0x8d, 0x6c,
0x4d, 0x1c, 0x79, 0x8e, 0x8b, 0xad, 0xee, 0x58, 0x3d, 0x0e, 0xbc, 0xed, 0x88, 0x63, 0xbc, 0x79, 0xe2, 0xc8, 0x73, 0x5c, 0x6c, 0x75, 0xc7, 0xea, 0x71, 0xe0, 0x2d, 0x47, 0x1c, 0xe3, 0xcd, 0x73,
0x8e, 0xcd, 0x70, 0xfb, 0x52, 0x72, 0x5b, 0xc8, 0x72, 0xfb, 0x92, 0x73, 0x9b, 0x78, 0x4c, 0x5e, 0x6c, 0x86, 0xdb, 0x97, 0x92, 0xdb, 0x5c, 0x96, 0xdb, 0x97, 0x9c, 0xdb, 0xd8, 0x63, 0xf2, 0x8a,
0x51, 0xb5, 0x63, 0x5f, 0xc1, 0xb9, 0xfc, 0x6c, 0xf3, 0x23, 0xf0, 0x99, 0x0c, 0x61, 0x5e, 0x2c, 0xaa, 0x1d, 0x7b, 0x0c, 0xa7, 0xf3, 0xb3, 0xcd, 0x8f, 0xc0, 0x67, 0x32, 0x84, 0x79, 0xae, 0xe8,
0xba, 0x4a, 0xe1, 0x1c, 0x3d, 0x2a, 0x2e, 0xbb, 0xf1, 0x9d, 0xe1, 0xd9, 0xd6, 0x75, 0xa1, 0x68, 0x2a, 0x85, 0x73, 0xf4, 0xa0, 0xb8, 0xec, 0xc6, 0x77, 0x86, 0x67, 0x5b, 0xd7, 0xd9, 0xa2, 0x41,
0x90, 0xfc, 0xc5, 0xe3, 0xb3, 0xe2, 0xb2, 0x4f, 0x70, 0x01, 0x39, 0x5e, 0xf0, 0xa5, 0xa2, 0x7b, 0xf2, 0x17, 0x8f, 0xcf, 0x8a, 0xcb, 0x3e, 0xc2, 0x05, 0xe4, 0x70, 0xc1, 0xe7, 0x8b, 0xee, 0x5d,
0x17, 0x6f, 0x29, 0xbf, 0x4b, 0x73, 0xa7, 0xc2, 0xe0, 0x77, 0x84, 0xc6, 0x39, 0x4b, 0xc9, 0x15, 0xbc, 0xa5, 0xfc, 0x2e, 0xcd, 0x9d, 0x0a, 0x83, 0xdf, 0x11, 0x1a, 0xe7, 0x2c, 0x25, 0x57, 0x98,
0xe6, 0x58, 0xb2, 0x16, 0x95, 0x58, 0x5e, 0xc4, 0xaa, 0xb3, 0x4e, 0xd6, 0x00, 0xea, 0x2b, 0x57, 0x63, 0xc1, 0x9a, 0x57, 0x62, 0x79, 0x11, 0xab, 0xce, 0x3a, 0x59, 0x03, 0xa8, 0xaf, 0x5c, 0xb9,
0xae, 0xb6, 0x55, 0xb9, 0xaa, 0xcb, 0xf0, 0x43, 0x32, 0x16, 0xfe, 0x38, 0x27, 0xcb, 0xf0, 0x0f, 0xda, 0x56, 0xe5, 0xaa, 0x2e, 0xc3, 0xf7, 0xc9, 0x48, 0xf8, 0xe3, 0x8c, 0x2c, 0xc3, 0x3f, 0x24,
0xc9, 0xd8, 0xdc, 0x2d, 0x44, 0x93, 0x5c, 0x9a, 0x8a, 0x4b, 0x04, 0x73, 0xdc, 0x91, 0x55, 0x3a, 0x23, 0x73, 0xab, 0x10, 0x4d, 0x72, 0x69, 0x2a, 0x2e, 0x11, 0xcc, 0x70, 0x47, 0x56, 0xe9, 0x5c,
0x17, 0x63, 0x74, 0x01, 0xc0, 0x4b, 0x6c, 0x57, 0xec, 0xb9, 0x5c, 0x54, 0xc7, 0xea, 0x7a, 0xca, 0x8c, 0xd1, 0x59, 0x00, 0x2f, 0xb1, 0x5d, 0xb1, 0xe7, 0x72, 0x51, 0x1d, 0xab, 0xeb, 0x29, 0x27,
0x09, 0x5c, 0xf3, 0x37, 0x99, 0xf0, 0xbc, 0xe5, 0xd3, 0xfd, 0xe7, 0xe8, 0x95, 0x59, 0x2d, 0xda, 0x70, 0xcd, 0x5f, 0x65, 0xc2, 0xf3, 0x86, 0x4f, 0x77, 0x8e, 0xd1, 0x2b, 0xb3, 0x5a, 0xb4, 0x73,
0x39, 0x2d, 0xb2, 0xf5, 0xf8, 0x5c, 0xbe, 0x1e, 0xcf, 0x04, 0x51, 0x76, 0x39, 0x75, 0x69, 0xf7, 0x5a, 0x64, 0xeb, 0xf1, 0x99, 0x7c, 0x3d, 0x9e, 0x09, 0xa2, 0xec, 0x72, 0xea, 0xd2, 0xee, 0x7d,
0x01, 0x7d, 0x7e, 0xb5, 0x5a, 0x39, 0xed, 0x4e, 0xb8, 0x2b, 0xf9, 0xef, 0xc2, 0x39, 0x6e, 0x70, 0x7a, 0x7c, 0xb5, 0x5a, 0x39, 0xed, 0x8e, 0xb9, 0x2b, 0xf9, 0xef, 0xc2, 0x69, 0x6e, 0x70, 0x09,
0x09, 0x15, 0x95, 0x40, 0xf3, 0x6a, 0xe9, 0x1f, 0xb3, 0x70, 0xbe, 0x9a, 0xb8, 0x49, 0xc5, 0xf4, 0x15, 0x95, 0x40, 0xf3, 0x6a, 0xe9, 0x1f, 0xd3, 0x70, 0xa6, 0x9a, 0xb8, 0x49, 0xc5, 0xf4, 0x1e,
0x1e, 0x18, 0x69, 0x45, 0xc2, 0x8f, 0xbd, 0x84, 0xe1, 0x20, 0x4a, 0x0f, 0x3e, 0x79, 0x3e, 0x9e, 0x18, 0x69, 0x45, 0xc2, 0x8f, 0xbd, 0x84, 0xe1, 0x20, 0x4a, 0x0f, 0x3e, 0x79, 0x3e, 0x9e, 0x52,
0x51, 0xe5, 0xc9, 0x03, 0x3d, 0xaf, 0x4f, 0xbf, 0x52, 0x39, 0xd3, 0x2e, 0x95, 0x33, 0x5c, 0x80, 0xe5, 0xc9, 0x7d, 0x3d, 0xaf, 0x4f, 0xbf, 0x52, 0x39, 0xd3, 0x2e, 0x95, 0x33, 0x5c, 0x80, 0x8b,
0x8b, 0x59, 0x9d, 0x00, 0x79, 0x3f, 0x3b, 0xe3, 0x62, 0x56, 0x27, 0x20, 0x25, 0x16, 0x02, 0xa4, 0x59, 0x9d, 0x00, 0x79, 0x3f, 0x3b, 0xe5, 0x62, 0x56, 0x27, 0x20, 0x25, 0x16, 0x02, 0xa4, 0xd7,
0xd7, 0xf6, 0x14, 0xbe, 0x10, 0x70, 0x01, 0x40, 0x5d, 0x9d, 0x46, 0xa1, 0x2e, 0xcf, 0xba, 0xf2, 0xf6, 0x14, 0xbe, 0x10, 0x70, 0x16, 0x40, 0x5d, 0x9d, 0x86, 0xa1, 0x2e, 0xcf, 0xba, 0xf2, 0xe2,
0xe2, 0x34, 0x0a, 0x6b, 0x6f, 0x90, 0x8b, 0xb5, 0x37, 0xc8, 0xfc, 0x6e, 0x76, 0x4a, 0xbb, 0xf9, 0x34, 0x0c, 0x6b, 0x6f, 0x90, 0xf3, 0xb5, 0x37, 0xc8, 0xfc, 0x6e, 0x76, 0x4a, 0xbb, 0xf9, 0x19,
0x19, 0xc0, 0x8e, 0x97, 0x1c, 0x4a, 0x23, 0xf3, 0x2b, 0xab, 0xeb, 0xc5, 0xea, 0x4d, 0x80, 0x0f, 0xc0, 0x4d, 0x2f, 0xd9, 0x97, 0x46, 0xe6, 0x57, 0x56, 0xd7, 0x8b, 0xd5, 0x9b, 0x00, 0x1f, 0x72,
0x39, 0x04, 0xfb, 0xbe, 0x32, 0x1d, 0x1f, 0xf2, 0xf0, 0x19, 0x25, 0xc4, 0x55, 0xd6, 0x11, 0x63, 0x08, 0xf6, 0x7d, 0x65, 0x3a, 0x3e, 0xe4, 0xe1, 0x33, 0x4c, 0x88, 0xab, 0xac, 0x23, 0xc6, 0x1c,
0x0e, 0x1b, 0xc6, 0x84, 0x28, 0x03, 0x88, 0xb1, 0xf9, 0xfb, 0x16, 0x74, 0xef, 0x91, 0x40, 0x71, 0xb6, 0x1b, 0x13, 0xa2, 0x0c, 0x20, 0xc6, 0xe6, 0xef, 0x5b, 0xd0, 0xbd, 0x4b, 0x02, 0xc5, 0xf9,
0xbe, 0x08, 0xf0, 0x88, 0xc6, 0x74, 0xc4, 0xbc, 0x90, 0xc8, 0x1b, 0xf6, 0xbc, 0x95, 0x81, 0x7c, 0x1c, 0xc0, 0x43, 0x1a, 0xd3, 0x21, 0xf3, 0x42, 0x22, 0x6f, 0xd8, 0xb3, 0x56, 0x06, 0xf2, 0xcd,
0x7b, 0x39, 0x22, 0x35, 0x10, 0x7f, 0xa8, 0x8c, 0x29, 0xc6, 0x1c, 0x76, 0x40, 0x70, 0xa4, 0xec, 0xe5, 0x88, 0xd4, 0x40, 0xfc, 0x5d, 0x65, 0x4c, 0x31, 0xe6, 0xb0, 0x3d, 0x82, 0x23, 0x65, 0x3f,
0x27, 0xc6, 0x68, 0x0d, 0xe6, 0x13, 0x86, 0x9d, 0x43, 0x61, 0xac, 0x39, 0x4b, 0x7e, 0x98, 0x7f, 0x31, 0x46, 0x2b, 0x30, 0x9b, 0x30, 0xec, 0xec, 0x0b, 0x63, 0xcd, 0x58, 0xf2, 0xc3, 0xfc, 0x53,
0x6e, 0x01, 0x58, 0x24, 0xa0, 0x4c, 0xf8, 0x1a, 0xbf, 0xb9, 0xee, 0x63, 0xe7, 0x90, 0xd7, 0x02, 0x0b, 0xc0, 0x22, 0x01, 0x65, 0xc2, 0xd7, 0xf8, 0xcd, 0x75, 0x07, 0x3b, 0xfb, 0xbc, 0x16, 0x60,
0x6c, 0x1c, 0x11, 0x65, 0x89, 0x9e, 0x82, 0x3d, 0x18, 0x47, 0x62, 0x87, 0x34, 0x8a, 0xca, 0x5f, 0xa3, 0x88, 0x28, 0x4b, 0xf4, 0x14, 0xec, 0xfe, 0x28, 0x12, 0x3b, 0xa4, 0x51, 0x54, 0xfe, 0xea,
0x5d, 0xab, 0xab, 0x20, 0xf2, 0xd6, 0xaf, 0x43, 0xb9, 0x6b, 0xf1, 0x61, 0x26, 0xa7, 0xc9, 0x65, 0x5a, 0x5d, 0x05, 0x91, 0xb7, 0x7e, 0x1d, 0xca, 0x5d, 0x8b, 0x0f, 0x33, 0x39, 0x4d, 0x2e, 0x5b,
0xeb, 0x9c, 0x76, 0x0e, 0xba, 0x45, 0x57, 0x10, 0xa9, 0x40, 0xf8, 0xc1, 0x4b, 0xb0, 0x14, 0x50, 0xe7, 0xb4, 0xd3, 0xd0, 0x2d, 0xba, 0x82, 0x48, 0x05, 0xc2, 0x0f, 0x2e, 0xc0, 0x42, 0x40, 0x5d,
0xd7, 0x1b, 0x7a, 0xc4, 0x15, 0x8e, 0xa6, 0x54, 0xe9, 0x6b, 0x20, 0x77, 0x2e, 0x73, 0x07, 0x4e, 0x6f, 0xd7, 0x23, 0xae, 0x70, 0x34, 0xa5, 0x4a, 0x5f, 0x03, 0xb9, 0x73, 0x99, 0x37, 0xe1, 0x84,
0xa9, 0xdb, 0x97, 0x47, 0xe2, 0xbb, 0xe1, 0x90, 0xa2, 0x2d, 0x98, 0xe7, 0x2c, 0xf4, 0x33, 0xe3, 0xba, 0x7d, 0x79, 0x24, 0xbe, 0x13, 0xee, 0x52, 0xb4, 0x01, 0xb3, 0x9c, 0x85, 0x7e, 0x66, 0x3c,
0xf9, 0xf2, 0x33, 0xe3, 0x44, 0x59, 0x4b, 0xa2, 0x9a, 0xdf, 0xb4, 0x60, 0x63, 0xc2, 0x86, 0x1f, 0x53, 0x7e, 0x66, 0x1c, 0x2b, 0x6b, 0x49, 0x54, 0xf3, 0xeb, 0x16, 0xac, 0x8d, 0xd9, 0xdc, 0xa5,
0xc7, 0x3b, 0x98, 0x3d, 0xa0, 0x12, 0xf1, 0xb9, 0xe4, 0xb8, 0x77, 0x60, 0xe0, 0x92, 0x84, 0x79, 0x07, 0xfc, 0x40, 0xbf, 0x4f, 0x25, 0xe2, 0xb1, 0xe4, 0xb8, 0x77, 0x60, 0xe0, 0x92, 0x84, 0x79,
0xa1, 0x28, 0xe3, 0x6c, 0x6d, 0xbe, 0x10, 0x07, 0x44, 0x19, 0x6a, 0x3d, 0x33, 0x7f, 0x4b, 0x4e, 0xa1, 0x28, 0xe3, 0x6c, 0x6d, 0xbe, 0x10, 0x07, 0x44, 0x19, 0x6a, 0x35, 0x33, 0x7f, 0x43, 0x4e,
0xef, 0xe2, 0x80, 0xa0, 0x6b, 0xb0, 0x7a, 0x48, 0x48, 0x64, 0xfb, 0xd4, 0xc1, 0xbe, 0xad, 0xa3, 0x6f, 0xe1, 0x80, 0xa0, 0x2b, 0xb0, 0xbc, 0x4f, 0x48, 0x64, 0xfb, 0xd4, 0xc1, 0xbe, 0xad, 0xa3,
0x47, 0xdd, 0x52, 0x56, 0xf8, 0xd4, 0x47, 0x7c, 0x66, 0x47, 0x46, 0x90, 0x99, 0xc0, 0x8b, 0xc7, 0x47, 0xdd, 0x52, 0x96, 0xf8, 0xd4, 0x47, 0x7c, 0xe6, 0xa6, 0x8c, 0x20, 0x33, 0x81, 0x17, 0x0e,
0x68, 0xa2, 0x32, 0xc8, 0x79, 0xe8, 0x46, 0x31, 0x75, 0x48, 0xc2, 0xbd, 0xab, 0x25, 0x0e, 0x94, 0xd1, 0x44, 0x65, 0x90, 0x33, 0xd0, 0x8d, 0x62, 0xea, 0x90, 0x84, 0x7b, 0x57, 0x4b, 0x1c, 0x28,
0x09, 0x00, 0xdd, 0x80, 0xd5, 0xf4, 0xe3, 0x63, 0x12, 0x3b, 0x24, 0x64, 0xf8, 0x91, 0x7c, 0x33, 0x63, 0x00, 0xba, 0x06, 0xcb, 0xe9, 0xc7, 0xc7, 0x24, 0x76, 0x48, 0xc8, 0xf0, 0x43, 0xf9, 0x66,
0x9c, 0xb5, 0xaa, 0xa6, 0xcc, 0x7f, 0xf5, 0xa1, 0xff, 0xc9, 0x88, 0xc4, 0xe3, 0xcc, 0x03, 0x5b, 0x38, 0x6d, 0x55, 0x4d, 0x99, 0xbf, 0x69, 0x81, 0x59, 0x92, 0x7a, 0x3b, 0xa6, 0xc1, 0x31, 0x5a,
0x42, 0x94, 0xee, 0xfa, 0x85, 0x38, 0x03, 0xe1, 0x79, 0x60, 0x18, 0xd3, 0xc0, 0x4e, 0x1f, 0x91, 0xf0, 0x2a, 0xac, 0x08, 0x3b, 0xc4, 0x82, 0xe5, 0xd8, 0x10, 0xb2, 0x98, 0x38, 0xc9, 0xe7, 0xa4,
0x67, 0x05, 0x4a, 0x8f, 0x03, 0xef, 0xc8, 0x87, 0x64, 0xf4, 0x3e, 0x2c, 0x0c, 0x3d, 0x9f, 0x11, 0x34, 0x6d, 0x89, 0x21, 0x5c, 0x38, 0x74, 0x4d, 0xff, 0x25, 0x5b, 0xfc, 0xab, 0x0f, 0xfd, 0x4f,
0xf9, 0x6c, 0xdb, 0xdb, 0x7a, 0xa5, 0xbc, 0x93, 0x59, 0x99, 0x9b, 0x77, 0x04, 0xb2, 0xa5, 0x88, 0x86, 0x24, 0x1e, 0x65, 0x1e, 0x1b, 0x13, 0xa2, 0xb4, 0xd0, 0xaf, 0xe5, 0x19, 0x08, 0xcf, 0x89,
0xd0, 0x3e, 0xac, 0x7a, 0x61, 0x24, 0x2e, 0xfd, 0xb1, 0x87, 0x7d, 0xef, 0xe9, 0xe4, 0x89, 0xa8, 0xbb, 0x31, 0x0d, 0xec, 0xf4, 0x41, 0x7d, 0x5a, 0xa0, 0xf4, 0x38, 0xf0, 0xb6, 0x7c, 0x54, 0x47,
0xb7, 0xf5, 0xe6, 0x14, 0x5e, 0x77, 0x39, 0xe5, 0x5e, 0x96, 0xd0, 0x42, 0x5e, 0x09, 0x86, 0x08, 0xef, 0xc3, 0xdc, 0xae, 0xe7, 0x33, 0x22, 0x9f, 0xb0, 0x7b, 0x1b, 0x2f, 0x95, 0xbd, 0x3a, 0x2b,
0xac, 0xd1, 0x11, 0x2b, 0x0b, 0x99, 0x17, 0x42, 0xb6, 0xa6, 0x08, 0xb9, 0x2f, 0x48, 0xf3, 0x52, 0x73, 0xfd, 0xb6, 0x40, 0xb6, 0x14, 0x11, 0xda, 0x81, 0x65, 0x2f, 0x8c, 0x44, 0x01, 0x14, 0x7b,
0x56, 0x69, 0x19, 0x68, 0xec, 0xc2, 0x82, 0x54, 0x8e, 0x47, 0xf0, 0xd0, 0x23, 0xbe, 0x7e, 0xf8, 0xd8, 0xf7, 0x9e, 0x8e, 0x9f, 0xcb, 0x7a, 0x1b, 0xaf, 0x4f, 0xe0, 0x75, 0x87, 0x53, 0x6e, 0x67,
0x96, 0x1f, 0xfc, 0x94, 0xa4, 0x11, 0x89, 0x71, 0xa8, 0x83, 0x51, 0x7f, 0x72, 0xfc, 0x23, 0xec, 0x09, 0x2d, 0xe4, 0x95, 0x60, 0x88, 0xc0, 0x0a, 0x1d, 0xb2, 0xb2, 0x90, 0x59, 0x21, 0x64, 0x63,
0x8f, 0xb4, 0x8f, 0xc9, 0x0f, 0xe3, 0x2f, 0xf3, 0x80, 0xca, 0x1a, 0xea, 0x77, 0xaf, 0x98, 0x24, 0x82, 0x90, 0x7b, 0x82, 0x34, 0x2f, 0x65, 0x99, 0x96, 0x81, 0xc6, 0x16, 0xcc, 0x49, 0xe5, 0x78,
0x3c, 0x6f, 0x66, 0xa3, 0x7f, 0x39, 0x03, 0x17, 0x19, 0xe0, 0x27, 0xd0, 0x75, 0x92, 0x23, 0x5b, 0x36, 0xdb, 0xf5, 0x88, 0xaf, 0x9b, 0x00, 0xf2, 0x83, 0xdf, 0x18, 0x68, 0x44, 0x62, 0x1c, 0xea,
0x98, 0x44, 0xc8, 0xec, 0x6d, 0xbd, 0x7b, 0x62, 0x93, 0x6e, 0x6e, 0xef, 0x3d, 0x14, 0x50, 0xab, 0xc4, 0xa4, 0x3f, 0x39, 0xfe, 0x01, 0xf6, 0x87, 0x3a, 0xde, 0xe4, 0x87, 0xf1, 0x97, 0x59, 0x40,
0xe3, 0x24, 0x47, 0x62, 0x84, 0x7e, 0x06, 0xf0, 0x65, 0x42, 0x43, 0xc5, 0x59, 0x6e, 0xfc, 0x7b, 0x65, 0x0d, 0xf5, 0x1b, 0x60, 0x4c, 0x12, 0x7e, 0x86, 0x64, 0x33, 0xe1, 0x62, 0x06, 0x2e, 0xb2,
0x27, 0xe7, 0xfc, 0xe3, 0xbd, 0xfb, 0xbb, 0x92, 0x75, 0x97, 0xb3, 0x93, 0xbc, 0x1d, 0x58, 0x8a, 0xe1, 0x8f, 0xa0, 0xeb, 0x24, 0x07, 0xb6, 0x30, 0x89, 0x90, 0xd9, 0xdb, 0x78, 0xf7, 0xc8, 0x26,
0x70, 0xfc, 0x78, 0x44, 0x98, 0x62, 0x2f, 0x7d, 0xe1, 0x83, 0x93, 0xb3, 0xff, 0x58, 0xb2, 0x91, 0x5d, 0xdf, 0xdc, 0x7e, 0x20, 0xa0, 0x56, 0xc7, 0x49, 0x0e, 0xc4, 0x08, 0xfd, 0x04, 0xe0, 0xcb,
0x12, 0xfa, 0x51, 0xe6, 0xcb, 0xf8, 0x66, 0x16, 0x3a, 0x5a, 0x2f, 0x5e, 0x37, 0x08, 0x0f, 0x97, 0x84, 0x86, 0x8a, 0xb3, 0xdc, 0xf8, 0xf7, 0x8e, 0xce, 0xf9, 0x87, 0xdb, 0xf7, 0xb6, 0x24, 0xeb,
0xd5, 0xb3, 0xed, 0x85, 0x43, 0xaa, 0x2c, 0x7a, 0x8a, 0xc3, 0x65, 0x01, 0x2d, 0xb2, 0xd6, 0x15, 0x2e, 0x67, 0x27, 0x79, 0x3b, 0xb0, 0x10, 0xe1, 0xf8, 0xd1, 0x90, 0x30, 0xc5, 0x5e, 0xfa, 0xc2,
0x58, 0x89, 0x89, 0x43, 0x63, 0x97, 0xdf, 0xc0, 0xbc, 0xc0, 0xe3, 0x6e, 0x2f, 0xf7, 0x72, 0x59, 0x07, 0x47, 0x67, 0xff, 0xb1, 0x64, 0x23, 0x25, 0xf4, 0xa3, 0xcc, 0x97, 0xf1, 0xf5, 0x34, 0x74,
0xc2, 0x77, 0x34, 0x18, 0xbd, 0x06, 0xcb, 0x62, 0xdb, 0x33, 0x98, 0x6d, 0xcd, 0x93, 0xf8, 0x19, 0xb4, 0x5e, 0xbc, 0x86, 0x12, 0x1e, 0x2e, 0x5f, 0x12, 0x6c, 0x2f, 0xdc, 0xa5, 0xca, 0xa2, 0x27,
0xc4, 0x2b, 0xb0, 0xf2, 0x78, 0x44, 0x19, 0xb1, 0x9d, 0x03, 0x1c, 0x63, 0x87, 0xd1, 0xb4, 0x8e, 0x38, 0x5c, 0x3e, 0x26, 0x88, 0x0c, 0x7e, 0x09, 0x96, 0x62, 0xe2, 0xd0, 0xd8, 0xe5, 0xb7, 0x51,
0x5d, 0x16, 0xf0, 0xed, 0x14, 0x8c, 0xfe, 0x0f, 0xd6, 0x25, 0x2a, 0x49, 0x1c, 0x1c, 0xa5, 0x14, 0x2f, 0xf0, 0xb8, 0xdb, 0xcb, 0xbd, 0x5c, 0x94, 0xf0, 0x9b, 0x1a, 0x8c, 0x5e, 0x81, 0x45, 0xb1,
0x24, 0x56, 0x65, 0xce, 0x9a, 0x98, 0xbd, 0x2d, 0x26, 0xb7, 0xf5, 0x1c, 0x32, 0xa0, 0xe3, 0xd0, 0xed, 0x19, 0xcc, 0xb6, 0xe6, 0x49, 0xfc, 0x0c, 0xe2, 0x25, 0x58, 0x7a, 0x34, 0xe4, 0x79, 0xc3,
0x20, 0x20, 0x21, 0x4b, 0x44, 0x72, 0xee, 0x5a, 0xe9, 0x37, 0xba, 0x09, 0x17, 0xb0, 0xef, 0xd3, 0xd9, 0xc3, 0x31, 0x76, 0x18, 0x4d, 0x6b, 0xfa, 0x45, 0x01, 0xdf, 0x4c, 0xc1, 0xe8, 0x4d, 0x58,
0xaf, 0x6c, 0x41, 0xe9, 0xda, 0x25, 0xed, 0xe4, 0xab, 0x8a, 0x21, 0x90, 0x3e, 0x11, 0x38, 0x56, 0x95, 0xa8, 0x24, 0x71, 0x70, 0x94, 0x52, 0x90, 0x58, 0x95, 0x7c, 0x2b, 0x62, 0xf6, 0x96, 0x98,
0x5e, 0x51, 0xe3, 0x12, 0x74, 0xd3, 0x7d, 0xe4, 0xe7, 0x59, 0xc6, 0x21, 0xc5, 0xd8, 0x38, 0x05, 0xdc, 0xd4, 0x73, 0xc8, 0x80, 0x8e, 0x43, 0x83, 0x80, 0x84, 0x2c, 0x11, 0x07, 0x55, 0xd7, 0x4a,
0xfd, 0xec, 0x4e, 0x18, 0xff, 0x6c, 0xc3, 0x6a, 0x45, 0x50, 0xa1, 0xcf, 0x01, 0xb8, 0xb7, 0xca, 0xbf, 0xd1, 0x75, 0x38, 0x8b, 0x7d, 0x9f, 0x3e, 0xb6, 0x05, 0xa5, 0x6b, 0x97, 0xb4, 0x93, 0x2f,
0xd0, 0x52, 0xee, 0xfa, 0xbd, 0x93, 0x07, 0x27, 0xf7, 0x57, 0x09, 0xb6, 0xb8, 0xf7, 0xcb, 0x21, 0x4c, 0x86, 0x40, 0xfa, 0x44, 0xe0, 0x58, 0x79, 0x45, 0x8d, 0xf3, 0xd0, 0x4d, 0xf7, 0x91, 0x9f,
0xfa, 0x39, 0xf4, 0x84, 0xc7, 0x2a, 0xee, 0xd2, 0x65, 0xdf, 0xff, 0x16, 0xdc, 0xb9, 0xae, 0x8a, 0xed, 0x19, 0x87, 0x14, 0x63, 0xe3, 0x04, 0xf4, 0xb3, 0x3b, 0x61, 0xfc, 0xb3, 0x0d, 0xcb, 0x15,
0xbd, 0x88, 0x01, 0x39, 0x36, 0xfe, 0xd6, 0x82, 0x6e, 0x2a, 0x98, 0x9f, 0xce, 0x72, 0xa3, 0xc4, 0x41, 0x85, 0x3e, 0x07, 0xe0, 0xde, 0x2a, 0x43, 0x4b, 0xb9, 0xeb, 0x77, 0x8e, 0x1e, 0x9c, 0xdc,
0x5e, 0x27, 0xfa, 0x74, 0x16, 0xb0, 0x3b, 0x02, 0xf4, 0x3f, 0xe9, 0x4a, 0xc6, 0xdb, 0x00, 0x13, 0x5f, 0x25, 0xd8, 0xe2, 0xde, 0x2f, 0x87, 0xe8, 0xa7, 0xd0, 0x13, 0x1e, 0xab, 0xb8, 0x4b, 0x97,
0xfd, 0x2b, 0x55, 0x68, 0x55, 0xaa, 0x60, 0x5e, 0x81, 0x25, 0x6e, 0x59, 0x8f, 0xb8, 0x7b, 0x2c, 0x7d, 0xff, 0x1b, 0x70, 0xe7, 0xba, 0x2a, 0xf6, 0x22, 0x06, 0xe4, 0xd8, 0xf8, 0x5b, 0x0b, 0xba,
0xf6, 0x22, 0xd1, 0xc2, 0x93, 0x38, 0x89, 0x2a, 0x6f, 0xf4, 0xe7, 0xd6, 0x1f, 0xcf, 0x42, 0x3f, 0xa9, 0x60, 0x7e, 0x53, 0x91, 0x1b, 0x25, 0xf6, 0x3a, 0xd1, 0x37, 0x15, 0x01, 0xbb, 0x2d, 0x40,
0xfb, 0x74, 0x83, 0xbe, 0x80, 0x5e, 0xa6, 0x55, 0x89, 0x5e, 0x2e, 0x6f, 0x5a, 0xb9, 0xf5, 0x69, 0xff, 0x97, 0xae, 0x64, 0xbc, 0x0d, 0x30, 0xd6, 0xbf, 0x52, 0x85, 0x56, 0xa5, 0x0a, 0xe6, 0x25,
0xbc, 0x32, 0x05, 0x4b, 0x55, 0x00, 0x33, 0x28, 0x84, 0xd3, 0xa5, 0x7e, 0x1f, 0xba, 0x5a, 0xa6, 0x58, 0xe0, 0x96, 0xf5, 0x88, 0xbb, 0xcd, 0x62, 0x2f, 0x12, 0xed, 0x4c, 0x89, 0x93, 0xa8, 0x52,
0xae, 0xeb, 0x26, 0x1a, 0xaf, 0x37, 0xc2, 0x4d, 0xe5, 0x31, 0x58, 0xad, 0x68, 0xe0, 0xa1, 0x37, 0x4f, 0x7f, 0x6e, 0xfc, 0xd9, 0x80, 0x7e, 0xf6, 0x19, 0x0b, 0x7d, 0x01, 0xbd, 0x4c, 0xdb, 0x16,
0xa6, 0x70, 0xc9, 0x35, 0x11, 0x8d, 0x6b, 0x0d, 0xb1, 0x53, 0xa9, 0x8f, 0x01, 0x95, 0xbb, 0x7b, 0xbd, 0x58, 0xde, 0xb4, 0x72, 0x1b, 0xd8, 0x78, 0x69, 0x02, 0x96, 0xaa, 0x86, 0xa6, 0x50, 0x08,
0xe8, 0xf5, 0xa9, 0x6c, 0x26, 0xdd, 0x43, 0xe3, 0x8d, 0x66, 0xc8, 0xb5, 0x8a, 0xca, 0xbe, 0xdf, 0x27, 0x4b, 0xbd, 0x4f, 0x74, 0xb9, 0x4c, 0x5d, 0xd7, 0x59, 0x35, 0x5e, 0x6d, 0x84, 0x9b, 0xca,
0x54, 0x45, 0x73, 0x9d, 0xc5, 0xa9, 0x8a, 0x16, 0x9a, 0x89, 0x33, 0xe8, 0x10, 0x56, 0x8a, 0x3d, 0x63, 0xb0, 0x5c, 0xd1, 0xcc, 0x44, 0xaf, 0x4d, 0xe0, 0x92, 0x6b, 0xa8, 0x1a, 0x57, 0x1a, 0x62,
0x41, 0x74, 0xa5, 0xae, 0x87, 0x5d, 0x6a, 0x39, 0x1a, 0x57, 0x9b, 0xa0, 0xa6, 0xc2, 0x08, 0x9c, 0xa7, 0x52, 0x1f, 0x01, 0x2a, 0x77, 0x3a, 0xd1, 0xab, 0x13, 0xd9, 0x8c, 0x3b, 0xa9, 0xc6, 0x6b,
0xca, 0xf7, 0xe0, 0xd0, 0x6b, 0x65, 0xfa, 0xca, 0x2e, 0xa4, 0x71, 0x79, 0x3a, 0x62, 0x56, 0xa7, 0xcd, 0x90, 0x6b, 0x15, 0x95, 0x3d, 0xd0, 0x89, 0x8a, 0xe6, 0xba, 0xac, 0x13, 0x15, 0x2d, 0x34,
0x62, 0x5f, 0xae, 0x4a, 0xa7, 0x9a, 0xa6, 0x5f, 0x95, 0x4e, 0x75, 0x6d, 0x3e, 0x73, 0x06, 0xfd, 0x56, 0xa7, 0xd0, 0x3e, 0x2c, 0x15, 0xfb, 0xa3, 0xe8, 0x52, 0x5d, 0x3f, 0xbf, 0xd4, 0x7e, 0x35,
0x42, 0x37, 0x7b, 0x0a, 0xfd, 0x2a, 0xb4, 0x59, 0xc7, 0xa6, 0xba, 0x61, 0x66, 0x5c, 0x6f, 0x8c, 0x2e, 0x37, 0x41, 0x4d, 0x85, 0x11, 0x38, 0x91, 0xef, 0x47, 0xa2, 0x57, 0xca, 0xf4, 0x95, 0x1d,
0xaf, 0x65, 0xdf, 0x68, 0xf1, 0x58, 0xcf, 0xb4, 0xad, 0xaa, 0x62, 0xbd, 0xdc, 0x08, 0xab, 0x8a, 0x59, 0xe3, 0xe2, 0x64, 0xc4, 0xac, 0x4e, 0xc5, 0x1e, 0x65, 0x95, 0x4e, 0x35, 0x0d, 0xd0, 0x2a,
0xf5, 0xaa, 0xde, 0xd7, 0x0c, 0xda, 0x87, 0xa5, 0x5c, 0x23, 0x0b, 0xbd, 0x5a, 0x47, 0x99, 0x7f, 0x9d, 0xea, 0x5a, 0x9e, 0xe6, 0x14, 0xfa, 0x99, 0x6e, 0x7c, 0x15, 0x7a, 0x77, 0x68, 0xbd, 0x8e,
0x9d, 0x32, 0x5e, 0x9b, 0x8a, 0x97, 0xca, 0xb0, 0x75, 0xf6, 0x52, 0xe9, 0xaa, 0x76, 0x71, 0xf9, 0x4d, 0x75, 0xf3, 0xd0, 0xb8, 0xda, 0x18, 0x5f, 0xcb, 0xbe, 0xd6, 0xe2, 0xb1, 0x9e, 0x69, 0xe1,
0x7c, 0xf5, 0xea, 0x34, 0xb4, 0x5c, 0x28, 0x97, 0xda, 0x5d, 0x95, 0xa1, 0x5c, 0xd7, 0x4e, 0xab, 0x55, 0xc5, 0x7a, 0xb9, 0x29, 0x58, 0x15, 0xeb, 0x55, 0x7d, 0xc0, 0x29, 0xb4, 0x03, 0x0b, 0xb9,
0x0c, 0xe5, 0xfa, 0x0e, 0xda, 0x0c, 0xfa, 0x29, 0xc0, 0xa4, 0x25, 0x85, 0x5e, 0xaa, 0xa3, 0xce, 0xa6, 0x1e, 0x7a, 0xb9, 0x8e, 0x32, 0xff, 0x52, 0x67, 0xbc, 0x32, 0x11, 0x2f, 0x95, 0x61, 0xeb,
0xee, 0xfe, 0xcb, 0xc7, 0x23, 0xa5, 0xac, 0xbf, 0x82, 0xb5, 0xaa, 0x57, 0x14, 0x74, 0xad, 0xaa, 0xec, 0xa5, 0xd2, 0x55, 0xed, 0xe2, 0xf2, 0xf9, 0xea, 0xe5, 0x49, 0x68, 0xb9, 0x50, 0x2e, 0xb5,
0x20, 0xac, 0x7d, 0xaa, 0x31, 0x36, 0x9b, 0xa2, 0xa7, 0x82, 0x3f, 0x85, 0x8e, 0x6e, 0x07, 0xa1, 0xfe, 0x2a, 0x43, 0xb9, 0xae, 0xb5, 0x58, 0x19, 0xca, 0xf5, 0xdd, 0xc4, 0x29, 0xf4, 0x63, 0x80,
0x17, 0xcb, 0xd4, 0x85, 0x06, 0x9a, 0x61, 0x1e, 0x87, 0x92, 0x71, 0xe0, 0x40, 0xc7, 0xea, 0xa4, 0x71, 0x7b, 0x0e, 0x5d, 0xa8, 0xa3, 0xce, 0xee, 0xfe, 0x8b, 0x87, 0x23, 0xa5, 0xac, 0x1f, 0xc3,
0x4f, 0x53, 0x1f, 0xab, 0xa5, 0x8e, 0x52, 0x7d, 0xac, 0x96, 0xdb, 0x3e, 0x42, 0x5c, 0xea, 0x0c, 0x4a, 0xd5, 0x8b, 0x12, 0xba, 0x52, 0x55, 0x1c, 0xd7, 0x3e, 0x5b, 0x19, 0xeb, 0x4d, 0xd1, 0x53,
0xd9, 0xb6, 0x46, 0xbd, 0x33, 0x54, 0x74, 0x6d, 0xea, 0x9d, 0xa1, 0xb2, 0x53, 0x32, 0x83, 0x7e, 0xc1, 0x9f, 0x42, 0x47, 0xb7, 0xc6, 0xd0, 0x0b, 0x65, 0xea, 0x42, 0x33, 0xd1, 0x30, 0x0f, 0x43,
0x09, 0xeb, 0xd5, 0xdd, 0x0c, 0x54, 0x1b, 0xf1, 0x35, 0x5d, 0x15, 0xe3, 0x46, 0x73, 0x82, 0x54, 0xc9, 0x38, 0x70, 0xa0, 0x63, 0x75, 0xdc, 0xb3, 0xaa, 0x8f, 0xd5, 0x52, 0x77, 0xad, 0x3e, 0x56,
0xfc, 0x53, 0x9d, 0x9f, 0x0a, 0xdd, 0x8c, 0xfa, 0xfc, 0x54, 0xdd, 0x53, 0x31, 0xae, 0x37, 0xc6, 0xcb, 0x2d, 0x30, 0x21, 0x2e, 0x75, 0x86, 0x6c, 0x8b, 0xa7, 0xde, 0x19, 0x2a, 0x3a, 0x58, 0xf5,
0x2f, 0x87, 0x5e, 0xb6, 0x25, 0x50, 0x6f, 0xed, 0x8a, 0x0e, 0x49, 0xbd, 0xb5, 0x2b, 0xbb, 0x0c, 0xce, 0x50, 0xd9, 0x35, 0x9a, 0x42, 0x3f, 0x87, 0xd5, 0xea, 0xce, 0x0e, 0xaa, 0x8d, 0xf8, 0x9a,
0x22, 0x3e, 0xaa, 0x9e, 0xfb, 0xab, 0xe2, 0xe3, 0x98, 0x7e, 0x84, 0xb1, 0xd9, 0x14, 0x3d, 0x77, 0x0e, 0x93, 0x71, 0xad, 0x39, 0x41, 0x2a, 0xfe, 0xa9, 0xce, 0x4f, 0x85, 0xce, 0x4e, 0x7d, 0x7e,
0x7c, 0x97, 0xdf, 0xf3, 0xd1, 0xd4, 0xf5, 0xe7, 0x32, 0xf3, 0xb5, 0x86, 0xd8, 0xf5, 0xbb, 0xab, 0xaa, 0xee, 0x2f, 0x19, 0x57, 0x1b, 0xe3, 0x97, 0x43, 0x2f, 0xdb, 0x1e, 0xa9, 0xb7, 0x76, 0x45,
0x33, 0xf5, 0x54, 0x05, 0x0a, 0x19, 0xfb, 0x7a, 0x63, 0xfc, 0x54, 0x76, 0xa4, 0x7f, 0x14, 0xc8, 0xb7, 0xa8, 0xde, 0xda, 0x95, 0x1d, 0x17, 0x11, 0x1f, 0x55, 0xad, 0x8f, 0xaa, 0xf8, 0x38, 0xa4,
0xbc, 0xc5, 0xa3, 0xab, 0x53, 0xf8, 0x64, 0x7a, 0x09, 0xc6, 0xeb, 0x8d, 0x70, 0xab, 0xa2, 0x37, 0x37, 0x63, 0xac, 0x37, 0x45, 0xcf, 0x1d, 0xdf, 0xe5, 0xde, 0x06, 0x9a, 0xb8, 0xfe, 0x5c, 0x66,
0xfb, 0x3a, 0x7e, 0x9c, 0x3f, 0x95, 0x9e, 0xf4, 0x8f, 0xf3, 0xa7, 0x8a, 0x07, 0xf7, 0x8a, 0xe8, 0xbe, 0xd2, 0x10, 0xbb, 0x7e, 0x77, 0x75, 0xa6, 0x9e, 0xa8, 0x40, 0x21, 0x63, 0x5f, 0x6d, 0x8c,
0xd5, 0x8f, 0xe2, 0xd3, 0xa3, 0xb7, 0xf0, 0x38, 0x3f, 0x3d, 0x7a, 0x4b, 0xef, 0xed, 0x33, 0xe8, 0x9f, 0xca, 0x8e, 0xf4, 0x4f, 0x13, 0x99, 0xbe, 0x04, 0xba, 0x3c, 0x81, 0x4f, 0xa6, 0xaf, 0x62,
0xd7, 0x93, 0x06, 0x72, 0xf9, 0xe1, 0x0b, 0x6d, 0xd5, 0xa6, 0xa2, 0xda, 0xf7, 0x3e, 0xe3, 0xad, 0xbc, 0xda, 0x08, 0xb7, 0x2a, 0x7a, 0xb3, 0x9d, 0x82, 0xc3, 0xfc, 0xa9, 0xd4, 0xde, 0x38, 0xcc,
0x13, 0xd1, 0x64, 0x8c, 0xff, 0x11, 0xcc, 0x8b, 0x62, 0x0f, 0x5d, 0x3c, 0xbe, 0x0a, 0x34, 0x2e, 0x9f, 0x2a, 0x9a, 0x0f, 0x15, 0xd1, 0xab, 0x1b, 0x04, 0x93, 0xa3, 0xb7, 0xd0, 0xa8, 0x98, 0x1c,
0x55, 0xcf, 0xa7, 0xb5, 0x0c, 0xe7, 0xb6, 0xbf, 0x20, 0xfe, 0xcc, 0x7c, 0xeb, 0x3f, 0x01, 0x00, 0xbd, 0xa5, 0xde, 0xc3, 0x14, 0xfa, 0xe5, 0xb8, 0x99, 0x5e, 0x7e, 0x04, 0x44, 0x1b, 0xb5, 0xa9,
0x00, 0xff, 0xff, 0x59, 0x62, 0x68, 0x9d, 0xb0, 0x29, 0x00, 0x00, 0xa8, 0xf6, 0xed, 0xd3, 0x78, 0xe3, 0x48, 0x34, 0x19, 0xe3, 0xff, 0xba, 0xa5, 0xbb, 0x77, 0x95,
0xaf, 0x70, 0xe8, 0xcd, 0x06, 0x8c, 0x4b, 0x0f, 0x89, 0xc6, 0x5b, 0x47, 0xa4, 0xca, 0x2c, 0xe8,
0x23, 0x98, 0x15, 0xd5, 0x27, 0x3a, 0x77, 0x78, 0x59, 0x6a, 0x9c, 0xaf, 0x9e, 0x4f, 0x8b, 0x2b,
0xce, 0x6d, 0x67, 0x4e, 0xfc, 0x36, 0xfb, 0xc6, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xb3, 0xd7,
0xc4, 0x53, 0x4d, 0x2b, 0x00, 0x00,
} }

View file

@ -0,0 +1,85 @@
package weed_server
import (
"fmt"
"time"
"github.com/chrislusf/seaweedfs/weed/pb/volume_server_pb"
"github.com/chrislusf/seaweedfs/weed/storage/backend"
"github.com/chrislusf/seaweedfs/weed/storage/needle"
)
// VolumeTierMoveDatFromRemote copy dat file from a remote tier to local volume server
func (vs *VolumeServer) VolumeTierMoveDatFromRemote(req *volume_server_pb.VolumeTierMoveDatFromRemoteRequest, stream volume_server_pb.VolumeServer_VolumeTierMoveDatFromRemoteServer) error {
// find existing volume
v := vs.store.GetVolume(needle.VolumeId(req.VolumeId))
if v == nil {
return fmt.Errorf("volume %d not found", req.VolumeId)
}
// verify the collection
if v.Collection != req.Collection {
return fmt.Errorf("existing collection:%v unexpected input: %v", v.Collection, req.Collection)
}
// locate the disk file
storageName, storageKey := v.RemoteStorageNameKey()
if storageName == "" || storageKey == "" {
return fmt.Errorf("volume %d is already on local disk", req.VolumeId)
}
// check whether the local .dat already exists
_, ok := v.DataBackend.(*backend.DiskFile)
if ok {
return fmt.Errorf("volume %d is already on local disk", req.VolumeId)
}
// check valid storage backend type
backendStorage, found := backend.BackendStorages[storageName]
if !found {
var keys []string
for key := range backend.BackendStorages {
keys = append(keys, key)
}
return fmt.Errorf("remote storage %s not found from suppported: %v", storageName, keys)
}
startTime := time.Now()
fn := func(progressed int64, percentage float32) error {
now := time.Now()
if now.Sub(startTime) < time.Second {
return nil
}
startTime = now
return stream.Send(&volume_server_pb.VolumeTierMoveDatFromRemoteResponse{
Processed: progressed,
ProcessedPercentage: percentage,
})
}
// copy the data file
_, err := backendStorage.DownloadFile(v.FileName()+".dat", storageKey, fn)
if err != nil {
return fmt.Errorf("backend %s copy file %s: %v", storageName, v.FileName()+".dat", err)
}
if req.KeepRemoteDatFile {
return nil
}
// remove remote file
if err := backendStorage.DeleteFile(storageKey); err != nil {
return fmt.Errorf("volume %d fail to delete remote file %s: %v", v.Id, storageKey, err)
}
// forget remote file
v.GetVolumeTierInfo().Files = v.GetVolumeTierInfo().Files[1:]
if err := v.SaveVolumeTierInfo(); err != nil {
return fmt.Errorf("volume %d fail to save remote file info: %v", v.Id, err)
}
v.DataBackend.Close()
v.DataBackend = nil
return nil
}

View file

@ -10,8 +10,8 @@ import (
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
) )
// VolumeTierCopyDatToRemote copy dat file to a remote tier // VolumeTierMoveDatToRemote copy dat file to a remote tier
func (vs *VolumeServer) VolumeTierCopyDatToRemote(req *volume_server_pb.VolumeTierCopyDatToRemoteRequest, stream volume_server_pb.VolumeServer_VolumeTierCopyDatToRemoteServer) error { func (vs *VolumeServer) VolumeTierMoveDatToRemote(req *volume_server_pb.VolumeTierMoveDatToRemoteRequest, stream volume_server_pb.VolumeServer_VolumeTierMoveDatToRemoteServer) error {
// find existing volume // find existing volume
v := vs.store.GetVolume(needle.VolumeId(req.VolumeId)) v := vs.store.GetVolume(needle.VolumeId(req.VolumeId))
@ -56,7 +56,7 @@ func (vs *VolumeServer) VolumeTierCopyDatToRemote(req *volume_server_pb.VolumeTi
return nil return nil
} }
startTime = now startTime = now
return stream.Send(&volume_server_pb.VolumeTierCopyDatToRemoteResponse{ return stream.Send(&volume_server_pb.VolumeTierMoveDatToRemoteResponse{
Processed: progressed, Processed: progressed,
ProcessedPercentage: percentage, ProcessedPercentage: percentage,
}) })

View file

@ -47,7 +47,7 @@ func (c *commandEcDecode) Do(args []string, commandEnv *CommandEnv, writer io.Wr
vid := needle.VolumeId(*volumeId) vid := needle.VolumeId(*volumeId)
// collect topology information // collect topology information
topologyInfo, err := collectTopologyInfoForEcDecode(ctx, commandEnv) topologyInfo, err := collectTopologyInfo(ctx, commandEnv)
if err != nil { if err != nil {
return err return err
} }
@ -203,7 +203,7 @@ func collectEcShards(ctx context.Context, commandEnv *CommandEnv, nodeToEcIndexB
} }
func collectTopologyInfoForEcDecode(ctx context.Context, commandEnv *CommandEnv) (topoInfo *master_pb.TopologyInfo, err error) { func collectTopologyInfo(ctx context.Context, commandEnv *CommandEnv) (topoInfo *master_pb.TopologyInfo, err error) {
var resp *master_pb.VolumeListResponse var resp *master_pb.VolumeListResponse
err = commandEnv.MasterClient.WithClient(ctx, func(client master_pb.SeaweedClient) error { err = commandEnv.MasterClient.WithClient(ctx, func(client master_pb.SeaweedClient) error {

View file

@ -0,0 +1,167 @@
package shell
import (
"context"
"flag"
"fmt"
"io"
"google.golang.org/grpc"
"github.com/chrislusf/seaweedfs/weed/operation"
"github.com/chrislusf/seaweedfs/weed/pb/master_pb"
"github.com/chrislusf/seaweedfs/weed/pb/volume_server_pb"
"github.com/chrislusf/seaweedfs/weed/storage/needle"
)
func init() {
Commands = append(Commands, &commandVolumeTierDownload{})
}
type commandVolumeTierDownload struct {
}
func (c *commandVolumeTierDownload) Name() string {
return "volume.tier.download"
}
func (c *commandVolumeTierDownload) Help() string {
return `move the dat file of a volume to a remote tier
volume.tier.download [-collection=""]
volume.tier.download [-collection=""] -volumeId=<volume_id>
e.g.:
volume.tier.download -volumeId=7
volume.tier.download -volumeId=7
This command will download the dat file of a volume from a remote tier to a volume server in local cluster.
`
}
func (c *commandVolumeTierDownload) Do(args []string, commandEnv *CommandEnv, writer io.Writer) (err error) {
tierCommand := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
volumeId := tierCommand.Int("volumeId", 0, "the volume id")
collection := tierCommand.String("collection", "", "the collection name")
if err = tierCommand.Parse(args); err != nil {
return nil
}
ctx := context.Background()
vid := needle.VolumeId(*volumeId)
// collect topology information
topologyInfo, err := collectTopologyInfo(ctx, commandEnv)
if err != nil {
return err
}
// volumeId is provided
if vid != 0 {
return doVolumeTierDownload(ctx, commandEnv, writer, *collection, vid)
}
// apply to all volumes in the collection
// reusing collectVolumeIdsForEcEncode for now
volumeIds := collectRemoteVolumes(topologyInfo, *collection)
if err != nil {
return err
}
fmt.Printf("tier download volumes: %v\n", volumeIds)
for _, vid := range volumeIds {
if err = doVolumeTierDownload(ctx, commandEnv, writer, *collection, vid); err != nil {
return err
}
}
return nil
}
func collectRemoteVolumes(topoInfo *master_pb.TopologyInfo, selectedCollection string) (vids []needle.VolumeId) {
vidMap := make(map[uint32]bool)
eachDataNode(topoInfo, func(dc string, rack RackId, dn *master_pb.DataNodeInfo) {
for _, v := range dn.VolumeInfos {
if v.Collection == selectedCollection && v.RemoteStorageKey != "" && v.RemoteStorageName != "" {
vidMap[v.Id] = true
}
}
})
for vid := range vidMap {
vids = append(vids, needle.VolumeId(vid))
}
return
}
func doVolumeTierDownload(ctx context.Context, commandEnv *CommandEnv, writer io.Writer, collection string, vid needle.VolumeId) (err error) {
// find volume location
locations, found := commandEnv.MasterClient.GetLocations(uint32(vid))
if !found {
return fmt.Errorf("volume %d not found", vid)
}
// TODO parallelize this
for _, loc := range locations {
// copy the .dat file from remote tier to local
err = downloadDatFromRemoteTier(ctx, commandEnv.option.GrpcDialOption, writer, needle.VolumeId(vid), collection, loc.Url)
if err != nil {
return fmt.Errorf("download dat file for volume %d to %s: %v", vid, loc.Url, err)
}
}
return nil
}
func downloadDatFromRemoteTier(ctx context.Context, grpcDialOption grpc.DialOption, writer io.Writer, volumeId needle.VolumeId, collection string, targetVolumeServer string) error {
err := operation.WithVolumeServerClient(targetVolumeServer, grpcDialOption, func(volumeServerClient volume_server_pb.VolumeServerClient) error {
stream, downloadErr := volumeServerClient.VolumeTierMoveDatFromRemote(ctx, &volume_server_pb.VolumeTierMoveDatFromRemoteRequest{
VolumeId: uint32(volumeId),
Collection: collection,
})
var lastProcessed int64
for {
resp, recvErr := stream.Recv()
if recvErr != nil {
if recvErr == io.EOF {
break
} else {
return recvErr
}
}
processingSpeed := float64(resp.Processed-lastProcessed) / 1024.0 / 1024.0
fmt.Fprintf(writer, "downloaded %.2f%%, %d bytes, %.2fMB/s\n", resp.ProcessedPercentage, resp.Processed, processingSpeed)
lastProcessed = resp.Processed
}
if downloadErr != nil {
return downloadErr
}
_, unmountErr := volumeServerClient.VolumeUnmount(ctx, &volume_server_pb.VolumeUnmountRequest{
VolumeId: uint32(volumeId),
})
if unmountErr != nil {
return unmountErr
}
_, mountErr := volumeServerClient.VolumeMount(ctx, &volume_server_pb.VolumeMountRequest{
VolumeId: uint32(volumeId),
})
if mountErr != nil {
return mountErr
}
return nil
})
return err
}

View file

@ -7,24 +7,25 @@ import (
"io" "io"
"time" "time"
"google.golang.org/grpc"
"github.com/chrislusf/seaweedfs/weed/operation" "github.com/chrislusf/seaweedfs/weed/operation"
"github.com/chrislusf/seaweedfs/weed/pb/volume_server_pb" "github.com/chrislusf/seaweedfs/weed/pb/volume_server_pb"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"google.golang.org/grpc"
) )
func init() { func init() {
Commands = append(Commands, &commandVolumeTier{}) Commands = append(Commands, &commandVolumeTierUpload{})
} }
type commandVolumeTier struct { type commandVolumeTierUpload struct {
} }
func (c *commandVolumeTier) Name() string { func (c *commandVolumeTierUpload) Name() string {
return "volume.tier.upload" return "volume.tier.upload"
} }
func (c *commandVolumeTier) Help() string { func (c *commandVolumeTierUpload) Help() string {
return `move the dat file of a volume to a remote tier return `move the dat file of a volume to a remote tier
volume.tier.upload [-collection=""] [-fullPercent=95] [-quietFor=1h] volume.tier.upload [-collection=""] [-fullPercent=95] [-quietFor=1h]
@ -53,7 +54,7 @@ func (c *commandVolumeTier) Help() string {
` `
} }
func (c *commandVolumeTier) Do(args []string, commandEnv *CommandEnv, writer io.Writer) (err error) { func (c *commandVolumeTierUpload) Do(args []string, commandEnv *CommandEnv, writer io.Writer) (err error) {
tierCommand := flag.NewFlagSet(c.Name(), flag.ContinueOnError) tierCommand := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
volumeId := tierCommand.Int("volumeId", 0, "the volume id") volumeId := tierCommand.Int("volumeId", 0, "the volume id")
@ -71,7 +72,7 @@ func (c *commandVolumeTier) Do(args []string, commandEnv *CommandEnv, writer io.
// volumeId is provided // volumeId is provided
if vid != 0 { if vid != 0 {
return doVolumeTier(ctx, commandEnv, writer, *collection, vid, *dest, *keepLocalDatFile) return doVolumeTierUpload(ctx, commandEnv, writer, *collection, vid, *dest, *keepLocalDatFile)
} }
// apply to all volumes in the collection // apply to all volumes in the collection
@ -80,9 +81,9 @@ func (c *commandVolumeTier) Do(args []string, commandEnv *CommandEnv, writer io.
if err != nil { if err != nil {
return err return err
} }
fmt.Printf("tiering volumes: %v\n", volumeIds) fmt.Printf("tier upload volumes: %v\n", volumeIds)
for _, vid := range volumeIds { for _, vid := range volumeIds {
if err = doVolumeTier(ctx, commandEnv, writer, *collection, vid, *dest, *keepLocalDatFile); err != nil { if err = doVolumeTierUpload(ctx, commandEnv, writer, *collection, vid, *dest, *keepLocalDatFile); err != nil {
return err return err
} }
} }
@ -90,23 +91,20 @@ func (c *commandVolumeTier) Do(args []string, commandEnv *CommandEnv, writer io.
return nil return nil
} }
func doVolumeTier(ctx context.Context, commandEnv *CommandEnv, writer io.Writer, collection string, vid needle.VolumeId, dest string, keepLocalDatFile bool) (err error) { func doVolumeTierUpload(ctx context.Context, commandEnv *CommandEnv, writer io.Writer, collection string, vid needle.VolumeId, dest string, keepLocalDatFile bool) (err error) {
// find volume location // find volume location
locations, found := commandEnv.MasterClient.GetLocations(uint32(vid)) locations, found := commandEnv.MasterClient.GetLocations(uint32(vid))
if !found { if !found {
return fmt.Errorf("volume %d not found", vid) return fmt.Errorf("volume %d not found", vid)
} }
// mark the volume as readonly err = markVolumeReadonly(ctx, commandEnv.option.GrpcDialOption, needle.VolumeId(vid), locations)
/* if err != nil {
err = markVolumeReadonly(ctx, commandEnv.option.GrpcDialOption, needle.VolumeId(vid), locations) return fmt.Errorf("mark volume %d as readonly on %s: %v", vid, locations[0].Url, err)
if err != nil { }
return fmt.Errorf("mark volume %d as readonly on %s: %v", vid, locations[0].Url, err)
}
*/
// copy the .dat file to remote tier // copy the .dat file to remote tier
err = copyDatToRemoteTier(ctx, commandEnv.option.GrpcDialOption, writer, needle.VolumeId(vid), collection, locations[0].Url, dest, keepLocalDatFile) err = uploadDatToRemoteTier(ctx, commandEnv.option.GrpcDialOption, writer, needle.VolumeId(vid), collection, locations[0].Url, dest, keepLocalDatFile)
if err != nil { if err != nil {
return fmt.Errorf("copy dat file for volume %d on %s to %s: %v", vid, locations[0].Url, dest, err) return fmt.Errorf("copy dat file for volume %d on %s to %s: %v", vid, locations[0].Url, dest, err)
} }
@ -114,10 +112,10 @@ func doVolumeTier(ctx context.Context, commandEnv *CommandEnv, writer io.Writer,
return nil return nil
} }
func copyDatToRemoteTier(ctx context.Context, grpcDialOption grpc.DialOption, writer io.Writer, volumeId needle.VolumeId, collection string, sourceVolumeServer string, dest string, keepLocalDatFile bool) error { func uploadDatToRemoteTier(ctx context.Context, grpcDialOption grpc.DialOption, writer io.Writer, volumeId needle.VolumeId, collection string, sourceVolumeServer string, dest string, keepLocalDatFile bool) error {
err := operation.WithVolumeServerClient(sourceVolumeServer, grpcDialOption, func(volumeServerClient volume_server_pb.VolumeServerClient) error { err := operation.WithVolumeServerClient(sourceVolumeServer, grpcDialOption, func(volumeServerClient volume_server_pb.VolumeServerClient) error {
stream, copyErr := volumeServerClient.VolumeTierCopyDatToRemote(ctx, &volume_server_pb.VolumeTierCopyDatToRemoteRequest{ stream, copyErr := volumeServerClient.VolumeTierMoveDatToRemote(ctx, &volume_server_pb.VolumeTierMoveDatToRemoteRequest{
VolumeId: uint32(volumeId), VolumeId: uint32(volumeId),
Collection: collection, Collection: collection,
DestinationBackendName: dest, DestinationBackendName: dest,

View file

@ -25,6 +25,8 @@ type BackendStorage interface {
ToProperties() map[string]string ToProperties() map[string]string
NewStorageFile(key string, tierInfo *volume_server_pb.VolumeTierInfo) BackendStorageFile NewStorageFile(key string, tierInfo *volume_server_pb.VolumeTierInfo) BackendStorageFile
CopyFile(f *os.File, fn func(progressed int64, percentage float32) error) (key string, size int64, err error) CopyFile(f *os.File, fn func(progressed int64, percentage float32) error) (key string, size int64, err error)
DownloadFile(fileName string, key string, fn func(progressed int64, percentage float32) error) (size int64, err error)
DeleteFile(key string) (err error)
} }
type StringProperties interface { type StringProperties interface {
@ -41,6 +43,7 @@ var (
BackendStorages = make(map[string]BackendStorage) BackendStorages = make(map[string]BackendStorage)
) )
// used by master to load remote storage configurations
func LoadConfiguration(config *viper.Viper) { func LoadConfiguration(config *viper.Viper) {
StorageBackendPrefix := "storage.backend" StorageBackendPrefix := "storage.backend"
@ -70,6 +73,7 @@ func LoadConfiguration(config *viper.Viper) {
} }
// used by volume server to receive remote storage configurations from master
func LoadFromPbStorageBackends(storageBackends []*master_pb.StorageBackend) { func LoadFromPbStorageBackends(storageBackends []*master_pb.StorageBackend) {
for _, storageBackend := range storageBackends { for _, storageBackend := range storageBackends {

View file

@ -9,10 +9,11 @@ import (
"github.com/aws/aws-sdk-go/service/s3" "github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3iface" "github.com/aws/aws-sdk-go/service/s3/s3iface"
"github.com/google/uuid"
"github.com/chrislusf/seaweedfs/weed/glog" "github.com/chrislusf/seaweedfs/weed/glog"
"github.com/chrislusf/seaweedfs/weed/pb/volume_server_pb" "github.com/chrislusf/seaweedfs/weed/pb/volume_server_pb"
"github.com/chrislusf/seaweedfs/weed/storage/backend" "github.com/chrislusf/seaweedfs/weed/storage/backend"
"github.com/google/uuid"
) )
func init() { func init() {
@ -85,6 +86,24 @@ func (s *S3BackendStorage) CopyFile(f *os.File, fn func(progressed int64, percen
return return
} }
func (s *S3BackendStorage) DownloadFile(fileName string, key string, fn func(progressed int64, percentage float32) error) (size int64, err error) {
glog.V(1).Infof("download dat file of %s from remote s3.%s as %s", fileName, s.id, key)
size, err = downloadFromS3(s.conn, fileName, s.bucket, key, fn)
return
}
func (s *S3BackendStorage) DeleteFile(key string) (err error) {
glog.V(1).Infof("delete dat file %s from remote", key)
err = deleteFromS3(s.conn, s.bucket, key)
return
}
type S3BackendStorageFile struct { type S3BackendStorageFile struct {
backendStorage *S3BackendStorage backendStorage *S3BackendStorage
key string key string

View file

@ -0,0 +1,98 @@
package s3_backend
import (
"fmt"
"os"
"sync/atomic"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3iface"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
"github.com/chrislusf/seaweedfs/weed/glog"
)
func downloadFromS3(sess s3iface.S3API, destFileName string, sourceBucket string, sourceKey string,
fn func(progressed int64, percentage float32) error) (fileSize int64, err error) {
fileSize, err = getFileSize(sess, sourceBucket, sourceKey)
if err != nil {
return
}
//open the file
f, err := os.OpenFile(destFileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
return 0, fmt.Errorf("failed to open file %q, %v", destFileName, err)
}
defer f.Close()
// Create a downloader with the session and custom options
downloader := s3manager.NewDownloaderWithClient(sess, func(u *s3manager.Downloader) {
u.PartSize = int64(64 * 1024 * 1024)
u.Concurrency = 5
})
fileWriter := &s3DownloadProgressedWriter{
fp: f,
size: fileSize,
written: 0,
fn: fn,
}
// Download the file from S3.
fileSize, err = downloader.Download(fileWriter,&s3.GetObjectInput{
Bucket: aws.String(sourceBucket),
Key: aws.String(sourceKey),
})
if err != nil {
return fileSize, fmt.Errorf("failed to download file %s: %v", destFileName, err)
}
glog.V(1).Infof("downloaded file %s\n", destFileName)
return
}
// adapted from https://github.com/aws/aws-sdk-go/pull/1868
// and https://petersouter.xyz/s3-download-progress-bar-in-golang/
type s3DownloadProgressedWriter struct {
fp *os.File
size int64
written int64
fn func(progressed int64, percentage float32) error
}
func (w *s3DownloadProgressedWriter) WriteAt(p []byte, off int64) (int, error) {
n, err := w.fp.WriteAt(p, off)
if err != nil {
return n, err
}
// Got the length have read( or means has uploaded), and you can construct your message
atomic.AddInt64(&w.written, int64(n))
if w.fn != nil {
written := w.written
if err := w.fn(written, float32(written*100)/float32(w.size)); err != nil {
return n, err
}
}
return n, err
}
func getFileSize(svc s3iface.S3API, bucket string, key string) (filesize int64, error error) {
params := &s3.HeadObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
}
resp, err := svc.HeadObject(params)
if err != nil {
return 0, err
}
return *resp.ContentLength, nil
}

View file

@ -52,3 +52,11 @@ func createSession(awsAccessKeyId, awsSecretAccessKey, region string) (s3iface.S
return t, nil return t, nil
} }
func deleteFromS3(sess s3iface.S3API, sourceBucket string, sourceKey string) (err error) {
_, err = sess.DeleteObject(&s3.DeleteObjectInput{
Bucket: aws.String(sourceBucket),
Key: aws.String(sourceKey),
})
return err
}