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.

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