Chris Lu
12 years ago
7 changed files with 337 additions and 16 deletions
-
74weed-fs/src/pkg/replication/volume_growth.go
-
129weed-fs/src/pkg/replication/volume_growth_test.go
-
20weed-fs/src/pkg/topology/node.go
-
69weed-fs/src/pkg/topology/node_list.go
-
39weed-fs/src/pkg/topology/node_list_test.go
-
5weed-fs/src/pkg/topology/topo_test.go
-
17weed-fs/src/pkg/topology/topology.go
@ -0,0 +1,129 @@ |
|||||
|
package replication |
||||
|
|
||||
|
import ( |
||||
|
"encoding/json" |
||||
|
"fmt" |
||||
|
"math/rand" |
||||
|
"pkg/storage" |
||||
|
"pkg/topology" |
||||
|
"testing" |
||||
|
"time" |
||||
|
) |
||||
|
|
||||
|
var topologyLayout = ` |
||||
|
{ |
||||
|
"dc1":{ |
||||
|
"rack1":{ |
||||
|
"server1":{ |
||||
|
"volumes":[ |
||||
|
{"id":1, "size":12312}, |
||||
|
{"id":2, "size":12312}, |
||||
|
{"id":3, "size":12312} |
||||
|
], |
||||
|
"limit":3 |
||||
|
}, |
||||
|
"server2":{ |
||||
|
"volumes":[ |
||||
|
{"id":4, "size":12312}, |
||||
|
{"id":5, "size":12312}, |
||||
|
{"id":6, "size":12312} |
||||
|
], |
||||
|
"limit":10 |
||||
|
} |
||||
|
}, |
||||
|
"rack2":{ |
||||
|
"server1":{ |
||||
|
"volumes":[ |
||||
|
{"id":4, "size":12312}, |
||||
|
{"id":5, "size":12312}, |
||||
|
{"id":6, "size":12312} |
||||
|
], |
||||
|
"limit":4 |
||||
|
}, |
||||
|
"server2":{ |
||||
|
"volumes":[], |
||||
|
"limit":4 |
||||
|
}, |
||||
|
"server3":{ |
||||
|
"volumes":[ |
||||
|
{"id":2, "size":12312}, |
||||
|
{"id":3, "size":12312}, |
||||
|
{"id":4, "size":12312} |
||||
|
], |
||||
|
"limit":2 |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
"dc2":{ |
||||
|
}, |
||||
|
"dc3":{ |
||||
|
"rack2":{ |
||||
|
"server1":{ |
||||
|
"volumes":[ |
||||
|
{"id":1, "size":12312}, |
||||
|
{"id":3, "size":12312}, |
||||
|
{"id":5, "size":12312} |
||||
|
], |
||||
|
"limit":4 |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
` |
||||
|
|
||||
|
func setup(topologyLayout string) *topology.Topology { |
||||
|
var data interface{} |
||||
|
err := json.Unmarshal([]byte(topologyLayout), &data) |
||||
|
if err != nil { |
||||
|
fmt.Println("error:", err) |
||||
|
} |
||||
|
fmt.Println("data:", data) |
||||
|
|
||||
|
//need to connect all nodes first before server adding volumes
|
||||
|
topo := topology.NewTopology("mynetwork") |
||||
|
mTopology := data.(map[string]interface{}) |
||||
|
for dcKey, dcValue := range mTopology { |
||||
|
dc := topology.NewDataCenter(dcKey) |
||||
|
dcMap := dcValue.(map[string]interface{}) |
||||
|
topo.LinkChildNode(dc) |
||||
|
for rackKey, rackValue := range dcMap { |
||||
|
rack := topology.NewRack(rackKey) |
||||
|
rackMap := rackValue.(map[string]interface{}) |
||||
|
dc.LinkChildNode(rack) |
||||
|
for serverKey, serverValue := range rackMap { |
||||
|
server := topology.NewServer(serverKey) |
||||
|
serverMap := serverValue.(map[string]interface{}) |
||||
|
rack.LinkChildNode(server) |
||||
|
for _, v := range serverMap["volumes"].([]interface{}) { |
||||
|
m := v.(map[string]interface{}) |
||||
|
vi := &storage.VolumeInfo{Id: storage.VolumeId(int64(m["id"].(float64))), Size: int64(m["size"].(float64))} |
||||
|
server.AddVolume(vi) |
||||
|
} |
||||
|
server.UpAdjustMaxVolumeCountDelta(int(serverMap["limit"].(float64))) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
fmt.Println("topology:", *topo) |
||||
|
|
||||
|
return topo |
||||
|
} |
||||
|
|
||||
|
func TestRemoveDataCenter(t *testing.T) { |
||||
|
topo := setup(topologyLayout) |
||||
|
topo.UnlinkChildNode(topology.NodeId("dc2")) |
||||
|
if topo.GetActiveVolumeCount() != 15 { |
||||
|
t.Fail() |
||||
|
} |
||||
|
topo.UnlinkChildNode(topology.NodeId("dc3")) |
||||
|
if topo.GetActiveVolumeCount() != 12 { |
||||
|
t.Fail() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func TestReserveOneVolume(t *testing.T) { |
||||
|
topo := setup(topologyLayout) |
||||
|
rand.Seed(time.Now().UnixNano()) |
||||
|
vg:=&VolumeGrowth{copy1factor:3,copy2factor:2,copy3factor:1,copyAll:4} |
||||
|
vg.GrowVolumeCopy(20,topo) |
||||
|
} |
@ -0,0 +1,69 @@ |
|||||
|
package topology |
||||
|
|
||||
|
import ( |
||||
|
"fmt" |
||||
|
"math/rand" |
||||
|
"pkg/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) ([]Node, bool) { |
||||
|
var list []Node |
||||
|
for _, n := range nl.nodes { |
||||
|
if n.FreeSpace() > 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 |
||||
|
|
||||
|
} |
@ -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) |
||||
|
} |
||||
|
|
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue