All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.elasticsearch.compute.aggregation.blockhash.BytesRefLongBlockHash Maven / Gradle / Ivy

/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0; you may not use this file except in compliance with the Elastic License
 * 2.0.
 */

package org.elasticsearch.compute.aggregation.blockhash;

import org.apache.lucene.util.BytesRef;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.common.util.BitArray;
import org.elasticsearch.common.util.LongLongHash;
import org.elasticsearch.compute.aggregation.GroupingAggregatorFunction;
import org.elasticsearch.compute.aggregation.SeenGroupIds;
import org.elasticsearch.compute.data.Block;
import org.elasticsearch.compute.data.BlockFactory;
import org.elasticsearch.compute.data.BytesRefBlock;
import org.elasticsearch.compute.data.BytesRefVector;
import org.elasticsearch.compute.data.IntBlock;
import org.elasticsearch.compute.data.IntVector;
import org.elasticsearch.compute.data.LongBlock;
import org.elasticsearch.compute.data.LongVector;
import org.elasticsearch.compute.data.Page;
import org.elasticsearch.compute.operator.mvdedupe.IntLongBlockAdd;
import org.elasticsearch.core.ReleasableIterator;
import org.elasticsearch.core.Releasables;

/**
 * Maps a {@link LongBlock} column paired with a {@link BytesRefBlock} column to group ids.
 */
final class BytesRefLongBlockHash extends BlockHash {
    private final int bytesChannel;
    private final int longsChannel;
    private final boolean reverseOutput;
    private final int emitBatchSize;
    private final BytesRefBlockHash bytesHash;
    private final LongLongHash finalHash;

    BytesRefLongBlockHash(BlockFactory blockFactory, int bytesChannel, int longsChannel, boolean reverseOutput, int emitBatchSize) {
        super(blockFactory);
        this.bytesChannel = bytesChannel;
        this.longsChannel = longsChannel;
        this.reverseOutput = reverseOutput;
        this.emitBatchSize = emitBatchSize;

        boolean success = false;
        BytesRefBlockHash bytesHash = null;
        try {
            bytesHash = new BytesRefBlockHash(bytesChannel, blockFactory);
            this.bytesHash = bytesHash;
            this.finalHash = new LongLongHash(1, blockFactory.bigArrays());
            success = true;
        } finally {
            if (success == false) {
                Releasables.close(bytesHash);
            }
        }
    }

    @Override
    public void close() {
        Releasables.close(bytesHash, finalHash);
    }

    @Override
    public void add(Page page, GroupingAggregatorFunction.AddInput addInput) {
        BytesRefBlock bytesBlock = page.getBlock(bytesChannel);
        BytesRefVector bytesVector = bytesBlock.asVector();
        if (bytesVector != null) {
            try (IntVector bytesHashes = bytesHash.add(bytesVector)) {
                add(page, bytesHashes, addInput);
            }
        } else {
            try (IntBlock bytesHashes = bytesHash.add(bytesBlock)) {
                add(bytesHashes, page.getBlock(longsChannel), addInput);
            }
        }
    }

    public void add(Page page, IntVector bytesHashes, GroupingAggregatorFunction.AddInput addInput) {
        LongBlock longsBlock = page.getBlock(longsChannel);
        LongVector longsVector = longsBlock.asVector();
        if (longsVector != null) {
            try (IntVector ords = add(bytesHashes, longsVector)) {
                addInput.add(0, ords);
            }
        } else {
            add(bytesHashes.asBlock(), longsBlock, addInput);
        }
    }

    public void add(IntBlock bytesHashes, LongBlock longsBlock, GroupingAggregatorFunction.AddInput addInput) {
        try (IntLongBlockAdd work = new IntLongBlockAdd(blockFactory, emitBatchSize, addInput, finalHash, bytesHashes, longsBlock)) {
            work.add();
        }
    }

    public IntVector add(IntVector bytesHashes, LongVector longsVector) {
        int positions = bytesHashes.getPositionCount();
        final int[] ords = new int[positions];
        for (int i = 0; i < positions; i++) {
            ords[i] = Math.toIntExact(hashOrdToGroup(finalHash.add(bytesHashes.getInt(i), longsVector.getLong(i))));
        }
        return blockFactory.newIntArrayVector(ords, positions);
    }

    @Override
    public ReleasableIterator lookup(Page page, ByteSizeValue targetBlockSize) {
        throw new UnsupportedOperationException("TODO");
    }

    @Override
    public Block[] getKeys() {
        int positions = (int) finalHash.size();
        BytesRefBlock k1 = null;
        LongVector k2 = null;
        try (
            BytesRefBlock.Builder keys1 = blockFactory.newBytesRefBlockBuilder(positions);
            LongVector.Builder keys2 = blockFactory.newLongVectorBuilder(positions)
        ) {
            BytesRef scratch = new BytesRef();
            for (long i = 0; i < positions; i++) {
                keys2.appendLong(finalHash.getKey2(i));
                long h1 = finalHash.getKey1(i);
                if (h1 == 0) {
                    keys1.appendNull();
                } else {
                    keys1.appendBytesRef(bytesHash.hash.get(h1 - 1, scratch));
                }
            }
            k1 = keys1.build();
            k2 = keys2.build();
        } finally {
            if (k2 == null) {
                Releasables.closeExpectNoException(k1);
            }
        }
        if (reverseOutput) {
            return new Block[] { k2.asBlock(), k1 };
        } else {
            return new Block[] { k1, k2.asBlock() };
        }
    }

    @Override
    public BitArray seenGroupIds(BigArrays bigArrays) {
        return new SeenGroupIds.Range(0, Math.toIntExact(finalHash.size())).seenGroupIds(bigArrays);
    }

    @Override
    public IntVector nonEmpty() {
        return IntVector.range(0, Math.toIntExact(finalHash.size()), blockFactory);
    }

    @Override
    public String toString() {
        return "BytesRefLongBlockHash{keys=[BytesRefKey[channel="
            + bytesChannel
            + "], LongKey[channel="
            + longsChannel
            + "]], entries="
            + finalHash.size()
            + ", size="
            + bytesHash.hash.ramBytesUsed()
            + "b}";
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy