mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2024-01-19 02:48:24 +00:00
assign volumes based on disk type
This commit is contained in:
parent
daa8157fc2
commit
f696a2b2a7
|
@ -77,7 +77,7 @@ func (ms *MasterServer) volumeGrowHandler(w http.ResponseWriter, r *http.Request
|
||||||
|
|
||||||
if count, err = strconv.Atoi(r.FormValue("count")); err == nil {
|
if count, err = strconv.Atoi(r.FormValue("count")); err == nil {
|
||||||
if ms.Topo.AvailableSpaceFor(option) < int64(count*option.ReplicaPlacement.GetCopyCount()) {
|
if ms.Topo.AvailableSpaceFor(option) < int64(count*option.ReplicaPlacement.GetCopyCount()) {
|
||||||
err = fmt.Errorf("only %d volumes left, not enough for %d", ms.Topo.FreeSpace(), count*option.ReplicaPlacement.GetCopyCount())
|
err = fmt.Errorf("only %d volumes left, not enough for %d", ms.Topo.AvailableSpaceFor(option), count*option.ReplicaPlacement.GetCopyCount())
|
||||||
} else {
|
} else {
|
||||||
count, err = ms.vg.GrowByCountAndType(ms.grpcDialOption, count, option, ms.Topo)
|
count, err = ms.vg.GrowByCountAndType(ms.grpcDialOption, count, option, ms.Topo)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,8 @@ type Node interface {
|
||||||
Id() NodeId
|
Id() NodeId
|
||||||
String() string
|
String() string
|
||||||
FreeSpace() int64
|
FreeSpace() int64
|
||||||
ReserveOneVolume(r int64) (*DataNode, error)
|
AvailableSpaceFor(option *VolumeGrowOption) int64
|
||||||
|
ReserveOneVolume(r int64, option *VolumeGrowOption) (*DataNode, error)
|
||||||
UpAdjustMaxVolumeCountDelta(maxVolumeCountDelta int64)
|
UpAdjustMaxVolumeCountDelta(maxVolumeCountDelta int64)
|
||||||
UpAdjustMaxSsdVolumeCountDelta(maxSsdVolumeCountDelta int64)
|
UpAdjustMaxSsdVolumeCountDelta(maxSsdVolumeCountDelta int64)
|
||||||
UpAdjustVolumeCountDelta(volumeCountDelta int64)
|
UpAdjustVolumeCountDelta(volumeCountDelta int64)
|
||||||
|
@ -69,7 +70,7 @@ type NodeImpl struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// the first node must satisfy filterFirstNodeFn(), the rest nodes must have one free slot
|
// the first node must satisfy filterFirstNodeFn(), the rest nodes must have one free slot
|
||||||
func (n *NodeImpl) PickNodesByWeight(numberOfNodes int, filterFirstNodeFn func(dn Node) error) (firstNode Node, restNodes []Node, err error) {
|
func (n *NodeImpl) PickNodesByWeight(numberOfNodes int, option *VolumeGrowOption, filterFirstNodeFn func(dn Node) error) (firstNode Node, restNodes []Node, err error) {
|
||||||
var totalWeights int64
|
var totalWeights int64
|
||||||
var errs []string
|
var errs []string
|
||||||
n.RLock()
|
n.RLock()
|
||||||
|
@ -77,12 +78,12 @@ func (n *NodeImpl) PickNodesByWeight(numberOfNodes int, filterFirstNodeFn func(d
|
||||||
candidatesWeights := make([]int64, 0, len(n.children))
|
candidatesWeights := make([]int64, 0, len(n.children))
|
||||||
//pick nodes which has enough free volumes as candidates, and use free volumes number as node weight.
|
//pick nodes which has enough free volumes as candidates, and use free volumes number as node weight.
|
||||||
for _, node := range n.children {
|
for _, node := range n.children {
|
||||||
if node.FreeSpace() <= 0 {
|
if node.AvailableSpaceFor(option) <= 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
totalWeights += node.FreeSpace()
|
totalWeights += node.AvailableSpaceFor(option)
|
||||||
candidates = append(candidates, node)
|
candidates = append(candidates, node)
|
||||||
candidatesWeights = append(candidatesWeights, node.FreeSpace())
|
candidatesWeights = append(candidatesWeights, node.AvailableSpaceFor(option))
|
||||||
}
|
}
|
||||||
n.RUnlock()
|
n.RUnlock()
|
||||||
if len(candidates) < numberOfNodes {
|
if len(candidates) < numberOfNodes {
|
||||||
|
@ -183,11 +184,11 @@ func (n *NodeImpl) Parent() Node {
|
||||||
func (n *NodeImpl) GetValue() interface{} {
|
func (n *NodeImpl) GetValue() interface{} {
|
||||||
return n.value
|
return n.value
|
||||||
}
|
}
|
||||||
func (n *NodeImpl) ReserveOneVolume(r int64) (assignedNode *DataNode, err error) {
|
func (n *NodeImpl) ReserveOneVolume(r int64, option *VolumeGrowOption) (assignedNode *DataNode, err error) {
|
||||||
n.RLock()
|
n.RLock()
|
||||||
defer n.RUnlock()
|
defer n.RUnlock()
|
||||||
for _, node := range n.children {
|
for _, node := range n.children {
|
||||||
freeSpace := node.FreeSpace()
|
freeSpace := node.AvailableSpaceFor(option)
|
||||||
// fmt.Println("r =", r, ", node =", node, ", freeSpace =", freeSpace)
|
// fmt.Println("r =", r, ", node =", node, ", freeSpace =", freeSpace)
|
||||||
if freeSpace <= 0 {
|
if freeSpace <= 0 {
|
||||||
continue
|
continue
|
||||||
|
@ -195,11 +196,11 @@ func (n *NodeImpl) ReserveOneVolume(r int64) (assignedNode *DataNode, err error)
|
||||||
if r >= freeSpace {
|
if r >= freeSpace {
|
||||||
r -= freeSpace
|
r -= freeSpace
|
||||||
} else {
|
} else {
|
||||||
if node.IsDataNode() && node.FreeSpace() > 0 {
|
if node.IsDataNode() && node.AvailableSpaceFor(option) > 0 {
|
||||||
// fmt.Println("vid =", vid, " assigned to node =", node, ", freeSpace =", node.FreeSpace())
|
// fmt.Println("vid =", vid, " assigned to node =", node, ", freeSpace =", node.FreeSpace())
|
||||||
return node.(*DataNode), nil
|
return node.(*DataNode), nil
|
||||||
}
|
}
|
||||||
assignedNode, err = node.ReserveOneVolume(r)
|
assignedNode, err = node.ReserveOneVolume(r, option)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,21 +114,21 @@ func (vg *VolumeGrowth) findAndGrow(grpcDialOption grpc.DialOption, topo *Topolo
|
||||||
func (vg *VolumeGrowth) findEmptySlotsForOneVolume(topo *Topology, option *VolumeGrowOption) (servers []*DataNode, err error) {
|
func (vg *VolumeGrowth) findEmptySlotsForOneVolume(topo *Topology, option *VolumeGrowOption) (servers []*DataNode, err error) {
|
||||||
//find main datacenter and other data centers
|
//find main datacenter and other data centers
|
||||||
rp := option.ReplicaPlacement
|
rp := option.ReplicaPlacement
|
||||||
mainDataCenter, otherDataCenters, dc_err := topo.PickNodesByWeight(rp.DiffDataCenterCount+1, func(node Node) error {
|
mainDataCenter, otherDataCenters, dc_err := topo.PickNodesByWeight(rp.DiffDataCenterCount+1, option, func(node Node) error {
|
||||||
if option.DataCenter != "" && node.IsDataCenter() && node.Id() != NodeId(option.DataCenter) {
|
if option.DataCenter != "" && node.IsDataCenter() && node.Id() != NodeId(option.DataCenter) {
|
||||||
return fmt.Errorf("Not matching preferred data center:%s", option.DataCenter)
|
return fmt.Errorf("Not matching preferred data center:%s", option.DataCenter)
|
||||||
}
|
}
|
||||||
if len(node.Children()) < rp.DiffRackCount+1 {
|
if len(node.Children()) < rp.DiffRackCount+1 {
|
||||||
return fmt.Errorf("Only has %d racks, not enough for %d.", len(node.Children()), rp.DiffRackCount+1)
|
return fmt.Errorf("Only has %d racks, not enough for %d.", len(node.Children()), rp.DiffRackCount+1)
|
||||||
}
|
}
|
||||||
if node.FreeSpace() < int64(rp.DiffRackCount+rp.SameRackCount+1) {
|
if node.AvailableSpaceFor(option) < int64(rp.DiffRackCount+rp.SameRackCount+1) {
|
||||||
return fmt.Errorf("Free:%d < Expected:%d", node.FreeSpace(), rp.DiffRackCount+rp.SameRackCount+1)
|
return fmt.Errorf("Free:%d < Expected:%d", node.AvailableSpaceFor(option), rp.DiffRackCount+rp.SameRackCount+1)
|
||||||
}
|
}
|
||||||
possibleRacksCount := 0
|
possibleRacksCount := 0
|
||||||
for _, rack := range node.Children() {
|
for _, rack := range node.Children() {
|
||||||
possibleDataNodesCount := 0
|
possibleDataNodesCount := 0
|
||||||
for _, n := range rack.Children() {
|
for _, n := range rack.Children() {
|
||||||
if n.FreeSpace() >= 1 {
|
if n.AvailableSpaceFor(option) >= 1 {
|
||||||
possibleDataNodesCount++
|
possibleDataNodesCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,12 +146,12 @@ func (vg *VolumeGrowth) findEmptySlotsForOneVolume(topo *Topology, option *Volum
|
||||||
}
|
}
|
||||||
|
|
||||||
//find main rack and other racks
|
//find main rack and other racks
|
||||||
mainRack, otherRacks, rackErr := mainDataCenter.(*DataCenter).PickNodesByWeight(rp.DiffRackCount+1, func(node Node) error {
|
mainRack, otherRacks, rackErr := mainDataCenter.(*DataCenter).PickNodesByWeight(rp.DiffRackCount+1, option, func(node Node) error {
|
||||||
if option.Rack != "" && node.IsRack() && node.Id() != NodeId(option.Rack) {
|
if option.Rack != "" && node.IsRack() && node.Id() != NodeId(option.Rack) {
|
||||||
return fmt.Errorf("Not matching preferred rack:%s", option.Rack)
|
return fmt.Errorf("Not matching preferred rack:%s", option.Rack)
|
||||||
}
|
}
|
||||||
if node.FreeSpace() < int64(rp.SameRackCount+1) {
|
if node.AvailableSpaceFor(option) < int64(rp.SameRackCount+1) {
|
||||||
return fmt.Errorf("Free:%d < Expected:%d", node.FreeSpace(), rp.SameRackCount+1)
|
return fmt.Errorf("Free:%d < Expected:%d", node.AvailableSpaceFor(option), rp.SameRackCount+1)
|
||||||
}
|
}
|
||||||
if len(node.Children()) < rp.SameRackCount+1 {
|
if len(node.Children()) < rp.SameRackCount+1 {
|
||||||
// a bit faster way to test free racks
|
// a bit faster way to test free racks
|
||||||
|
@ -159,7 +159,7 @@ func (vg *VolumeGrowth) findEmptySlotsForOneVolume(topo *Topology, option *Volum
|
||||||
}
|
}
|
||||||
possibleDataNodesCount := 0
|
possibleDataNodesCount := 0
|
||||||
for _, n := range node.Children() {
|
for _, n := range node.Children() {
|
||||||
if n.FreeSpace() >= 1 {
|
if n.AvailableSpaceFor(option) >= 1 {
|
||||||
possibleDataNodesCount++
|
possibleDataNodesCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,12 +173,12 @@ func (vg *VolumeGrowth) findEmptySlotsForOneVolume(topo *Topology, option *Volum
|
||||||
}
|
}
|
||||||
|
|
||||||
//find main rack and other racks
|
//find main rack and other racks
|
||||||
mainServer, otherServers, serverErr := mainRack.(*Rack).PickNodesByWeight(rp.SameRackCount+1, func(node Node) error {
|
mainServer, otherServers, serverErr := mainRack.(*Rack).PickNodesByWeight(rp.SameRackCount+1, option, func(node Node) error {
|
||||||
if option.DataNode != "" && node.IsDataNode() && node.Id() != NodeId(option.DataNode) {
|
if option.DataNode != "" && node.IsDataNode() && node.Id() != NodeId(option.DataNode) {
|
||||||
return fmt.Errorf("Not matching preferred data node:%s", option.DataNode)
|
return fmt.Errorf("Not matching preferred data node:%s", option.DataNode)
|
||||||
}
|
}
|
||||||
if node.FreeSpace() < 1 {
|
if node.AvailableSpaceFor(option) < 1 {
|
||||||
return fmt.Errorf("Free:%d < Expected:%d", node.FreeSpace(), 1)
|
return fmt.Errorf("Free:%d < Expected:%d", node.AvailableSpaceFor(option), 1)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
@ -191,16 +191,16 @@ func (vg *VolumeGrowth) findEmptySlotsForOneVolume(topo *Topology, option *Volum
|
||||||
servers = append(servers, server.(*DataNode))
|
servers = append(servers, server.(*DataNode))
|
||||||
}
|
}
|
||||||
for _, rack := range otherRacks {
|
for _, rack := range otherRacks {
|
||||||
r := rand.Int63n(rack.FreeSpace())
|
r := rand.Int63n(rack.AvailableSpaceFor(option))
|
||||||
if server, e := rack.ReserveOneVolume(r); e == nil {
|
if server, e := rack.ReserveOneVolume(r, option); e == nil {
|
||||||
servers = append(servers, server)
|
servers = append(servers, server)
|
||||||
} else {
|
} else {
|
||||||
return servers, e
|
return servers, e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, datacenter := range otherDataCenters {
|
for _, datacenter := range otherDataCenters {
|
||||||
r := rand.Int63n(datacenter.FreeSpace())
|
r := rand.Int63n(datacenter.AvailableSpaceFor(option))
|
||||||
if server, e := datacenter.ReserveOneVolume(r); e == nil {
|
if server, e := datacenter.ReserveOneVolume(r, option); e == nil {
|
||||||
servers = append(servers, server)
|
servers = append(servers, server)
|
||||||
} else {
|
} else {
|
||||||
return servers, e
|
return servers, e
|
||||||
|
|
Loading…
Reference in a new issue