You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by dk...@apache.org on 2019/01/14 21:10:30 UTC
[avro] branch master updated: Make elements of an array reusable
again
This is an automated email from the ASF dual-hosted git repository.
dkulp pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/avro.git
The following commit(s) were added to refs/heads/master by this push:
new 806adf7 Make elements of an array reusable again
806adf7 is described below
commit 806adf7bba3dbff20002b6dd2d64d6e3be062321
Author: unchuckable <un...@wolke7.net>
AuthorDate: Thu Dec 20 23:56:28 2018 +0100
Make elements of an array reusable again
---
.../java/org/apache/avro/generic/GenericArray.java | 8 ++++++++
.../java/org/apache/avro/generic/GenericData.java | 13 +++++++++++++
.../apache/avro/generic/GenericDatumReader.java | 18 +++++++++++++++---
.../org/apache/avro/generic/TestGenericData.java | 22 ++++++++++++++++++++++
4 files changed, 58 insertions(+), 3 deletions(-)
diff --git a/lang/java/avro/src/main/java/org/apache/avro/generic/GenericArray.java b/lang/java/avro/src/main/java/org/apache/avro/generic/GenericArray.java
index 428d2f3..56f4438 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/generic/GenericArray.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/generic/GenericArray.java
@@ -27,6 +27,14 @@ public interface GenericArray<T> extends List<T>, GenericContainer {
* without allocating new objects. */
T peek();
+ /** reset size counter of array to zero */
+ default void reset() {
+ clear();
+ }
+
+ /** clean up reusable objects from array (if reset didn't already) */
+ default void prune() {}
+
/** Reverses the order of the elements in this array. */
void reverse();
}
diff --git a/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java b/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java
index 7294192..26b0872 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java
@@ -267,6 +267,19 @@ public class GenericData {
Arrays.fill(elements, 0, size, null);
size = 0;
}
+
+ @Override
+ public void reset() {
+ size = 0;
+ }
+
+ @Override
+ public void prune() {
+ if (size<elements.length) {
+ Arrays.fill(elements, size, elements.length, null);
+ }
+ }
+
@Override public Iterator<T> iterator() {
return new Iterator<T>() {
private int position = 0;
diff --git a/lang/java/avro/src/main/java/org/apache/avro/generic/GenericDatumReader.java b/lang/java/avro/src/main/java/org/apache/avro/generic/GenericDatumReader.java
index 9b7b04c..b5ef33b 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/generic/GenericDatumReader.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/generic/GenericDatumReader.java
@@ -100,6 +100,7 @@ public class GenericDatumReader<D> implements DatumReader<D> {
private static final ThreadLocal<Map<Schema,Map<Schema,ResolvingDecoder>>>
RESOLVER_CACHE =
new ThreadLocal<Map<Schema,Map<Schema,ResolvingDecoder>>>() {
+ @Override
protected Map<Schema,Map<Schema,ResolvingDecoder>> initialValue() {
return new WeakIdentityHashMap<>();
}
@@ -269,12 +270,20 @@ public class GenericDatumReader<D> implements DatumReader<D> {
}
base += l;
} while ((l = in.arrayNext()) > 0);
- return array;
+ return pruneArray(array);
} else {
- return newArray(old, 0, expected);
+ return pruneArray(newArray(old, 0, expected));
}
}
+
+ private Object pruneArray(Object object) {
+ if (object instanceof GenericArray<?>) {
+ ((GenericArray<?>)object).prune();
+ }
+ return object;
+ }
+
/** Called by the default implementation of {@link #readArray} to retrieve a
* value from a reused instance. The default implementation is for {@link
* GenericArray}.*/
@@ -385,7 +394,10 @@ public class GenericDatumReader<D> implements DatumReader<D> {
* GenericData.Array}.*/
@SuppressWarnings("unchecked")
protected Object newArray(Object old, int size, Schema schema) {
- if (old instanceof Collection) {
+ if (old instanceof GenericArray) {
+ ((GenericArray)old).reset();
+ return old;
+ } else if (old instanceof Collection) {
((Collection) old).clear();
return old;
} else return new GenericData.Array(size, schema);
diff --git a/lang/java/avro/src/test/java/org/apache/avro/generic/TestGenericData.java b/lang/java/avro/src/test/java/org/apache/avro/generic/TestGenericData.java
index fe8f618..dd4c1f6 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/generic/TestGenericData.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/generic/TestGenericData.java
@@ -695,4 +695,26 @@ public class TestGenericData {
fail("StackOverflowError occurred");
}
}
+
+ @Test
+ /** check that GenericArray.reset() retains reusable elements and that GenericArray.prune() cleans
+ * them up properly.
+ */
+ public void testGenericArrayPeek() {
+ Schema elementSchema = SchemaBuilder.record("element").fields().requiredString("value").endRecord();
+ Schema arraySchema = Schema.createArray(elementSchema);
+
+ GenericRecord record = new GenericData.Record( elementSchema );
+ record.put("value", "string");
+
+ GenericArray<GenericRecord> list = new GenericData.Array<GenericRecord>(1, arraySchema);
+ list.add(record);
+
+ list.reset();
+ assertTrue( record == list.peek() );
+
+ list.prune();
+ assertNull( list.peek() );
+ }
+
}