|
@@ -22,22 +22,29 @@ package org.apache.hadoop.hdfs.server.namenode;
|
|
|
import java.io.BufferedReader;
|
|
|
import java.io.IOException;
|
|
|
import java.io.StringReader;
|
|
|
+import java.util.EnumSet;
|
|
|
+import java.util.List;
|
|
|
|
|
|
import org.apache.commons.logging.Log;
|
|
|
import org.apache.commons.logging.LogFactory;
|
|
|
import org.apache.hadoop.conf.Configuration;
|
|
|
-import org.apache.hadoop.fs.FileSystem;
|
|
|
import org.apache.hadoop.fs.Path;
|
|
|
+import org.apache.hadoop.fs.XAttr;
|
|
|
+import org.apache.hadoop.fs.XAttrSetFlag;
|
|
|
import org.apache.hadoop.hdfs.protocol.NSQuotaExceededException;
|
|
|
+import org.apache.hadoop.hdfs.DFSConfigKeys;
|
|
|
import org.apache.hadoop.hdfs.DFSTestUtil;
|
|
|
import org.apache.hadoop.hdfs.DistributedFileSystem;
|
|
|
import org.apache.hadoop.hdfs.MiniDFSCluster;
|
|
|
import org.apache.hadoop.hdfs.server.namenode.snapshot.Snapshot;
|
|
|
+import org.apache.hadoop.test.GenericTestUtils;
|
|
|
import org.junit.After;
|
|
|
import org.junit.Assert;
|
|
|
import org.junit.Before;
|
|
|
import org.junit.Test;
|
|
|
|
|
|
+import com.google.common.collect.Lists;
|
|
|
+
|
|
|
/**
|
|
|
* Test {@link FSDirectory}, the in-memory namespace tree.
|
|
|
*/
|
|
@@ -70,6 +77,7 @@ public class TestFSDirectory {
|
|
|
@Before
|
|
|
public void setUp() throws Exception {
|
|
|
conf = new Configuration();
|
|
|
+ conf.setInt(DFSConfigKeys.DFS_NAMENODE_MAX_XATTRS_PER_INODE_KEY, 2);
|
|
|
cluster = new MiniDFSCluster.Builder(conf)
|
|
|
.numDataNodes(REPLICATION)
|
|
|
.build();
|
|
@@ -172,4 +180,36 @@ public class TestFSDirectory {
|
|
|
Assert.assertTrue(classname.startsWith(INodeFile.class.getSimpleName())
|
|
|
|| classname.startsWith(INodeDirectory.class.getSimpleName()));
|
|
|
}
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testINodeXAttrsLimit() throws Exception {
|
|
|
+ List<XAttr> existingXAttrs = Lists.newArrayListWithCapacity(2);
|
|
|
+ XAttr xAttr1 = (new XAttr.Builder()).setNameSpace(XAttr.NameSpace.USER).
|
|
|
+ setName("a1").setValue(new byte[]{0x31, 0x32, 0x33}).build();
|
|
|
+ XAttr xAttr2 = (new XAttr.Builder()).setNameSpace(XAttr.NameSpace.USER).
|
|
|
+ setName("a2").setValue(new byte[]{0x31, 0x31, 0x31}).build();
|
|
|
+ existingXAttrs.add(xAttr1);
|
|
|
+ existingXAttrs.add(xAttr2);
|
|
|
+
|
|
|
+ // Adding a system namespace xAttr, isn't affected by inode xAttrs limit.
|
|
|
+ XAttr newXAttr = (new XAttr.Builder()).setNameSpace(XAttr.NameSpace.SYSTEM).
|
|
|
+ setName("a3").setValue(new byte[]{0x33, 0x33, 0x33}).build();
|
|
|
+ List<XAttr> xAttrs = fsdir.setINodeXAttr(existingXAttrs, newXAttr,
|
|
|
+ EnumSet.of(XAttrSetFlag.CREATE, XAttrSetFlag.REPLACE));
|
|
|
+ Assert.assertEquals(xAttrs.size(), 3);
|
|
|
+
|
|
|
+ // Adding a trusted namespace xAttr, is affected by inode xAttrs limit.
|
|
|
+ XAttr newXAttr1 = (new XAttr.Builder()).setNameSpace(
|
|
|
+ XAttr.NameSpace.TRUSTED).setName("a4").
|
|
|
+ setValue(new byte[]{0x34, 0x34, 0x34}).build();
|
|
|
+ try {
|
|
|
+ fsdir.setINodeXAttr(existingXAttrs, newXAttr1,
|
|
|
+ EnumSet.of(XAttrSetFlag.CREATE, XAttrSetFlag.REPLACE));
|
|
|
+ Assert.fail("Setting user visable xattr on inode should fail if " +
|
|
|
+ "reaching limit.");
|
|
|
+ } catch (IOException e) {
|
|
|
+ GenericTestUtils.assertExceptionContains("Cannot add additional XAttr " +
|
|
|
+ "to inode, would exceed limit", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|