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.

203 lines
6.6 KiB

  1. package replication
  2. import (
  3. "code.google.com/p/weed-fs/go/operation"
  4. "code.google.com/p/weed-fs/go/storage"
  5. "code.google.com/p/weed-fs/go/topology"
  6. "errors"
  7. "fmt"
  8. "math/rand"
  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, dataCenter string, topo *topology.Topology) (int, error) {
  29. switch repType {
  30. case storage.Copy000:
  31. return vg.GrowByCountAndType(vg.copy1factor, repType, dataCenter, topo)
  32. case storage.Copy001:
  33. return vg.GrowByCountAndType(vg.copy2factor, repType, dataCenter, topo)
  34. case storage.Copy010:
  35. return vg.GrowByCountAndType(vg.copy2factor, repType, dataCenter, topo)
  36. case storage.Copy100:
  37. return vg.GrowByCountAndType(vg.copy2factor, repType, dataCenter, topo)
  38. case storage.Copy110:
  39. return vg.GrowByCountAndType(vg.copy3factor, repType, dataCenter, topo)
  40. case storage.Copy200:
  41. return vg.GrowByCountAndType(vg.copy3factor, repType, dataCenter, topo)
  42. }
  43. return 0, errors.New("Unknown Replication Type!")
  44. }
  45. func (vg *VolumeGrowth) GrowByCountAndType(count int, repType storage.ReplicationType, dataCenter string, 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(dataCenter); ok {
  53. if err = vg.grow(topo, *vid, repType, server); err == nil {
  54. counter++
  55. } else {
  56. return counter, err
  57. }
  58. } else {
  59. return counter, fmt.Errorf("Failed to grown volume for data center %s", dataCenter)
  60. }
  61. }
  62. case storage.Copy001:
  63. for i := 0; i < count; i++ {
  64. //randomly pick one server from the datacenter, and then choose from the same rack
  65. if ok, server1, vid := topo.RandomlyReserveOneVolume(dataCenter); ok {
  66. rack := server1.Parent()
  67. exclusion := make(map[string]topology.Node)
  68. exclusion[server1.String()] = server1
  69. newNodeList := topology.NewNodeList(rack.Children(), exclusion)
  70. if newNodeList.FreeSpace() > 0 {
  71. if ok2, server2 := newNodeList.ReserveOneVolume(rand.Intn(newNodeList.FreeSpace()), *vid); ok2 {
  72. if err = vg.grow(topo, *vid, repType, server1, server2); err == nil {
  73. counter++
  74. }
  75. }
  76. }
  77. }
  78. }
  79. case storage.Copy010:
  80. for i := 0; i < count; i++ {
  81. //randomly pick one server from the datacenter, and then choose from the a different rack
  82. if ok, server1, vid := topo.RandomlyReserveOneVolume(dataCenter); ok {
  83. rack := server1.Parent()
  84. dc := rack.Parent()
  85. exclusion := make(map[string]topology.Node)
  86. exclusion[rack.String()] = rack
  87. newNodeList := topology.NewNodeList(dc.Children(), exclusion)
  88. if newNodeList.FreeSpace() > 0 {
  89. if ok2, server2 := newNodeList.ReserveOneVolume(rand.Intn(newNodeList.FreeSpace()), *vid); ok2 {
  90. if err = vg.grow(topo, *vid, repType, server1, server2); err == nil {
  91. counter++
  92. }
  93. }
  94. }
  95. }
  96. }
  97. case storage.Copy100:
  98. for i := 0; i < count; i++ {
  99. nl := topology.NewNodeList(topo.Children(), nil)
  100. picked, ret := nl.RandomlyPickN(2, 1, dataCenter)
  101. vid := topo.NextVolumeId()
  102. println("growing on picked servers", picked)
  103. if ret {
  104. var servers []*topology.DataNode
  105. for _, n := range picked {
  106. if n.FreeSpace() > 0 {
  107. if ok, server := n.ReserveOneVolume(rand.Intn(n.FreeSpace()), vid, ""); ok {
  108. servers = append(servers, server)
  109. }
  110. }
  111. }
  112. println("growing on servers", servers)
  113. if len(servers) == 2 {
  114. if err = vg.grow(topo, vid, repType, servers...); err == nil {
  115. counter++
  116. }
  117. }
  118. } else {
  119. return counter, fmt.Errorf("Failed to grown volume on data center %s and another data center", dataCenter)
  120. }
  121. }
  122. case storage.Copy110:
  123. for i := 0; i < count; i++ {
  124. nl := topology.NewNodeList(topo.Children(), nil)
  125. picked, ret := nl.RandomlyPickN(2, 2, dataCenter)
  126. vid := topo.NextVolumeId()
  127. if ret {
  128. var servers []*topology.DataNode
  129. dc1, dc2 := picked[0], picked[1]
  130. if dc2.FreeSpace() > dc1.FreeSpace() {
  131. dc1, dc2 = dc2, dc1
  132. }
  133. if dc1.FreeSpace() > 0 {
  134. if ok, server1 := dc1.ReserveOneVolume(rand.Intn(dc1.FreeSpace()), vid, ""); ok {
  135. servers = append(servers, server1)
  136. rack := server1.Parent()
  137. exclusion := make(map[string]topology.Node)
  138. exclusion[rack.String()] = rack
  139. newNodeList := topology.NewNodeList(dc1.Children(), exclusion)
  140. if newNodeList.FreeSpace() > 0 {
  141. if ok2, server2 := newNodeList.ReserveOneVolume(rand.Intn(newNodeList.FreeSpace()), vid); ok2 {
  142. servers = append(servers, server2)
  143. }
  144. }
  145. }
  146. }
  147. if dc2.FreeSpace() > 0 {
  148. if ok, server := dc2.ReserveOneVolume(rand.Intn(dc2.FreeSpace()), vid, ""); ok {
  149. servers = append(servers, server)
  150. }
  151. }
  152. if len(servers) == 3 {
  153. if err = vg.grow(topo, vid, repType, servers...); err == nil {
  154. counter++
  155. }
  156. }
  157. }
  158. }
  159. case storage.Copy200:
  160. for i := 0; i < count; i++ {
  161. nl := topology.NewNodeList(topo.Children(), nil)
  162. picked, ret := nl.RandomlyPickN(3, 1, dataCenter)
  163. vid := topo.NextVolumeId()
  164. if ret {
  165. var servers []*topology.DataNode
  166. for _, n := range picked {
  167. if n.FreeSpace() > 0 {
  168. if ok, server := n.ReserveOneVolume(rand.Intn(n.FreeSpace()), vid, ""); ok {
  169. servers = append(servers, server)
  170. }
  171. }
  172. }
  173. if len(servers) == 3 {
  174. if err = vg.grow(topo, vid, repType, servers...); err == nil {
  175. counter++
  176. }
  177. }
  178. }
  179. }
  180. }
  181. return
  182. }
  183. func (vg *VolumeGrowth) grow(topo *topology.Topology, vid storage.VolumeId, repType storage.ReplicationType, servers ...*topology.DataNode) error {
  184. for _, server := range servers {
  185. if err := operation.AllocateVolume(server, vid, repType); err == nil {
  186. vi := storage.VolumeInfo{Id: vid, Size: 0, RepType: repType, Version: storage.CurrentVersion}
  187. server.AddOrUpdateVolume(vi)
  188. topo.RegisterVolumeLayout(&vi, server)
  189. fmt.Println("Created Volume", vid, "on", server)
  190. } else {
  191. fmt.Println("Failed to assign", vid, "to", servers, "error", err)
  192. return errors.New("Failed to assign " + vid.String())
  193. }
  194. }
  195. return nil
  196. }