disk_location_ec.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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) DestroyEcVolume(vid needle.VolumeId) {
  25. l.ecVolumesLock.Lock()
  26. defer l.ecVolumesLock.Unlock()
  27. ecVolume, found := l.ecVolumes[vid]
  28. if found {
  29. ecVolume.Destroy()
  30. delete(l.ecVolumes, vid)
  31. }
  32. }
  33. func (l *DiskLocation) FindEcShard(vid needle.VolumeId, shardId erasure_coding.ShardId) (*erasure_coding.EcVolumeShard, bool) {
  34. l.ecVolumesLock.RLock()
  35. defer l.ecVolumesLock.RUnlock()
  36. ecVolume, ok := l.ecVolumes[vid]
  37. if !ok {
  38. return nil, false
  39. }
  40. for _, ecShard := range ecVolume.Shards {
  41. if ecShard.ShardId == shardId {
  42. return ecShard, true
  43. }
  44. }
  45. return nil, false
  46. }
  47. func (l *DiskLocation) LoadEcShard(collection string, vid needle.VolumeId, shardId erasure_coding.ShardId) (err error) {
  48. ecVolumeShard, err := erasure_coding.NewEcVolumeShard(l.Directory, collection, vid, shardId)
  49. if err != nil {
  50. return fmt.Errorf("failed to create ec shard %d.%d: %v", vid, shardId, err)
  51. }
  52. l.ecVolumesLock.Lock()
  53. defer l.ecVolumesLock.Unlock()
  54. ecVolume, found := l.ecVolumes[vid]
  55. if !found {
  56. ecVolume, err = erasure_coding.NewEcVolume(l.Directory, collection, vid)
  57. if err != nil {
  58. return fmt.Errorf("failed to create ec volume %d: %v", vid, err)
  59. }
  60. l.ecVolumes[vid] = ecVolume
  61. }
  62. ecVolume.AddEcVolumeShard(ecVolumeShard)
  63. return nil
  64. }
  65. func (l *DiskLocation) UnloadEcShard(vid needle.VolumeId, shardId erasure_coding.ShardId) bool {
  66. l.ecVolumesLock.Lock()
  67. defer l.ecVolumesLock.Unlock()
  68. ecVolume, found := l.ecVolumes[vid]
  69. if !found {
  70. return false
  71. }
  72. if _, deleted := ecVolume.DeleteEcVolumeShard(shardId); deleted {
  73. if len(ecVolume.Shards) == 0 {
  74. delete(l.ecVolumes, vid)
  75. ecVolume.Close()
  76. }
  77. return true
  78. }
  79. return true
  80. }
  81. func (l *DiskLocation) loadEcShards(shards []string, collection string, vid needle.VolumeId) (err error) {
  82. for _, shard := range shards {
  83. shardId, err := strconv.ParseInt(path.Ext(shard)[3:], 10, 64)
  84. if err != nil {
  85. return fmt.Errorf("failed to parse ec shard name %v: %v", shard, err)
  86. }
  87. err = l.LoadEcShard(collection, vid, erasure_coding.ShardId(shardId))
  88. if err != nil {
  89. return fmt.Errorf("failed to load ec shard %v: %v", shard, err)
  90. }
  91. }
  92. return nil
  93. }
  94. func (l *DiskLocation) loadAllEcShards() (err error) {
  95. fileInfos, err := ioutil.ReadDir(l.Directory)
  96. if err != nil {
  97. return fmt.Errorf("load all ec shards in dir %s: %v", l.Directory, err)
  98. }
  99. sort.Slice(fileInfos, func(i, j int) bool {
  100. return fileInfos[i].Name() < fileInfos[j].Name()
  101. })
  102. var sameVolumeShards []string
  103. var prevVolumeId needle.VolumeId
  104. for _, fileInfo := range fileInfos {
  105. if fileInfo.IsDir() {
  106. continue
  107. }
  108. ext := path.Ext(fileInfo.Name())
  109. name := fileInfo.Name()
  110. baseName := name[:len(name)-len(ext)]
  111. collection, volumeId, err := parseCollectionVolumeId(baseName)
  112. if err != nil {
  113. continue
  114. }
  115. if re.MatchString(ext) {
  116. if prevVolumeId == 0 || volumeId == prevVolumeId {
  117. sameVolumeShards = append(sameVolumeShards, fileInfo.Name())
  118. } else {
  119. sameVolumeShards = []string{fileInfo.Name()}
  120. }
  121. prevVolumeId = volumeId
  122. continue
  123. }
  124. if ext == ".ecx" && volumeId == prevVolumeId {
  125. if err = l.loadEcShards(sameVolumeShards, collection, volumeId); err != nil {
  126. return fmt.Errorf("loadEcShards collection:%v volumeId:%d : %v", collection, volumeId, err)
  127. }
  128. prevVolumeId = volumeId
  129. continue
  130. }
  131. }
  132. return nil
  133. }
  134. func (l *DiskLocation) deleteEcVolumeById(vid needle.VolumeId) (e error) {
  135. ecVolume, ok := l.ecVolumes[vid]
  136. if !ok {
  137. return
  138. }
  139. ecVolume.Destroy()
  140. delete(l.ecVolumes, vid)
  141. return
  142. }