/// <exception cref="System.IO.IOException"/> private INodeReference LoadINodeReference(FsImageProto.INodeReferenceSection.INodeReference r) { long referredId = r.GetReferredId(); INode referred = fsDir.GetInode(referredId); INodeReference.WithCount withCount = (INodeReference.WithCount)referred.GetParentReference (); if (withCount == null) { withCount = new INodeReference.WithCount(null, referred); } INodeReference @ref; if (r.HasDstSnapshotId()) { // DstReference @ref = new INodeReference.DstReference(null, withCount, r.GetDstSnapshotId()); } else { @ref = new INodeReference.WithName(null, withCount, r.GetName().ToByteArray(), r. GetLastSnapshotId()); } return(@ref); }
/// <summary>We just found a deleted WithName node as the source of a rename operation. /// </summary> /// <remarks> /// We just found a deleted WithName node as the source of a rename operation. /// However, we should include it in our snapshot diff report as rename only /// if the rename target is also under the same snapshottable directory. /// </remarks> private byte[][] FindRenameTargetPath(INodeDirectory snapshotRoot, INodeReference.WithName wn, int snapshotId) { INode inode = wn.GetReferredINode(); List <byte[]> ancestors = Lists.NewLinkedList(); while (inode != null) { if (inode == snapshotRoot) { return(Sharpen.Collections.ToArray(ancestors, new byte[ancestors.Count][])); } if (inode is INodeReference.WithCount) { inode = ((INodeReference.WithCount)inode).GetParentRef(snapshotId); } else { INode parent = inode.GetParentReference() != null?inode.GetParentReference() : inode.GetParent(); if (parent != null && parent is INodeDirectory) { int sid = parent.AsDirectory().SearchChild(inode); if (sid < snapshotId) { return(null); } } if (!(parent is INodeReference.WithCount)) { ancestors.AddFirst(inode.GetLocalNameBytes()); } inode = parent; } } return(null); }
/// <summary> /// Clean an inode while we move it from the deleted list of post to the /// deleted list of prior. /// </summary> /// <param name="bsps">The block storage policy suite.</param> /// <param name="inode">The inode to clean.</param> /// <param name="post">The post snapshot.</param> /// <param name="prior">The id of the prior snapshot.</param> /// <param name="collectedBlocks">Used to collect blocks for later deletion.</param> /// <returns>Quota usage update.</returns> private static QuotaCounts CleanDeletedINode(BlockStoragePolicySuite bsps, INode inode, int post, int prior, INode.BlocksMapUpdateInfo collectedBlocks, IList <INode > removedINodes) { QuotaCounts counts = new QuotaCounts.Builder().Build(); Deque <INode> queue = new ArrayDeque <INode>(); queue.AddLast(inode); while (!queue.IsEmpty()) { INode topNode = queue.PollFirst(); if (topNode is INodeReference.WithName) { INodeReference.WithName wn = (INodeReference.WithName)topNode; if (wn.GetLastSnapshotId() >= post) { wn.CleanSubtree(bsps, post, prior, collectedBlocks, removedINodes); } } else { // For DstReference node, since the node is not in the created list of // prior, we should treat it as regular file/dir if (topNode.IsFile() && topNode.AsFile().IsWithSnapshot()) { INodeFile file = topNode.AsFile(); counts.Add(file.GetDiffs().DeleteSnapshotDiff(bsps, post, prior, file, collectedBlocks , removedINodes)); } else { if (topNode.IsDirectory()) { INodeDirectory dir = topNode.AsDirectory(); DirectoryWithSnapshotFeature.ChildrenDiff priorChildrenDiff = null; DirectoryWithSnapshotFeature sf = dir.GetDirectoryWithSnapshotFeature(); if (sf != null) { // delete files/dirs created after prior. Note that these // files/dirs, along with inode, were deleted right after post. DirectoryWithSnapshotFeature.DirectoryDiff priorDiff = sf.GetDiffs().GetDiffById( prior); if (priorDiff != null && priorDiff.GetSnapshotId() == prior) { priorChildrenDiff = priorDiff.GetChildrenDiff(); counts.Add(priorChildrenDiff.DestroyCreatedList(bsps, dir, collectedBlocks, removedINodes )); } } foreach (INode child in dir.GetChildrenList(prior)) { if (priorChildrenDiff != null && priorChildrenDiff.Search(Diff.ListType.Deleted, child.GetLocalNameBytes()) != null) { continue; } queue.AddLast(child); } } } } } return(counts); }