public static Cluster randomShufflePartitions ( final Cluster nextCandidateCluster , final int randomSwapAttempts , final int randomSwapSuccesses , final List < Integer > randomSwapZoneIds , List < StoreDefinition > storeDefs ) { List < Integer > zoneIds = null ; if ( randomSwapZoneIds . isEmpty ( ) ) { zoneIds = new ArrayList < Integer > ( nextCandidateCluster . getZoneIds ( ) ) ; } else { zoneIds = new ArrayList < Integer > ( randomSwapZoneIds ) ; } List < Integer > nodeIds = new ArrayList < Integer > ( ) ; Cluster returnCluster = Cluster . cloneCluster ( nextCandidateCluster ) ; double currentUtility = new PartitionBalance ( returnCluster , storeDefs ) . getUtility ( ) ; int successes = 0 ; for ( int i = 0 ; i < randomSwapAttempts ; i ++ ) { // Iterate over zone ids to decide which node ids to include for // intra-zone swapping. // In future, if there is a need to support inter-zone swapping, // then just remove the // zone specific logic that populates nodeIdSet and add all nodes // from across all zones. int zoneIdOffset = i % zoneIds . size ( ) ; Set < Integer > nodeIdSet = nextCandidateCluster . getNodeIdsInZone ( zoneIds . get ( zoneIdOffset ) ) ; nodeIds = new ArrayList < Integer > ( nodeIdSet ) ; Collections . shuffle ( zoneIds , new Random ( System . currentTimeMillis ( ) ) ) ; Cluster shuffleResults = swapRandomPartitionsAmongNodes ( returnCluster , nodeIds ) ; double nextUtility = new PartitionBalance ( shuffleResults , storeDefs ) . getUtility ( ) ; if ( nextUtility < currentUtility ) { System . out . println ( "Swap improved max-min ratio: " + currentUtility + " -> " + nextUtility + " (improvement " + successes + " on swap attempt " + i + ")" ) ; successes ++ ; returnCluster = shuffleResults ; currentUtility = nextUtility ; } if ( successes >= randomSwapSuccesses ) { // Enough successes, move on. break ; } } return returnCluster ; }
Randomly shuffle partitions between nodes within every zone .