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

com.huaweicloud.dws.client.collector.SecurityModeCollector Maven / Gradle / Ivy

package com.huaweicloud.dws.client.collector;

import com.huaweicloud.dws.client.DwsConfig;
import com.huaweicloud.dws.client.action.SecurityModeAction;
import com.huaweicloud.dws.client.exception.DwsClientException;
import com.huaweicloud.dws.client.exception.InvalidException;
import com.huaweicloud.dws.client.model.OperationType;
import com.huaweicloud.dws.client.model.Record;
import com.huaweicloud.dws.client.model.TableSchema;
import com.huaweicloud.dws.client.model.WriteMode;
import com.huaweicloud.dws.client.worker.ExecutionPool;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ProjectName: dws-connector
 * @ClassName: TableActionCollector
 * @Description: 表事件收集, 用于按表维处理事件
 * @Date: 2023/1/10 15:48
 * @Version: 1.0
 */
@Slf4j
public class SecurityModeCollector extends TableActionCollector {


    public SecurityModeCollector(DwsConfig config, ExecutionPool pool, TableSchema schema) {
        super(config, pool, schema);
    }

    private boolean hasCopy;

    private CopyReader copyReader;

    private SecurityModeAction currentAction;

    private List columnList;

    /**
     * 按批次维度缓存数据去重
     */
    private final Map nextRecord = new HashMap<>(30000);

    private boolean isWriteBuffer;


    @Override
    public void collector(Record record) throws DwsClientException {
        // 刷库后就会将字段清空,重新缓存
        if (columnList == null) {
            initEnv(record);
            // 是否需要写入缓存:如果不是纯写入,由于需要主键判断是否重复,必须写缓存,如果有重试也必须写缓存,因为需要获取全量数据
            isWriteBuffer = !(tableConfig.getWriteMode() == WriteMode.COPY || !record.isUpsert()) || config.getMaxFlushRetryTimes() != 1;
        }
        if (!hasCopy) {
            super.collector(record);
            return;
        }
        if (record.getType() != OperationType.WRITE) {
            // 流式写入不支持删除
            throw new InvalidException("security mode use copy write only support write record.");
        }
        pool.checkStatus();
        lock.lock();
        try {
            initCopy(record, null);
            if (isWriteBuffer) {
                // 如果当前数据存在过,放到下批入库
                Record write = buffer.write(record);
                if (write != null) {
                    nextRecord.put(write.getRecordKey(), write);
                    return;
                }
            }
            // 该模式下格式不会变化,可以直接将数据写入copy流
            copyReader.writeRecord(record);
            if (needFlush()) {
                // 只有在数量超过容量规定倍数后 才强制业务线程提交刷库,否则等待定时任务刷库即可
                flush(false);
            }
        } finally {
            lock.unlock();
        }

    }

    private boolean needFlush() {
        if (buffer.flush() && buffer.getSize() >= tableConfig.getAutoFlushBatchSize() * tableConfig.getBatchOutWeighRatio()) {
            return true;
        }
        return copyReader != null && copyReader.willStop() && copyReader.getSize() >= tableConfig.getAutoFlushBatchSize() * tableConfig.getBatchOutWeighRatio();
    }

    private synchronized void initEnv(Record record) {
        if (columnList != null) {
            return;
        }
        if (currentTableSchema == null) {
            currentTableSchema = record.getTableSchema();
            tableConfig = config.getTableConfig(currentTableSchema.getTableName());
        }
        hasCopy = tableConfig.getWriteMode().name().startsWith("COPY");
        columnList = new ArrayList<>();
        record.getColumnBit().stream().forEach(item -> columnList.add(currentTableSchema.getColumnNames().get(item)));
    }

    private void initCopy(Record record, Object lock) throws DwsClientException {
        if (copyReader != null) {
            return;
        }
        copyReader = new CopyReader(tableConfig);
        if (lock == null) {
            currentAction = new SecurityModeAction(record, config, copyReader, columnList);
        } else {
            currentAction = new SecurityModeAction(record, config, copyReader, columnList, lock);
        }
        long start = System.currentTimeMillis();
        while (!pool.submit(currentAction)) {
            log.debug("try submit.");
        }
        log.info("submit action successful. use time = {}", System.currentTimeMillis() - start);
    }

    @Override
    public void flush() throws DwsClientException {
        flush(true);
    }

    public void flush(boolean force) throws DwsClientException {
        if (!hasCopy) {
            super.flush();
            return;
        }
        lock.lock();
        try {
            if (copyReader == null || currentAction == null) {
                return;
            }
            // 结算完成上一个正在执行的copy
            log.info("will flush size {}", buffer.getSize());
            copyReader.setAllRecords(buffer.getRecords());
            copyReader.stop();
            // 清空当前copy
            copyReader = null;
            // 清空缓存
            buffer.clear();
            pool.waitAction(currentAction);
            if (!nextRecord.isEmpty()) {
                log.info("current batch has more record, size {}", nextRecord.size());
                for (Record record : nextRecord.values()) {
                    if (copyReader == null) {
                        initCopy(record, currentAction.getLock());
                    }
                    copyReader.writeRecord(record);
                    if (!force) {
                        buffer.write(record);
                    }
                }
                // 如果不是程序运行结束需要强制结算,则将重复数据直接放入下批中写入
                nextRecord.clear();
                if (force) {
                    copyReader.stop();
                    pool.waitAction(currentAction);
                    copyReader = null;
                }
            }
        } finally {
            lock.unlock();
        }
    }


    /**
     * 根据 缓存是否达到刷库要求决定是否需要刷库
     * @return
     */
    @Override
    public void tryFlush() throws DwsClientException {
        if (buffer.flush() || (copyReader != null && copyReader.willStop())) {
            flush(false);
        }
    }

    @Override
    public TableSchema getTableSchema() {
        return currentTableSchema;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy