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.

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