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.

214 lines
6.8 KiB

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