/** * 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()); } }