@Override
  public Iterable<FileStatus> getDeletableFiles(Iterable<FileStatus> files) {
    if (conf == null) {
      return files;
    }
    // obtain the Set of TableName's which have been fully backed up
    // so that we filter BulkLoad to be returned from server
    if (checkForFullyBackedUpTables) {
      if (connection == null) {
        return files;
      }

      try (BackupSystemTable tbl = new BackupSystemTable(connection)) {
        fullyBackedUpTables = new ArrayList<>(tbl.getTablesIncludedInBackups());
      } catch (IOException ioe) {
        LOG.error("Failed to get tables which have been fully backed up, skipping checking", ioe);
        return Collections.emptyList();
      }
      Collections.sort(fullyBackedUpTables);
    }
    final Set<String> hfileRefs;
    try {
      hfileRefs = loadHFileRefs(fullyBackedUpTables);
    } catch (IOException ioe) {
      LOG.error("Failed to read hfile references, skipping checking deletable files", ioe);
      return Collections.emptyList();
    }
    Iterable<FileStatus> deletables = Iterables.filter(files, file -> {
      // If the file is recent, be conservative and wait for one more scan of backup:system table
      if (file.getModificationTime() > secondPrevReadFromBackupTbl) {
        return false;
      }
      String hfile = file.getPath().getName();
      boolean foundHFileRef = hfileRefs.contains(hfile);
      return !foundHFileRef;
    });
    return deletables;
  }
Implementation of a file cleaner that checks if an hfile is still referenced by backup before
deleting it from hfile archive directory.
hbase-backup/src/main/java/org/apache/hadoop/hbase/backup/BackupHFileCleaner.java