/// <summary>Delete a snapshot for a snapshottable directory</summary> /// <param name="snapshotName">Name of the snapshot to be deleted</param> /// <param name="collectedBlocks">Used to collect information to update blocksMap</param> /// <exception cref="System.IO.IOException"/> public virtual void DeleteSnapshot(INodesInPath iip, string snapshotName, INode.BlocksMapUpdateInfo collectedBlocks, IList <INode> removedINodes) { INodeDirectory srcRoot = GetSnapshottableRoot(iip); srcRoot.RemoveSnapshot(fsdir.GetBlockStoragePolicySuite(), snapshotName, collectedBlocks , removedINodes); numSnapshots.GetAndDecrement(); }
/// <summary> /// Find the source root directory where the snapshot will be taken /// for a given path. /// </summary> /// <returns>Snapshottable directory.</returns> /// <exception cref="System.IO.IOException"> /// Throw IOException when the given path does not lead to an /// existing snapshottable directory. /// </exception> public virtual INodeDirectory GetSnapshottableRoot(INodesInPath iip) { string path = iip.GetPath(); INodeDirectory dir = INodeDirectory.ValueOf(iip.GetLastINode(), path); if (!dir.IsSnapshottable()) { throw new SnapshotException("Directory is not a snapshottable directory: " + path ); } return(dir); }
/// <summary>Test that the global limit on snapshots is honored.</summary> /// <exception cref="System.Exception"/> public virtual void TestSnapshotLimits() { // Setup mock objects for SnapshotManager.createSnapshot. // INodeDirectory ids = Org.Mockito.Mockito.Mock <INodeDirectory>(); FSDirectory fsdir = Org.Mockito.Mockito.Mock <FSDirectory>(); INodesInPath iip = Org.Mockito.Mockito.Mock <INodesInPath>(); SnapshotManager sm = Org.Mockito.Mockito.Spy(new SnapshotManager(fsdir)); Org.Mockito.Mockito.DoReturn(ids).When(sm).GetSnapshottableRoot((INodesInPath)Matchers.AnyObject ()); Org.Mockito.Mockito.DoReturn(testMaxSnapshotLimit).When(sm).GetMaxSnapshotID(); // Create testMaxSnapshotLimit snapshots. These should all succeed. // for (int i = 0; i < testMaxSnapshotLimit; ++i) { sm.CreateSnapshot(iip, "dummy", i.ToString()); } // Attempt to create one more snapshot. This should fail due to snapshot // ID rollover. // try { sm.CreateSnapshot(iip, "dummy", "shouldFailSnapshot"); NUnit.Framework.Assert.Fail("Expected SnapshotException not thrown"); } catch (SnapshotException se) { NUnit.Framework.Assert.IsTrue(StringUtils.ToLowerCase(se.Message).Contains("rollover" )); } // Delete a snapshot to free up a slot. // sm.DeleteSnapshot(iip, string.Empty, Org.Mockito.Mockito.Mock <INode.BlocksMapUpdateInfo >(), new AList <INode>()); // Attempt to create a snapshot again. It should still fail due // to snapshot ID rollover. // try { sm.CreateSnapshot(iip, "dummy", "shouldFailSnapshot2"); NUnit.Framework.Assert.Fail("Expected SnapshotException not thrown"); } catch (SnapshotException se) { NUnit.Framework.Assert.IsTrue(StringUtils.ToLowerCase(se.Message).Contains("rollover" )); } }
/// <summary> /// Compute the difference between two snapshots of a directory, or between a /// snapshot of the directory and its current tree. /// </summary> /// <exception cref="System.IO.IOException"/> public virtual SnapshotDiffReport Diff(INodesInPath iip, string snapshotRootPath, string from, string to) { // Find the source root directory path where the snapshots were taken. // All the check for path has been included in the valueOf method. INodeDirectory snapshotRoot = GetSnapshottableRoot(iip); if ((from == null || from.IsEmpty()) && (to == null || to.IsEmpty())) { // both fromSnapshot and toSnapshot indicate the current tree return(new SnapshotDiffReport(snapshotRootPath, from, to, Sharpen.Collections.EmptyList <SnapshotDiffReport.DiffReportEntry>())); } SnapshotDiffInfo diffs = snapshotRoot.GetDirectorySnapshottableFeature().ComputeDiff (snapshotRoot, from, to); return(diffs != null?diffs.GenerateReport() : new SnapshotDiffReport(snapshotRootPath , from, to, Sharpen.Collections.EmptyList <SnapshotDiffReport.DiffReportEntry>())); }
/// <summary>Set the given directory as a snapshottable directory.</summary> /// <remarks> /// Set the given directory as a snapshottable directory. /// If the path is already a snapshottable directory, update the quota. /// </remarks> /// <exception cref="System.IO.IOException"/> public virtual void SetSnapshottable(string path, bool checkNestedSnapshottable) { INodesInPath iip = fsdir.GetINodesInPath4Write(path); INodeDirectory d = INodeDirectory.ValueOf(iip.GetLastINode(), path); if (checkNestedSnapshottable) { CheckNestedSnapshottable(d, path); } if (d.IsSnapshottable()) { //The directory is already a snapshottable directory. d.SetSnapshotQuota(DirectorySnapshottableFeature.SnapshotLimit); } else { d.AddSnapshottableFeature(); } AddSnapshottable(d); }
/// <summary>Check the replication for both the current file and all its prior snapshots /// </summary> /// <param name="currentFile">the Path of the current file</param> /// <param name="snapshotRepMap"> /// A map maintaining all the snapshots of the current file, as well /// as their expected replication number stored in their corresponding /// INodes /// </param> /// <param name="expectedBlockRep">The expected replication number</param> /// <exception cref="System.Exception"/> private void CheckSnapshotFileReplication(Path currentFile, IDictionary <Path, short > snapshotRepMap, short expectedBlockRep) { // First check the getBlockReplication for the INode of the currentFile INodeFile inodeOfCurrentFile = GetINodeFile(currentFile); NUnit.Framework.Assert.AreEqual(expectedBlockRep, inodeOfCurrentFile.GetBlockReplication ()); // Then check replication for every snapshot foreach (Path ss in snapshotRepMap.Keys) { INodesInPath iip = fsdir.GetINodesInPath(ss.ToString(), true); INodeFile ssInode = iip.GetLastINode().AsFile(); // The replication number derived from the // INodeFileWithLink#getBlockReplication should always == expectedBlockRep NUnit.Framework.Assert.AreEqual(expectedBlockRep, ssInode.GetBlockReplication()); // Also check the number derived from INodeFile#getFileReplication NUnit.Framework.Assert.AreEqual(snapshotRepMap[ss], ssInode.GetFileReplication(iip .GetPathSnapshotId())); } }
/// <summary>Create a snapshot of the given path.</summary> /// <remarks> /// Create a snapshot of the given path. /// It is assumed that the caller will perform synchronization. /// </remarks> /// <param name="iip">the INodes resolved from the snapshottable directory's path</param> /// <param name="snapshotName">The name of the snapshot.</param> /// <exception cref="System.IO.IOException"> /// Throw IOException when 1) the given path does not lead to an /// existing snapshottable directory, and/or 2) there exists a /// snapshot with the given name for the directory, and/or 3) /// snapshot number exceeds quota /// </exception> public virtual string CreateSnapshot(INodesInPath iip, string snapshotRoot, string snapshotName) { INodeDirectory srcRoot = GetSnapshottableRoot(iip); if (snapshotCounter == GetMaxSnapshotID()) { // We have reached the maximum allowable snapshot ID and since we don't // handle rollover we will fail all subsequent snapshot creation // requests. // throw new SnapshotException("Failed to create the snapshot. The FileSystem has run out of " + "snapshot IDs and ID rollover is not supported."); } srcRoot.AddSnapshot(snapshotCounter, snapshotName); //create success, update id snapshotCounter++; numSnapshots.GetAndIncrement(); return(Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot.GetSnapshotPath(snapshotRoot , snapshotName)); }