예제 #1
0
        /// <summary>Add a snapshot.</summary>
        /// <exception cref="Org.Apache.Hadoop.Hdfs.Protocol.SnapshotException"/>
        /// <exception cref="Org.Apache.Hadoop.Hdfs.Protocol.QuotaExceededException"/>
        public virtual Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot AddSnapshot
            (INodeDirectory snapshotRoot, int id, string name)
        {
            //check snapshot quota
            int n = GetNumSnapshots();

            if (n + 1 > snapshotQuota)
            {
                throw new SnapshotException("Failed to add snapshot: there are already " + n + " snapshot(s) and the snapshot quota is "
                                            + snapshotQuota);
            }
            Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot s = new Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot
                                                                             (id, name, snapshotRoot);
            byte[] nameBytes = s.GetRoot().GetLocalNameBytes();
            int    i         = SearchSnapshot(nameBytes);

            if (i >= 0)
            {
                throw new SnapshotException("Failed to add snapshot: there is already a " + "snapshot with the same name \""
                                            + Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot.GetSnapshotName(s) +
                                            "\".");
            }
            DirectoryWithSnapshotFeature.DirectoryDiff d = GetDiffs().AddDiff(id, snapshotRoot
                                                                              );
            d.SetSnapshotRoot(s.GetRoot());
            snapshotsByNames.Add(-i - 1, s);
            // set modification time
            long now = Time.Now();

            snapshotRoot.UpdateModificationTime(now, Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot
                                                .CurrentStateId);
            s.GetRoot().SetModificationTime(now, Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot
                                            .CurrentStateId);
            return(s);
        }
예제 #2
0
 public virtual INode GetChild(INodeDirectory currentINode, byte[] name, int snapshotId
                               )
 {
     DirectoryWithSnapshotFeature.DirectoryDiff diff = diffs.GetDiffById(snapshotId);
     return(diff != null?diff.GetChild(name, true, currentINode) : currentINode.GetChild
                    (name, Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot.CurrentStateId));
 }
예제 #3
0
 /// <returns>
 /// If there is no corresponding directory diff for the given
 /// snapshot, this means that the current children list should be
 /// returned for the snapshot. Otherwise we calculate the children list
 /// for the snapshot and return it.
 /// </returns>
 public virtual ReadOnlyList <INode> GetChildrenList(INodeDirectory currentINode, int
                                                     snapshotId)
 {
     DirectoryWithSnapshotFeature.DirectoryDiff diff = diffs.GetDiffById(snapshotId);
     return(diff != null?diff.GetChildrenList(currentINode) : currentINode.GetChildrenList
                    (Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot.CurrentStateId));
 }
예제 #4
0
 public override INodeDirectory.SnapshotAndINode Next()
 {
     INodeDirectory.SnapshotAndINode pair = new INodeDirectory.SnapshotAndINode(this.next
                                                                                .GetSnapshotId(), this._enclosing._enclosing.GetSnapshotById(this.next.GetSnapshotId
                                                                                                                                                 ()).GetRoot());
     this.next = this.FindNext();
     return(pair);
 }
예제 #5
0
        /// <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);
                }
            }
        }
예제 #6
0
 private DirectoryWithSnapshotFeature.DirectoryDiff FindNext()
 {
     for (; this.i.HasNext();)
     {
         DirectoryWithSnapshotFeature.DirectoryDiff diff = this.i.Next();
         if (diff.IsSnapshotRoot())
         {
             return(diff);
         }
     }
     return(null);
 }
예제 #7
0
            /// <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);
                    }
                }
            }
예제 #8
0
 private IList <INode> InitChildren()
 {
     if (this.children == null)
     {
         DirectoryWithSnapshotFeature.ChildrenDiff combined = new DirectoryWithSnapshotFeature.ChildrenDiff
                                                                  ();
         for (DirectoryWithSnapshotFeature.DirectoryDiff d = this._enclosing; d != null; d
                  = d.GetPosterior())
         {
             combined.CombinePosterior(d.diff, null);
         }
         this.children = combined.Apply2Current(ReadOnlyList.Util.AsList(currentDir.GetChildrenList
                                                                             (Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot.CurrentStateId)));
     }
     return(this.children);
 }
        /// <summary>
        /// Test snapshot during file appending, before the corresponding
        /// <see cref="Org.Apache.Hadoop.FS.FSDataOutputStream"/>
        /// instance closes.
        /// </summary>
        /// <exception cref="System.Exception"/>
        public virtual void TestSnapshotWhileAppending()
        {
            Path file = new Path(dir, "file");

            DFSTestUtil.CreateFile(hdfs, file, Blocksize, Replication, seed);
            // 1. append without closing stream --> create snapshot
            HdfsDataOutputStream @out = AppendFileWithoutClosing(file, Blocksize);

            @out.Hsync(EnumSet.Of(HdfsDataOutputStream.SyncFlag.UpdateLength));
            SnapshotTestHelper.CreateSnapshot(hdfs, dir, "s0");
            @out.Close();
            // check: an INodeFileUnderConstructionWithSnapshot should be stored into s0's
            // deleted list, with size BLOCKSIZE*2
            INodeFile fileNode = (INodeFile)fsdir.GetINode(file.ToString());

            NUnit.Framework.Assert.AreEqual(Blocksize * 2, fileNode.ComputeFileSize());
            INodeDirectory dirNode = fsdir.GetINode(dir.ToString()).AsDirectory();

            DirectoryWithSnapshotFeature.DirectoryDiff last = dirNode.GetDiffs().GetLast();
            // 2. append without closing stream
            @out = AppendFileWithoutClosing(file, Blocksize);
            @out.Hsync(EnumSet.Of(HdfsDataOutputStream.SyncFlag.UpdateLength));
            // re-check nodeInDeleted_S0
            dirNode = fsdir.GetINode(dir.ToString()).AsDirectory();
            NUnit.Framework.Assert.AreEqual(Blocksize * 2, fileNode.ComputeFileSize(last.GetSnapshotId
                                                                                        ()));
            // 3. take snapshot --> close stream
            hdfs.CreateSnapshot(dir, "s1");
            @out.Close();
            // check: an INodeFileUnderConstructionWithSnapshot with size BLOCKSIZE*3 should
            // have been stored in s1's deleted list
            fileNode = (INodeFile)fsdir.GetINode(file.ToString());
            dirNode  = fsdir.GetINode(dir.ToString()).AsDirectory();
            last     = dirNode.GetDiffs().GetLast();
            NUnit.Framework.Assert.IsTrue(fileNode.IsWithSnapshot());
            NUnit.Framework.Assert.AreEqual(Blocksize * 3, fileNode.ComputeFileSize(last.GetSnapshotId
                                                                                        ()));
            // 4. modify file --> append without closing stream --> take snapshot -->
            // close stream
            hdfs.SetReplication(file, (short)(Replication - 1));
            @out = AppendFileWithoutClosing(file, Blocksize);
            hdfs.CreateSnapshot(dir, "s2");
            @out.Close();
            // re-check the size of nodeInDeleted_S1
            NUnit.Framework.Assert.AreEqual(Blocksize * 3, fileNode.ComputeFileSize(last.GetSnapshotId
                                                                                        ()));
        }
예제 #10
0
 /// <summary>Used to record the modification of a symlink node</summary>
 public virtual INode SaveChild2Snapshot(INodeDirectory currentINode, INode child,
                                         int latestSnapshotId, INode snapshotCopy)
 {
     Preconditions.CheckArgument(!child.IsDirectory(), "child is a directory, child=%s"
                                 , child);
     Preconditions.CheckArgument(latestSnapshotId != Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot
                                 .CurrentStateId);
     DirectoryWithSnapshotFeature.DirectoryDiff diff = diffs.CheckAndAddLatestSnapshotDiff
                                                           (latestSnapshotId, currentINode);
     if (diff.GetChild(child.GetLocalNameBytes(), false, currentINode) != null)
     {
         // it was already saved in the latest snapshot earlier.
         return(child);
     }
     diff.diff.Modify(snapshotCopy, child);
     return(child);
 }
예제 #11
0
        /// <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);
        }
예제 #12
0
 /// <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);
     }
 }
예제 #13
0
        public virtual QuotaCounts CleanDirectory(BlockStoragePolicySuite bsps, INodeDirectory
                                                  currentINode, int snapshot, int prior, INode.BlocksMapUpdateInfo collectedBlocks
                                                  , IList <INode> removedINodes)
        {
            QuotaCounts counts = new QuotaCounts.Builder().Build();
            IDictionary <INode, INode> priorCreated = null;
            IDictionary <INode, INode> priorDeleted = null;

            if (snapshot == Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot.CurrentStateId)
            {
                // delete the current directory
                currentINode.RecordModification(prior);
                // delete everything in created list
                DirectoryWithSnapshotFeature.DirectoryDiff lastDiff = diffs.GetLast();
                if (lastDiff != null)
                {
                    counts.Add(lastDiff.diff.DestroyCreatedList(bsps, currentINode, collectedBlocks,
                                                                removedINodes));
                }
                counts.Add(currentINode.CleanSubtreeRecursively(bsps, snapshot, prior, collectedBlocks
                                                                , removedINodes, priorDeleted));
            }
            else
            {
                // update prior
                prior = GetDiffs().UpdatePrior(snapshot, prior);
                // if there is a snapshot diff associated with prior, we need to record
                // its original created and deleted list before deleting post
                if (prior != Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot.NoSnapshotId)
                {
                    DirectoryWithSnapshotFeature.DirectoryDiff priorDiff = this.GetDiffs().GetDiffById
                                                                               (prior);
                    if (priorDiff != null && priorDiff.GetSnapshotId() == prior)
                    {
                        IList <INode> cList = priorDiff.diff.GetList(Diff.ListType.Created);
                        IList <INode> dList = priorDiff.diff.GetList(Diff.ListType.Deleted);
                        priorCreated = CloneDiffList(cList);
                        priorDeleted = CloneDiffList(dList);
                    }
                }
                counts.Add(GetDiffs().DeleteSnapshotDiff(bsps, snapshot, prior, currentINode, collectedBlocks
                                                         , removedINodes));
                counts.Add(currentINode.CleanSubtreeRecursively(bsps, snapshot, prior, collectedBlocks
                                                                , removedINodes, priorDeleted));
                // check priorDiff again since it may be created during the diff deletion
                if (prior != Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot.NoSnapshotId)
                {
                    DirectoryWithSnapshotFeature.DirectoryDiff priorDiff = this.GetDiffs().GetDiffById
                                                                               (prior);
                    if (priorDiff != null && priorDiff.GetSnapshotId() == prior)
                    {
                        // For files/directories created between "prior" and "snapshot",
                        // we need to clear snapshot copies for "snapshot". Note that we must
                        // use null as prior in the cleanSubtree call. Files/directories that
                        // were created before "prior" will be covered by the later
                        // cleanSubtreeRecursively call.
                        if (priorCreated != null)
                        {
                            // we only check the node originally in prior's created list
                            foreach (INode cNode in priorDiff.GetChildrenDiff().GetList(Diff.ListType.Created
                                                                                        ))
                            {
                                if (priorCreated.Contains(cNode))
                                {
                                    counts.Add(cNode.CleanSubtree(bsps, snapshot, Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot
                                                                  .NoSnapshotId, collectedBlocks, removedINodes));
                                }
                            }
                        }
                        // When a directory is moved from the deleted list of the posterior
                        // diff to the deleted list of this diff, we need to destroy its
                        // descendants that were 1) created after taking this diff and 2)
                        // deleted after taking posterior diff.
                        // For files moved from posterior's deleted list, we also need to
                        // delete its snapshot copy associated with the posterior snapshot.
                        foreach (INode dNode in priorDiff.GetChildrenDiff().GetList(Diff.ListType.Deleted
                                                                                    ))
                        {
                            if (priorDeleted == null || !priorDeleted.Contains(dNode))
                            {
                                counts.Add(CleanDeletedINode(bsps, dNode, snapshot, prior, collectedBlocks, removedINodes
                                                             ));
                            }
                        }
                    }
                }
            }
            if (currentINode.IsQuotaSet())
            {
                currentINode.GetDirectoryWithQuotaFeature().AddSpaceConsumed2Cache(counts.Negation
                                                                                       ());
            }
            return(counts);
        }
예제 #14
0
        /// <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);
        }
예제 #15
0
 /// <summary>Destroy a subtree under a DstReference node.</summary>
 /// <exception cref="Org.Apache.Hadoop.Hdfs.Protocol.QuotaExceededException"/>
 public static void DestroyDstSubtree(BlockStoragePolicySuite bsps, INode inode, int
                                      snapshot, int prior, INode.BlocksMapUpdateInfo collectedBlocks, IList <INode> removedINodes
                                      )
 {
     Preconditions.CheckArgument(prior != Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot
                                 .NoSnapshotId);
     if (inode.IsReference())
     {
         if (inode is INodeReference.WithName && snapshot != Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot
             .CurrentStateId)
         {
             // this inode has been renamed before the deletion of the DstReference
             // subtree
             inode.CleanSubtree(bsps, snapshot, prior, collectedBlocks, removedINodes);
         }
         else
         {
             // for DstReference node, continue this process to its subtree
             DestroyDstSubtree(bsps, inode.AsReference().GetReferredINode(), snapshot, prior,
                               collectedBlocks, removedINodes);
         }
     }
     else
     {
         if (inode.IsFile())
         {
             inode.CleanSubtree(bsps, snapshot, prior, collectedBlocks, removedINodes);
         }
         else
         {
             if (inode.IsDirectory())
             {
                 IDictionary <INode, INode>   excludedNodes = null;
                 INodeDirectory               dir           = inode.AsDirectory();
                 DirectoryWithSnapshotFeature sf            = dir.GetDirectoryWithSnapshotFeature();
                 if (sf != null)
                 {
                     DirectoryWithSnapshotFeature.DirectoryDiffList diffList  = sf.GetDiffs();
                     DirectoryWithSnapshotFeature.DirectoryDiff     priorDiff = diffList.GetDiffById(prior
                                                                                                     );
                     if (priorDiff != null && priorDiff.GetSnapshotId() == prior)
                     {
                         IList <INode> dList = priorDiff.diff.GetList(Diff.ListType.Deleted);
                         excludedNodes = CloneDiffList(dList);
                     }
                     if (snapshot != Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot.CurrentStateId)
                     {
                         diffList.DeleteSnapshotDiff(bsps, snapshot, prior, dir, collectedBlocks, removedINodes
                                                     );
                     }
                     priorDiff = diffList.GetDiffById(prior);
                     if (priorDiff != null && priorDiff.GetSnapshotId() == prior)
                     {
                         priorDiff.diff.DestroyCreatedList(bsps, dir, collectedBlocks, removedINodes);
                     }
                 }
                 foreach (INode child in inode.AsDirectory().GetChildrenList(prior))
                 {
                     if (excludedNodes != null && excludedNodes.Contains(child))
                     {
                         continue;
                     }
                     DestroyDstSubtree(bsps, child, snapshot, prior, collectedBlocks, removedINodes);
                 }
             }
         }
     }
 }