/// <summary>Compute the difference between Snapshots.</summary> /// <param name="fromSnapshot"> /// Start point of the diff computation. Null indicates /// current tree. /// </param> /// <param name="toSnapshot"> /// End point of the diff computation. Null indicates current /// tree. /// </param> /// <param name="diff"> /// Used to capture the changes happening to the children. Note /// that the diff still represents (later_snapshot - earlier_snapshot) /// although toSnapshot can be before fromSnapshot. /// </param> /// <param name="currentINode"> /// The /// <see cref="Org.Apache.Hadoop.Hdfs.Server.Namenode.INodeDirectory"/> /// this feature belongs to. /// </param> /// <returns>Whether changes happened between the startSnapshot and endSnaphsot.</returns> internal virtual bool ComputeDiffBetweenSnapshots(Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot fromSnapshot, Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot toSnapshot , DirectoryWithSnapshotFeature.ChildrenDiff diff, INodeDirectory currentINode) { int[] diffIndexPair = diffs.ChangedBetweenSnapshots(fromSnapshot, toSnapshot); if (diffIndexPair == null) { return(false); } int earlierDiffIndex = diffIndexPair[0]; int laterDiffIndex = diffIndexPair[1]; bool dirMetadataChanged = false; INodeDirectoryAttributes dirCopy = null; IList <DirectoryWithSnapshotFeature.DirectoryDiff> difflist = diffs.AsList(); for (int i = earlierDiffIndex; i < laterDiffIndex; i++) { DirectoryWithSnapshotFeature.DirectoryDiff sdiff = difflist[i]; diff.CombinePosterior(sdiff.diff, null); if (!dirMetadataChanged && sdiff.snapshotINode != null) { if (dirCopy == null) { dirCopy = sdiff.snapshotINode; } else { if (!dirCopy.MetadataEquals(sdiff.snapshotINode)) { dirMetadataChanged = true; } } } } if (!diff.IsEmpty() || dirMetadataChanged) { return(true); } else { if (dirCopy != null) { for (int i_1 = laterDiffIndex; i_1 < difflist.Count; i_1++) { if (!dirCopy.MetadataEquals(difflist[i_1].snapshotINode)) { return(true); } } return(!dirCopy.MetadataEquals(currentINode)); } else { return(false); } } }
/// <exception cref="System.IO.IOException"/> private void SerializeDirDiffList(INodeDirectory dir, IList <INodeReference> refList , OutputStream @out) { DirectoryWithSnapshotFeature sf = dir.GetDirectoryWithSnapshotFeature(); if (sf != null) { IList <DirectoryWithSnapshotFeature.DirectoryDiff> diffList = sf.GetDiffs().AsList (); FsImageProto.SnapshotDiffSection.DiffEntry entry = ((FsImageProto.SnapshotDiffSection.DiffEntry )FsImageProto.SnapshotDiffSection.DiffEntry.NewBuilder().SetInodeId(dir.GetId()) .SetType(FsImageProto.SnapshotDiffSection.DiffEntry.Type.Directorydiff).SetNumOfDiff (diffList.Count).Build()); entry.WriteDelimitedTo(@out); for (int i = diffList.Count - 1; i >= 0; i--) { // reverse order! DirectoryWithSnapshotFeature.DirectoryDiff diff = diffList[i]; FsImageProto.SnapshotDiffSection.DirectoryDiff.Builder db = FsImageProto.SnapshotDiffSection.DirectoryDiff .NewBuilder().SetSnapshotId(diff.GetSnapshotId()).SetChildrenSize(diff.GetChildrenSize ()).SetIsSnapshotRoot(diff.IsSnapshotRoot()); INodeDirectoryAttributes copy = diff.snapshotINode; if (!diff.IsSnapshotRoot() && copy != null) { db.SetName(ByteString.CopyFrom(copy.GetLocalNameBytes())).SetSnapshotCopy(FSImageFormatPBINode.Saver.BuildINodeDirectory (copy, parent.GetSaverContext())); } // process created list and deleted list IList <INode> created = diff.GetChildrenDiff().GetList(Diff.ListType.Created); db.SetCreatedListSize(created.Count); IList <INode> deleted = diff.GetChildrenDiff().GetList(Diff.ListType.Deleted); foreach (INode d in deleted) { if (d.IsReference()) { refList.AddItem(d.AsReference()); db.AddDeletedINodeRef(refList.Count - 1); } else { db.AddDeletedINode(d.GetId()); } } ((FsImageProto.SnapshotDiffSection.DirectoryDiff)db.Build()).WriteDelimitedTo(@out ); SaveCreatedList(created, @out); } } }
/// <summary> /// Load /// <see cref="DirectoryDiff"/> /// from fsimage. /// </summary> /// <param name="parent">The directory that the SnapshotDiff belongs to.</param> /// <param name="in"> /// The /// <see cref="System.IO.DataInput"/> /// instance to read. /// </param> /// <param name="loader"> /// The /// <see cref="Loader"/> /// instance that this loading procedure is /// using. /// </param> /// <returns> /// A /// <see cref="DirectoryDiff"/> /// . /// </returns> /// <exception cref="System.IO.IOException"/> private static DirectoryWithSnapshotFeature.DirectoryDiff LoadDirectoryDiff(INodeDirectory parent, DataInput @in, FSImageFormat.Loader loader) { // 1. Read the full path of the Snapshot root to identify the Snapshot Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot snapshot = loader.GetSnapshot (@in); // 2. Load DirectoryDiff#childrenSize int childrenSize = @in.ReadInt(); // 3. Load DirectoryDiff#snapshotINode INodeDirectoryAttributes snapshotINode = LoadSnapshotINodeInDirectoryDiff(snapshot , @in, loader); // 4. Load the created list in SnapshotDiff#Diff IList <INode> createdList = LoadCreatedList(parent, @in); // 5. Load the deleted list in SnapshotDiff#Diff IList <INode> deletedList = LoadDeletedList(parent, createdList, @in, loader); // 6. Compose the SnapshotDiff IList <DirectoryWithSnapshotFeature.DirectoryDiff> diffs = parent.GetDiffs().AsList (); DirectoryWithSnapshotFeature.DirectoryDiff sdiff = new DirectoryWithSnapshotFeature.DirectoryDiff (snapshot.GetId(), snapshotINode, diffs.IsEmpty() ? null : diffs[0], childrenSize , createdList, deletedList, snapshotINode == snapshot.GetRoot()); return(sdiff); }
/// <summary>Load DirectoryDiff list for a directory with snapshot feature</summary> /// <exception cref="System.IO.IOException"/> private void LoadDirectoryDiffList(InputStream @in, INodeDirectory dir, int size, IList <INodeReference> refList) { if (!dir.IsWithSnapshot()) { dir.AddSnapshotFeature(null); } DirectoryWithSnapshotFeature.DirectoryDiffList diffs = dir.GetDiffs(); FSImageFormatProtobuf.LoaderContext state = parent.GetLoaderContext(); for (int i = 0; i < size; i++) { // load a directory diff FsImageProto.SnapshotDiffSection.DirectoryDiff diffInPb = FsImageProto.SnapshotDiffSection.DirectoryDiff .ParseDelimitedFrom(@in); int snapshotId = diffInPb.GetSnapshotId(); Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot snapshot = snapshotMap[snapshotId ]; int childrenSize = diffInPb.GetChildrenSize(); bool useRoot = diffInPb.GetIsSnapshotRoot(); INodeDirectoryAttributes copy = null; if (useRoot) { copy = snapshot.GetRoot(); } else { if (diffInPb.HasSnapshotCopy()) { FsImageProto.INodeSection.INodeDirectory dirCopyInPb = diffInPb.GetSnapshotCopy(); byte[] name = diffInPb.GetName().ToByteArray(); PermissionStatus permission = FSImageFormatPBINode.Loader.LoadPermission(dirCopyInPb .GetPermission(), state.GetStringTable()); AclFeature acl = null; if (dirCopyInPb.HasAcl()) { int[] entries = AclEntryStatusFormat.ToInt(FSImageFormatPBINode.Loader.LoadAclEntries (dirCopyInPb.GetAcl(), state.GetStringTable())); acl = new AclFeature(entries); } XAttrFeature xAttrs = null; if (dirCopyInPb.HasXAttrs()) { xAttrs = new XAttrFeature(FSImageFormatPBINode.Loader.LoadXAttrs(dirCopyInPb.GetXAttrs (), state.GetStringTable())); } long modTime = dirCopyInPb.GetModificationTime(); bool noQuota = dirCopyInPb.GetNsQuota() == -1 && dirCopyInPb.GetDsQuota() == -1 && (!dirCopyInPb.HasTypeQuotas()); if (noQuota) { copy = new INodeDirectoryAttributes.SnapshotCopy(name, permission, acl, modTime, xAttrs); } else { EnumCounters <StorageType> typeQuotas = null; if (dirCopyInPb.HasTypeQuotas()) { ImmutableList <QuotaByStorageTypeEntry> qes = FSImageFormatPBINode.Loader.LoadQuotaByStorageTypeEntries (dirCopyInPb.GetTypeQuotas()); typeQuotas = new EnumCounters <StorageType>(typeof(StorageType), HdfsConstants.QuotaReset ); foreach (QuotaByStorageTypeEntry qe in qes) { if (qe.GetQuota() >= 0 && qe.GetStorageType() != null && qe.GetStorageType().SupportTypeQuota ()) { typeQuotas.Set(qe.GetStorageType(), qe.GetQuota()); } } } copy = new INodeDirectoryAttributes.CopyWithQuota(name, permission, acl, modTime, dirCopyInPb.GetNsQuota(), dirCopyInPb.GetDsQuota(), typeQuotas, xAttrs); } } } // load created list IList <INode> clist = LoadCreatedList(@in, dir, diffInPb.GetCreatedListSize()); // load deleted list IList <INode> dlist = LoadDeletedList(refList, @in, dir, diffInPb.GetDeletedINodeList (), diffInPb.GetDeletedINodeRefList()); // create the directory diff DirectoryWithSnapshotFeature.DirectoryDiff diff = new DirectoryWithSnapshotFeature.DirectoryDiff (snapshotId, copy, null, childrenSize, clist, dlist, useRoot); diffs.AddFirst(diff); } }