/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.hadoop.raid;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.Random;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.channels.SocketChannel;

import org.apache.hadoop.util.DataChecksum;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.hdfs.protocol.Block;
import org.apache.hadoop.hdfs.protocol.DataTransferProtocol;
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
import org.apache.hadoop.hdfs.protocol.FSConstants;
import org.apache.hadoop.hdfs.protocol.FSConstants.DatanodeReportType;
import org.apache.hadoop.hdfs.protocol.LocatedBlock;
import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
import org.apache.hadoop.hdfs.server.common.HdfsConstants;
import org.apache.hadoop.hdfs.server.datanode.FSDataset;
import org.apache.hadoop.hdfs.server.datanode.RaidBlockSender;
import org.apache.hadoop.io.Text;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.ChecksumException;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.hdfs.BlockMissingException;
import org.apache.hadoop.hdfs.RaidDFSUtil;
import org.apache.hadoop.util.StringUtils;
import org.apache.hadoop.net.NetUtils;

import org.apache.hadoop.raid.RaidNode;
import org.apache.hadoop.raid.RaidUtils;

/**
 * This class fixes source file blocks using the parity file,
 * and parity file blocks using the source file.
 * It periodically fetches the list of corrupt files from the namenode,
 * and figures out the location of the bad block by reading through
 * the corrupt file.
 */
public class BlockFixer implements Runnable {
  public static final Log LOG = LogFactory.getLog(
                                  "org.apache.hadoop.raid.BlockFixer");
  private java.util.HashMap<String, java.util.Date> history;
  private int blockFixInterval = 60*1000; // 1min
  private long numFilesFixed = 0;
  private Configuration conf;
  private String xorPrefix;
  private XOREncoder xorEncoder;
  private XORDecoder xorDecoder;

  boolean running = true;

  public BlockFixer(Configuration conf) throws IOException {
    this.conf = conf;
    history = new java.util.HashMap<String, java.util.Date>();
    blockFixInterval = conf.getInt("raid.blockfix.interval",
                                   blockFixInterval);
    xorPrefix = RaidNode.getDestinationPath(conf).toUri().getPath();
    int stripeLength = RaidNode.getStripeLength(conf);
    xorEncoder = new XOREncoder(conf, stripeLength);
    xorDecoder = new XORDecoder(conf, stripeLength);
  }

  public void run() {
    while (running) {
      try {
        LOG.info("BlockFixer continuing to run...");
        doFix();
      } catch (Exception e) {
        LOG.error(StringUtils.stringifyException(e));
      } catch (Error err) {
        LOG.error("Exiting after encountering " +
                    StringUtils.stringifyException(err));
        throw err;
      }
    }
  }

  public long filesFixed() {
    return numFilesFixed;
  }

  void doFix() throws InterruptedException, IOException {
    while (running) {
      // Sleep before proceeding to fix files.
      Thread.sleep(blockFixInterval);

      // Purge history older than the history interval.
      purgeHistory();

      List<Path> corruptFiles = getCorruptFiles();
      if (corruptFiles.isEmpty()) {
        // If there are no corrupt files, retry after some time.
        continue;
      }
      LOG.info("Found " + corruptFiles.size() + " corrupt files.");

      sortCorruptFiles(corruptFiles);

      for (Path srcPath: corruptFiles) {
        if (!running) break;
        try {
          fixFile(srcPath);
        } catch (IOException ie) {
          LOG.error("Hit error while processing " + srcPath +
            ": " + StringUtils.stringifyException(ie));
          // Do nothing, move on to the next file.
        }
      }
    }
  }


  void fixFile(Path srcPath) throws IOException {
    if (RaidNode.isParityHarPartFile(srcPath)) {
      processCorruptParityHarPartFile(srcPath);
      return;
    }

    // The corrupted file is a XOR parity file
    if (isXorParityFile(srcPath)) {
      processCorruptParityFile(srcPath, xorEncoder);
      return;
    }

    // The corrupted file is a source file

    // Do we have a parity file for this file?
    RaidNode.ParityFilePair ppair = null;
    Decoder decoder = null;
    Path destPath = null;
    try {
      destPath = RaidNode.getDestinationPath(conf);
      ppair = RaidNode.getParityFile(destPath, srcPath, conf);
      if (ppair != null) {
        decoder = xorDecoder;
      }
    } catch (FileNotFoundException e) {
    }
    // If we have a parity file, process the file and fix it.
    if (ppair != null) {
      processCorruptFile(srcPath, destPath, decoder);
    }
  }

  /**
   * We maintain history of fixed files because a fixed file may appear in
   * the list of corrupt files if we loop around too quickly.
   * This function removes the old items in the history so that we can
   * recognize files that have actually become corrupt since being fixed.
   */
  void purgeHistory() {
    // Default history interval is 1 hour.
    long historyInterval = conf.getLong(
                             "raid.blockfix.history.interval", 3600*1000);
    java.util.Date cutOff = new java.util.Date(
                                   System.currentTimeMillis()-historyInterval);
    List<String> toRemove = new java.util.ArrayList<String>();

    for (String key: history.keySet()) {
      java.util.Date item = history.get(key);
      if (item.before(cutOff)) {
        toRemove.add(key);
      }
    }
    for (String key: toRemove) {
      LOG.info("Removing " + key + " from history");
      history.remove(key);
    }
  }

  /**
   * @return A list of corrupt files as obtained from the namenode
   */
  List<Path> getCorruptFiles() throws IOException {
    DistributedFileSystem dfs = getDFS(new Path("/"));

    String[] nnCorruptFiles = RaidDFSUtil.getCorruptFiles(conf);
    List<Path> corruptFiles = new LinkedList<Path>();
    for (String file: nnCorruptFiles) {
      if (!history.containsKey(file)) {
        corruptFiles.add(new Path(file));
      }
    }
    RaidUtils.filterTrash(conf, corruptFiles);
    return corruptFiles;
  }

  /**
   * Sorts source files ahead of parity files.
   */
  void sortCorruptFiles(List<Path> files) {
    // TODO: We should first fix the files that lose more blocks
    Comparator<Path> comp = new Comparator<Path>() {
      public int compare(Path p1, Path p2) {
        if (isXorParityFile(p2)) {
          // If p2 is a parity file, p1 is smaller.
          return -1;
        }
        if (isXorParityFile(p1)) {
          // If p1 is a parity file, p2 is smaller.
          return 1;
        }
        // If both are source files, they are equal.
        return 0;
      }
    };
    Collections.sort(files, comp);
  }


  /**
   * Returns a DistributedFileSystem hosting the path supplied.
   */
  private DistributedFileSystem getDFS(Path p) throws IOException {
    return (DistributedFileSystem) p.getFileSystem(conf);
  }

  /**
   * Reads through a corrupt source file fixing corrupt blocks on the way.
   * @param srcPath Path identifying the corrupt file.
   * @throws IOException
   */
  void processCorruptFile(Path srcPath, Path destPath, Decoder decoder)
      throws IOException {
    LOG.info("Processing corrupt file " + srcPath);

    DistributedFileSystem srcFs = getDFS(srcPath);
    FileStatus srcStat = srcFs.getFileStatus(srcPath);
    long blockSize = srcStat.getBlockSize();
    long srcFileSize = srcStat.getLen();
    String uriPath = srcPath.toUri().getPath();

    int numBlocksFixed = 0;
    List<LocatedBlock> corrupt =
      RaidDFSUtil.corruptBlocksInFile(srcFs, uriPath, 0, srcFileSize);
    for (LocatedBlock lb: corrupt) {
      Block corruptBlock = lb.getBlock();
      long corruptOffset = lb.getStartOffset();

      LOG.info("Found corrupt block " + corruptBlock +
          ", offset " + corruptOffset);

      final long blockContentsSize =
        Math.min(blockSize, srcFileSize - corruptOffset);
      File localBlockFile =
        File.createTempFile(corruptBlock.getBlockName(), ".tmp");
      localBlockFile.deleteOnExit();

      try {
        RaidNode.ParityFilePair parityPair = RaidNode.getParityFile(
            destPath, srcPath, conf);

        decoder.recoverBlockToFile(srcFs, srcPath, parityPair.getFileSystem(),
          parityPair.getPath(), blockSize, corruptOffset, localBlockFile,
          blockContentsSize);

        // We have a the contents of the block, send them.
        DatanodeInfo datanode = chooseDatanode(lb.getLocations());
        computeMetdataAndSendFixedBlock(
          datanode, localBlockFile, lb, blockContentsSize);
        numBlocksFixed++;

        LOG.info("Adding " + srcPath + " to history");
        history.put(srcPath.toString(), new java.util.Date());
      } finally {
        localBlockFile.delete();
      }
    }
    LOG.info("Fixed " + numBlocksFixed + " blocks in " + srcPath);
    numFilesFixed++;
  }

  boolean isXorParityFile(Path p) {
    String pathStr = p.toUri().getPath();
    if (pathStr.contains(RaidNode.HAR_SUFFIX)) {
      return false;
    }
    return pathStr.startsWith(xorPrefix);
  }

  /**
   * Reads through a parity file, fixing corrupt blocks on the way.
   * This function uses the corresponding source file to regenerate parity
   * file blocks.
   */
  void processCorruptParityFile(Path parityPath, Encoder encoder)
      throws IOException {
    LOG.info("Processing corrupt file " + parityPath);
    Path srcPath = sourcePathFromParityPath(parityPath);
    if (srcPath == null) {
      LOG.warn("Unusable parity file " + parityPath);
      return;
    }

    DistributedFileSystem parityFs = getDFS(parityPath);
    FileStatus parityStat = parityFs.getFileStatus(parityPath);
    long blockSize = parityStat.getBlockSize();
    long parityFileSize = parityStat.getLen();
    FileStatus srcStat = getDFS(srcPath).getFileStatus(srcPath);
    long srcFileSize = srcStat.getLen();

    // Check timestamp.
    if (srcStat.getModificationTime() != parityStat.getModificationTime()) {
      LOG.info("Mismatching timestamp for " + srcPath + " and " + parityPath +
               ", moving on...");
      return;
    }

    String uriPath = parityPath.toUri().getPath();
    int numBlocksFixed = 0;
    List<LocatedBlock> corrupt = RaidDFSUtil.corruptBlocksInFile(
      parityFs, uriPath, 0, parityFileSize);
    for (LocatedBlock lb: corrupt) {
      Block corruptBlock = lb.getBlock();
      long corruptOffset = lb.getStartOffset();

      LOG.info("Found corrupt block " + corruptBlock +
          ", offset " + corruptOffset);

      File localBlockFile =
        File.createTempFile(corruptBlock.getBlockName(), ".tmp");
      localBlockFile.deleteOnExit();

      try {
        encoder.recoverParityBlockToFile(parityFs, srcPath, srcFileSize,
            blockSize, parityPath, corruptOffset, localBlockFile);
        // We have a the contents of the block, send them.
        DatanodeInfo datanode = chooseDatanode(lb.getLocations());
        computeMetdataAndSendFixedBlock(
          datanode, localBlockFile, lb, blockSize);

        numBlocksFixed++;
        LOG.info("Adding " + parityPath + " to history");
        history.put(parityPath.toString(), new java.util.Date());
      } finally {
        localBlockFile.delete();
      }
    }
    LOG.info("Fixed " + numBlocksFixed + " blocks in " + parityPath);
    numFilesFixed++;
  }

  /**
   * Reads through a parity HAR part file, fixing corrupt blocks on the way.
   * A HAR block can contain many file blocks, as long as the HAR part file
   * block size is a multiple of the file block size.
   */
  void processCorruptParityHarPartFile(Path partFile) throws IOException {
    LOG.info("Processing corrupt file " + partFile);
    // Get some basic information.
    DistributedFileSystem dfs = getDFS(partFile);
    FileStatus partFileStat = dfs.getFileStatus(partFile);
    long partFileSize = partFileStat.getLen();
    long partFileBlockSize = partFileStat.getBlockSize();
    LOG.info(partFile + " has block size " + partFileBlockSize);

    // Find the path to the index file.
    // Parity file HARs are only one level deep, so the index files is at the
    // same level as the part file.
    String harDirectory = partFile.toUri().getPath(); // Temporarily.
    harDirectory =
      harDirectory.substring(0, harDirectory.lastIndexOf(Path.SEPARATOR));
    Path indexFile = new Path(harDirectory + "/" + HarIndex.indexFileName);
    FileStatus indexStat = dfs.getFileStatus(indexFile);
    // Parses through the HAR index file.
    HarIndex harIndex = new HarIndex(dfs.open(indexFile), indexStat.getLen());

    String uriPath = partFile.toUri().getPath();
    int numBlocksFixed = 0;
    List<LocatedBlock> corrupt = RaidDFSUtil.corruptBlocksInFile(
      dfs, uriPath, 0, partFileSize);
    for (LocatedBlock lb: corrupt) {
      Block corruptBlock = lb.getBlock();
      long corruptOffset = lb.getStartOffset();

      File localBlockFile =
        File.createTempFile(corruptBlock.getBlockName(), ".tmp");
      localBlockFile.deleteOnExit();
      processCorruptParityHarPartBlock(
        dfs, partFile, corruptBlock, corruptOffset, partFileStat, harIndex,
        localBlockFile);
      // Now we have recovered the part file block locally, send it.
      try {
        DatanodeInfo datanode = chooseDatanode(lb.getLocations());
        computeMetdataAndSendFixedBlock(datanode, localBlockFile,
          lb, localBlockFile.length());
        numBlocksFixed++;

        LOG.info("Adding " + partFile + " to history");
        history.put(partFile.toString(), new java.util.Date());
      } finally {
        localBlockFile.delete();
      }
    }
    LOG.info("Fixed " + numBlocksFixed + " blocks in " + partFile);
    numFilesFixed++;
  }

  /**
   * This fixes a single part file block by recovering in sequence each
   * parity block in the part file block.
   */
  private void processCorruptParityHarPartBlock(
    FileSystem dfs, Path partFile, Block corruptBlock, long corruptOffset,
    FileStatus partFileStat, HarIndex harIndex, File localBlockFile)
    throws IOException {
    String partName = partFile.toUri().getPath(); // Temporarily.
    partName = partName.substring(1 + partName.lastIndexOf(Path.SEPARATOR));

    OutputStream out = new FileOutputStream(localBlockFile);

    try {
      // A HAR part file block could map to several parity files. We need to
      // use all of them to recover this block.
      final long corruptEnd = Math.min(corruptOffset + partFileStat.getBlockSize(),
                                      partFileStat.getLen());
      for (long offset = corruptOffset; offset < corruptEnd; ) {
        HarIndex.IndexEntry entry = harIndex.findEntry(partName, offset);
        if (entry == null) {
          String msg = "Corrupt index file has no matching index entry for " +
            partName + ":" + offset;
          LOG.warn(msg);
          throw new IOException(msg);
        }
        Path parityFile = new Path(entry.fileName);
        Encoder encoder;
        if (isXorParityFile(parityFile)) {
          encoder = xorEncoder;
        } else {
          String msg = "Could not figure out parity file correctly";
          LOG.warn(msg);
          throw new IOException(msg);
        }
        Path srcFile = sourcePathFromParityPath(parityFile);
        FileStatus srcStat = dfs.getFileStatus(srcFile);
        if (srcStat.getModificationTime() != entry.mtime) {
          String msg = "Modification times of " + parityFile + " and " + srcFile +
            " do not match.";
          LOG.warn(msg);
          throw new IOException(msg);
        }
        long corruptOffsetInParity = offset - entry.startOffset;
        LOG.info(partFile + ":" + offset + " maps to " +
                 parityFile + ":" + corruptOffsetInParity +
                 " and will be recovered from " + srcFile);
        encoder.recoverParityBlockToStream(dfs, srcFile, srcStat.getLen(),
          srcStat.getBlockSize(), parityFile, corruptOffsetInParity, out);
        // Finished recovery of one parity block. Since a parity block has the
        // same size as a source block, we can move offset by source block size.
        offset += srcStat.getBlockSize();
        LOG.info("Recovered " + srcStat.getBlockSize() + " part file bytes ");
        if (offset > corruptEnd) {
          String msg =
            "Recovered block spills across part file blocks. Cannot continue...";
          throw new IOException(msg);
        }
      }
    } finally {
      out.close();
    }
  }

  /**
   * Choose a datanode (hostname:portnumber). The datanode is chosen at
   * random from the live datanodes.
   * @param locationsToAvoid locations to avoid.
   * @return A string in the format name:port.
   * @throws IOException
   */
  private DatanodeInfo chooseDatanode(DatanodeInfo[] locationsToAvoid)
    throws IOException {
    DistributedFileSystem dfs = getDFS(new Path("/"));
    DatanodeInfo[] live = dfs.getClient().datanodeReport(
                                                 DatanodeReportType.LIVE);
    LOG.info("Choosing a datanode from " + live.length +
      " live nodes while avoiding " + locationsToAvoid.length);
    Random rand = new Random();
    DatanodeInfo chosen = null;
    int maxAttempts = 1000;
    for (int i = 0; i < maxAttempts && chosen == null; i++) {
      int idx = rand.nextInt(live.length);
      chosen = live[idx];
      for (DatanodeInfo avoid: locationsToAvoid) {
        if (chosen.name.equals(avoid.name)) {
          LOG.info("Avoiding " + avoid.name);
          chosen = null;
          break;
        }
      }
    }
    if (chosen == null) {
      throw new IOException("Could not choose datanode");
    }
    LOG.info("Choosing datanode " + chosen.name);
    return chosen;
  }

  /**
   * Reads data from the data stream provided and computes metadata.
   */
  static DataInputStream computeMetadata(
    Configuration conf, InputStream dataStream) throws IOException {
    ByteArrayOutputStream mdOutBase = new ByteArrayOutputStream(1024*1024);
    DataOutputStream mdOut = new DataOutputStream(mdOutBase);

    // First, write out the version.
    mdOut.writeShort(FSDataset.METADATA_VERSION);

    // Create a summer and write out its header.
    int bytesPerChecksum = conf.getInt("io.bytes.per.checksum", 512);
    DataChecksum sum = DataChecksum.newDataChecksum(
                        DataChecksum.CHECKSUM_CRC32,
                        bytesPerChecksum);
    sum.writeHeader(mdOut);

    // Buffer to read in a chunk of data.
    byte[] buf = new byte[bytesPerChecksum];
    // Buffer to store the checksum bytes.
    byte[] chk = new byte[sum.getChecksumSize()];

    // Read data till we reach the end of the input stream.
    int bytesSinceFlush = 0;
    while (true) {
      // Read some bytes.
      int bytesRead = dataStream.read(
        buf, bytesSinceFlush, bytesPerChecksum-bytesSinceFlush);
      if (bytesRead == -1) {
        if (bytesSinceFlush > 0) {
          boolean reset = true;
          sum.writeValue(chk, 0, reset); // This also resets the sum.
          // Write the checksum to the stream.
          mdOut.write(chk, 0, chk.length);
          bytesSinceFlush = 0;
        }
        break;
      }
      // Update the checksum.
      sum.update(buf, bytesSinceFlush, bytesRead);
      bytesSinceFlush += bytesRead;

      // Flush the checksum if necessary.
      if (bytesSinceFlush == bytesPerChecksum) {
        boolean reset = true;
        sum.writeValue(chk, 0, reset); // This also resets the sum.
        // Write the checksum to the stream.
        mdOut.write(chk, 0, chk.length);
        bytesSinceFlush = 0;
      }
    }

    byte[] mdBytes = mdOutBase.toByteArray();
    return new DataInputStream(new ByteArrayInputStream(mdBytes));
  }

  private void computeMetdataAndSendFixedBlock(
    DatanodeInfo datanode,
    File localBlockFile, LocatedBlock block, long blockSize
    ) throws IOException {

    LOG.info("Computing metdata");
    InputStream blockContents = null;
    DataInputStream blockMetadata = null;
    try {
      blockContents = new FileInputStream(localBlockFile);
      blockMetadata = computeMetadata(conf, blockContents);
      blockContents.close();
      // Reopen
      blockContents = new FileInputStream(localBlockFile);
      sendFixedBlock(datanode, blockContents, blockMetadata, block, blockSize);
    } finally {
      if (blockContents != null) {
        blockContents.close();
        blockContents = null;
      }
      if (blockMetadata != null) {
        blockMetadata.close();
        blockMetadata = null;
      }
    }
  }

  /**
   * Send a generated block to a datanode.
   * @param datanode Chosen datanode name in host:port form.
   * @param blockContents Stream with the block contents.
   * @param corruptBlock Block identifying the block to be sent.
   * @param blockSize size of the block.
   * @throws IOException
   */
  private void sendFixedBlock(
    DatanodeInfo datanode,
    final InputStream blockContents, DataInputStream metadataIn,
    LocatedBlock block, long blockSize
    ) throws IOException {
    InetSocketAddress target = NetUtils.createSocketAddr(datanode.name);
    Socket sock = SocketChannel.open().socket();

    int readTimeout =  conf.getInt(
        "raid.blockfix.read.timeout", HdfsConstants.READ_TIMEOUT);
    NetUtils.connect(sock, target, readTimeout);
    sock.setSoTimeout(readTimeout);

    int writeTimeout = conf.getInt(
        "raid.blockfix.write.timeout", HdfsConstants.WRITE_TIMEOUT);

    OutputStream baseStream = NetUtils.getOutputStream(sock, writeTimeout);
    DataOutputStream out = new DataOutputStream(
        new BufferedOutputStream(baseStream, FSConstants.SMALL_BUFFER_SIZE));

    boolean corruptChecksumOk = false;
    boolean chunkOffsetOK = false;
    boolean verifyChecksum = true;
    boolean transferToAllowed = false;

    try {
      LOG.info("Sending block " + block.getBlock() +
          " from " + sock.getLocalSocketAddress().toString() +
          " to " + sock.getRemoteSocketAddress().toString() +
          " " + blockSize + " bytes");
      RaidBlockSender blockSender = new RaidBlockSender(
          block.getBlock(), blockSize, 0, blockSize,
          corruptChecksumOk, chunkOffsetOK, verifyChecksum, transferToAllowed,
          metadataIn, new RaidBlockSender.InputStreamFactory() {
          @Override
          public InputStream createStream(long offset) throws IOException {
            // we are passing 0 as the offset above, so we can safely ignore
            // the offset passed
            return blockContents;
          }
        });

      DatanodeInfo[] nodes = new DatanodeInfo[]{datanode};
      DataTransferProtocol.Sender.opWriteBlock(
        out, block.getBlock(), 1,
        DataTransferProtocol.BlockConstructionStage.PIPELINE_SETUP_CREATE,
        0, blockSize, 0, "", null, nodes, block.getBlockToken());
      blockSender.sendBlock(out, baseStream);

      LOG.info("Sent block " + block.getBlock() + " to " + datanode.name);
    } finally {
      out.close();
    }
  }

  Path sourcePathFromParityPath(Path parityPath) {
    String parityPathStr = parityPath.toUri().getPath();
    if (parityPathStr.startsWith(xorPrefix)) {
      // Remove the prefix to get the source file.
      String src = parityPathStr.replaceFirst(xorPrefix, "");
      return new Path(src);
    }
    return null;
  }
}

