HDFS-10656. Optimize conversion of byte arrays back to path string. Contributed by Daryn Sharp.

(cherry picked from commit bebf10d245)
(cherry picked from commit ab7072838f)
(cherry picked from commit 7b5e12229d)
This commit is contained in:
Kihwal Lee 2016-08-03 11:54:51 -05:00 committed by Zhe Zhang
parent 319a6005e6
commit d3c6120576
1 changed files with 31 additions and 18 deletions

View File

@ -37,6 +37,7 @@ import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_SERVER_HTTPS_KEYPASSWORD_
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_SERVER_HTTPS_KEYSTORE_PASSWORD_KEY;
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_SERVER_HTTPS_TRUSTSTORE_PASSWORD_KEY;
import com.google.common.base.Charsets;
import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
@ -103,7 +104,6 @@ import org.apache.hadoop.util.StringUtils;
import org.apache.hadoop.util.ToolRunner;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
@ -342,27 +342,40 @@ public class DFSUtil {
/**
* Given a list of path components returns a path as a UTF8 String
*/
public static String byteArray2PathString(byte[][] pathComponents,
int offset, int length) {
if (pathComponents.length == 0) {
public static String byteArray2PathString(final byte[][] components,
final int offset, final int length) {
// specifically not using StringBuilder to more efficiently build
// string w/o excessive byte[] copies and charset conversions.
final int range = offset + length;
Preconditions.checkPositionIndexes(offset, range, components.length);
if (length == 0) {
return "";
}
Preconditions.checkArgument(offset >= 0 && offset < pathComponents.length);
Preconditions.checkArgument(length >= 0 && offset + length <=
pathComponents.length);
if (offset == 0 && length == 1
&& (pathComponents[0] == null || pathComponents[0].length == 0)) {
return Path.SEPARATOR;
// absolute paths start with either null or empty byte[]
byte[] firstComponent = components[offset];
boolean isAbsolute = (offset == 0 &&
(firstComponent == null || firstComponent.length == 0));
if (offset == 0 && length == 1) {
return isAbsolute ? Path.SEPARATOR : bytes2String(firstComponent);
}
StringBuilder result = new StringBuilder();
int lastIndex = offset + length - 1;
for (int i = offset; i <= lastIndex; i++) {
result.append(new String(pathComponents[i], Charsets.UTF_8));
if (i < lastIndex) {
result.append(Path.SEPARATOR_CHAR);
}
// compute length of full byte[], seed with 1st component and delimiters
int pos = isAbsolute ? 0 : firstComponent.length;
int size = pos + length - 1;
for (int i=offset + 1; i < range; i++) {
size += components[i].length;
}
return result.toString();
final byte[] result = new byte[size];
if (!isAbsolute) {
System.arraycopy(firstComponent, 0, result, 0, firstComponent.length);
}
// append remaining components as "/component".
for (int i=offset + 1; i < range; i++) {
result[pos++] = (byte)Path.SEPARATOR_CHAR;
int len = components[i].length;
System.arraycopy(components[i], 0, result, pos, len);
pos += len;
}
return bytes2String(result);
}
public static String byteArray2PathString(byte[][] pathComponents) {