HBASE-3429 HBaseObjectWritable should support arrays of any Writable or Serializable, not just Writable[]

git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1056548 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Michael Stack 2011-01-07 22:33:24 +00:00
parent ce16f762e9
commit efa5448aa3
3 changed files with 110 additions and 29 deletions

View File

@ -46,6 +46,8 @@ Release 0.91.0 - Unreleased
(Jesse Yates via Stack)
HBASE-3393 Update Avro gateway to use Avro 1.4.1 and the new
server.join() method (Jeff Hammerbacher via Stack)
HBASE-3429 HBaseObjectWritable should support arrays of any Writable
or Serializable, not just Writable[] (Ed Kohlwey via Stack)
NEW FEATURES

View File

@ -84,6 +84,7 @@ import org.apache.hadoop.hbase.regionserver.HRegion;
import org.apache.hadoop.hbase.regionserver.wal.HLog;
import org.apache.hadoop.hbase.regionserver.wal.HLogKey;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Classes;
import org.apache.hadoop.io.MapWritable;
import org.apache.hadoop.io.ObjectWritable;
import org.apache.hadoop.io.Text;
@ -382,7 +383,9 @@ public class HbaseObjectWritable implements Writable, WritableWithSize, Configur
declClass = Writable.class;
}
writeClassCode(out, declClass);
if (declClass.isArray()) { // array
// used to just be arrays. Now check for ones for which there's a
// class code, and let the others get scooped up by serializable.
if (declClass.isArray() && CLASS_TO_CODE.get(declClass)!=null) { // array
// If bytearray, just dump it out -- avoid the recursion and
// byte-at-a-time we were previously doing.
if (declClass.equals(byte [].class)) {
@ -449,18 +452,27 @@ public class HbaseObjectWritable implements Writable, WritableWithSize, Configur
} else {
writeClassCode(out, c);
}
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
try{
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(instanceObj);
byte[] value = bos.toByteArray();
out.writeInt(value.length);
out.write(value);
} finally {
if(bos!=null) bos.close();
if(oos!=null) oos.close();
if(declClass.isArray()){
int length = Array.getLength(instanceObj);
out.writeInt(length);
for (int i = 0; i < length; i++) {
writeObject(out, Array.get(instanceObj, i),
declClass.getComponentType(), conf);
}
} else {
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
try{
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(instanceObj);
byte[] value = bos.toByteArray();
out.writeInt(value.length);
out.write(value);
} finally {
if(bos!=null) bos.close();
if(oos!=null) oos.close();
}
}
} else {
throw new IOException("Can't write: "+instanceObj+" as "+declClass);
@ -569,21 +581,29 @@ public class HbaseObjectWritable implements Writable, WritableWithSize, Configur
instance = null;
}
} else {
int length = in.readInt();
byte[] objectBytes = new byte[length];
in.readFully(objectBytes);
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try {
bis = new ByteArrayInputStream(objectBytes);
ois = new ObjectInputStream(bis);
instance = ois.readObject();
} catch (ClassNotFoundException e) {
LOG.error("Error in readFields", e);
throw new IOException("Error in readFields", e);
} finally {
if(bis!=null) bis.close();
if(ois!=null) ois.close();
if(instanceClass.isArray()){
int length = in.readInt();
instance = Array.newInstance(instanceClass.getComponentType(), length);
for(int i = 0; i< length; i++){
Array.set(instance, i, HbaseObjectWritable.readObject(in, conf));
}
} else {
int length = in.readInt();
byte[] objectBytes = new byte[length];
in.readFully(objectBytes);
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try {
bis = new ByteArrayInputStream(objectBytes);
ois = new ObjectInputStream(bis);
instance = ois.readObject();
} catch (ClassNotFoundException e) {
LOG.error("Error in readFields", e);
throw new IOException("Error in readFields", e);
} finally {
if(bis!=null) bis.close();
if(ois!=null) ois.close();
}
}
}
}

View File

@ -21,6 +21,7 @@ package org.apache.hadoop.hbase.io;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import junit.framework.TestCase;
@ -122,6 +123,20 @@ public class TestHbaseObjectWritable extends TestCase {
assertEquals("mykey", ((CustomFilter)child).getKey());
}
public void testCustomWritableArray() throws Exception {
Configuration conf = HBaseConfiguration.create();
// test proper serialization of un-encoded custom writables
CustomWritable custom1 = new CustomWritable("test phrase");
CustomWritable custom2 = new CustomWritable("test phrase2");
CustomWritable[] customs = {custom1, custom2};
Object obj = doType(conf, customs, CustomWritable[].class);
assertTrue("Arrays should match " + Arrays.toString(customs) + ", "
+ Arrays.toString((Object[]) obj),
Arrays.equals(customs, (Object[])obj));
}
public void testCustomSerializable() throws Exception {
Configuration conf = HBaseConfiguration.create();
@ -132,6 +147,20 @@ public class TestHbaseObjectWritable extends TestCase {
assertTrue(obj instanceof CustomSerializable);
assertEquals("test phrase", ((CustomSerializable)obj).getValue());
}
public void testCustomSerializableArray() throws Exception {
Configuration conf = HBaseConfiguration.create();
// test proper serialization of un-encoded serialized java objects
CustomSerializable custom1 = new CustomSerializable("test phrase");
CustomSerializable custom2 = new CustomSerializable("test phrase2");
CustomSerializable[] custom = {custom1, custom2};
Object obj = doType(conf, custom, CustomSerializable[].class);
assertTrue("Arrays should match " + Arrays.toString(custom) + ", "
+ Arrays.toString((Object[]) obj),
Arrays.equals(custom, (Object[]) obj));
}
private Object doType(final Configuration conf, final Object value,
final Class<?> clazz)
@ -149,7 +178,7 @@ public class TestHbaseObjectWritable extends TestCase {
}
public static class CustomSerializable implements Serializable {
private static final long serialVersionUID = 1048445561865740632L;
private static final long serialVersionUID = 1048445561865740633L;
private String value = null;
public CustomSerializable() {
@ -167,6 +196,21 @@ public class TestHbaseObjectWritable extends TestCase {
this.value = value;
}
@Override
public boolean equals(Object obj) {
return (obj instanceof CustomSerializable) && ((CustomSerializable)obj).value.equals(value);
}
@Override
public int hashCode() {
return value.hashCode();
}
@Override
public String toString() {
return "<" + value + ">";
}
}
public static class CustomWritable implements Writable {
@ -190,6 +234,21 @@ public class TestHbaseObjectWritable extends TestCase {
public void readFields(DataInput in) throws IOException {
this.value = Text.readString(in);
}
@Override
public boolean equals(Object obj) {
return (obj instanceof CustomWritable) && ((CustomWritable)obj).value.equals(value);
}
@Override
public int hashCode() {
return value.hashCode();
}
@Override
public String toString() {
return "<" + value + ">";
}
}
public static class CustomFilter extends FilterBase {