/// <exception cref="System.IO.IOException"/> private void SerializeFileDiffList(INodeFile file, OutputStream @out) { FileWithSnapshotFeature sf = file.GetFileWithSnapshotFeature(); if (sf != null) { IList <FileDiff> diffList = sf.GetDiffs().AsList(); FsImageProto.SnapshotDiffSection.DiffEntry entry = ((FsImageProto.SnapshotDiffSection.DiffEntry )FsImageProto.SnapshotDiffSection.DiffEntry.NewBuilder().SetInodeId(file.GetId() ).SetType(FsImageProto.SnapshotDiffSection.DiffEntry.Type.Filediff).SetNumOfDiff (diffList.Count).Build()); entry.WriteDelimitedTo(@out); for (int i = diffList.Count - 1; i >= 0; i--) { FileDiff diff = diffList[i]; FsImageProto.SnapshotDiffSection.FileDiff.Builder fb = FsImageProto.SnapshotDiffSection.FileDiff .NewBuilder().SetSnapshotId(diff.GetSnapshotId()).SetFileSize(diff.GetFileSize() ); if (diff.GetBlocks() != null) { foreach (Block block in diff.GetBlocks()) { fb.AddBlocks(PBHelper.Convert(block)); } } INodeFileAttributes copy = diff.snapshotINode; if (copy != null) { fb.SetName(ByteString.CopyFrom(copy.GetLocalNameBytes())).SetSnapshotCopy(FSImageFormatPBINode.Saver.BuildINodeFile (copy, parent.GetSaverContext())); } ((FsImageProto.SnapshotDiffSection.FileDiff)fb.Build()).WriteDelimitedTo(@out); } } }
/// <summary> /// Recursively compute the difference between snapshots under a given /// directory/file. /// </summary> /// <param name="snapshotRoot">The directory where snapshots were taken.</param> /// <param name="node">The directory/file under which the diff is computed.</param> /// <param name="parentPath"> /// Relative path (corresponding to the snapshot root) of /// the node's parent. /// </param> /// <param name="diffReport">data structure used to store the diff.</param> private void ComputeDiffRecursively(INodeDirectory snapshotRoot, INode node, IList <byte[]> parentPath, SnapshotDiffInfo diffReport) { Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot earlierSnapshot = diffReport .IsFromEarlier() ? diffReport.GetFrom() : diffReport.GetTo(); Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot laterSnapshot = diffReport .IsFromEarlier() ? diffReport.GetTo() : diffReport.GetFrom(); byte[][] relativePath = Sharpen.Collections.ToArray(parentPath, new byte[parentPath .Count][]); if (node.IsDirectory()) { DirectoryWithSnapshotFeature.ChildrenDiff diff = new DirectoryWithSnapshotFeature.ChildrenDiff (); INodeDirectory dir = node.AsDirectory(); DirectoryWithSnapshotFeature sf = dir.GetDirectoryWithSnapshotFeature(); if (sf != null) { bool change = sf.ComputeDiffBetweenSnapshots(earlierSnapshot, laterSnapshot, diff , dir); if (change) { diffReport.AddDirDiff(dir, relativePath, diff); } } ReadOnlyList <INode> children = dir.GetChildrenList(earlierSnapshot.GetId()); foreach (INode child in children) { byte[] name = child.GetLocalNameBytes(); bool toProcess = diff.SearchIndex(Diff.ListType.Deleted, name) < 0; if (!toProcess && child is INodeReference.WithName) { byte[][] renameTargetPath = FindRenameTargetPath(snapshotRoot, (INodeReference.WithName )child, laterSnapshot == null ? Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot .CurrentStateId : laterSnapshot.GetId()); if (renameTargetPath != null) { toProcess = true; diffReport.SetRenameTarget(child.GetId(), renameTargetPath); } } if (toProcess) { parentPath.AddItem(name); ComputeDiffRecursively(snapshotRoot, child, parentPath, diffReport); parentPath.Remove(parentPath.Count - 1); } } } else { if (node.IsFile() && node.AsFile().IsWithSnapshot()) { INodeFile file = node.AsFile(); bool change = file.GetFileWithSnapshotFeature().ChangedBetweenSnapshots(file, earlierSnapshot , laterSnapshot); if (change) { diffReport.AddFileDiff(file, relativePath); } } } }