/** * 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); } } }
@Override public int compare(INode left, INode right) { if (left == null) { return right == null ? 0 : -1; } else { if (right == null) { return 1; } else { int cmp = compare(left.getParent(), right.getParent()); return cmp == 0 ? SignedBytes.lexicographicalComparator() .compare(left.getLocalNameBytes(), right.getLocalNameBytes()) : cmp; } } }
private void saveCreatedList(List<INode> created, OutputStream out) throws IOException { // local names of the created list member for (INode c : created) { SnapshotDiffSection.CreatedListEntry.newBuilder() .setName(ByteString.copyFrom(c.getLocalNameBytes())) .build() .writeDelimitedTo(out); } }