private void addTasksToStageInBatches(List<TaskWrapper> tasks, String verb, UpgradeContext ctx, String service,
                                          ProcessingComponent pc, Map<String, String> params) {
      if (tasks == null || tasks.isEmpty() || tasks.get(0).getTasks() == null || tasks.get(0).getTasks().isEmpty()) {
        return;
      }

      // Our assumption is that all of the tasks in the StageWrapper are of the same type.
      StageWrapper.Type type = tasks.get(0).getTasks().get(0).getStageWrapperType();

      // Expand some of the TaskWrappers into multiple based on the batch size.
      for (TaskWrapper tw : tasks) {
        List<Set<String>> hostSets = null;

        int parallel = getParallelHostCount(ctx, 1);
        final String rackYamlFile =
                ctx.getResolver().getValueFromDesiredConfigurations(ConfigHelper.CLUSTER_ENV, "rack_yaml_file_path");
        if (StringUtils.isNotEmpty(rackYamlFile)) {
          // If rack to hosts mapping yaml file path is present in cluster-env property: rack_yaml_file_path,
          // host sets will be formed based on rack i.e. based on parallel value, hosts present on same rack will
          // be part of the same batch. This is useful when we want to avoid possibility of single rack failure
          Map<String, Set<String>> hostsByRack = organizeHostsByRack(tw.getHosts(), rackYamlFile);
          List<Set<String>> hostSetsForRack;
          for (String rack : hostsByRack.keySet()) {
            hostSetsForRack = SetUtils.split(hostsByRack.get(rack), parallel);
            if (hostSets == null) {
              hostSets = hostSetsForRack;
            } else {
              hostSets.addAll(hostSetsForRack);
            }
          }
        } else {
          hostSets = SetUtils.split(tw.getHosts(), parallel);
        }
        int numBatchesNeeded = hostSets.size();
        int batchNum = 0;
        for (Set<String> hostSubset : hostSets) {
          batchNum++;

          String stageText = getStageText(verb, ctx.getComponentDisplay(service, pc.name), hostSubset, batchNum, numBatchesNeeded);

          StageWrapper stage = new StageWrapper(
              type,
              stageText,
              params,
              new TaskWrapper(service, pc.name, hostSubset, params, tw.getTasks()));
          m_stages.add(stage);
        }
      }
    }
Helper function to analyze a ProcessingComponent and add its task to stages, depending on the batch size.
@param tasks Collection of tasks for this stage
@param verb Verb string to use in the title of the task
@param ctx Upgrade Context
@param service Service
@param pc Processing Component
@param params Params to add to the stage.
ambari-server/src/main/java/org/apache/ambari/server/stack/upgrade/Grouping.java