2012-09-03 08:50:04 +00:00
|
|
|
package topology
|
|
|
|
|
|
|
|
import (
|
2013-02-27 06:54:22 +00:00
|
|
|
"code.google.com/p/weed-fs/go/storage"
|
2013-07-14 02:44:24 +00:00
|
|
|
"log"
|
2012-09-03 08:50:04 +00:00
|
|
|
"math/rand"
|
|
|
|
)
|
|
|
|
|
|
|
|
type NodeList struct {
|
|
|
|
nodes map[NodeId]Node
|
|
|
|
except map[string]Node
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewNodeList(nodes map[NodeId]Node, except map[string]Node) *NodeList {
|
|
|
|
m := make(map[NodeId]Node, len(nodes)-len(except))
|
|
|
|
for _, n := range nodes {
|
|
|
|
if except[n.String()] == nil {
|
|
|
|
m[n.Id()] = n
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nl := &NodeList{nodes: m}
|
|
|
|
return nl
|
|
|
|
}
|
|
|
|
|
|
|
|
func (nl *NodeList) FreeSpace() int {
|
|
|
|
freeSpace := 0
|
|
|
|
for _, n := range nl.nodes {
|
|
|
|
freeSpace += n.FreeSpace()
|
|
|
|
}
|
|
|
|
return freeSpace
|
|
|
|
}
|
|
|
|
|
2013-06-20 01:10:38 +00:00
|
|
|
func (nl *NodeList) RandomlyPickN(count int, minSpace int, firstNodeName string) ([]Node, bool) {
|
2012-09-03 08:50:04 +00:00
|
|
|
var list []Node
|
2013-06-20 01:10:38 +00:00
|
|
|
var preferredNode *Node
|
|
|
|
if firstNodeName != "" {
|
|
|
|
for _, n := range nl.nodes {
|
|
|
|
if n.Id() == NodeId(firstNodeName) && n.FreeSpace() >= minSpace {
|
|
|
|
preferredNode = &n
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if preferredNode == nil {
|
|
|
|
return list, false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-03 08:50:04 +00:00
|
|
|
for _, n := range nl.nodes {
|
2013-06-20 01:10:38 +00:00
|
|
|
if n.FreeSpace() >= minSpace && n.Id() != NodeId(firstNodeName) {
|
2012-09-03 08:50:04 +00:00
|
|
|
list = append(list, n)
|
|
|
|
}
|
|
|
|
}
|
2013-06-20 01:10:38 +00:00
|
|
|
if count > len(list) || count == len(list) && firstNodeName != "" {
|
2013-01-17 08:56:56 +00:00
|
|
|
return nil, false
|
2012-09-03 08:50:04 +00:00
|
|
|
}
|
2013-06-20 01:10:38 +00:00
|
|
|
for i := len(list); i > 0; i-- {
|
2013-01-17 08:56:56 +00:00
|
|
|
r := rand.Intn(i)
|
2013-06-20 01:10:38 +00:00
|
|
|
list[r], list[i-1] = list[i-1], list[r]
|
|
|
|
}
|
|
|
|
if firstNodeName != "" {
|
2013-07-14 02:44:24 +00:00
|
|
|
list[0] = *preferredNode
|
2012-09-03 08:50:04 +00:00
|
|
|
}
|
2013-06-20 01:10:38 +00:00
|
|
|
return list[:count], true
|
2012-09-03 08:50:04 +00:00
|
|
|
}
|
|
|
|
|
2012-09-08 23:25:44 +00:00
|
|
|
func (nl *NodeList) ReserveOneVolume(randomVolumeIndex int, vid storage.VolumeId) (bool, *DataNode) {
|
2012-09-03 08:50:04 +00:00
|
|
|
for _, node := range nl.nodes {
|
|
|
|
freeSpace := node.FreeSpace()
|
|
|
|
if randomVolumeIndex >= freeSpace {
|
|
|
|
randomVolumeIndex -= freeSpace
|
|
|
|
} else {
|
2012-09-08 23:25:44 +00:00
|
|
|
if node.IsDataNode() && node.FreeSpace() > 0 {
|
2013-07-14 02:44:24 +00:00
|
|
|
log.Println("vid =", vid, " assigned to node =", node, ", freeSpace =", node.FreeSpace())
|
2012-09-08 23:25:44 +00:00
|
|
|
return true, node.(*DataNode)
|
2012-09-03 08:50:04 +00:00
|
|
|
}
|
|
|
|
children := node.Children()
|
|
|
|
newNodeList := NewNodeList(children, nl.except)
|
|
|
|
return newNodeList.ReserveOneVolume(randomVolumeIndex, vid)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false, nil
|
|
|
|
|
|
|
|
}
|