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.

267 lines
7.0 KiB

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