/** Update {@link lastStatus} so that it can be viewed from outside */
 private void updateStatus() {
   int highPriorityFiles = 0;
   int lowPriorityFiles = 0;
   List<JobStatus> jobs = new ArrayList<JobStatus>();
   List<String> highPriorityFileNames = new ArrayList<String>();
   for (Map.Entry<String, CorruptFileInfo> e : fileIndex.entrySet()) {
     String fileName = e.getKey();
     CorruptFileInfo fileInfo = e.getValue();
     if (fileInfo.getHighestPriority() > 0) {
       highPriorityFileNames.add(fileName);
       highPriorityFiles += 1;
     } else {
       lowPriorityFiles += 1;
     }
   }
   for (Job job : jobIndex.keySet()) {
     String url = job.getTrackingURL();
     String name = job.getJobName();
     JobID jobId = job.getID();
     jobs.add(new BlockFixer.JobStatus(jobId, name, url));
   }
   lastStatus =
       new BlockFixer.Status(highPriorityFiles, lowPriorityFiles, jobs, highPriorityFileNames);
   RaidNodeMetrics.getInstance().corruptFilesHighPri.set(highPriorityFiles);
   RaidNodeMetrics.getInstance().corruptFilesLowPri.set(lowPriorityFiles);
   LOG.info("Update status done." + lastStatus.toString());
 }
  // Compute integer priority. Urgency is indicated by higher numbers.
  Map<String, Integer> computePriorities(FileSystem fs, Map<String, Integer> corruptFiles)
      throws IOException {

    Map<String, Integer> corruptFilePriority = new HashMap<String, Integer>();
    String[] parityDestPrefixes = destPrefixes();
    Set<String> srcDirsToWatchOutFor = new HashSet<String>();
    // Loop over parity files once.
    for (Iterator<String> it = corruptFiles.keySet().iterator(); it.hasNext(); ) {
      String p = it.next();
      if (BlockFixer.isSourceFile(p, parityDestPrefixes)) {
        continue;
      }
      // Find the parent of the parity file.
      Path parent = new Path(p).getParent();
      // If the file was a HAR part file, the parent will end with _raid.har. In
      // that case, the parity directory is the parent of the parent.
      if (parent.toUri().getPath().endsWith(RaidNode.HAR_SUFFIX)) {
        parent = parent.getParent();
      }
      String parentUriPath = parent.toUri().getPath();
      // Remove the RAID prefix to get the source dir.
      srcDirsToWatchOutFor.add(parentUriPath.substring(parentUriPath.indexOf(Path.SEPARATOR, 1)));
      int numCorrupt = corruptFiles.get(p);
      int priority = (numCorrupt > 1) ? 1 : 0;
      CorruptFileInfo fileInfo = fileIndex.get(p);
      if (fileInfo == null || priority > fileInfo.getHighestPriority()) {
        corruptFilePriority.put(p, priority);
      }
    }
    // Loop over src files now.
    for (Iterator<String> it = corruptFiles.keySet().iterator(); it.hasNext(); ) {
      String p = it.next();
      if (BlockFixer.isSourceFile(p, parityDestPrefixes)) {
        if (BlockFixer.doesParityDirExist(fs, p, parityDestPrefixes)) {
          int numCorrupt = corruptFiles.get(p);
          FileStatus stat = fs.getFileStatus(new Path(p));
          int priority = 0;
          if (stat.getReplication() > 1) {
            // If we have a missing block when replication > 1, it is high pri.
            priority = 1;
          } else {
            // Replication == 1. Assume Reed Solomon parity exists.
            // If we have more than one missing block when replication == 1, then
            // high pri.
            priority = (numCorrupt > 1) ? 1 : 0;
          }
          // If priority is low, check if the scan of corrupt parity files found
          // the src dir to be risky.
          if (priority == 0) {
            Path parent = new Path(p).getParent();
            String parentUriPath = parent.toUri().getPath();
            if (srcDirsToWatchOutFor.contains(parentUriPath)) {
              priority = 1;
            }
          }
          CorruptFileInfo fileInfo = fileIndex.get(p);
          if (fileInfo == null || priority > fileInfo.getHighestPriority()) {
            corruptFilePriority.put(p, priority);
          }
        }
      }
    }
    return corruptFilePriority;
  }