protected List<BulkLoad> handleBulkLoad(List<TableName> tablesToBackup) throws IOException {
    Map<TableName, MergeSplitBulkloadInfo> toBulkload = new HashMap<>();
    List<BulkLoad> bulkLoads = backupManager.readBulkloadRows(tablesToBackup);
    FileSystem tgtFs;
    try {
      tgtFs = FileSystem.get(new URI(backupInfo.getBackupRootDir()), conf);
    } catch (URISyntaxException use) {
      throw new IOException("Unable to get FileSystem", use);
    }
    Path rootdir = CommonFSUtils.getRootDir(conf);
    Path tgtRoot = new Path(new Path(backupInfo.getBackupRootDir()), backupId);

    for (BulkLoad bulkLoad : bulkLoads) {
      TableName srcTable = bulkLoad.getTableName();
      MergeSplitBulkloadInfo bulkloadInfo =
        toBulkload.computeIfAbsent(srcTable, MergeSplitBulkloadInfo::new);
      String regionName = bulkLoad.getRegion();
      String fam = bulkLoad.getColumnFamily();
      String filename = FilenameUtils.getName(bulkLoad.getHfilePath());

      if (!tablesToBackup.contains(srcTable)) {
        LOG.debug("Skipping {} since it is not in tablesToBackup", srcTable);
        continue;
      }
      Path tblDir = CommonFSUtils.getTableDir(rootdir, srcTable);
      Path p = new Path(tblDir, regionName + Path.SEPARATOR + fam + Path.SEPARATOR + filename);

      String srcTableQualifier = srcTable.getQualifierAsString();
      String srcTableNs = srcTable.getNamespaceAsString();
      Path tgtFam = new Path(tgtRoot, srcTableNs + Path.SEPARATOR + srcTableQualifier
        + Path.SEPARATOR + regionName + Path.SEPARATOR + fam);
      if (!tgtFs.mkdirs(tgtFam)) {
        throw new IOException("couldn't create " + tgtFam);
      }
      Path tgt = new Path(tgtFam, filename);

      Path archiveDir = HFileArchiveUtil.getStoreArchivePath(conf, srcTable, regionName, fam);
      Path archive = new Path(archiveDir, filename);

      if (fs.exists(p)) {
        if (LOG.isTraceEnabled()) {
          LOG.trace("found bulk hfile {} in {} for {}", bulkLoad.getHfilePath(), p.getParent(),
            srcTableQualifier);
          LOG.trace("copying {} to {}", p, tgt);
        }
        bulkloadInfo.addActiveFile(p.toString());
      } else if (fs.exists(archive)) {
        LOG.debug("copying archive {} to {}", archive, tgt);
        bulkloadInfo.addArchiveFiles(archive.toString());
      }
    }

    for (MergeSplitBulkloadInfo bulkloadInfo : toBulkload.values()) {
      mergeSplitAndCopyBulkloadedHFiles(bulkloadInfo.getActiveFiles(),
        bulkloadInfo.getArchiveFiles(), bulkloadInfo.getSrcTable(), tgtFs);
    }

    return bulkLoads;
  }
Reads bulk load records from backup table, iterates through the records and forms the paths for
bulk loaded hfiles. Copies the bulk loaded hfiles to backup destination. This method does NOT
clean up the entries in the bulk load system table. Those entries should not be cleaned until
the backup is marked as complete.
@param tablesToBackup list of tables to be backed up
hbase-backup/src/main/java/org/apache/hadoop/hbase/backup/impl/IncrementalTableBackupClient.java