package topology import ( "fmt" "math/rand" "code.google.com/p/weed-fs/go/storage" ) 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 } func (nl *NodeList) RandomlyPickN(n int, min int) ([]Node, bool) { var list []Node for _, n := range nl.nodes { if n.FreeSpace() >= min { list = append(list, n) } } if n > len(list) { return nil, false } for i := n; i > 0; i-- { r := rand.Intn(i) t := list[r] list[r] = list[i-1] list[i-1] = t } return list[len(list)-n:], true } func (nl *NodeList) ReserveOneVolume(randomVolumeIndex int, vid storage.VolumeId) (bool, *DataNode) { for _, node := range nl.nodes { freeSpace := node.FreeSpace() if randomVolumeIndex >= freeSpace { randomVolumeIndex -= freeSpace } else { if node.IsDataNode() && node.FreeSpace() > 0 { fmt.Println("vid =", vid, " assigned to node =", node, ", freeSpace =", node.FreeSpace()) return true, node.(*DataNode) } children := node.Children() newNodeList := NewNodeList(children, nl.except) return newNodeList.ReserveOneVolume(randomVolumeIndex, vid) } } return false, nil }