@ -1,6 +1,7 @@
package shell
package shell
import (
import (
"cmp"
"flag"
"flag"
"fmt"
"fmt"
"io"
"io"
@ -79,7 +80,7 @@ func (c *commandVolumeBalance) Do(args []string, commandEnv *CommandEnv, writer
}
}
// collect topology information
// collect topology information
topologyInfo , volumeSizeLimitMb , err := collectTopologyInfo ( commandEnv , 15 * time . Second )
topologyInfo , _ , err := collectTopologyInfo ( commandEnv , 15 * time . Second )
if err != nil {
if err != nil {
return err
return err
}
}
@ -94,16 +95,12 @@ func (c *commandVolumeBalance) Do(args []string, commandEnv *CommandEnv, writer
return err
return err
}
}
for _ , c := range collections {
for _ , c := range collections {
if err = balanceVolumeServers ( commandEnv , diskTypes , volumeReplicas , volumeServers , volumeSizeLimitMb * 1024 * 1024 , c , * applyBalancing ) ; err != nil {
if err = balanceVolumeServers ( commandEnv , diskTypes , volumeReplicas , volumeServers , c , * applyBalancing ) ; err != nil {
return err
return err
}
}
}
}
} else if * collection == "ALL_COLLECTIONS" {
if err = balanceVolumeServers ( commandEnv , diskTypes , volumeReplicas , volumeServers , volumeSizeLimitMb * 1024 * 1024 , "ALL_COLLECTIONS" , * applyBalancing ) ; err != nil {
return err
}
} else {
} else {
if err = balanceVolumeServers ( commandEnv , diskTypes , volumeReplicas , volumeServers , volumeSizeLimitMb * 1024 * 1024 , * collection , * applyBalancing ) ; err != nil {
if err = balanceVolumeServers ( commandEnv , diskTypes , volumeReplicas , volumeServers , * collection , * applyBalancing ) ; err != nil {
return err
return err
}
}
}
}
@ -111,10 +108,10 @@ func (c *commandVolumeBalance) Do(args []string, commandEnv *CommandEnv, writer
return nil
return nil
}
}
func balanceVolumeServers ( commandEnv * CommandEnv , diskTypes [ ] types . DiskType , volumeReplicas map [ uint32 ] [ ] * VolumeReplica , nodes [ ] * Node , volumeSizeLimit uint64 , collection string , applyBalancing bool ) error {
func balanceVolumeServers ( commandEnv * CommandEnv , diskTypes [ ] types . DiskType , volumeReplicas map [ uint32 ] [ ] * VolumeReplica , nodes [ ] * Node , collection string , applyBalancing bool ) error {
for _ , diskType := range diskTypes {
for _ , diskType := range diskTypes {
if err := balanceVolumeServersByDiskType ( commandEnv , diskType , volumeReplicas , nodes , volumeSizeLimit , collection , applyBalancing ) ; err != nil {
if err := balanceVolumeServersByDiskType ( commandEnv , diskType , volumeReplicas , nodes , collection , applyBalancing ) ; err != nil {
return err
return err
}
}
}
}
@ -122,7 +119,7 @@ func balanceVolumeServers(commandEnv *CommandEnv, diskTypes []types.DiskType, vo
}
}
func balanceVolumeServersByDiskType ( commandEnv * CommandEnv , diskType types . DiskType , volumeReplicas map [ uint32 ] [ ] * VolumeReplica , nodes [ ] * Node , volumeSizeLimit uint64 , collection string , applyBalancing bool ) error {
func balanceVolumeServersByDiskType ( commandEnv * CommandEnv , diskType types . DiskType , volumeReplicas map [ uint32 ] [ ] * VolumeReplica , nodes [ ] * Node , collection string , applyBalancing bool ) error {
for _ , n := range nodes {
for _ , n := range nodes {
n . selectVolumes ( func ( v * master_pb . VolumeInformationMessage ) bool {
n . selectVolumes ( func ( v * master_pb . VolumeInformationMessage ) bool {
@ -164,7 +161,7 @@ func collectVolumeDiskTypes(t *master_pb.TopologyInfo) (diskTypes []types.DiskTy
for _ , dc := range t . DataCenterInfos {
for _ , dc := range t . DataCenterInfos {
for _ , r := range dc . RackInfos {
for _ , r := range dc . RackInfos {
for _ , dn := range r . DataNodeInfos {
for _ , dn := range r . DataNodeInfos {
for diskType , _ := range dn . DiskInfos {
for diskType := range dn . DiskInfos {
if _ , found := knownTypes [ diskType ] ; ! found {
if _ , found := knownTypes [ diskType ] ; ! found {
knownTypes [ diskType ] = true
knownTypes [ diskType ] = true
}
}
@ -172,7 +169,7 @@ func collectVolumeDiskTypes(t *master_pb.TopologyInfo) (diskTypes []types.DiskTy
}
}
}
}
}
}
for diskType , _ := range knownTypes {
for diskType := range knownTypes {
diskTypes = append ( diskTypes , types . ToDiskType ( diskType ) )
diskTypes = append ( diskTypes , types . ToDiskType ( diskType ) )
}
}
return
return
@ -244,7 +241,7 @@ func (n *Node) selectVolumes(fn func(v *master_pb.VolumeInformationMessage) bool
func sortWritableVolumes ( volumes [ ] * master_pb . VolumeInformationMessage ) {
func sortWritableVolumes ( volumes [ ] * master_pb . VolumeInformationMessage ) {
slices . SortFunc ( volumes , func ( a , b * master_pb . VolumeInformationMessage ) int {
slices . SortFunc ( volumes , func ( a , b * master_pb . VolumeInformationMessage ) int {
return int ( a . Size - b . Size )
return cmp . Compare ( a . Size , b . Size )
} )
} )
}
}
@ -270,7 +267,7 @@ func balanceSelectedVolume(commandEnv *CommandEnv, diskType types.DiskType, volu
for hasMoved {
for hasMoved {
hasMoved = false
hasMoved = false
slices . SortFunc ( nodesWithCapacity , func ( a , b * Node ) int {
slices . SortFunc ( nodesWithCapacity , func ( a , b * Node ) int {
return int ( a . localVolumeRatio ( capacityFunc ) - b . localVolumeRatio ( capacityFunc ) )
return cmp . Compare ( a . localVolumeRatio ( capacityFunc ) , b . localVolumeRatio ( capacityFunc ) )
} )
} )
if len ( nodesWithCapacity ) == 0 {
if len ( nodesWithCapacity ) == 0 {
fmt . Printf ( "no volume server found with capacity for %s" , diskType . ReadableString ( ) )
fmt . Printf ( "no volume server found with capacity for %s" , diskType . ReadableString ( ) )
@ -278,7 +275,8 @@ func balanceSelectedVolume(commandEnv *CommandEnv, diskType types.DiskType, volu
}
}
var fullNode * Node
var fullNode * Node
for fullNodeIndex := len ( nodesWithCapacity ) - 1 ; fullNodeIndex >= 0 ; fullNodeIndex -- {
var fullNodeIndex int
for fullNodeIndex = len ( nodesWithCapacity ) - 1 ; fullNodeIndex >= 0 ; fullNodeIndex -- {
fullNode = nodesWithCapacity [ fullNodeIndex ]
fullNode = nodesWithCapacity [ fullNodeIndex ]
if ! fullNode . isOneVolumeOnly ( ) {
if ! fullNode . isOneVolumeOnly ( ) {
break
break
@ -289,9 +287,7 @@ func balanceSelectedVolume(commandEnv *CommandEnv, diskType types.DiskType, volu
candidateVolumes = append ( candidateVolumes , v )
candidateVolumes = append ( candidateVolumes , v )
}
}
sortCandidatesFn ( candidateVolumes )
sortCandidatesFn ( candidateVolumes )
for i := 0 ; i < len ( nodesWithCapacity ) - 1 ; i ++ {
emptyNode := nodesWithCapacity [ i ]
for _ , emptyNode := range nodesWithCapacity [ : fullNodeIndex ] {
if ! ( fullNode . localVolumeRatio ( capacityFunc ) > idealVolumeRatio && emptyNode . localVolumeNextRatio ( capacityFunc ) <= idealVolumeRatio ) {
if ! ( fullNode . localVolumeRatio ( capacityFunc ) > idealVolumeRatio && emptyNode . localVolumeNextRatio ( capacityFunc ) <= idealVolumeRatio ) {
// no more volume servers with empty slots
// no more volume servers with empty slots
break
break