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

com.alipay.oceanbase.rpc.direct_load.execution.ObDirectLoadStatementHeartBeatTask Maven / Gradle / Ivy

/*-
 * #%L
 * com.oceanbase:obkv-table-client
 * %%
 * Copyright (C) 2021 - 2024 OceanBase
 * %%
 * OBKV Table Client Framework is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 * #L%
 */

package com.alipay.oceanbase.rpc.direct_load.execution;

import java.util.concurrent.TimeUnit;

import com.alipay.oceanbase.rpc.direct_load.ObDirectLoadConnection;
import com.alipay.oceanbase.rpc.direct_load.ObDirectLoadStatement;
import com.alipay.oceanbase.rpc.direct_load.exception.ObDirectLoadException;
import com.alipay.oceanbase.rpc.direct_load.exception.ObDirectLoadExceptionUtil;
import com.alipay.oceanbase.rpc.direct_load.exception.ObDirectLoadRpcException;
import com.alipay.oceanbase.rpc.direct_load.exception.ObDirectLoadRpcTimeoutException;
import com.alipay.oceanbase.rpc.direct_load.exception.ObDirectLoadServerException;
import com.alipay.oceanbase.rpc.direct_load.future.ObDirectLoadStatementAsyncPromiseTask;
import com.alipay.oceanbase.rpc.direct_load.protocol.payload.ObDirectLoadGetStatusRpc;
import com.alipay.oceanbase.rpc.direct_load.protocol.payload.ObDirectLoadHeartBeatRpc;
import com.alipay.oceanbase.rpc.direct_load.protocol.payload.ObTableLoadClientStatus;
import com.alipay.oceanbase.rpc.direct_load.protocol.ObDirectLoadProtocol;
import com.alipay.oceanbase.rpc.protocol.payload.ResultCodes;
import com.alipay.oceanbase.rpc.table.ObTable;

public class ObDirectLoadStatementHeartBeatTask extends ObDirectLoadStatementAsyncPromiseTask {

    private final ObDirectLoadConnection                       connection;
    private final ObDirectLoadProtocol                         protocol;
    private final ObDirectLoadStatementExecutor                executor;
    private final ObDirectLoadStatementExecutor.HeartBeatProxy proxy;

    private boolean                                            isRunning = false;
    private boolean                                            isCancel  = false;

    public ObDirectLoadStatementHeartBeatTask(ObDirectLoadStatement statement,
                                              ObDirectLoadStatementExecutor executor) {
        super(statement);
        this.connection = statement.getConnection();
        this.protocol = connection.getProtocol();
        this.executor = executor;
        this.proxy = executor.getHeartBeatProxy();
    }

    public synchronized boolean cancel() {
        isCancel = true;
        return !isRunning;
    }

    @Override
    public void run() {
        try {
            synchronized (this) {
                isRunning = true;
                if (isCancel) {
                    setSuccess();
                    return;
                }
            }
            proxy.checkStatus();
            sendHeartBeat();
            synchronized (this) {
                if (isCancel) {
                    setSuccess();
                    return;
                }
            }
        } catch (ObDirectLoadException e) {
            logger.warn("statement heart beat task run failed", e);
            proxy.setFailure(e);
            setFailure(e);
        } finally {
            synchronized (this) {
                isRunning = false;
            }
        }
    }

    private void sendHeartBeat() throws ObDirectLoadException {
        try {
            ObTableLoadClientStatus status = ObTableLoadClientStatus.MAX_STATUS;
            int errorCode = ResultCodes.OB_SUCCESS.errorCode;
            try {
                ObDirectLoadHeartBeatRpc rpc = doSendHeartBeat();
                status = rpc.getStatus();
                errorCode = rpc.getErrorCode();
            } catch (ObDirectLoadException e) {
                logger.warn("statement send heart beat rpc failed", e);
                boolean sendGetStatus = false;
                if (e instanceof ObDirectLoadServerException) {
                    final int ret = ((ObDirectLoadServerException) e).getErrorCode();
                    if (ret == ResultCodes.OB_ENTRY_NOT_EXIST.errorCode) {
                        // 如果心跳找不到任务, 则通过get status获取错误码
                        sendGetStatus = true;
                        try {
                            ObDirectLoadGetStatusRpc rpc2 = doSendGetStatus();
                            status = rpc2.getStatus();
                            errorCode = rpc2.getErrorCode();
                        } catch (ObDirectLoadException e2) {
                            logger.warn("statement send get status rpc failed", e2);
                            throw e2;
                        }
                    }
                }
                if (!sendGetStatus) {
                    throw e;
                }
            }
            switch (status) {
                case INITIALIZING:
                case WAITTING:
                case RUNNING:
                case COMMITTING:
                case COMMIT:
                    schedule(connection.getHeartBeatInterval(), TimeUnit.MILLISECONDS);
                    break;
                case ERROR:
                    logger.warn("statement server status is error, errorCode:" + errorCode);
                    throw ObDirectLoadExceptionUtil.convertException(status, errorCode);
                case ABORT:
                    logger.warn("statement server status is abort, errorCode:" + errorCode);
                    if (errorCode == ResultCodes.OB_SUCCESS.errorCode) {
                        errorCode = ResultCodes.OB_CANCELED.errorCode;
                    }
                    throw ObDirectLoadExceptionUtil.convertException(status, errorCode);
                default:
                    logger.warn("statement server status is unexpected, status:" + status);
                    throw ObDirectLoadExceptionUtil.convertException(status, errorCode);
            }
        } catch (ObDirectLoadException e) {
            logger.warn("statement send heart beat failed", e);
            boolean canRetry = false;
            if (e instanceof ObDirectLoadRpcException) {
                if (e instanceof ObDirectLoadRpcTimeoutException) {
                    canRetry = true;
                    schedule(500, TimeUnit.MILLISECONDS);
                }
            }
            if (!canRetry) {
                throw e;
            }
        }
    }

    private ObDirectLoadHeartBeatRpc doSendHeartBeat() throws ObDirectLoadException {
        final ObTable table = statement.getObTablePool().getHighPrioObTable();
        final long timeoutMillis = statement.getTimeoutRemain();

        ObDirectLoadHeartBeatRpc rpc = protocol.getHeartBeatRpc(executor.getTraceId());
        rpc.setSvrAddr(executor.getSvrAddr());
        rpc.setTableId(executor.getTableId());
        rpc.setTaskId(executor.getTaskId());

        logger.info("statement send heart beat rpc, arg:" + rpc.getArg());
        connection.executeWithConnection(rpc, table, timeoutMillis);
        logger.info("statement heart beat rpc response successful, res:" + rpc.getRes());

        return rpc;
    }

    private ObDirectLoadGetStatusRpc doSendGetStatus() throws ObDirectLoadException {
        final ObTable table = statement.getObTablePool().getControlObTable();
        final long timeoutMillis = statement.getTimeoutRemain();

        ObDirectLoadGetStatusRpc rpc = protocol.getGetStatusRpc(executor.getTraceId());
        rpc.setSvrAddr(executor.getSvrAddr());
        rpc.setTableId(executor.getTableId());
        rpc.setTaskId(executor.getTaskId());

        logger.debug("statement send get status rpc, arg:" + rpc.getArg());
        connection.executeWithConnection(rpc, table, timeoutMillis);
        logger.debug("statement get status rpc response successful, res:" + rpc.getRes());

        return rpc;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy