Author: shv Date: Wed Apr 6 19:04:34 2011 New Revision: 1089563 URL: http://svn.apache.org/viewvc?rev=1089563&view=rev Log: HADOOP-6949. Merge -c 1083957 from trunk to branch 0.22.
Added: hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/io/ArrayPrimitiveWritable.java (with props) hadoop/common/branches/branch-0.22/src/test/core/org/apache/hadoop/io/TestArrayPrimitiveWritable.java (with props) Modified: hadoop/common/branches/branch-0.22/CHANGES.txt hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/io/ObjectWritable.java hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/ipc/Server.java hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/ipc/WritableRpcEngine.java Modified: hadoop/common/branches/branch-0.22/CHANGES.txt URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.22/CHANGES.txt?rev=1089563&r1=1089562&r2=1089563&view=diff ============================================================================== --- hadoop/common/branches/branch-0.22/CHANGES.txt (original) +++ hadoop/common/branches/branch-0.22/CHANGES.txt Wed Apr 6 19:04:34 2011 @@ -234,6 +234,9 @@ Release 0.22.0 - Unreleased HADOOP-6683. ZlibCompressor does not fully utilize the buffer. (Kang Xiao via eli) + HADOOP-6949. Reduce RPC packet size of primitive arrays using + ArrayPrimitiveWritable instead of ObjectWritable. (Matt Foley via suresh) + BUG FIXES HADOOP-6638. try to relogin in a case of failed RPC connection (expired Added: hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/io/ArrayPrimitiveWritable.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/io/ArrayPrimitiveWritable.java?rev=1089563&view=auto ============================================================================== --- hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/io/ArrayPrimitiveWritable.java (added) +++ hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/io/ArrayPrimitiveWritable.java Wed Apr 6 19:04:34 2011 @@ -0,0 +1,346 @@ +/** + * 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.lang.reflect.Array; +import java.util.HashMap; +import java.util.Map; + +import org.apache.hadoop.HadoopIllegalArgumentException; +import org.apache.hadoop.classification.InterfaceAudience; +import org.apache.hadoop.classification.InterfaceStability; + +/** + * This is a wrapper class. It wraps a Writable implementation around + * an array of primitives (e.g., int[], long[], etc.), with optimized + * wire format, and without creating new objects per element. + * + * This is a wrapper class only; it does not make a copy of the + * underlying array. + */ +@InterfaceAudience.Public +@InterfaceStability.Stable +public class ArrayPrimitiveWritable implements Writable { + + //componentType is determined from the component type of the value array + //during a "set" operation. It must be primitive. + private Class<?> componentType = null; + //declaredComponentType need not be declared, but if you do (by using the + //ArrayPrimitiveWritable(Class<?>) constructor), it will provide typechecking + //for all "set" operations. + private Class<?> declaredComponentType = null; + private int length; + private Object value; //must be an array of <componentType>[length] + + private static final Map<String, Class<?>> PRIMITIVE_NAMES = + new HashMap<String, Class<?>>(16); + static { + PRIMITIVE_NAMES.put(boolean.class.getName(), boolean.class); + PRIMITIVE_NAMES.put(byte.class.getName(), byte.class); + PRIMITIVE_NAMES.put(char.class.getName(), char.class); + PRIMITIVE_NAMES.put(short.class.getName(), short.class); + PRIMITIVE_NAMES.put(int.class.getName(), int.class); + PRIMITIVE_NAMES.put(long.class.getName(), long.class); + PRIMITIVE_NAMES.put(float.class.getName(), float.class); + PRIMITIVE_NAMES.put(double.class.getName(), double.class); + } + + private static Class<?> getPrimitiveClass(String className) { + return PRIMITIVE_NAMES.get(className); + } + + private static void checkPrimitive(Class<?> componentType) { + if (componentType == null) { + throw new HadoopIllegalArgumentException("null component type not allowed"); + } + if (! PRIMITIVE_NAMES.containsKey(componentType.getName())) { + throw new HadoopIllegalArgumentException("input array component type " + + componentType.getName() + " is not a candidate primitive type"); + } + } + + private void checkDeclaredComponentType(Class<?> componentType) { + if ((declaredComponentType != null) + && (componentType != declaredComponentType)) { + throw new HadoopIllegalArgumentException("input array component type " + + componentType.getName() + " does not match declared type " + + declaredComponentType.getName()); + } + } + + private static void checkArray(Object value) { + if (value == null) { + throw new HadoopIllegalArgumentException("null value not allowed"); + } + if (! value.getClass().isArray()) { + throw new HadoopIllegalArgumentException("non-array value of class " + + value.getClass() + " not allowed"); + } + } + + /** + * Construct an empty instance, for use during Writable read + */ + public ArrayPrimitiveWritable() { + //empty constructor + } + + /** + * Construct an instance of known type but no value yet + * for use with type-specific wrapper classes + */ + public ArrayPrimitiveWritable(Class<?> componentType) { + checkPrimitive(componentType); + this.declaredComponentType = componentType; + } + + /** + * Wrap an existing array of primitives + * @param value - array of primitives + */ + public ArrayPrimitiveWritable(Object value) { + set(value); + } + + /** + * Get the original array. + * Client must cast it back to type componentType[] + * (or may use type-specific wrapper classes). + * @return - original array as Object + */ + public Object get() { return value; } + + public Class<?> getComponentType() { return componentType; } + + public Class<?> getDeclaredComponentType() { return declaredComponentType; } + + public boolean isDeclaredComponentType(Class<?> componentType) { + return componentType == declaredComponentType; + } + + public void set(Object value) { + checkArray(value); + Class<?> componentType = value.getClass().getComponentType(); + checkPrimitive(componentType); + checkDeclaredComponentType(componentType); + this.componentType = componentType; + this.value = value; + this.length = Array.getLength(value); + } + + /** + * Do not use this class. + * This is an internal class, purely for ObjectWritable to use as + * a label class for transparent conversions of arrays of primitives + * during wire protocol reads and writes. + */ + static class Internal extends ArrayPrimitiveWritable { + Internal() { //use for reads + super(); + } + + Internal(Object value) { //use for writes + super(value); + } + } //end Internal subclass declaration + + /* + * @see org.apache.hadoop.io.Writable#write(java.io.DataOutput) + */ + @Override + @SuppressWarnings("deprecation") + public void write(DataOutput out) throws IOException { + // write componentType + UTF8.writeString(out, componentType.getName()); + // write length + out.writeInt(length); + + // do the inner loop. Walk the decision tree only once. + if (componentType == Boolean.TYPE) { // boolean + writeBooleanArray(out); + } else if (componentType == Character.TYPE) { // char + writeCharArray(out); + } else if (componentType == Byte.TYPE) { // byte + writeByteArray(out); + } else if (componentType == Short.TYPE) { // short + writeShortArray(out); + } else if (componentType == Integer.TYPE) { // int + writeIntArray(out); + } else if (componentType == Long.TYPE) { // long + writeLongArray(out); + } else if (componentType == Float.TYPE) { // float + writeFloatArray(out); + } else if (componentType == Double.TYPE) { // double + writeDoubleArray(out); + } else { + throw new IOException("Component type " + componentType.toString() + + " is set as the output type, but no encoding is implemented for this type."); + } + } + + /* + * @see org.apache.hadoop.io.Writable#readFields(java.io.DataInput) + */ + @Override + public void readFields(DataInput in) throws IOException { + + // read and set the component type of the array + @SuppressWarnings("deprecation") + String className = UTF8.readString(in); + Class<?> componentType = getPrimitiveClass(className); + if (componentType == null) { + throw new IOException("encoded array component type " + + className + " is not a candidate primitive type"); + } + checkDeclaredComponentType(componentType); + this.componentType = componentType; + + // read and set the length of the array + int length = in.readInt(); + if (length < 0) { + throw new IOException("encoded array length is negative " + length); + } + this.length = length; + + // construct and read in the array + value = Array.newInstance(componentType, length); + + // do the inner loop. Walk the decision tree only once. + if (componentType == Boolean.TYPE) { // boolean + readBooleanArray(in); + } else if (componentType == Character.TYPE) { // char + readCharArray(in); + } else if (componentType == Byte.TYPE) { // byte + readByteArray(in); + } else if (componentType == Short.TYPE) { // short + readShortArray(in); + } else if (componentType == Integer.TYPE) { // int + readIntArray(in); + } else if (componentType == Long.TYPE) { // long + readLongArray(in); + } else if (componentType == Float.TYPE) { // float + readFloatArray(in); + } else if (componentType == Double.TYPE) { // double + readDoubleArray(in); + } else { + throw new IOException("Encoded type " + className + + " converted to valid component type " + componentType.toString() + + " but no encoding is implemented for this type."); + } + } + + //For efficient implementation, there's no way around + //the following massive code duplication. + + private void writeBooleanArray(DataOutput out) throws IOException { + boolean[] v = (boolean[]) value; + for (int i = 0; i < length; i++) + out.writeBoolean(v[i]); + } + + private void writeCharArray(DataOutput out) throws IOException { + char[] v = (char[]) value; + for (int i = 0; i < length; i++) + out.writeChar(v[i]); + } + + private void writeByteArray(DataOutput out) throws IOException { + out.write((byte[]) value, 0, length); + } + + private void writeShortArray(DataOutput out) throws IOException { + short[] v = (short[]) value; + for (int i = 0; i < length; i++) + out.writeShort(v[i]); + } + + private void writeIntArray(DataOutput out) throws IOException { + int[] v = (int[]) value; + for (int i = 0; i < length; i++) + out.writeInt(v[i]); + } + + private void writeLongArray(DataOutput out) throws IOException { + long[] v = (long[]) value; + for (int i = 0; i < length; i++) + out.writeLong(v[i]); + } + + private void writeFloatArray(DataOutput out) throws IOException { + float[] v = (float[]) value; + for (int i = 0; i < length; i++) + out.writeFloat(v[i]); + } + + private void writeDoubleArray(DataOutput out) throws IOException { + double[] v = (double[]) value; + for (int i = 0; i < length; i++) + out.writeDouble(v[i]); + } + + private void readBooleanArray(DataInput in) throws IOException { + boolean[] v = (boolean[]) value; + for (int i = 0; i < length; i++) + v[i] = in.readBoolean(); + } + + private void readCharArray(DataInput in) throws IOException { + char[] v = (char[]) value; + for (int i = 0; i < length; i++) + v[i] = in.readChar(); + } + + private void readByteArray(DataInput in) throws IOException { + in.readFully((byte[]) value, 0, length); + } + + private void readShortArray(DataInput in) throws IOException { + short[] v = (short[]) value; + for (int i = 0; i < length; i++) + v[i] = in.readShort(); + } + + private void readIntArray(DataInput in) throws IOException { + int[] v = (int[]) value; + for (int i = 0; i < length; i++) + v[i] = in.readInt(); + } + + private void readLongArray(DataInput in) throws IOException { + long[] v = (long[]) value; + for (int i = 0; i < length; i++) + v[i] = in.readLong(); + } + + private void readFloatArray(DataInput in) throws IOException { + float[] v = (float[]) value; + for (int i = 0; i < length; i++) + v[i] = in.readFloat(); + } + + private void readDoubleArray(DataInput in) throws IOException { + double[] v = (double[]) value; + for (int i = 0; i < length; i++) + v[i] = in.readDouble(); + } +} + Propchange: hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/io/ArrayPrimitiveWritable.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/io/ObjectWritable.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/io/ObjectWritable.java?rev=1089563&r1=1089562&r2=1089563&view=diff ============================================================================== --- hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/io/ObjectWritable.java (original) +++ hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/io/ObjectWritable.java Wed Apr 6 19:04:34 2011 @@ -115,22 +115,51 @@ public class ObjectWritable implements W public static void writeObject(DataOutput out, Object instance, Class declaredClass, Configuration conf) throws IOException { + writeObject(out, instance, declaredClass, conf, false); + } + + /** + * Write a {@link Writable}, {@link String}, primitive type, or an array of + * the preceding. + * + * @param allowCompactArrays - set true for RPC and internal or intra-cluster + * usages. Set false for inter-cluster, File, and other persisted output + * usages, to preserve the ability to interchange files with other clusters + * that may not be running the same version of software. Sometime in ~2013 + * we can consider removing this parameter and always using the compact format. + */ + public static void writeObject(DataOutput out, Object instance, + Class declaredClass, Configuration conf, boolean allowCompactArrays) + throws IOException { if (instance == null) { // null instance = new NullInstance(declaredClass, conf); declaredClass = Writable.class; } + + // Special case: must come before writing out the declaredClass. + // If this is an eligible array of primitives, + // wrap it in an ArrayPrimitiveWritable$Internal wrapper class. + if (allowCompactArrays && declaredClass.isArray() + && instance.getClass().getName().equals(declaredClass.getName()) + && instance.getClass().getComponentType().isPrimitive()) { + instance = new ArrayPrimitiveWritable.Internal(instance); + declaredClass = ArrayPrimitiveWritable.Internal.class; + } UTF8.writeString(out, declaredClass.getName()); // always write declared - if (declaredClass.isArray()) { // array + if (declaredClass.isArray()) { // non-primitive or non-compact array int length = Array.getLength(instance); out.writeInt(length); for (int i = 0; i < length; i++) { writeObject(out, Array.get(instance, i), - declaredClass.getComponentType(), conf); + declaredClass.getComponentType(), conf, allowCompactArrays); } + } else if (declaredClass == ArrayPrimitiveWritable.Internal.class) { + ((ArrayPrimitiveWritable.Internal) instance).write(out); + } else if (declaredClass == String.class) { // String UTF8.writeString(out, (String)instance); @@ -219,6 +248,15 @@ public class ObjectWritable implements W Array.set(instance, i, readObject(in, conf)); } + } else if (declaredClass == ArrayPrimitiveWritable.Internal.class) { + // Read and unwrap ArrayPrimitiveWritable$Internal array. + // Always allow the read, even if write is disabled by allowCompactArrays. + ArrayPrimitiveWritable.Internal temp = + new ArrayPrimitiveWritable.Internal(); + temp.readFields(in); + instance = temp.get(); + declaredClass = instance.getClass(); + } else if (declaredClass == String.class) { // String instance = UTF8.readString(in); } else if (declaredClass.isEnum()) { // enum Modified: hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/ipc/Server.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/ipc/Server.java?rev=1089563&r1=1089562&r2=1089563&view=diff ============================================================================== --- hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/ipc/Server.java (original) +++ hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/ipc/Server.java Wed Apr 6 19:04:34 2011 @@ -105,7 +105,9 @@ public abstract class Server { // 1 : Introduce ping and server does not throw away RPCs // 3 : Introduce the protocol into the RPC connection header // 4 : Introduced SASL security layer - public static final byte CURRENT_VERSION = 4; + // 5 : Introduced use of {@link ArrayPrimitiveWritable$Internal} + // in ObjectWritable to efficiently transmit arrays of primitives + public static final byte CURRENT_VERSION = 5; /** * Initial and max size of response buffer Modified: hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/ipc/WritableRpcEngine.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/ipc/WritableRpcEngine.java?rev=1089563&r1=1089562&r2=1089563&view=diff ============================================================================== --- hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/ipc/WritableRpcEngine.java (original) +++ hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/ipc/WritableRpcEngine.java Wed Apr 6 19:04:34 2011 @@ -88,7 +88,7 @@ public class WritableRpcEngine implement out.writeInt(parameterClasses.length); for (int i = 0; i < parameterClasses.length; i++) { ObjectWritable.writeObject(out, parameters[i], parameterClasses[i], - conf); + conf, true); } } Added: hadoop/common/branches/branch-0.22/src/test/core/org/apache/hadoop/io/TestArrayPrimitiveWritable.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.22/src/test/core/org/apache/hadoop/io/TestArrayPrimitiveWritable.java?rev=1089563&view=auto ============================================================================== --- hadoop/common/branches/branch-0.22/src/test/core/org/apache/hadoop/io/TestArrayPrimitiveWritable.java (added) +++ hadoop/common/branches/branch-0.22/src/test/core/org/apache/hadoop/io/TestArrayPrimitiveWritable.java Wed Apr 6 19:04:34 2011 @@ -0,0 +1,180 @@ +/** + * 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.*; +import java.util.Arrays; + +import org.apache.hadoop.util.StringUtils; +import org.junit.*; + +import junit.framework.TestCase; + +/** Unit tests for {@link ArrayPrimitiveWritable} */ +public class TestArrayPrimitiveWritable extends TestCase { + + static final boolean[] b = {true, true, false}; + static final char[] c = {'a', 'b', 'c'}; + static final byte[] by = {1, 2, 3}; + static final short[] sh = {1, 2, 3}; + static final int[] i = {1, 2, 3}; + static final long[] lo = {1L, 2L, 3L}; + static final float[] f = {(float) 1.0, (float) 2.5, (float) 3.3}; + static final double[] d = {1.0, 2.5, 3.3}; + + static final Object[] bigSet = {b, c, by, sh, i, lo, f, d}; + static final Object[] expectedResultSet = {b, b, c, c, by, by, sh, sh, + i, i, lo, lo, f, f, d, d}; + final Object[] resultSet = new Object[bigSet.length * 2]; + + final DataOutputBuffer out = new DataOutputBuffer(); + final DataInputBuffer in = new DataInputBuffer(); + + @Before + public void resetBuffers() throws IOException { + out.reset(); + in.reset(); + } + + @Test + public void testMany() throws IOException { + //Write a big set of data, one of each primitive type array + for (Object x : bigSet) { + //write each test object two ways + //First, transparently via ObjectWritable + ObjectWritable.writeObject(out, x, x.getClass(), null, true); + //Second, explicitly via ArrayPrimitiveWritable + (new ArrayPrimitiveWritable(x)).write(out); + } + + //Now read the data back in + in.reset(out.getData(), out.getLength()); + for (int x = 0; x < resultSet.length; ) { + //First, transparently + resultSet[x++] = ObjectWritable.readObject(in, null); + //Second, explicitly + ArrayPrimitiveWritable apw = new ArrayPrimitiveWritable(); + apw.readFields(in); + resultSet[x++] = apw.get(); + } + + //validate data structures and values + assertEquals(expectedResultSet.length, resultSet.length); + for (int x = 0; x < resultSet.length; x++) { + assertEquals("ComponentType of array " + x, + expectedResultSet[x].getClass().getComponentType(), + resultSet[x].getClass().getComponentType()); + } + assertTrue("In and Out arrays didn't match values", + Arrays.deepEquals(expectedResultSet, resultSet)); + } + + @Test + @SuppressWarnings("deprecation") + public void testObjectLabeling() throws IOException { + //Do a few tricky experiments to make sure things are being written + //the way we expect + + //Write the data array with ObjectWritable + //which will indirectly write it using APW.Internal + ObjectWritable.writeObject(out, i, i.getClass(), null, true); + + //Write the corresponding APW directly with ObjectWritable + ArrayPrimitiveWritable apw = new ArrayPrimitiveWritable(i); + ObjectWritable.writeObject(out, apw, apw.getClass(), null, true); + + //Get ready to read it back + in.reset(out.getData(), out.getLength()); + + //Read the int[] object as written by ObjectWritable, but + //"going around" ObjectWritable + String className = UTF8.readString(in); + assertEquals("The int[] written by ObjectWritable was not labelled as " + + "an ArrayPrimitiveWritable.Internal", + ArrayPrimitiveWritable.Internal.class.getName(), className); + ArrayPrimitiveWritable.Internal apwi = + new ArrayPrimitiveWritable.Internal(); + apwi.readFields(in); + assertEquals("The ArrayPrimitiveWritable.Internal component type was corrupted", + int.class, apw.getComponentType()); + assertTrue("The int[] written by ObjectWritable as " + + "ArrayPrimitiveWritable.Internal was corrupted", + Arrays.equals(i, (int[])(apwi.get()))); + + //Read the APW object as written by ObjectWritable, but + //"going around" ObjectWritable + String declaredClassName = UTF8.readString(in); + assertEquals("The APW written by ObjectWritable was not labelled as " + + "declaredClass ArrayPrimitiveWritable", + ArrayPrimitiveWritable.class.getName(), declaredClassName); + className = UTF8.readString(in); + assertEquals("The APW written by ObjectWritable was not labelled as " + + "class ArrayPrimitiveWritable", + ArrayPrimitiveWritable.class.getName(), className); + ArrayPrimitiveWritable apw2 = + new ArrayPrimitiveWritable(); + apw2.readFields(in); + assertEquals("The ArrayPrimitiveWritable component type was corrupted", + int.class, apw2.getComponentType()); + assertTrue("The int[] written by ObjectWritable as " + + "ArrayPrimitiveWritable was corrupted", + Arrays.equals(i, (int[])(apw2.get()))); + } + + @Test + public void testOldFormat() throws IOException { + //Make sure we still correctly write the old format if desired. + + //Write the data array with old ObjectWritable API + //which will set allowCompactArrays false. + ObjectWritable.writeObject(out, i, i.getClass(), null); + + //Get ready to read it back + in.reset(out.getData(), out.getLength()); + + //Read the int[] object as written by ObjectWritable, but + //"going around" ObjectWritable + @SuppressWarnings("deprecation") + String className = UTF8.readString(in); + assertEquals("The int[] written by ObjectWritable as a non-compact array " + + "was not labelled as an array of int", + i.getClass().getName(), className); + + int length = in.readInt(); + assertEquals("The int[] written by ObjectWritable as a non-compact array " + + "was not expected length", i.length, length); + + int[] readValue = new int[length]; + try { + for (int i = 0; i < length; i++) { + readValue[i] = (int)((Integer)ObjectWritable.readObject(in, null)); + } + } catch (Exception e) { + fail("The int[] written by ObjectWritable as a non-compact array " + + "was corrupted. Failed to correctly read int[] of length " + + length + ". Got exception:\n" + + StringUtils.stringifyException(e)); + } + assertTrue("The int[] written by ObjectWritable as a non-compact array " + + "was corrupted.", Arrays.equals(i, readValue)); + + } +} + + Propchange: hadoop/common/branches/branch-0.22/src/test/core/org/apache/hadoop/io/TestArrayPrimitiveWritable.java ------------------------------------------------------------------------------ svn:mime-type = text/plain