2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 package org
.apache
.arrow
.vector
;
20 import static org
.apache
.arrow
.memory
.util
.LargeMemoryUtil
.capAtMaxInt
;
22 import java
.nio
.ByteBuffer
;
23 import java
.util
.ArrayList
;
24 import java
.util
.Collections
;
25 import java
.util
.List
;
27 import org
.apache
.arrow
.memory
.ArrowBuf
;
28 import org
.apache
.arrow
.memory
.BufferAllocator
;
29 import org
.apache
.arrow
.memory
.util
.ArrowBufPointer
;
30 import org
.apache
.arrow
.memory
.util
.ByteFunctionHelpers
;
31 import org
.apache
.arrow
.memory
.util
.hash
.ArrowBufHasher
;
32 import org
.apache
.arrow
.util
.Preconditions
;
33 import org
.apache
.arrow
.vector
.compare
.VectorVisitor
;
34 import org
.apache
.arrow
.vector
.ipc
.message
.ArrowFieldNode
;
35 import org
.apache
.arrow
.vector
.types
.pojo
.Field
;
36 import org
.apache
.arrow
.vector
.util
.CallBack
;
37 import org
.apache
.arrow
.vector
.util
.OversizedAllocationException
;
38 import org
.apache
.arrow
.vector
.util
.TransferPair
;
40 import io
.netty
.util
.internal
.PlatformDependent
;
43 * BaseFixedWidthVector provides an abstract interface for
44 * implementing vectors of fixed width values. The vectors are nullable
45 * implying that zero or more elements in the vector could be NULL.
47 public abstract class BaseFixedWidthVector
extends BaseValueVector
48 implements FixedWidthVector
, FieldVector
, VectorDefinitionSetter
{
49 private final int typeWidth
;
51 protected int lastValueCapacity
;
52 protected int actualValueCapacity
;
54 protected final Field field
;
55 private int allocationMonitor
;
56 protected ArrowBuf validityBuffer
;
57 protected ArrowBuf valueBuffer
;
58 protected int valueCount
;
61 * Constructs a new instance.
63 * @param field field materialized by this vector
64 * @param allocator The allocator to use for allocating memory for the vector.
65 * @param typeWidth The width in bytes of the type.
67 public BaseFixedWidthVector(Field field
, final BufferAllocator allocator
, final int typeWidth
) {
69 this.typeWidth
= typeWidth
;
72 allocationMonitor
= 0;
73 validityBuffer
= allocator
.getEmpty();
74 valueBuffer
= allocator
.getEmpty();
75 lastValueCapacity
= INITIAL_VALUE_ALLOCATION
;
76 refreshValueCapacity();
80 public int getTypeWidth() {
85 public String
getName() {
86 return field
.getName();
90 * see if getNullCount() can be made faster -- O(1)
94 * Once the entire hierarchy has been refactored, move common functions
95 * like getNullCount(), splitAndTransferValidityBuffer to top level
96 * base class BaseValueVector.
98 * Along with this, some class members (validityBuffer) can also be
99 * abstracted out to top level base class.
101 * Right now BaseValueVector is the top level base class for other
102 * vector types in ValueVector hierarchy (non-nullable) and those
103 * vectors have not yet been refactored/removed so moving things to
104 * the top class as of now is not a good idea.
108 * Get the memory address of buffer that manages the validity
109 * (NULL or NON-NULL nature) of elements in the vector.
110 * @return starting address of the buffer
113 public long getValidityBufferAddress() {
114 return (validityBuffer
.memoryAddress());
118 * Get the memory address of buffer that stores the data for elements
120 * @return starting address of the buffer
123 public long getDataBufferAddress() {
124 return (valueBuffer
.memoryAddress());
128 * Get the memory address of buffer that stores the offsets for elements
129 * in the vector. This operation is not supported for fixed-width vectors.
130 * @return starting address of the buffer
131 * @throws UnsupportedOperationException for fixed width vectors
134 public long getOffsetBufferAddress() {
135 throw new UnsupportedOperationException("not supported for fixed-width vectors");
139 * Get buffer that manages the validity (NULL or NON-NULL nature) of
140 * elements in the vector. Consider it as a buffer for internal bit vector
145 public ArrowBuf
getValidityBuffer() {
146 return validityBuffer
;
150 * Get the buffer that stores the data for elements in the vector.
154 public ArrowBuf
getDataBuffer() {
159 * buffer that stores the offsets for elements
160 * in the vector. This operation is not supported for fixed-width vectors.
162 * @throws UnsupportedOperationException for fixed width vectors
165 public ArrowBuf
getOffsetBuffer() {
166 throw new UnsupportedOperationException("not supported for fixed-width vectors");
170 * Sets the desired value capacity for the vector. This function doesn't
171 * allocate any memory for the vector.
172 * @param valueCount desired number of elements in the vector
175 public void setInitialCapacity(int valueCount
) {
176 computeAndCheckBufferSize(valueCount
);
177 lastValueCapacity
= valueCount
;
181 * Get the current value capacity for the vector.
183 * @return number of elements that vector can hold.
186 public int getValueCapacity() {
187 return actualValueCapacity
;
191 * Call this if you change the capacity of valueBuffer or validityBuffer.
193 protected void refreshValueCapacity() {
194 actualValueCapacity
= Math
.min(getValueBufferValueCapacity(), getValidityBufferValueCapacity());
197 protected int getValueBufferValueCapacity() {
198 return capAtMaxInt(valueBuffer
.capacity() / typeWidth
);
201 protected int getValidityBufferValueCapacity() {
202 return capAtMaxInt(validityBuffer
.capacity() * 8);
206 * zero out the vector and the data in associated buffers.
209 public void zeroVector() {
210 initValidityBuffer();
214 /* zero out the validity buffer */
215 private void initValidityBuffer() {
216 validityBuffer
.setZero(0, validityBuffer
.capacity());
219 /* zero out the data buffer */
220 private void initValueBuffer() {
221 valueBuffer
.setZero(0, valueBuffer
.capacity());
225 * Reset the vector to initial state. Same as {@link #zeroVector()}.
226 * Note that this method doesn't release any memory.
229 public void reset() {
235 * Close the vector and release the associated buffers.
238 public void close() {
243 * Same as {@link #close()}.
246 public void clear() {
248 validityBuffer
= releaseBuffer(validityBuffer
);
249 valueBuffer
= releaseBuffer(valueBuffer
);
250 refreshValueCapacity();
253 /* used to step down the memory allocation */
254 protected void incrementAllocationMonitor() {
255 if (allocationMonitor
< 0) {
256 allocationMonitor
= 0;
261 /* used to step up the memory allocation */
262 protected void decrementAllocationMonitor() {
263 if (allocationMonitor
> 0) {
264 allocationMonitor
= 0;
270 * Same as {@link #allocateNewSafe()}.
273 public void allocateNew() {
274 allocateNew(lastValueCapacity
);
278 * Allocate memory for the vector. We internally use a default value count
279 * of 4096 to allocate memory for at least these many elements in the
280 * vector. See {@link #allocateNew(int)} for allocating memory for specific
281 * number of elements in the vector.
283 * @return false if memory allocation fails, true otherwise.
286 public boolean allocateNewSafe() {
288 allocateNew(lastValueCapacity
);
290 } catch (Exception e
) {
296 * Allocate memory for the vector to support storing at least the provided number of
297 * elements in the vector. This method must be called prior to using the ValueVector.
299 * @param valueCount the desired number of elements in the vector
300 * @throws org.apache.arrow.memory.OutOfMemoryException on error
302 public void allocateNew(int valueCount
) {
303 computeAndCheckBufferSize(valueCount
);
305 /* we are doing a new allocation -- release the current buffers */
309 allocateBytes(valueCount
);
310 } catch (Exception e
) {
317 * Compute the buffer size required for 'valueCount', and check if it's within bounds.
319 private long computeAndCheckBufferSize(int valueCount
) {
320 final long size
= computeCombinedBufferSize(valueCount
, typeWidth
);
321 if (size
> MAX_ALLOCATION_SIZE
) {
322 throw new OversizedAllocationException("Memory required for vector capacity " +
324 " is (" + size
+ "), which is more than max allowed (" + MAX_ALLOCATION_SIZE
+ ")");
330 * Actual memory allocation is done by this function. All the calculations
331 * and knowledge about what size to allocate is upto the callers of this
333 * Callers appropriately handle errors if memory allocation fails here.
334 * Callers should also take care of determining that desired size is
335 * within the bounds of max allocation allowed and any other error
338 private void allocateBytes(int valueCount
) {
339 DataAndValidityBuffers buffers
= allocFixedDataAndValidityBufs(valueCount
, typeWidth
);
340 valueBuffer
= buffers
.getDataBuf();
341 validityBuffer
= buffers
.getValidityBuf();
344 refreshValueCapacity();
345 lastValueCapacity
= getValueCapacity();
349 * During splitAndTransfer, if we splitting from a random position within a byte,
350 * we can't just slice the source buffer so we have to explicitly allocate the
351 * validityBuffer of the target vector. This is unlike the databuffer which we can
352 * always slice for the target vector.
354 private void allocateValidityBuffer(final int validityBufferSize
) {
355 validityBuffer
= allocator
.buffer(validityBufferSize
);
356 validityBuffer
.readerIndex(0);
357 refreshValueCapacity();
361 * Get the potential buffer size for a particular number of records.
362 * @param count desired number of elements in the vector
363 * @return estimated size of underlying buffers if the vector holds
364 * a given number of elements
367 public int getBufferSizeFor(final int count
) {
371 return (count
* typeWidth
) + getValidityBufferSizeFromCount(count
);
375 * Get the size (number of bytes) of underlying buffers used by this
377 * @return size of underlying buffers.
380 public int getBufferSize() {
381 if (valueCount
== 0) {
384 return (valueCount
* typeWidth
) + getValidityBufferSizeFromCount(valueCount
);
388 * Get information about how this field is materialized.
389 * @return the field corresponding to this vector
392 public Field
getField() {
397 * Return the underlying buffers associated with this vector. Note that this doesn't
398 * impact the reference counts for this buffer so it only should be used for in-context
399 * access. Also note that this buffer changes regularly thus
400 * external classes shouldn't hold a reference to it (unless they change it).
402 * @param clear Whether to clear vector before returning; the buffers will still be refcounted
403 * but the returned array will be the only reference to them
404 * @return The underlying {@link ArrowBuf buffers} that is used by this
408 public ArrowBuf
[] getBuffers(boolean clear
) {
409 final ArrowBuf
[] buffers
;
410 setReaderAndWriterIndex();
411 if (getBufferSize() == 0) {
412 buffers
= new ArrowBuf
[0];
414 buffers
= new ArrowBuf
[2];
415 buffers
[0] = validityBuffer
;
416 buffers
[1] = valueBuffer
;
419 for (final ArrowBuf buffer
: buffers
) {
420 buffer
.getReferenceManager().retain(1);
428 * Resize the vector to increase the capacity. The internal behavior is to
429 * double the current value capacity.
432 public void reAlloc() {
433 int targetValueCount
= getValueCapacity() * 2;
434 if (targetValueCount
== 0) {
435 if (lastValueCapacity
> 0) {
436 targetValueCount
= lastValueCapacity
;
438 targetValueCount
= INITIAL_VALUE_ALLOCATION
* 2;
441 computeAndCheckBufferSize(targetValueCount
);
443 DataAndValidityBuffers buffers
= allocFixedDataAndValidityBufs(targetValueCount
, typeWidth
);
444 final ArrowBuf newValueBuffer
= buffers
.getDataBuf();
445 newValueBuffer
.setBytes(0, valueBuffer
, 0, valueBuffer
.capacity());
446 newValueBuffer
.setZero(valueBuffer
.capacity(), newValueBuffer
.capacity() - valueBuffer
.capacity());
447 valueBuffer
.getReferenceManager().release();
448 valueBuffer
= newValueBuffer
;
450 final ArrowBuf newValidityBuffer
= buffers
.getValidityBuf();
451 newValidityBuffer
.setBytes(0, validityBuffer
, 0, validityBuffer
.capacity());
452 newValidityBuffer
.setZero(validityBuffer
.capacity(), newValidityBuffer
.capacity() - validityBuffer
.capacity());
453 validityBuffer
.getReferenceManager().release();
454 validityBuffer
= newValidityBuffer
;
456 refreshValueCapacity();
457 lastValueCapacity
= getValueCapacity();
461 * Get the inner vectors.
463 * @deprecated This API will be removed as the current implementations no longer support inner vectors.
465 * @return the inner vectors for this field as defined by the TypeLayout
469 public List
<BufferBacked
> getFieldInnerVectors() {
470 throw new UnsupportedOperationException("There are no inner vectors. Use getFieldBuffers");
474 * Initialize the children in schema for this Field. This operation is a
475 * NO-OP for scalar types since they don't have any children.
476 * @param children the schema
477 * @throws IllegalArgumentException if children is a non-empty list for scalar types.
480 public void initializeChildrenFromFields(List
<Field
> children
) {
481 if (!children
.isEmpty()) {
482 throw new IllegalArgumentException("primitive type vector can not have children");
487 * Get the inner child vectors.
488 * @return list of child vectors for complex types, empty list for scalar vector types
491 public List
<FieldVector
> getChildrenFromFields() {
492 return Collections
.emptyList();
496 * Load the buffers of this vector with provided source buffers.
497 * The caller manages the source buffers and populates them before invoking
499 * @param fieldNode the fieldNode indicating the value count
500 * @param ownBuffers the buffers for this Field (own buffers only, children not included)
503 public void loadFieldBuffers(ArrowFieldNode fieldNode
, List
<ArrowBuf
> ownBuffers
) {
504 if (ownBuffers
.size() != 2) {
505 throw new IllegalArgumentException("Illegal buffer count, expected " + 2 + ", got: " + ownBuffers
.size());
508 ArrowBuf bitBuffer
= ownBuffers
.get(0);
509 ArrowBuf dataBuffer
= ownBuffers
.get(1);
511 validityBuffer
.getReferenceManager().release();
512 validityBuffer
= BitVectorHelper
.loadValidityBuffer(fieldNode
, bitBuffer
, allocator
);
513 valueBuffer
.getReferenceManager().release();
514 valueBuffer
= dataBuffer
.getReferenceManager().retain(dataBuffer
, allocator
);
515 refreshValueCapacity();
517 valueCount
= fieldNode
.getLength();
521 * Get the buffers belonging to this vector.
523 * @return the inner buffers.
525 public List
<ArrowBuf
> getFieldBuffers() {
526 List
<ArrowBuf
> result
= new ArrayList
<>(2);
527 setReaderAndWriterIndex();
528 result
.add(validityBuffer
);
529 result
.add(valueBuffer
);
535 * Set the reader and writer indexes for the inner buffers.
537 private void setReaderAndWriterIndex() {
538 validityBuffer
.readerIndex(0);
539 valueBuffer
.readerIndex(0);
540 if (valueCount
== 0) {
541 validityBuffer
.writerIndex(0);
542 valueBuffer
.writerIndex(0);
544 validityBuffer
.writerIndex(getValidityBufferSizeFromCount(valueCount
));
545 if (typeWidth
== 0) {
546 /* specialized handling for BitVector */
547 valueBuffer
.writerIndex(getValidityBufferSizeFromCount(valueCount
));
549 valueBuffer
.writerIndex((long) valueCount
* typeWidth
);
555 * Construct a transfer pair of this vector and another vector of same type.
556 * @param ref name of the target vector
557 * @param allocator allocator for the target vector
558 * @param callBack not used
559 * @return TransferPair
562 public TransferPair
getTransferPair(String ref
, BufferAllocator allocator
, CallBack callBack
) {
563 return getTransferPair(ref
, allocator
);
567 * Construct a transfer pair of this vector and another vector of same type.
568 * @param allocator allocator for the target vector
569 * @return TransferPair
572 public TransferPair
getTransferPair(BufferAllocator allocator
) {
573 return getTransferPair(getName(), allocator
);
577 * Construct a transfer pair of this vector and another vector of same type.
578 * @param ref name of the target vector
579 * @param allocator allocator for the target vector
580 * @return TransferPair
582 public abstract TransferPair
getTransferPair(String ref
, BufferAllocator allocator
);
585 * Transfer this vector'data to another vector. The memory associated
586 * with this vector is transferred to the allocator of target vector
587 * for accounting and management purposes.
588 * @param target destination vector for transfer
590 public void transferTo(BaseFixedWidthVector target
) {
591 compareTypes(target
, "transferTo");
593 target
.validityBuffer
= transferBuffer(validityBuffer
, target
.allocator
);
594 target
.valueBuffer
= transferBuffer(valueBuffer
, target
.allocator
);
595 target
.valueCount
= valueCount
;
596 target
.refreshValueCapacity();
601 * Slice this vector at desired index and length and transfer the
602 * corresponding data to the target vector.
603 * @param startIndex start position of the split in source vector.
604 * @param length length of the split.
605 * @param target destination vector
607 public void splitAndTransferTo(int startIndex
, int length
,
608 BaseFixedWidthVector target
) {
609 Preconditions
.checkArgument(startIndex
>= 0 && length
>= 0 && startIndex
+ length
<= valueCount
,
610 "Invalid parameters startIndex: %s, length: %s for valueCount: %s", startIndex
, length
, valueCount
);
611 compareTypes(target
, "splitAndTransferTo");
613 splitAndTransferValidityBuffer(startIndex
, length
, target
);
614 splitAndTransferValueBuffer(startIndex
, length
, target
);
615 target
.setValueCount(length
);
619 * Data buffer can always be split and transferred using slicing.
621 private void splitAndTransferValueBuffer(int startIndex
, int length
,
622 BaseFixedWidthVector target
) {
623 final int startPoint
= startIndex
* typeWidth
;
624 final int sliceLength
= length
* typeWidth
;
625 final ArrowBuf slicedBuffer
= valueBuffer
.slice(startPoint
, sliceLength
);
626 target
.valueBuffer
= transferBuffer(slicedBuffer
, target
.allocator
);
627 target
.refreshValueCapacity();
631 * Validity buffer has multiple cases of split and transfer depending on
632 * the starting position of the source index.
634 private void splitAndTransferValidityBuffer(int startIndex
, int length
,
635 BaseFixedWidthVector target
) {
636 int firstByteSource
= BitVectorHelper
.byteIndex(startIndex
);
637 int lastByteSource
= BitVectorHelper
.byteIndex(valueCount
- 1);
638 int byteSizeTarget
= getValidityBufferSizeFromCount(length
);
639 int offset
= startIndex
% 8;
644 if (target
.validityBuffer
!= null) {
645 target
.validityBuffer
.getReferenceManager().release();
647 target
.validityBuffer
= validityBuffer
.slice(firstByteSource
, byteSizeTarget
);
648 target
.validityBuffer
.getReferenceManager().retain(1);
649 target
.refreshValueCapacity();
652 * When the first bit starts from the middle of a byte (offset != 0),
653 * copy data from src BitVector.
654 * Each byte in the target is composed by a part in i-th byte,
655 * another part in (i+1)-th byte.
657 target
.allocateValidityBuffer(byteSizeTarget
);
659 for (int i
= 0; i
< byteSizeTarget
- 1; i
++) {
660 byte b1
= BitVectorHelper
.getBitsFromCurrentByte(this.validityBuffer
,
661 firstByteSource
+ i
, offset
);
662 byte b2
= BitVectorHelper
.getBitsFromNextByte(this.validityBuffer
,
663 firstByteSource
+ i
+ 1, offset
);
665 target
.validityBuffer
.setByte(i
, (b1
+ b2
));
668 /* Copying the last piece is done in the following manner:
669 * if the source vector has 1 or more bytes remaining, we copy
670 * the last piece as a byte formed by shifting data
671 * from the current byte and the next byte.
673 * if the source vector has no more bytes remaining
674 * (we are at the last byte), we copy the last piece as a byte
675 * by shifting data from the current byte.
677 if ((firstByteSource
+ byteSizeTarget
- 1) < lastByteSource
) {
678 byte b1
= BitVectorHelper
.getBitsFromCurrentByte(this.validityBuffer
,
679 firstByteSource
+ byteSizeTarget
- 1, offset
);
680 byte b2
= BitVectorHelper
.getBitsFromNextByte(this.validityBuffer
,
681 firstByteSource
+ byteSizeTarget
, offset
);
683 target
.validityBuffer
.setByte(byteSizeTarget
- 1, b1
+ b2
);
685 byte b1
= BitVectorHelper
.getBitsFromCurrentByte(this.validityBuffer
,
686 firstByteSource
+ byteSizeTarget
- 1, offset
);
687 target
.validityBuffer
.setByte(byteSizeTarget
- 1, b1
);
694 /*----------------------------------------------------------------*
696 | common getters and setters |
698 *----------------------------------------------------------------*/
702 * Get the number of elements that are null in the vector.
704 * @return the number of null elements.
707 public int getNullCount() {
708 return BitVectorHelper
.getNullCount(validityBuffer
, valueCount
);
712 * Get the value count of vector. This will always be zero unless
713 * {@link #setValueCount(int)} has been called prior to calling this.
715 * @return valueCount for the vector
718 public int getValueCount() {
723 * Set value count for the vector.
725 * @param valueCount value count to set
728 public void setValueCount(int valueCount
) {
729 this.valueCount
= valueCount
;
730 final int currentValueCapacity
= getValueCapacity();
731 while (valueCount
> getValueCapacity()) {
735 * We are trying to understand the pattern of memory allocation.
736 * If initially, the user did vector.allocateNew(), we would have
737 * allocated memory of default size (4096 * type width).
738 * Later on user invokes setValueCount(count).
740 * If the existing value capacity is twice as large as the
741 * valueCount, we know that we over-provisioned memory in the
742 * first place when default memory allocation was done because user
743 * really needs a much less value count in the vector.
745 * We record this by bumping up the allocationMonitor. If this pattern
746 * happens for certain number of times and allocationMonitor
747 * reaches the threshold (internal hardcoded) value, subsequent
748 * call to allocateNew() will take care of stepping down the
749 * default memory allocation size.
751 * Another case would be under-provisioning the initial memory and
752 * thus going through a lot of realloc(). Here the goal is to
753 * see if we can minimize the number of reallocations. Again the
754 * state is recorded in allocationMonitor by decrementing it
755 * (negative value). If a threshold is hit, realloc will try to
756 * allocate more memory in order to possibly avoid a future realloc.
757 * This case is also applicable to setSafe() methods which can trigger
758 * a realloc() and thus we record the state there as well.
760 if (valueCount
> 0) {
761 if (currentValueCapacity
>= (valueCount
* 2)) {
762 incrementAllocationMonitor();
763 } else if (currentValueCapacity
<= (valueCount
/ 2)) {
764 decrementAllocationMonitor();
767 setReaderAndWriterIndex();
771 * Check if the given index is within the current value capacity
774 * @param index position to check
775 * @return true if index is within the current value capacity
777 public boolean isSafe(int index
) {
778 return index
< getValueCapacity();
782 * Check if element at given index is null.
784 * @param index position of element
785 * @return true if element at given index is null, false otherwise
788 public boolean isNull(int index
) {
789 return (isSet(index
) == 0);
793 * Same as {@link #isNull(int)}.
795 * @param index position of element
796 * @return 1 if element at given index is not null, 0 otherwise
798 public int isSet(int index
) {
799 final int byteIndex
= index
>> 3;
800 final byte b
= validityBuffer
.getByte(byteIndex
);
801 final int bitIndex
= index
& 7;
802 return (b
>> bitIndex
) & 0x01;
806 * Mark the particular position in the vector as non-null.
808 * @param index position of the element.
811 public void setIndexDefined(int index
) {
813 BitVectorHelper
.setBit(validityBuffer
, index
);
816 public void set(int index
, byte[] value
, int start
, int length
) {
817 throw new UnsupportedOperationException();
820 public void setSafe(int index
, byte[] value
, int start
, int length
) {
821 throw new UnsupportedOperationException();
824 public void set(int index
, ByteBuffer value
, int start
, int length
) {
825 throw new UnsupportedOperationException();
828 public void setSafe(int index
, ByteBuffer value
, int start
, int length
) {
829 throw new UnsupportedOperationException();
833 /*----------------------------------------------------------------*
835 | helper methods for setters |
837 *----------------------------------------------------------------*/
840 protected void handleSafe(int index
) {
841 while (index
>= getValueCapacity()) {
842 decrementAllocationMonitor();
848 * Copy a cell value from a particular index in source vector to a particular
849 * position in this vector. The source vector should be of the same type as this one.
851 * @param fromIndex position to copy from in source vector
852 * @param thisIndex position to copy to in this vector
853 * @param from source vector
856 public void copyFrom(int fromIndex
, int thisIndex
, ValueVector from
) {
857 Preconditions
.checkArgument(this.getMinorType() == from
.getMinorType());
858 if (from
.isNull(fromIndex
)) {
859 BitVectorHelper
.unsetBit(this.getValidityBuffer(), thisIndex
);
861 BitVectorHelper
.setBit(this.getValidityBuffer(), thisIndex
);
862 PlatformDependent
.copyMemory(from
.getDataBuffer().memoryAddress() + (long) fromIndex
* typeWidth
,
863 this.getDataBuffer().memoryAddress() + (long) thisIndex
* typeWidth
, typeWidth
);
868 * Same as {@link #copyFrom(int, int, ValueVector)} except that
869 * it handles the case when the capacity of the vector needs to be expanded
872 * @param fromIndex position to copy from in source vector
873 * @param thisIndex position to copy to in this vector
874 * @param from source vector
877 public void copyFromSafe(int fromIndex
, int thisIndex
, ValueVector from
) {
878 Preconditions
.checkArgument(this.getMinorType() == from
.getMinorType());
879 handleSafe(thisIndex
);
880 copyFrom(fromIndex
, thisIndex
, from
);
884 * Set the element at the given index to null.
886 * @param index position of element
888 public void setNull(int index
) {
890 // not really needed to set the bit to 0 as long as
891 // the buffer always starts from 0.
892 BitVectorHelper
.unsetBit(validityBuffer
, index
);
896 public ArrowBufPointer
getDataPointer(int index
) {
897 return getDataPointer(index
, new ArrowBufPointer());
901 public ArrowBufPointer
getDataPointer(int index
, ArrowBufPointer reuse
) {
903 reuse
.set(null, 0, 0);
905 reuse
.set(valueBuffer
, (long) index
* typeWidth
, typeWidth
);
911 public int hashCode(int index
) {
912 return hashCode(index
, null);
916 public int hashCode(int index
, ArrowBufHasher hasher
) {
918 return ArrowBufPointer
.NULL_HASH_CODE
;
920 long start
= (long) typeWidth
* index
;
921 long end
= (long) typeWidth
* (index
+ 1);
922 return ByteFunctionHelpers
.hash(hasher
, this.getDataBuffer(), start
, end
);
926 public <OUT
, IN
> OUT
accept(VectorVisitor
<OUT
, IN
> visitor
, IN value
) {
927 return visitor
.visit(this, value
);