/** * Verify child's name for fs limit. * * @param childName byte[] containing new child name * @param parentPath String containing parent path * @throws PathComponentTooLongException child's name is too long. */ void verifyMaxComponentLength(byte[] childName, String parentPath) throws PathComponentTooLongException { if (maxComponentLength == 0) { return; } final int length = childName.length; if (length > maxComponentLength) { final PathComponentTooLongException e = new PathComponentTooLongException( maxComponentLength, length, parentPath, DFSUtil.bytes2String(childName)); if (namesystem.isImageLoaded()) { throw e; } else { // Do not throw if edits log is still being processed NameNode.LOG.error("ERROR in FSDirectory.verifyINodeName", e); } } }
@Test /** * This test verifies that error string contains the * right parent directory name if the operation fails with * PathComponentTooLongException */ public void testParentDirectoryNameIsCorrect() throws Exception { conf.setInt(DFSConfigKeys.DFS_NAMENODE_MAX_COMPONENT_LENGTH_KEY, 20); mkdirs("/user", null); mkdirs("/user/testHome", null); mkdirs("/user/testHome/FileNameLength", null); mkdirCheckParentDirectory( "/user/testHome/FileNameLength/really_big_name_0003_fail", "/user/testHome/FileNameLength", PathComponentTooLongException.class); renameCheckParentDirectory("/user/testHome/FileNameLength", "/user/testHome/really_big_name_0003_fail", "/user/testHome/", PathComponentTooLongException.class); }
/** * Verify child's name for fs limit. * * @param childName byte[] containing new child name * @param parentPath Object either INode[] or String containing parent path * @param pos int position of new child in path * @throws PathComponentTooLongException child's name is too long. */ private void verifyMaxComponentLength(byte[] childName, Object parentPath, int pos) throws PathComponentTooLongException { if (maxComponentLength == 0) { return; } final int length = childName.length; if (length > maxComponentLength) { final String p = parentPath instanceof INode[]? getFullPathName((INode[])parentPath, pos - 1): (String)parentPath; final PathComponentTooLongException e = new PathComponentTooLongException( maxComponentLength, length, p, DFSUtil.bytes2String(childName)); if (namesystem.isImageLoaded()) { throw e; } else { // Do not throw if edits log is still being processed NameNode.LOG.error("ERROR in FSDirectory.verifyINodeName", e); } } }
/** * Verify child's name for fs limit. * @throws PathComponentTooLongException child's name is too long. */ void verifyMaxComponentLength(byte[] childName, Object parentPath, int pos) throws PathComponentTooLongException { if (maxComponentLength == 0) { return; } final int length = childName.length; if (length > maxComponentLength) { final String p = parentPath instanceof INode[]? getFullPathName((INode[])parentPath, pos - 1): (String)parentPath; final PathComponentTooLongException e = new PathComponentTooLongException( maxComponentLength, length, p, DFSUtil.bytes2String(childName)); if (ready) { throw e; } else { // Do not throw if edits log is still being processed NameNode.LOG.error("ERROR in FSDirectory.verifyINodeName", e); } } }
/** * Verify child's name for fs limit. * * @param childName byte[] containing new child name * @param parentPath Object either INode[] or String containing parent path * @param pos int position of new child in path * @throws PathComponentTooLongException child's name is too long. */ private void verifyMaxComponentLength(byte[] childName, Object parentPath, int pos) throws PathComponentTooLongException { if (maxComponentLength == 0) { return; } final int length = childName.length; if (length > maxComponentLength) { final String p = parentPath instanceof INode[]? getFullPathName((INode[])parentPath, pos - 1): (String)parentPath; final PathComponentTooLongException e = new PathComponentTooLongException( maxComponentLength, length, p, DFSUtil.bytes2String(childName)); if (ready) { throw e; } else { // Do not throw if edits log is still being processed NameNode.LOG.error("ERROR in FSDirectory.verifyINodeName", e); } } }
@Test public void testMaxComponentLength() throws Exception { conf.setInt(DFSConfigKeys.DFS_NAMENODE_MAX_COMPONENT_LENGTH_KEY, 2); mkdirs("/1", null); mkdirs("/22", null); mkdirs("/333", PathComponentTooLongException.class); mkdirs("/4444", PathComponentTooLongException.class); }
@Test public void testMaxComponentLengthRename() throws Exception { conf.setInt(DFSConfigKeys.DFS_NAMENODE_MAX_COMPONENT_LENGTH_KEY, 2); mkdirs("/5", null); rename("/5", "/555", PathComponentTooLongException.class); rename("/5", "/55", null); mkdirs("/6", null); deprecatedRename("/6", "/666", PathComponentTooLongException.class); deprecatedRename("/6", "/66", null); }
@Test public void testMaxComponentsAndMaxDirItems() throws Exception { conf.setInt(DFSConfigKeys.DFS_NAMENODE_MAX_COMPONENT_LENGTH_KEY, 3); conf.setInt(DFSConfigKeys.DFS_NAMENODE_MAX_DIRECTORY_ITEMS_KEY, 2); mkdirs("/1", null); mkdirs("/22", null); mkdirs("/333", MaxDirectoryItemsExceededException.class); mkdirs("/4444", PathComponentTooLongException.class); }
/** * Checks file system limits (max component length and max directory items) * during a rename operation. * * @param srcIIP INodesInPath containing every inode in the rename source * @param dstIIP INodesInPath containing every inode in the rename destination * @throws PathComponentTooLongException child's name is too long. * @throws MaxDirectoryItemsExceededException too many children. */ private void verifyFsLimitsForRename(INodesInPath srcIIP, INodesInPath dstIIP) throws PathComponentTooLongException, MaxDirectoryItemsExceededException { byte[] dstChildName = dstIIP.getLastLocalName(); INode[] dstInodes = dstIIP.getINodes(); int pos = dstInodes.length - 1; verifyMaxComponentLength(dstChildName, dstInodes, pos); // Do not enforce max directory items if renaming within same directory. if (srcIIP.getINode(-2) != dstIIP.getINode(-2)) { verifyMaxDirItems(dstInodes, pos); } }
/** Verify if the snapshot name is legal. */ void verifySnapshotName(String snapshotName, String path) throws PathComponentTooLongException { if (snapshotName.contains(Path.SEPARATOR)) { throw new HadoopIllegalArgumentException( "Snapshot name cannot contain \"" + Path.SEPARATOR + "\""); } final byte[] bytes = DFSUtil.string2Bytes(snapshotName); verifyINodeName(bytes); verifyMaxComponentLength(bytes, path, 0); }
/** Verify if the snapshot name is legal. */ void verifySnapshotName(String snapshotName, String path) throws PathComponentTooLongException { final byte[] bytes = DFSUtil.string2Bytes(snapshotName); verifyINodeName(bytes); verifyMaxComponentLength(bytes, path, 0); }
@Test public void testMaxComponentLength() throws Exception { conf.setInt(DFSConfigKeys.DFS_NAMENODE_MAX_COMPONENT_LENGTH_KEY, 2); addChildWithName("1", null); addChildWithName("22", null); addChildWithName("333", PathComponentTooLongException.class); addChildWithName("4444", PathComponentTooLongException.class); }
@Test public void testMaxComponentsAndMaxDirItems() throws Exception { conf.setInt(DFSConfigKeys.DFS_NAMENODE_MAX_COMPONENT_LENGTH_KEY, 3); conf.setInt(DFSConfigKeys.DFS_NAMENODE_MAX_DIRECTORY_ITEMS_KEY, 2); addChildWithName("1", null); addChildWithName("22", null); addChildWithName("333", MaxDirectoryItemsExceededException.class); addChildWithName("4444", PathComponentTooLongException.class); }
/** * Verify that filesystem limit constraints are not violated * * @throws PathComponentTooLongException * child's name is too long * @throws MaxDirectoryItemsExceededException * items per directory is exceeded */ protected <T extends INode> void verifyFsLimits(INode[] pathComponents, int pos, T child) throws FSLimitException, StorageException, TransactionContextException { boolean includeChildName = false; try { if (maxComponentLength != 0) { int length = child.getLocalName().length(); if (length > maxComponentLength) { includeChildName = true; throw new PathComponentTooLongException(maxComponentLength, length); } } if (maxDirItems != 0) { INodeDirectory parent = (INodeDirectory) pathComponents[pos - 1]; int count = parent.getChildrenList().size(); if (count >= maxDirItems) { throw new MaxDirectoryItemsExceededException(maxDirItems, count); } } } catch (FSLimitException e) { String badPath = getFullPathName(pathComponents, pos - 1); if (includeChildName) { badPath += Path.SEPARATOR + child.getLocalName(); } e.setPathName(badPath); // Do not throw if edits log is still being processed if (ready) { throw (e); } // log pre-existing paths that exceed limits NameNode.LOG .error("FSDirectory.verifyFsLimits - " + e.getLocalizedMessage()); } }