@Override
    public Void call() throws Exception {
      // Taking the region read lock prevents the individual region from being closed while a
      // snapshot is in progress. This is helpful but not sufficient for preventing races with
      // snapshots that involve multiple regions and regionservers. It is still possible to have
      // an interleaving such that globally regions are missing, so we still need the verification
      // step.
      LOG.debug("Starting snapshot operation on " + region);
      region.startRegionOperation(Operation.SNAPSHOT);
      try {
        if (skipFlush) {
          /*
           * This is to take an online-snapshot without force a coordinated flush to prevent pause
           * The snapshot type is defined inside the snapshot description. FlushSnapshotSubprocedure
           * should be renamed to distributedSnapshotSubprocedure, and the flush() behavior can be
           * turned on/off based on the flush type. To minimized the code change, class name is not
           * changed.
           */
          LOG.debug("take snapshot without flush memstore first");
        } else {
          LOG.debug("Flush Snapshotting region " + region.toString() + " started...");
          boolean succeeded = false;
          long readPt = region.getReadPoint(IsolationLevel.READ_COMMITTED);
          for (int i = 0; i < MAX_RETRIES; i++) {
            FlushResult res = region.flush(true);
            if (res.getResult() == FlushResult.Result.CANNOT_FLUSH) {
              // CANNOT_FLUSH may mean that a flush is already on-going
              // we need to wait for that flush to complete
              region.waitForFlushes();
              if (region.getMaxFlushedSeqId() >= readPt) {
                // writes at the start of the snapshot have been persisted
                succeeded = true;
                break;
              }
            } else {
              succeeded = true;
              break;
            }
          }
          if (!succeeded) {
            throw new IOException("Unable to complete flush after " + MAX_RETRIES + " attempts");
          }
        }
        region.addRegionToSnapshot(snapshotDesc, monitor);
        if (skipFlush) {
          LOG.debug("... SkipFlush Snapshotting region " + region.toString() + " completed.");
        } else {
          LOG.debug("... Flush Snapshotting region " + region.toString() + " completed.");
        }
      } finally {
        LOG.debug("Closing snapshot operation on " + region);
        region.closeRegionOperation(Operation.SNAPSHOT);
      }
      return null;
    }
Callable for adding files to snapshot manifest working dir. Ready for multithreading.
hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/snapshot/FlushSnapshotSubprocedure.java