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.

210 lines
5.7 KiB

  1. package topology
  2. import (
  3. "errors"
  4. "math/rand"
  5. "sync"
  6. "github.com/chrislusf/weed-fs/go/glog"
  7. "github.com/chrislusf/weed-fs/go/storage"
  8. )
  9. // mapping from volume to its locations, inverted from server to volume
  10. type VolumeLayout struct {
  11. rp *storage.ReplicaPlacement
  12. ttl *storage.TTL
  13. vid2location map[storage.VolumeId]*VolumeLocationList
  14. writables []storage.VolumeId // transient array of writable volume id
  15. volumeSizeLimit uint64
  16. accessLock sync.Mutex
  17. }
  18. func NewVolumeLayout(rp *storage.ReplicaPlacement, ttl *storage.TTL, volumeSizeLimit uint64) *VolumeLayout {
  19. return &VolumeLayout{
  20. rp: rp,
  21. ttl: ttl,
  22. vid2location: make(map[storage.VolumeId]*VolumeLocationList),
  23. writables: *new([]storage.VolumeId),
  24. volumeSizeLimit: volumeSizeLimit,
  25. }
  26. }
  27. func (vl *VolumeLayout) RegisterVolume(v *storage.VolumeInfo, dn *DataNode) {
  28. vl.accessLock.Lock()
  29. defer vl.accessLock.Unlock()
  30. if _, ok := vl.vid2location[v.Id]; !ok {
  31. vl.vid2location[v.Id] = NewVolumeLocationList()
  32. }
  33. vl.vid2location[v.Id].Set(dn)
  34. glog.V(4).Infoln("volume", v.Id, "added to dn", dn, "len", vl.vid2location[v.Id].Length(), "copy", v.ReplicaPlacement.GetCopyCount())
  35. if vl.vid2location[v.Id].Length() == vl.rp.GetCopyCount() && vl.isWritable(v) {
  36. vl.AddToWritable(v.Id)
  37. } else {
  38. vl.removeFromWritable(v.Id)
  39. }
  40. }
  41. func (vl *VolumeLayout) UnRegisterVolume(v *storage.VolumeInfo, dn *DataNode) {
  42. vl.accessLock.Lock()
  43. defer vl.accessLock.Unlock()
  44. vl.removeFromWritable(v.Id)
  45. delete(vl.vid2location, v.Id)
  46. }
  47. func (vl *VolumeLayout) AddToWritable(vid storage.VolumeId) {
  48. for _, id := range vl.writables {
  49. if vid == id {
  50. return
  51. }
  52. }
  53. vl.writables = append(vl.writables, vid)
  54. }
  55. func (vl *VolumeLayout) isWritable(v *storage.VolumeInfo) bool {
  56. return uint64(v.Size) < vl.volumeSizeLimit &&
  57. v.Version == storage.CurrentVersion &&
  58. !v.ReadOnly
  59. }
  60. func (vl *VolumeLayout) Lookup(vid storage.VolumeId) []*DataNode {
  61. if location := vl.vid2location[vid]; location != nil {
  62. return location.list
  63. }
  64. return nil
  65. }
  66. func (vl *VolumeLayout) ListVolumeServers() (nodes []*DataNode) {
  67. for _, location := range vl.vid2location {
  68. nodes = append(nodes, location.list...)
  69. }
  70. return
  71. }
  72. func (vl *VolumeLayout) PickForWrite(count int, option *VolumeGrowOption) (*storage.VolumeId, int, *VolumeLocationList, error) {
  73. len_writers := len(vl.writables)
  74. if len_writers <= 0 {
  75. glog.V(0).Infoln("No more writable volumes!")
  76. return nil, 0, nil, errors.New("No more writable volumes!")
  77. }
  78. if option.DataCenter == "" {
  79. vid := vl.writables[rand.Intn(len_writers)]
  80. locationList := vl.vid2location[vid]
  81. if locationList != nil {
  82. return &vid, count, locationList, nil
  83. }
  84. return nil, 0, nil, errors.New("Strangely vid " + vid.String() + " is on no machine!")
  85. } else {
  86. var vid storage.VolumeId
  87. var locationList *VolumeLocationList
  88. counter := 0
  89. for _, v := range vl.writables {
  90. volumeLocationList := vl.vid2location[v]
  91. for _, dn := range volumeLocationList.list {
  92. if dn.GetDataCenter().Id() == NodeId(option.DataCenter) {
  93. if option.Rack != "" && dn.GetRack().Id() != NodeId(option.Rack) {
  94. continue
  95. }
  96. if option.DataNode != "" && dn.Id() != NodeId(option.DataNode) {
  97. continue
  98. }
  99. counter++
  100. if rand.Intn(counter) < 1 {
  101. vid, locationList = v, volumeLocationList
  102. }
  103. }
  104. }
  105. }
  106. return &vid, count, locationList, nil
  107. }
  108. }
  109. func (vl *VolumeLayout) GetActiveVolumeCount(option *VolumeGrowOption) int {
  110. if option.DataCenter == "" {
  111. return len(vl.writables)
  112. }
  113. counter := 0
  114. for _, v := range vl.writables {
  115. for _, dn := range vl.vid2location[v].list {
  116. if dn.GetDataCenter().Id() == NodeId(option.DataCenter) {
  117. if option.Rack != "" && dn.GetRack().Id() != NodeId(option.Rack) {
  118. continue
  119. }
  120. if option.DataNode != "" && dn.Id() != NodeId(option.DataNode) {
  121. continue
  122. }
  123. counter++
  124. }
  125. }
  126. }
  127. return counter
  128. }
  129. func (vl *VolumeLayout) removeFromWritable(vid storage.VolumeId) bool {
  130. toDeleteIndex := -1
  131. for k, id := range vl.writables {
  132. if id == vid {
  133. toDeleteIndex = k
  134. break
  135. }
  136. }
  137. if toDeleteIndex >= 0 {
  138. glog.V(0).Infoln("Volume", vid, "becomes unwritable")
  139. vl.writables = append(vl.writables[0:toDeleteIndex], vl.writables[toDeleteIndex+1:]...)
  140. return true
  141. }
  142. return false
  143. }
  144. func (vl *VolumeLayout) setVolumeWritable(vid storage.VolumeId) bool {
  145. for _, v := range vl.writables {
  146. if v == vid {
  147. return false
  148. }
  149. }
  150. glog.V(0).Infoln("Volume", vid, "becomes writable")
  151. vl.writables = append(vl.writables, vid)
  152. return true
  153. }
  154. func (vl *VolumeLayout) SetVolumeUnavailable(dn *DataNode, vid storage.VolumeId) bool {
  155. vl.accessLock.Lock()
  156. defer vl.accessLock.Unlock()
  157. if location, ok := vl.vid2location[vid]; ok {
  158. if location.Remove(dn) {
  159. if location.Length() < vl.rp.GetCopyCount() {
  160. glog.V(0).Infoln("Volume", vid, "has", location.Length(), "replica, less than required", vl.rp.GetCopyCount())
  161. return vl.removeFromWritable(vid)
  162. }
  163. }
  164. }
  165. return false
  166. }
  167. func (vl *VolumeLayout) SetVolumeAvailable(dn *DataNode, vid storage.VolumeId) bool {
  168. vl.accessLock.Lock()
  169. defer vl.accessLock.Unlock()
  170. vl.vid2location[vid].Set(dn)
  171. if vl.vid2location[vid].Length() >= vl.rp.GetCopyCount() {
  172. return vl.setVolumeWritable(vid)
  173. }
  174. return false
  175. }
  176. func (vl *VolumeLayout) SetVolumeCapacityFull(vid storage.VolumeId) bool {
  177. vl.accessLock.Lock()
  178. defer vl.accessLock.Unlock()
  179. // glog.V(0).Infoln("Volume", vid, "reaches full capacity.")
  180. return vl.removeFromWritable(vid)
  181. }
  182. func (vl *VolumeLayout) ToMap() map[string]interface{} {
  183. m := make(map[string]interface{})
  184. m["replication"] = vl.rp.String()
  185. m["ttl"] = vl.ttl.String()
  186. m["writables"] = vl.writables
  187. //m["locations"] = vl.vid2location
  188. return m
  189. }