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.

275 lines
6.9 KiB

  1. package topology
  2. import (
  3. "fmt"
  4. "github.com/chrislusf/seaweedfs/weed/storage/types"
  5. "github.com/chrislusf/seaweedfs/weed/util"
  6. "sync"
  7. "github.com/chrislusf/seaweedfs/weed/pb/master_pb"
  8. "github.com/chrislusf/seaweedfs/weed/storage/erasure_coding"
  9. "github.com/chrislusf/seaweedfs/weed/storage/needle"
  10. "github.com/chrislusf/seaweedfs/weed/storage"
  11. )
  12. type Disk struct {
  13. NodeImpl
  14. volumes map[needle.VolumeId]storage.VolumeInfo
  15. ecShards map[needle.VolumeId]*erasure_coding.EcVolumeInfo
  16. ecShardsLock sync.RWMutex
  17. }
  18. func NewDisk(diskType string) *Disk {
  19. s := &Disk{}
  20. s.id = NodeId(diskType)
  21. s.nodeType = "Disk"
  22. s.diskUsages = newDiskUsages()
  23. s.volumes = make(map[needle.VolumeId]storage.VolumeInfo, 2)
  24. s.ecShards = make(map[needle.VolumeId]*erasure_coding.EcVolumeInfo, 2)
  25. s.NodeImpl.value = s
  26. return s
  27. }
  28. type DiskUsages struct {
  29. sync.RWMutex
  30. usages map[types.DiskType]*DiskUsageCounts
  31. }
  32. func newDiskUsages() *DiskUsages {
  33. return &DiskUsages{
  34. usages: make(map[types.DiskType]*DiskUsageCounts),
  35. }
  36. }
  37. func (d *DiskUsages) negative() (*DiskUsages) {
  38. d.RLock()
  39. defer d.RUnlock()
  40. t := newDiskUsages()
  41. for diskType, b := range d.usages {
  42. a := t.getOrCreateDisk(diskType)
  43. a.volumeCount = - b.volumeCount
  44. a.remoteVolumeCount = - b.remoteVolumeCount
  45. a.activeVolumeCount = - b.activeVolumeCount
  46. a.ecShardCount = - b.ecShardCount
  47. a.maxVolumeCount = - b.maxVolumeCount
  48. }
  49. return t
  50. }
  51. func (d *DiskUsages) ToMap() interface{} {
  52. d.RLock()
  53. defer d.RUnlock()
  54. ret := make(map[string]interface{})
  55. for diskType, diskUsage := range d.usages {
  56. ret[types.DiskType(diskType).String()] = diskUsage.ToMap()
  57. }
  58. return ret
  59. }
  60. func (d *DiskUsages) FreeSpace() (freeSpace int64) {
  61. d.RLock()
  62. defer d.RUnlock()
  63. for _, diskUsage := range d.usages {
  64. freeSpace += diskUsage.FreeSpace()
  65. }
  66. return
  67. }
  68. func (d *DiskUsages) GetMaxVolumeCount() (maxVolumeCount int64) {
  69. d.RLock()
  70. defer d.RUnlock()
  71. for _, diskUsage := range d.usages {
  72. maxVolumeCount += diskUsage.maxVolumeCount
  73. }
  74. return
  75. }
  76. type DiskUsageCounts struct {
  77. volumeCount int64
  78. remoteVolumeCount int64
  79. activeVolumeCount int64
  80. ecShardCount int64
  81. maxVolumeCount int64
  82. }
  83. func (a *DiskUsageCounts) addDiskUsageCounts(b *DiskUsageCounts) {
  84. a.volumeCount += b.volumeCount
  85. a.remoteVolumeCount += b.remoteVolumeCount
  86. a.activeVolumeCount += b.activeVolumeCount
  87. a.ecShardCount += b.ecShardCount
  88. a.maxVolumeCount += b.maxVolumeCount
  89. }
  90. func (a *DiskUsageCounts) FreeSpace() int64 {
  91. freeVolumeSlotCount := a.maxVolumeCount + a.remoteVolumeCount - a.volumeCount
  92. if a.ecShardCount > 0 {
  93. freeVolumeSlotCount = freeVolumeSlotCount - a.ecShardCount/erasure_coding.DataShardsCount - 1
  94. }
  95. return freeVolumeSlotCount
  96. }
  97. func (a *DiskUsageCounts) minus(b *DiskUsageCounts) (*DiskUsageCounts) {
  98. return &DiskUsageCounts{
  99. volumeCount: a.volumeCount - b.volumeCount,
  100. remoteVolumeCount: a.remoteVolumeCount - b.remoteVolumeCount,
  101. activeVolumeCount: a.activeVolumeCount - b.activeVolumeCount,
  102. ecShardCount: a.ecShardCount - b.ecShardCount,
  103. maxVolumeCount: a.maxVolumeCount - b.maxVolumeCount,
  104. }
  105. }
  106. func (diskUsage *DiskUsageCounts) ToMap() interface{} {
  107. ret := make(map[string]interface{})
  108. ret["Volumes"] = diskUsage.volumeCount
  109. ret["EcShards"] = diskUsage.ecShardCount
  110. ret["Max"] = diskUsage.maxVolumeCount
  111. ret["Free"] = diskUsage.FreeSpace()
  112. return ret
  113. }
  114. func (du *DiskUsages) getOrCreateDisk(diskType types.DiskType) *DiskUsageCounts {
  115. du.Lock()
  116. defer du.Unlock()
  117. t, found := du.usages[diskType]
  118. if found {
  119. return t
  120. }
  121. t = &DiskUsageCounts{}
  122. du.usages[diskType] = t
  123. return t
  124. }
  125. func (d *Disk) String() string {
  126. d.RLock()
  127. defer d.RUnlock()
  128. return fmt.Sprintf("Disk:%s, volumes:%v, ecShards:%v, Port:%d, PublicUrl:%s", d.NodeImpl.String(), d.volumes, d.ecShards)
  129. }
  130. func (d *Disk) AddOrUpdateVolume(v storage.VolumeInfo) (isNew, isChangedRO bool) {
  131. d.Lock()
  132. defer d.Unlock()
  133. return d.doAddOrUpdateVolume(v)
  134. }
  135. func (d *Disk) doAddOrUpdateVolume(v storage.VolumeInfo) (isNew, isChangedRO bool) {
  136. deltaDiskUsages := newDiskUsages()
  137. deltaDiskUsage := deltaDiskUsages.getOrCreateDisk(types.DiskType(v.DiskType))
  138. if oldV, ok := d.volumes[v.Id]; !ok {
  139. d.volumes[v.Id] = v
  140. deltaDiskUsage.volumeCount = 1
  141. if v.IsRemote() {
  142. deltaDiskUsage.remoteVolumeCount = 1
  143. }
  144. if !v.ReadOnly {
  145. deltaDiskUsage.activeVolumeCount = 1
  146. }
  147. d.UpAdjustMaxVolumeId(v.Id)
  148. d.UpAdjustDiskUsageDelta(deltaDiskUsages)
  149. isNew = true
  150. } else {
  151. if oldV.IsRemote() != v.IsRemote() {
  152. if v.IsRemote() {
  153. deltaDiskUsage.remoteVolumeCount = 1
  154. }
  155. if oldV.IsRemote() {
  156. deltaDiskUsage.remoteVolumeCount = -1
  157. }
  158. d.UpAdjustDiskUsageDelta(deltaDiskUsages)
  159. }
  160. isChangedRO = d.volumes[v.Id].ReadOnly != v.ReadOnly
  161. d.volumes[v.Id] = v
  162. }
  163. return
  164. }
  165. func (d *Disk) GetVolumes() (ret []storage.VolumeInfo) {
  166. d.RLock()
  167. for _, v := range d.volumes {
  168. ret = append(ret, v)
  169. }
  170. d.RUnlock()
  171. return ret
  172. }
  173. func (d *Disk) GetVolumesById(id needle.VolumeId) (storage.VolumeInfo, error) {
  174. d.RLock()
  175. defer d.RUnlock()
  176. vInfo, ok := d.volumes[id]
  177. if ok {
  178. return vInfo, nil
  179. } else {
  180. return storage.VolumeInfo{}, fmt.Errorf("volumeInfo not found")
  181. }
  182. }
  183. func (d *Disk) GetDataCenter() *DataCenter {
  184. dn := d.Parent()
  185. rack := dn.Parent()
  186. dcNode := rack.Parent()
  187. dcValue := dcNode.GetValue()
  188. return dcValue.(*DataCenter)
  189. }
  190. func (d *Disk) GetRack() *Rack {
  191. return d.Parent().Parent().(*NodeImpl).value.(*Rack)
  192. }
  193. func (d *Disk) GetTopology() *Topology {
  194. p := d.Parent()
  195. for p.Parent() != nil {
  196. p = p.Parent()
  197. }
  198. t := p.(*Topology)
  199. return t
  200. }
  201. func (d *Disk) ToMap() interface{} {
  202. ret := make(map[string]interface{})
  203. diskUsage := d.diskUsages.getOrCreateDisk(types.DiskType(d.Id()))
  204. ret["Volumes"] = diskUsage.volumeCount
  205. ret["VolumeIds"] = d.GetVolumeIds()
  206. ret["EcShards"] = diskUsage.ecShardCount
  207. ret["Max"] = diskUsage.maxVolumeCount
  208. ret["Free"] = d.FreeSpace()
  209. return ret
  210. }
  211. func (d *Disk) FreeSpace() int64 {
  212. t := d.diskUsages.getOrCreateDisk(types.DiskType(d.Id()))
  213. return t.FreeSpace()
  214. }
  215. func (d *Disk) ToDiskInfo() *master_pb.DiskInfo {
  216. diskUsage := d.diskUsages.getOrCreateDisk(types.DiskType(d.Id()))
  217. m := &master_pb.DiskInfo{
  218. Type: string(d.Id()),
  219. VolumeCount: uint64(diskUsage.volumeCount),
  220. MaxVolumeCount: uint64(diskUsage.maxVolumeCount),
  221. FreeVolumeCount: uint64(d.FreeSpace()),
  222. ActiveVolumeCount: uint64(diskUsage.activeVolumeCount),
  223. RemoteVolumeCount: uint64(diskUsage.remoteVolumeCount),
  224. }
  225. for _, v := range d.GetVolumes() {
  226. m.VolumeInfos = append(m.VolumeInfos, v.ToVolumeInformationMessage())
  227. }
  228. for _, ecv := range d.GetEcShards() {
  229. m.EcShardInfos = append(m.EcShardInfos, ecv.ToVolumeEcShardInformationMessage())
  230. }
  231. return m
  232. }
  233. // GetVolumeIds returns the human readable volume ids limited to count of max 100.
  234. func (d *Disk) GetVolumeIds() string {
  235. d.RLock()
  236. defer d.RUnlock()
  237. ids := make([]int, 0, len(d.volumes))
  238. for k := range d.volumes {
  239. ids = append(ids, int(k))
  240. }
  241. return util.HumanReadableIntsMax(100, ids...)
  242. }