You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by we...@apache.org on 2017/07/29 04:05:59 UTC
arrow git commit: ARROW-1192: [JAVA] Use buffer slice for
splitAndTransfer in List and Union Vectors.
Repository: arrow
Updated Branches:
refs/heads/master 05af6400d -> ec3261782
ARROW-1192: [JAVA] Use buffer slice for splitAndTransfer in List and Union Vectors.
@jacques-n
@StevenMPhillips
PR for the original change-set https://github.com/dremio/arrow/commit/75396ba07f58eb122110edb33ee2305bcdc122d7
with corresponding unit tests.
Author: siddharth <si...@dremio.com>
Author: Steven Phillips <st...@dremio.com>
Closes #901 from siddharthteotia/ARROW-1192-PR and squashes the following commits:
3d89c999 [siddharth] ARROW-1192: splitAndTransfer changes for ListVector,UnionVector and corresponding unit tests
035e886c [Steven Phillips] Use buffer slice for splitAndTransfer in List and Union vectors
Project: http://git-wip-us.apache.org/repos/asf/arrow/repo
Commit: http://git-wip-us.apache.org/repos/asf/arrow/commit/ec326178
Tree: http://git-wip-us.apache.org/repos/asf/arrow/tree/ec326178
Diff: http://git-wip-us.apache.org/repos/asf/arrow/diff/ec326178
Branch: refs/heads/master
Commit: ec3261782b864ed82e72971121667b57ab2d2e0b
Parents: 05af640
Author: siddharth <si...@dremio.com>
Authored: Sat Jul 29 00:05:55 2017 -0400
Committer: Wes McKinney <we...@twosigma.com>
Committed: Sat Jul 29 00:05:55 2017 -0400
----------------------------------------------------------------------
.../src/main/codegen/templates/UnionVector.java | 6 +-
.../apache/arrow/vector/complex/ListVector.java | 30 ++-
.../org/apache/arrow/vector/TestListVector.java | 199 +++++++++++++++++++
.../apache/arrow/vector/TestUnionVector.java | 181 +++++++++++++++++
4 files changed, 405 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/arrow/blob/ec326178/java/vector/src/main/codegen/templates/UnionVector.java
----------------------------------------------------------------------
diff --git a/java/vector/src/main/codegen/templates/UnionVector.java b/java/vector/src/main/codegen/templates/UnionVector.java
index aa9d34d..eabe42a 100644
--- a/java/vector/src/main/codegen/templates/UnionVector.java
+++ b/java/vector/src/main/codegen/templates/UnionVector.java
@@ -321,10 +321,8 @@ public class UnionVector implements FieldVector {
@Override
public void splitAndTransfer(int startIndex, int length) {
- to.allocateNew();
- for (int i = 0; i < length; i++) {
- to.copyFromSafe(startIndex + i, i, org.apache.arrow.vector.complex.UnionVector.this);
- }
+ internalMapVectorTransferPair.splitAndTransfer(startIndex, length);
+ typeVectorTransferPair.splitAndTransfer(startIndex, length);
to.getMutator().setValueCount(length);
}
http://git-wip-us.apache.org/repos/asf/arrow/blob/ec326178/java/vector/src/main/java/org/apache/arrow/vector/complex/ListVector.java
----------------------------------------------------------------------
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/complex/ListVector.java b/java/vector/src/main/java/org/apache/arrow/vector/complex/ListVector.java
index 6357294..fdeac39 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/complex/ListVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/complex/ListVector.java
@@ -38,6 +38,7 @@ import org.apache.arrow.vector.BufferBacked;
import org.apache.arrow.vector.FieldVector;
import org.apache.arrow.vector.UInt4Vector;
import org.apache.arrow.vector.ValueVector;
+import org.apache.arrow.vector.VarCharVector;
import org.apache.arrow.vector.ZeroVector;
import org.apache.arrow.vector.complex.impl.ComplexCopier;
import org.apache.arrow.vector.complex.impl.UnionListReader;
@@ -179,7 +180,11 @@ public class ListVector extends BaseRepeatedValueVector implements FieldVector,
private class TransferImpl implements TransferPair {
ListVector to;
- TransferPair pairs[] = new TransferPair[3];
+ TransferPair bitsTransferPair;
+ TransferPair offsetsTransferPair;
+ TransferPair dataTransferPair;
+
+ TransferPair[] pairs;
public TransferImpl(String name, BufferAllocator allocator, CallBack callBack) {
this(new ListVector(name, allocator, fieldType, callBack));
@@ -188,12 +193,13 @@ public class ListVector extends BaseRepeatedValueVector implements FieldVector,
public TransferImpl(ListVector to) {
this.to = to;
to.addOrGetVector(vector.getField().getFieldType());
- pairs[0] = offsets.makeTransferPair(to.offsets);
- pairs[1] = bits.makeTransferPair(to.bits);
+ offsetsTransferPair = offsets.makeTransferPair(to.offsets);
+ bitsTransferPair = bits.makeTransferPair(to.bits);
if (to.getDataVector() instanceof ZeroVector) {
to.addOrGetVector(vector.getField().getFieldType());
}
- pairs[2] = getDataVector().makeTransferPair(to.getDataVector());
+ dataTransferPair = getDataVector().makeTransferPair(to.getDataVector());
+ pairs = new TransferPair[] { bitsTransferPair, offsetsTransferPair, dataTransferPair };
}
@Override
@@ -206,10 +212,20 @@ public class ListVector extends BaseRepeatedValueVector implements FieldVector,
@Override
public void splitAndTransfer(int startIndex, int length) {
- to.allocateNew();
- for (int i = 0; i < length; i++) {
- copyValueSafe(startIndex + i, i);
+ UInt4Vector.Accessor offsetVectorAccessor = ListVector.this.offsets.getAccessor();
+ final int startPoint = offsetVectorAccessor.get(startIndex);
+ final int sliceLength = offsetVectorAccessor.get(startIndex + length) - startPoint;
+ to.clear();
+ to.offsets.allocateNew(length + 1);
+ offsetVectorAccessor = ListVector.this.offsets.getAccessor();
+ final UInt4Vector.Mutator targetOffsetVectorMutator = to.offsets.getMutator();
+ for (int i = 0; i < length + 1; i++) {
+ targetOffsetVectorMutator.set(i, offsetVectorAccessor.get(startIndex + i) - startPoint);
}
+ bitsTransferPair.splitAndTransfer(startIndex, length);
+ dataTransferPair.splitAndTransfer(startPoint, sliceLength);
+ to.lastSet = length;
+ to.mutator.setValueCount(length);
}
@Override
http://git-wip-us.apache.org/repos/asf/arrow/blob/ec326178/java/vector/src/test/java/org/apache/arrow/vector/TestListVector.java
----------------------------------------------------------------------
diff --git a/java/vector/src/test/java/org/apache/arrow/vector/TestListVector.java b/java/vector/src/test/java/org/apache/arrow/vector/TestListVector.java
index 29ea762..a1762c4 100644
--- a/java/vector/src/test/java/org/apache/arrow/vector/TestListVector.java
+++ b/java/vector/src/test/java/org/apache/arrow/vector/TestListVector.java
@@ -19,6 +19,8 @@ package org.apache.arrow.vector;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
import org.apache.arrow.memory.BufferAllocator;
import org.apache.arrow.vector.complex.ListVector;
@@ -30,6 +32,7 @@ import org.apache.arrow.vector.holders.NullableBigIntHolder;
import org.apache.arrow.vector.types.Types;
import org.apache.arrow.vector.types.Types.*;
import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.TransferPair;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@@ -234,4 +237,200 @@ public class TestListVector {
assertNull(actual);
}
}
+
+ @Test
+ public void testSplitAndTransfer() throws Exception {
+ try (ListVector listVector = ListVector.empty("sourceVector", allocator)) {
+
+ /* Explicitly add the dataVector */
+ MinorType type = MinorType.BIGINT;
+ listVector.addOrGetVector(FieldType.nullable(type.getType()));
+
+ UnionListWriter listWriter = listVector.getWriter();
+
+ /* allocate memory */
+ listWriter.allocate();
+
+ /* populate data */
+ listWriter.setPosition(0);
+ listWriter.startList();
+ listWriter.bigInt().writeBigInt(10);
+ listWriter.bigInt().writeBigInt(11);
+ listWriter.bigInt().writeBigInt(12);
+ listWriter.endList();
+
+ listWriter.setPosition(1);
+ listWriter.startList();
+ listWriter.bigInt().writeBigInt(13);
+ listWriter.bigInt().writeBigInt(14);
+ listWriter.endList();
+
+ listWriter.setPosition(2);
+ listWriter.startList();
+ listWriter.bigInt().writeBigInt(15);
+ listWriter.bigInt().writeBigInt(16);
+ listWriter.bigInt().writeBigInt(17);
+ listWriter.bigInt().writeBigInt(18);
+ listWriter.endList();
+
+ listWriter.setPosition(3);
+ listWriter.startList();
+ listWriter.bigInt().writeBigInt(19);
+ listWriter.endList();
+
+ listWriter.setPosition(4);
+ listWriter.startList();
+ listWriter.bigInt().writeBigInt(20);
+ listWriter.bigInt().writeBigInt(21);
+ listWriter.bigInt().writeBigInt(22);
+ listWriter.bigInt().writeBigInt(23);
+ listWriter.endList();
+
+ listVector.getMutator().setValueCount(5);
+
+ assertEquals(5, listVector.getMutator().getLastSet());
+
+ /* get offsetVector */
+ UInt4Vector offsetVector = (UInt4Vector)listVector.getOffsetVector();
+
+ /* get dataVector */
+ NullableBigIntVector dataVector = (NullableBigIntVector)listVector.getDataVector();
+
+ /* check the vector output */
+ final UInt4Vector.Accessor offsetAccessor = offsetVector.getAccessor();
+ final ValueVector.Accessor valueAccessor = dataVector.getAccessor();
+
+ int index = 0;
+ int offset = 0;
+ Object actual = null;
+
+ /* index 0 */
+ assertFalse(listVector.getAccessor().isNull(index));
+ offset = offsetAccessor.get(index);
+ assertEquals(Integer.toString(0), Integer.toString(offset));
+
+ actual = valueAccessor.getObject(offset);
+ assertEquals(new Long(10), (Long)actual);
+ offset++;
+ actual = valueAccessor.getObject(offset);
+ assertEquals(new Long(11), (Long)actual);
+ offset++;
+ actual = valueAccessor.getObject(offset);
+ assertEquals(new Long(12), (Long)actual);
+
+ /* index 1 */
+ index++;
+ assertFalse(listVector.getAccessor().isNull(index));
+ offset = offsetAccessor.get(index);
+ assertEquals(Integer.toString(3), Integer.toString(offset));
+
+ actual = valueAccessor.getObject(offset);
+ assertEquals(new Long(13), (Long)actual);
+ offset++;
+ actual = valueAccessor.getObject(offset);
+ assertEquals(new Long(14), (Long)actual);
+
+ /* index 2 */
+ index++;
+ assertFalse(listVector.getAccessor().isNull(index));
+ offset = offsetAccessor.get(index);
+ assertEquals(Integer.toString(5), Integer.toString(offset));
+
+ actual = valueAccessor.getObject(offset);
+ assertEquals(new Long(15), (Long)actual);
+ offset++;
+ actual = valueAccessor.getObject(offset);
+ assertEquals(new Long(16), (Long)actual);
+ offset++;
+ actual = valueAccessor.getObject(offset);
+ assertEquals(new Long(17), (Long)actual);
+ offset++;
+ actual = valueAccessor.getObject(offset);
+ assertEquals(new Long(18), (Long)actual);
+
+ /* index 3 */
+ index++;
+ assertFalse(listVector.getAccessor().isNull(index));
+ offset = offsetAccessor.get(index);
+ assertEquals(Integer.toString(9), Integer.toString(offset));
+
+ actual = valueAccessor.getObject(offset);
+ assertEquals(new Long(19), (Long)actual);
+
+ /* index 4 */
+ index++;
+ assertFalse(listVector.getAccessor().isNull(index));
+ offset = offsetAccessor.get(index);
+ assertEquals(Integer.toString(10), Integer.toString(offset));
+
+ actual = valueAccessor.getObject(offset);
+ assertEquals(new Long(20), (Long)actual);
+ offset++;
+ actual = valueAccessor.getObject(offset);
+ assertEquals(new Long(21), (Long)actual);
+ offset++;
+ actual = valueAccessor.getObject(offset);
+ assertEquals(new Long(22), (Long)actual);
+ offset++;
+ actual = valueAccessor.getObject(offset);
+ assertEquals(new Long(23), (Long)actual);
+
+ /* index 5 */
+ index++;
+ assertTrue(listVector.getAccessor().isNull(index));
+ offset = offsetAccessor.get(index);
+ assertEquals(Integer.toString(14), Integer.toString(offset));
+
+ /* do split and transfer */
+ try (ListVector toVector = ListVector.empty("toVector", allocator)) {
+
+ TransferPair transferPair = listVector.makeTransferPair(toVector);
+
+ int[][] transferLengths = { {0, 2},
+ {3, 1},
+ {4, 1}
+ };
+
+ for (final int[] transferLength : transferLengths) {
+ int start = transferLength[0];
+ int splitLength = transferLength[1];
+
+ int dataLength1 = 0;
+ int dataLength2 = 0;
+
+ int offset1 = 0;
+ int offset2 = 0;
+
+ transferPair.splitAndTransfer(start, splitLength);
+
+ /* get offsetVector of toVector */
+ UInt4Vector offsetVector1 = (UInt4Vector)toVector.getOffsetVector();
+ UInt4Vector.Accessor offsetAccessor1 = offsetVector1.getAccessor();
+
+ /* get dataVector of toVector */
+ NullableBigIntVector dataVector1 = (NullableBigIntVector)toVector.getDataVector();
+ NullableBigIntVector.Accessor valueAccessor1 = dataVector1.getAccessor();
+
+ for(int i = 0; i < splitLength; i++) {
+ dataLength1 = offsetAccessor.get(start + i + 1) - offsetAccessor.get(start + i);
+ dataLength2 = offsetAccessor1.get(i + 1) - offsetAccessor1.get(i);
+
+ assertEquals("Different data lengths at index: " + i + " and start: " + start,
+ dataLength1, dataLength2);
+
+ offset1 = offsetAccessor.get(start + i);
+ offset2 = offsetAccessor1.get(i);
+
+ for(int j = 0; j < dataLength1; j++) {
+ assertEquals("Different data at indexes: " + offset1 + " and " + offset2,
+ valueAccessor.getObject(offset1), valueAccessor1.getObject(offset2));
+
+ offset1++;
+ offset2++;
+ }
+ }
+ }
+ }
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/arrow/blob/ec326178/java/vector/src/test/java/org/apache/arrow/vector/TestUnionVector.java
----------------------------------------------------------------------
diff --git a/java/vector/src/test/java/org/apache/arrow/vector/TestUnionVector.java b/java/vector/src/test/java/org/apache/arrow/vector/TestUnionVector.java
index a5b90ee..a515924 100644
--- a/java/vector/src/test/java/org/apache/arrow/vector/TestUnionVector.java
+++ b/java/vector/src/test/java/org/apache/arrow/vector/TestUnionVector.java
@@ -24,6 +24,7 @@ import org.apache.arrow.vector.complex.UnionVector;
import org.apache.arrow.vector.holders.NullableBitHolder;
import org.apache.arrow.vector.holders.NullableIntHolder;
import org.apache.arrow.vector.holders.NullableUInt4Holder;
+import org.apache.arrow.vector.holders.NullableFloat4Holder;
import org.apache.arrow.vector.types.Types;
import org.apache.arrow.vector.types.Types.MinorType;
import org.apache.arrow.vector.util.TransferPair;
@@ -117,6 +118,179 @@ public class TestUnionVector {
}
}
+ @Test
+ public void testSplitAndTransfer() throws Exception {
+ try (UnionVector sourceVector = new UnionVector(EMPTY_SCHEMA_PATH, allocator, null)) {
+ final UnionVector.Mutator sourceMutator = sourceVector.getMutator();
+ final UnionVector.Accessor sourceAccessor = sourceVector.getAccessor();
+
+ sourceVector.allocateNew();
+
+ /* populate the UnionVector */
+ sourceMutator.setType(0, MinorType.INT);
+ sourceMutator.setSafe(0, newIntHolder(5));
+ sourceMutator.setType(1, MinorType.INT);
+ sourceMutator.setSafe(1, newIntHolder(10));
+ sourceMutator.setType(2, MinorType.INT);
+ sourceMutator.setSafe(2, newIntHolder(15));
+ sourceMutator.setType(3, MinorType.INT);
+ sourceMutator.setSafe(3, newIntHolder(20));
+ sourceMutator.setType(4, MinorType.INT);
+ sourceMutator.setSafe(4, newIntHolder(25));
+ sourceMutator.setType(5, MinorType.INT);
+ sourceMutator.setSafe(5, newIntHolder(30));
+ sourceMutator.setType(6, MinorType.INT);
+ sourceMutator.setSafe(6, newIntHolder(35));
+ sourceMutator.setType(7, MinorType.INT);
+ sourceMutator.setSafe(7, newIntHolder(40));
+ sourceMutator.setType(8, MinorType.INT);
+ sourceMutator.setSafe(8, newIntHolder(45));
+ sourceMutator.setType(9, MinorType.INT);
+ sourceMutator.setSafe(9, newIntHolder(50));
+ sourceMutator.setValueCount(10);
+
+ /* check the vector output */
+ assertEquals(10, sourceAccessor.getValueCount());
+ assertEquals(false, sourceAccessor.isNull(0));
+ assertEquals(5, sourceAccessor.getObject(0));
+ assertEquals(false, sourceAccessor.isNull(1));
+ assertEquals(10, sourceAccessor.getObject(1));
+ assertEquals(false, sourceAccessor.isNull(2));
+ assertEquals(15, sourceAccessor.getObject(2));
+ assertEquals(false, sourceAccessor.isNull(3));
+ assertEquals(20, sourceAccessor.getObject(3));
+ assertEquals(false, sourceAccessor.isNull(4));
+ assertEquals(25, sourceAccessor.getObject(4));
+ assertEquals(false, sourceAccessor.isNull(5));
+ assertEquals(30, sourceAccessor.getObject(5));
+ assertEquals(false, sourceAccessor.isNull(6));
+ assertEquals(35, sourceAccessor.getObject(6));
+ assertEquals(false, sourceAccessor.isNull(7));
+ assertEquals(40, sourceAccessor.getObject(7));
+ assertEquals(false, sourceAccessor.isNull(8));
+ assertEquals(45, sourceAccessor.getObject(8));
+ assertEquals(false, sourceAccessor.isNull(9));
+ assertEquals(50, sourceAccessor.getObject(9));
+
+ try(UnionVector toVector = new UnionVector(EMPTY_SCHEMA_PATH, allocator, null)) {
+
+ final TransferPair transferPair = sourceVector.makeTransferPair(toVector);
+ final UnionVector.Accessor toAccessor = toVector.getAccessor();
+
+ final int[][] transferLengths = { {0, 3},
+ {3, 1},
+ {4, 2},
+ {6, 1},
+ {7, 1},
+ {8, 2}
+ };
+
+ for (final int[] transferLength : transferLengths) {
+ final int start = transferLength[0];
+ final int length = transferLength[1];
+
+ transferPair.splitAndTransfer(start, length);
+
+ /* check the toVector output after doing the splitAndTransfer */
+ for (int i = 0; i < length; i++) {
+ assertEquals("Different data at indexes: " + (start + i) + "and " + i, sourceAccessor.getObject(start + i),
+ toAccessor.getObject(i));
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testSplitAndTransferWithMixedVectors() throws Exception {
+ try (UnionVector sourceVector = new UnionVector(EMPTY_SCHEMA_PATH, allocator, null)) {
+ final UnionVector.Mutator sourceMutator = sourceVector.getMutator();
+ final UnionVector.Accessor sourceAccessor = sourceVector.getAccessor();
+
+ sourceVector.allocateNew();
+
+ /* populate the UnionVector */
+ sourceMutator.setType(0, MinorType.INT);
+ sourceMutator.setSafe(0, newIntHolder(5));
+
+ sourceMutator.setType(1, MinorType.FLOAT4);
+ sourceMutator.setSafe(1, newFloat4Holder(5.5f));
+
+ sourceMutator.setType(2, MinorType.INT);
+ sourceMutator.setSafe(2, newIntHolder(10));
+
+ sourceMutator.setType(3, MinorType.FLOAT4);
+ sourceMutator.setSafe(3, newFloat4Holder(10.5f));
+
+ sourceMutator.setType(4, MinorType.INT);
+ sourceMutator.setSafe(4, newIntHolder(15));
+
+ sourceMutator.setType(5, MinorType.FLOAT4);
+ sourceMutator.setSafe(5, newFloat4Holder(15.5f));
+
+ sourceMutator.setType(6, MinorType.INT);
+ sourceMutator.setSafe(6, newIntHolder(20));
+
+ sourceMutator.setType(7, MinorType.FLOAT4);
+ sourceMutator.setSafe(7, newFloat4Holder(20.5f));
+
+ sourceMutator.setType(8, MinorType.INT);
+ sourceMutator.setSafe(8, newIntHolder(30));
+
+ sourceMutator.setType(9, MinorType.FLOAT4);
+ sourceMutator.setSafe(9, newFloat4Holder(30.5f));
+ sourceMutator.setValueCount(10);
+
+ /* check the vector output */
+ assertEquals(10, sourceAccessor.getValueCount());
+ assertEquals(false, sourceAccessor.isNull(0));
+ assertEquals(5, sourceAccessor.getObject(0));
+ assertEquals(false, sourceAccessor.isNull(1));
+ assertEquals(5.5f, sourceAccessor.getObject(1));
+ assertEquals(false, sourceAccessor.isNull(2));
+ assertEquals(10, sourceAccessor.getObject(2));
+ assertEquals(false, sourceAccessor.isNull(3));
+ assertEquals(10.5f, sourceAccessor.getObject(3));
+ assertEquals(false, sourceAccessor.isNull(4));
+ assertEquals(15, sourceAccessor.getObject(4));
+ assertEquals(false, sourceAccessor.isNull(5));
+ assertEquals(15.5f, sourceAccessor.getObject(5));
+ assertEquals(false, sourceAccessor.isNull(6));
+ assertEquals(20, sourceAccessor.getObject(6));
+ assertEquals(false, sourceAccessor.isNull(7));
+ assertEquals(20.5f, sourceAccessor.getObject(7));
+ assertEquals(false, sourceAccessor.isNull(8));
+ assertEquals(30, sourceAccessor.getObject(8));
+ assertEquals(false, sourceAccessor.isNull(9));
+ assertEquals(30.5f, sourceAccessor.getObject(9));
+
+ try(UnionVector toVector = new UnionVector(EMPTY_SCHEMA_PATH, allocator, null)) {
+
+ final TransferPair transferPair = sourceVector.makeTransferPair(toVector);
+ final UnionVector.Accessor toAccessor = toVector.getAccessor();
+
+ final int[][] transferLengths = { {0, 2},
+ {2, 1},
+ {3, 2},
+ {5, 3},
+ {8, 2}
+ };
+
+ for (final int[] transferLength : transferLengths) {
+ final int start = transferLength[0];
+ final int length = transferLength[1];
+
+ transferPair.splitAndTransfer(start, length);
+
+ /* check the toVector output after doing the splitAndTransfer */
+ for (int i = 0; i < length; i++) {
+ assertEquals("Different values at index: " + i, sourceAccessor.getObject(start + i), toAccessor.getObject(i));
+ }
+ }
+ }
+ }
+ }
+
private static NullableIntHolder newIntHolder(int value) {
final NullableIntHolder holder = new NullableIntHolder();
holder.isSet = 1;
@@ -130,4 +304,11 @@ public class TestUnionVector {
holder.value = value ? 1 : 0;
return holder;
}
+
+ private static NullableFloat4Holder newFloat4Holder(float value) {
+ final NullableFloat4Holder holder = new NullableFloat4Holder();
+ holder.isSet = 1;
+ holder.value = value;
+ return holder;
+ }
}