|
@@ -182,6 +182,7 @@ public class FSNamesystem implements FSConstants, FSNamesystemMBean, FSClusterSt
|
|
// Default initial capacity and load factor of map
|
|
// Default initial capacity and load factor of map
|
|
public static final int DEFAULT_INITIAL_MAP_CAPACITY = 16;
|
|
public static final int DEFAULT_INITIAL_MAP_CAPACITY = 16;
|
|
public static final float DEFAULT_MAP_LOAD_FACTOR = 0.75f;
|
|
public static final float DEFAULT_MAP_LOAD_FACTOR = 0.75f;
|
|
|
|
+ static int BLOCK_DELETION_INCREMENT = 1000;
|
|
|
|
|
|
private float blocksInvalidateWorkPct;
|
|
private float blocksInvalidateWorkPct;
|
|
private int blocksReplWorkMultiplier;
|
|
private int blocksReplWorkMultiplier;
|
|
@@ -1833,16 +1834,32 @@ public class FSNamesystem implements FSConstants, FSNamesystemMBean, FSClusterSt
|
|
|
|
|
|
/**
|
|
/**
|
|
* Adds block to list of blocks which will be invalidated on
|
|
* Adds block to list of blocks which will be invalidated on
|
|
- * specified datanode and log the move
|
|
|
|
|
|
+ * specified datanode
|
|
* @param b block
|
|
* @param b block
|
|
* @param n datanode
|
|
* @param n datanode
|
|
|
|
+ * @param log true to create an entry in the log
|
|
*/
|
|
*/
|
|
- void addToInvalidates(Block b, DatanodeInfo n) {
|
|
|
|
- addToInvalidatesNoLog(b, n);
|
|
|
|
- NameNode.stateChangeLog.info("BLOCK* NameSystem.addToInvalidates: "
|
|
|
|
- + b.getBlockName() + " is added to invalidSet of " + n.getName());
|
|
|
|
|
|
+ void addToInvalidates(Block b, DatanodeInfo dn, boolean log) {
|
|
|
|
+ addToInvalidatesNoLog(b, dn);
|
|
|
|
+ if (log) {
|
|
|
|
+ NameNode.stateChangeLog.info("BLOCK* NameSystem.addToInvalidates: "
|
|
|
|
+ + b.getBlockName() + " to " + dn.getName());
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Adds block to list of blocks which will be invalidated on specified
|
|
|
|
+ * datanode and log the operation
|
|
|
|
+ *
|
|
|
|
+ * @param b
|
|
|
|
+ * block
|
|
|
|
+ * @param dn
|
|
|
|
+ * datanode
|
|
|
|
+ */
|
|
|
|
+ void addToInvalidates(Block b, DatanodeInfo dn) {
|
|
|
|
+ addToInvalidates(b, dn, true);
|
|
|
|
+ }
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Adds block to list of blocks which will be invalidated on
|
|
* Adds block to list of blocks which will be invalidated on
|
|
* specified datanode
|
|
* specified datanode
|
|
@@ -1865,10 +1882,16 @@ public class FSNamesystem implements FSConstants, FSNamesystemMBean, FSClusterSt
|
|
* all its datanodes.
|
|
* all its datanodes.
|
|
*/
|
|
*/
|
|
private void addToInvalidates(Block b) {
|
|
private void addToInvalidates(Block b) {
|
|
|
|
+ StringBuilder datanodes = new StringBuilder();
|
|
for (Iterator<DatanodeDescriptor> it =
|
|
for (Iterator<DatanodeDescriptor> it =
|
|
blocksMap.nodeIterator(b); it.hasNext();) {
|
|
blocksMap.nodeIterator(b); it.hasNext();) {
|
|
DatanodeDescriptor node = it.next();
|
|
DatanodeDescriptor node = it.next();
|
|
- addToInvalidates(b, node);
|
|
|
|
|
|
+ addToInvalidates(b, node, false);
|
|
|
|
+ datanodes.append(node.getName()).append(" ");
|
|
|
|
+ }
|
|
|
|
+ if (datanodes.length() != 0) {
|
|
|
|
+ NameNode.stateChangeLog.info("BLOCK* NameSystem.addToInvalidates: "
|
|
|
|
+ + b.getBlockName() + " to " + datanodes.toString());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2025,8 +2048,10 @@ public class FSNamesystem implements FSConstants, FSNamesystemMBean, FSClusterSt
|
|
if ((!recursive) && (!dir.isDirEmpty(src))) {
|
|
if ((!recursive) && (!dir.isDirEmpty(src))) {
|
|
throw new IOException(src + " is non empty");
|
|
throw new IOException(src + " is non empty");
|
|
}
|
|
}
|
|
|
|
+ if (NameNode.stateChangeLog.isDebugEnabled()) {
|
|
|
|
+ NameNode.stateChangeLog.debug("DIR* NameSystem.delete: " + src);
|
|
|
|
+ }
|
|
boolean status = deleteInternal(src, true);
|
|
boolean status = deleteInternal(src, true);
|
|
- getEditLog().logSync();
|
|
|
|
if (status && auditLog.isInfoEnabled() && isExternalInvocation()) {
|
|
if (status && auditLog.isInfoEnabled() && isExternalInvocation()) {
|
|
logAuditEvent(UserGroupInformation.getCurrentUser(),
|
|
logAuditEvent(UserGroupInformation.getCurrentUser(),
|
|
Server.getRemoteIp(),
|
|
Server.getRemoteIp(),
|
|
@@ -2036,30 +2061,73 @@ public class FSNamesystem implements FSConstants, FSNamesystemMBean, FSClusterSt
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Remove the indicated filename from the namespace. This may
|
|
|
|
- * invalidate some blocks that make up the file.
|
|
|
|
|
|
+ * Remove a file/directory from the namespace.
|
|
|
|
+ * <p>
|
|
|
|
+ * For large directories, deletion is incremental. The blocks under the
|
|
|
|
+ * directory are collected and deleted a small number at a time holding the
|
|
|
|
+ * {@link FSNamesystem} lock.
|
|
|
|
+ * <p>
|
|
|
|
+ * For small directory or file the deletion is done in one shot.
|
|
*/
|
|
*/
|
|
- synchronized boolean deleteInternal(String src,
|
|
|
|
|
|
+ private boolean deleteInternal(String src,
|
|
boolean enforcePermission) throws IOException {
|
|
boolean enforcePermission) throws IOException {
|
|
|
|
+ boolean deleteNow = false;
|
|
|
|
+ ArrayList<Block> collectedBlocks = new ArrayList<Block>();
|
|
|
|
+ synchronized (this) {
|
|
|
|
+ if (isInSafeMode()) {
|
|
|
|
+ throw new SafeModeException("Cannot delete " + src, safeMode);
|
|
|
|
+ }
|
|
|
|
+ if (enforcePermission && isPermissionEnabled) {
|
|
|
|
+ checkPermission(src, false, null, FsAction.WRITE, null, FsAction.ALL);
|
|
|
|
+ }
|
|
|
|
+ // Unlink the target directory from directory tree
|
|
|
|
+ if (!dir.delete(src, collectedBlocks)) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ deleteNow = collectedBlocks.size() <= BLOCK_DELETION_INCREMENT;
|
|
|
|
+ if (deleteNow) { // Perform small deletes right away
|
|
|
|
+ removeBlocks(collectedBlocks);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Log directory deletion to editlog
|
|
|
|
+ getEditLog().logSync();
|
|
|
|
+ if (!deleteNow) {
|
|
|
|
+ removeBlocks(collectedBlocks); // Incremental deletion of blocks
|
|
|
|
+ }
|
|
|
|
+ collectedBlocks.clear();
|
|
if (NameNode.stateChangeLog.isDebugEnabled()) {
|
|
if (NameNode.stateChangeLog.isDebugEnabled()) {
|
|
- NameNode.stateChangeLog.debug("DIR* NameSystem.delete: " + src);
|
|
|
|
|
|
+ NameNode.stateChangeLog.debug("DIR* Namesystem.delete: " + src
|
|
|
|
+ + " is removed");
|
|
}
|
|
}
|
|
- if (isInSafeMode())
|
|
|
|
- throw new SafeModeException("Cannot delete " + src, safeMode);
|
|
|
|
- if (enforcePermission && isPermissionEnabled) {
|
|
|
|
- checkPermission(src, false, null, FsAction.WRITE, null, FsAction.ALL);
|
|
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /** From the given list, incrementally remove the blocks from blockManager */
|
|
|
|
+ private void removeBlocks(List<Block> blocks) {
|
|
|
|
+ int start = 0;
|
|
|
|
+ int end = 0;
|
|
|
|
+ while (start < blocks.size()) {
|
|
|
|
+ end = BLOCK_DELETION_INCREMENT + start;
|
|
|
|
+ end = end > blocks.size() ? blocks.size() : end;
|
|
|
|
+ synchronized (this) {
|
|
|
|
+ for (int i = start; i < end; i++) {
|
|
|
|
+ Block b = blocks.get(i);
|
|
|
|
+ blocksMap.removeINode(b);
|
|
|
|
+ corruptReplicas.removeFromCorruptReplicasMap(b);
|
|
|
|
+ addToInvalidates(b);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ start = end;
|
|
}
|
|
}
|
|
-
|
|
|
|
- return dir.delete(src);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- void removePathAndBlocks(String src, List<Block> blocks) throws IOException {
|
|
|
|
|
|
+ void removePathAndBlocks(String src, List<Block> blocks) {
|
|
leaseManager.removeLeaseWithPrefixPath(src);
|
|
leaseManager.removeLeaseWithPrefixPath(src);
|
|
- for(Block b : blocks) {
|
|
|
|
- blocksMap.removeINode(b);
|
|
|
|
- corruptReplicas.removeFromCorruptReplicasMap(b);
|
|
|
|
- addToInvalidates(b);
|
|
|
|
|
|
+ if (blocks == null) {
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
+ removeBlocks(blocks);
|
|
}
|
|
}
|
|
|
|
|
|
/** Get the file info for a specific file.
|
|
/** Get the file info for a specific file.
|