2019-05-22 05:41:20 +00:00
|
|
|
package erasure_coding
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2019-05-24 20:28:44 +00:00
|
|
|
"math"
|
2019-05-22 05:41:20 +00:00
|
|
|
"os"
|
|
|
|
"path"
|
2019-05-24 20:28:44 +00:00
|
|
|
"sort"
|
2019-05-22 05:41:20 +00:00
|
|
|
"strconv"
|
|
|
|
|
|
|
|
"github.com/chrislusf/seaweedfs/weed/pb/master_pb"
|
|
|
|
"github.com/chrislusf/seaweedfs/weed/storage/needle"
|
|
|
|
)
|
|
|
|
|
2019-05-23 05:44:28 +00:00
|
|
|
type ShardId uint8
|
|
|
|
|
2019-05-22 05:41:20 +00:00
|
|
|
type EcVolumeShard struct {
|
|
|
|
VolumeId needle.VolumeId
|
2019-05-23 05:44:28 +00:00
|
|
|
ShardId ShardId
|
2019-05-22 05:41:20 +00:00
|
|
|
Collection string
|
|
|
|
dir string
|
|
|
|
ecdFile *os.File
|
|
|
|
ecxFile *os.File
|
|
|
|
}
|
|
|
|
type EcVolumeShards []*EcVolumeShard
|
|
|
|
|
|
|
|
func NewEcVolumeShard(dirname string, collection string, id needle.VolumeId, shardId int) (v *EcVolumeShard, e error) {
|
|
|
|
|
2019-05-23 05:44:28 +00:00
|
|
|
v = &EcVolumeShard{dir: dirname, Collection: collection, VolumeId: id, ShardId: ShardId(shardId)}
|
2019-05-22 05:41:20 +00:00
|
|
|
|
|
|
|
baseFileName := v.FileName()
|
|
|
|
if v.ecxFile, e = os.OpenFile(baseFileName+".ecx", os.O_RDONLY, 0644); e != nil {
|
|
|
|
return nil, fmt.Errorf("cannot read ec volume index %s.ecx: %v", baseFileName, e)
|
|
|
|
}
|
|
|
|
if v.ecdFile, e = os.OpenFile(baseFileName+ToExt(shardId), os.O_RDONLY, 0644); e != nil {
|
|
|
|
return nil, fmt.Errorf("cannot read ec volume shard %s.%s: %v", baseFileName, ToExt(shardId), e)
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (shards *EcVolumeShards) AddEcVolumeShard(ecVolumeShard *EcVolumeShard) bool {
|
|
|
|
for _, s := range *shards {
|
|
|
|
if s.ShardId == ecVolumeShard.ShardId {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*shards = append(*shards, ecVolumeShard)
|
2019-05-24 20:28:44 +00:00
|
|
|
sort.Slice(shards, func(i, j int) bool {
|
|
|
|
return (*shards)[i].VolumeId < (*shards)[j].VolumeId ||
|
|
|
|
(*shards)[i].VolumeId == (*shards)[j].VolumeId && (*shards)[i].ShardId < (*shards)[j].ShardId
|
|
|
|
})
|
2019-05-22 05:41:20 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (shards *EcVolumeShards) DeleteEcVolumeShard(ecVolumeShard *EcVolumeShard) bool {
|
|
|
|
foundPosition := -1
|
|
|
|
for i, s := range *shards {
|
|
|
|
if s.ShardId == ecVolumeShard.ShardId {
|
|
|
|
foundPosition = i
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if foundPosition < 0 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
*shards = append((*shards)[:foundPosition], (*shards)[foundPosition+1:]...)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (shards *EcVolumeShards) Close() {
|
|
|
|
for _, s := range *shards {
|
|
|
|
s.Close()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-24 20:28:44 +00:00
|
|
|
func (shards *EcVolumeShards) ToVolumeEcShardInformationMessage() (messages []*master_pb.VolumeEcShardInformationMessage) {
|
|
|
|
prevVolumeId := needle.VolumeId(math.MaxUint32)
|
|
|
|
var m *master_pb.VolumeEcShardInformationMessage
|
2019-05-22 05:41:20 +00:00
|
|
|
for _, s := range *shards {
|
2019-05-24 20:28:44 +00:00
|
|
|
if s.VolumeId != prevVolumeId {
|
|
|
|
m = &master_pb.VolumeEcShardInformationMessage{
|
|
|
|
Id: uint32(s.VolumeId),
|
|
|
|
Collection: s.Collection,
|
|
|
|
}
|
|
|
|
messages = append(messages, m)
|
2019-05-22 05:41:20 +00:00
|
|
|
}
|
2019-05-24 20:28:44 +00:00
|
|
|
prevVolumeId = s.VolumeId
|
|
|
|
m.EcIndexBits = uint32(ShardBits(m.EcIndexBits).AddShardId(s.ShardId))
|
2019-05-22 05:41:20 +00:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (v *EcVolumeShard) String() string {
|
|
|
|
return fmt.Sprintf("ec shard %v:%v, dir:%s, Collection:%s", v.VolumeId, v.ShardId, v.dir, v.Collection)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (v *EcVolumeShard) FileName() (fileName string) {
|
|
|
|
return EcShardFileName(v.Collection, v.dir, int(v.VolumeId))
|
|
|
|
}
|
|
|
|
|
|
|
|
func EcShardFileName(collection string, dir string, id int) (fileName string) {
|
|
|
|
idString := strconv.Itoa(id)
|
|
|
|
if collection == "" {
|
|
|
|
fileName = path.Join(dir, idString)
|
|
|
|
} else {
|
|
|
|
fileName = path.Join(dir, collection+"_"+idString)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (v *EcVolumeShard) Close() {
|
|
|
|
if v.ecdFile != nil {
|
|
|
|
_ = v.ecdFile.Close()
|
|
|
|
v.ecdFile = nil
|
|
|
|
}
|
|
|
|
if v.ecxFile != nil {
|
|
|
|
_ = v.ecxFile.Close()
|
|
|
|
v.ecxFile = nil
|
|
|
|
}
|
|
|
|
}
|