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

com.olapdb.core.scanners.VerticalVoxelScanner Maven / Gradle / Ivy

The newest version!
package com.olapdb.core.scanners;

import com.olapdb.core.domain.MultiMeasureStat;
import com.olapdb.core.hll.HLLDistinct;
import com.olapdb.core.tables.Voxel;
import com.olapdb.obase.data.Bytez;
import com.olapdb.obase.data.index.Lunnar;
import com.olapdb.obase.utils.Obase;
import lombok.extern.slf4j.Slf4j;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.filter.Filter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;

@Slf4j
public class VerticalVoxelScanner {
    // special marker to indicate when a scanning task has finished
    private static final Voxel MARKER = new Voxel("marker", false);

    // number of scanning tasks still running
    private AtomicInteger taskCount = new AtomicInteger(0);

    // the size limited buffer to use
    private BlockingDeque results;

    private volatile Exception exception;

    private long destSegId; //输出的Voxel的Seg ID
    private boolean cacheBlocks;
    private boolean inclusiveStart = true;
    private boolean checkMatch = false;

    private AtomicLong scanCounter = new AtomicLong();

    private TreeSet scanners = new TreeSet<>(new Comparator() {
        @Override
        public int compare(IndicatorScanner o1, IndicatorScanner o2) {
            int result = Bytez.compareTo(o1.indicator, o2.indicator);

            if(result == 0){
                result = o1.scanner.hashCode() - o2.scanner.hashCode();
            }

            return result;
        }
    });

    private Thread loadingThread = new Thread(){
        public void run(){
        List currents =  new ArrayList<>();

        try {
            while(taskCount.get() > 0){
                IndicatorScanner scanner = scanners.pollFirst();
                Voxel voxel = scanner.voxel;

                if(!currents.isEmpty() && Bytez.compareTo(currents.get(0).getIndicator(), voxel.getIndicator()) !=0){
                    Voxel cbResult = combine(currents);
                    if(cbResult.valid()) {
                        results.put(cbResult);
                    }
                    currents.clear();
                }
                currents.add(voxel);

                if(!addScannerToTree(scanner)){
                    taskCount.decrementAndGet();
                }

                scanCounter.incrementAndGet();
            }

            if(! currents.isEmpty()){
                if(results != null) {
                    Voxel cbResult = combine(currents);
                    if(cbResult.valid()) {
                        results.put(cbResult);
                    }
                }
            }

            if(results != null) {
                results.put(MARKER);
            }
        }catch (Exception e){
            exception = e;
        }
        }
    };

    private Voxel combine(List voxels){
        Voxel first = voxels.get(0);
        Voxel result = new Voxel(destSegId,first.getIndicator(), false);
        if(voxels.size() == 1){
            byte[] bytes = first.getAttribute("stat");
            if(bytes != null){
                result.setAttribute("stat", bytes);
            }

            bytes = first.getAttribute("distinct");
            if(bytes != null){
                result.setAttribute("distinct", bytes);
            }
        }else{
            MultiMeasureStat stat = first.getStat();
            for(int i=1; i segIds, long destSegId, int cuboidId, Filter filter) throws Exception {
        this(segIds, destSegId, Bytez.from(cuboidId), Bytez.next(Bytez.from(cuboidId)), filter, true, true, false);
    }

    public VerticalVoxelScanner(List segIds, long destSegId, byte[] startValue, byte[] stopValue, Filter filter, boolean cacheBlocks, boolean inclusiveStart, boolean checkMatch) throws Exception {
        this.destSegId = destSegId;
        this.cacheBlocks = cacheBlocks;
        this.inclusiveStart = inclusiveStart;
        this.checkMatch = checkMatch;
        init(segIds, startValue, stopValue, filter, 10000);
    }

    private void init(List segIds, byte[] startValue, byte[] stopValue, Filter filter, int bufferSize) throws Exception {
        bufferSize = bufferSize>0?bufferSize:1000;
        results = new LinkedBlockingDeque<>(bufferSize);
        taskCount.set(0);

        final AtomicReference exceptionAtomicReference = new AtomicReference<>();
        Lunnar lunnar = new Lunnar(Math.min(100, segIds.size()));
        for(long seg : segIds){
            lunnar.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        byte[] start = Bytez.add(Bytez.from(seg), startValue);
                        byte[] stop = Bytez.add(Bytez.from(seg), stopValue);
                        Scan scan = new Scan().withStartRow(start, inclusiveStart).withStopRow(stop).setCaching(1000);
                        scan.setCacheBlocks(VerticalVoxelScanner.this.cacheBlocks);
                        if(filter != null) {
                            scan.setFilter(filter);
                        }

                        ResultScanner rs = Obase.getTable(Voxel.class).getScanner(scan);
                        if(VerticalVoxelScanner.this.addScannerToTree(new IndicatorScanner(rs))) {
                            taskCount.incrementAndGet();
                        }
                    }catch (Exception e){
                        log.error("create partion scan failed", e);
                        exceptionAtomicReference.set(e);
                    }
                }
            });
        }

        lunnar.waitForComplete();

        if(this.checkMatch && this.scanners.size() != segIds.size()){
            throw new Exception("FlOOD ERROR: create vertical voxel scanner failed. segIds.size = " + segIds.size() + " not match scanners.size = "+ this.scanners.size() );
        }

        if(exceptionAtomicReference.get() != null){
            throw exceptionAtomicReference.get();
        }

        loadingThread.start();
    }

    public long getScanCount(){
        return scanCounter.get();
    }

    public Voxel next() throws Exception {
        try {
            // if at least one task is active wait for results to arrive.
            if (exception != null) {
                throw exception;
            }

            Voxel r = results.take();
            // skip markers, adjust task count if needed
            if (r != MARKER) {
                return r;
            }

            return results.poll();
        } catch (InterruptedException x) {
            close();
            throw new IOException(x);
        }
    }

    public List next(int nbRows) throws Exception {
        List resultSets = new ArrayList(nbRows);

        for(int i = 0; i < nbRows; ++i) {
            Voxel next = this.next();
            if (next == null) {
                break;
            }

            resultSets.add(next);
        }

        return resultSets;
    }

    public void close() {
        results = null;

        if(loadingThread!=null && loadingThread.isAlive()) {
            loadingThread.interrupt();
        }
        loadingThread = null;

        scanners.forEach(e->e.scanner.close());
    }

    synchronized private boolean addScannerToTree(IndicatorScanner indicatorScanner)throws Exception{
        Result result = indicatorScanner.scanner.next();
        if(result == null){
            indicatorScanner.scanner.close();
            return false;
        }

        Voxel voxel = new Voxel(result);
        indicatorScanner.voxel = voxel;
        indicatorScanner.indicator = voxel.getIndicator();
        this.scanners.add(indicatorScanner);

        return true;
    }

    private final static class IndicatorScanner{
        byte[] indicator;
        ResultScanner scanner;
        Voxel voxel;

        IndicatorScanner(ResultScanner scanner){
            this.scanner = scanner;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy