HDFS-10653. Optimize conversion from path string to components. Contributed by Daryn Sharp.

This commit is contained in:
Jing Zhao 2016-07-21 11:14:39 -07:00
parent 557a245d83
commit bd3dcf46e2
3 changed files with 26 additions and 33 deletions

View File

@ -319,6 +319,15 @@ public static String path2String(final Object path) {
: path.toString(); : path.toString();
} }
/**
* Convert a UTF8 string to an array of byte arrays.
*/
public static byte[][] getPathComponents(String path) {
// avoid intermediate split to String[]
final byte[] bytes = string2Bytes(path);
return bytes2byteArray(bytes, bytes.length, (byte)Path.SEPARATOR_CHAR);
}
/** /**
* Splits the array of bytes into array of arrays of bytes * Splits the array of bytes into array of arrays of bytes
* on byte separator * on byte separator

View File

@ -727,18 +727,8 @@ public byte getStoragePolicyIDForQuota(byte parentStoragePolicyId) {
*/ */
@VisibleForTesting @VisibleForTesting
public static byte[][] getPathComponents(String path) { public static byte[][] getPathComponents(String path) {
return getPathComponents(getPathNames(path)); checkAbsolutePath(path);
} return DFSUtil.getPathComponents(path);
/** Convert strings to byte arrays for path components. */
static byte[][] getPathComponents(String[] strings) {
if (strings.length == 0) {
return new byte[][]{null};
}
byte[][] bytes = new byte[strings.length][];
for (int i = 0; i < strings.length; i++)
bytes[i] = DFSUtil.string2Bytes(strings[i]);
return bytes;
} }
/** /**
@ -747,11 +737,15 @@ static byte[][] getPathComponents(String[] strings) {
* @return array of path components. * @return array of path components.
*/ */
public static String[] getPathNames(String path) { public static String[] getPathNames(String path) {
checkAbsolutePath(path);
return StringUtils.split(path, Path.SEPARATOR_CHAR);
}
private static void checkAbsolutePath(final String path) {
if (path == null || !path.startsWith(Path.SEPARATOR)) { if (path == null || !path.startsWith(Path.SEPARATOR)) {
throw new AssertionError("Absolute path required, but got '" throw new AssertionError("Absolute path required, but got '"
+ path + "'"); + path + "'");
} }
return StringUtils.split(path, Path.SEPARATOR_CHAR);
} }
@Override @Override

View File

@ -138,8 +138,7 @@ static void assertINodeFile(INode inode, Path path) {
@Test (timeout=15000) @Test (timeout=15000)
public void testNonSnapshotPathINodes() throws Exception { public void testNonSnapshotPathINodes() throws Exception {
// Get the inodes by resolving the path of a normal file // Get the inodes by resolving the path of a normal file
String[] names = INode.getPathNames(file1.toString()); byte[][] components = INode.getPathComponents(file1.toString());
byte[][] components = INode.getPathComponents(names);
INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir, INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir,
components, false); components, false);
// The number of inodes should be equal to components.length // The number of inodes should be equal to components.length
@ -175,8 +174,7 @@ public void testSnapshotPathINodes() throws Exception {
// The path when accessing the snapshot file of file1 is // The path when accessing the snapshot file of file1 is
// /TestSnapshot/sub1/.snapshot/s1/file1 // /TestSnapshot/sub1/.snapshot/s1/file1
String snapshotPath = sub1.toString() + "/.snapshot/s1/file1"; String snapshotPath = sub1.toString() + "/.snapshot/s1/file1";
String[] names = INode.getPathNames(snapshotPath); byte[][] components = INode.getPathComponents(snapshotPath);
byte[][] components = INode.getPathComponents(names);
INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir, INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir,
components, false); components, false);
// Length of inodes should be (components.length - 1), since we will ignore // Length of inodes should be (components.length - 1), since we will ignore
@ -199,8 +197,7 @@ public void testSnapshotPathINodes() throws Exception {
// Resolve the path "/TestSnapshot/sub1/.snapshot" // Resolve the path "/TestSnapshot/sub1/.snapshot"
String dotSnapshotPath = sub1.toString() + "/.snapshot"; String dotSnapshotPath = sub1.toString() + "/.snapshot";
names = INode.getPathNames(dotSnapshotPath); components = INode.getPathComponents(dotSnapshotPath);
components = INode.getPathComponents(names);
nodesInPath = INodesInPath.resolve(fsdir.rootDir, components, false); nodesInPath = INodesInPath.resolve(fsdir.rootDir, components, false);
// The number of INodes returned should still be components.length // The number of INodes returned should still be components.length
// since we put a null in the inode array for ".snapshot" // since we put a null in the inode array for ".snapshot"
@ -246,8 +243,7 @@ public void testSnapshotPathINodesAfterDeletion() throws Exception {
// Resolve the path for the snapshot file // Resolve the path for the snapshot file
// /TestSnapshot/sub1/.snapshot/s2/file1 // /TestSnapshot/sub1/.snapshot/s2/file1
String snapshotPath = sub1.toString() + "/.snapshot/s2/file1"; String snapshotPath = sub1.toString() + "/.snapshot/s2/file1";
String[] names = INode.getPathNames(snapshotPath); byte[][] components = INode.getPathComponents(snapshotPath);
byte[][] components = INode.getPathComponents(names);
INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir, INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir,
components, false); components, false);
// Length of inodes should be (components.length - 1), since we will ignore // Length of inodes should be (components.length - 1), since we will ignore
@ -264,8 +260,7 @@ public void testSnapshotPathINodesAfterDeletion() throws Exception {
} }
// Check the INodes for path /TestSnapshot/sub1/file1 // Check the INodes for path /TestSnapshot/sub1/file1
String[] names = INode.getPathNames(file1.toString()); byte[][] components = INode.getPathComponents(file1.toString());
byte[][] components = INode.getPathComponents(names);
INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir, INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir,
components, false); components, false);
// The length of inodes should be equal to components.length // The length of inodes should be equal to components.length
@ -314,8 +309,7 @@ public void testSnapshotPathINodesWithAddedFile() throws Exception {
{ {
// Check the inodes for /TestSnapshot/sub1/.snapshot/s4/file3 // Check the inodes for /TestSnapshot/sub1/.snapshot/s4/file3
String snapshotPath = sub1.toString() + "/.snapshot/s4/file3"; String snapshotPath = sub1.toString() + "/.snapshot/s4/file3";
String[] names = INode.getPathNames(snapshotPath); byte[][] components = INode.getPathComponents(snapshotPath);
byte[][] components = INode.getPathComponents(names);
INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir, INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir,
components, false); components, false);
// Length of inodes should be (components.length - 1), since we will ignore // Length of inodes should be (components.length - 1), since we will ignore
@ -334,8 +328,7 @@ public void testSnapshotPathINodesWithAddedFile() throws Exception {
} }
// Check the inodes for /TestSnapshot/sub1/file3 // Check the inodes for /TestSnapshot/sub1/file3
String[] names = INode.getPathNames(file3.toString()); byte[][] components = INode.getPathComponents(file3.toString());
byte[][] components = INode.getPathComponents(names);
INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir, INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir,
components, false); components, false);
// The number of inodes should be equal to components.length // The number of inodes should be equal to components.length
@ -361,8 +354,7 @@ public void testSnapshotPathINodesWithAddedFile() throws Exception {
@Test (timeout=15000) @Test (timeout=15000)
public void testSnapshotPathINodesAfterModification() throws Exception { public void testSnapshotPathINodesAfterModification() throws Exception {
// First check the INode for /TestSnapshot/sub1/file1 // First check the INode for /TestSnapshot/sub1/file1
String[] names = INode.getPathNames(file1.toString()); byte[][] components = INode.getPathComponents(file1.toString());
byte[][] components = INode.getPathComponents(names);
INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir, INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir,
components, false); components, false);
// The number of inodes should be equal to components.length // The number of inodes should be equal to components.length
@ -385,8 +377,7 @@ public void testSnapshotPathINodesAfterModification() throws Exception {
// Check the INodes for snapshot of file1 // Check the INodes for snapshot of file1
String snapshotPath = sub1.toString() + "/.snapshot/s3/file1"; String snapshotPath = sub1.toString() + "/.snapshot/s3/file1";
names = INode.getPathNames(snapshotPath); components = INode.getPathComponents(snapshotPath);
components = INode.getPathComponents(names);
INodesInPath ssNodesInPath = INodesInPath.resolve(fsdir.rootDir, INodesInPath ssNodesInPath = INodesInPath.resolve(fsdir.rootDir,
components, false); components, false);
// Length of ssInodes should be (components.length - 1), since we will // Length of ssInodes should be (components.length - 1), since we will
@ -404,8 +395,7 @@ public void testSnapshotPathINodesAfterModification() throws Exception {
snapshotFileNode.getModificationTime(ssNodesInPath.getPathSnapshotId())); snapshotFileNode.getModificationTime(ssNodesInPath.getPathSnapshotId()));
// Check the INode for /TestSnapshot/sub1/file1 again // Check the INode for /TestSnapshot/sub1/file1 again
names = INode.getPathNames(file1.toString()); components = INode.getPathComponents(file1.toString());
components = INode.getPathComponents(names);
INodesInPath newNodesInPath = INodesInPath.resolve(fsdir.rootDir, INodesInPath newNodesInPath = INodesInPath.resolve(fsdir.rootDir,
components, false); components, false);
assertSnapshot(newNodesInPath, false, s3, -1); assertSnapshot(newNodesInPath, false, s3, -1);