HDFS-16055. Quota is not preserved in snapshot INode (#3078)
(cherry picked from commit ebee2aed00
)
This commit is contained in:
parent
c1ad91e72d
commit
72508e6430
|
@ -176,6 +176,11 @@ public final class DirectoryWithQuotaFeature implements INode.Feature {
|
||||||
usage.setTypeSpaces(c.getTypeSpaces());
|
usage.setTypeSpaces(c.getTypeSpaces());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return the namespace and storagespace and typespace allowed. */
|
||||||
|
public QuotaCounts getSpaceAllowed() {
|
||||||
|
return new QuotaCounts.Builder().quotaCount(quota).build();
|
||||||
|
}
|
||||||
|
|
||||||
/** @return the namespace and storagespace and typespace consumed. */
|
/** @return the namespace and storagespace and typespace consumed. */
|
||||||
public QuotaCounts getSpaceConsumed() {
|
public QuotaCounts getSpaceConsumed() {
|
||||||
return new QuotaCounts.Builder().quotaCount(usage).build();
|
return new QuotaCounts.Builder().quotaCount(usage).build();
|
||||||
|
|
|
@ -24,17 +24,18 @@ import java.text.SimpleDateFormat;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import org.apache.hadoop.classification.InterfaceAudience;
|
import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
import org.apache.hadoop.fs.Path;
|
import org.apache.hadoop.fs.Path;
|
||||||
import org.apache.hadoop.hdfs.DFSUtil;
|
import org.apache.hadoop.hdfs.DFSUtil;
|
||||||
import org.apache.hadoop.hdfs.protocol.HdfsConstants;
|
import org.apache.hadoop.hdfs.protocol.HdfsConstants;
|
||||||
import org.apache.hadoop.hdfs.server.namenode.AclFeature;
|
import org.apache.hadoop.hdfs.server.namenode.AclFeature;
|
||||||
import org.apache.hadoop.hdfs.server.namenode.ContentSummaryComputationContext;
|
import org.apache.hadoop.hdfs.server.namenode.ContentSummaryComputationContext;
|
||||||
|
import org.apache.hadoop.hdfs.server.namenode.DirectoryWithQuotaFeature;
|
||||||
import org.apache.hadoop.hdfs.server.namenode.FSImageFormat;
|
import org.apache.hadoop.hdfs.server.namenode.FSImageFormat;
|
||||||
import org.apache.hadoop.hdfs.server.namenode.FSImageSerialization;
|
import org.apache.hadoop.hdfs.server.namenode.FSImageSerialization;
|
||||||
import org.apache.hadoop.hdfs.server.namenode.INode;
|
import org.apache.hadoop.hdfs.server.namenode.INode;
|
||||||
import org.apache.hadoop.hdfs.server.namenode.INodeDirectory;
|
import org.apache.hadoop.hdfs.server.namenode.INodeDirectory;
|
||||||
|
import org.apache.hadoop.hdfs.server.namenode.QuotaCounts;
|
||||||
import org.apache.hadoop.hdfs.server.namenode.XAttrFeature;
|
import org.apache.hadoop.hdfs.server.namenode.XAttrFeature;
|
||||||
import org.apache.hadoop.hdfs.util.ReadOnlyList;
|
import org.apache.hadoop.hdfs.util.ReadOnlyList;
|
||||||
|
|
||||||
|
@ -145,15 +146,26 @@ public class Snapshot implements Comparable<byte[]> {
|
||||||
/** The root directory of the snapshot. */
|
/** The root directory of the snapshot. */
|
||||||
static public class Root extends INodeDirectory {
|
static public class Root extends INodeDirectory {
|
||||||
Root(INodeDirectory other) {
|
Root(INodeDirectory other) {
|
||||||
// Always preserve ACL, XAttr.
|
// Always preserve ACL, XAttr and Quota.
|
||||||
super(other, false, Arrays.asList(other.getFeatures()).stream().filter(
|
super(other, false,
|
||||||
input -> {
|
Arrays.stream(other.getFeatures()).filter(feature ->
|
||||||
if (AclFeature.class.isInstance(input)
|
feature instanceof AclFeature
|
||||||
|| XAttrFeature.class.isInstance(input)) {
|
|| feature instanceof XAttrFeature
|
||||||
return true;
|
|| feature instanceof DirectoryWithQuotaFeature
|
||||||
|
).map(feature -> {
|
||||||
|
if (feature instanceof DirectoryWithQuotaFeature) {
|
||||||
|
// Return copy if feature is quota because a ref could be updated
|
||||||
|
final QuotaCounts quota =
|
||||||
|
((DirectoryWithQuotaFeature) feature).getSpaceAllowed();
|
||||||
|
return new DirectoryWithQuotaFeature.Builder()
|
||||||
|
.nameSpaceQuota(quota.getNameSpace())
|
||||||
|
.storageSpaceQuota(quota.getStorageSpace())
|
||||||
|
.typeQuotas(quota.getTypeSpaces())
|
||||||
|
.build();
|
||||||
|
} else {
|
||||||
|
return feature;
|
||||||
}
|
}
|
||||||
return false;
|
}).toArray(Feature[]::new));
|
||||||
}).collect(Collectors.toList()).toArray(new Feature[0]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -813,6 +813,24 @@ public class TestSnapshotDiffReport {
|
||||||
new DiffReportEntry(DiffType.DELETE, DFSUtil.string2Bytes("subsub1")));
|
new DiffReportEntry(DiffType.DELETE, DFSUtil.string2Bytes("subsub1")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDiffReportWithQuota() throws Exception {
|
||||||
|
final Path testdir = new Path(sub1, "testdir1");
|
||||||
|
hdfs.mkdirs(testdir);
|
||||||
|
hdfs.allowSnapshot(testdir);
|
||||||
|
// Set quota BEFORE creating the snapshot
|
||||||
|
hdfs.setQuota(testdir, 10, 10);
|
||||||
|
hdfs.createSnapshot(testdir, "s0");
|
||||||
|
final SnapshotDiffReport report =
|
||||||
|
hdfs.getSnapshotDiffReport(testdir, "s0", "");
|
||||||
|
// The diff should be null. Snapshot dir inode should keep the quota.
|
||||||
|
Assert.assertEquals(0, report.getDiffList().size());
|
||||||
|
// Cleanup
|
||||||
|
hdfs.deleteSnapshot(testdir, "s0");
|
||||||
|
hdfs.disallowSnapshot(testdir);
|
||||||
|
hdfs.delete(testdir, true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rename a directory to its prior descendant, and verify the diff report.
|
* Rename a directory to its prior descendant, and verify the diff report.
|
||||||
*/
|
*/
|
||||||
|
@ -1005,7 +1023,6 @@ public class TestSnapshotDiffReport {
|
||||||
|
|
||||||
// we always put modification on the file before rename
|
// we always put modification on the file before rename
|
||||||
verifyDiffReport(root, "s1", "",
|
verifyDiffReport(root, "s1", "",
|
||||||
new DiffReportEntry(DiffType.MODIFY, DFSUtil.string2Bytes("")),
|
|
||||||
new DiffReportEntry(DiffType.MODIFY, DFSUtil.string2Bytes("foo2")),
|
new DiffReportEntry(DiffType.MODIFY, DFSUtil.string2Bytes("foo2")),
|
||||||
new DiffReportEntry(DiffType.RENAME, DFSUtil.string2Bytes("foo2/bar"),
|
new DiffReportEntry(DiffType.RENAME, DFSUtil.string2Bytes("foo2/bar"),
|
||||||
DFSUtil.string2Bytes("foo2/bar-new")));
|
DFSUtil.string2Bytes("foo2/bar-new")));
|
||||||
|
@ -1091,8 +1108,7 @@ public class TestSnapshotDiffReport {
|
||||||
new DiffReportEntry(DiffType.MODIFY,
|
new DiffReportEntry(DiffType.MODIFY,
|
||||||
DFSUtil.string2Bytes(flumeFileName)));
|
DFSUtil.string2Bytes(flumeFileName)));
|
||||||
|
|
||||||
verifyDiffReport(level0A, flumeSnap2Name, "",
|
verifyDiffReport(level0A, flumeSnap2Name, "");
|
||||||
new DiffReportEntry(DiffType.MODIFY, DFSUtil.string2Bytes("")));
|
|
||||||
|
|
||||||
verifyDiffReport(level0A, flumeSnap1Name, flumeSnap2Name,
|
verifyDiffReport(level0A, flumeSnap1Name, flumeSnap2Name,
|
||||||
new DiffReportEntry(DiffType.MODIFY, DFSUtil.string2Bytes("")),
|
new DiffReportEntry(DiffType.MODIFY, DFSUtil.string2Bytes("")),
|
||||||
|
@ -1128,7 +1144,6 @@ public class TestSnapshotDiffReport {
|
||||||
DFSUtil.string2Bytes(flumeFileName)));
|
DFSUtil.string2Bytes(flumeFileName)));
|
||||||
|
|
||||||
verifyDiffReport(level0A, flumeSnap2Name, "",
|
verifyDiffReport(level0A, flumeSnap2Name, "",
|
||||||
new DiffReportEntry(DiffType.MODIFY, DFSUtil.string2Bytes("")),
|
|
||||||
new DiffReportEntry(DiffType.MODIFY,
|
new DiffReportEntry(DiffType.MODIFY,
|
||||||
DFSUtil.string2Bytes(flumeFileName)));
|
DFSUtil.string2Bytes(flumeFileName)));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue