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.

255 lines
6.7 KiB

13 years ago
13 years ago
13 years ago
  1. package topology
  2. import (
  3. "errors"
  4. "math/rand"
  5. "strings"
  6. "github.com/chrislusf/weed-fs/go/glog"
  7. "github.com/chrislusf/weed-fs/go/storage"
  8. )
  9. type NodeId string
  10. type Node interface {
  11. Id() NodeId
  12. String() string
  13. FreeSpace() int
  14. ReserveOneVolume(r int) (*DataNode, error)
  15. UpAdjustMaxVolumeCountDelta(maxVolumeCountDelta int)
  16. UpAdjustVolumeCountDelta(volumeCountDelta int)
  17. UpAdjustActiveVolumeCountDelta(activeVolumeCountDelta int)
  18. UpAdjustMaxVolumeId(vid storage.VolumeId)
  19. GetVolumeCount() int
  20. GetActiveVolumeCount() int
  21. GetMaxVolumeCount() int
  22. GetMaxVolumeId() storage.VolumeId
  23. SetParent(Node)
  24. LinkChildNode(node Node)
  25. UnlinkChildNode(nodeId NodeId)
  26. CollectDeadNodeAndFullVolumes(freshThreshHold int64, volumeSizeLimit uint64)
  27. IsDataNode() bool
  28. IsRack() bool
  29. IsDataCenter() bool
  30. Children() map[NodeId]Node
  31. Parent() Node
  32. GetValue() interface{} //get reference to the topology,dc,rack,datanode
  33. }
  34. type NodeImpl struct {
  35. id NodeId
  36. volumeCount int
  37. activeVolumeCount int
  38. maxVolumeCount int
  39. parent Node
  40. children map[NodeId]Node
  41. maxVolumeId storage.VolumeId
  42. //for rack, data center, topology
  43. nodeType string
  44. value interface{}
  45. }
  46. // the first node must satisfy filterFirstNodeFn(), the rest nodes must have one free slot
  47. func (n *NodeImpl) RandomlyPickNodes(numberOfNodes int, filterFirstNodeFn func(dn Node) error) (firstNode Node, restNodes []Node, err error) {
  48. candidates := make([]Node, 0, len(n.children))
  49. var errs []string
  50. for _, node := range n.children {
  51. if err := filterFirstNodeFn(node); err == nil {
  52. candidates = append(candidates, node)
  53. } else {
  54. errs = append(errs, string(node.Id())+":"+err.Error())
  55. }
  56. }
  57. if len(candidates) == 0 {
  58. return nil, nil, errors.New("No matching data node found! \n" + strings.Join(errs, "\n"))
  59. }
  60. firstNode = candidates[rand.Intn(len(candidates))]
  61. glog.V(2).Infoln(n.Id(), "picked main node:", firstNode.Id())
  62. restNodes = make([]Node, numberOfNodes-1)
  63. candidates = candidates[:0]
  64. for _, node := range n.children {
  65. if node.Id() == firstNode.Id() {
  66. continue
  67. }
  68. if node.FreeSpace() <= 0 {
  69. continue
  70. }
  71. glog.V(2).Infoln("select rest node candidate:", node.Id())
  72. candidates = append(candidates, node)
  73. }
  74. glog.V(2).Infoln(n.Id(), "picking", numberOfNodes-1, "from rest", len(candidates), "node candidates")
  75. ret := len(restNodes) == 0
  76. for k, node := range candidates {
  77. if k < len(restNodes) {
  78. restNodes[k] = node
  79. if k == len(restNodes)-1 {
  80. ret = true
  81. }
  82. } else {
  83. r := rand.Intn(k + 1)
  84. if r < len(restNodes) {
  85. restNodes[r] = node
  86. }
  87. }
  88. }
  89. if !ret {
  90. glog.V(2).Infoln(n.Id(), "failed to pick", numberOfNodes-1, "from rest", len(candidates), "node candidates")
  91. err = errors.New("Not enough data node found!")
  92. }
  93. return
  94. }
  95. func (n *NodeImpl) IsDataNode() bool {
  96. return n.nodeType == "DataNode"
  97. }
  98. func (n *NodeImpl) IsRack() bool {
  99. return n.nodeType == "Rack"
  100. }
  101. func (n *NodeImpl) IsDataCenter() bool {
  102. return n.nodeType == "DataCenter"
  103. }
  104. func (n *NodeImpl) String() string {
  105. if n.parent != nil {
  106. return n.parent.String() + ":" + string(n.id)
  107. }
  108. return string(n.id)
  109. }
  110. func (n *NodeImpl) Id() NodeId {
  111. return n.id
  112. }
  113. func (n *NodeImpl) FreeSpace() int {
  114. return n.maxVolumeCount - n.volumeCount
  115. }
  116. func (n *NodeImpl) SetParent(node Node) {
  117. n.parent = node
  118. }
  119. func (n *NodeImpl) Children() map[NodeId]Node {
  120. return n.children
  121. }
  122. func (n *NodeImpl) Parent() Node {
  123. return n.parent
  124. }
  125. func (n *NodeImpl) GetValue() interface{} {
  126. return n.value
  127. }
  128. func (n *NodeImpl) ReserveOneVolume(r int) (assignedNode *DataNode, err error) {
  129. for _, node := range n.children {
  130. freeSpace := node.FreeSpace()
  131. // fmt.Println("r =", r, ", node =", node, ", freeSpace =", freeSpace)
  132. if freeSpace <= 0 {
  133. continue
  134. }
  135. if r >= freeSpace {
  136. r -= freeSpace
  137. } else {
  138. if node.IsDataNode() && node.FreeSpace() > 0 {
  139. // fmt.Println("vid =", vid, " assigned to node =", node, ", freeSpace =", node.FreeSpace())
  140. return node.(*DataNode), nil
  141. }
  142. assignedNode, err = node.ReserveOneVolume(r)
  143. if err != nil {
  144. return
  145. }
  146. }
  147. }
  148. return
  149. }
  150. func (n *NodeImpl) UpAdjustMaxVolumeCountDelta(maxVolumeCountDelta int) { //can be negative
  151. n.maxVolumeCount += maxVolumeCountDelta
  152. if n.parent != nil {
  153. n.parent.UpAdjustMaxVolumeCountDelta(maxVolumeCountDelta)
  154. }
  155. }
  156. func (n *NodeImpl) UpAdjustVolumeCountDelta(volumeCountDelta int) { //can be negative
  157. n.volumeCount += volumeCountDelta
  158. if n.parent != nil {
  159. n.parent.UpAdjustVolumeCountDelta(volumeCountDelta)
  160. }
  161. }
  162. func (n *NodeImpl) UpAdjustActiveVolumeCountDelta(activeVolumeCountDelta int) { //can be negative
  163. n.activeVolumeCount += activeVolumeCountDelta
  164. if n.parent != nil {
  165. n.parent.UpAdjustActiveVolumeCountDelta(activeVolumeCountDelta)
  166. }
  167. }
  168. func (n *NodeImpl) UpAdjustMaxVolumeId(vid storage.VolumeId) { //can be negative
  169. if n.maxVolumeId < vid {
  170. n.maxVolumeId = vid
  171. if n.parent != nil {
  172. n.parent.UpAdjustMaxVolumeId(vid)
  173. }
  174. }
  175. }
  176. func (n *NodeImpl) GetMaxVolumeId() storage.VolumeId {
  177. return n.maxVolumeId
  178. }
  179. func (n *NodeImpl) GetVolumeCount() int {
  180. return n.volumeCount
  181. }
  182. func (n *NodeImpl) GetActiveVolumeCount() int {
  183. return n.activeVolumeCount
  184. }
  185. func (n *NodeImpl) GetMaxVolumeCount() int {
  186. return n.maxVolumeCount
  187. }
  188. func (n *NodeImpl) LinkChildNode(node Node) {
  189. if n.children[node.Id()] == nil {
  190. n.children[node.Id()] = node
  191. n.UpAdjustMaxVolumeCountDelta(node.GetMaxVolumeCount())
  192. n.UpAdjustMaxVolumeId(node.GetMaxVolumeId())
  193. n.UpAdjustVolumeCountDelta(node.GetVolumeCount())
  194. n.UpAdjustActiveVolumeCountDelta(node.GetActiveVolumeCount())
  195. node.SetParent(n)
  196. glog.V(0).Infoln(n, "adds child", node.Id())
  197. }
  198. }
  199. func (n *NodeImpl) UnlinkChildNode(nodeId NodeId) {
  200. node := n.children[nodeId]
  201. node.SetParent(nil)
  202. if node != nil {
  203. delete(n.children, node.Id())
  204. n.UpAdjustVolumeCountDelta(-node.GetVolumeCount())
  205. n.UpAdjustActiveVolumeCountDelta(-node.GetActiveVolumeCount())
  206. n.UpAdjustMaxVolumeCountDelta(-node.GetMaxVolumeCount())
  207. glog.V(0).Infoln(n, "removes", node, "volumeCount =", n.activeVolumeCount)
  208. }
  209. }
  210. func (n *NodeImpl) CollectDeadNodeAndFullVolumes(freshThreshHold int64, volumeSizeLimit uint64) {
  211. if n.IsRack() {
  212. for _, c := range n.Children() {
  213. dn := c.(*DataNode) //can not cast n to DataNode
  214. if dn.LastSeen < freshThreshHold {
  215. if !dn.Dead {
  216. dn.Dead = true
  217. n.GetTopology().chanDeadDataNodes <- dn
  218. }
  219. }
  220. for _, v := range dn.volumes {
  221. if uint64(v.Size) >= volumeSizeLimit {
  222. //fmt.Println("volume",v.Id,"size",v.Size,">",volumeSizeLimit)
  223. n.GetTopology().chanFullVolumes <- v
  224. }
  225. }
  226. }
  227. } else {
  228. for _, c := range n.Children() {
  229. c.CollectDeadNodeAndFullVolumes(freshThreshHold, volumeSizeLimit)
  230. }
  231. }
  232. }
  233. func (n *NodeImpl) GetTopology() *Topology {
  234. var p Node
  235. p = n
  236. for p.Parent() != nil {
  237. p = p.Parent()
  238. }
  239. return p.GetValue().(*Topology)
  240. }