diff --git a/weed-fs/src/pkg/replication/volume_growth.go b/weed-fs/src/pkg/replication/volume_growth.go index 5747330ea..ee6b745e9 100644 --- a/weed-fs/src/pkg/replication/volume_growth.go +++ b/weed-fs/src/pkg/replication/volume_growth.go @@ -1,6 +1,9 @@ package replication import ( + "fmt" + "math/rand" + "pkg/storage" "pkg/topology" ) @@ -19,11 +22,74 @@ type VolumeGrowth struct { copyAll int } -func (vg *VolumeGrowth) GrowVolumeCopy(copyLevel int, topo topology.Topology) { - if copyLevel == 1 { - for i := 0; i 0 { + 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, *Server) { + for _, node := range nl.nodes { + freeSpace := node.FreeSpace() + if randomVolumeIndex >= freeSpace { + randomVolumeIndex -= freeSpace + } else { + if node.IsServer() && node.FreeSpace() > 0 { + fmt.Println("vid =", vid, " assigned to node =", node, ", freeSpace =", node.FreeSpace()) + return true, node.(*Server) + } + children := node.Children() + newNodeList := NewNodeList(children, nl.except) + return newNodeList.ReserveOneVolume(randomVolumeIndex, vid) + } + } + return false, nil + +} diff --git a/weed-fs/src/pkg/topology/node_list_test.go b/weed-fs/src/pkg/topology/node_list_test.go new file mode 100644 index 000000000..1e5b0d9f6 --- /dev/null +++ b/weed-fs/src/pkg/topology/node_list_test.go @@ -0,0 +1,39 @@ +package topology + +import ( + "strconv" + "testing" + _ "fmt" +) + +func TestXYZ(t *testing.T) { + topo := NewTopology("topo") + for i := 0; i < 5; i++ { + dc := NewDataCenter("dc" + strconv.Itoa(i)) + dc.activeVolumeCount = i + dc.maxVolumeCount = 5 + topo.LinkChildNode(dc) + } + nl := NewNodeList(topo.Children(),nil) + + picked, ret := nl.RandomlyPickN(1) + if !ret || len(picked)!=1 { + t.Errorf("need to randomly pick 1 node") + } + + picked, ret = nl.RandomlyPickN(4) + if !ret || len(picked)!=4 { + t.Errorf("need to randomly pick 4 nodes") + } + + picked, ret = nl.RandomlyPickN(5) + if !ret || len(picked)!=5 { + t.Errorf("need to randomly pick 5 nodes") + } + + picked, ret = nl.RandomlyPickN(6) + if ret || len(picked)!=0 { + t.Errorf("can not randomly pick 6 nodes:", ret, picked) + } + +} diff --git a/weed-fs/src/pkg/topology/topo_test.go b/weed-fs/src/pkg/topology/topo_test.go index 66e4d34e5..cc3e284cd 100644 --- a/weed-fs/src/pkg/topology/topo_test.go +++ b/weed-fs/src/pkg/topology/topo_test.go @@ -76,8 +76,8 @@ func setup(topologyLayout string) *Topology { if err != nil { fmt.Println("error:", err) } - fmt.Println("data:", data) - printMap(data) + //fmt.Println("data:", data) + //printMap(data) //need to connect all nodes first before server adding volumes topo := NewTopology("mynetwork") @@ -156,4 +156,5 @@ func TestReserveOneVolume(t *testing.T) { ret, node, vid := topo.RandomlyReserveOneVolume() fmt.Println("topology:", topo) fmt.Println("assigned :", ret, ", node :", node,", volume id:", vid) + } diff --git a/weed-fs/src/pkg/topology/topology.go b/weed-fs/src/pkg/topology/topology.go index 3806bdbc7..041aaf46c 100644 --- a/weed-fs/src/pkg/topology/topology.go +++ b/weed-fs/src/pkg/topology/topology.go @@ -1,7 +1,7 @@ package topology import ( - "fmt" + _ "fmt" "math/rand" "pkg/storage" ) @@ -18,13 +18,22 @@ func NewTopology(id string) *Topology { return t } func (t *Topology) RandomlyReserveOneVolume() (bool, *Server, storage.VolumeId) { - vid := t.nextVolumeId() + vid := t.NextVolumeId() ret, node := t.ReserveOneVolume(rand.Intn(t.FreeSpace()), vid) - fmt.Println("node.IsServer", node.IsServer()) return ret, node, vid } -func (t *Topology) nextVolumeId() storage.VolumeId { +func (t *Topology) RandomlyReserveOneVolumeExcept(except []Node) (bool, *Server, storage.VolumeId) { + freeSpace := t.FreeSpace() + for _, node := range except { + freeSpace -= node.FreeSpace() + } + vid := t.NextVolumeId() + ret, node := t.ReserveOneVolume(rand.Intn(freeSpace), vid) + return ret, node, vid +} + +func (t *Topology) NextVolumeId() storage.VolumeId { vid := t.GetMaxVolumeId() return vid.Next() }