diff --git a/weed/topology/node.go b/weed/topology/node.go index a8edb828a..e78b128c3 100644 --- a/weed/topology/node.go +++ b/weed/topology/node.go @@ -127,6 +127,7 @@ type Node interface { String() string AvailableSpaceFor(option *VolumeGrowOption) int64 ReserveOneVolume(r int64, option *VolumeGrowOption) (*DataNode, error) + ReserveOneVolumeForReservation(r int64, option *VolumeGrowOption) (*DataNode, error) UpAdjustDiskUsageDelta(diskType types.DiskType, diskUsage *DiskUsageCounts) UpAdjustMaxVolumeId(vid needle.VolumeId) GetDiskUsages() *DiskUsages @@ -336,10 +337,24 @@ func (n *NodeImpl) GetValue() interface{} { } func (n *NodeImpl) ReserveOneVolume(r int64, option *VolumeGrowOption) (assignedNode *DataNode, err error) { + return n.reserveOneVolumeInternal(r, option, false) +} + +// ReserveOneVolumeForReservation selects a node using reservation-aware capacity checks +func (n *NodeImpl) ReserveOneVolumeForReservation(r int64, option *VolumeGrowOption) (assignedNode *DataNode, err error) { + return n.reserveOneVolumeInternal(r, option, true) +} + +func (n *NodeImpl) reserveOneVolumeInternal(r int64, option *VolumeGrowOption, useReservations bool) (assignedNode *DataNode, err error) { n.RLock() defer n.RUnlock() for _, node := range n.children { - freeSpace := node.AvailableSpaceFor(option) + var freeSpace int64 + if useReservations { + freeSpace = node.AvailableSpaceForReservation(option) + } else { + freeSpace = node.AvailableSpaceFor(option) + } // fmt.Println("r =", r, ", node =", node, ", freeSpace =", freeSpace) if freeSpace <= 0 { continue @@ -347,7 +362,13 @@ func (n *NodeImpl) ReserveOneVolume(r int64, option *VolumeGrowOption) (assigned if r >= freeSpace { r -= freeSpace } else { - if node.IsDataNode() && node.AvailableSpaceFor(option) > 0 { + var hasSpace bool + if useReservations { + hasSpace = node.IsDataNode() && node.AvailableSpaceForReservation(option) > 0 + } else { + hasSpace = node.IsDataNode() && node.AvailableSpaceFor(option) > 0 + } + if hasSpace { // fmt.Println("vid =", vid, " assigned to node =", node, ", freeSpace =", node.FreeSpace()) dn := node.(*DataNode) if dn.IsTerminating { @@ -355,7 +376,11 @@ func (n *NodeImpl) ReserveOneVolume(r int64, option *VolumeGrowOption) (assigned } return dn, nil } - assignedNode, err = node.ReserveOneVolume(r, option) + if useReservations { + assignedNode, err = node.ReserveOneVolumeForReservation(r, option) + } else { + assignedNode, err = node.ReserveOneVolume(r, option) + } if err == nil { return } diff --git a/weed/topology/volume_growth.go b/weed/topology/volume_growth.go index 2500d08d2..1ed0ea0ca 100644 --- a/weed/topology/volume_growth.go +++ b/weed/topology/volume_growth.go @@ -268,7 +268,7 @@ func (vg *VolumeGrowth) findEmptySlotsForOneVolume(topo *Topology, option *Volum } for _, rack := range otherRacks { r := rand.Int64N(rack.AvailableSpaceForReservation(option)) - if server, e := rack.ReserveOneVolume(r, option); e == nil { + if server, e := rack.ReserveOneVolumeForReservation(r, option); e == nil { servers = append(servers, server) } else { return servers, nil, e @@ -276,7 +276,7 @@ func (vg *VolumeGrowth) findEmptySlotsForOneVolume(topo *Topology, option *Volum } for _, datacenter := range otherDataCenters { r := rand.Int64N(datacenter.AvailableSpaceForReservation(option)) - if server, e := datacenter.ReserveOneVolume(r, option); e == nil { + if server, e := datacenter.ReserveOneVolumeForReservation(r, option); e == nil { servers = append(servers, server) } else { return servers, nil, e