/**
  * Recursively compute the difference between snapshots under a given directory/file.
  *
  * @param node The directory/file under which the diff is computed.
  * @param parentPath Relative path (corresponding to the snapshot root) of the node's parent.
  * @param diffReport data structure used to store the diff.
  */
 private void computeDiffRecursively(
     INode node, List<byte[]> parentPath, SnapshotDiffInfo diffReport) {
   ChildrenDiff diff = new ChildrenDiff();
   byte[][] relativePath = parentPath.toArray(new byte[parentPath.size()][]);
   if (node.isDirectory()) {
     INodeDirectory dir = node.asDirectory();
     if (dir instanceof INodeDirectoryWithSnapshot) {
       INodeDirectoryWithSnapshot sdir = (INodeDirectoryWithSnapshot) dir;
       boolean change = sdir.computeDiffBetweenSnapshots(diffReport.from, diffReport.to, diff);
       if (change) {
         diffReport.addDirDiff(sdir, relativePath, diff);
       }
     }
     ReadOnlyList<INode> children =
         dir.getChildrenList(diffReport.isFromEarlier() ? diffReport.to : diffReport.from);
     for (INode child : children) {
       final byte[] name = child.getLocalNameBytes();
       if (diff.searchIndex(ListType.CREATED, name) < 0
           && diff.searchIndex(ListType.DELETED, name) < 0) {
         parentPath.add(name);
         computeDiffRecursively(child, parentPath, diffReport);
         parentPath.remove(parentPath.size() - 1);
       }
     }
   } else if (node.isFile() && node.asFile() instanceof FileWithSnapshot) {
     FileWithSnapshot file = (FileWithSnapshot) node.asFile();
     Snapshot earlierSnapshot = diffReport.isFromEarlier() ? diffReport.from : diffReport.to;
     Snapshot laterSnapshot = diffReport.isFromEarlier() ? diffReport.to : diffReport.from;
     boolean change = file.getDiffs().changedBetweenSnapshots(earlierSnapshot, laterSnapshot);
     if (change) {
       diffReport.addFileDiff(file.asINodeFile(), relativePath);
     }
   }
 }
 /** Load the snapshot diff section from fsimage. */
 public void loadSnapshotDiffSection(InputStream in) throws IOException {
   final List<INodeReference> refList = parent.getLoaderContext().getRefList();
   while (true) {
     SnapshotDiffSection.DiffEntry entry = SnapshotDiffSection.DiffEntry.parseDelimitedFrom(in);
     if (entry == null) {
       break;
     }
     long inodeId = entry.getInodeId();
     INode inode = fsDir.getInode(inodeId);
     SnapshotDiffSection.DiffEntry.Type type = entry.getType();
     switch (type) {
       case FILEDIFF:
         loadFileDiffList(in, inode.asFile(), entry.getNumOfDiff());
         break;
       case DIRECTORYDIFF:
         loadDirectoryDiffList(in, inode.asDirectory(), entry.getNumOfDiff(), refList);
         break;
     }
   }
 }
 private void addToDeletedList(INode dnode, INodeDirectory parent) {
   dnode.setParent(parent);
   if (dnode.isFile()) {
     updateBlocksMap(dnode.asFile(), fsn.getBlockManager());
   }
 }