You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by cu...@apache.org on 2007/08/23 16:34:59 UTC
svn commit: r569015 - in /lucene/hadoop/trunk: CHANGES.txt
src/java/org/apache/hadoop/dfs/INode.java
Author: cutting
Date: Thu Aug 23 07:34:59 2007
New Revision: 569015
URL: http://svn.apache.org/viewvc?rev=569015&view=rev
Log:
HADOOP-1759. Change file name in INode from String to byte[], saving memory on the namenode. Contributed by Konstantin.
Modified:
lucene/hadoop/trunk/CHANGES.txt
lucene/hadoop/trunk/src/java/org/apache/hadoop/dfs/INode.java
Modified: lucene/hadoop/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/hadoop/trunk/CHANGES.txt?rev=569015&r1=569014&r2=569015&view=diff
==============================================================================
--- lucene/hadoop/trunk/CHANGES.txt (original)
+++ lucene/hadoop/trunk/CHANGES.txt Thu Aug 23 07:34:59 2007
@@ -41,6 +41,9 @@
class, with specialized subclasses for directories and files, to
save memory on the namenode. (Konstantin Shvachko via cutting)
+ HADOOP-1759. Change file name in INode from String to byte[],
+ saving memory on the namenode. (Konstantin Shvachko via cutting)
+
BUG FIXES
HADOOP-1463. HDFS report correct usage statistics for disk space
Modified: lucene/hadoop/trunk/src/java/org/apache/hadoop/dfs/INode.java
URL: http://svn.apache.org/viewvc/lucene/hadoop/trunk/src/java/org/apache/hadoop/dfs/INode.java?rev=569015&r1=569014&r2=569015&view=diff
==============================================================================
--- lucene/hadoop/trunk/src/java/org/apache/hadoop/dfs/INode.java (original)
+++ lucene/hadoop/trunk/src/java/org/apache/hadoop/dfs/INode.java Thu Aug 23 07:34:59 2007
@@ -18,8 +18,10 @@
package org.apache.hadoop.dfs;
import java.io.FileNotFoundException;
+import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Arrays;
import java.util.List;
import org.apache.hadoop.fs.Path;
@@ -29,17 +31,19 @@
* This is a base INode class containing common fields for file and
* directory inodes.
*/
-abstract class INode implements Comparable<String> {
- protected String name;
+abstract class INode implements Comparable<byte[]> {
+ protected byte[] name;
protected INodeDirectory parent;
protected long modificationTime;
protected INode(String name) {
this(0L);
- this.name = name;
+ setLocalName(name);
}
INode(long mTime) {
+ this.name = null;
+ this.parent = null;
this.modificationTime = mTime;
}
@@ -55,14 +59,14 @@
* @return local file name
*/
String getLocalName() {
- return name;
+ return bytes2String(name);
}
/**
* Set local file name
*/
void setLocalName(String name) {
- this.name = name;
+ this.name = string2Bytes(name);
}
/**
@@ -78,9 +82,9 @@
return Path.SEPARATOR; // root directory is "/"
}
if (this.parent.parent == null) {
- return Path.SEPARATOR + name;
+ return Path.SEPARATOR + getLocalName();
}
- return parent.getAbsoluteName() + Path.SEPARATOR + name;
+ return parent.getAbsoluteName() + Path.SEPARATOR + getLocalName();
}
/**
@@ -109,13 +113,24 @@
}
}
- static String[] getPathComponents(String path) {
+ /**
+ * Breaks file path into components.
+ * @param path
+ * @return array of byte arrays each of which represents
+ * a single path component.
+ */
+ static byte[][] getPathComponents(String path) {
if (path == null || !path.startsWith(Path.SEPARATOR)) {
return null;
}
if (Path.SEPARATOR.equals(path)) // root
- return new String[]{""};
- return path.split(Path.SEPARATOR, -1);
+ return new byte[][]{null};
+ String[] strings = path.split(Path.SEPARATOR, -1);
+ int size = strings.length;
+ byte[][] bytes = new byte[size][];
+ for (int i = 0; i < size; i++)
+ bytes[i] = string2Bytes(strings[i]);
+ return bytes;
}
/**
@@ -133,19 +148,68 @@
//
// Comparable interface
//
- public int compareTo(String o) {
- return getLocalName().compareTo(o);
+ public int compareTo(byte[] o) {
+ return compareBytes(name, o);
}
public boolean equals(Object o) {
if (!(o instanceof INode)) {
return false;
}
- return getLocalName().equals(((INode)o).getLocalName());
+ return Arrays.equals(this.name, ((INode)o).name);
}
-
+
public int hashCode() {
- return getLocalName().hashCode();
+ return Arrays.hashCode(this.name);
+ }
+
+ //
+ // static methods
+ //
+ /**
+ * Compare two byte arrays.
+ *
+ * @return a negative integer, zero, or a positive integer
+ * as defined by {@link #compareTo(byte[])}.
+ */
+ static int compareBytes(byte[] a1, byte[] a2) {
+ if (a1==a2)
+ return 0;
+ int len1 = (a1==null ? 0 : a1.length);
+ int len2 = (a2==null ? 0 : a2.length);
+ int n = Math.min(len1, len2);
+ byte b1, b2;
+ for (int i=0; i<n; i++) {
+ b1 = a1[i];
+ b2 = a2[i];
+ if (b1 != b2)
+ return b1 - b2;
+ }
+ return len1 - len2;
+ }
+
+ /**
+ * Converts a byte array to a string using UTF8 encoding.
+ */
+ static String bytes2String(byte[] bytes) {
+ try {
+ return new String(bytes, "UTF8");
+ } catch(UnsupportedEncodingException e) {
+ assert false : "UTF8 encoding is not supported ";
+ }
+ return null;
+ }
+
+ /**
+ * Converts a string to a byte array using UTF8 encoding.
+ */
+ static byte[] string2Bytes(String str) {
+ try {
+ return str.getBytes("UTF8");
+ } catch(UnsupportedEncodingException e) {
+ assert false : "UTF8 encoding is not supported ";
+ }
+ return null;
}
}
@@ -177,13 +241,17 @@
void removeChild(INode node) {
assert children != null;
- int low = Collections.binarySearch(children, node.getLocalName());
+ int low = Collections.binarySearch(children, node.name);
if (low >= 0) {
children.remove(low);
}
}
INode getChild(String name) {
+ return getChildINode(string2Bytes(name));
+ }
+
+ private INode getChildINode(byte[] name) {
if (children == null) {
return null;
}
@@ -196,7 +264,7 @@
/**
*/
- private INode getNode(String[] components) {
+ private INode getNode(byte[][] components) {
return getINode(components, components.length-1);
}
@@ -207,8 +275,8 @@
* @param end the end component of the path
* @return found INode or null otherwise
*/
- private INode getINode(String[] components, int end) {
- assert getLocalName().equals(components[0]) :
+ private INode getINode(byte[][] components, int end) {
+ assert compareBytes(this.name, components[0]) == 0 :
"Incorrect name " + getLocalName() + " expected " + components[0];
if (end >= components.length)
end = components.length-1;
@@ -219,7 +287,7 @@
if(!curNode.isDirectory()) // file is not expected here
return null; // because there is more components in the path
INodeDirectory parentDir = (INodeDirectory)curNode;
- curNode = parentDir.getChild(components[start+1]);
+ curNode = parentDir.getChildINode(components[start+1]);
if(curNode == null) // not found
return null;
}
@@ -244,7 +312,7 @@
if (children == null) {
children = new ArrayList<INode>(DEFAULT_FILES_PER_DIRECTORY);
}
- int low = Collections.binarySearch(children, node.getLocalName());
+ int low = Collections.binarySearch(children, node.name);
if(low >= 0)
return null;
node.parent = this;
@@ -264,7 +332,7 @@
* @throws FileNotFoundException
*/
<T extends INode> T addNode(String path, T newNode) throws FileNotFoundException {
- String[] pathComponents = getPathComponents(path);
+ byte[][] pathComponents = getPathComponents(path);
assert pathComponents != null : "Incorrect path " + path;
int pathLen = pathComponents.length;
if (pathLen < 2) // add root
@@ -278,7 +346,7 @@
}
INodeDirectory parentNode = (INodeDirectory)node;
// insert into the parent children list
- newNode.setLocalName(pathComponents[pathLen-1]);
+ newNode.name = pathComponents[pathLen-1];
return parentNode.addChild(newNode);
}