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.

195 lines
6.0 KiB

  1. package replication
  2. import (
  3. "errors"
  4. "fmt"
  5. "math/rand"
  6. "code.google.com/p/weed-fs/weed/operation"
  7. "code.google.com/p/weed-fs/weed/storage"
  8. "code.google.com/p/weed-fs/weed/topology"
  9. "sync"
  10. )
  11. /*
  12. This package is created to resolve these replica placement issues:
  13. 1. growth factor for each replica level, e.g., add 10 volumes for 1 copy, 20 volumes for 2 copies, 30 volumes for 3 copies
  14. 2. in time of tight storage, how to reduce replica level
  15. 3. optimizing for hot data on faster disk, cold data on cheaper storage,
  16. 4. volume allocation for each bucket
  17. */
  18. type VolumeGrowth struct {
  19. copy1factor int
  20. copy2factor int
  21. copy3factor int
  22. copyAll int
  23. accessLock sync.Mutex
  24. }
  25. func NewDefaultVolumeGrowth() *VolumeGrowth {
  26. return &VolumeGrowth{copy1factor: 7, copy2factor: 6, copy3factor: 3}
  27. }
  28. func (vg *VolumeGrowth) GrowByType(repType storage.ReplicationType, topo *topology.Topology) (int, error) {
  29. switch repType {
  30. case storage.Copy000:
  31. return vg.GrowByCountAndType(vg.copy1factor, repType, topo)
  32. case storage.Copy001:
  33. return vg.GrowByCountAndType(vg.copy2factor, repType, topo)
  34. case storage.Copy010:
  35. return vg.GrowByCountAndType(vg.copy2factor, repType, topo)
  36. case storage.Copy100:
  37. return vg.GrowByCountAndType(vg.copy2factor, repType, topo)
  38. case storage.Copy110:
  39. return vg.GrowByCountAndType(vg.copy3factor, repType, topo)
  40. case storage.Copy200:
  41. return vg.GrowByCountAndType(vg.copy3factor, repType, topo)
  42. }
  43. return 0, errors.New("Unknown Replication Type!")
  44. }
  45. func (vg *VolumeGrowth) GrowByCountAndType(count int, repType storage.ReplicationType, topo *topology.Topology) (counter int, err error) {
  46. vg.accessLock.Lock()
  47. defer vg.accessLock.Unlock()
  48. counter = 0
  49. switch repType {
  50. case storage.Copy000:
  51. for i := 0; i < count; i++ {
  52. if ok, server, vid := topo.RandomlyReserveOneVolume(); ok {
  53. if err = vg.grow(topo, *vid, repType, server); err == nil {
  54. counter++
  55. }
  56. }
  57. }
  58. case storage.Copy001:
  59. for i := 0; i < count; i++ {
  60. //randomly pick one server, and then choose from the same rack
  61. if ok, server1, vid := topo.RandomlyReserveOneVolume(); ok {
  62. rack := server1.Parent()
  63. exclusion := make(map[string]topology.Node)
  64. exclusion[server1.String()] = server1
  65. newNodeList := topology.NewNodeList(rack.Children(), exclusion)
  66. if newNodeList.FreeSpace() > 0 {
  67. if ok2, server2 := newNodeList.ReserveOneVolume(rand.Intn(newNodeList.FreeSpace()), *vid); ok2 {
  68. if err = vg.grow(topo, *vid, repType, server1, server2); err == nil {
  69. counter++
  70. }
  71. }
  72. }
  73. }
  74. }
  75. case storage.Copy010:
  76. for i := 0; i < count; i++ {
  77. //randomly pick one server, and then choose from the same rack
  78. if ok, server1, vid := topo.RandomlyReserveOneVolume(); ok {
  79. rack := server1.Parent()
  80. dc := rack.Parent()
  81. exclusion := make(map[string]topology.Node)
  82. exclusion[rack.String()] = rack
  83. newNodeList := topology.NewNodeList(dc.Children(), exclusion)
  84. if newNodeList.FreeSpace() > 0 {
  85. if ok2, server2 := newNodeList.ReserveOneVolume(rand.Intn(newNodeList.FreeSpace()), *vid); ok2 {
  86. if err = vg.grow(topo, *vid, repType, server1, server2); err == nil {
  87. counter++
  88. }
  89. }
  90. }
  91. }
  92. }
  93. case storage.Copy100:
  94. for i := 0; i < count; i++ {
  95. nl := topology.NewNodeList(topo.Children(), nil)
  96. picked, ret := nl.RandomlyPickN(2, 1)
  97. vid := topo.NextVolumeId()
  98. if ret {
  99. var servers []*topology.DataNode
  100. for _, n := range picked {
  101. if n.FreeSpace() > 0 {
  102. if ok, server := n.ReserveOneVolume(rand.Intn(n.FreeSpace()), vid); ok {
  103. servers = append(servers, server)
  104. }
  105. }
  106. }
  107. if len(servers) == 2 {
  108. if err = vg.grow(topo, vid, repType, servers...); err == nil {
  109. counter++
  110. }
  111. }
  112. }
  113. }
  114. case storage.Copy110:
  115. for i := 0; i < count; i++ {
  116. nl := topology.NewNodeList(topo.Children(), nil)
  117. picked, ret := nl.RandomlyPickN(2, 2)
  118. vid := topo.NextVolumeId()
  119. if ret {
  120. var servers []*topology.DataNode
  121. dc1, dc2 := picked[0], picked[1]
  122. if dc2.FreeSpace() > dc1.FreeSpace() {
  123. dc1, dc2 = dc2, dc1
  124. }
  125. if dc1.FreeSpace() > 0 {
  126. if ok, server1 := dc1.ReserveOneVolume(rand.Intn(dc1.FreeSpace()), vid); ok {
  127. servers = append(servers, server1)
  128. rack := server1.Parent()
  129. exclusion := make(map[string]topology.Node)
  130. exclusion[rack.String()] = rack
  131. newNodeList := topology.NewNodeList(dc1.Children(), exclusion)
  132. if newNodeList.FreeSpace() > 0 {
  133. if ok2, server2 := newNodeList.ReserveOneVolume(rand.Intn(newNodeList.FreeSpace()), vid); ok2 {
  134. servers = append(servers, server2)
  135. }
  136. }
  137. }
  138. }
  139. if dc2.FreeSpace() > 0 {
  140. if ok, server := dc2.ReserveOneVolume(rand.Intn(dc2.FreeSpace()), vid); ok {
  141. servers = append(servers, server)
  142. }
  143. }
  144. if len(servers) == 3 {
  145. if err = vg.grow(topo, vid, repType, servers...); err == nil {
  146. counter++
  147. }
  148. }
  149. }
  150. }
  151. case storage.Copy200:
  152. for i := 0; i < count; i++ {
  153. nl := topology.NewNodeList(topo.Children(), nil)
  154. picked, ret := nl.RandomlyPickN(3, 1)
  155. vid := topo.NextVolumeId()
  156. if ret {
  157. var servers []*topology.DataNode
  158. for _, n := range picked {
  159. if n.FreeSpace() > 0 {
  160. if ok, server := n.ReserveOneVolume(rand.Intn(n.FreeSpace()), vid); ok {
  161. servers = append(servers, server)
  162. }
  163. }
  164. }
  165. if len(servers) == 3 {
  166. if err = vg.grow(topo, vid, repType, servers...); err == nil {
  167. counter++
  168. }
  169. }
  170. }
  171. }
  172. }
  173. return
  174. }
  175. func (vg *VolumeGrowth) grow(topo *topology.Topology, vid storage.VolumeId, repType storage.ReplicationType, servers ...*topology.DataNode) error {
  176. for _, server := range servers {
  177. if err := operation.AllocateVolume(server, vid, repType); err == nil {
  178. vi := storage.VolumeInfo{Id: vid, Size: 0, RepType: repType, Version: storage.CurrentVersion}
  179. server.AddOrUpdateVolume(vi)
  180. topo.RegisterVolumeLayout(&vi, server)
  181. fmt.Println("Created Volume", vid, "on", server)
  182. } else {
  183. fmt.Println("Failed to assign", vid, "to", servers)
  184. return errors.New("Failed to assign " + vid.String())
  185. }
  186. }
  187. return nil
  188. }