Class AbstractDelegatingCompoundBlock<T extends Block>

java.lang.Object
org.elasticsearch.compute.data.AbstractNonThreadSafeRefCounted
org.elasticsearch.compute.data.AbstractDelegatingCompoundBlock<T>
All Implemented Interfaces:
Closeable, AutoCloseable, org.apache.lucene.util.Accountable, Writeable, Block, RefCounted, Releasable, BlockLoader.Block
Direct Known Subclasses:
ExponentialHistogramArrayBlock, TDigestArrayBlock

public abstract class AbstractDelegatingCompoundBlock<T extends Block> extends AbstractNonThreadSafeRefCounted implements Block
Abstract base class for composite block types that are implemented by delegating to several concrete sub-blocks. Supports multi-valued fields via firstValueIndexes.

The key insight is that value indices in the composite block correspond to positions in the sub-blocks. Sub-blocks are always single-valued per position. For example, a multi-valued exponential histogram block with three histograms at one position would have three corresponding positions in each sub-block.

Null handling is delegated to the first sub-block returned by getSubBlocks() which must be non-null for non-null composite values.

  • Constructor Details

    • AbstractDelegatingCompoundBlock

      protected AbstractDelegatingCompoundBlock(int positionCount, @Nullable int[] firstValueIndexes)
      Parameters:
      positionCount - the number of positions in this block
      firstValueIndexes - maps positions to ranges of value indices in sub-blocks. Null if single-valued.
  • Method Details

    • getSubBlocks

      protected abstract List<Block> getSubBlocks()
      Returns:
      a list of the sub-blocks composing this compound block. The first block must be non-null for non-null composite values (used for null detection). The order should match the order expected by buildFromSubBlocks(List, int, int[]).
    • buildFromSubBlocks

      protected abstract T buildFromSubBlocks(List<Block> subBlocks, int positionCount, @Nullable int[] firstValueIndexes)
      Construct a new instance of the block, based on the given list of sub-blocks.
      Parameters:
      subBlocks - List of sub-blocks, in the same order as getSubBlocks()
      positionCount - the number of positions in the new block
      firstValueIndexes - the firstValueIndexes array for the new block (may be null for single-valued)
      Returns:
      a new instance based on the given blocks.
    • getPositionCount

      public final int getPositionCount()
      Description copied from interface: Block
      Returns the number of positions (rows) in this block. See class javadoc for the usual way to iterate these positions.
      Specified by:
      getPositionCount in interface Block
      Returns:
      the number of positions (rows) in this block
    • getFirstValueIndex

      public final int getFirstValueIndex(int position)
      Description copied from interface: Block
      Returns the index of the first value for the given position. See class javadoc for the usual way to iterate these positions.

      For densely packed data this will return its parameter unchanged. For fields with null values or multivalued fields, this will shift. Here's an example:

      
           0   <---+
           1       | Values at first position
           2       |
           3   <---+
           5   <---- Value at second position
           6   <---+ Values at third position
           7   <---+
       

      This represents three rows. The first has the value [0, 1, 2, 3]. The second has the value 5. The third has the value [6, 7]. This method will return 0 for the first position, 4 for the second, and 5 for the third.

      Specified by:
      getFirstValueIndex in interface Block
      Returns:
      the index of the first value for the given position
    • getValueCount

      public final int getValueCount(int position)
      Description copied from interface: Block
      Returns the number of values for the given position. See class javadoc for the usual way to iterate these positions.

      For densely packed data this will return 1. For nulls this will return 0. For multivalued fields, this will return the number of values. Here's an example:

      
           0   <---+
           1       | Values at first position
           2       |
           3   <---+
           5   <---- Value at second position
           6   <---+ Values at third position
           7   <---+
       

      This represents three rows. The first has the value [0, 1, 2, 3]. The second has the value 5. The third has the value [6, 7]. This method will return 4 for the first position, 1 for the second, and 2 for the third.

      Specified by:
      getValueCount in interface Block
      Returns:
      the number of values for the given position
    • getTotalValueCount

      public final int getTotalValueCount()
      Description copied from interface: Block
      Returns the total number of values in this block not counting nulls. This powers the COUNT aggregation and is used to report the number of fields loaded by ESQL.
      Specified by:
      getTotalValueCount in interface Block
      Returns:
      the total number of values in this block not counting nulls
    • isNull

      public final boolean isNull(int position)
      Specified by:
      isNull in interface Block
      Parameters:
      position - the position
      Returns:
      true if the value stored at the given position is null, false otherwise
    • mayHaveNulls

      public final boolean mayHaveNulls()
      Specified by:
      mayHaveNulls in interface Block
      Returns:
      true if some values might be null. False, if all values are guaranteed to be not null.
    • areAllValuesNull

      public final boolean areAllValuesNull()
      Specified by:
      areAllValuesNull in interface Block
      Returns:
      true if all values in this block are guaranteed to be null.
    • mayHaveMultivaluedFields

      public final boolean mayHaveMultivaluedFields()
      Description copied from interface: Block
      Can this block have multivalued fields? Blocks that return false will never return more than one from Block.getValueCount(int). This may return true for Blocks that do not have multivalued fields, but it will always answer quickly.
      Specified by:
      mayHaveMultivaluedFields in interface Block
    • doesHaveMultivaluedFields

      public boolean doesHaveMultivaluedFields()
      Description copied from interface: Block
      Does this block have multivalued fields? Unlike Block.mayHaveMultivaluedFields() this will never return a false positive. In other words, if this returns true then there are positions for which Block.getValueCount(int) will return more than 1. This will answer quickly if it can but may have to check all positions.
      Specified by:
      doesHaveMultivaluedFields in interface Block
    • mvOrdering

      public final Block.MvOrdering mvOrdering()
      Description copied from interface: Block
      How are multivalued fields ordered?
      Specified by:
      mvOrdering in interface Block
    • layoutEquals

      protected final boolean layoutEquals(AbstractDelegatingCompoundBlock<?> that)
      Compares positionCount and firstValueIndexes with another block for equality.
    • assertInvariants

      protected boolean assertInvariants()
    • allowPassingToDifferentDriver

      public void allowPassingToDifferentDriver()
      Description copied from interface: Block
      Before passing a Block to another Driver, it is necessary to switch the owning block factory to its parent, which is associated with the global circuit breaker. This ensures that when the new driver releases this Block, it returns memory directly to the parent block factory instead of the local block factory of this Block. This is important because the local block factory is not thread safe and doesn't support simultaneous access by more than one thread.
      Specified by:
      allowPassingToDifferentDriver in interface Block
    • blockFactory

      public BlockFactory blockFactory()
      Description copied from interface: Block
      The block factory associated with this block.
      Specified by:
      blockFactory in interface Block
    • valueMaxByteSize

      public int valueMaxByteSize()
      Description copied from interface: Block
      Returns the maximum byte size of any single value in this block. For fixed-width types this is a constant. For BytesRef, this scans all values quickly.
      Specified by:
      valueMaxByteSize in interface Block
      Returns:
      the maximum byte size of any single value in this block
    • ramBytesUsed

      public long ramBytesUsed()
      Specified by:
      ramBytesUsed in interface org.apache.lucene.util.Accountable
    • closeInternal

      protected void closeInternal()
      Description copied from class: AbstractNonThreadSafeRefCounted
      This is called when the number of references reaches zero. This is where resources should be released (adjusting circuit breakers if needed).
      Specified by:
      closeInternal in class AbstractNonThreadSafeRefCounted
    • filter

      public T filter(boolean mayContainDuplicates, int[] positions, int offset, int length)
      Description copied from interface: Block
      Creates a new block that only exposes the positions provided.
      Specified by:
      filter in interface Block
      Parameters:
      mayContainDuplicates - may the positions array contain duplicate positions?
      positions - the positions to retain
      offset - the start index in the positions array
      length - the number of positions to use from the array
      Returns:
      a filtered block
    • slice

      public T slice(int beginInclusive, int endExclusive)
      Description copied from interface: Block
      Return a subset of this Block from position beginInclusive to position endExclusive. This may return the same instance if the range covers all positions, but if it does it will RefCounted.incRef() it.

      NOTE: Implementations will not try to optimize zero length slices as we expect them to be rare.

      Specified by:
      slice in interface Block
    • keepMask

      public T keepMask(BooleanVector mask)
      Description copied from interface: Block
      Build a Block with the same values as this Block, but replacing all values for which mask.getBooleanValue(position) returns false with null. The mask vector must be at least as long as this Block.
      Specified by:
      keepMask in interface Block
    • deepCopy

      public T deepCopy(BlockFactory blockFactory)
      Description copied from interface: Block
      Make a deep copy of this Block using the provided BlockFactory, likely copying all data.
      Specified by:
      deepCopy in interface Block
    • writeMultiValueMetadata

      protected void writeMultiValueMetadata(StreamOutput out) throws IOException
      Writes the multivalue metadata (positionCount, firstValueIndexes) to a stream.
      Throws:
      IOException
    • readFrom

      protected static <T extends Block> T readFrom(BlockStreamInput in, AbstractDelegatingCompoundBlock.Deserializer<T> deserializer) throws IOException
      Throws:
      IOException