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 sz...@apache.org on 2009/05/05 01:56:47 UTC
svn commit: r771505 - in /hadoop/core/trunk: CHANGES.txt
src/core/org/apache/hadoop/io/EnumSetWritable.java
src/core/org/apache/hadoop/io/ObjectWritable.java
src/test/org/apache/hadoop/io/TestEnumSetWritable.java
Author: szetszwo
Date: Mon May 4 23:56:46 2009
New Revision: 771505
URL: http://svn.apache.org/viewvc?rev=771505&view=rev
Log:
HADOOP-5596. Add EnumSetWritable. Contributed by He Yongqiang
Added:
hadoop/core/trunk/src/core/org/apache/hadoop/io/EnumSetWritable.java
hadoop/core/trunk/src/test/org/apache/hadoop/io/TestEnumSetWritable.java
Modified:
hadoop/core/trunk/CHANGES.txt
hadoop/core/trunk/src/core/org/apache/hadoop/io/ObjectWritable.java
Modified: hadoop/core/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/core/trunk/CHANGES.txt?rev=771505&r1=771504&r2=771505&view=diff
==============================================================================
--- hadoop/core/trunk/CHANGES.txt (original)
+++ hadoop/core/trunk/CHANGES.txt Mon May 4 23:56:46 2009
@@ -298,6 +298,8 @@
HADOOP-5733. Add map/reduce slot capacity and blacklisted capacity to
JobTracker metrics. (Sreekanth Ramakrishnan via cdouglas)
+ HADOOP-5596. Add EnumSetWritable. (He Yongqiang via szetszwo)
+
OPTIMIZATIONS
HADOOP-5595. NameNode does not need to run a replicator to choose a
Added: hadoop/core/trunk/src/core/org/apache/hadoop/io/EnumSetWritable.java
URL: http://svn.apache.org/viewvc/hadoop/core/trunk/src/core/org/apache/hadoop/io/EnumSetWritable.java?rev=771505&view=auto
==============================================================================
--- hadoop/core/trunk/src/core/org/apache/hadoop/io/EnumSetWritable.java (added)
+++ hadoop/core/trunk/src/core/org/apache/hadoop/io/EnumSetWritable.java Mon May 4 23:56:46 2009
@@ -0,0 +1,202 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.io;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.EnumSet;
+import java.util.Iterator;
+
+import org.apache.hadoop.conf.Configurable;
+import org.apache.hadoop.conf.Configuration;
+
+/** A Writable wrapper for EnumSet. */
+public class EnumSetWritable<E extends Enum<E>> implements Writable,
+ Configurable {
+
+ private EnumSet<E> value;
+
+ private Class<E> elementType;
+
+ private Configuration conf;
+
+ EnumSetWritable() {
+ }
+
+ /**
+ * Construct a new EnumSetWritable. If the <tt>value</tt> argument is null or
+ * its size is zero, the <tt>elementType</tt> argument must not be null. If
+ * the argument <tt>value</tt>'s size is bigger than zero, the argument
+ * <tt>elementType</tt> is not be used.
+ *
+ * @param value
+ * @param elementType
+ */
+ public EnumSetWritable(EnumSet<E> value, Class<E> elementType) {
+ set(value, elementType);
+ }
+
+ /**
+ * Construct a new EnumSetWritable. Argument <tt>value</tt> should not be null
+ * or empty.
+ *
+ * @param value
+ */
+ public EnumSetWritable(EnumSet<E> value) {
+ this(value, null);
+ }
+
+ /**
+ * reset the EnumSetWritable with specified
+ * <tt>value</value> and <tt>elementType</tt>. If the <tt>value</tt> argument
+ * is null or its size is zero, the <tt>elementType</tt> argument must not be
+ * null. If the argument <tt>value</tt>'s size is bigger than zero, the
+ * argument <tt>elementType</tt> is not be used.
+ *
+ * @param value
+ * @param elementType
+ */
+ public void set(EnumSet<E> value, Class<E> elementType) {
+ if ((value == null || value.size() == 0)
+ && (this.elementType == null && elementType == null)) {
+ throw new IllegalArgumentException(
+ "The EnumSet argument is null, or is an empty set but with no elementType provided.");
+ }
+ this.value = value;
+ if (value != null && value.size() > 0) {
+ Iterator<E> iterator = value.iterator();
+ this.elementType = iterator.next().getDeclaringClass();
+ } else if (elementType != null) {
+ this.elementType = elementType;
+ }
+ }
+
+ /** Return the value of this EnumSetWritable. */
+ public EnumSet<E> get() {
+ return value;
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ public void readFields(DataInput in) throws IOException {
+ int length = in.readInt();
+ if (length == -1)
+ this.value = null;
+ else if (length == 0) {
+ this.elementType = (Class<E>) ObjectWritable.loadClass(conf,
+ WritableUtils.readString(in));
+ this.value = EnumSet.noneOf(this.elementType);
+ } else {
+ E first = (E) ObjectWritable.readObject(in, conf);
+ this.value = (EnumSet<E>) EnumSet.of(first);
+ for (int i = 1; i < length; i++)
+ this.value.add((E) ObjectWritable.readObject(in, conf));
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void write(DataOutput out) throws IOException {
+ if (this.value == null) {
+ out.writeInt(-1);
+ WritableUtils.writeString(out, this.elementType.getName());
+ } else {
+ Object[] array = this.value.toArray();
+ int length = array.length;
+ out.writeInt(length);
+ if (length == 0) {
+ if (this.elementType == null)
+ throw new UnsupportedOperationException(
+ "Unable to serialize empty EnumSet with no element type provided.");
+ WritableUtils.writeString(out, this.elementType.getName());
+ }
+ for (int i = 0; i < length; i++) {
+ ObjectWritable.writeObject(out, array[i], array[i].getClass(), conf);
+ }
+ }
+ }
+
+ /**
+ * Returns true if <code>o</code> is an EnumSetWritable with the same value,
+ * or both are null.
+ */
+ public boolean equals(Object o) {
+ if (o == null) {
+ throw new IllegalArgumentException("null argument passed in equal().");
+ }
+
+ if (!(o instanceof EnumSetWritable))
+ return false;
+
+ EnumSetWritable<?> other = (EnumSetWritable<?>) o;
+
+ if (this == o || (this.value == other.value))
+ return true;
+ if (this.value == null) // other.value must not be null if we reach here
+ return false;
+
+ return this.value.equals(other.value);
+ }
+
+ /**
+ * Returns the class of all the elements of the underlying EnumSetWriable. It
+ * may return null.
+ *
+ * @return the element class
+ */
+ public Class<E> getElementType() {
+ return elementType;
+ }
+
+ /** {@inheritDoc} */
+ public int hashCode() {
+ if (value == null)
+ return 0;
+ return (int) value.hashCode();
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ if (value == null)
+ return "(null)";
+ return value.toString();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Configuration getConf() {
+ return this.conf;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setConf(Configuration conf) {
+ this.conf = conf;
+ }
+
+ static {
+ WritableFactories.setFactory(EnumSetWritable.class, new WritableFactory() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public Writable newInstance() {
+ return new EnumSetWritable();
+ }
+ });
+ }
+}
Modified: hadoop/core/trunk/src/core/org/apache/hadoop/io/ObjectWritable.java
URL: http://svn.apache.org/viewvc/hadoop/core/trunk/src/core/org/apache/hadoop/io/ObjectWritable.java?rev=771505&r1=771504&r2=771505&view=diff
==============================================================================
--- hadoop/core/trunk/src/core/org/apache/hadoop/io/ObjectWritable.java (original)
+++ hadoop/core/trunk/src/core/org/apache/hadoop/io/ObjectWritable.java Mon May 4 23:56:46 2009
@@ -179,13 +179,9 @@
String className = UTF8.readString(in);
Class<?> declaredClass = PRIMITIVE_NAMES.get(className);
if (declaredClass == null) {
- try {
- declaredClass = conf.getClassByName(className);
- } catch (ClassNotFoundException e) {
- throw new RuntimeException("readObject can't find class " + className, e);
- }
- }
-
+ declaredClass = loadClass(conf, className);
+ }
+
Object instance;
if (declaredClass.isPrimitive()) { // primitive types
@@ -225,13 +221,8 @@
instance = Enum.valueOf((Class<? extends Enum>) declaredClass, UTF8.readString(in));
} else { // Writable
Class instanceClass = null;
- String str = "";
- try {
- str = UTF8.readString(in);
- instanceClass = conf.getClassByName(str);
- } catch (ClassNotFoundException e) {
- throw new RuntimeException("readObject can't find class " + str, e);
- }
+ String str = UTF8.readString(in);
+ instanceClass = loadClass(conf, str);
Writable writable = WritableFactories.newInstance(instanceClass, conf);
writable.readFields(in);
@@ -252,6 +243,25 @@
}
+ /**
+ * Find and load the class with given name <tt>className</tt> by first finding
+ * it in the specified <tt>conf</tt>. If the specified <tt>conf</tt> is null,
+ * try load it directly.
+ */
+ public static Class<?> loadClass(Configuration conf, String className) {
+ Class<?> declaredClass = null;
+ try {
+ if (conf != null)
+ declaredClass = conf.getClassByName(className);
+ else
+ declaredClass = Class.forName(className);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("readObject can't find class " + className,
+ e);
+ }
+ return declaredClass;
+ }
+
public void setConf(Configuration conf) {
this.conf = conf;
}
Added: hadoop/core/trunk/src/test/org/apache/hadoop/io/TestEnumSetWritable.java
URL: http://svn.apache.org/viewvc/hadoop/core/trunk/src/test/org/apache/hadoop/io/TestEnumSetWritable.java?rev=771505&view=auto
==============================================================================
--- hadoop/core/trunk/src/test/org/apache/hadoop/io/TestEnumSetWritable.java (added)
+++ hadoop/core/trunk/src/test/org/apache/hadoop/io/TestEnumSetWritable.java Mon May 4 23:56:46 2009
@@ -0,0 +1,103 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.io;
+
+import java.io.IOException;
+import java.util.EnumSet;
+
+import junit.framework.TestCase;
+
+/** Unit test for EnumSetWritable */
+public class TestEnumSetWritable extends TestCase {
+
+ enum TestEnumSet {
+ CREATE, OVERWRITE, APPEND;
+ }
+
+ EnumSet<TestEnumSet> nonEmptyFlag = EnumSet.of(TestEnumSet.APPEND);
+ EnumSetWritable<TestEnumSet> nonEmptyFlagWritable = new EnumSetWritable<TestEnumSet>(
+ nonEmptyFlag);
+
+ @SuppressWarnings("unchecked")
+ public void testSerializeAndDeserializeNonEmpty() throws IOException {
+ DataOutputBuffer out = new DataOutputBuffer();
+ ObjectWritable.writeObject(out, nonEmptyFlagWritable, nonEmptyFlagWritable
+ .getClass(), null);
+ DataInputBuffer in = new DataInputBuffer();
+ in.reset(out.getData(), out.getLength());
+ EnumSet<TestEnumSet> read = ((EnumSetWritable<TestEnumSet>) ObjectWritable
+ .readObject(in, null)).get();
+ assertEquals(read, nonEmptyFlag);
+ }
+
+ EnumSet<TestEnumSet> emptyFlag = EnumSet.noneOf(TestEnumSet.class);
+
+ @SuppressWarnings("unchecked")
+ public void testSerializeAndDeserializeEmpty() throws IOException {
+
+ boolean gotException = false;
+ try {
+ new EnumSetWritable<TestEnumSet>(emptyFlag);
+ } catch (RuntimeException e) {
+ gotException = true;
+ }
+
+ assertTrue(
+ "Instantiate empty EnumSetWritable with no element type class providesd should throw exception.",
+ gotException);
+
+ EnumSetWritable<TestEnumSet> emptyFlagWritable = new EnumSetWritable<TestEnumSet>(
+ emptyFlag, TestEnumSet.class);
+ DataOutputBuffer out = new DataOutputBuffer();
+ ObjectWritable.writeObject(out, emptyFlagWritable, emptyFlagWritable
+ .getClass(), null);
+ DataInputBuffer in = new DataInputBuffer();
+ in.reset(out.getData(), out.getLength());
+ EnumSet<TestEnumSet> read = ((EnumSetWritable<TestEnumSet>) ObjectWritable
+ .readObject(in, null)).get();
+ assertEquals(read, emptyFlag);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testSerializeAndDeserializeNull() throws IOException {
+
+ boolean gotException = false;
+ try {
+ new EnumSetWritable<TestEnumSet>(null);
+ } catch (RuntimeException e) {
+ gotException = true;
+ }
+
+ assertTrue(
+ "Instantiate empty EnumSetWritable with no element type class providesd should throw exception.",
+ gotException);
+
+ EnumSetWritable<TestEnumSet> nullFlagWritable = new EnumSetWritable<TestEnumSet>(
+ null, TestEnumSet.class);
+
+ DataOutputBuffer out = new DataOutputBuffer();
+ ObjectWritable.writeObject(out, nullFlagWritable, nullFlagWritable
+ .getClass(), null);
+ DataInputBuffer in = new DataInputBuffer();
+ in.reset(out.getData(), out.getLength());
+ EnumSet<TestEnumSet> read = ((EnumSetWritable<TestEnumSet>) ObjectWritable
+ .readObject(in, null)).get();
+ assertEquals(read, null);
+ }
+}