Permalink
Browse files

AVRO-1199. Java: Fix SortedKeyValueFile to copy the key used to compa…

…re against next.

git-svn-id: https://svn.apache.org/repos/asf/avro/trunk@1409542 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information...
1 parent 1638ebb commit c8fe3e085e7afb5ee7de69561f0578a8ca2f046c @cutting cutting committed Nov 14, 2012
View
@@ -40,6 +40,9 @@ Trunk (not yet released)
AVRO-1200. DatumWriter can write malformed data if collection is
modified during write. (tomwhite)
+ AVRO-1199. Java: Fix SortedKeyValueFile to copy the key used to
+ compare against next. Also improve GenericData#deepCopy() to be
+ generic, so that its return type matches its parameter type. (cutting)
Avro 1.7.2 (20 October 2012)
@@ -767,7 +767,7 @@ protected int compare(Object o1, Object o2, Schema s, boolean equals) {
* @return a deep copy of the given value.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
- public Object deepCopy(Schema schema, Object value) {
+ public <T> T deepCopy(Schema schema, T value) {
if (value == null) {
return null;
}
@@ -779,30 +779,30 @@ public Object deepCopy(Schema schema, Object value) {
for (Object obj : arrayValue) {
arrayCopy.add(deepCopy(schema.getElementType(), obj));
}
- return arrayCopy;
+ return (T)arrayCopy;
case BOOLEAN:
- return new Boolean((Boolean)value);
+ return (T)new Boolean((Boolean)value);
case BYTES:
ByteBuffer byteBufferValue = (ByteBuffer) value;
int start = byteBufferValue.position();
int length = byteBufferValue.limit() - start;
byte[] bytesCopy = new byte[length];
byteBufferValue.get(bytesCopy, 0, length);
byteBufferValue.position(start);
- return ByteBuffer.wrap(bytesCopy, 0, length);
+ return (T)ByteBuffer.wrap(bytesCopy, 0, length);
case DOUBLE:
- return new Double((Double)value);
+ return (T)new Double((Double)value);
case ENUM:
// Enums are immutable; shallow copy will suffice
return value;
case FIXED:
- return createFixed(null, ((GenericFixed) value).bytes(), schema);
+ return (T)createFixed(null, ((GenericFixed) value).bytes(), schema);
case FLOAT:
- return new Float((Float)value);
+ return (T)new Float((Float)value);
case INT:
- return new Integer((Integer)value);
+ return (T)new Integer((Integer)value);
case LONG:
- return new Long((Long)value);
+ return (T)new Long((Long)value);
case MAP:
Map<CharSequence, Object> mapValue = (Map) value;
Map<CharSequence, Object> mapCopy =
@@ -811,7 +811,7 @@ public Object deepCopy(Schema schema, Object value) {
mapCopy.put((CharSequence)(deepCopy(STRINGS, entry.getKey())),
deepCopy(schema.getValueType(), entry.getValue()));
}
- return mapCopy;
+ return (T)mapCopy;
case NULL:
return null;
case RECORD:
@@ -821,21 +821,21 @@ public Object deepCopy(Schema schema, Object value) {
recordCopy.put(field.pos(),
deepCopy(field.schema(), recordValue.get(field.pos())));
}
- return recordCopy;
+ return (T)recordCopy;
case STRING:
// Strings are immutable
if (value instanceof String) {
- return value;
+ return (T)value;
}
// Some CharSequence subclasses are mutable, so we still need to make
// a copy
else if (value instanceof Utf8) {
// Utf8 copy constructor is more efficient than converting
// to string and then back to Utf8
- return new Utf8((Utf8)value);
+ return (T)new Utf8((Utf8)value);
}
- return new Utf8(value.toString());
+ return (T)new Utf8(value.toString());
case UNION:
return deepCopy(
schema.getTypes().get(resolveUnion(schema, value)), value);
@@ -83,6 +83,14 @@ public Utf8 setByteLength(int newLength) {
return this;
}
+ /** Set to the contents of a String. */
+ public Utf8 set(String string) {
+ this.bytes = getBytesFor(string);
+ this.length = bytes.length;
+ this.string = string;
+ return this;
+ }
+
@Override
public String toString() {
if (this.length == 0) return "";
@@ -96,11 +96,11 @@ private Builder(org.apache.avro.FooBarSpecificRecord.Builder other) {
private Builder(org.apache.avro.FooBarSpecificRecord other) {
super(org.apache.avro.FooBarSpecificRecord.SCHEMA$);
if (isValidValue(fields()[0], other.id)) {
- this.id = (java.lang.Integer) data().deepCopy(fields()[0].schema(), other.id);
+ this.id = data().deepCopy(fields()[0].schema(), other.id);
fieldSetFlags()[0] = true;
}
if (isValidValue(fields()[1], other.relatedids)) {
- this.relatedids = (java.util.List<java.lang.Integer>) data().deepCopy(fields()[1].schema(), other.relatedids);
+ this.relatedids = data().deepCopy(fields()[1].schema(), other.relatedids);
fieldSetFlags()[1] = true;
}
}
@@ -374,8 +374,7 @@ public void testByteBufferDeepCopy() {
GenericRecord record = new GenericData.Record(schema);
record.put(byte_field.name(), buffer);
- GenericRecord copy =
- (GenericRecord) GenericData.get().deepCopy(schema, record);
+ GenericRecord copy = GenericData.get().deepCopy(schema, record);
ByteBuffer buffer_copy = (ByteBuffer) copy.get(byte_field.name());
assertEquals(buffer, buffer_copy);
@@ -159,7 +159,7 @@ public class ${this.mangle($schema.getName())}#if ($schema.isError()) extends or
super(#if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.SCHEMA$)#end;
#foreach ($field in $schema.getFields())
if (isValidValue(fields()[$field.pos()], other.${this.mangle($field.name(), $schema.isError())})) {
- this.${this.mangle($field.name(), $schema.isError())} = (${this.javaType($field.schema())}) data().deepCopy(fields()[$field.pos()].schema(), other.${this.mangle($field.name(), $schema.isError())});
+ this.${this.mangle($field.name(), $schema.isError())} = data().deepCopy(fields()[$field.pos()].schema(), other.${this.mangle($field.name(), $schema.isError())});
fieldSetFlags()[$field.pos()] = true;
}
#end
@@ -536,7 +536,7 @@ public void append(K key, V value) throws IOException {
throw new IllegalArgumentException("Records must be inserted in sorted key order."
+ " Attempted to insert key " + key + " after " + mPreviousKey + ".");
}
- mPreviousKey = key;
+ mPreviousKey = GenericData.get().deepCopy(mKeySchema, key);
// Construct the data record.
AvroKeyValue<K, V> dataRecord
@@ -32,6 +32,7 @@
import org.apache.avro.io.DatumReader;
import org.apache.avro.file.FileReader;
import org.apache.avro.file.DataFileReader;
+import org.apache.avro.util.Utf8;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.junit.Rule;
@@ -61,9 +62,11 @@ public void testWriteOutOfSortedOrder() throws IOException {
SortedKeyValueFile.Writer<CharSequence, CharSequence> writer
= new SortedKeyValueFile.Writer<CharSequence, CharSequence>(options);
+ Utf8 key = new Utf8(); // re-use key, to test copied
+
try {
- writer.append("banana", "Banana");
- writer.append("apple", "Apple"); // Ruh, roh!
+ writer.append(key.set("banana"), "Banana");
+ writer.append(key.set("apple"), "Apple"); // Ruh, roh!
} finally {
writer.close();
}
@@ -150,19 +150,19 @@ private Builder(avro.examples.baseball.Player.Builder other) {
private Builder(avro.examples.baseball.Player other) {
super(avro.examples.baseball.Player.SCHEMA$);
if (isValidValue(fields()[0], other.number)) {
- this.number = (java.lang.Integer) data().deepCopy(fields()[0].schema(), other.number);
+ this.number = data().deepCopy(fields()[0].schema(), other.number);
fieldSetFlags()[0] = true;
}
if (isValidValue(fields()[1], other.first_name)) {
- this.first_name = (java.lang.CharSequence) data().deepCopy(fields()[1].schema(), other.first_name);
+ this.first_name = data().deepCopy(fields()[1].schema(), other.first_name);
fieldSetFlags()[1] = true;
}
if (isValidValue(fields()[2], other.last_name)) {
- this.last_name = (java.lang.CharSequence) data().deepCopy(fields()[2].schema(), other.last_name);
+ this.last_name = data().deepCopy(fields()[2].schema(), other.last_name);
fieldSetFlags()[2] = true;
}
if (isValidValue(fields()[3], other.position)) {
- this.position = (java.util.List<avro.examples.baseball.Position>) data().deepCopy(fields()[3].schema(), other.position);
+ this.position = data().deepCopy(fields()[3].schema(), other.position);
fieldSetFlags()[3] = true;
}
}

0 comments on commit c8fe3e0

Please sign in to comment.