|
@@ -19,24 +19,30 @@
|
|
|
package org.apache.hadoop.hdfs.server.namenode;
|
|
|
|
|
|
import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
|
|
|
+import com.google.common.collect.ImmutableList;
|
|
|
+import com.google.common.collect.Lists;
|
|
|
+import com.google.common.collect.Maps;
|
|
|
import org.apache.hadoop.classification.InterfaceAudience;
|
|
|
import org.apache.hadoop.fs.XAttr;
|
|
|
import org.apache.hadoop.hdfs.protocol.QuotaExceededException;
|
|
|
-import org.apache.hadoop.hdfs.server.namenode.INode;
|
|
|
-
|
|
|
-import com.google.common.collect.ImmutableList;
|
|
|
|
|
|
/**
|
|
|
* XAttrStorage is used to read and set xattrs for an inode.
|
|
|
*/
|
|
|
@InterfaceAudience.Private
|
|
|
public class XAttrStorage {
|
|
|
-
|
|
|
+
|
|
|
+ private static final Map<String, String> internedNames = Maps.newHashMap();
|
|
|
+
|
|
|
/**
|
|
|
* Reads the existing extended attributes of an inode. If the
|
|
|
* inode does not have an <code>XAttr</code>, then this method
|
|
|
* returns an empty list.
|
|
|
+ * <p/>
|
|
|
+ * Must be called while holding the FSDirectory read lock.
|
|
|
+ *
|
|
|
* @param inode INode to read
|
|
|
* @param snapshotId
|
|
|
* @return List<XAttr> <code>XAttr</code> list.
|
|
@@ -48,6 +54,9 @@ public class XAttrStorage {
|
|
|
|
|
|
/**
|
|
|
* Reads the existing extended attributes of an inode.
|
|
|
+ * <p/>
|
|
|
+ * Must be called while holding the FSDirectory read lock.
|
|
|
+ *
|
|
|
* @param inode INode to read.
|
|
|
* @return List<XAttr> <code>XAttr</code> list.
|
|
|
*/
|
|
@@ -58,6 +67,9 @@ public class XAttrStorage {
|
|
|
|
|
|
/**
|
|
|
* Update xattrs of inode.
|
|
|
+ * <p/>
|
|
|
+ * Must be called while holding the FSDirectory write lock.
|
|
|
+ *
|
|
|
* @param inode INode to update
|
|
|
* @param xAttrs to update xAttrs.
|
|
|
* @param snapshotId id of the latest snapshot of the inode
|
|
@@ -70,8 +82,24 @@ public class XAttrStorage {
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
- ImmutableList<XAttr> newXAttrs = ImmutableList.copyOf(xAttrs);
|
|
|
+ // Dedupe the xAttr name and save them into a new interned list
|
|
|
+ List<XAttr> internedXAttrs = Lists.newArrayListWithCapacity(xAttrs.size());
|
|
|
+ for (XAttr xAttr : xAttrs) {
|
|
|
+ final String name = xAttr.getName();
|
|
|
+ String internedName = internedNames.get(name);
|
|
|
+ if (internedName == null) {
|
|
|
+ internedName = name;
|
|
|
+ internedNames.put(internedName, internedName);
|
|
|
+ }
|
|
|
+ XAttr internedXAttr = new XAttr.Builder()
|
|
|
+ .setName(internedName)
|
|
|
+ .setNameSpace(xAttr.getNameSpace())
|
|
|
+ .setValue(xAttr.getValue())
|
|
|
+ .build();
|
|
|
+ internedXAttrs.add(internedXAttr);
|
|
|
+ }
|
|
|
+ // Save the list of interned xattrs
|
|
|
+ ImmutableList<XAttr> newXAttrs = ImmutableList.copyOf(internedXAttrs);
|
|
|
if (inode.getXAttrFeature() != null) {
|
|
|
inode.removeXAttrFeature(snapshotId);
|
|
|
}
|