Browse Source

shell: add ec.decode command

pull/1167/head
Chris Lu 5 years ago
parent
commit
09ca936c78
  1. 6
      unmaintained/change_superblock/change_superblock.go
  2. 6
      unmaintained/fix_dat/fix_dat.go
  3. 5
      unmaintained/remove_duplicate_fids/remove_duplicate_fids.go
  4. 3
      unmaintained/see_dat/see_dat.go
  5. 10
      weed/command/backup.go
  6. 8
      weed/command/export.go
  7. 5
      weed/command/fix.go
  8. 11
      weed/pb/volume_server.proto
  9. 482
      weed/pb/volume_server_pb/volume_server.pb.go
  10. 7
      weed/server/master_grpc_server_volume.go
  11. 4
      weed/server/master_server_handlers_admin.go
  12. 22
      weed/server/volume_grpc_copy.go
  13. 75
      weed/server/volume_grpc_erasure_coding.go
  14. 3
      weed/server/volume_grpc_tail.go
  15. 1
      weed/shell/command_ec_common.go
  16. 263
      weed/shell/command_ec_decode.go
  17. 1
      weed/shell/command_ec_rebuild.go
  18. 15
      weed/shell/command_volume_fix_replication.go
  19. 198
      weed/storage/erasure_coding/ec_decoder.go
  20. 2
      weed/storage/erasure_coding/ec_encoder.go
  21. 9
      weed/storage/erasure_coding/ec_volume_info.go
  22. 9
      weed/storage/store.go
  23. 6
      weed/storage/store_ec.go
  24. 2
      weed/storage/super_block/replica_placement.go
  25. 2
      weed/storage/super_block/replica_placement_test.go
  26. 69
      weed/storage/super_block/super_block.go
  27. 44
      weed/storage/super_block/super_block_read.go.go
  28. 4
      weed/storage/super_block/super_block_test.go
  29. 9
      weed/storage/volume.go
  30. 12
      weed/storage/volume_backup.go
  31. 7
      weed/storage/volume_info.go
  32. 5
      weed/storage/volume_loading.go
  33. 3
      weed/storage/volume_read_write.go
  34. 103
      weed/storage/volume_super_block.go
  35. 7
      weed/storage/volume_vacuum.go
  36. 5
      weed/storage/volume_vacuum_test.go
  37. 4
      weed/topology/collection.go
  38. 4
      weed/topology/topology.go
  39. 5
      weed/topology/topology_test.go
  40. 4
      weed/topology/volume_growth.go
  41. 3
      weed/topology/volume_growth_test.go
  42. 5
      weed/topology/volume_layout.go

6
unmaintained/change_superblock/change_superblock.go

@ -8,9 +8,9 @@ import (
"strconv" "strconv"
"github.com/chrislusf/seaweedfs/weed/glog" "github.com/chrislusf/seaweedfs/weed/glog"
"github.com/chrislusf/seaweedfs/weed/storage"
"github.com/chrislusf/seaweedfs/weed/storage/backend" "github.com/chrislusf/seaweedfs/weed/storage/backend"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
) )
var ( var (
@ -51,7 +51,7 @@ func main() {
datBackend := backend.NewDiskFile(datFile) datBackend := backend.NewDiskFile(datFile)
defer datBackend.Close() defer datBackend.Close()
superBlock, err := storage.ReadSuperBlock(datBackend)
superBlock, err := super_block.ReadSuperBlock(datBackend)
if err != nil { if err != nil {
glog.Fatalf("cannot parse existing super block: %v", err) glog.Fatalf("cannot parse existing super block: %v", err)
@ -63,7 +63,7 @@ func main() {
hasChange := false hasChange := false
if *targetReplica != "" { if *targetReplica != "" {
replica, err := storage.NewReplicaPlacementFromString(*targetReplica)
replica, err := super_block.NewReplicaPlacementFromString(*targetReplica)
if err != nil { if err != nil {
glog.Fatalf("cannot parse target replica %s: %v", *targetReplica, err) glog.Fatalf("cannot parse target replica %s: %v", *targetReplica, err)

6
unmaintained/fix_dat/fix_dat.go

@ -9,9 +9,9 @@ import (
"strconv" "strconv"
"github.com/chrislusf/seaweedfs/weed/glog" "github.com/chrislusf/seaweedfs/weed/glog"
"github.com/chrislusf/seaweedfs/weed/storage"
"github.com/chrislusf/seaweedfs/weed/storage/backend" "github.com/chrislusf/seaweedfs/weed/storage/backend"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
"github.com/chrislusf/seaweedfs/weed/storage/types" "github.com/chrislusf/seaweedfs/weed/storage/types"
"github.com/chrislusf/seaweedfs/weed/util" "github.com/chrislusf/seaweedfs/weed/util"
) )
@ -59,7 +59,7 @@ func main() {
} }
defer newDatFile.Close() defer newDatFile.Close()
superBlock, err := storage.ReadSuperBlock(datBackend)
superBlock, err := super_block.ReadSuperBlock(datBackend)
if err != nil { if err != nil {
glog.Fatalf("Read Volume Data superblock %v", err) glog.Fatalf("Read Volume Data superblock %v", err)
} }
@ -81,7 +81,7 @@ func iterateEntries(datBackend backend.BackendStorageFile, idxFile *os.File, vis
readerOffset += int64(count) readerOffset += int64(count)
// start to read dat file // start to read dat file
superBlock, err := storage.ReadSuperBlock(datBackend)
superBlock, err := super_block.ReadSuperBlock(datBackend)
if err != nil { if err != nil {
fmt.Printf("cannot read dat file super block: %v", err) fmt.Printf("cannot read dat file super block: %v", err)
return return

5
unmaintained/remove_duplicate_fids/remove_duplicate_fids.go

@ -10,6 +10,7 @@ import (
"github.com/chrislusf/seaweedfs/weed/storage" "github.com/chrislusf/seaweedfs/weed/storage"
"github.com/chrislusf/seaweedfs/weed/storage/backend" "github.com/chrislusf/seaweedfs/weed/storage/backend"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
) )
var ( var (
@ -24,7 +25,7 @@ func Checksum(n *needle.Needle) string {
type VolumeFileScanner4SeeDat struct { type VolumeFileScanner4SeeDat struct {
version needle.Version version needle.Version
block storage.SuperBlock
block super_block.SuperBlock
dir string dir string
hashes map[string]bool hashes map[string]bool
@ -32,7 +33,7 @@ type VolumeFileScanner4SeeDat struct {
datBackend backend.BackendStorageFile datBackend backend.BackendStorageFile
} }
func (scanner *VolumeFileScanner4SeeDat) VisitSuperBlock(superBlock storage.SuperBlock) error {
func (scanner *VolumeFileScanner4SeeDat) VisitSuperBlock(superBlock super_block.SuperBlock) error {
scanner.version = superBlock.Version() scanner.version = superBlock.Version()
scanner.block = superBlock scanner.block = superBlock
return nil return nil

3
unmaintained/see_dat/see_dat.go

@ -7,6 +7,7 @@ import (
"github.com/chrislusf/seaweedfs/weed/glog" "github.com/chrislusf/seaweedfs/weed/glog"
"github.com/chrislusf/seaweedfs/weed/storage" "github.com/chrislusf/seaweedfs/weed/storage"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
) )
var ( var (
@ -19,7 +20,7 @@ type VolumeFileScanner4SeeDat struct {
version needle.Version version needle.Version
} }
func (scanner *VolumeFileScanner4SeeDat) VisitSuperBlock(superBlock storage.SuperBlock) error {
func (scanner *VolumeFileScanner4SeeDat) VisitSuperBlock(superBlock super_block.SuperBlock) error {
scanner.version = superBlock.Version() scanner.version = superBlock.Version()
return nil return nil

10
weed/command/backup.go

@ -3,10 +3,12 @@ package command
import ( import (
"fmt" "fmt"
"github.com/spf13/viper"
"github.com/chrislusf/seaweedfs/weed/security" "github.com/chrislusf/seaweedfs/weed/security"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
"github.com/chrislusf/seaweedfs/weed/util" "github.com/chrislusf/seaweedfs/weed/util"
"github.com/spf13/viper"
"github.com/chrislusf/seaweedfs/weed/operation" "github.com/chrislusf/seaweedfs/weed/operation"
"github.com/chrislusf/seaweedfs/weed/storage" "github.com/chrislusf/seaweedfs/weed/storage"
@ -98,15 +100,15 @@ func runBackup(cmd *Command, args []string) bool {
return true return true
} }
} }
var replication *storage.ReplicaPlacement
var replication *super_block.ReplicaPlacement
if *s.replication != "" { if *s.replication != "" {
replication, err = storage.NewReplicaPlacementFromString(*s.replication)
replication, err = super_block.NewReplicaPlacementFromString(*s.replication)
if err != nil { if err != nil {
fmt.Printf("Error generate volume %d replication %s : %v\n", vid, *s.replication, err) fmt.Printf("Error generate volume %d replication %s : %v\n", vid, *s.replication, err)
return true return true
} }
} else { } else {
replication, err = storage.NewReplicaPlacementFromString(stats.Replication)
replication, err = super_block.NewReplicaPlacementFromString(stats.Replication)
if err != nil { if err != nil {
fmt.Printf("Error get volume %d replication %s : %v\n", vid, stats.Replication, err) fmt.Printf("Error get volume %d replication %s : %v\n", vid, stats.Replication, err)
return true return true

8
weed/command/export.go

@ -4,6 +4,7 @@ import (
"archive/tar" "archive/tar"
"bytes" "bytes"
"fmt" "fmt"
"io"
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
@ -12,11 +13,10 @@ import (
"text/template" "text/template"
"time" "time"
"io"
"github.com/chrislusf/seaweedfs/weed/glog" "github.com/chrislusf/seaweedfs/weed/glog"
"github.com/chrislusf/seaweedfs/weed/storage" "github.com/chrislusf/seaweedfs/weed/storage"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
"github.com/chrislusf/seaweedfs/weed/storage/types" "github.com/chrislusf/seaweedfs/weed/storage/types"
) )
@ -93,8 +93,8 @@ type VolumeFileScanner4Export struct {
vid needle.VolumeId vid needle.VolumeId
} }
func (scanner *VolumeFileScanner4Export) VisitSuperBlock(superBlock storage.SuperBlock) error {
scanner.version = superBlock.Version()
func (scanner *VolumeFileScanner4Export) VisitSuperBlock(superBlock super_block.SuperBlock) error {
scanner.version = superBlock.Version
return nil return nil
} }

5
weed/command/fix.go

@ -8,6 +8,7 @@ import (
"github.com/chrislusf/seaweedfs/weed/glog" "github.com/chrislusf/seaweedfs/weed/glog"
"github.com/chrislusf/seaweedfs/weed/storage" "github.com/chrislusf/seaweedfs/weed/storage"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
"github.com/chrislusf/seaweedfs/weed/storage/types" "github.com/chrislusf/seaweedfs/weed/storage/types"
) )
@ -34,8 +35,8 @@ type VolumeFileScanner4Fix struct {
nm *storage.NeedleMap nm *storage.NeedleMap
} }
func (scanner *VolumeFileScanner4Fix) VisitSuperBlock(superBlock storage.SuperBlock) error {
scanner.version = superBlock.Version()
func (scanner *VolumeFileScanner4Fix) VisitSuperBlock(superBlock super_block.SuperBlock) error {
scanner.version = superBlock.Version
return nil return nil
} }

11
weed/pb/volume_server.proto

@ -66,6 +66,8 @@ service VolumeServer {
} }
rpc VolumeEcBlobDelete (VolumeEcBlobDeleteRequest) returns (VolumeEcBlobDeleteResponse) { rpc VolumeEcBlobDelete (VolumeEcBlobDeleteRequest) returns (VolumeEcBlobDeleteResponse) {
} }
rpc VolumeEcShardsToVolume (VolumeEcShardsToVolumeRequest) returns (VolumeEcShardsToVolumeResponse) {
}
// tiered storage // tiered storage
rpc VolumeTierCopyDatToRemote (VolumeTierCopyDatToRemoteRequest) returns (stream VolumeTierCopyDatToRemoteResponse) { rpc VolumeTierCopyDatToRemote (VolumeTierCopyDatToRemoteRequest) returns (stream VolumeTierCopyDatToRemoteResponse) {
@ -203,6 +205,7 @@ message CopyFileRequest {
uint64 stop_offset = 4; uint64 stop_offset = 4;
string collection = 5; string collection = 5;
bool is_ec_volume = 6; bool is_ec_volume = 6;
bool ignore_source_file_not_found = 7;
} }
message CopyFileResponse { message CopyFileResponse {
bytes file_content = 1; bytes file_content = 1;
@ -249,6 +252,7 @@ message VolumeEcShardsCopyRequest {
repeated uint32 shard_ids = 3; repeated uint32 shard_ids = 3;
bool copy_ecx_file = 4; bool copy_ecx_file = 4;
string source_data_node = 5; string source_data_node = 5;
bool copy_ecj_file = 6;
} }
message VolumeEcShardsCopyResponse { message VolumeEcShardsCopyResponse {
} }
@ -297,6 +301,13 @@ message VolumeEcBlobDeleteRequest {
message VolumeEcBlobDeleteResponse { message VolumeEcBlobDeleteResponse {
} }
message VolumeEcShardsToVolumeRequest {
uint32 volume_id = 1;
string collection = 2;
}
message VolumeEcShardsToVolumeResponse {
}
message ReadVolumeFileStatusRequest { message ReadVolumeFileStatusRequest {
uint32 volume_id = 1; uint32 volume_id = 1;
} }

482
weed/pb/volume_server_pb/volume_server.pb.go

@ -61,6 +61,8 @@ It has these top-level messages:
VolumeEcShardReadResponse VolumeEcShardReadResponse
VolumeEcBlobDeleteRequest VolumeEcBlobDeleteRequest
VolumeEcBlobDeleteResponse VolumeEcBlobDeleteResponse
VolumeEcShardsToVolumeRequest
VolumeEcShardsToVolumeResponse
ReadVolumeFileStatusRequest ReadVolumeFileStatusRequest
ReadVolumeFileStatusResponse ReadVolumeFileStatusResponse
DiskStatus DiskStatus
@ -663,12 +665,13 @@ func (m *VolumeCopyResponse) GetLastAppendAtNs() uint64 {
} }
type CopyFileRequest struct { type CopyFileRequest struct {
VolumeId uint32 `protobuf:"varint,1,opt,name=volume_id,json=volumeId" json:"volume_id,omitempty"`
Ext string `protobuf:"bytes,2,opt,name=ext" json:"ext,omitempty"`
CompactionRevision uint32 `protobuf:"varint,3,opt,name=compaction_revision,json=compactionRevision" json:"compaction_revision,omitempty"`
StopOffset uint64 `protobuf:"varint,4,opt,name=stop_offset,json=stopOffset" json:"stop_offset,omitempty"`
Collection string `protobuf:"bytes,5,opt,name=collection" json:"collection,omitempty"`
IsEcVolume bool `protobuf:"varint,6,opt,name=is_ec_volume,json=isEcVolume" json:"is_ec_volume,omitempty"`
VolumeId uint32 `protobuf:"varint,1,opt,name=volume_id,json=volumeId" json:"volume_id,omitempty"`
Ext string `protobuf:"bytes,2,opt,name=ext" json:"ext,omitempty"`
CompactionRevision uint32 `protobuf:"varint,3,opt,name=compaction_revision,json=compactionRevision" json:"compaction_revision,omitempty"`
StopOffset uint64 `protobuf:"varint,4,opt,name=stop_offset,json=stopOffset" json:"stop_offset,omitempty"`
Collection string `protobuf:"bytes,5,opt,name=collection" json:"collection,omitempty"`
IsEcVolume bool `protobuf:"varint,6,opt,name=is_ec_volume,json=isEcVolume" json:"is_ec_volume,omitempty"`
IgnoreSourceFileNotFound bool `protobuf:"varint,7,opt,name=ignore_source_file_not_found,json=ignoreSourceFileNotFound" json:"ignore_source_file_not_found,omitempty"`
} }
func (m *CopyFileRequest) Reset() { *m = CopyFileRequest{} } func (m *CopyFileRequest) Reset() { *m = CopyFileRequest{} }
@ -718,6 +721,13 @@ func (m *CopyFileRequest) GetIsEcVolume() bool {
return false return false
} }
func (m *CopyFileRequest) GetIgnoreSourceFileNotFound() bool {
if m != nil {
return m.IgnoreSourceFileNotFound
}
return false
}
type CopyFileResponse struct { type CopyFileResponse struct {
FileContent []byte `protobuf:"bytes,1,opt,name=file_content,json=fileContent,proto3" json:"file_content,omitempty"` FileContent []byte `protobuf:"bytes,1,opt,name=file_content,json=fileContent,proto3" json:"file_content,omitempty"`
} }
@ -924,6 +934,7 @@ type VolumeEcShardsCopyRequest struct {
ShardIds []uint32 `protobuf:"varint,3,rep,packed,name=shard_ids,json=shardIds" json:"shard_ids,omitempty"` ShardIds []uint32 `protobuf:"varint,3,rep,packed,name=shard_ids,json=shardIds" json:"shard_ids,omitempty"`
CopyEcxFile bool `protobuf:"varint,4,opt,name=copy_ecx_file,json=copyEcxFile" json:"copy_ecx_file,omitempty"` CopyEcxFile bool `protobuf:"varint,4,opt,name=copy_ecx_file,json=copyEcxFile" json:"copy_ecx_file,omitempty"`
SourceDataNode string `protobuf:"bytes,5,opt,name=source_data_node,json=sourceDataNode" json:"source_data_node,omitempty"` SourceDataNode string `protobuf:"bytes,5,opt,name=source_data_node,json=sourceDataNode" json:"source_data_node,omitempty"`
CopyEcjFile bool `protobuf:"varint,6,opt,name=copy_ecj_file,json=copyEcjFile" json:"copy_ecj_file,omitempty"`
} }
func (m *VolumeEcShardsCopyRequest) Reset() { *m = VolumeEcShardsCopyRequest{} } func (m *VolumeEcShardsCopyRequest) Reset() { *m = VolumeEcShardsCopyRequest{} }
@ -966,6 +977,13 @@ func (m *VolumeEcShardsCopyRequest) GetSourceDataNode() string {
return "" return ""
} }
func (m *VolumeEcShardsCopyRequest) GetCopyEcjFile() bool {
if m != nil {
return m.CopyEcjFile
}
return false
}
type VolumeEcShardsCopyResponse struct { type VolumeEcShardsCopyResponse struct {
} }
@ -1206,6 +1224,38 @@ func (m *VolumeEcBlobDeleteResponse) String() string { return proto.C
func (*VolumeEcBlobDeleteResponse) ProtoMessage() {} func (*VolumeEcBlobDeleteResponse) ProtoMessage() {}
func (*VolumeEcBlobDeleteResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{51} } func (*VolumeEcBlobDeleteResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{51} }
type VolumeEcShardsToVolumeRequest 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"`
}
func (m *VolumeEcShardsToVolumeRequest) Reset() { *m = VolumeEcShardsToVolumeRequest{} }
func (m *VolumeEcShardsToVolumeRequest) String() string { return proto.CompactTextString(m) }
func (*VolumeEcShardsToVolumeRequest) ProtoMessage() {}
func (*VolumeEcShardsToVolumeRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{52} }
func (m *VolumeEcShardsToVolumeRequest) GetVolumeId() uint32 {
if m != nil {
return m.VolumeId
}
return 0
}
func (m *VolumeEcShardsToVolumeRequest) GetCollection() string {
if m != nil {
return m.Collection
}
return ""
}
type VolumeEcShardsToVolumeResponse struct {
}
func (m *VolumeEcShardsToVolumeResponse) Reset() { *m = VolumeEcShardsToVolumeResponse{} }
func (m *VolumeEcShardsToVolumeResponse) String() string { return proto.CompactTextString(m) }
func (*VolumeEcShardsToVolumeResponse) ProtoMessage() {}
func (*VolumeEcShardsToVolumeResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{53} }
type ReadVolumeFileStatusRequest struct { type ReadVolumeFileStatusRequest 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"`
} }
@ -1213,7 +1263,7 @@ type ReadVolumeFileStatusRequest struct {
func (m *ReadVolumeFileStatusRequest) Reset() { *m = ReadVolumeFileStatusRequest{} } func (m *ReadVolumeFileStatusRequest) Reset() { *m = ReadVolumeFileStatusRequest{} }
func (m *ReadVolumeFileStatusRequest) String() string { return proto.CompactTextString(m) } func (m *ReadVolumeFileStatusRequest) String() string { return proto.CompactTextString(m) }
func (*ReadVolumeFileStatusRequest) ProtoMessage() {} func (*ReadVolumeFileStatusRequest) ProtoMessage() {}
func (*ReadVolumeFileStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{52} }
func (*ReadVolumeFileStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{54} }
func (m *ReadVolumeFileStatusRequest) GetVolumeId() uint32 { func (m *ReadVolumeFileStatusRequest) GetVolumeId() uint32 {
if m != nil { if m != nil {
@ -1236,7 +1286,7 @@ type ReadVolumeFileStatusResponse struct {
func (m *ReadVolumeFileStatusResponse) Reset() { *m = ReadVolumeFileStatusResponse{} } func (m *ReadVolumeFileStatusResponse) Reset() { *m = ReadVolumeFileStatusResponse{} }
func (m *ReadVolumeFileStatusResponse) String() string { return proto.CompactTextString(m) } func (m *ReadVolumeFileStatusResponse) String() string { return proto.CompactTextString(m) }
func (*ReadVolumeFileStatusResponse) ProtoMessage() {} func (*ReadVolumeFileStatusResponse) ProtoMessage() {}
func (*ReadVolumeFileStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{53} }
func (*ReadVolumeFileStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{55} }
func (m *ReadVolumeFileStatusResponse) GetVolumeId() uint32 { func (m *ReadVolumeFileStatusResponse) GetVolumeId() uint32 {
if m != nil { if m != nil {
@ -1304,7 +1354,7 @@ type DiskStatus struct {
func (m *DiskStatus) Reset() { *m = DiskStatus{} } func (m *DiskStatus) Reset() { *m = DiskStatus{} }
func (m *DiskStatus) String() string { return proto.CompactTextString(m) } func (m *DiskStatus) String() string { return proto.CompactTextString(m) }
func (*DiskStatus) ProtoMessage() {} func (*DiskStatus) ProtoMessage() {}
func (*DiskStatus) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{54} }
func (*DiskStatus) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{56} }
func (m *DiskStatus) GetDir() string { func (m *DiskStatus) GetDir() string {
if m != nil { if m != nil {
@ -1347,7 +1397,7 @@ type MemStatus struct {
func (m *MemStatus) Reset() { *m = MemStatus{} } func (m *MemStatus) Reset() { *m = MemStatus{} }
func (m *MemStatus) String() string { return proto.CompactTextString(m) } func (m *MemStatus) String() string { return proto.CompactTextString(m) }
func (*MemStatus) ProtoMessage() {} func (*MemStatus) ProtoMessage() {}
func (*MemStatus) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{55} }
func (*MemStatus) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{57} }
func (m *MemStatus) GetGoroutines() int32 { func (m *MemStatus) GetGoroutines() int32 {
if m != nil { if m != nil {
@ -1411,7 +1461,7 @@ type RemoteFile struct {
func (m *RemoteFile) Reset() { *m = RemoteFile{} } func (m *RemoteFile) Reset() { *m = RemoteFile{} }
func (m *RemoteFile) String() string { return proto.CompactTextString(m) } func (m *RemoteFile) String() string { return proto.CompactTextString(m) }
func (*RemoteFile) ProtoMessage() {} func (*RemoteFile) ProtoMessage() {}
func (*RemoteFile) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{56} }
func (*RemoteFile) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{58} }
func (m *RemoteFile) GetBackendType() string { func (m *RemoteFile) GetBackendType() string {
if m != nil { if m != nil {
@ -1462,7 +1512,7 @@ type VolumeTierInfo struct {
func (m *VolumeTierInfo) Reset() { *m = VolumeTierInfo{} } func (m *VolumeTierInfo) Reset() { *m = VolumeTierInfo{} }
func (m *VolumeTierInfo) String() string { return proto.CompactTextString(m) } func (m *VolumeTierInfo) String() string { return proto.CompactTextString(m) }
func (*VolumeTierInfo) ProtoMessage() {} func (*VolumeTierInfo) ProtoMessage() {}
func (*VolumeTierInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{57} }
func (*VolumeTierInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{59} }
func (m *VolumeTierInfo) GetFiles() []*RemoteFile { func (m *VolumeTierInfo) GetFiles() []*RemoteFile {
if m != nil { if m != nil {
@ -1482,7 +1532,7 @@ func (m *VolumeTierCopyDatToRemoteRequest) Reset() { *m = VolumeTierCopy
func (m *VolumeTierCopyDatToRemoteRequest) String() string { return proto.CompactTextString(m) } func (m *VolumeTierCopyDatToRemoteRequest) String() string { return proto.CompactTextString(m) }
func (*VolumeTierCopyDatToRemoteRequest) ProtoMessage() {} func (*VolumeTierCopyDatToRemoteRequest) ProtoMessage() {}
func (*VolumeTierCopyDatToRemoteRequest) Descriptor() ([]byte, []int) { func (*VolumeTierCopyDatToRemoteRequest) Descriptor() ([]byte, []int) {
return fileDescriptor0, []int{58}
return fileDescriptor0, []int{60}
} }
func (m *VolumeTierCopyDatToRemoteRequest) GetVolumeId() uint32 { func (m *VolumeTierCopyDatToRemoteRequest) GetVolumeId() uint32 {
@ -1522,7 +1572,7 @@ func (m *VolumeTierCopyDatToRemoteResponse) Reset() { *m = VolumeTierCop
func (m *VolumeTierCopyDatToRemoteResponse) String() string { return proto.CompactTextString(m) } func (m *VolumeTierCopyDatToRemoteResponse) String() string { return proto.CompactTextString(m) }
func (*VolumeTierCopyDatToRemoteResponse) ProtoMessage() {} func (*VolumeTierCopyDatToRemoteResponse) ProtoMessage() {}
func (*VolumeTierCopyDatToRemoteResponse) Descriptor() ([]byte, []int) { func (*VolumeTierCopyDatToRemoteResponse) Descriptor() ([]byte, []int) {
return fileDescriptor0, []int{59}
return fileDescriptor0, []int{61}
} }
func (m *VolumeTierCopyDatToRemoteResponse) GetProcessed() int64 { func (m *VolumeTierCopyDatToRemoteResponse) GetProcessed() int64 {
@ -1551,7 +1601,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{60} }
func (*QueryRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{62} }
func (m *QueryRequest) GetSelections() []string { func (m *QueryRequest) GetSelections() []string {
if m != nil { if m != nil {
@ -1597,7 +1647,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{60, 0} }
func (*QueryRequest_Filter) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{62, 0} }
func (m *QueryRequest_Filter) GetField() string { func (m *QueryRequest_Filter) GetField() string {
if m != nil { if m != nil {
@ -1632,7 +1682,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{60, 1}
return fileDescriptor0, []int{62, 1}
} }
func (m *QueryRequest_InputSerialization) GetCompressionType() string { func (m *QueryRequest_InputSerialization) GetCompressionType() string {
@ -1680,7 +1730,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{60, 1, 0}
return fileDescriptor0, []int{62, 1, 0}
} }
func (m *QueryRequest_InputSerialization_CSVInput) GetFileHeaderInfo() string { func (m *QueryRequest_InputSerialization_CSVInput) GetFileHeaderInfo() string {
@ -1742,7 +1792,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{60, 1, 1}
return fileDescriptor0, []int{62, 1, 1}
} }
func (m *QueryRequest_InputSerialization_JSONInput) GetType() string { func (m *QueryRequest_InputSerialization_JSONInput) GetType() string {
@ -1763,7 +1813,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{60, 1, 2}
return fileDescriptor0, []int{62, 1, 2}
} }
type QueryRequest_OutputSerialization struct { type QueryRequest_OutputSerialization struct {
@ -1775,7 +1825,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{60, 2}
return fileDescriptor0, []int{62, 2}
} }
func (m *QueryRequest_OutputSerialization) GetCsvOutput() *QueryRequest_OutputSerialization_CSVOutput { func (m *QueryRequest_OutputSerialization) GetCsvOutput() *QueryRequest_OutputSerialization_CSVOutput {
@ -1808,7 +1858,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{60, 2, 0}
return fileDescriptor0, []int{62, 2, 0}
} }
func (m *QueryRequest_OutputSerialization_CSVOutput) GetQuoteFields() string { func (m *QueryRequest_OutputSerialization_CSVOutput) GetQuoteFields() string {
@ -1858,7 +1908,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{60, 2, 1}
return fileDescriptor0, []int{62, 2, 1}
} }
func (m *QueryRequest_OutputSerialization_JSONOutput) GetRecordDelimiter() string { func (m *QueryRequest_OutputSerialization_JSONOutput) GetRecordDelimiter() string {
@ -1875,7 +1925,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{61} }
func (*QueriedStripe) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{63} }
func (m *QueriedStripe) GetRecords() []byte { func (m *QueriedStripe) GetRecords() []byte {
if m != nil { if m != nil {
@ -1937,6 +1987,8 @@ func init() {
proto.RegisterType((*VolumeEcShardReadResponse)(nil), "volume_server_pb.VolumeEcShardReadResponse") proto.RegisterType((*VolumeEcShardReadResponse)(nil), "volume_server_pb.VolumeEcShardReadResponse")
proto.RegisterType((*VolumeEcBlobDeleteRequest)(nil), "volume_server_pb.VolumeEcBlobDeleteRequest") proto.RegisterType((*VolumeEcBlobDeleteRequest)(nil), "volume_server_pb.VolumeEcBlobDeleteRequest")
proto.RegisterType((*VolumeEcBlobDeleteResponse)(nil), "volume_server_pb.VolumeEcBlobDeleteResponse") proto.RegisterType((*VolumeEcBlobDeleteResponse)(nil), "volume_server_pb.VolumeEcBlobDeleteResponse")
proto.RegisterType((*VolumeEcShardsToVolumeRequest)(nil), "volume_server_pb.VolumeEcShardsToVolumeRequest")
proto.RegisterType((*VolumeEcShardsToVolumeResponse)(nil), "volume_server_pb.VolumeEcShardsToVolumeResponse")
proto.RegisterType((*ReadVolumeFileStatusRequest)(nil), "volume_server_pb.ReadVolumeFileStatusRequest") proto.RegisterType((*ReadVolumeFileStatusRequest)(nil), "volume_server_pb.ReadVolumeFileStatusRequest")
proto.RegisterType((*ReadVolumeFileStatusResponse)(nil), "volume_server_pb.ReadVolumeFileStatusResponse") proto.RegisterType((*ReadVolumeFileStatusResponse)(nil), "volume_server_pb.ReadVolumeFileStatusResponse")
proto.RegisterType((*DiskStatus)(nil), "volume_server_pb.DiskStatus") proto.RegisterType((*DiskStatus)(nil), "volume_server_pb.DiskStatus")
@ -1997,6 +2049,7 @@ type VolumeServerClient interface {
VolumeEcShardsUnmount(ctx context.Context, in *VolumeEcShardsUnmountRequest, opts ...grpc.CallOption) (*VolumeEcShardsUnmountResponse, error) VolumeEcShardsUnmount(ctx context.Context, in *VolumeEcShardsUnmountRequest, opts ...grpc.CallOption) (*VolumeEcShardsUnmountResponse, error)
VolumeEcShardRead(ctx context.Context, in *VolumeEcShardReadRequest, opts ...grpc.CallOption) (VolumeServer_VolumeEcShardReadClient, error) VolumeEcShardRead(ctx context.Context, in *VolumeEcShardReadRequest, opts ...grpc.CallOption) (VolumeServer_VolumeEcShardReadClient, error)
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)
// tiered storage // tiered storage
VolumeTierCopyDatToRemote(ctx context.Context, in *VolumeTierCopyDatToRemoteRequest, opts ...grpc.CallOption) (VolumeServer_VolumeTierCopyDatToRemoteClient, error) VolumeTierCopyDatToRemote(ctx context.Context, in *VolumeTierCopyDatToRemoteRequest, opts ...grpc.CallOption) (VolumeServer_VolumeTierCopyDatToRemoteClient, error)
// query // query
@ -2337,6 +2390,15 @@ func (c *volumeServerClient) VolumeEcBlobDelete(ctx context.Context, in *VolumeE
return out, nil return out, nil
} }
func (c *volumeServerClient) VolumeEcShardsToVolume(ctx context.Context, in *VolumeEcShardsToVolumeRequest, opts ...grpc.CallOption) (*VolumeEcShardsToVolumeResponse, error) {
out := new(VolumeEcShardsToVolumeResponse)
err := grpc.Invoke(ctx, "/volume_server_pb.VolumeServer/VolumeEcShardsToVolume", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *volumeServerClient) VolumeTierCopyDatToRemote(ctx context.Context, in *VolumeTierCopyDatToRemoteRequest, opts ...grpc.CallOption) (VolumeServer_VolumeTierCopyDatToRemoteClient, error) { func (c *volumeServerClient) VolumeTierCopyDatToRemote(ctx context.Context, in *VolumeTierCopyDatToRemoteRequest, opts ...grpc.CallOption) (VolumeServer_VolumeTierCopyDatToRemoteClient, 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/VolumeTierCopyDatToRemote", opts...)
if err != nil { if err != nil {
@ -2433,6 +2495,7 @@ type VolumeServerServer interface {
VolumeEcShardsUnmount(context.Context, *VolumeEcShardsUnmountRequest) (*VolumeEcShardsUnmountResponse, error) VolumeEcShardsUnmount(context.Context, *VolumeEcShardsUnmountRequest) (*VolumeEcShardsUnmountResponse, error)
VolumeEcShardRead(*VolumeEcShardReadRequest, VolumeServer_VolumeEcShardReadServer) error VolumeEcShardRead(*VolumeEcShardReadRequest, VolumeServer_VolumeEcShardReadServer) error
VolumeEcBlobDelete(context.Context, *VolumeEcBlobDeleteRequest) (*VolumeEcBlobDeleteResponse, error) VolumeEcBlobDelete(context.Context, *VolumeEcBlobDeleteRequest) (*VolumeEcBlobDeleteResponse, error)
VolumeEcShardsToVolume(context.Context, *VolumeEcShardsToVolumeRequest) (*VolumeEcShardsToVolumeResponse, error)
// tiered storage // tiered storage
VolumeTierCopyDatToRemote(*VolumeTierCopyDatToRemoteRequest, VolumeServer_VolumeTierCopyDatToRemoteServer) error VolumeTierCopyDatToRemote(*VolumeTierCopyDatToRemoteRequest, VolumeServer_VolumeTierCopyDatToRemoteServer) error
// query // query
@ -2923,6 +2986,24 @@ func _VolumeServer_VolumeEcBlobDelete_Handler(srv interface{}, ctx context.Conte
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _VolumeServer_VolumeEcShardsToVolume_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(VolumeEcShardsToVolumeRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(VolumeServerServer).VolumeEcShardsToVolume(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/volume_server_pb.VolumeServer/VolumeEcShardsToVolume",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(VolumeServerServer).VolumeEcShardsToVolume(ctx, req.(*VolumeEcShardsToVolumeRequest))
}
return interceptor(ctx, in, info, handler)
}
func _VolumeServer_VolumeTierCopyDatToRemote_Handler(srv interface{}, stream grpc.ServerStream) error { func _VolumeServer_VolumeTierCopyDatToRemote_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(VolumeTierCopyDatToRemoteRequest) m := new(VolumeTierCopyDatToRemoteRequest)
if err := stream.RecvMsg(m); err != nil { if err := stream.RecvMsg(m); err != nil {
@ -3057,6 +3138,10 @@ var _VolumeServer_serviceDesc = grpc.ServiceDesc{
MethodName: "VolumeEcBlobDelete", MethodName: "VolumeEcBlobDelete",
Handler: _VolumeServer_VolumeEcBlobDelete_Handler, Handler: _VolumeServer_VolumeEcBlobDelete_Handler,
}, },
{
MethodName: "VolumeEcShardsToVolume",
Handler: _VolumeServer_VolumeEcShardsToVolume_Handler,
},
}, },
Streams: []grpc.StreamDesc{ Streams: []grpc.StreamDesc{
{ {
@ -3096,176 +3181,181 @@ 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{
// 2735 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xd4, 0x3a, 0xcd, 0x73, 0x1c, 0x47,
0xf5, 0x5a, 0xaf, 0x64, 0xed, 0xbe, 0x5d, 0x59, 0x72, 0x4b, 0x91, 0x37, 0x23, 0x4b, 0x56, 0x26,
0x5f, 0x92, 0x13, 0xcb, 0x8e, 0xf2, 0xfb, 0x91, 0x90, 0x10, 0xc0, 0x96, 0x6c, 0x30, 0x89, 0xe5,
0x64, 0xe4, 0x98, 0x40, 0x52, 0x4c, 0xb5, 0x66, 0x5a, 0xd6, 0xa0, 0x99, 0xe9, 0xf1, 0x4c, 0xaf,
0xe2, 0x75, 0xc1, 0x29, 0x1c, 0xb8, 0xf0, 0x07, 0x70, 0xe6, 0xce, 0x89, 0x2a, 0xaa, 0xb8, 0x72,
0xc9, 0x1f, 0x00, 0x57, 0x2e, 0x9c, 0x39, 0x70, 0xa3, 0x8a, 0x0b, 0xd5, 0x5f, 0xb3, 0xf3, 0xa9,
0x1d, 0xc5, 0xae, 0xa2, 0xb8, 0xf5, 0xbc, 0x7e, 0x1f, 0xfd, 0x5e, 0xbf, 0xf7, 0xfa, 0x75, 0xbf,
0x81, 0xc5, 0x13, 0xea, 0x0f, 0x03, 0x62, 0x27, 0x24, 0x3e, 0x21, 0xf1, 0x56, 0x14, 0x53, 0x46,
0xd1, 0x42, 0x0e, 0x68, 0x47, 0x07, 0xe6, 0x75, 0x40, 0xb7, 0x30, 0x73, 0x8e, 0x76, 0x89, 0x4f,
0x18, 0xb1, 0xc8, 0xe3, 0x21, 0x49, 0x18, 0x7a, 0x11, 0x3a, 0x87, 0x9e, 0x4f, 0x6c, 0xcf, 0x4d,
0x06, 0xad, 0xf5, 0xf6, 0x46, 0xd7, 0x9a, 0xe5, 0xdf, 0x77, 0xdd, 0xc4, 0xbc, 0x0f, 0x8b, 0x39,
0x82, 0x24, 0xa2, 0x61, 0x42, 0xd0, 0xbb, 0x30, 0x1b, 0x93, 0x64, 0xe8, 0x33, 0x49, 0xd0, 0xdb,
0x5e, 0xdb, 0x2a, 0xca, 0xda, 0x4a, 0x49, 0x86, 0x3e, 0xb3, 0x34, 0xba, 0xf9, 0x55, 0x0b, 0xfa,
0xd9, 0x19, 0x74, 0x09, 0x66, 0x95, 0xf0, 0x41, 0x6b, 0xbd, 0xb5, 0xd1, 0xb5, 0xce, 0x4b, 0xd9,
0x68, 0x19, 0xce, 0x27, 0x0c, 0xb3, 0x61, 0x32, 0x38, 0xb7, 0xde, 0xda, 0x98, 0xb1, 0xd4, 0x17,
0x5a, 0x82, 0x19, 0x12, 0xc7, 0x34, 0x1e, 0xb4, 0x05, 0xba, 0xfc, 0x40, 0x08, 0xa6, 0x13, 0xef,
0x29, 0x19, 0x4c, 0xaf, 0xb7, 0x36, 0xe6, 0x2c, 0x31, 0x46, 0x03, 0x98, 0x3d, 0x21, 0x71, 0xe2,
0xd1, 0x70, 0x30, 0x23, 0xc0, 0xfa, 0xd3, 0x9c, 0x85, 0x99, 0xdb, 0x41, 0xc4, 0x46, 0xe6, 0x3b,
0x30, 0x78, 0x88, 0x9d, 0xe1, 0x30, 0x78, 0x28, 0x96, 0xbf, 0x73, 0x44, 0x9c, 0x63, 0x6d, 0x96,
0x15, 0xe8, 0x2a, 0xa5, 0xd4, 0xda, 0xe6, 0xac, 0x8e, 0x04, 0xdc, 0x75, 0xcd, 0xef, 0xc3, 0x8b,
0x15, 0x84, 0xca, 0x3c, 0x2f, 0xc3, 0xdc, 0x23, 0x1c, 0x1f, 0xe0, 0x47, 0xc4, 0x8e, 0x31, 0xf3,
0xa8, 0xa0, 0x6e, 0x59, 0x7d, 0x05, 0xb4, 0x38, 0xcc, 0xfc, 0x1c, 0x8c, 0x1c, 0x07, 0x1a, 0x44,
0xd8, 0x61, 0x4d, 0x84, 0xa3, 0x75, 0xe8, 0x45, 0x31, 0xc1, 0xbe, 0x4f, 0x1d, 0xcc, 0x88, 0xb0,
0x4f, 0xdb, 0xca, 0x82, 0xcc, 0x55, 0x58, 0xa9, 0x64, 0x2e, 0x17, 0x68, 0xbe, 0x5b, 0x58, 0x3d,
0x0d, 0x02, 0xaf, 0x91, 0x68, 0xf3, 0x72, 0x69, 0xd5, 0x82, 0x52, 0xf1, 0xfd, 0x76, 0x61, 0xd6,
0x27, 0x38, 0x1c, 0x46, 0x8d, 0x18, 0x17, 0x57, 0xac, 0x49, 0x53, 0xce, 0x97, 0xa4, 0xdb, 0xec,
0x50, 0xdf, 0x27, 0x0e, 0xf3, 0x68, 0xa8, 0xd9, 0xae, 0x01, 0x38, 0x29, 0x50, 0x39, 0x51, 0x06,
0x62, 0x1a, 0x30, 0x28, 0x93, 0x2a, 0xb6, 0x7f, 0x6b, 0xc1, 0x0b, 0x37, 0x95, 0xd1, 0xa4, 0xe0,
0x46, 0x1b, 0x90, 0x17, 0x79, 0xae, 0x28, 0xb2, 0xb8, 0x41, 0xed, 0xd2, 0x06, 0x71, 0x8c, 0x98,
0x44, 0xbe, 0xe7, 0x60, 0xc1, 0x62, 0x5a, 0xb0, 0xc8, 0x82, 0xd0, 0x02, 0xb4, 0x19, 0xf3, 0x85,
0xe7, 0x76, 0x2d, 0x3e, 0x44, 0xdb, 0xb0, 0x1c, 0x90, 0x80, 0xc6, 0x23, 0x3b, 0xc0, 0x91, 0x1d,
0xe0, 0x27, 0x36, 0x77, 0x73, 0x3b, 0x38, 0x18, 0x9c, 0x17, 0xeb, 0x43, 0x72, 0xf6, 0x1e, 0x8e,
0xee, 0xe1, 0x27, 0xfb, 0xde, 0x53, 0x72, 0xef, 0xc0, 0x1c, 0xc0, 0x72, 0x51, 0x3f, 0xa5, 0xfa,
0xb7, 0xe0, 0x92, 0x84, 0xec, 0x8f, 0x42, 0x67, 0x5f, 0xc4, 0x56, 0xa3, 0x8d, 0xfa, 0x77, 0x0b,
0x06, 0x65, 0x42, 0xe5, 0xf9, 0xcf, 0x6a, 0xb5, 0x33, 0xdb, 0xe4, 0x0a, 0xf4, 0x18, 0xf6, 0x7c,
0x9b, 0x1e, 0x1e, 0x26, 0x84, 0x09, 0x43, 0x4c, 0x5b, 0xc0, 0x41, 0xf7, 0x05, 0x04, 0x6d, 0xc2,
0x82, 0x23, 0xbd, 0xdf, 0x8e, 0xc9, 0x89, 0x27, 0xb2, 0xc1, 0xac, 0x58, 0xd8, 0xbc, 0xa3, 0xa3,
0x42, 0x82, 0x91, 0x09, 0x73, 0x9e, 0xfb, 0xc4, 0x16, 0xe9, 0x48, 0x24, 0x93, 0x8e, 0xe0, 0xd6,
0xf3, 0xdc, 0x27, 0x77, 0x3c, 0x9f, 0x70, 0x8b, 0x9a, 0x0f, 0xe1, 0xb2, 0x54, 0xfe, 0x6e, 0xe8,
0xc4, 0x24, 0x20, 0x21, 0xc3, 0xfe, 0x0e, 0x8d, 0x46, 0x8d, 0xdc, 0xe6, 0x45, 0xe8, 0x24, 0x5e,
0xe8, 0x10, 0x3b, 0x94, 0x49, 0x6d, 0xda, 0x9a, 0x15, 0xdf, 0x7b, 0x89, 0x79, 0x0b, 0x56, 0x6b,
0xf8, 0x2a, 0xcb, 0xbe, 0x04, 0x7d, 0xb1, 0x30, 0x87, 0x86, 0x8c, 0x84, 0x4c, 0xf0, 0xee, 0x5b,
0x3d, 0x0e, 0xdb, 0x91, 0x20, 0xf3, 0x2d, 0x40, 0x92, 0xc7, 0x3d, 0x3a, 0x0c, 0x9b, 0x85, 0xf3,
0x0b, 0xb0, 0x98, 0x23, 0x51, 0xbe, 0xf1, 0x36, 0x2c, 0x49, 0xf0, 0xa7, 0x61, 0xd0, 0x98, 0xd7,
0x25, 0x78, 0xa1, 0x40, 0xa4, 0xb8, 0x6d, 0x6b, 0x21, 0xf9, 0x63, 0xe7, 0x54, 0x66, 0xcb, 0x7a,
0x05, 0xf9, 0x93, 0x47, 0x64, 0x2e, 0xb9, 0x60, 0x1c, 0x1f, 0x5b, 0x04, 0xbb, 0x34, 0xf4, 0x47,
0x8d, 0x33, 0x57, 0x05, 0xa5, 0xe2, 0xfb, 0xfb, 0x16, 0x5c, 0xd4, 0x29, 0xad, 0xe1, 0x6e, 0x9e,
0xd1, 0x9d, 0xdb, 0xb5, 0xee, 0x3c, 0x3d, 0x76, 0xe7, 0x0d, 0x58, 0x48, 0xe8, 0x30, 0x76, 0x88,
0xed, 0x62, 0x86, 0xed, 0x90, 0xba, 0x44, 0x79, 0xfb, 0x05, 0x09, 0xdf, 0xc5, 0x0c, 0xef, 0x51,
0x97, 0x98, 0xdf, 0xd3, 0x9b, 0x9d, 0xf3, 0x92, 0x4d, 0xb8, 0xe8, 0xe3, 0x84, 0xd9, 0x38, 0x8a,
0x48, 0xe8, 0xda, 0x98, 0x71, 0x57, 0x6b, 0x09, 0x57, 0xbb, 0xc0, 0x27, 0x6e, 0x0a, 0xf8, 0x4d,
0xb6, 0x97, 0x98, 0x7f, 0x69, 0xc1, 0x3c, 0xa7, 0xe5, 0xae, 0xdd, 0x48, 0xdf, 0x05, 0x68, 0x93,
0x27, 0x4c, 0x29, 0xca, 0x87, 0xe8, 0x3a, 0x2c, 0xaa, 0x18, 0xf2, 0x68, 0x38, 0x0e, 0xaf, 0xb6,
0xcc, 0x46, 0xe3, 0xa9, 0x34, 0xc2, 0xae, 0x40, 0x2f, 0x61, 0x34, 0xd2, 0xd1, 0x3a, 0x2d, 0xa3,
0x95, 0x83, 0x54, 0xb4, 0xe6, 0x6d, 0x3a, 0x53, 0x61, 0xd3, 0xbe, 0x97, 0xd8, 0xc4, 0xb1, 0xe5,
0xaa, 0x44, 0xbc, 0x77, 0x2c, 0xf0, 0x92, 0xdb, 0x8e, 0xb4, 0x86, 0xf9, 0xff, 0xb0, 0x30, 0xd6,
0xaa, 0x79, 0xec, 0x7c, 0xd5, 0xd2, 0xe9, 0xf0, 0x01, 0xf6, 0xfc, 0x7d, 0x12, 0xba, 0x24, 0x7e,
0xc6, 0x98, 0x46, 0x37, 0x60, 0xc9, 0x73, 0x7d, 0x62, 0x33, 0x2f, 0x20, 0x74, 0xc8, 0xec, 0x84,
0x38, 0x34, 0x74, 0x13, 0x6d, 0x1f, 0x3e, 0xf7, 0x40, 0x4e, 0xed, 0xcb, 0x19, 0xf3, 0x57, 0x69,
0x6e, 0xcd, 0xae, 0x62, 0x5c, 0x55, 0x84, 0x84, 0x70, 0x86, 0x47, 0x04, 0xbb, 0x24, 0x56, 0x6a,
0xf4, 0x25, 0xf0, 0x87, 0x02, 0xc6, 0x2d, 0xac, 0x90, 0x0e, 0xa8, 0x3b, 0x12, 0x2b, 0xea, 0x5b,
0x20, 0x41, 0xb7, 0xa8, 0x3b, 0x12, 0x49, 0x2e, 0xb1, 0x85, 0x93, 0x38, 0x47, 0xc3, 0xf0, 0x58,
0xac, 0xa6, 0x63, 0xf5, 0xbc, 0xe4, 0x23, 0x9c, 0xb0, 0x1d, 0x0e, 0x32, 0xff, 0xd8, 0xd2, 0x51,
0xc6, 0x97, 0x61, 0x11, 0x87, 0x78, 0x27, 0xff, 0x05, 0x73, 0x70, 0x0a, 0x15, 0x0d, 0xb9, 0xea,
0x52, 0x05, 0x0c, 0x92, 0x73, 0xea, 0x2c, 0x12, 0x33, 0xe3, 0x20, 0xcf, 0x2f, 0x5c, 0x05, 0xf9,
0x17, 0x3a, 0xc9, 0xde, 0x76, 0xf6, 0x8f, 0x70, 0xec, 0x26, 0x3f, 0x20, 0x21, 0x89, 0x31, 0x7b,
0x2e, 0x87, 0xbe, 0xb9, 0x0e, 0x6b, 0x75, 0xdc, 0x95, 0xfc, 0xcf, 0xf5, 0xe1, 0xa1, 0x31, 0x2c,
0x72, 0x30, 0xf4, 0x7c, 0xf7, 0xb9, 0x88, 0xff, 0xb0, 0xa8, 0x5c, 0xca, 0x5c, 0xf9, 0xcf, 0x55,
0xb8, 0x18, 0x0b, 0x10, 0xb3, 0x13, 0x8e, 0x90, 0xd6, 0xfb, 0x73, 0xd6, 0xbc, 0x9a, 0x10, 0x84,
0xbc, 0xee, 0xff, 0x73, 0xea, 0x01, 0x9a, 0xdb, 0x73, 0x4b, 0x8b, 0x2b, 0xd0, 0x1d, 0x8b, 0x6f,
0x0b, 0xf1, 0x9d, 0x44, 0xc9, 0xe5, 0xde, 0xe9, 0xd0, 0x68, 0x64, 0x13, 0x47, 0x9e, 0xc3, 0x62,
0xab, 0x3b, 0x56, 0x8f, 0x03, 0x6f, 0x3b, 0xe2, 0x18, 0x3e, 0x43, 0x8e, 0x4c, 0xbd, 0x21, 0xaf,
0x84, 0xda, 0x8d, 0x2f, 0x61, 0x25, 0x3f, 0xdb, 0xfc, 0x78, 0x7a, 0x26, 0x25, 0xcd, 0xb5, 0xa2,
0x1b, 0x14, 0xce, 0xb8, 0x93, 0xe2, 0xb2, 0x1b, 0x9f, 0xe7, 0xcf, 0xb6, 0xae, 0xd5, 0xa2, 0x41,
0xf2, 0x45, 0xc1, 0x67, 0xc5, 0x65, 0x9f, 0xa1, 0x38, 0x38, 0x5d, 0xf0, 0x95, 0xa2, 0xeb, 0x16,
0x2b, 0x88, 0xdf, 0xa6, 0x79, 0x51, 0x61, 0xf0, 0xf3, 0xbb, 0x71, 0x3e, 0x52, 0x72, 0x85, 0x39,
0xe6, 0xac, 0x59, 0x25, 0x96, 0x5f, 0x30, 0xd5, 0x39, 0x24, 0xeb, 0x73, 0xf5, 0x95, 0xbb, 0x4a,
0xb6, 0xd5, 0x55, 0x52, 0x5f, 0x91, 0x8f, 0xc9, 0x48, 0xf8, 0xda, 0xb4, 0xbc, 0x22, 0x7f, 0x48,
0x46, 0xe6, 0x5e, 0x21, 0x52, 0xe4, 0xd2, 0x54, 0xcc, 0x21, 0x98, 0xe6, 0x4e, 0xaa, 0x52, 0xb5,
0x18, 0xa3, 0x55, 0x00, 0x2f, 0xb1, 0x5d, 0xb1, 0xe7, 0x72, 0x51, 0x1d, 0xab, 0xeb, 0x29, 0x27,
0x70, 0xcd, 0xdf, 0x64, 0x42, 0xef, 0x96, 0x4f, 0x0f, 0x9e, 0xa3, 0x57, 0x66, 0xb5, 0x68, 0xe7,
0xb4, 0xc8, 0xde, 0x95, 0xa7, 0xf3, 0x77, 0xe5, 0x4c, 0x10, 0x65, 0x97, 0xa3, 0x76, 0xe6, 0x3d,
0x58, 0xe1, 0x0a, 0x4b, 0x0c, 0x51, 0x25, 0x37, 0xbf, 0x49, 0xfc, 0xe3, 0x1c, 0x5c, 0xae, 0x26,
0x6e, 0x72, 0x9b, 0x78, 0x1f, 0x8c, 0xb4, 0x5a, 0xe7, 0x47, 0x4a, 0xc2, 0x70, 0x10, 0xa5, 0x87,
0x8a, 0x3c, 0x7b, 0x2e, 0xa9, 0xd2, 0xfd, 0x81, 0x9e, 0xd7, 0x27, 0x4b, 0xa9, 0xd4, 0x6f, 0x97,
0x4a, 0x7d, 0x2e, 0xc0, 0xc5, 0xac, 0x4e, 0x80, 0xac, 0x5d, 0x2e, 0xb9, 0x98, 0xd5, 0x09, 0x48,
0x89, 0x85, 0x00, 0xe9, 0x35, 0x3d, 0x85, 0x2f, 0x04, 0xac, 0x02, 0xa8, 0xb2, 0x64, 0x18, 0xea,
0xab, 0x4b, 0x57, 0x16, 0x25, 0xc3, 0xb0, 0xb6, 0xba, 0x9a, 0xad, 0xad, 0xae, 0xf2, 0xdb, 0xdf,
0x29, 0x9d, 0x10, 0x9f, 0x01, 0xec, 0x7a, 0xc9, 0xb1, 0x34, 0x32, 0x2f, 0xe7, 0x5c, 0x2f, 0x56,
0xf7, 0x65, 0x3e, 0xe4, 0x10, 0xec, 0xfb, 0xca, 0x74, 0x7c, 0xc8, 0xdd, 0x77, 0x98, 0x10, 0x57,
0x59, 0x47, 0x8c, 0x39, 0xec, 0x30, 0x26, 0x44, 0x19, 0x40, 0x8c, 0xcd, 0xdf, 0xb5, 0xa0, 0x7b,
0x8f, 0x04, 0x8a, 0xf3, 0x1a, 0xc0, 0x23, 0x1a, 0xd3, 0x21, 0xf3, 0x42, 0x22, 0xab, 0xcf, 0x19,
0x2b, 0x03, 0xf9, 0xe6, 0x72, 0x44, 0x68, 0x12, 0xff, 0x50, 0x19, 0x53, 0x8c, 0x39, 0xec, 0x88,
0xe0, 0x48, 0xd9, 0x4f, 0x8c, 0xd1, 0x12, 0xcc, 0x24, 0x0c, 0x3b, 0xc7, 0xc2, 0x58, 0xd3, 0x96,
0xfc, 0x30, 0xff, 0xd4, 0x02, 0xb0, 0x48, 0x40, 0x99, 0xf0, 0x35, 0x5e, 0x15, 0x1e, 0x60, 0xe7,
0x98, 0xd7, 0xc9, 0x6c, 0x14, 0x11, 0x65, 0x89, 0x9e, 0x82, 0x3d, 0x18, 0x45, 0x62, 0x87, 0x34,
0x8a, 0xca, 0x1f, 0x5d, 0xab, 0xab, 0x20, 0xb2, 0x22, 0xd6, 0xa1, 0xd4, 0xb5, 0xf8, 0x30, 0x93,
0x53, 0xe4, 0xb2, 0x75, 0x4e, 0x59, 0x81, 0x6e, 0xd1, 0x15, 0x44, 0x28, 0x0a, 0x3f, 0x78, 0x19,
0xe6, 0x02, 0xea, 0x7a, 0x87, 0x1e, 0x71, 0x85, 0xa3, 0x29, 0x55, 0xfa, 0x1a, 0xc8, 0x9d, 0xcb,
0xdc, 0x85, 0x0b, 0xaa, 0xb2, 0xf1, 0x48, 0x7c, 0x37, 0x3c, 0xa4, 0x68, 0x1b, 0x66, 0x38, 0x0b,
0xfd, 0x04, 0x77, 0xb9, 0xfc, 0x04, 0x37, 0x56, 0xd6, 0x92, 0xa8, 0xe6, 0xd7, 0x2d, 0x58, 0x1f,
0xb3, 0xe1, 0xc7, 0xe1, 0x2e, 0x66, 0x0f, 0xa8, 0x44, 0x7c, 0x2e, 0x39, 0xe6, 0x5d, 0x18, 0xb8,
0x24, 0x61, 0x5e, 0x28, 0xae, 0x38, 0xb6, 0x36, 0x5f, 0x88, 0x03, 0xa2, 0x0c, 0xb5, 0x9c, 0x99,
0xbf, 0x25, 0xa7, 0xf7, 0x70, 0x40, 0xd0, 0x35, 0x58, 0x3c, 0x26, 0x24, 0xb2, 0x7d, 0xea, 0x60,
0xdf, 0xd6, 0xd1, 0xa3, 0x2a, 0x80, 0x05, 0x3e, 0xf5, 0x11, 0x9f, 0xd9, 0x95, 0x11, 0x64, 0x26,
0xf0, 0xd2, 0x29, 0x9a, 0xa8, 0x0c, 0x72, 0x19, 0xba, 0x51, 0x4c, 0x1d, 0x92, 0x70, 0xef, 0x6a,
0x89, 0x84, 0x3e, 0x06, 0xa0, 0x1b, 0xb0, 0x98, 0x7e, 0x7c, 0x4c, 0x62, 0x87, 0xdf, 0xba, 0x1f,
0xc9, 0xf7, 0xb4, 0x73, 0x56, 0xd5, 0x94, 0xf9, 0xaf, 0x3e, 0xf4, 0x3f, 0x19, 0x92, 0x78, 0x94,
0x79, 0x7c, 0x4a, 0x88, 0xd2, 0x5d, 0xbf, 0x9e, 0x66, 0x20, 0x3c, 0x0f, 0x1c, 0xc6, 0x34, 0xb0,
0xd3, 0x07, 0xd6, 0x73, 0x02, 0xa5, 0xc7, 0x81, 0x77, 0xe4, 0x23, 0x2b, 0xfa, 0x00, 0xce, 0x1f,
0x7a, 0x3e, 0x23, 0xf2, 0x49, 0xb3, 0xb7, 0xfd, 0x6a, 0x79, 0x27, 0xb3, 0x32, 0xb7, 0xee, 0x08,
0x64, 0x4b, 0x11, 0xa1, 0x03, 0x58, 0xf4, 0xc2, 0x48, 0x14, 0xd4, 0xb1, 0x87, 0x7d, 0xef, 0xe9,
0xf8, 0xf9, 0xa4, 0xb7, 0xfd, 0xd6, 0x04, 0x5e, 0x77, 0x39, 0xe5, 0x7e, 0x96, 0xd0, 0x42, 0x5e,
0x09, 0x86, 0x08, 0x2c, 0xd1, 0x21, 0x2b, 0x0b, 0x99, 0x11, 0x42, 0xb6, 0x27, 0x08, 0xb9, 0x2f,
0x48, 0xf3, 0x52, 0x16, 0x69, 0x19, 0x68, 0xec, 0xc1, 0x79, 0xa9, 0x1c, 0x8f, 0xe0, 0x43, 0x8f,
0xf8, 0xfa, 0x51, 0x58, 0x7e, 0xf0, 0x53, 0x8a, 0x46, 0x24, 0xc6, 0xa1, 0x0e, 0x46, 0xfd, 0xc9,
0xf1, 0x4f, 0xb0, 0x3f, 0xd4, 0x3e, 0x26, 0x3f, 0x8c, 0xbf, 0xce, 0x00, 0x2a, 0x6b, 0xa8, 0xdf,
0x84, 0x62, 0x92, 0xf0, 0xbc, 0x99, 0x8d, 0xfe, 0xf9, 0x0c, 0x5c, 0x64, 0x80, 0x1f, 0x43, 0xd7,
0x49, 0x4e, 0x6c, 0x61, 0x12, 0x21, 0xb3, 0xb7, 0xfd, 0xde, 0x99, 0x4d, 0xba, 0xb5, 0xb3, 0xff,
0x50, 0x40, 0xad, 0x8e, 0x93, 0x9c, 0x88, 0x11, 0xfa, 0x29, 0xc0, 0xcf, 0x13, 0x1a, 0x2a, 0xce,
0x72, 0xe3, 0xdf, 0x3f, 0x3b, 0xe7, 0x1f, 0xed, 0xdf, 0xdf, 0x93, 0xac, 0xbb, 0x9c, 0x9d, 0xe4,
0xed, 0xc0, 0x5c, 0x84, 0xe3, 0xc7, 0x43, 0xc2, 0x14, 0x7b, 0xe9, 0x0b, 0xdf, 0x3d, 0x3b, 0xfb,
0x8f, 0x25, 0x1b, 0x29, 0xa1, 0x1f, 0x65, 0xbe, 0x8c, 0xaf, 0xcf, 0x41, 0x47, 0xeb, 0xc5, 0x6b,
0x72, 0xe1, 0xe1, 0xf2, 0x66, 0x6a, 0x7b, 0xe1, 0x21, 0x55, 0x16, 0xbd, 0xc0, 0xe1, 0xf2, 0x72,
0x2a, 0xb2, 0xd6, 0x26, 0x2c, 0xc4, 0xc4, 0xa1, 0xb1, 0xcb, 0x2b, 0x20, 0x2f, 0xf0, 0xb8, 0xdb,
0xcb, 0xbd, 0x9c, 0x97, 0xf0, 0x5d, 0x0d, 0x46, 0xaf, 0xc3, 0xbc, 0xd8, 0xf6, 0x0c, 0x66, 0x5b,
0xf3, 0x24, 0x7e, 0x06, 0x71, 0x13, 0x16, 0x1e, 0x0f, 0x29, 0x23, 0xb6, 0x73, 0x84, 0x63, 0xec,
0x30, 0x9a, 0xde, 0x11, 0xe7, 0x05, 0x7c, 0x27, 0x05, 0xa3, 0xff, 0x83, 0x65, 0x89, 0x4a, 0x12,
0x07, 0x47, 0x29, 0x05, 0x89, 0xd5, 0x15, 0x62, 0x49, 0xcc, 0xde, 0x16, 0x93, 0x3b, 0x7a, 0x0e,
0x19, 0xd0, 0x71, 0x68, 0x10, 0x90, 0x90, 0x25, 0x22, 0x39, 0x77, 0xad, 0xf4, 0x1b, 0xdd, 0x84,
0x55, 0xec, 0xfb, 0xf4, 0x4b, 0x5b, 0x50, 0xba, 0x76, 0x49, 0xbb, 0x59, 0x91, 0xc0, 0x0c, 0x81,
0xf4, 0x89, 0xc0, 0xb1, 0xf2, 0x8a, 0x1a, 0x57, 0xa0, 0x9b, 0xee, 0x23, 0x3f, 0xcf, 0x32, 0x0e,
0x29, 0xc6, 0xc6, 0x05, 0xe8, 0x67, 0x77, 0xc2, 0xf8, 0x67, 0x1b, 0x16, 0x2b, 0x82, 0x0a, 0x7d,
0x0e, 0xc0, 0xbd, 0x55, 0x86, 0x96, 0x72, 0xd7, 0xef, 0x9c, 0x3d, 0x38, 0xb9, 0xbf, 0x4a, 0xb0,
0xc5, 0xbd, 0x5f, 0x0e, 0xd1, 0xcf, 0xa0, 0x27, 0x3c, 0x56, 0x71, 0x97, 0x2e, 0xfb, 0xc1, 0x37,
0xe0, 0xce, 0x75, 0x55, 0xec, 0x45, 0x0c, 0xc8, 0xb1, 0xf1, 0xf7, 0x16, 0x74, 0x53, 0xc1, 0xfc,
0x74, 0x96, 0x1b, 0x25, 0xf6, 0x3a, 0xd1, 0xa7, 0xb3, 0x80, 0xdd, 0x11, 0xa0, 0xff, 0x49, 0x57,
0x32, 0xde, 0x01, 0x18, 0xeb, 0x5f, 0xa9, 0x42, 0xab, 0x52, 0x05, 0x73, 0x13, 0xe6, 0xb8, 0x65,
0x3d, 0xe2, 0xee, 0xb3, 0xd8, 0x8b, 0x44, 0x7b, 0x4b, 0xe2, 0x24, 0xea, 0x7a, 0xa1, 0x3f, 0xb7,
0xff, 0x30, 0x80, 0x7e, 0xf6, 0x59, 0x04, 0x7d, 0x01, 0xbd, 0x4c, 0x1b, 0x0f, 0xbd, 0x52, 0xde,
0xb4, 0x72, 0x5b, 0xd0, 0x78, 0x75, 0x02, 0x96, 0xba, 0x01, 0x4c, 0xa1, 0x10, 0x2e, 0x96, 0x7a,
0x61, 0xe8, 0x6a, 0x99, 0xba, 0xae, 0xd3, 0x66, 0xbc, 0xd1, 0x08, 0x37, 0x95, 0xc7, 0x60, 0xb1,
0xa2, 0xb9, 0x85, 0xde, 0x9c, 0xc0, 0x25, 0xd7, 0x60, 0x33, 0xae, 0x35, 0xc4, 0x4e, 0xa5, 0x3e,
0x06, 0x54, 0xee, 0x7c, 0xa1, 0x37, 0x26, 0xb2, 0x19, 0x77, 0xd6, 0x8c, 0x37, 0x9b, 0x21, 0xd7,
0x2a, 0x2a, 0x7b, 0x62, 0x13, 0x15, 0xcd, 0x75, 0xdd, 0x26, 0x2a, 0x5a, 0x68, 0xb4, 0x4d, 0xa1,
0x63, 0x58, 0x28, 0xf6, 0xcb, 0xd0, 0x66, 0x5d, 0x7f, 0xb7, 0xd4, 0x8e, 0x33, 0xae, 0x36, 0x41,
0x4d, 0x85, 0x11, 0xb8, 0x90, 0xef, 0x4f, 0xa1, 0xd7, 0xcb, 0xf4, 0x95, 0x1d, 0x3a, 0x63, 0x63,
0x32, 0x62, 0x56, 0xa7, 0x62, 0xcf, 0xaa, 0x4a, 0xa7, 0x9a, 0x86, 0x58, 0x95, 0x4e, 0x75, 0x2d,
0x30, 0x73, 0x0a, 0xfd, 0x42, 0x37, 0x42, 0x0a, 0xbd, 0x1c, 0xb4, 0x55, 0xc7, 0xa6, 0xba, 0x99,
0x64, 0x5c, 0x6f, 0x8c, 0xaf, 0x65, 0xdf, 0x68, 0xf1, 0x58, 0xcf, 0xb4, 0x74, 0xaa, 0x62, 0xbd,
0xdc, 0x24, 0xaa, 0x8a, 0xf5, 0xaa, 0xbe, 0xd0, 0x14, 0x3a, 0x80, 0xb9, 0x5c, 0x93, 0x07, 0xbd,
0x56, 0x47, 0x99, 0x7f, 0x1d, 0x32, 0x5e, 0x9f, 0x88, 0x97, 0xca, 0xb0, 0x75, 0xf6, 0x52, 0xe9,
0xaa, 0x76, 0x71, 0xf9, 0x7c, 0xf5, 0xda, 0x24, 0xb4, 0x5c, 0x28, 0x97, 0x5a, 0x41, 0x95, 0xa1,
0x5c, 0xd7, 0x6a, 0xaa, 0x0c, 0xe5, 0xfa, 0xee, 0xd2, 0x14, 0xfa, 0x09, 0xc0, 0xb8, 0x5d, 0x83,
0x5e, 0xae, 0xa3, 0xce, 0xee, 0xfe, 0x2b, 0xa7, 0x23, 0xa5, 0xac, 0xbf, 0x84, 0xa5, 0xaa, 0x57,
0x14, 0x74, 0xad, 0xea, 0x42, 0x58, 0xfb, 0x54, 0x63, 0x6c, 0x35, 0x45, 0x4f, 0x05, 0x7f, 0x0a,
0x1d, 0xdd, 0x6a, 0x41, 0x2f, 0x95, 0xa9, 0x0b, 0xcd, 0x25, 0xc3, 0x3c, 0x0d, 0x25, 0xe3, 0xc0,
0x81, 0x8e, 0xd5, 0x71, 0x0f, 0xa4, 0x3e, 0x56, 0x4b, 0xdd, 0x9a, 0xfa, 0x58, 0x2d, 0xb7, 0x54,
0x84, 0xb8, 0xd4, 0x19, 0xb2, 0x2d, 0x83, 0x7a, 0x67, 0xa8, 0xe8, 0x88, 0xd4, 0x3b, 0x43, 0x65,
0x17, 0x62, 0x0a, 0xfd, 0x12, 0x96, 0xab, 0x3b, 0x05, 0xa8, 0x36, 0xe2, 0x6b, 0x3a, 0x16, 0xc6,
0x8d, 0xe6, 0x04, 0xa9, 0xf8, 0xa7, 0x3a, 0x3f, 0x15, 0x3a, 0x05, 0xf5, 0xf9, 0xa9, 0xba, 0x5f,
0x61, 0x5c, 0x6f, 0x8c, 0x5f, 0x0e, 0xbd, 0xec, 0x93, 0x7c, 0xbd, 0xb5, 0x2b, 0xba, 0x0f, 0xf5,
0xd6, 0xae, 0x7c, 0xe5, 0x17, 0xf1, 0x51, 0xf5, 0xdc, 0x5e, 0x15, 0x1f, 0xa7, 0xf4, 0x03, 0x8c,
0xad, 0xa6, 0xe8, 0xb9, 0xe3, 0xbb, 0xfc, 0x9e, 0x8e, 0x26, 0xae, 0x3f, 0x97, 0x99, 0xaf, 0x35,
0xc4, 0xae, 0xdf, 0x5d, 0x9d, 0xa9, 0x27, 0x2a, 0x50, 0xc8, 0xd8, 0xd7, 0x1b, 0xe3, 0xa7, 0xb2,
0x23, 0xdd, 0x44, 0xcf, 0xbc, 0x85, 0xa3, 0xab, 0x13, 0xf8, 0x64, 0xde, 0xf2, 0x8d, 0x37, 0x1a,
0xe1, 0x56, 0x45, 0x6f, 0xf6, 0x75, 0xfa, 0x34, 0x7f, 0x2a, 0x3d, 0xa9, 0x9f, 0xe6, 0x4f, 0x15,
0x0f, 0xde, 0x53, 0xe8, 0xd7, 0xe3, 0xee, 0x68, 0xf9, 0xe5, 0x09, 0x6d, 0xd7, 0xe6, 0x82, 0xda,
0x07, 0x37, 0xe3, 0xed, 0x33, 0xd1, 0x64, 0xb4, 0xff, 0x08, 0x66, 0xc4, 0x6d, 0x0b, 0xad, 0x9d,
0x7e, 0x0d, 0x33, 0xae, 0x54, 0xcf, 0xa7, 0x97, 0x09, 0xce, 0xed, 0xe0, 0xbc, 0xf8, 0x6d, 0xf0,
0xed, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0x8a, 0x85, 0xda, 0x2e, 0x4d, 0x28, 0x00, 0x00,
// 2811 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xd4, 0x3a, 0x4b, 0x73, 0xdc, 0xc6,
0xd1, 0x5c, 0x2e, 0x1f, 0xbb, 0xbd, 0x4b, 0x91, 0x1a, 0xd2, 0xd4, 0x0a, 0x7a, 0xd1, 0xf0, 0x4b,
0x92, 0x2d, 0x4a, 0xa6, 0xbf, 0x2f, 0x76, 0xec, 0xd8, 0x89, 0x44, 0x4a, 0x89, 0x62, 0x8b, 0xb2,
0x41, 0x59, 0x71, 0x62, 0x57, 0x50, 0x43, 0x60, 0x56, 0x84, 0x09, 0x60, 0x20, 0x60, 0x96, 0xd6,
0xaa, 0x92, 0x93, 0x73, 0xc8, 0x25, 0xb7, 0x5c, 0x72, 0xce, 0x3d, 0x97, 0x1c, 0x52, 0x95, 0x5f,
0xe0, 0x3f, 0x90, 0x6b, 0x2e, 0x39, 0xe4, 0x94, 0x43, 0x6e, 0xa9, 0xca, 0x25, 0x35, 0x2f, 0x2c,
0x9e, 0x5c, 0xd0, 0x52, 0x55, 0x2a, 0xb7, 0x41, 0x4f, 0x3f, 0xa6, 0x7b, 0xba, 0x7b, 0xa6, 0xa7,
0x01, 0xab, 0x47, 0xd4, 0x1f, 0x05, 0xc4, 0x4e, 0x48, 0x7c, 0x44, 0xe2, 0xcd, 0x28, 0xa6, 0x8c,
0xa2, 0x95, 0x1c, 0xd0, 0x8e, 0xf6, 0xcd, 0xeb, 0x80, 0x6e, 0x61, 0xe6, 0x1c, 0xec, 0x10, 0x9f,
0x30, 0x62, 0x91, 0xc7, 0x23, 0x92, 0x30, 0x74, 0x16, 0x3a, 0x43, 0xcf, 0x27, 0xb6, 0xe7, 0x26,
0x83, 0xd6, 0x46, 0xfb, 0x72, 0xd7, 0x5a, 0xe4, 0xdf, 0x77, 0xdd, 0xc4, 0xbc, 0x0f, 0xab, 0x39,
0x82, 0x24, 0xa2, 0x61, 0x42, 0xd0, 0x3b, 0xb0, 0x18, 0x93, 0x64, 0xe4, 0x33, 0x49, 0xd0, 0xdb,
0xba, 0xb8, 0x59, 0x94, 0xb5, 0x99, 0x92, 0x8c, 0x7c, 0x66, 0x69, 0x74, 0xf3, 0xeb, 0x16, 0xf4,
0xb3, 0x33, 0xe8, 0x0c, 0x2c, 0x2a, 0xe1, 0x83, 0xd6, 0x46, 0xeb, 0x72, 0xd7, 0x5a, 0x90, 0xb2,
0xd1, 0x3a, 0x2c, 0x24, 0x0c, 0xb3, 0x51, 0x32, 0x98, 0xdd, 0x68, 0x5d, 0x9e, 0xb7, 0xd4, 0x17,
0x5a, 0x83, 0x79, 0x12, 0xc7, 0x34, 0x1e, 0xb4, 0x05, 0xba, 0xfc, 0x40, 0x08, 0xe6, 0x12, 0xef,
0x29, 0x19, 0xcc, 0x6d, 0xb4, 0x2e, 0x2f, 0x59, 0x62, 0x8c, 0x06, 0xb0, 0x78, 0x44, 0xe2, 0xc4,
0xa3, 0xe1, 0x60, 0x5e, 0x80, 0xf5, 0xa7, 0xb9, 0x08, 0xf3, 0xb7, 0x83, 0x88, 0x8d, 0xcd, 0xb7,
0x61, 0xf0, 0x10, 0x3b, 0xa3, 0x51, 0xf0, 0x50, 0x2c, 0x7f, 0xfb, 0x80, 0x38, 0x87, 0xda, 0x2c,
0xe7, 0xa0, 0xab, 0x94, 0x52, 0x6b, 0x5b, 0xb2, 0x3a, 0x12, 0x70, 0xd7, 0x35, 0x7f, 0x00, 0x67,
0x2b, 0x08, 0x95, 0x79, 0x5e, 0x82, 0xa5, 0x47, 0x38, 0xde, 0xc7, 0x8f, 0x88, 0x1d, 0x63, 0xe6,
0x51, 0x41, 0xdd, 0xb2, 0xfa, 0x0a, 0x68, 0x71, 0x98, 0xf9, 0x39, 0x18, 0x39, 0x0e, 0x34, 0x88,
0xb0, 0xc3, 0x9a, 0x08, 0x47, 0x1b, 0xd0, 0x8b, 0x62, 0x82, 0x7d, 0x9f, 0x3a, 0x98, 0x11, 0x61,
0x9f, 0xb6, 0x95, 0x05, 0x99, 0x17, 0xe0, 0x5c, 0x25, 0x73, 0xb9, 0x40, 0xf3, 0x9d, 0xc2, 0xea,
0x69, 0x10, 0x78, 0x8d, 0x44, 0x9b, 0xe7, 0x4b, 0xab, 0x16, 0x94, 0x8a, 0xef, 0x77, 0x0b, 0xb3,
0x3e, 0xc1, 0xe1, 0x28, 0x6a, 0xc4, 0xb8, 0xb8, 0x62, 0x4d, 0x9a, 0x72, 0x3e, 0x23, 0xdd, 0x66,
0x9b, 0xfa, 0x3e, 0x71, 0x98, 0x47, 0x43, 0xcd, 0xf6, 0x22, 0x80, 0x93, 0x02, 0x95, 0x13, 0x65,
0x20, 0xa6, 0x01, 0x83, 0x32, 0xa9, 0x62, 0xfb, 0xd7, 0x16, 0xbc, 0x70, 0x53, 0x19, 0x4d, 0x0a,
0x6e, 0xb4, 0x01, 0x79, 0x91, 0xb3, 0x45, 0x91, 0xc5, 0x0d, 0x6a, 0x97, 0x36, 0x88, 0x63, 0xc4,
0x24, 0xf2, 0x3d, 0x07, 0x0b, 0x16, 0x73, 0x82, 0x45, 0x16, 0x84, 0x56, 0xa0, 0xcd, 0x98, 0x2f,
0x3c, 0xb7, 0x6b, 0xf1, 0x21, 0xda, 0x82, 0xf5, 0x80, 0x04, 0x34, 0x1e, 0xdb, 0x01, 0x8e, 0xec,
0x00, 0x3f, 0xb1, 0xb9, 0x9b, 0xdb, 0xc1, 0xfe, 0x60, 0x41, 0xac, 0x0f, 0xc9, 0xd9, 0x7b, 0x38,
0xba, 0x87, 0x9f, 0xec, 0x79, 0x4f, 0xc9, 0xbd, 0x7d, 0x73, 0x00, 0xeb, 0x45, 0xfd, 0x94, 0xea,
0xdf, 0x81, 0x33, 0x12, 0xb2, 0x37, 0x0e, 0x9d, 0x3d, 0x11, 0x5b, 0x8d, 0x36, 0xea, 0xdf, 0x2d,
0x18, 0x94, 0x09, 0x95, 0xe7, 0x3f, 0xab, 0xd5, 0x4e, 0x6c, 0x93, 0x4b, 0xd0, 0x63, 0xd8, 0xf3,
0x6d, 0x3a, 0x1c, 0x26, 0x84, 0x09, 0x43, 0xcc, 0x59, 0xc0, 0x41, 0xf7, 0x05, 0x04, 0x5d, 0x81,
0x15, 0x47, 0x7a, 0xbf, 0x1d, 0x93, 0x23, 0x4f, 0x64, 0x83, 0x45, 0xb1, 0xb0, 0x65, 0x47, 0x47,
0x85, 0x04, 0x23, 0x13, 0x96, 0x3c, 0xf7, 0x89, 0x2d, 0xd2, 0x91, 0x48, 0x26, 0x1d, 0xc1, 0xad,
0xe7, 0xb9, 0x4f, 0xee, 0x78, 0x3e, 0xe1, 0x16, 0x35, 0x1f, 0xc2, 0x79, 0xa9, 0xfc, 0xdd, 0xd0,
0x89, 0x49, 0x40, 0x42, 0x86, 0xfd, 0x6d, 0x1a, 0x8d, 0x1b, 0xb9, 0xcd, 0x59, 0xe8, 0x24, 0x5e,
0xe8, 0x10, 0x3b, 0x94, 0x49, 0x6d, 0xce, 0x5a, 0x14, 0xdf, 0xbb, 0x89, 0x79, 0x0b, 0x2e, 0xd4,
0xf0, 0x55, 0x96, 0x7d, 0x11, 0xfa, 0x62, 0x61, 0x0e, 0x0d, 0x19, 0x09, 0x99, 0xe0, 0xdd, 0xb7,
0x7a, 0x1c, 0xb6, 0x2d, 0x41, 0xe6, 0x9b, 0x80, 0x24, 0x8f, 0x7b, 0x74, 0x14, 0x36, 0x0b, 0xe7,
0x17, 0x60, 0x35, 0x47, 0xa2, 0x7c, 0xe3, 0x2d, 0x58, 0x93, 0xe0, 0x4f, 0xc3, 0xa0, 0x31, 0xaf,
0x33, 0xf0, 0x42, 0x81, 0x48, 0x71, 0xdb, 0xd2, 0x42, 0xf2, 0xc7, 0xce, 0xb1, 0xcc, 0xd6, 0xf5,
0x0a, 0xf2, 0x27, 0x8f, 0xc8, 0x5c, 0x72, 0xc1, 0x38, 0x3e, 0xb4, 0x08, 0x76, 0x69, 0xe8, 0x8f,
0x1b, 0x67, 0xae, 0x0a, 0x4a, 0xc5, 0xf7, 0x0f, 0x2d, 0x38, 0xad, 0x53, 0x5a, 0xc3, 0xdd, 0x3c,
0xa1, 0x3b, 0xb7, 0x6b, 0xdd, 0x79, 0x6e, 0xe2, 0xce, 0x97, 0x61, 0x25, 0xa1, 0xa3, 0xd8, 0x21,
0xb6, 0x8b, 0x19, 0xb6, 0x43, 0xea, 0x12, 0xe5, 0xed, 0xa7, 0x24, 0x7c, 0x07, 0x33, 0xbc, 0x4b,
0x5d, 0x62, 0x7e, 0x5f, 0x6f, 0x76, 0xce, 0x4b, 0xae, 0xc0, 0x69, 0x1f, 0x27, 0xcc, 0xc6, 0x51,
0x44, 0x42, 0xd7, 0xc6, 0x8c, 0xbb, 0x5a, 0x4b, 0xb8, 0xda, 0x29, 0x3e, 0x71, 0x53, 0xc0, 0x6f,
0xb2, 0xdd, 0xc4, 0xfc, 0xed, 0x2c, 0x2c, 0x73, 0x5a, 0xee, 0xda, 0x8d, 0xf4, 0x5d, 0x81, 0x36,
0x79, 0xc2, 0x94, 0xa2, 0x7c, 0x88, 0xae, 0xc3, 0xaa, 0x8a, 0x21, 0x8f, 0x86, 0x93, 0xf0, 0x6a,
0xcb, 0x6c, 0x34, 0x99, 0x4a, 0x23, 0xec, 0x12, 0xf4, 0x12, 0x46, 0x23, 0x1d, 0xad, 0x73, 0x32,
0x5a, 0x39, 0x48, 0x45, 0x6b, 0xde, 0xa6, 0xf3, 0x15, 0x36, 0xed, 0x7b, 0x89, 0x4d, 0x1c, 0x5b,
0xae, 0x4a, 0xc4, 0x7b, 0xc7, 0x02, 0x2f, 0xb9, 0xed, 0x48, 0x6b, 0xa0, 0x0f, 0xe0, 0xbc, 0xf7,
0x28, 0xa4, 0x31, 0xb1, 0x95, 0x21, 0x45, 0xd4, 0x84, 0x94, 0xd9, 0x43, 0x3a, 0x0a, 0x5d, 0x11,
0xfb, 0x1d, 0x6b, 0x20, 0x71, 0xf6, 0x04, 0x0a, 0xb7, 0xc0, 0x2e, 0x65, 0x77, 0xf8, 0xbc, 0xf9,
0xff, 0xb0, 0x32, 0xb1, 0x4a, 0xf3, 0xd8, 0xfb, 0xba, 0xa5, 0xd3, 0xe9, 0x03, 0xec, 0xf9, 0x7b,
0x24, 0x74, 0x49, 0xfc, 0x8c, 0x39, 0x01, 0xdd, 0x80, 0x35, 0xcf, 0xf5, 0x89, 0xcd, 0xbc, 0x80,
0xd0, 0x11, 0xb3, 0x13, 0xe2, 0xd0, 0xd0, 0x4d, 0xb4, 0x7d, 0xf9, 0xdc, 0x03, 0x39, 0xb5, 0x27,
0x67, 0xcc, 0x5f, 0xa5, 0xb9, 0x39, 0xbb, 0x8a, 0xc9, 0xad, 0x24, 0x24, 0x84, 0x33, 0x3c, 0x20,
0xd8, 0x25, 0xb1, 0x52, 0xa3, 0x2f, 0x81, 0x3f, 0x12, 0x30, 0xbe, 0x43, 0x0a, 0x69, 0x9f, 0xba,
0x63, 0xb1, 0xa2, 0xbe, 0x05, 0x12, 0x74, 0x8b, 0xba, 0x63, 0x91, 0x24, 0x13, 0x5b, 0x38, 0x99,
0x73, 0x30, 0x0a, 0x0f, 0xc5, 0x6a, 0x3a, 0x56, 0xcf, 0x4b, 0x3e, 0xc2, 0x09, 0xdb, 0xe6, 0x20,
0xf3, 0x4f, 0x2d, 0x1d, 0xa5, 0x7c, 0x19, 0x16, 0x71, 0x88, 0x77, 0xf4, 0x5f, 0x30, 0x07, 0xa7,
0x50, 0x4e, 0x90, 0xbb, 0x9d, 0xaa, 0x80, 0x43, 0x72, 0x4e, 0x9d, 0x65, 0x62, 0x66, 0x92, 0x24,
0xf2, 0x0b, 0x57, 0x49, 0xe2, 0x0b, 0x9d, 0xa4, 0x6f, 0x3b, 0x7b, 0x07, 0x38, 0x76, 0x93, 0x1f,
0x92, 0x90, 0xc4, 0x98, 0x3d, 0x97, 0x4b, 0x83, 0xb9, 0x01, 0x17, 0xeb, 0xb8, 0x2b, 0xf9, 0x9f,
0xeb, 0xc3, 0x47, 0x63, 0x58, 0x64, 0x7f, 0xe4, 0xf9, 0xee, 0x73, 0x11, 0xff, 0x61, 0x51, 0xb9,
0x94, 0xb9, 0xf2, 0x9f, 0xab, 0x70, 0x3a, 0x16, 0x20, 0x66, 0x27, 0x1c, 0x21, 0xad, 0x17, 0x96,
0xac, 0x65, 0x35, 0x21, 0x08, 0x79, 0xdd, 0xf0, 0xf7, 0xd4, 0x03, 0x34, 0xb7, 0xe7, 0x96, 0x56,
0xcf, 0x41, 0x77, 0x22, 0xbe, 0x2d, 0xc4, 0x77, 0x12, 0x25, 0x97, 0x7b, 0xa7, 0x43, 0xa3, 0xb1,
0x4d, 0x1c, 0x79, 0x8e, 0x8b, 0xad, 0xee, 0x58, 0x3d, 0x0e, 0xbc, 0xed, 0x88, 0x63, 0xbc, 0x79,
0x8e, 0xcd, 0x70, 0xfb, 0x52, 0x72, 0x5b, 0xc8, 0x72, 0xfb, 0x92, 0x73, 0x9b, 0x78, 0x4c, 0x5e,
0x51, 0xb5, 0x63, 0x5f, 0xc1, 0xb9, 0xfc, 0x6c, 0xf3, 0x23, 0xf0, 0x99, 0x0c, 0x61, 0x5e, 0x2c,
0xba, 0x4a, 0xe1, 0x1c, 0x3d, 0x2a, 0x2e, 0xbb, 0xf1, 0x9d, 0xe1, 0xd9, 0xd6, 0x75, 0xa1, 0x68,
0x90, 0xfc, 0xc5, 0xe3, 0xb3, 0xe2, 0xb2, 0x4f, 0x70, 0x01, 0x39, 0x5e, 0xf0, 0xa5, 0xa2, 0x7b,
0x17, 0x6f, 0x29, 0xbf, 0x4b, 0x73, 0xa7, 0xc2, 0xe0, 0x77, 0x84, 0xc6, 0x39, 0x4b, 0xc9, 0x15,
0xe6, 0x58, 0xb2, 0x16, 0x95, 0x58, 0x5e, 0xc4, 0xaa, 0xb3, 0x4e, 0xd6, 0x00, 0xea, 0x2b, 0x57,
0xae, 0xb6, 0x55, 0xb9, 0xaa, 0xcb, 0xf0, 0x43, 0x32, 0x16, 0xfe, 0x38, 0x27, 0xcb, 0xf0, 0x0f,
0xc9, 0xd8, 0xdc, 0x2d, 0x44, 0x93, 0x5c, 0x9a, 0x8a, 0x4b, 0x04, 0x73, 0xdc, 0x91, 0x55, 0x3a,
0x17, 0x63, 0x74, 0x01, 0xc0, 0x4b, 0x6c, 0x57, 0xec, 0xb9, 0x5c, 0x54, 0xc7, 0xea, 0x7a, 0xca,
0x09, 0x5c, 0xf3, 0x37, 0x99, 0xf0, 0xbc, 0xe5, 0xd3, 0xfd, 0xe7, 0xe8, 0x95, 0x59, 0x2d, 0xda,
0x39, 0x2d, 0xb2, 0xf5, 0xf8, 0x5c, 0xbe, 0x1e, 0xcf, 0x04, 0x51, 0x76, 0x39, 0x75, 0x69, 0xf7,
0x01, 0x7d, 0x7e, 0xb5, 0x5a, 0x39, 0xed, 0x4e, 0xb8, 0x2b, 0xf9, 0xef, 0xc2, 0x39, 0x6e, 0x70,
0x09, 0x15, 0x95, 0x40, 0xf3, 0x6a, 0xe9, 0x1f, 0xb3, 0x70, 0xbe, 0x9a, 0xb8, 0x49, 0xc5, 0xf4,
0x1e, 0x18, 0x69, 0x45, 0xc2, 0x8f, 0xbd, 0x84, 0xe1, 0x20, 0x4a, 0x0f, 0x3e, 0x79, 0x3e, 0x9e,
0x51, 0xe5, 0xc9, 0x03, 0x3d, 0xaf, 0x4f, 0xbf, 0x52, 0x39, 0xd3, 0x2e, 0x95, 0x33, 0x5c, 0x80,
0x8b, 0x59, 0x9d, 0x00, 0x79, 0x3f, 0x3b, 0xe3, 0x62, 0x56, 0x27, 0x20, 0x25, 0x16, 0x02, 0xa4,
0xd7, 0xf6, 0x14, 0xbe, 0x10, 0x70, 0x01, 0x40, 0x5d, 0x9d, 0x46, 0xa1, 0x2e, 0xcf, 0xba, 0xf2,
0xe2, 0x34, 0x0a, 0x6b, 0x6f, 0x90, 0x8b, 0xb5, 0x37, 0xc8, 0xfc, 0x6e, 0x76, 0x4a, 0xbb, 0xf9,
0x19, 0xc0, 0x8e, 0x97, 0x1c, 0x4a, 0x23, 0xf3, 0x2b, 0xab, 0xeb, 0xc5, 0xea, 0x4d, 0x80, 0x0f,
0x39, 0x04, 0xfb, 0xbe, 0x32, 0x1d, 0x1f, 0xf2, 0xf0, 0x19, 0x25, 0xc4, 0x55, 0xd6, 0x11, 0x63,
0x0e, 0x1b, 0xc6, 0x84, 0x28, 0x03, 0x88, 0xb1, 0xf9, 0xfb, 0x16, 0x74, 0xef, 0x91, 0x40, 0x71,
0xbe, 0x08, 0xf0, 0x88, 0xc6, 0x74, 0xc4, 0xbc, 0x90, 0xc8, 0x1b, 0xf6, 0xbc, 0x95, 0x81, 0x7c,
0x7b, 0x39, 0x22, 0x35, 0x10, 0x7f, 0xa8, 0x8c, 0x29, 0xc6, 0x1c, 0x76, 0x40, 0x70, 0xa4, 0xec,
0x27, 0xc6, 0x68, 0x0d, 0xe6, 0x13, 0x86, 0x9d, 0x43, 0x61, 0xac, 0x39, 0x4b, 0x7e, 0x98, 0x7f,
0x6e, 0x01, 0x58, 0x24, 0xa0, 0x4c, 0xf8, 0x1a, 0xbf, 0xb9, 0xee, 0x63, 0xe7, 0x90, 0xd7, 0x02,
0x6c, 0x1c, 0x11, 0x65, 0x89, 0x9e, 0x82, 0x3d, 0x18, 0x47, 0x62, 0x87, 0x34, 0x8a, 0xca, 0x5f,
0x5d, 0xab, 0xab, 0x20, 0xf2, 0xd6, 0xaf, 0x43, 0xb9, 0x6b, 0xf1, 0x61, 0x26, 0xa7, 0xc9, 0x65,
0xeb, 0x9c, 0x76, 0x0e, 0xba, 0x45, 0x57, 0x10, 0xa9, 0x40, 0xf8, 0xc1, 0x4b, 0xb0, 0x14, 0x50,
0xd7, 0x1b, 0x7a, 0xc4, 0x15, 0x8e, 0xa6, 0x54, 0xe9, 0x6b, 0x20, 0x77, 0x2e, 0x73, 0x07, 0x4e,
0xa9, 0xdb, 0x97, 0x47, 0xe2, 0xbb, 0xe1, 0x90, 0xa2, 0x2d, 0x98, 0xe7, 0x2c, 0xf4, 0x33, 0xe3,
0xf9, 0xf2, 0x33, 0xe3, 0x44, 0x59, 0x4b, 0xa2, 0x9a, 0xdf, 0xb4, 0x60, 0x63, 0xc2, 0x86, 0x1f,
0xc7, 0x3b, 0x98, 0x3d, 0xa0, 0x12, 0xf1, 0xb9, 0xe4, 0xb8, 0x77, 0x60, 0xe0, 0x92, 0x84, 0x79,
0xa1, 0x28, 0xe3, 0x6c, 0x6d, 0xbe, 0x10, 0x07, 0x44, 0x19, 0x6a, 0x3d, 0x33, 0x7f, 0x4b, 0x4e,
0xef, 0xe2, 0x80, 0xa0, 0x6b, 0xb0, 0x7a, 0x48, 0x48, 0x64, 0xfb, 0xd4, 0xc1, 0xbe, 0xad, 0xa3,
0x47, 0xdd, 0x52, 0x56, 0xf8, 0xd4, 0x47, 0x7c, 0x66, 0x47, 0x46, 0x90, 0x99, 0xc0, 0x8b, 0xc7,
0x68, 0xa2, 0x32, 0xc8, 0x79, 0xe8, 0x46, 0x31, 0x75, 0x48, 0xc2, 0xbd, 0xab, 0x25, 0x0e, 0x94,
0x09, 0x00, 0xdd, 0x80, 0xd5, 0xf4, 0xe3, 0x63, 0x12, 0x3b, 0x24, 0x64, 0xf8, 0x91, 0x7c, 0x33,
0x9c, 0xb5, 0xaa, 0xa6, 0xcc, 0x7f, 0xf5, 0xa1, 0xff, 0xc9, 0x88, 0xc4, 0xe3, 0xcc, 0x03, 0x5b,
0x42, 0x94, 0xee, 0xfa, 0x85, 0x38, 0x03, 0xe1, 0x79, 0x60, 0x18, 0xd3, 0xc0, 0x4e, 0x1f, 0x91,
0x67, 0x05, 0x4a, 0x8f, 0x03, 0xef, 0xc8, 0x87, 0x64, 0xf4, 0x3e, 0x2c, 0x0c, 0x3d, 0x9f, 0x11,
0xf9, 0x6c, 0xdb, 0xdb, 0x7a, 0xa5, 0xbc, 0x93, 0x59, 0x99, 0x9b, 0x77, 0x04, 0xb2, 0xa5, 0x88,
0xd0, 0x3e, 0xac, 0x7a, 0x61, 0x24, 0x2e, 0xfd, 0xb1, 0x87, 0x7d, 0xef, 0xe9, 0xe4, 0x89, 0xa8,
0xb7, 0xf5, 0xe6, 0x14, 0x5e, 0x77, 0x39, 0xe5, 0x5e, 0x96, 0xd0, 0x42, 0x5e, 0x09, 0x86, 0x08,
0xac, 0xd1, 0x11, 0x2b, 0x0b, 0x99, 0x17, 0x42, 0xb6, 0xa6, 0x08, 0xb9, 0x2f, 0x48, 0xf3, 0x52,
0x56, 0x69, 0x19, 0x68, 0xec, 0xc2, 0x82, 0x54, 0x8e, 0x47, 0xf0, 0xd0, 0x23, 0xbe, 0x7e, 0xf8,
0x96, 0x1f, 0xfc, 0x94, 0xa4, 0x11, 0x89, 0x71, 0xa8, 0x83, 0x51, 0x7f, 0x72, 0xfc, 0x23, 0xec,
0x8f, 0xb4, 0x8f, 0xc9, 0x0f, 0xe3, 0x2f, 0xf3, 0x80, 0xca, 0x1a, 0xea, 0x77, 0xaf, 0x98, 0x24,
0x3c, 0x6f, 0x66, 0xa3, 0x7f, 0x39, 0x03, 0x17, 0x19, 0xe0, 0x27, 0xd0, 0x75, 0x92, 0x23, 0x5b,
0x98, 0x44, 0xc8, 0xec, 0x6d, 0xbd, 0x7b, 0x62, 0x93, 0x6e, 0x6e, 0xef, 0x3d, 0x14, 0x50, 0xab,
0xe3, 0x24, 0x47, 0x62, 0x84, 0x7e, 0x06, 0xf0, 0x65, 0x42, 0x43, 0xc5, 0x59, 0x6e, 0xfc, 0x7b,
0x27, 0xe7, 0xfc, 0xe3, 0xbd, 0xfb, 0xbb, 0x92, 0x75, 0x97, 0xb3, 0x93, 0xbc, 0x1d, 0x58, 0x8a,
0x70, 0xfc, 0x78, 0x44, 0x98, 0x62, 0x2f, 0x7d, 0xe1, 0x83, 0x93, 0xb3, 0xff, 0x58, 0xb2, 0x91,
0x12, 0xfa, 0x51, 0xe6, 0xcb, 0xf8, 0x66, 0x16, 0x3a, 0x5a, 0x2f, 0x5e, 0x37, 0x08, 0x0f, 0x97,
0xd5, 0xb3, 0xed, 0x85, 0x43, 0xaa, 0x2c, 0x7a, 0x8a, 0xc3, 0x65, 0x01, 0x2d, 0xb2, 0xd6, 0x15,
0x58, 0x89, 0x89, 0x43, 0x63, 0x97, 0xdf, 0xc0, 0xbc, 0xc0, 0xe3, 0x6e, 0x2f, 0xf7, 0x72, 0x59,
0xc2, 0x77, 0x34, 0x18, 0xbd, 0x06, 0xcb, 0x62, 0xdb, 0x33, 0x98, 0x6d, 0xcd, 0x93, 0xf8, 0x19,
0xc4, 0x2b, 0xb0, 0xf2, 0x78, 0x44, 0x19, 0xb1, 0x9d, 0x03, 0x1c, 0x63, 0x87, 0xd1, 0xb4, 0x8e,
0x5d, 0x16, 0xf0, 0xed, 0x14, 0x8c, 0xfe, 0x0f, 0xd6, 0x25, 0x2a, 0x49, 0x1c, 0x1c, 0xa5, 0x14,
0x24, 0x56, 0x65, 0xce, 0x9a, 0x98, 0xbd, 0x2d, 0x26, 0xb7, 0xf5, 0x1c, 0x32, 0xa0, 0xe3, 0xd0,
0x20, 0x20, 0x21, 0x4b, 0x44, 0x72, 0xee, 0x5a, 0xe9, 0x37, 0xba, 0x09, 0x17, 0xb0, 0xef, 0xd3,
0xaf, 0x6c, 0x41, 0xe9, 0xda, 0x25, 0xed, 0xe4, 0xab, 0x8a, 0x21, 0x90, 0x3e, 0x11, 0x38, 0x56,
0x5e, 0x51, 0xe3, 0x12, 0x74, 0xd3, 0x7d, 0xe4, 0xe7, 0x59, 0xc6, 0x21, 0xc5, 0xd8, 0x38, 0x05,
0xfd, 0xec, 0x4e, 0x18, 0xff, 0x6c, 0xc3, 0x6a, 0x45, 0x50, 0xa1, 0xcf, 0x01, 0xb8, 0xb7, 0xca,
0xd0, 0x52, 0xee, 0xfa, 0xbd, 0x93, 0x07, 0x27, 0xf7, 0x57, 0x09, 0xb6, 0xb8, 0xf7, 0xcb, 0x21,
0xfa, 0x39, 0xf4, 0x84, 0xc7, 0x2a, 0xee, 0xd2, 0x65, 0xdf, 0xff, 0x16, 0xdc, 0xb9, 0xae, 0x8a,
0xbd, 0x88, 0x01, 0x39, 0x36, 0xfe, 0xd6, 0x82, 0x6e, 0x2a, 0x98, 0x9f, 0xce, 0x72, 0xa3, 0xc4,
0x5e, 0x27, 0xfa, 0x74, 0x16, 0xb0, 0x3b, 0x02, 0xf4, 0x3f, 0xe9, 0x4a, 0xc6, 0xdb, 0x00, 0x13,
0xfd, 0x2b, 0x55, 0x68, 0x55, 0xaa, 0x60, 0x5e, 0x81, 0x25, 0x6e, 0x59, 0x8f, 0xb8, 0x7b, 0x2c,
0xf6, 0x22, 0xd1, 0xc2, 0x93, 0x38, 0x89, 0x2a, 0x6f, 0xf4, 0xe7, 0xd6, 0x1f, 0xcf, 0x42, 0x3f,
0xfb, 0x74, 0x83, 0xbe, 0x80, 0x5e, 0xa6, 0x55, 0x89, 0x5e, 0x2e, 0x6f, 0x5a, 0xb9, 0xf5, 0x69,
0xbc, 0x32, 0x05, 0x4b, 0x55, 0x00, 0x33, 0x28, 0x84, 0xd3, 0xa5, 0x7e, 0x1f, 0xba, 0x5a, 0xa6,
0xae, 0xeb, 0x26, 0x1a, 0xaf, 0x37, 0xc2, 0x4d, 0xe5, 0x31, 0x58, 0xad, 0x68, 0xe0, 0xa1, 0x37,
0xa6, 0x70, 0xc9, 0x35, 0x11, 0x8d, 0x6b, 0x0d, 0xb1, 0x53, 0xa9, 0x8f, 0x01, 0x95, 0xbb, 0x7b,
0xe8, 0xf5, 0xa9, 0x6c, 0x26, 0xdd, 0x43, 0xe3, 0x8d, 0x66, 0xc8, 0xb5, 0x8a, 0xca, 0xbe, 0xdf,
0x54, 0x45, 0x73, 0x9d, 0xc5, 0xa9, 0x8a, 0x16, 0x9a, 0x89, 0x33, 0xe8, 0x10, 0x56, 0x8a, 0x3d,
0x41, 0x74, 0xa5, 0xae, 0x87, 0x5d, 0x6a, 0x39, 0x1a, 0x57, 0x9b, 0xa0, 0xa6, 0xc2, 0x08, 0x9c,
0xca, 0xf7, 0xe0, 0xd0, 0x6b, 0x65, 0xfa, 0xca, 0x2e, 0xa4, 0x71, 0x79, 0x3a, 0x62, 0x56, 0xa7,
0x62, 0x5f, 0xae, 0x4a, 0xa7, 0x9a, 0xa6, 0x5f, 0x95, 0x4e, 0x75, 0x6d, 0x3e, 0x73, 0x06, 0xfd,
0x42, 0x37, 0x7b, 0x0a, 0xfd, 0x2a, 0xb4, 0x59, 0xc7, 0xa6, 0xba, 0x61, 0x66, 0x5c, 0x6f, 0x8c,
0xaf, 0x65, 0xdf, 0x68, 0xf1, 0x58, 0xcf, 0xb4, 0xad, 0xaa, 0x62, 0xbd, 0xdc, 0x08, 0xab, 0x8a,
0xf5, 0xaa, 0xde, 0xd7, 0x0c, 0xda, 0x87, 0xa5, 0x5c, 0x23, 0x0b, 0xbd, 0x5a, 0x47, 0x99, 0x7f,
0x9d, 0x32, 0x5e, 0x9b, 0x8a, 0x97, 0xca, 0xb0, 0x75, 0xf6, 0x52, 0xe9, 0xaa, 0x76, 0x71, 0xf9,
0x7c, 0xf5, 0xea, 0x34, 0xb4, 0x5c, 0x28, 0x97, 0xda, 0x5d, 0x95, 0xa1, 0x5c, 0xd7, 0x4e, 0xab,
0x0c, 0xe5, 0xfa, 0x0e, 0xda, 0x0c, 0xfa, 0x29, 0xc0, 0xa4, 0x25, 0x85, 0x5e, 0xaa, 0xa3, 0xce,
0xee, 0xfe, 0xcb, 0xc7, 0x23, 0xa5, 0xac, 0xbf, 0x82, 0xb5, 0xaa, 0x57, 0x14, 0x74, 0xad, 0xaa,
0x20, 0xac, 0x7d, 0xaa, 0x31, 0x36, 0x9b, 0xa2, 0xa7, 0x82, 0x3f, 0x85, 0x8e, 0x6e, 0x07, 0xa1,
0x17, 0xcb, 0xd4, 0x85, 0x06, 0x9a, 0x61, 0x1e, 0x87, 0x92, 0x71, 0xe0, 0x40, 0xc7, 0xea, 0xa4,
0x4f, 0x53, 0x1f, 0xab, 0xa5, 0x8e, 0x52, 0x7d, 0xac, 0x96, 0xdb, 0x3e, 0x42, 0x5c, 0xea, 0x0c,
0xd9, 0xb6, 0x46, 0xbd, 0x33, 0x54, 0x74, 0x6d, 0xea, 0x9d, 0xa1, 0xb2, 0x53, 0x32, 0x83, 0x7e,
0x09, 0xeb, 0xd5, 0xdd, 0x0c, 0x54, 0x1b, 0xf1, 0x35, 0x5d, 0x15, 0xe3, 0x46, 0x73, 0x82, 0x54,
0xfc, 0x53, 0x9d, 0x9f, 0x0a, 0xdd, 0x8c, 0xfa, 0xfc, 0x54, 0xdd, 0x53, 0x31, 0xae, 0x37, 0xc6,
0x2f, 0x87, 0x5e, 0xb6, 0x25, 0x50, 0x6f, 0xed, 0x8a, 0x0e, 0x49, 0xbd, 0xb5, 0x2b, 0xbb, 0x0c,
0x22, 0x3e, 0xaa, 0x9e, 0xfb, 0xab, 0xe2, 0xe3, 0x98, 0x7e, 0x84, 0xb1, 0xd9, 0x14, 0x3d, 0x77,
0x7c, 0x97, 0xdf, 0xf3, 0xd1, 0xd4, 0xf5, 0xe7, 0x32, 0xf3, 0xb5, 0x86, 0xd8, 0xf5, 0xbb, 0xab,
0x33, 0xf5, 0x54, 0x05, 0x0a, 0x19, 0xfb, 0x7a, 0x63, 0xfc, 0x54, 0x76, 0xa4, 0x7f, 0x14, 0xc8,
0xbc, 0xc5, 0xa3, 0xab, 0x53, 0xf8, 0x64, 0x7a, 0x09, 0xc6, 0xeb, 0x8d, 0x70, 0xab, 0xa2, 0x37,
0xfb, 0x3a, 0x7e, 0x9c, 0x3f, 0x95, 0x9e, 0xf4, 0x8f, 0xf3, 0xa7, 0x8a, 0x07, 0xf7, 0x8a, 0xe8,
0xd5, 0x8f, 0xe2, 0xd3, 0xa3, 0xb7, 0xf0, 0x38, 0x3f, 0x3d, 0x7a, 0x4b, 0xef, 0xed, 0x33, 0xe8,
0xd7, 0x93, 0x06, 0x72, 0xf9, 0xe1, 0x0b, 0x6d, 0xd5, 0xa6, 0xa2, 0xda, 0xf7, 0x3e, 0xe3, 0xad,
0x13, 0xd1, 0x64, 0x8c, 0xff, 0x11, 0xcc, 0x8b, 0x62, 0x0f, 0x5d, 0x3c, 0xbe, 0x0a, 0x34, 0x2e,
0x55, 0xcf, 0xa7, 0xb5, 0x0c, 0xe7, 0xb6, 0xbf, 0x20, 0xfe, 0xcc, 0x7c, 0xeb, 0x3f, 0x01, 0x00,
0x00, 0xff, 0xff, 0x59, 0x62, 0x68, 0x9d, 0xb0, 0x29, 0x00, 0x00,
} }

7
weed/server/master_grpc_server_volume.go

@ -5,10 +5,11 @@ import (
"fmt" "fmt"
"github.com/chrislusf/raft" "github.com/chrislusf/raft"
"github.com/chrislusf/seaweedfs/weed/pb/master_pb" "github.com/chrislusf/seaweedfs/weed/pb/master_pb"
"github.com/chrislusf/seaweedfs/weed/security" "github.com/chrislusf/seaweedfs/weed/security"
"github.com/chrislusf/seaweedfs/weed/storage"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
"github.com/chrislusf/seaweedfs/weed/topology" "github.com/chrislusf/seaweedfs/weed/topology"
) )
@ -52,7 +53,7 @@ func (ms *MasterServer) Assign(ctx context.Context, req *master_pb.AssignRequest
if req.Replication == "" { if req.Replication == "" {
req.Replication = ms.option.DefaultReplicaPlacement req.Replication = ms.option.DefaultReplicaPlacement
} }
replicaPlacement, err := storage.NewReplicaPlacementFromString(req.Replication)
replicaPlacement, err := super_block.NewReplicaPlacementFromString(req.Replication)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -108,7 +109,7 @@ func (ms *MasterServer) Statistics(ctx context.Context, req *master_pb.Statistic
if req.Replication == "" { if req.Replication == "" {
req.Replication = ms.option.DefaultReplicaPlacement req.Replication = ms.option.DefaultReplicaPlacement
} }
replicaPlacement, err := storage.NewReplicaPlacementFromString(req.Replication)
replicaPlacement, err := super_block.NewReplicaPlacementFromString(req.Replication)
if err != nil { if err != nil {
return nil, err return nil, err
} }

4
weed/server/master_server_handlers_admin.go

@ -10,9 +10,9 @@ import (
"github.com/chrislusf/seaweedfs/weed/glog" "github.com/chrislusf/seaweedfs/weed/glog"
"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"
"github.com/chrislusf/seaweedfs/weed/storage/backend/memory_map" "github.com/chrislusf/seaweedfs/weed/storage/backend/memory_map"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
"github.com/chrislusf/seaweedfs/weed/topology" "github.com/chrislusf/seaweedfs/weed/topology"
"github.com/chrislusf/seaweedfs/weed/util" "github.com/chrislusf/seaweedfs/weed/util"
) )
@ -145,7 +145,7 @@ func (ms *MasterServer) getVolumeGrowOption(r *http.Request) (*topology.VolumeGr
if replicationString == "" { if replicationString == "" {
replicationString = ms.option.DefaultReplicaPlacement replicationString = ms.option.DefaultReplicaPlacement
} }
replicaPlacement, err := storage.NewReplicaPlacementFromString(replicationString)
replicaPlacement, err := super_block.NewReplicaPlacementFromString(replicationString)
if err != nil { if err != nil {
return nil, err return nil, err
} }

22
weed/server/volume_grpc_copy.go

@ -55,11 +55,11 @@ func (vs *VolumeServer) VolumeCopy(ctx context.Context, req *volume_server_pb.Vo
// println("source:", volFileInfoResp.String()) // println("source:", volFileInfoResp.String())
// copy ecx file // copy ecx file
if err := vs.doCopyFile(ctx, client, false, req.Collection, req.VolumeId, volFileInfoResp.CompactionRevision, volFileInfoResp.IdxFileSize, volumeFileName, ".idx", false); err != nil {
if err := vs.doCopyFile(ctx, client, false, req.Collection, req.VolumeId, volFileInfoResp.CompactionRevision, volFileInfoResp.IdxFileSize, volumeFileName, ".idx", false, false); err != nil {
return err return err
} }
if err := vs.doCopyFile(ctx, client, false, req.Collection, req.VolumeId, volFileInfoResp.CompactionRevision, volFileInfoResp.DatFileSize, volumeFileName, ".dat", false); err != nil {
if err := vs.doCopyFile(ctx, client, false, req.Collection, req.VolumeId, volFileInfoResp.CompactionRevision, volFileInfoResp.DatFileSize, volumeFileName, ".dat", false, true); err != nil {
return err return err
} }
@ -95,15 +95,16 @@ func (vs *VolumeServer) VolumeCopy(ctx context.Context, req *volume_server_pb.Vo
} }
func (vs *VolumeServer) doCopyFile(ctx context.Context, client volume_server_pb.VolumeServerClient, isEcVolume bool, collection string, vid uint32, func (vs *VolumeServer) doCopyFile(ctx context.Context, client volume_server_pb.VolumeServerClient, isEcVolume bool, collection string, vid uint32,
compactRevision uint32, stopOffset uint64, baseFileName, ext string, isAppend bool) error {
compactRevision uint32, stopOffset uint64, baseFileName, ext string, isAppend bool, ignoreSourceFileNotFound bool) error {
copyFileClient, err := client.CopyFile(ctx, &volume_server_pb.CopyFileRequest{ copyFileClient, err := client.CopyFile(ctx, &volume_server_pb.CopyFileRequest{
VolumeId: vid,
Ext: ext,
CompactionRevision: compactRevision,
StopOffset: stopOffset,
Collection: collection,
IsEcVolume: isEcVolume,
VolumeId: vid,
Ext: ext,
CompactionRevision: compactRevision,
StopOffset: stopOffset,
Collection: collection,
IsEcVolume: isEcVolume,
IgnoreSourceFileNotFound: ignoreSourceFileNotFound,
}) })
if err != nil { if err != nil {
return fmt.Errorf("failed to start copying volume %d %s file: %v", vid, ext, err) return fmt.Errorf("failed to start copying volume %d %s file: %v", vid, ext, err)
@ -221,6 +222,9 @@ func (vs *VolumeServer) CopyFile(req *volume_server_pb.CopyFileRequest, stream v
file, err := os.Open(fileName) file, err := os.Open(fileName)
if err != nil { if err != nil {
if req.IgnoreSourceFileNotFound && err == os.ErrNotExist {
return nil
}
return err return err
} }
defer file.Close() defer file.Close()

75
weed/server/volume_grpc_erasure_coding.go

@ -8,6 +8,7 @@ import (
"math" "math"
"os" "os"
"path" "path"
"path/filepath"
"strings" "strings"
"github.com/chrislusf/seaweedfs/weed/glog" "github.com/chrislusf/seaweedfs/weed/glog"
@ -24,7 +25,7 @@ import (
Steps to apply erasure coding to .dat .idx files Steps to apply erasure coding to .dat .idx files
0. ensure the volume is readonly 0. ensure the volume is readonly
1. client call VolumeEcShardsGenerate to generate the .ecx and .ec01~.ec14 files
1. client call VolumeEcShardsGenerate to generate the .ecx and .ec00 ~ .ec13 files
2. client ask master for possible servers to hold the ec files, at least 4 servers 2. client ask master for possible servers to hold the ec files, at least 4 servers
3. client call VolumeEcShardsCopy on above target servers to copy ec files from the source server 3. client call VolumeEcShardsCopy on above target servers to copy ec files from the source server
4. target servers report the new ec files to the master 4. target servers report the new ec files to the master
@ -33,7 +34,7 @@ Steps to apply erasure coding to .dat .idx files
*/ */
// VolumeEcShardsGenerate generates the .ecx and .ec01 ~ .ec14 files
// VolumeEcShardsGenerate generates the .ecx and .ec00 ~ .ec13 files
func (vs *VolumeServer) VolumeEcShardsGenerate(ctx context.Context, req *volume_server_pb.VolumeEcShardsGenerateRequest) (*volume_server_pb.VolumeEcShardsGenerateResponse, error) { func (vs *VolumeServer) VolumeEcShardsGenerate(ctx context.Context, req *volume_server_pb.VolumeEcShardsGenerateRequest) (*volume_server_pb.VolumeEcShardsGenerateResponse, error) {
v := vs.store.GetVolume(needle.VolumeId(req.VolumeId)) v := vs.store.GetVolume(needle.VolumeId(req.VolumeId))
@ -51,7 +52,7 @@ func (vs *VolumeServer) VolumeEcShardsGenerate(ctx context.Context, req *volume_
return nil, fmt.Errorf("WriteSortedFileFromIdx %s: %v", baseFileName, err) return nil, fmt.Errorf("WriteSortedFileFromIdx %s: %v", baseFileName, err)
} }
// write .ec01 ~ .ec14 files
// write .ec00 ~ .ec13 files
if err := erasure_coding.WriteEcFiles(baseFileName); err != nil { if err := erasure_coding.WriteEcFiles(baseFileName); err != nil {
return nil, fmt.Errorf("WriteEcFiles %s: %v", baseFileName, err) return nil, fmt.Errorf("WriteEcFiles %s: %v", baseFileName, err)
} }
@ -59,7 +60,7 @@ func (vs *VolumeServer) VolumeEcShardsGenerate(ctx context.Context, req *volume_
return &volume_server_pb.VolumeEcShardsGenerateResponse{}, nil return &volume_server_pb.VolumeEcShardsGenerateResponse{}, nil
} }
// VolumeEcShardsRebuild generates the any of the missing .ec01 ~ .ec14 files
// VolumeEcShardsRebuild generates the any of the missing .ec00 ~ .ec13 files
func (vs *VolumeServer) VolumeEcShardsRebuild(ctx context.Context, req *volume_server_pb.VolumeEcShardsRebuildRequest) (*volume_server_pb.VolumeEcShardsRebuildResponse, error) { func (vs *VolumeServer) VolumeEcShardsRebuild(ctx context.Context, req *volume_server_pb.VolumeEcShardsRebuildRequest) (*volume_server_pb.VolumeEcShardsRebuildResponse, error) {
baseFileName := erasure_coding.EcShardBaseFileName(req.Collection, int(req.VolumeId)) baseFileName := erasure_coding.EcShardBaseFileName(req.Collection, int(req.VolumeId))
@ -68,7 +69,7 @@ func (vs *VolumeServer) VolumeEcShardsRebuild(ctx context.Context, req *volume_s
for _, location := range vs.store.Locations { for _, location := range vs.store.Locations {
if util.FileExists(path.Join(location.Directory, baseFileName+".ecx")) { if util.FileExists(path.Join(location.Directory, baseFileName+".ecx")) {
// write .ec01 ~ .ec14 files
// write .ec00 ~ .ec13 files
baseFileName = path.Join(location.Directory, baseFileName) baseFileName = path.Join(location.Directory, baseFileName)
if generatedShardIds, err := erasure_coding.RebuildEcFiles(baseFileName); err != nil { if generatedShardIds, err := erasure_coding.RebuildEcFiles(baseFileName); err != nil {
return nil, fmt.Errorf("RebuildEcFiles %s: %v", baseFileName, err) return nil, fmt.Errorf("RebuildEcFiles %s: %v", baseFileName, err)
@ -103,25 +104,26 @@ func (vs *VolumeServer) VolumeEcShardsCopy(ctx context.Context, req *volume_serv
// copy ec data slices // copy ec data slices
for _, shardId := range req.ShardIds { for _, shardId := range req.ShardIds {
if err := vs.doCopyFile(ctx, client, true, req.Collection, req.VolumeId, math.MaxUint32, math.MaxInt64, baseFileName, erasure_coding.ToExt(int(shardId)), false); err != nil {
if err := vs.doCopyFile(ctx, client, true, req.Collection, req.VolumeId, math.MaxUint32, math.MaxInt64, baseFileName, erasure_coding.ToExt(int(shardId)), false, false); err != nil {
return err return err
} }
} }
if !req.CopyEcxFile {
return nil
}
if req.CopyEcxFile {
// copy ecx file
if err := vs.doCopyFile(ctx, client, true, req.Collection, req.VolumeId, math.MaxUint32, math.MaxInt64, baseFileName, ".ecx", false); err != nil {
return err
// copy ecx file
if err := vs.doCopyFile(ctx, client, true, req.Collection, req.VolumeId, math.MaxUint32, math.MaxInt64, baseFileName, ".ecx", false, false); err != nil {
return err
}
return nil
} }
// copy ecj file
if err := vs.doCopyFile(ctx, client, true, req.Collection, req.VolumeId, math.MaxUint32, math.MaxInt64, baseFileName, ".ecj", true); err != nil {
return err
if req.CopyEcjFile {
// copy ecj file
if err := vs.doCopyFile(ctx, client, true, req.Collection, req.VolumeId, math.MaxUint32, math.MaxInt64, baseFileName, ".ecj", true, true); err != nil {
return err
}
} }
return nil return nil
}) })
if err != nil { if err != nil {
@ -137,6 +139,8 @@ func (vs *VolumeServer) VolumeEcShardsDelete(ctx context.Context, req *volume_se
baseFilename := erasure_coding.EcShardBaseFileName(req.Collection, int(req.VolumeId)) baseFilename := erasure_coding.EcShardBaseFileName(req.Collection, int(req.VolumeId))
glog.V(0).Infof("ec volume %d shard delete %v", req.VolumeId, req.ShardIds)
found := false found := false
for _, location := range vs.store.Locations { for _, location := range vs.store.Locations {
if util.FileExists(path.Join(location.Directory, baseFilename+".ecx")) { if util.FileExists(path.Join(location.Directory, baseFilename+".ecx")) {
@ -153,21 +157,22 @@ func (vs *VolumeServer) VolumeEcShardsDelete(ctx context.Context, req *volume_se
return nil, nil return nil, nil
} }
// check whether to delete the ecx file also
// check whether to delete the .ecx and .ecj file also
hasEcxFile := false hasEcxFile := false
existingShardCount := 0 existingShardCount := 0
bName := filepath.Base(baseFilename)
for _, location := range vs.store.Locations { for _, location := range vs.store.Locations {
fileInfos, err := ioutil.ReadDir(location.Directory) fileInfos, err := ioutil.ReadDir(location.Directory)
if err != nil { if err != nil {
continue continue
} }
for _, fileInfo := range fileInfos { for _, fileInfo := range fileInfos {
if fileInfo.Name() == baseFilename+".ecx" {
if fileInfo.Name() == bName+".ecx" || fileInfo.Name() == bName+".ecj"{
hasEcxFile = true hasEcxFile = true
continue continue
} }
if strings.HasPrefix(fileInfo.Name(), baseFilename+".ec") {
if strings.HasPrefix(fileInfo.Name(), bName+".ec") {
existingShardCount++ existingShardCount++
} }
} }
@ -317,3 +322,35 @@ func (vs *VolumeServer) VolumeEcBlobDelete(ctx context.Context, req *volume_serv
return resp, nil return resp, nil
} }
// VolumeEcShardsToVolume generates the .idx, .dat files from .ecx, .ecj and .ec01 ~ .ec14 files
func (vs *VolumeServer) VolumeEcShardsToVolume(ctx context.Context, req *volume_server_pb.VolumeEcShardsToVolumeRequest) (*volume_server_pb.VolumeEcShardsToVolumeResponse, error) {
v, found := vs.store.FindEcVolume(needle.VolumeId(req.VolumeId))
if !found {
return nil, fmt.Errorf("ec volume %d not found", req.VolumeId)
}
baseFileName := v.FileName()
if v.Collection != req.Collection {
return nil, fmt.Errorf("existing collection:%v unexpected input: %v", v.Collection, req.Collection)
}
// calculate .dat file size
datFileSize, err := erasure_coding.FindDatFileSize(baseFileName)
if err != nil {
return nil, fmt.Errorf("FindDatFileSize %s: %v", baseFileName, err)
}
// write .dat file from .ec00 ~ .ec09 files
if err := erasure_coding.WriteDatFile(baseFileName, datFileSize); err != nil {
return nil, fmt.Errorf("WriteEcFiles %s: %v", baseFileName, err)
}
// write .idx file from .ecx and .ecj files
if err := erasure_coding.WriteIdxFileFromEcIndex(baseFileName); err != nil {
return nil, fmt.Errorf("WriteIdxFileFromEcIndex %s: %v", baseFileName, err)
}
return &volume_server_pb.VolumeEcShardsToVolumeResponse{}, nil
}

3
weed/server/volume_grpc_tail.go

@ -10,6 +10,7 @@ import (
"github.com/chrislusf/seaweedfs/weed/pb/volume_server_pb" "github.com/chrislusf/seaweedfs/weed/pb/volume_server_pb"
"github.com/chrislusf/seaweedfs/weed/storage" "github.com/chrislusf/seaweedfs/weed/storage"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
) )
func (vs *VolumeServer) VolumeTailSender(req *volume_server_pb.VolumeTailSenderRequest, stream volume_server_pb.VolumeServer_VolumeTailSenderServer) error { func (vs *VolumeServer) VolumeTailSender(req *volume_server_pb.VolumeTailSenderRequest, stream volume_server_pb.VolumeServer_VolumeTailSenderServer) error {
@ -101,7 +102,7 @@ type VolumeFileScanner4Tailing struct {
lastProcessedTimestampNs uint64 lastProcessedTimestampNs uint64
} }
func (scanner *VolumeFileScanner4Tailing) VisitSuperBlock(superBlock storage.SuperBlock) error {
func (scanner *VolumeFileScanner4Tailing) VisitSuperBlock(superBlock super_block.SuperBlock) error {
return nil return nil
} }

1
weed/shell/command_ec_common.go

@ -70,6 +70,7 @@ func oneServerCopyAndMountEcShardsFromSource(ctx context.Context, grpcDialOption
Collection: collection, Collection: collection,
ShardIds: shardIdsToCopy, ShardIds: shardIdsToCopy,
CopyEcxFile: true, CopyEcxFile: true,
CopyEcjFile: true,
SourceDataNode: existingLocation, SourceDataNode: existingLocation,
}) })
if copyErr != nil { if copyErr != nil {

263
weed/shell/command_ec_decode.go

@ -0,0 +1,263 @@
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/erasure_coding"
"github.com/chrislusf/seaweedfs/weed/storage/needle"
)
func init() {
Commands = append(Commands, &commandEcDecode{})
}
type commandEcDecode struct {
}
func (c *commandEcDecode) Name() string {
return "ec.decode"
}
func (c *commandEcDecode) Help() string {
return `decode a erasure coded volume into a normal volume
ec.decode [-collection=""] [-volumeId=<volume_id>]
`
}
func (c *commandEcDecode) Do(args []string, commandEnv *CommandEnv, writer io.Writer) (err error) {
encodeCommand := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
volumeId := encodeCommand.Int("volumeId", 0, "the volume id")
collection := encodeCommand.String("collection", "", "the collection name")
if err = encodeCommand.Parse(args); err != nil {
return nil
}
ctx := context.Background()
vid := needle.VolumeId(*volumeId)
// collect topology information
topologyInfo, err := collectTopologyInfoForEcDecode(ctx, commandEnv)
if err != nil {
return err
}
// volumeId is provided
if vid != 0 {
return doEcDecode(ctx, commandEnv, topologyInfo, *collection, vid)
}
// apply to all volumes in the collection
volumeIds := collectEcShardIds(topologyInfo, *collection)
fmt.Printf("ec encode volumes: %v\n", volumeIds)
for _, vid := range volumeIds {
if err = doEcDecode(ctx, commandEnv, topologyInfo, *collection, vid); err != nil {
return err
}
}
return nil
}
func doEcDecode(ctx context.Context, commandEnv *CommandEnv, topoInfo *master_pb.TopologyInfo, collection string, vid needle.VolumeId) (err error) {
// find volume location
nodeToEcIndexBits := collectEcNodeShardBits(topoInfo, vid)
fmt.Printf("ec volume %d shard locations: %+v\n", vid, nodeToEcIndexBits)
// collect ec shards to the server with most space
targetNodeLocation, err := collectEcShards(ctx, commandEnv, nodeToEcIndexBits, collection, vid)
if err != nil {
return fmt.Errorf("collectEcShards for volume %d: %v", vid, err)
}
// generate a normal volume
err = generateNormalVolume(ctx, commandEnv.option.GrpcDialOption, needle.VolumeId(vid), collection, targetNodeLocation)
if err != nil {
return fmt.Errorf("generate normal volume %d on %s: %v", vid, targetNodeLocation, err)
}
// delete the previous ec shards
err = mountVolumeAndDeleteEcShards(ctx, commandEnv.option.GrpcDialOption, collection, targetNodeLocation, nodeToEcIndexBits, vid)
if err != nil {
return fmt.Errorf("delete ec shards for volume %d: %v", vid, err)
}
return nil
}
func mountVolumeAndDeleteEcShards(ctx context.Context, grpcDialOption grpc.DialOption, collection, targetNodeLocation string, nodeToEcIndexBits map[string]erasure_coding.ShardBits, vid needle.VolumeId) error {
// mount volume
if err := operation.WithVolumeServerClient(targetNodeLocation, grpcDialOption, func(volumeServerClient volume_server_pb.VolumeServerClient) error {
_, mountErr := volumeServerClient.VolumeMount(ctx, &volume_server_pb.VolumeMountRequest{
VolumeId: uint32(vid),
})
return mountErr
}); err != nil {
return fmt.Errorf("mountVolumeAndDeleteEcShards mount volume %d on %s: %v", vid, targetNodeLocation, err)
}
// unmount ec shards
for location, ecIndexBits := range nodeToEcIndexBits {
fmt.Printf("unmount ec volume %d on %s has shards: %+v\n", vid, location, ecIndexBits.ShardIds())
err := unmountEcShards(ctx, grpcDialOption, vid, location, ecIndexBits.ToUint32Slice())
if err != nil {
return fmt.Errorf("mountVolumeAndDeleteEcShards unmount ec volume %d on %s: %v", vid, location, err)
}
}
// delete ec shards
for location, ecIndexBits := range nodeToEcIndexBits {
fmt.Printf("delete ec volume %d on %s has shards: %+v\n", vid, location, ecIndexBits.ShardIds())
err := sourceServerDeleteEcShards(ctx, grpcDialOption, collection, vid, location, ecIndexBits.ToUint32Slice())
if err != nil {
return fmt.Errorf("mountVolumeAndDeleteEcShards delete ec volume %d on %s: %v", vid, location, err)
}
}
return nil
}
func generateNormalVolume(ctx context.Context, grpcDialOption grpc.DialOption, vid needle.VolumeId, collection string, sourceVolumeServer string) error {
fmt.Printf("generateNormalVolume from ec volume %d on %s\n", vid, sourceVolumeServer)
err := operation.WithVolumeServerClient(sourceVolumeServer, grpcDialOption, func(volumeServerClient volume_server_pb.VolumeServerClient) error {
_, genErr := volumeServerClient.VolumeEcShardsToVolume(ctx, &volume_server_pb.VolumeEcShardsToVolumeRequest{
VolumeId: uint32(vid),
Collection: collection,
})
return genErr
})
return err
}
func collectEcShards(ctx context.Context, commandEnv *CommandEnv, nodeToEcIndexBits map[string]erasure_coding.ShardBits, collection string, vid needle.VolumeId) (targetNodeLocation string, err error) {
maxShardCount := 0
var exisitngEcIndexBits erasure_coding.ShardBits
for loc, ecIndexBits := range nodeToEcIndexBits {
if ecIndexBits.ShardIdCount() > maxShardCount {
maxShardCount = ecIndexBits.ShardIdCount()
targetNodeLocation = loc
exisitngEcIndexBits = ecIndexBits
}
}
fmt.Printf("collectEcShards: ec volume %d collect shards to %s from: %+v\n", vid, targetNodeLocation, nodeToEcIndexBits)
var copiedEcIndexBits erasure_coding.ShardBits
for loc, ecIndexBits := range nodeToEcIndexBits {
if loc == targetNodeLocation {
continue
}
needToCopyEcIndexBits := ecIndexBits.Minus(exisitngEcIndexBits)
if needToCopyEcIndexBits.ShardIdCount() == 0 {
continue
}
err = operation.WithVolumeServerClient(targetNodeLocation, commandEnv.option.GrpcDialOption, func(volumeServerClient volume_server_pb.VolumeServerClient) error {
fmt.Printf("copy %d.%v %s => %s\n", vid, needToCopyEcIndexBits.ShardIds(), loc, targetNodeLocation)
_, copyErr := volumeServerClient.VolumeEcShardsCopy(ctx, &volume_server_pb.VolumeEcShardsCopyRequest{
VolumeId: uint32(vid),
Collection: collection,
ShardIds: needToCopyEcIndexBits.ToUint32Slice(),
CopyEcxFile: false,
CopyEcjFile: true,
SourceDataNode: loc,
})
if copyErr != nil {
return fmt.Errorf("copy %d.%v %s => %s : %v\n", vid, needToCopyEcIndexBits.ShardIds(), loc, targetNodeLocation, copyErr)
}
return nil
})
if err != nil {
break
}
copiedEcIndexBits = copiedEcIndexBits.Plus(needToCopyEcIndexBits)
}
nodeToEcIndexBits[targetNodeLocation] = exisitngEcIndexBits.Plus(copiedEcIndexBits)
return targetNodeLocation, err
}
func collectTopologyInfoForEcDecode(ctx context.Context, commandEnv *CommandEnv) (topoInfo *master_pb.TopologyInfo, err error) {
var resp *master_pb.VolumeListResponse
err = commandEnv.MasterClient.WithClient(ctx, func(client master_pb.SeaweedClient) error {
resp, err = client.VolumeList(ctx, &master_pb.VolumeListRequest{})
return err
})
if err != nil {
return
}
return resp.TopologyInfo, nil
}
func collectEcShardInfos(topoInfo *master_pb.TopologyInfo, selectedCollection string, vid needle.VolumeId) (ecShardInfos []*master_pb.VolumeEcShardInformationMessage) {
eachDataNode(topoInfo, func(dc string, rack RackId, dn *master_pb.DataNodeInfo) {
for _, v := range dn.EcShardInfos {
if v.Collection == selectedCollection && v.Id == uint32(vid) {
ecShardInfos = append(ecShardInfos, v)
}
}
})
return
}
func collectEcShardIds(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.EcShardInfos {
if v.Collection == selectedCollection {
vidMap[v.Id] = true
}
}
})
for vid := range vidMap {
vids = append(vids, needle.VolumeId(vid))
}
return
}
func collectEcNodeShardBits(topoInfo *master_pb.TopologyInfo, vid needle.VolumeId) map[string]erasure_coding.ShardBits {
nodeToEcIndexBits := make(map[string]erasure_coding.ShardBits)
eachDataNode(topoInfo, func(dc string, rack RackId, dn *master_pb.DataNodeInfo) {
for _, v := range dn.EcShardInfos {
if v.Id == uint32(vid) {
nodeToEcIndexBits[dn.Id] = erasure_coding.ShardBits(v.EcIndexBits)
}
}
})
return nodeToEcIndexBits
}

1
weed/shell/command_ec_rebuild.go

@ -215,6 +215,7 @@ func prepareDataToRecover(ctx context.Context, commandEnv *CommandEnv, rebuilder
Collection: collection, Collection: collection,
ShardIds: []uint32{uint32(shardId)}, ShardIds: []uint32{uint32(shardId)},
CopyEcxFile: needEcxFile, CopyEcxFile: needEcxFile,
CopyEcjFile: needEcxFile,
SourceDataNode: ecNodes[0].info.Id, SourceDataNode: ecNodes[0].info.Id,
}) })
return copyErr return copyErr

15
weed/shell/command_volume_fix_replication.go

@ -3,13 +3,14 @@ package shell
import ( import (
"context" "context"
"fmt" "fmt"
"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"
"io" "io"
"math/rand" "math/rand"
"sort" "sort"
"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/super_block"
) )
func init() { func init() {
@ -78,7 +79,7 @@ func (c *commandVolumeFixReplication) Do(args []string, commandEnv *CommandEnv,
underReplicatedVolumeLocations := make(map[uint32][]location) underReplicatedVolumeLocations := make(map[uint32][]location)
for vid, locations := range replicatedVolumeLocations { for vid, locations := range replicatedVolumeLocations {
volumeInfo := replicatedVolumeInfo[vid] volumeInfo := replicatedVolumeInfo[vid]
replicaPlacement, _ := storage.NewReplicaPlacementFromByte(byte(volumeInfo.ReplicaPlacement))
replicaPlacement, _ := super_block.NewReplicaPlacementFromByte(byte(volumeInfo.ReplicaPlacement))
if replicaPlacement.GetCopyCount() > len(locations) { if replicaPlacement.GetCopyCount() > len(locations) {
underReplicatedVolumeLocations[vid] = locations underReplicatedVolumeLocations[vid] = locations
} }
@ -97,7 +98,7 @@ func (c *commandVolumeFixReplication) Do(args []string, commandEnv *CommandEnv,
for vid, locations := range underReplicatedVolumeLocations { for vid, locations := range underReplicatedVolumeLocations {
volumeInfo := replicatedVolumeInfo[vid] volumeInfo := replicatedVolumeInfo[vid]
replicaPlacement, _ := storage.NewReplicaPlacementFromByte(byte(volumeInfo.ReplicaPlacement))
replicaPlacement, _ := super_block.NewReplicaPlacementFromByte(byte(volumeInfo.ReplicaPlacement))
foundNewLocation := false foundNewLocation := false
for _, dst := range allLocations { for _, dst := range allLocations {
// check whether data nodes satisfy the constraints // check whether data nodes satisfy the constraints
@ -145,7 +146,7 @@ func keepDataNodesSorted(dataNodes []location) {
}) })
} }
func satisfyReplicaPlacement(replicaPlacement *storage.ReplicaPlacement, existingLocations []location, possibleLocation location) bool {
func satisfyReplicaPlacement(replicaPlacement *super_block.ReplicaPlacement, existingLocations []location, possibleLocation location) bool {
existingDataCenters := make(map[string]bool) existingDataCenters := make(map[string]bool)
existingRacks := make(map[string]bool) existingRacks := make(map[string]bool)

198
weed/storage/erasure_coding/ec_decoder.go

@ -0,0 +1,198 @@
package erasure_coding
import (
"fmt"
"io"
"os"
"github.com/chrislusf/seaweedfs/weed/storage/backend"
"github.com/chrislusf/seaweedfs/weed/storage/idx"
"github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/needle_map"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
"github.com/chrislusf/seaweedfs/weed/storage/types"
)
// write .idx file from .ecx and .ecj files
func WriteIdxFileFromEcIndex(baseFileName string) (err error) {
ecxFile, openErr := os.OpenFile(baseFileName+".ecx", os.O_RDONLY, 0644)
if openErr != nil {
return fmt.Errorf("cannot open ec index %s.ecx: %v", baseFileName, openErr)
}
defer ecxFile.Close()
idxFile, openErr := os.OpenFile(baseFileName+".idx", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if openErr != nil {
return fmt.Errorf("cannot open %s.idx: %v", baseFileName, openErr)
}
defer idxFile.Close()
io.Copy(idxFile, ecxFile)
err = iterateEcjFile(baseFileName, func(key types.NeedleId) error {
bytes := needle_map.ToBytes(key, types.Offset{}, types.TombstoneFileSize)
idxFile.Write(bytes)
return nil
})
return err
}
// FindDatFileSize calculate .dat file size from max offset entry
// there may be extra deletions after that entry
// but they are deletions anyway
func FindDatFileSize(baseFileName string) (datSize int64, err error) {
version, err := readEcVolumeVersion(baseFileName)
if err != nil {
return 0, fmt.Errorf("read ec volume %s version: %v", baseFileName, err)
}
err = iterateEcxFile(baseFileName, func(key types.NeedleId, offset types.Offset, size uint32) error {
if size == types.TombstoneFileSize {
return nil
}
entryStopOffset := offset.ToAcutalOffset() + needle.GetActualSize(size, version)
if datSize < entryStopOffset {
datSize = entryStopOffset
}
return nil
})
return
}
func readEcVolumeVersion(baseFileName string) (version needle.Version, err error) {
// find volume version
datFile, err := os.OpenFile(baseFileName+".ec00", os.O_RDONLY, 0644)
if err != nil {
return 0, fmt.Errorf("open ec volume %s superblock: %v", baseFileName, err)
}
datBackend := backend.NewDiskFile(datFile)
superBlock, err := super_block.ReadSuperBlock(datBackend)
datBackend.Close()
if err != nil {
return 0, fmt.Errorf("read ec volume %s superblock: %v", baseFileName, err)
}
return superBlock.Version, nil
}
func iterateEcxFile(baseFileName string, processNeedleFn func(key types.NeedleId, offset types.Offset, size uint32) error) error {
ecxFile, openErr := os.OpenFile(baseFileName+".ecx", os.O_RDONLY, 0644)
if openErr != nil {
return fmt.Errorf("cannot open ec index %s.ecx: %v", baseFileName, openErr)
}
defer ecxFile.Close()
buf := make([]byte, types.NeedleMapEntrySize)
for {
n, err := ecxFile.Read(buf)
if n != types.NeedleMapEntrySize {
if err == io.EOF {
return nil
}
return err
}
key, offset, size := idx.IdxFileEntry(buf)
if processNeedleFn != nil {
err = processNeedleFn(key, offset, size)
}
if err != nil {
if err != io.EOF {
return err
}
return nil
}
}
}
func iterateEcjFile(baseFileName string, processNeedleFn func(key types.NeedleId) error) error {
ecjFile, openErr := os.OpenFile(baseFileName+".ecj", os.O_RDONLY, 0644)
if openErr != nil {
return fmt.Errorf("cannot open ec index %s.ecx: %v", baseFileName, openErr)
}
defer ecjFile.Close()
buf := make([]byte, types.NeedleIdSize)
for {
n, err := ecjFile.Read(buf)
if n != types.NeedleIdSize {
if err == io.EOF {
return nil
}
return err
}
if processNeedleFn != nil {
err = processNeedleFn(types.BytesToNeedleId(buf))
}
if err != nil {
if err == io.EOF {
return nil
}
return err
}
}
}
// WriteDatFile generates .dat from from .ec00 ~ .ec09 files
func WriteDatFile(baseFileName string, datFileSize int64) error {
datFile, openErr := os.OpenFile(baseFileName+".dat", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if openErr != nil {
return fmt.Errorf("cannot write volume %s.dat: %v", baseFileName, openErr)
}
defer datFile.Close()
inputFiles := make([]*os.File, DataShardsCount)
for shardId := 0; shardId < DataShardsCount; shardId++ {
shardFileName := baseFileName + ToExt(shardId)
inputFiles[shardId], openErr = os.OpenFile(shardFileName, os.O_RDONLY, 0)
if openErr != nil {
return openErr
}
defer inputFiles[shardId].Close()
}
for datFileSize >= DataShardsCount*ErasureCodingLargeBlockSize {
for shardId := 0; shardId < DataShardsCount; shardId++ {
w, err := io.CopyN(datFile, inputFiles[shardId], ErasureCodingLargeBlockSize)
if w != ErasureCodingLargeBlockSize {
return fmt.Errorf("copy %s large block %d: %v", baseFileName, shardId, err)
}
datFileSize -= ErasureCodingLargeBlockSize
}
}
for datFileSize > 0 {
for shardId := 0; shardId < DataShardsCount; shardId++ {
toRead := min(datFileSize, ErasureCodingSmallBlockSize)
w, err := io.CopyN(datFile, inputFiles[shardId], toRead)
if w != toRead {
return fmt.Errorf("copy %s small block %d: %v", baseFileName, shardId, err)
}
datFileSize -= toRead
}
}
return nil
}
func min(x, y int64) int64 {
if x > y {
return y
}
return x
}

2
weed/storage/erasure_coding/ec_encoder.go

@ -49,7 +49,7 @@ func WriteSortedFileFromIdx(baseFileName string, ext string) (e error) {
return nil return nil
} }
// WriteEcFiles generates .ec01 ~ .ec14 files
// WriteEcFiles generates .ec00 ~ .ec13 files
func WriteEcFiles(baseFileName string) error { func WriteEcFiles(baseFileName string) error {
return generateEcFiles(baseFileName, 256*1024, ErasureCodingLargeBlockSize, ErasureCodingSmallBlockSize) return generateEcFiles(baseFileName, 256*1024, ErasureCodingLargeBlockSize, ErasureCodingSmallBlockSize)
} }

9
weed/storage/erasure_coding/ec_volume_info.go

@ -81,6 +81,15 @@ func (b ShardBits) ShardIds() (ret []ShardId) {
return return
} }
func (b ShardBits) ToUint32Slice() (ret []uint32) {
for i := uint32(0); i < TotalShardsCount; i++ {
if b.HasShardId(ShardId(i)) {
ret = append(ret, i)
}
}
return
}
func (b ShardBits) ShardIdCount() (count int) { func (b ShardBits) ShardIdCount() (count int) {
for count = 0; b > 0; count++ { for count = 0; b > 0; count++ {
b &= b - 1 b &= b - 1

9
weed/storage/store.go

@ -10,6 +10,7 @@ import (
"github.com/chrislusf/seaweedfs/weed/pb/master_pb" "github.com/chrislusf/seaweedfs/weed/pb/master_pb"
"github.com/chrislusf/seaweedfs/weed/stats" "github.com/chrislusf/seaweedfs/weed/stats"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
. "github.com/chrislusf/seaweedfs/weed/storage/types" . "github.com/chrislusf/seaweedfs/weed/storage/types"
) )
@ -61,7 +62,7 @@ func NewStore(grpcDialOption grpc.DialOption, port int, ip, publicUrl string, di
return return
} }
func (s *Store) AddVolume(volumeId needle.VolumeId, collection string, needleMapKind NeedleMapType, replicaPlacement string, ttlString string, preallocate int64, MemoryMapMaxSizeMb uint32) error { func (s *Store) AddVolume(volumeId needle.VolumeId, collection string, needleMapKind NeedleMapType, replicaPlacement string, ttlString string, preallocate int64, MemoryMapMaxSizeMb uint32) error {
rt, e := NewReplicaPlacementFromString(replicaPlacement)
rt, e := super_block.NewReplicaPlacementFromString(replicaPlacement)
if e != nil { if e != nil {
return e return e
} }
@ -102,7 +103,7 @@ func (s *Store) FindFreeLocation() (ret *DiskLocation) {
} }
return ret return ret
} }
func (s *Store) addVolume(vid needle.VolumeId, collection string, needleMapKind NeedleMapType, replicaPlacement *ReplicaPlacement, ttl *needle.TTL, preallocate int64, memoryMapMaxSizeMb uint32) error {
func (s *Store) addVolume(vid needle.VolumeId, collection string, needleMapKind NeedleMapType, replicaPlacement *super_block.ReplicaPlacement, ttl *needle.TTL, preallocate int64, memoryMapMaxSizeMb uint32) error {
if s.findVolume(vid) != nil { if s.findVolume(vid) != nil {
return fmt.Errorf("Volume Id %d already exists!", vid) return fmt.Errorf("Volume Id %d already exists!", vid)
} }
@ -229,7 +230,7 @@ func (s *Store) WriteVolumeNeedle(i needle.VolumeId, n *needle.Needle) (size uin
err = fmt.Errorf("volume %d is read only", i) err = fmt.Errorf("volume %d is read only", i)
return return
} }
if MaxPossibleVolumeSize >= v.ContentSize()+uint64(needle.GetActualSize(size, v.version)) {
if MaxPossibleVolumeSize >= v.ContentSize()+uint64(needle.GetActualSize(size, v.Version())) {
_, size, isUnchanged, err = v.writeNeedle(n) _, size, isUnchanged, err = v.writeNeedle(n)
} else { } else {
err = fmt.Errorf("volume size limit %d exceeded! current size is %d", s.GetVolumeSizeLimit(), v.ContentSize()) err = fmt.Errorf("volume size limit %d exceeded! current size is %d", s.GetVolumeSizeLimit(), v.ContentSize())
@ -246,7 +247,7 @@ func (s *Store) DeleteVolumeNeedle(i needle.VolumeId, n *needle.Needle) (uint32,
if v.noWriteOrDelete { if v.noWriteOrDelete {
return 0, fmt.Errorf("volume %d is read only", i) return 0, fmt.Errorf("volume %d is read only", i)
} }
if MaxPossibleVolumeSize >= v.ContentSize()+uint64(needle.GetActualSize(0, v.version)) {
if MaxPossibleVolumeSize >= v.ContentSize()+uint64(needle.GetActualSize(0, v.Version())) {
return v.deleteNeedle(n) return v.deleteNeedle(n)
} else { } else {
return 0, fmt.Errorf("volume size limit %d exceeded! current size is %d", s.GetVolumeSizeLimit(), v.ContentSize()) return 0, fmt.Errorf("volume size limit %d exceeded! current size is %d", s.GetVolumeSizeLimit(), v.ContentSize())

6
weed/storage/store_ec.go

@ -8,6 +8,8 @@ import (
"sync" "sync"
"time" "time"
"github.com/klauspost/reedsolomon"
"github.com/chrislusf/seaweedfs/weed/glog" "github.com/chrislusf/seaweedfs/weed/glog"
"github.com/chrislusf/seaweedfs/weed/operation" "github.com/chrislusf/seaweedfs/weed/operation"
"github.com/chrislusf/seaweedfs/weed/pb/master_pb" "github.com/chrislusf/seaweedfs/weed/pb/master_pb"
@ -15,8 +17,8 @@ import (
"github.com/chrislusf/seaweedfs/weed/stats" "github.com/chrislusf/seaweedfs/weed/stats"
"github.com/chrislusf/seaweedfs/weed/storage/erasure_coding" "github.com/chrislusf/seaweedfs/weed/storage/erasure_coding"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
"github.com/chrislusf/seaweedfs/weed/storage/types" "github.com/chrislusf/seaweedfs/weed/storage/types"
"github.com/klauspost/reedsolomon"
) )
func (s *Store) CollectErasureCodingHeartbeat() *master_pb.Heartbeat { func (s *Store) CollectErasureCodingHeartbeat() *master_pb.Heartbeat {
@ -169,7 +171,7 @@ func (s *Store) readEcVolumeVersion(ctx context.Context, vid needle.VolumeId, ec
interval := erasure_coding.Interval{ interval := erasure_coding.Interval{
BlockIndex: 0, BlockIndex: 0,
InnerBlockOffset: 0, InnerBlockOffset: 0,
Size: _SuperBlockSize,
Size: super_block.SuperBlockSize,
IsLargeBlock: true, // it could be large block, but ok in this place IsLargeBlock: true, // it could be large block, but ok in this place
LargeBlockRowsCount: 0, LargeBlockRowsCount: 0,
} }

2
weed/storage/replica_placement.go → weed/storage/super_block/replica_placement.go

@ -1,4 +1,4 @@
package storage
package super_block
import ( import (
"errors" "errors"

2
weed/storage/replica_placement_test.go → weed/storage/super_block/replica_placement_test.go

@ -1,4 +1,4 @@
package storage
package super_block
import ( import (
"testing" "testing"

69
weed/storage/super_block/super_block.go

@ -0,0 +1,69 @@
package super_block
import (
"github.com/golang/protobuf/proto"
"github.com/chrislusf/seaweedfs/weed/glog"
"github.com/chrislusf/seaweedfs/weed/pb/master_pb"
"github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/util"
)
const (
SuperBlockSize = 8
)
/*
* Super block currently has 8 bytes allocated for each volume.
* Byte 0: version, 1 or 2
* Byte 1: Replica Placement strategy, 000, 001, 002, 010, etc
* Byte 2 and byte 3: Time to live. See TTL for definition
* Byte 4 and byte 5: The number of times the volume has been compacted.
* Rest bytes: Reserved
*/
type SuperBlock struct {
Version needle.Version
ReplicaPlacement *ReplicaPlacement
Ttl *needle.TTL
CompactionRevision uint16
Extra *master_pb.SuperBlockExtra
ExtraSize uint16
}
func (s *SuperBlock) BlockSize() int {
switch s.Version {
case needle.Version2, needle.Version3:
return SuperBlockSize + int(s.ExtraSize)
}
return SuperBlockSize
}
func (s *SuperBlock) Bytes() []byte {
header := make([]byte, SuperBlockSize)
header[0] = byte(s.Version)
header[1] = s.ReplicaPlacement.Byte()
s.Ttl.ToBytes(header[2:4])
util.Uint16toBytes(header[4:6], s.CompactionRevision)
if s.Extra != nil {
extraData, err := proto.Marshal(s.Extra)
if err != nil {
glog.Fatalf("cannot marshal super block extra %+v: %v", s.Extra, err)
}
extraSize := len(extraData)
if extraSize > 256*256-2 {
// reserve a couple of bits for future extension
glog.Fatalf("super block extra size is %d bigger than %d", extraSize, 256*256-2)
}
s.ExtraSize = uint16(extraSize)
util.Uint16toBytes(header[6:8], s.ExtraSize)
header = append(header, extraData...)
}
return header
}
func (s *SuperBlock) Initialized() bool {
return s.ReplicaPlacement != nil && s.Ttl != nil
}

44
weed/storage/super_block/super_block_read.go.go

@ -0,0 +1,44 @@
package super_block
import (
"fmt"
"github.com/golang/protobuf/proto"
"github.com/chrislusf/seaweedfs/weed/pb/master_pb"
"github.com/chrislusf/seaweedfs/weed/storage/backend"
"github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/util"
)
// ReadSuperBlock reads from data file and load it into volume's super block
func ReadSuperBlock(datBackend backend.BackendStorageFile) (superBlock SuperBlock, err error) {
header := make([]byte, SuperBlockSize)
if _, e := datBackend.ReadAt(header, 0); e != nil {
err = fmt.Errorf("cannot read volume %s super block: %v", datBackend.Name(), e)
return
}
superBlock.Version = needle.Version(header[0])
if superBlock.ReplicaPlacement, err = NewReplicaPlacementFromByte(header[1]); err != nil {
err = fmt.Errorf("cannot read replica type: %s", err.Error())
return
}
superBlock.Ttl = needle.LoadTTLFromBytes(header[2:4])
superBlock.CompactionRevision = util.BytesToUint16(header[4:6])
superBlock.ExtraSize = util.BytesToUint16(header[6:8])
if superBlock.ExtraSize > 0 {
// read more
extraData := make([]byte, int(superBlock.ExtraSize))
superBlock.Extra = &master_pb.SuperBlockExtra{}
err = proto.Unmarshal(extraData, superBlock.Extra)
if err != nil {
err = fmt.Errorf("cannot read volume %s super block extra: %v", datBackend.Name(), err)
return
}
}
return
}

4
weed/storage/volume_super_block_test.go → weed/storage/super_block/super_block_test.go

@ -1,4 +1,4 @@
package storage
package super_block
import ( import (
"testing" "testing"
@ -10,7 +10,7 @@ func TestSuperBlockReadWrite(t *testing.T) {
rp, _ := NewReplicaPlacementFromByte(byte(001)) rp, _ := NewReplicaPlacementFromByte(byte(001))
ttl, _ := needle.ReadTTL("15d") ttl, _ := needle.ReadTTL("15d")
s := &SuperBlock{ s := &SuperBlock{
version: needle.CurrentVersion,
Version: needle.CurrentVersion,
ReplicaPlacement: rp, ReplicaPlacement: rp,
Ttl: ttl, Ttl: ttl,
} }

9
weed/storage/volume.go

@ -12,6 +12,7 @@ import (
"github.com/chrislusf/seaweedfs/weed/stats" "github.com/chrislusf/seaweedfs/weed/stats"
"github.com/chrislusf/seaweedfs/weed/storage/backend" "github.com/chrislusf/seaweedfs/weed/storage/backend"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
"github.com/chrislusf/seaweedfs/weed/storage/types" "github.com/chrislusf/seaweedfs/weed/storage/types"
"github.com/chrislusf/seaweedfs/weed/glog" "github.com/chrislusf/seaweedfs/weed/glog"
@ -28,7 +29,7 @@ type Volume struct {
noWriteCanDelete bool // if readonly, either noWriteOrDelete or noWriteCanDelete noWriteCanDelete bool // if readonly, either noWriteOrDelete or noWriteCanDelete
MemoryMapMaxSizeMb uint32 MemoryMapMaxSizeMb uint32
SuperBlock
super_block.SuperBlock
dataFileAccessLock sync.RWMutex dataFileAccessLock sync.RWMutex
lastModifiedTsSeconds uint64 //unix time in seconds lastModifiedTsSeconds uint64 //unix time in seconds
@ -42,10 +43,10 @@ type Volume struct {
volumeTierInfo *volume_server_pb.VolumeTierInfo volumeTierInfo *volume_server_pb.VolumeTierInfo
} }
func NewVolume(dirname string, collection string, id needle.VolumeId, needleMapKind NeedleMapType, replicaPlacement *ReplicaPlacement, ttl *needle.TTL, preallocate int64, memoryMapMaxSizeMb uint32) (v *Volume, e error) {
func NewVolume(dirname string, collection string, id needle.VolumeId, needleMapKind NeedleMapType, replicaPlacement *super_block.ReplicaPlacement, ttl *needle.TTL, preallocate int64, memoryMapMaxSizeMb uint32) (v *Volume, e error) {
// if replicaPlacement is nil, the superblock will be loaded from disk // if replicaPlacement is nil, the superblock will be loaded from disk
v = &Volume{dir: dirname, Collection: collection, Id: id, MemoryMapMaxSizeMb: memoryMapMaxSizeMb} v = &Volume{dir: dirname, Collection: collection, Id: id, MemoryMapMaxSizeMb: memoryMapMaxSizeMb}
v.SuperBlock = SuperBlock{ReplicaPlacement: replicaPlacement, Ttl: ttl}
v.SuperBlock = super_block.SuperBlock{ReplicaPlacement: replicaPlacement, Ttl: ttl}
v.needleMapKind = needleMapKind v.needleMapKind = needleMapKind
e = v.load(true, true, needleMapKind, preallocate) e = v.load(true, true, needleMapKind, preallocate)
return return
@ -68,7 +69,7 @@ func (v *Volume) FileName() (fileName string) {
} }
func (v *Volume) Version() needle.Version { func (v *Volume) Version() needle.Version {
return v.SuperBlock.Version()
return v.SuperBlock.Version
} }
func (v *Volume) FileStat() (datSize uint64, idxSize uint64, modTime time.Time) { func (v *Volume) FileStat() (datSize uint64, idxSize uint64, modTime time.Time) {

12
weed/storage/volume_backup.go

@ -6,12 +6,14 @@ import (
"io" "io"
"os" "os"
"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/idx" "github.com/chrislusf/seaweedfs/weed/storage/idx"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
. "github.com/chrislusf/seaweedfs/weed/storage/types" . "github.com/chrislusf/seaweedfs/weed/storage/types"
"google.golang.org/grpc"
) )
func (v *Volume) GetVolumeSyncStatus() *volume_server_pb.VolumeSyncStatusResponse { func (v *Volume) GetVolumeSyncStatus() *volume_server_pb.VolumeSyncStatusResponse {
@ -108,7 +110,7 @@ func (v *Volume) IncrementalBackup(volumeServer string, grpcDialOption grpc.Dial
} }
// add to needle map // add to needle map
return ScanVolumeFileFrom(v.version, v.DataBackend, int64(startFromOffset), &VolumeFileScanner4GenIdx{v: v})
return ScanVolumeFileFrom(v.Version(), v.DataBackend, int64(startFromOffset), &VolumeFileScanner4GenIdx{v: v})
} }
@ -154,11 +156,11 @@ func (v *Volume) locateLastAppendEntry() (Offset, error) {
func (v *Volume) readAppendAtNs(offset Offset) (uint64, error) { func (v *Volume) readAppendAtNs(offset Offset) (uint64, error) {
n, _, bodyLength, err := needle.ReadNeedleHeader(v.DataBackend, v.SuperBlock.version, offset.ToAcutalOffset())
n, _, bodyLength, err := needle.ReadNeedleHeader(v.DataBackend, v.SuperBlock.Version, offset.ToAcutalOffset())
if err != nil { if err != nil {
return 0, fmt.Errorf("ReadNeedleHeader: %v", err) return 0, fmt.Errorf("ReadNeedleHeader: %v", err)
} }
_, err = n.ReadNeedleBody(v.DataBackend, v.SuperBlock.version, offset.ToAcutalOffset()+int64(NeedleHeaderSize), bodyLength)
_, err = n.ReadNeedleBody(v.DataBackend, v.SuperBlock.Version, offset.ToAcutalOffset()+int64(NeedleHeaderSize), bodyLength)
if err != nil { if err != nil {
return 0, fmt.Errorf("ReadNeedleBody offset %d, bodyLength %d: %v", offset.ToAcutalOffset(), bodyLength, err) return 0, fmt.Errorf("ReadNeedleBody offset %d, bodyLength %d: %v", offset.ToAcutalOffset(), bodyLength, err)
} }
@ -244,7 +246,7 @@ type VolumeFileScanner4GenIdx struct {
v *Volume v *Volume
} }
func (scanner *VolumeFileScanner4GenIdx) VisitSuperBlock(superBlock SuperBlock) error {
func (scanner *VolumeFileScanner4GenIdx) VisitSuperBlock(superBlock super_block.SuperBlock) error {
return nil return nil
} }

7
weed/storage/volume_info.go

@ -6,12 +6,13 @@ import (
"github.com/chrislusf/seaweedfs/weed/pb/master_pb" "github.com/chrislusf/seaweedfs/weed/pb/master_pb"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
) )
type VolumeInfo struct { type VolumeInfo struct {
Id needle.VolumeId Id needle.VolumeId
Size uint64 Size uint64
ReplicaPlacement *ReplicaPlacement
ReplicaPlacement *super_block.ReplicaPlacement
Ttl *needle.TTL Ttl *needle.TTL
Collection string Collection string
Version needle.Version Version needle.Version
@ -40,7 +41,7 @@ func NewVolumeInfo(m *master_pb.VolumeInformationMessage) (vi VolumeInfo, err er
RemoteStorageName: m.RemoteStorageName, RemoteStorageName: m.RemoteStorageName,
RemoteStorageKey: m.RemoteStorageKey, RemoteStorageKey: m.RemoteStorageKey,
} }
rp, e := NewReplicaPlacementFromByte(byte(m.ReplicaPlacement))
rp, e := super_block.NewReplicaPlacementFromByte(byte(m.ReplicaPlacement))
if e != nil { if e != nil {
return vi, e return vi, e
} }
@ -55,7 +56,7 @@ func NewVolumeInfoFromShort(m *master_pb.VolumeShortInformationMessage) (vi Volu
Collection: m.Collection, Collection: m.Collection,
Version: needle.Version(m.Version), Version: needle.Version(m.Version),
} }
rp, e := NewReplicaPlacementFromByte(byte(m.ReplicaPlacement))
rp, e := super_block.NewReplicaPlacementFromByte(byte(m.ReplicaPlacement))
if e != nil { if e != nil {
return vi, e return vi, e
} }

5
weed/storage/volume_loading.go

@ -11,11 +11,12 @@ import (
"github.com/chrislusf/seaweedfs/weed/stats" "github.com/chrislusf/seaweedfs/weed/stats"
"github.com/chrislusf/seaweedfs/weed/storage/backend" "github.com/chrislusf/seaweedfs/weed/storage/backend"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
) )
func loadVolumeWithoutIndex(dirname string, collection string, id needle.VolumeId, needleMapKind NeedleMapType) (v *Volume, err error) { func loadVolumeWithoutIndex(dirname string, collection string, id needle.VolumeId, needleMapKind NeedleMapType) (v *Volume, err error) {
v = &Volume{dir: dirname, Collection: collection, Id: id} v = &Volume{dir: dirname, Collection: collection, Id: id}
v.SuperBlock = SuperBlock{}
v.SuperBlock = super_block.SuperBlock{}
v.needleMapKind = needleMapKind v.needleMapKind = needleMapKind
err = v.load(false, false, needleMapKind, 0) err = v.load(false, false, needleMapKind, 0)
return return
@ -43,7 +44,7 @@ func (v *Volume) load(alsoLoadIndex bool, createDatIfMissing bool, needleMapKind
v.noWriteOrDelete = true v.noWriteOrDelete = true
} }
v.lastModifiedTsSeconds = uint64(modifiedTime.Unix()) v.lastModifiedTsSeconds = uint64(modifiedTime.Unix())
if fileSize >= _SuperBlockSize {
if fileSize >= super_block.SuperBlockSize {
alreadyHasSuperBlock = true alreadyHasSuperBlock = true
} }
v.DataBackend = backend.NewDiskFile(dataFile) v.DataBackend = backend.NewDiskFile(dataFile)

3
weed/storage/volume_read_write.go

@ -11,6 +11,7 @@ import (
"github.com/chrislusf/seaweedfs/weed/glog" "github.com/chrislusf/seaweedfs/weed/glog"
"github.com/chrislusf/seaweedfs/weed/storage/backend" "github.com/chrislusf/seaweedfs/weed/storage/backend"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
. "github.com/chrislusf/seaweedfs/weed/storage/types" . "github.com/chrislusf/seaweedfs/weed/storage/types"
) )
@ -165,7 +166,7 @@ func (v *Volume) readNeedle(n *needle.Needle) (int, error) {
} }
type VolumeFileScanner interface { type VolumeFileScanner interface {
VisitSuperBlock(SuperBlock) error
VisitSuperBlock(super_block.SuperBlock) error
ReadNeedleBody() bool ReadNeedleBody() bool
VisitNeedle(n *needle.Needle, offset int64, needleHeader, needleBody []byte) error VisitNeedle(n *needle.Needle, offset int64, needleHeader, needleBody []byte) error
} }

103
weed/storage/volume_super_block.go

@ -1,79 +1,14 @@
package storage package storage
import ( import (
"fmt"
"os" "os"
"github.com/chrislusf/seaweedfs/weed/glog" "github.com/chrislusf/seaweedfs/weed/glog"
"github.com/chrislusf/seaweedfs/weed/pb/master_pb"
"github.com/chrislusf/seaweedfs/weed/storage/backend" "github.com/chrislusf/seaweedfs/weed/storage/backend"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/util"
"github.com/golang/protobuf/proto"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
) )
const (
_SuperBlockSize = 8
)
/*
* Super block currently has 8 bytes allocated for each volume.
* Byte 0: version, 1 or 2
* Byte 1: Replica Placement strategy, 000, 001, 002, 010, etc
* Byte 2 and byte 3: Time to live. See TTL for definition
* Byte 4 and byte 5: The number of times the volume has been compacted.
* Rest bytes: Reserved
*/
type SuperBlock struct {
version needle.Version
ReplicaPlacement *ReplicaPlacement
Ttl *needle.TTL
CompactionRevision uint16
Extra *master_pb.SuperBlockExtra
extraSize uint16
}
func (s *SuperBlock) BlockSize() int {
switch s.version {
case needle.Version2, needle.Version3:
return _SuperBlockSize + int(s.extraSize)
}
return _SuperBlockSize
}
func (s *SuperBlock) Version() needle.Version {
return s.version
}
func (s *SuperBlock) Bytes() []byte {
header := make([]byte, _SuperBlockSize)
header[0] = byte(s.version)
header[1] = s.ReplicaPlacement.Byte()
s.Ttl.ToBytes(header[2:4])
util.Uint16toBytes(header[4:6], s.CompactionRevision)
if s.Extra != nil {
extraData, err := proto.Marshal(s.Extra)
if err != nil {
glog.Fatalf("cannot marshal super block extra %+v: %v", s.Extra, err)
}
extraSize := len(extraData)
if extraSize > 256*256-2 {
// reserve a couple of bits for future extension
glog.Fatalf("super block extra size is %d bigger than %d", extraSize, 256*256-2)
}
s.extraSize = uint16(extraSize)
util.Uint16toBytes(header[6:8], s.extraSize)
header = append(header, extraData...)
}
return header
}
func (s *SuperBlock) Initialized() bool {
return s.ReplicaPlacement != nil && s.Ttl != nil
}
func (v *Volume) maybeWriteSuperBlock() error { func (v *Volume) maybeWriteSuperBlock() error {
datSize, _, e := v.DataBackend.GetStat() datSize, _, e := v.DataBackend.GetStat()
@ -82,7 +17,7 @@ func (v *Volume) maybeWriteSuperBlock() error {
return e return e
} }
if datSize == 0 { if datSize == 0 {
v.SuperBlock.version = needle.CurrentVersion
v.SuperBlock.Version = needle.CurrentVersion
_, e = v.DataBackend.WriteAt(v.SuperBlock.Bytes(), 0) _, e = v.DataBackend.WriteAt(v.SuperBlock.Bytes(), 0)
if e != nil && os.IsPermission(e) { if e != nil && os.IsPermission(e) {
//read-only, but zero length - recreate it! //read-only, but zero length - recreate it!
@ -100,38 +35,6 @@ func (v *Volume) maybeWriteSuperBlock() error {
} }
func (v *Volume) readSuperBlock() (err error) { func (v *Volume) readSuperBlock() (err error) {
v.SuperBlock, err = ReadSuperBlock(v.DataBackend)
v.SuperBlock, err = super_block.ReadSuperBlock(v.DataBackend)
return err return err
} }
// ReadSuperBlock reads from data file and load it into volume's super block
func ReadSuperBlock(datBackend backend.BackendStorageFile) (superBlock SuperBlock, err error) {
header := make([]byte, _SuperBlockSize)
if _, e := datBackend.ReadAt(header, 0); e != nil {
err = fmt.Errorf("cannot read volume %s super block: %v", datBackend.Name(), e)
return
}
superBlock.version = needle.Version(header[0])
if superBlock.ReplicaPlacement, err = NewReplicaPlacementFromByte(header[1]); err != nil {
err = fmt.Errorf("cannot read replica type: %s", err.Error())
return
}
superBlock.Ttl = needle.LoadTTLFromBytes(header[2:4])
superBlock.CompactionRevision = util.BytesToUint16(header[4:6])
superBlock.extraSize = util.BytesToUint16(header[6:8])
if superBlock.extraSize > 0 {
// read more
extraData := make([]byte, int(superBlock.extraSize))
superBlock.Extra = &master_pb.SuperBlockExtra{}
err = proto.Unmarshal(extraData, superBlock.Extra)
if err != nil {
err = fmt.Errorf("cannot read volume %s super block extra: %v", datBackend.Name(), err)
return
}
}
return
}

7
weed/storage/volume_vacuum.go

@ -11,6 +11,7 @@ import (
idx2 "github.com/chrislusf/seaweedfs/weed/storage/idx" idx2 "github.com/chrislusf/seaweedfs/weed/storage/idx"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/needle_map" "github.com/chrislusf/seaweedfs/weed/storage/needle_map"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
. "github.com/chrislusf/seaweedfs/weed/storage/types" . "github.com/chrislusf/seaweedfs/weed/storage/types"
"github.com/chrislusf/seaweedfs/weed/util" "github.com/chrislusf/seaweedfs/weed/util"
) )
@ -133,7 +134,7 @@ func (v *Volume) cleanupCompact() error {
} }
func fetchCompactRevisionFromDatFile(datBackend backend.BackendStorageFile) (compactRevision uint16, err error) { func fetchCompactRevisionFromDatFile(datBackend backend.BackendStorageFile) (compactRevision uint16, err error) {
superBlock, err := ReadSuperBlock(datBackend)
superBlock, err := super_block.ReadSuperBlock(datBackend)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -277,8 +278,8 @@ type VolumeFileScanner4Vacuum struct {
writeThrottler *util.WriteThrottler writeThrottler *util.WriteThrottler
} }
func (scanner *VolumeFileScanner4Vacuum) VisitSuperBlock(superBlock SuperBlock) error {
scanner.version = superBlock.Version()
func (scanner *VolumeFileScanner4Vacuum) VisitSuperBlock(superBlock super_block.SuperBlock) error {
scanner.version = superBlock.Version
superBlock.CompactionRevision++ superBlock.CompactionRevision++
_, err := scanner.dstBackend.WriteAt(superBlock.Bytes(), 0) _, err := scanner.dstBackend.WriteAt(superBlock.Bytes(), 0)
scanner.newOffset = int64(superBlock.BlockSize()) scanner.newOffset = int64(superBlock.BlockSize())

5
weed/storage/volume_vacuum_test.go

@ -8,6 +8,7 @@ import (
"time" "time"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
"github.com/chrislusf/seaweedfs/weed/storage/types" "github.com/chrislusf/seaweedfs/weed/storage/types"
) )
@ -46,7 +47,7 @@ func TestMakeDiff(t *testing.T) {
v := new(Volume) v := new(Volume)
//lastCompactIndexOffset value is the index file size before step 4 //lastCompactIndexOffset value is the index file size before step 4
v.lastCompactIndexOffset = 96 v.lastCompactIndexOffset = 96
v.SuperBlock.version = 0x2
v.SuperBlock.Version = 0x2
/* /*
err := v.makeupDiff( err := v.makeupDiff(
"/yourpath/1.cpd", "/yourpath/1.cpd",
@ -68,7 +69,7 @@ func TestCompaction(t *testing.T) {
} }
defer os.RemoveAll(dir) // clean up defer os.RemoveAll(dir) // clean up
v, err := NewVolume(dir, "", 1, NeedleMapInMemory, &ReplicaPlacement{}, &needle.TTL{}, 0, 0)
v, err := NewVolume(dir, "", 1, NeedleMapInMemory, &super_block.ReplicaPlacement{}, &needle.TTL{}, 0, 0)
if err != nil { if err != nil {
t.Fatalf("volume creation: %v", err) t.Fatalf("volume creation: %v", err)
} }

4
weed/topology/collection.go

@ -3,8 +3,8 @@ package topology
import ( import (
"fmt" "fmt"
"github.com/chrislusf/seaweedfs/weed/storage"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
"github.com/chrislusf/seaweedfs/weed/util" "github.com/chrislusf/seaweedfs/weed/util"
) )
@ -24,7 +24,7 @@ func (c *Collection) String() string {
return fmt.Sprintf("Name:%s, volumeSizeLimit:%d, storageType2VolumeLayout:%v", c.Name, c.volumeSizeLimit, c.storageType2VolumeLayout) return fmt.Sprintf("Name:%s, volumeSizeLimit:%d, storageType2VolumeLayout:%v", c.Name, c.volumeSizeLimit, c.storageType2VolumeLayout)
} }
func (c *Collection) GetOrCreateVolumeLayout(rp *storage.ReplicaPlacement, ttl *needle.TTL) *VolumeLayout {
func (c *Collection) GetOrCreateVolumeLayout(rp *super_block.ReplicaPlacement, ttl *needle.TTL) *VolumeLayout {
keyString := rp.String() keyString := rp.String()
if ttl != nil { if ttl != nil {
keyString += ttl.String() keyString += ttl.String()

4
weed/topology/topology.go

@ -7,11 +7,13 @@ import (
"sync" "sync"
"github.com/chrislusf/raft" "github.com/chrislusf/raft"
"github.com/chrislusf/seaweedfs/weed/glog" "github.com/chrislusf/seaweedfs/weed/glog"
"github.com/chrislusf/seaweedfs/weed/pb/master_pb" "github.com/chrislusf/seaweedfs/weed/pb/master_pb"
"github.com/chrislusf/seaweedfs/weed/sequence" "github.com/chrislusf/seaweedfs/weed/sequence"
"github.com/chrislusf/seaweedfs/weed/storage" "github.com/chrislusf/seaweedfs/weed/storage"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
"github.com/chrislusf/seaweedfs/weed/util" "github.com/chrislusf/seaweedfs/weed/util"
) )
@ -129,7 +131,7 @@ func (t *Topology) PickForWrite(count uint64, option *VolumeGrowOption) (string,
return needle.NewFileId(*vid, fileId, rand.Uint32()).String(), count, datanodes.Head(), nil return needle.NewFileId(*vid, fileId, rand.Uint32()).String(), count, datanodes.Head(), nil
} }
func (t *Topology) GetVolumeLayout(collectionName string, rp *storage.ReplicaPlacement, ttl *needle.TTL) *VolumeLayout {
func (t *Topology) GetVolumeLayout(collectionName string, rp *super_block.ReplicaPlacement, ttl *needle.TTL) *VolumeLayout {
return t.collectionMap.Get(collectionName, func() interface{} { return t.collectionMap.Get(collectionName, func() interface{} {
return NewCollection(collectionName, t.volumeSizeLimit) return NewCollection(collectionName, t.volumeSizeLimit)
}).(*Collection).GetOrCreateVolumeLayout(rp, ttl) }).(*Collection).GetOrCreateVolumeLayout(rp, ttl)

5
weed/topology/topology_test.go

@ -5,6 +5,7 @@ import (
"github.com/chrislusf/seaweedfs/weed/sequence" "github.com/chrislusf/seaweedfs/weed/sequence"
"github.com/chrislusf/seaweedfs/weed/storage" "github.com/chrislusf/seaweedfs/weed/storage"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
"testing" "testing"
) )
@ -94,7 +95,7 @@ func TestHandlingVolumeServerHeartbeat(t *testing.T) {
[]*master_pb.VolumeShortInformationMessage{newVolumeShortMessage}, []*master_pb.VolumeShortInformationMessage{newVolumeShortMessage},
nil, nil,
dn) dn)
rp, _ := storage.NewReplicaPlacementFromString("000")
rp, _ := super_block.NewReplicaPlacementFromString("000")
layout := topo.GetVolumeLayout("", rp, needle.EMPTY_TTL) layout := topo.GetVolumeLayout("", rp, needle.EMPTY_TTL)
assert(t, "writables after repeated add", len(layout.writables), volumeCount) assert(t, "writables after repeated add", len(layout.writables), volumeCount)
@ -154,7 +155,7 @@ func TestAddRemoveVolume(t *testing.T) {
DeletedByteCount: 45, DeletedByteCount: 45,
ReadOnly: false, ReadOnly: false,
Version: needle.CurrentVersion, Version: needle.CurrentVersion,
ReplicaPlacement: &storage.ReplicaPlacement{},
ReplicaPlacement: &super_block.ReplicaPlacement{},
Ttl: needle.EMPTY_TTL, Ttl: needle.EMPTY_TTL,
} }

4
weed/topology/volume_growth.go

@ -6,6 +6,8 @@ import (
"sync" "sync"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
"google.golang.org/grpc" "google.golang.org/grpc"
"github.com/chrislusf/seaweedfs/weed/glog" "github.com/chrislusf/seaweedfs/weed/glog"
@ -22,7 +24,7 @@ This package is created to resolve these replica placement issues:
type VolumeGrowOption struct { type VolumeGrowOption struct {
Collection string Collection string
ReplicaPlacement *storage.ReplicaPlacement
ReplicaPlacement *super_block.ReplicaPlacement
Ttl *needle.TTL Ttl *needle.TTL
Prealloacte int64 Prealloacte int64
DataCenter string DataCenter string

3
weed/topology/volume_growth_test.go

@ -8,6 +8,7 @@ import (
"github.com/chrislusf/seaweedfs/weed/sequence" "github.com/chrislusf/seaweedfs/weed/sequence"
"github.com/chrislusf/seaweedfs/weed/storage" "github.com/chrislusf/seaweedfs/weed/storage"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
) )
var topologyLayout = ` var topologyLayout = `
@ -113,7 +114,7 @@ func setup(topologyLayout string) *Topology {
func TestFindEmptySlotsForOneVolume(t *testing.T) { func TestFindEmptySlotsForOneVolume(t *testing.T) {
topo := setup(topologyLayout) topo := setup(topologyLayout)
vg := NewDefaultVolumeGrowth() vg := NewDefaultVolumeGrowth()
rp, _ := storage.NewReplicaPlacementFromString("002")
rp, _ := super_block.NewReplicaPlacementFromString("002")
volumeGrowOption := &VolumeGrowOption{ volumeGrowOption := &VolumeGrowOption{
Collection: "", Collection: "",
ReplicaPlacement: rp, ReplicaPlacement: rp,

5
weed/topology/volume_layout.go

@ -10,11 +10,12 @@ import (
"github.com/chrislusf/seaweedfs/weed/glog" "github.com/chrislusf/seaweedfs/weed/glog"
"github.com/chrislusf/seaweedfs/weed/storage" "github.com/chrislusf/seaweedfs/weed/storage"
"github.com/chrislusf/seaweedfs/weed/storage/needle" "github.com/chrislusf/seaweedfs/weed/storage/needle"
"github.com/chrislusf/seaweedfs/weed/storage/super_block"
) )
// mapping from volume to its locations, inverted from server to volume // mapping from volume to its locations, inverted from server to volume
type VolumeLayout struct { type VolumeLayout struct {
rp *storage.ReplicaPlacement
rp *super_block.ReplicaPlacement
ttl *needle.TTL ttl *needle.TTL
vid2location map[needle.VolumeId]*VolumeLocationList vid2location map[needle.VolumeId]*VolumeLocationList
writables []needle.VolumeId // transient array of writable volume id writables []needle.VolumeId // transient array of writable volume id
@ -30,7 +31,7 @@ type VolumeLayoutStats struct {
FileCount uint64 FileCount uint64
} }
func NewVolumeLayout(rp *storage.ReplicaPlacement, ttl *needle.TTL, volumeSizeLimit uint64) *VolumeLayout {
func NewVolumeLayout(rp *super_block.ReplicaPlacement, ttl *needle.TTL, volumeSizeLimit uint64) *VolumeLayout {
return &VolumeLayout{ return &VolumeLayout{
rp: rp, rp: rp,
ttl: ttl, ttl: ttl,

Loading…
Cancel
Save