You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

150 lines
3.5 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. package storage
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "path"
  6. "regexp"
  7. "sort"
  8. "strconv"
  9. "github.com/chrislusf/seaweedfs/weed/storage/erasure_coding"
  10. "github.com/chrislusf/seaweedfs/weed/storage/needle"
  11. )
  12. var (
  13. re = regexp.MustCompile("\\.ec[0-9][0-9]")
  14. )
  15. func (l *DiskLocation) FindEcVolume(vid needle.VolumeId) (*erasure_coding.EcVolume, bool) {
  16. l.ecVolumesLock.RLock()
  17. defer l.ecVolumesLock.RUnlock()
  18. ecVolume, ok := l.ecVolumes[vid]
  19. if ok {
  20. return ecVolume, true
  21. }
  22. return nil, false
  23. }
  24. func (l *DiskLocation) FindEcShard(vid needle.VolumeId, shardId erasure_coding.ShardId) (*erasure_coding.EcVolumeShard, bool) {
  25. l.ecVolumesLock.RLock()
  26. defer l.ecVolumesLock.RUnlock()
  27. ecVolume, ok := l.ecVolumes[vid]
  28. if !ok {
  29. return nil, false
  30. }
  31. for _, ecShard := range ecVolume.Shards {
  32. if ecShard.ShardId == shardId {
  33. return ecShard, true
  34. }
  35. }
  36. return nil, false
  37. }
  38. func (l *DiskLocation) LoadEcShard(collection string, vid needle.VolumeId, shardId erasure_coding.ShardId) (err error) {
  39. ecVolumeShard, err := erasure_coding.NewEcVolumeShard(l.Directory, collection, vid, shardId)
  40. if err != nil {
  41. return fmt.Errorf("failed to create ec shard %d.%d: %v", vid, shardId, err)
  42. }
  43. l.ecVolumesLock.Lock()
  44. ecVolume, found := l.ecVolumes[vid]
  45. if !found {
  46. ecVolume, err = erasure_coding.NewEcVolume(l.Directory, collection, vid)
  47. if err != nil {
  48. return fmt.Errorf("failed to create ec volume %d: %v", vid, err)
  49. }
  50. l.ecVolumes[vid] = ecVolume
  51. }
  52. ecVolume.AddEcVolumeShard(ecVolumeShard)
  53. l.ecVolumesLock.Unlock()
  54. return nil
  55. }
  56. func (l *DiskLocation) UnloadEcShard(vid needle.VolumeId, shardId erasure_coding.ShardId) bool {
  57. l.ecVolumesLock.Lock()
  58. defer l.ecVolumesLock.Unlock()
  59. ecVolume, found := l.ecVolumes[vid]
  60. if !found {
  61. return false
  62. }
  63. if deleted := ecVolume.DeleteEcVolumeShard(shardId); deleted {
  64. if len(ecVolume.Shards) == 0 {
  65. delete(l.ecVolumes, vid)
  66. }
  67. ecVolume.Close()
  68. return true
  69. }
  70. return true
  71. }
  72. func (l *DiskLocation) loadEcShards(shards []string, collection string, vid needle.VolumeId) (err error) {
  73. for _, shard := range shards {
  74. shardId, err := strconv.ParseInt(path.Ext(shard)[3:], 10, 64)
  75. if err != nil {
  76. return fmt.Errorf("failed to parse ec shard name %v: %v", shard, err)
  77. }
  78. err = l.LoadEcShard(collection, vid, erasure_coding.ShardId(shardId))
  79. if err != nil {
  80. return fmt.Errorf("failed to load ec shard %v: %v", shard, err)
  81. }
  82. }
  83. return nil
  84. }
  85. func (l *DiskLocation) loadAllEcShards() (err error) {
  86. fileInfos, err := ioutil.ReadDir(l.Directory)
  87. if err != nil {
  88. return fmt.Errorf("load all ec shards in dir %s: %v", l.Directory, err)
  89. }
  90. sort.Slice(fileInfos, func(i, j int) bool {
  91. return fileInfos[i].Name() < fileInfos[j].Name()
  92. })
  93. var sameVolumeShards []string
  94. var prevVolumeId needle.VolumeId
  95. for _, fileInfo := range fileInfos {
  96. if fileInfo.IsDir() {
  97. continue
  98. }
  99. ext := path.Ext(fileInfo.Name())
  100. name := fileInfo.Name()
  101. baseName := name[:len(name)-len(ext)]
  102. collection, volumeId, err := parseCollectionVolumeId(baseName)
  103. if err != nil {
  104. continue
  105. }
  106. if re.MatchString(ext) {
  107. if prevVolumeId == 0 || volumeId == prevVolumeId {
  108. sameVolumeShards = append(sameVolumeShards, fileInfo.Name())
  109. } else {
  110. sameVolumeShards = []string{fileInfo.Name()}
  111. }
  112. prevVolumeId = volumeId
  113. continue
  114. }
  115. if ext == ".ecx" && volumeId == prevVolumeId {
  116. if err = l.loadEcShards(sameVolumeShards, collection, volumeId); err != nil {
  117. return fmt.Errorf("loadEcShards collection:%v volumeId:%d : %v", collection, volumeId, err)
  118. }
  119. prevVolumeId = volumeId
  120. continue
  121. }
  122. }
  123. return nil
  124. }