HDFS-14504. Rename with Snapshots does not honor quota limit.
This commit is contained in:
parent
872c2909bd
commit
83fd15b412
|
@ -1210,7 +1210,8 @@ public class FSDirectory implements Closeable {
|
||||||
|
|
||||||
// check existing components in the path
|
// check existing components in the path
|
||||||
for(int i = (pos > iip.length() ? iip.length(): pos) - 1; i >= 0; i--) {
|
for(int i = (pos > iip.length() ? iip.length(): pos) - 1; i >= 0; i--) {
|
||||||
if (commonAncestor == iip.getINode(i)) {
|
if (commonAncestor == iip.getINode(i)
|
||||||
|
&& !commonAncestor.isInLatestSnapshot(iip.getLatestSnapshotId())) {
|
||||||
// Stop checking for quota when common ancestor is reached
|
// Stop checking for quota when common ancestor is reached
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.apache.hadoop.hdfs.DFSTestUtil;
|
||||||
import org.apache.hadoop.hdfs.DistributedFileSystem;
|
import org.apache.hadoop.hdfs.DistributedFileSystem;
|
||||||
import org.apache.hadoop.hdfs.MiniDFSCluster;
|
import org.apache.hadoop.hdfs.MiniDFSCluster;
|
||||||
import org.apache.hadoop.hdfs.protocol.HdfsConstants;
|
import org.apache.hadoop.hdfs.protocol.HdfsConstants;
|
||||||
|
import org.apache.hadoop.hdfs.protocol.NSQuotaExceededException;
|
||||||
import org.apache.hadoop.hdfs.protocol.SnapshotException;
|
import org.apache.hadoop.hdfs.protocol.SnapshotException;
|
||||||
import org.apache.hadoop.hdfs.server.namenode.FSDirectory;
|
import org.apache.hadoop.hdfs.server.namenode.FSDirectory;
|
||||||
import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
|
import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
|
||||||
|
@ -41,6 +42,7 @@ import org.apache.hadoop.hdfs.server.namenode.snapshot.DirectoryWithSnapshotFeat
|
||||||
import org.apache.hadoop.hdfs.util.ReadOnlyList;
|
import org.apache.hadoop.hdfs.util.ReadOnlyList;
|
||||||
import org.apache.hadoop.ipc.RemoteException;
|
import org.apache.hadoop.ipc.RemoteException;
|
||||||
import org.apache.hadoop.test.GenericTestUtils;
|
import org.apache.hadoop.test.GenericTestUtils;
|
||||||
|
import org.apache.hadoop.test.LambdaTestUtils;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
|
@ -280,4 +282,150 @@ public class TestSnapshotRename {
|
||||||
System.setErr(oldErr);
|
System.setErr(oldErr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test rename of a snapshotted by setting quota in same directory.
|
||||||
|
@Test
|
||||||
|
public void testQuotaAndRenameWithSnapshot() throws Exception {
|
||||||
|
String dirr = "/dir2";
|
||||||
|
Path dir2 = new Path(dirr);
|
||||||
|
Path fil1 = new Path(dir2, "file1");
|
||||||
|
hdfs.mkdirs(dir2);
|
||||||
|
hdfs.setQuota(dir2, 3, 0);
|
||||||
|
hdfs.allowSnapshot(dir2);
|
||||||
|
hdfs.create(fil1);
|
||||||
|
hdfs.createSnapshot(dir2, "snap1");
|
||||||
|
Path file2 = new Path(dir2, "file2");
|
||||||
|
hdfs.rename(fil1, file2);
|
||||||
|
hdfs.getFileStatus(dir2);
|
||||||
|
Path filex = new Path(dir2, "filex");
|
||||||
|
// create a file after exceeding namespace quota
|
||||||
|
LambdaTestUtils.intercept(NSQuotaExceededException.class,
|
||||||
|
"The NameSpace quota (directories and files) of "
|
||||||
|
+ "directory /dir2 is exceeded",
|
||||||
|
() -> hdfs.create(filex));
|
||||||
|
hdfs.createSnapshot(dir2, "snap2");
|
||||||
|
// rename a file after exceeding namespace quota
|
||||||
|
Path file3 = new Path(dir2, "file3");
|
||||||
|
LambdaTestUtils
|
||||||
|
.intercept(NSQuotaExceededException.class,
|
||||||
|
"The NameSpace quota (directories and files) of"
|
||||||
|
+ " directory /dir2 is exceeded",
|
||||||
|
() -> hdfs.rename(file2, file3));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Rename across directories within snapshot with quota set on source
|
||||||
|
// directory.
|
||||||
|
@Test
|
||||||
|
public void testRenameAcrossDirWithinSnapshot() throws Exception {
|
||||||
|
// snapshottable directory
|
||||||
|
String dirr = "/dir";
|
||||||
|
Path rootDir = new Path(dirr);
|
||||||
|
hdfs.mkdirs(rootDir);
|
||||||
|
hdfs.allowSnapshot(rootDir);
|
||||||
|
|
||||||
|
// set quota for source directory under snapshottable root directory
|
||||||
|
Path dir2 = new Path(rootDir, "dir2");
|
||||||
|
Path fil1 = new Path(dir2, "file1");
|
||||||
|
hdfs.mkdirs(dir2);
|
||||||
|
hdfs.setQuota(dir2, 3, 0);
|
||||||
|
hdfs.create(fil1);
|
||||||
|
Path file2 = new Path(dir2, "file2");
|
||||||
|
hdfs.rename(fil1, file2);
|
||||||
|
Path fil3 = new Path(dir2, "file3");
|
||||||
|
hdfs.create(fil3);
|
||||||
|
|
||||||
|
// destination directory under snapshottable root directory
|
||||||
|
Path dir1 = new Path(rootDir, "dir1");
|
||||||
|
Path dir1fil1 = new Path(dir1, "file1");
|
||||||
|
hdfs.mkdirs(dir1);
|
||||||
|
hdfs.create(dir1fil1);
|
||||||
|
Path dir1fil2 = new Path(dir1, "file2");
|
||||||
|
hdfs.rename(dir1fil1, dir1fil2);
|
||||||
|
|
||||||
|
hdfs.createSnapshot(rootDir, "snap1");
|
||||||
|
Path filex = new Path(dir2, "filex");
|
||||||
|
// create a file after exceeding namespace quota
|
||||||
|
LambdaTestUtils.intercept(NSQuotaExceededException.class,
|
||||||
|
"The NameSpace quota (directories and files) of "
|
||||||
|
+ "directory /dir/dir2 is exceeded",
|
||||||
|
() -> hdfs.create(filex));
|
||||||
|
|
||||||
|
// Rename across directories within snapshot with quota set on source
|
||||||
|
// directory
|
||||||
|
assertTrue(hdfs.rename(fil3, dir1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test rename within the same directory within a snapshottable root with
|
||||||
|
// quota set.
|
||||||
|
@Test
|
||||||
|
public void testRenameInSameDirWithSnapshotableRoot() throws Exception {
|
||||||
|
|
||||||
|
// snapshottable root directory
|
||||||
|
String rootStr = "/dir";
|
||||||
|
Path rootDir = new Path(rootStr);
|
||||||
|
hdfs.mkdirs(rootDir);
|
||||||
|
hdfs.setQuota(rootDir, 3, 0);
|
||||||
|
hdfs.allowSnapshot(rootDir);
|
||||||
|
|
||||||
|
// rename to be performed directory
|
||||||
|
String dirr = "dir2";
|
||||||
|
Path dir2 = new Path(rootDir, dirr);
|
||||||
|
Path fil1 = new Path(dir2, "file1");
|
||||||
|
hdfs.mkdirs(dir2);
|
||||||
|
hdfs.create(fil1);
|
||||||
|
hdfs.createSnapshot(rootDir, "snap1");
|
||||||
|
Path file2 = new Path(dir2, "file2");
|
||||||
|
// rename a file after exceeding namespace quota
|
||||||
|
LambdaTestUtils
|
||||||
|
.intercept(NSQuotaExceededException.class,
|
||||||
|
"The NameSpace quota (directories and files) of"
|
||||||
|
+ " directory /dir is exceeded",
|
||||||
|
() -> hdfs.rename(fil1, file2));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test rename from a directory under snapshottable root to a directory with
|
||||||
|
// quota set to a directory not under under any snapshottable root.
|
||||||
|
@Test
|
||||||
|
public void testRenameAcrossDirWithSnapshotableSrc() throws Exception {
|
||||||
|
// snapshottable directory
|
||||||
|
String dirr = "/dir";
|
||||||
|
Path rootDir = new Path(dirr);
|
||||||
|
hdfs.mkdirs(rootDir);
|
||||||
|
hdfs.allowSnapshot(rootDir);
|
||||||
|
|
||||||
|
// set quota for source directory
|
||||||
|
Path dir2 = new Path(rootDir, "dir2");
|
||||||
|
Path fil1 = new Path(dir2, "file1");
|
||||||
|
hdfs.mkdirs(dir2);
|
||||||
|
hdfs.setQuota(dir2, 3, 0);
|
||||||
|
hdfs.create(fil1);
|
||||||
|
Path file2 = new Path(dir2, "file2");
|
||||||
|
hdfs.rename(fil1, file2);
|
||||||
|
Path fil3 = new Path(dir2, "file3");
|
||||||
|
hdfs.create(fil3);
|
||||||
|
|
||||||
|
hdfs.createSnapshot(rootDir, "snap1");
|
||||||
|
|
||||||
|
// destination directory not under any snapshot
|
||||||
|
String dirr1 = "/dir1";
|
||||||
|
Path dir1 = new Path(dirr1);
|
||||||
|
Path dir1fil1 = new Path(dir1, "file1");
|
||||||
|
hdfs.mkdirs(dir1);
|
||||||
|
hdfs.create(dir1fil1);
|
||||||
|
Path dir1fil2 = new Path(dir1, "file2");
|
||||||
|
hdfs.rename(dir1fil1, dir1fil2);
|
||||||
|
|
||||||
|
Path filex = new Path(dir2, "filex");
|
||||||
|
// create a file after exceeding namespace quota on source
|
||||||
|
LambdaTestUtils.intercept(NSQuotaExceededException.class,
|
||||||
|
"The NameSpace quota (directories and files) of "
|
||||||
|
+ "directory /dir/dir2 is exceeded",
|
||||||
|
() -> hdfs.create(filex));
|
||||||
|
|
||||||
|
// Rename across directories source dir under snapshot with quota set and
|
||||||
|
// destination directory not under any snapshot
|
||||||
|
assertTrue(hdfs.rename(fil3, dir1));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue