public BalanceResponse balance(BalanceRequest request) throws IOException {
    checkInitialized();

    BalanceResponse.Builder responseBuilder = BalanceResponse.newBuilder();

    if (loadBalancerStateStore == null || !(loadBalancerStateStore.get() || request.isDryRun())) {
      return responseBuilder.build();
    }

    if (skipRegionManagementAction("balancer")) {
      return responseBuilder.build();
    }

    synchronized (this.balancer) {
      // Only allow one balance run at at time.
      if (this.assignmentManager.hasRegionsInTransition()) {
        List<RegionStateNode> regionsInTransition = assignmentManager.getRegionsInTransition();
        // if hbase:meta region is in transition, result of assignment cannot be recorded
        // ignore the force flag in that case
        boolean metaInTransition = assignmentManager.isMetaRegionInTransition();
        List<RegionStateNode> toPrint = regionsInTransition;
        int max = 5;
        boolean truncated = false;
        if (regionsInTransition.size() > max) {
          toPrint = regionsInTransition.subList(0, max);
          truncated = true;
        }

        if (!request.isIgnoreRegionsInTransition() || metaInTransition) {
          LOG.info("Not running balancer (ignoreRIT=false" + ", metaRIT=" + metaInTransition
            + ") because " + regionsInTransition.size() + " region(s) in transition: " + toPrint
            + (truncated ? "(truncated list)" : ""));
          return responseBuilder.build();
        }
      }
      if (this.serverManager.areDeadServersInProgress()) {
        LOG.info("Not running balancer because processing dead regionserver(s): "
          + this.serverManager.getDeadServers());
        return responseBuilder.build();
      }

      if (this.cpHost != null) {
        try {
          if (this.cpHost.preBalance(request)) {
            LOG.debug("Coprocessor bypassing balancer request");
            return responseBuilder.build();
          }
        } catch (IOException ioe) {
          LOG.error("Error invoking master coprocessor preBalance()", ioe);
          return responseBuilder.build();
        }
      }

      Map<TableName, Map<ServerName, List<RegionInfo>>> assignments =
        this.assignmentManager.getRegionStates().getAssignmentsForBalancer(tableStateManager,
          this.serverManager.getOnlineServersList());
      for (Map<ServerName, List<RegionInfo>> serverMap : assignments.values()) {
        serverMap.keySet().removeAll(this.serverManager.getDrainingServersList());
      }

      // Give the balancer the current cluster state.
      this.balancer.updateClusterMetrics(getClusterMetricsWithoutCoprocessor());

      List<RegionPlan> plans = this.balancer.balanceCluster(assignments);

      responseBuilder.setBalancerRan(true).setMovesCalculated(plans == null ? 0 : plans.size());

      if (skipRegionManagementAction("balancer")) {
        // make one last check that the cluster isn't shutting down before proceeding.
        return responseBuilder.build();
      }

      // For dry run we don't actually want to execute the moves, but we do want
      // to execute the coprocessor below
      List<RegionPlan> sucRPs =
        request.isDryRun() ? Collections.emptyList() : executeRegionPlansWithThrottling(plans);

      if (this.cpHost != null) {
        try {
          this.cpHost.postBalance(request, sucRPs);
        } catch (IOException ioe) {
          // balancing already succeeded so don't change the result
          LOG.error("Error invoking master coprocessor postBalance()", ioe);
        }
      }

      responseBuilder.setMovesExecuted(sucRPs.size());
    }

    // If LoadBalancer did not generate any plans, it means the cluster is already balanced.
    // Return true indicating a success.
    return responseBuilder.build();
  }
Checks master state before initiating action over region topology.
@param action the name of the action under consideration, for logging.
@return {@code true} when the caller should exit early, {@code false} otherwise.
hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java