Skip to content

Commit 3c60bf0

Browse files
committed
fix: snapshot scenarios & checkstyle
1 parent c0040fe commit 3c60bf0

File tree

3 files changed

+52
-54
lines changed

3 files changed

+52
-54
lines changed

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirRenameOp.java

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -82,15 +82,14 @@ private static Triple<Boolean, Optional<QuotaCounts>, Optional<QuotaCounts>> ver
8282
return Triple.of(false, srcDelta, dstDelta);
8383
}
8484

85-
// Verify srcPath and dstPath without valid 'DirectoryWithQuotaFeature'
86-
// Note: In overwrite scenarios, quota calculation is still required because:
87-
// Overwrite operations delete existing content (affecting rootDir's quota)
88-
if (FSDirectory.verifyPathWithoutValidQuotaFeature(src, src.length() - 1)
89-
&& FSDirectory.verifyPathWithoutValidQuotaFeature(dst, dst.length() - 1)
90-
&& !overwrite) {
85+
// Verify path without valid 'DirectoryWithQuotaFeature'
86+
// Note: In overwrite scenarios, quota calculation is still required,
87+
// overwrite operations delete existing content, which affects the root directory's quota.
88+
if (!overwrite && FSDirectory.verifyPathWithoutValidFeature(src)
89+
&& FSDirectory.verifyPathWithoutValidFeature(dst)) {
9190
return Triple.of(false, srcDelta, dstDelta);
9291
}
93-
92+
9493
int i = 0;
9594
while (src.getINode(i) == dst.getINode(i)) {
9695
i++;
@@ -723,8 +722,8 @@ private static class RenameOperation {
723722
} else {
724723
withCount = null;
725724
}
726-
this.updateQuota = quotaPair.getLeft();
727725
// Set quota for src and dst, ignore src is in Snapshot or is Reference
726+
this.updateQuota = quotaPair.getLeft() || isSrcInSnapshot || srcChildIsReference;
728727
this.srcSubTreeCount = withCount == null ?
729728
quotaPair.getMiddle() : Optional.empty();
730729
this.dstSubTreeCount = quotaPair.getRight();
@@ -768,9 +767,9 @@ long removeSrc() throws IOException {
768767
throw new IOException(error);
769768
} else {
770769
// update the quota count if necessary
771-
Optional<QuotaCounts> countOp = sameStoragePolicy ?
772-
srcSubTreeCount : Optional.empty();
773770
if (updateQuota) {
771+
Optional<QuotaCounts> countOp = sameStoragePolicy ?
772+
srcSubTreeCount : Optional.empty();
774773
fsd.updateCountForDelete(srcChild, srcIIP, countOp);
775774
}
776775
srcIIP = INodesInPath.replace(srcIIP, srcIIP.length() - 1, null);
@@ -787,9 +786,9 @@ boolean removeSrc4OldRename() {
787786
return false;
788787
} else {
789788
// update the quota count if necessary
790-
Optional<QuotaCounts> countOp = sameStoragePolicy ?
791-
srcSubTreeCount : Optional.empty();
792789
if (updateQuota) {
790+
Optional<QuotaCounts> countOp = sameStoragePolicy ?
791+
srcSubTreeCount : Optional.empty();
793792
fsd.updateCountForDelete(srcChild, srcIIP, countOp);
794793
}
795794
srcIIP = INodesInPath.replace(srcIIP, srcIIP.length() - 1, null);

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirectory.java

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,22 +1241,19 @@ static void verifyQuota(INodesInPath iip, int pos, QuotaCounts deltas,
12411241
}
12421242
}
12431243
}
1244-
1244+
12451245
/**
1246-
* Verifies that the path from the specified position to the root
1246+
* Verify that the path from the specified position to the root
12471247
* (excluding the root itself) does not contain any valid quota features.
12481248
*
12491249
* @param iip the INodesInPath containing all the ancestral INodes.
1250-
* @param pos Starting position in the path (0-based index).
1251-
* @return true if no valid quota features are found along the path (root excluded),
1252-
* false if any directory in the path has an active quota feature.
1250+
* @return true if no valid features are found along the path,
1251+
* false if any directory in the path has an active feature.
12531252
*/
1254-
static boolean verifyPathWithoutValidQuotaFeature(INodesInPath iip, int pos) {
1255-
// Does not include the root path
1256-
for (int i = Math.min(pos, iip.length()) - 1; i >= 1; i--) {
1257-
final DirectoryWithQuotaFeature q =
1258-
iip.getINode(i).asDirectory().getDirectoryWithQuotaFeature();
1259-
if (q != null) {
1253+
static boolean verifyPathWithoutValidFeature(INodesInPath iip) {
1254+
for (int i = iip.length() - 2; i >= 1; i--) {
1255+
INodeDirectory d = iip.getINode(i).asDirectory();
1256+
if (d.isWithQuota()) {
12601257
return false;
12611258
}
12621259
}
@@ -1364,11 +1361,12 @@ private void copyINodeDefaultAcl(INode child, FsPermission modes) {
13641361
* @param inode the new INode to add
13651362
* @param modes create modes
13661363
* @param checkQuota whether to check quota
1364+
* @param updateQuota whether to update quota
13671365
* @return an INodesInPath instance containing the new INode
13681366
*/
13691367
@VisibleForTesting
1370-
public INodesInPath addLastINode(INodesInPath existing, INode inode,
1371-
FsPermission modes, boolean checkQuota, Optional<QuotaCounts> quotaCount, boolean updateQuota)
1368+
public INodesInPath addLastINode(INodesInPath existing, INode inode, FsPermission modes,
1369+
boolean checkQuota, Optional<QuotaCounts> quotaCount, boolean updateQuota)
13721370
throws QuotaExceededException {
13731371
assert existing.getLastINode() != null &&
13741372
existing.getLastINode().isDirectory();
@@ -1400,9 +1398,8 @@ public INodesInPath addLastINode(INodesInPath existing, INode inode,
14001398
// always verify inode name
14011399
verifyINodeName(inode.getLocalNameBytes());
14021400

1403-
QuotaCounts counts;
14041401
if (updateQuota) {
1405-
counts = quotaCount.orElseGet(() -> inode.
1402+
QuotaCounts counts = quotaCount.orElseGet(() -> inode.
14061403
computeQuotaUsage(getBlockStoragePolicySuite(),
14071404
parent.getStoragePolicyID(), false,
14081405
Snapshot.CURRENT_STATE_ID));
@@ -1413,7 +1410,7 @@ public INodesInPath addLastINode(INodesInPath existing, INode inode,
14131410
final boolean added = parent.addChild(inode, true,
14141411
existing.getLatestSnapshotId());
14151412
if (!added && updateQuota) {
1416-
counts = quotaCount.orElseGet(() -> inode.
1413+
QuotaCounts counts = quotaCount.orElseGet(() -> inode.
14171414
computeQuotaUsage(getBlockStoragePolicySuite(),
14181415
parent.getStoragePolicyID(), false,
14191416
Snapshot.CURRENT_STATE_ID));

hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestCorrectnessOfQuotaAfterRenameOp.java

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public void testQuotaUsageWhenRenameWithSameStoragePolicy() throws Exception {
8080
DFSTestUtil.createFile(dfs, file2, fileLen, replication, 0);
8181

8282
final Path dstDir1 = new Path(testParentDir2, "dst-dir");
83-
// If dstDir1 not exist, after the rename operation,
83+
// If dstDir1 not exist, after the rename operation,
8484
// the root dir's quota usage should remain unchanged.
8585
QuotaUsage quotaUsage1 = dfs.getQuotaUsage(new Path("/"));
8686
ContentSummary cs1 = dfs.getContentSummary(testParentDir1);
@@ -169,10 +169,10 @@ public void testQuotaUsageWhenRenameWithDifferStoragePolicy() throws Exception {
169169
}
170170

171171
@Test
172-
public void testRenameWithoutValidQuotaFeature() throws Exception {
172+
public void testRenameWithoutValidFeature() throws Exception {
173173
final int fileLen = 1024;
174174
final short replication = 3;
175-
final Path root = new Path("/testRoot");
175+
final Path root = new Path("/testRename");
176176
assertTrue(dfs.mkdirs(root));
177177

178178
Path testParentDir1 = new Path(root, "testDir1");
@@ -189,36 +189,38 @@ public void testRenameWithoutValidQuotaFeature() throws Exception {
189189
}
190190

191191
// 1. Test rename1
192-
QuotaUsage quotaUsage1 = dfs.getQuotaUsage(new Path("/"));
193-
final Path dstDir1 = new Path(testParentDir2, "dst-dir");
194-
ContentSummary cs1 = dfs.getContentSummary(testParentDir1);
195-
196-
// srcDir=/testRoot/testDir1/src-dir
197-
// dstDir=/testRoot/testDir2/dst-dir dstDir1 not exist
198-
boolean rename = dfs.rename(srcDir, dstDir1);
199-
assertTrue(rename);
200-
ContentSummary cs2 = dfs.getContentSummary(testParentDir2);
201-
assertEquals(cs1, cs2);
202-
203-
QuotaUsage quotaUsage2 = dfs.getQuotaUsage(new Path("/"));
204-
assertEquals(quotaUsage1.getFileAndDirectoryCount(), quotaUsage2.getFileAndDirectoryCount());
192+
ContentSummary rootContentSummary1 = dfs.getContentSummary(new Path("/"));
193+
QuotaUsage rootQuotaUsage1 = dfs.getQuotaUsage(new Path("/"));
194+
ContentSummary contentSummary1 = dfs.getContentSummary(testParentDir1);
195+
// srcDir=/testRename/testDir1/src-dir
196+
// dstDir=/testRename/testDir2/dst-dir dstDir1 not exist
197+
final Path dstDir2 = new Path(testParentDir2, "dst-dir");
198+
assertTrue(dfs.rename(srcDir, dstDir2));
199+
ContentSummary contentSummary2 = dfs.getContentSummary(testParentDir2);
200+
assertEquals(contentSummary1, contentSummary2);
201+
QuotaUsage rootQuotaUsage2 = dfs.getQuotaUsage(new Path("/"));
202+
assertEquals(rootQuotaUsage1.getFileAndDirectoryCount(),
203+
rootQuotaUsage2.getFileAndDirectoryCount());
204+
// The return values of the getContentSummary() and getQuotaUsage() should be consistent
205+
assertEquals(rootContentSummary1.getFileAndDirectoryCount(),
206+
rootQuotaUsage2.getFileAndDirectoryCount());
205207

206208
// 2. Test rename2
207-
final Path dstDir2 = new Path(testParentDir3, "dst-dir");
208-
assertTrue(dfs.mkdirs(dstDir2));
209-
long originDstDir2Usage = dfs.getQuotaUsage(dstDir2).getFileAndDirectoryCount();
210-
// The usage for covering the root dir should not include dstDir2 usage
209+
final Path dstDir3 = new Path(testParentDir3, "dst-dir");
210+
assertTrue(dfs.mkdirs(dstDir3));
211+
long originDstDir2Usage = dfs.getQuotaUsage(dstDir3).getFileAndDirectoryCount();
212+
// Exclude dstDir2 usage
211213
long rootINodeCount1 =
212214
dfs.getQuotaUsage(new Path("/")).getFileAndDirectoryCount() - originDstDir2Usage;
213-
ContentSummary cs3 = dfs.getContentSummary(testParentDir2);
215+
ContentSummary contentSummary3 = dfs.getContentSummary(testParentDir2);
214216

215217
// Src and dst must be same (all file or all dir)
216-
// dstDir1=/testRoot/testDir3/dst-dir
217-
// dstDir2=/testRoot/testDir3/dst-dir
218-
dfs.rename(dstDir1, dstDir2, Options.Rename.OVERWRITE);
218+
// dstDir2=/testRename/testDir3/dst-dir
219+
// dstDir3=/testRename/testDir3/dst-dir
220+
dfs.rename(dstDir2, dstDir3, Options.Rename.OVERWRITE);
219221
long rootINodeCount2 = dfs.getQuotaUsage(new Path("/")).getFileAndDirectoryCount();
220222
assertEquals(rootINodeCount1, rootINodeCount2);
221-
ContentSummary cs4 = dfs.getContentSummary(testParentDir3);
222-
assertEquals(cs3, cs4);
223+
ContentSummary contentSummary4 = dfs.getContentSummary(testParentDir3);
224+
assertEquals(contentSummary3, contentSummary4);
223225
}
224226
}

0 commit comments

Comments
 (0)