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.

272 lines
7.0 KiB

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