From 211ae46a05299a6d24dead4ea9dec5cff96b1147 Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Sat, 2 Jul 2022 16:59:49 +0800 Subject: [PATCH 1/9] enh: refactor scheduler code --- include/libs/qcom/query.h | 13 +- include/libs/scheduler/scheduler.h | 26 +- source/client/src/clientImpl.c | 48 +- source/client/src/clientMain.c | 2 +- source/libs/qcom/src/queryUtil.c | 14 +- source/libs/qworker/inc/qwInt.h | 4 +- source/libs/qworker/src/qwDbg.c | 36 +- source/libs/qworker/src/qworker.c | 18 +- .../inc/{schedulerInt.h => schInt.h} | 36 +- source/libs/scheduler/src/schJob.c | 1053 ++--------------- source/libs/scheduler/src/schRemote.c | 10 +- source/libs/scheduler/src/schStatus.c | 46 + source/libs/scheduler/src/schTask.c | 843 +++++++++++++ source/libs/scheduler/src/schUtil.c | 17 + source/libs/scheduler/src/scheduler.c | 49 +- source/libs/scheduler/test/schedulerTests.cpp | 11 +- 16 files changed, 1115 insertions(+), 1111 deletions(-) rename source/libs/scheduler/inc/{schedulerInt.h => schInt.h} (95%) create mode 100644 source/libs/scheduler/src/schStatus.c create mode 100644 source/libs/scheduler/src/schTask.c diff --git a/include/libs/qcom/query.h b/include/libs/qcom/query.h index 7f7fe76139..64196aa64f 100644 --- a/include/libs/qcom/query.h +++ b/include/libs/qcom/query.h @@ -29,12 +29,13 @@ extern "C" { typedef enum { JOB_TASK_STATUS_NULL = 0, - JOB_TASK_STATUS_NOT_START = 1, - JOB_TASK_STATUS_EXECUTING, - JOB_TASK_STATUS_PARTIAL_SUCCEED, - JOB_TASK_STATUS_SUCCEED, - JOB_TASK_STATUS_FAILED, - JOB_TASK_STATUS_DROPPING, + JOB_TASK_STATUS_INIT, + JOB_TASK_STATUS_EXEC, + JOB_TASK_STATUS_PART_SUCC, + JOB_TASK_STATUS_SUCC, + JOB_TASK_STATUS_FAIL, + JOB_TASK_STATUS_DROP, + JOB_TASK_STATUS_MAX, } EJobTaskType; typedef enum { diff --git a/include/libs/scheduler/scheduler.h b/include/libs/scheduler/scheduler.h index 1c73b2c2c8..66e1f7ed3a 100644 --- a/include/libs/scheduler/scheduler.h +++ b/include/libs/scheduler/scheduler.h @@ -74,6 +74,7 @@ typedef void (*schedulerFetchFp)(void* pResult, void* param, int32_t code); typedef bool (*schedulerChkKillFp)(void* param); typedef struct SSchedulerReq { + bool syncReq; SRequestConnInfo *pConn; SArray *pNodeList; SQueryPlan *pDag; @@ -83,36 +84,17 @@ typedef struct SSchedulerReq { void* execParam; schedulerChkKillFp chkKillFp; void* chkKillParam; + SQueryResult* pQueryRes; } SSchedulerReq; int32_t schedulerInit(SSchedulerCfg *cfg); -/** - * Process the query job, generated according to the query physical plan. - * This is a synchronized API, and is also thread-safety. - * @param nodeList Qnode/Vnode address list, element is SQueryNodeAddr - * @return - */ -int32_t schedulerExecJob(SSchedulerReq *pReq, int64_t *pJob, SQueryResult *pRes); +int32_t schedulerExecJob(SSchedulerReq *pReq, int64_t *pJob); -/** - * Process the query job, generated according to the query physical plan. - * This is a asynchronized API, and is also thread-safety. - * @param pNodeList Qnode/Vnode address list, element is SQueryNodeAddr - * @return - */ - int32_t schedulerAsyncExecJob(SSchedulerReq *pReq, int64_t *pJob); - -/** - * Fetch query result from the remote query executor - * @param pJob - * @param data - * @return - */ int32_t schedulerFetchRows(int64_t job, void **data); -void schedulerAsyncFetchRows(int64_t job, schedulerFetchFp fp, void* param); +void schedulerFetchRowsA(int64_t job, schedulerFetchFp fp, void* param); int32_t schedulerGetTasksStatus(int64_t job, SArray *pSub); diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index 9047a9d27e..63b153b6fc 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -631,17 +631,21 @@ int32_t scheduleQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNodeList SRequestConnInfo conn = {.pTrans = pRequest->pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self}; - SSchedulerReq req = {.pConn = &conn, - .pNodeList = pNodeList, - .pDag = pDag, - .sql = pRequest->sqlstr, - .startTs = pRequest->metric.start, - .execFp = NULL, - .execParam = NULL, - .chkKillFp = chkRequestKilled, - .chkKillParam = (void*)pRequest->self}; + SSchedulerReq req = { + .syncReq = true, + .pConn = &conn, + .pNodeList = pNodeList, + .pDag = pDag, + .sql = pRequest->sqlstr, + .startTs = pRequest->metric.start, + .execFp = NULL, + .execParam = NULL, + .chkKillFp = chkRequestKilled, + .chkKillParam = (void*)pRequest->self + .pQueryRes = &res, + }; - int32_t code = schedulerExecJob(&req, &pRequest->body.queryJob, &res); + int32_t code = schedulerExecJob(&req, &pRequest->body.queryJob); pRequest->body.resInfo.execRes = res.res; if (code != TSDB_CODE_SUCCESS) { @@ -939,16 +943,20 @@ void launchAsyncQuery(SRequestObj* pRequest, SQuery* pQuery, SMetaData* pResultM SRequestConnInfo conn = { .pTrans = pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self}; - SSchedulerReq req = {.pConn = &conn, - .pNodeList = pNodeList, - .pDag = pDag, - .sql = pRequest->sqlstr, - .startTs = pRequest->metric.start, - .execFp = schedulerExecCb, - .execParam = pRequest, - .chkKillFp = chkRequestKilled, - .chkKillParam = (void*)pRequest->self}; - code = schedulerAsyncExecJob(&req, &pRequest->body.queryJob); + SSchedulerReq req = { + .syncReq = false, + .pConn = &conn, + .pNodeList = pNodeList, + .pDag = pDag, + .sql = pRequest->sqlstr, + .startTs = pRequest->metric.start, + .execFp = schedulerExecCb, + .execParam = pRequest, + .chkKillFp = chkRequestKilled, + .chkKillParam = (void*)pRequest->self, + .pQueryRes = NULL, + }; + code = schedulerExecJob(&req, &pRequest->body.queryJob); taosArrayDestroy(pNodeList); } else { tscDebug("0x%" PRIx64 " plan not executed, code:%s 0x%" PRIx64, pRequest->self, tstrerror(code), diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c index d824ef998f..f660c46d3c 100644 --- a/source/client/src/clientMain.c +++ b/source/client/src/clientMain.c @@ -863,7 +863,7 @@ void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) { } } - schedulerAsyncFetchRows(pRequest->body.queryJob, fetchCallback, pRequest); + schedulerFetchRowsA(pRequest->body.queryJob, fetchCallback, pRequest); } void taos_fetch_raw_block_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) { diff --git a/source/libs/qcom/src/queryUtil.c b/source/libs/qcom/src/queryUtil.c index a3a15869eb..1db13dd931 100644 --- a/source/libs/qcom/src/queryUtil.c +++ b/source/libs/qcom/src/queryUtil.c @@ -171,17 +171,17 @@ char* jobTaskStatusStr(int32_t status) { switch (status) { case JOB_TASK_STATUS_NULL: return "NULL"; - case JOB_TASK_STATUS_NOT_START: - return "NOT_START"; - case JOB_TASK_STATUS_EXECUTING: + case JOB_TASK_STATUS_INIT: + return "INIT"; + case JOB_TASK_STATUS_EXEC: return "EXECUTING"; - case JOB_TASK_STATUS_PARTIAL_SUCCEED: + case JOB_TASK_STATUS_PART_SUCC: return "PARTIAL_SUCCEED"; - case JOB_TASK_STATUS_SUCCEED: + case JOB_TASK_STATUS_SUCC: return "SUCCEED"; - case JOB_TASK_STATUS_FAILED: + case JOB_TASK_STATUS_FAIL: return "FAILED"; - case JOB_TASK_STATUS_DROPPING: + case JOB_TASK_STATUS_DROP: return "DROPPING"; default: break; diff --git a/source/libs/qworker/inc/qwInt.h b/source/libs/qworker/inc/qwInt.h index 6faffa13b3..eb10a2fdd6 100644 --- a/source/libs/qworker/inc/qwInt.h +++ b/source/libs/qworker/inc/qwInt.h @@ -226,8 +226,8 @@ typedef struct SQWorkerMgmt { #define QW_TASK_NOT_EXIST(code) (TSDB_CODE_QRY_SCH_NOT_EXIST == (code) || TSDB_CODE_QRY_TASK_NOT_EXIST == (code)) #define QW_TASK_ALREADY_EXIST(code) (TSDB_CODE_QRY_TASK_ALREADY_EXIST == (code)) #define QW_TASK_READY(status) \ - (status == JOB_TASK_STATUS_SUCCEED || status == JOB_TASK_STATUS_FAILED || status == JOB_TASK_STATUS_CANCELLED || \ - status == JOB_TASK_STATUS_PARTIAL_SUCCEED) + (status == JOB_TASK_STATUS_SUCC || status == JOB_TASK_STATUS_FAIL || status == JOB_TASK_STATUS_CANCELLED || \ + status == JOB_TASK_STATUS_PART_SUCC) #define QW_SET_QTID(id, qId, tId, eId) \ do { \ *(uint64_t *)(id) = (qId); \ diff --git a/source/libs/qworker/src/qwDbg.c b/source/libs/qworker/src/qwDbg.c index 68058334ab..dfe5a04d19 100644 --- a/source/libs/qworker/src/qwDbg.c +++ b/source/libs/qworker/src/qwDbg.c @@ -19,7 +19,7 @@ int32_t qwDbgValidateStatus(QW_FPARAMS_DEF, int8_t oriStatus, int8_t newStatus, int32_t code = 0; if (oriStatus == newStatus) { - if (newStatus == JOB_TASK_STATUS_EXECUTING || newStatus == JOB_TASK_STATUS_FAILED) { + if (newStatus == JOB_TASK_STATUS_EXEC || newStatus == JOB_TASK_STATUS_FAIL) { *ignore = true; return TSDB_CODE_SUCCESS; } @@ -29,47 +29,47 @@ int32_t qwDbgValidateStatus(QW_FPARAMS_DEF, int8_t oriStatus, int8_t newStatus, switch (oriStatus) { case JOB_TASK_STATUS_NULL: - if (newStatus != JOB_TASK_STATUS_EXECUTING && newStatus != JOB_TASK_STATUS_FAILED && - newStatus != JOB_TASK_STATUS_NOT_START) { + if (newStatus != JOB_TASK_STATUS_EXEC && newStatus != JOB_TASK_STATUS_FAIL && + newStatus != JOB_TASK_STATUS_INIT) { QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); } break; - case JOB_TASK_STATUS_NOT_START: - if (newStatus != JOB_TASK_STATUS_DROPPING && newStatus != JOB_TASK_STATUS_EXECUTING - && newStatus != JOB_TASK_STATUS_FAILED) { + case JOB_TASK_STATUS_INIT: + if (newStatus != JOB_TASK_STATUS_DROP && newStatus != JOB_TASK_STATUS_EXEC + && newStatus != JOB_TASK_STATUS_FAIL) { QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); } break; - case JOB_TASK_STATUS_EXECUTING: - if (newStatus != JOB_TASK_STATUS_PARTIAL_SUCCEED && newStatus != JOB_TASK_STATUS_SUCCEED && - newStatus != JOB_TASK_STATUS_FAILED && newStatus != JOB_TASK_STATUS_DROPPING) { + case JOB_TASK_STATUS_EXEC: + if (newStatus != JOB_TASK_STATUS_PART_SUCC && newStatus != JOB_TASK_STATUS_SUCC && + newStatus != JOB_TASK_STATUS_FAIL && newStatus != JOB_TASK_STATUS_DROP) { QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); } break; - case JOB_TASK_STATUS_PARTIAL_SUCCEED: - if (newStatus != JOB_TASK_STATUS_EXECUTING && newStatus != JOB_TASK_STATUS_SUCCEED && - newStatus != JOB_TASK_STATUS_FAILED && newStatus != JOB_TASK_STATUS_DROPPING) { + case JOB_TASK_STATUS_PART_SUCC: + if (newStatus != JOB_TASK_STATUS_EXEC && newStatus != JOB_TASK_STATUS_SUCC && + newStatus != JOB_TASK_STATUS_FAIL && newStatus != JOB_TASK_STATUS_DROP) { QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); } break; - case JOB_TASK_STATUS_SUCCEED: - if (newStatus != JOB_TASK_STATUS_DROPPING && newStatus != JOB_TASK_STATUS_FAILED) { + case JOB_TASK_STATUS_SUCC: + if (newStatus != JOB_TASK_STATUS_DROP && newStatus != JOB_TASK_STATUS_FAIL) { QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); } break; - case JOB_TASK_STATUS_FAILED: - if (newStatus != JOB_TASK_STATUS_DROPPING) { + case JOB_TASK_STATUS_FAIL: + if (newStatus != JOB_TASK_STATUS_DROP) { QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); } break; - case JOB_TASK_STATUS_DROPPING: - if (newStatus != JOB_TASK_STATUS_FAILED && newStatus != JOB_TASK_STATUS_PARTIAL_SUCCEED) { + case JOB_TASK_STATUS_DROP: + if (newStatus != JOB_TASK_STATUS_FAIL && newStatus != JOB_TASK_STATUS_PART_SUCC) { QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); } break; diff --git a/source/libs/qworker/src/qworker.c b/source/libs/qworker/src/qworker.c index 949b67249f..b8a2f911bc 100644 --- a/source/libs/qworker/src/qworker.c +++ b/source/libs/qworker/src/qworker.c @@ -206,7 +206,7 @@ int32_t qwGetQueryResFromSink(QW_FPARAMS_DEF, SQWTaskCtx *ctx, int32_t *dataLen, QW_TASK_DLOG_E("no data in sink and query end"); - qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_SUCCEED); + qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_SUCC); QW_ERR_RET(qwMallocFetchRsp(len, &rsp)); *rspMsg = rsp; @@ -236,7 +236,7 @@ int32_t qwGetQueryResFromSink(QW_FPARAMS_DEF, SQWTaskCtx *ctx, int32_t *dataLen, if (DS_BUF_EMPTY == pOutput->bufStatus && pOutput->queryEnd) { QW_TASK_DLOG_E("task all data fetched, done"); - qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_SUCCEED); + qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_SUCC); } return TSDB_CODE_SUCCESS; @@ -330,7 +330,7 @@ int32_t qwHandlePrePhaseEvents(QW_FPARAMS_DEF, int8_t phase, SQWPhaseInput *inpu break; } - QW_ERR_JRET(qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_EXECUTING)); + QW_ERR_JRET(qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_EXEC)); break; } case QW_PHASE_PRE_FETCH: { @@ -447,7 +447,7 @@ int32_t qwHandlePostPhaseEvents(QW_FPARAMS_DEF, int8_t phase, SQWPhaseInput *inp _return: if (TSDB_CODE_SUCCESS == code && QW_PHASE_POST_QUERY == phase) { - qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_PARTIAL_SUCCEED); + qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_PART_SUCC); } if (rspConnection) { @@ -467,7 +467,7 @@ _return: } if (code) { - qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_FAILED); + qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_FAIL); } QW_TASK_DLOG("end to handle event at phase %s, code:%x - %s", qwPhaseStr(phase), code, tstrerror(code)); @@ -499,7 +499,7 @@ int32_t qwPrerocessQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg) { ctx->ctrlConnInfo = qwMsg->connInfo; - QW_ERR_JRET(qwAddTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_NOT_START)); + QW_ERR_JRET(qwAddTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_INIT)); _return: @@ -698,7 +698,7 @@ int32_t qwProcessFetch(QW_FPARAMS_DEF, SQWMsg *qwMsg) { if (QW_IS_QUERY_RUNNING(ctx)) { atomic_store_8((int8_t *)&ctx->queryContinue, 1); } else if (0 == atomic_load_8((int8_t *)&ctx->queryInQueue)) { - qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_EXECUTING); + qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_EXEC); atomic_store_8((int8_t *)&ctx->queryInQueue, 1); @@ -749,7 +749,7 @@ int32_t qwProcessDrop(QW_FPARAMS_DEF, SQWMsg *qwMsg) { if (QW_IS_QUERY_RUNNING(ctx)) { QW_ERR_JRET(qwKillTaskHandle(QW_FPARAMS(), ctx)); - qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_DROPPING); + qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_DROP); } else if (ctx->phase > 0) { QW_ERR_JRET(qwDropTask(QW_FPARAMS())); rsped = true; @@ -770,7 +770,7 @@ _return: QW_UPDATE_RSP_CODE(ctx, code); } - qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_FAILED); + qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_FAIL); } if (locked) { diff --git a/source/libs/scheduler/inc/schedulerInt.h b/source/libs/scheduler/inc/schInt.h similarity index 95% rename from source/libs/scheduler/inc/schedulerInt.h rename to source/libs/scheduler/inc/schInt.h index aaa8274ce8..ce4b9eea19 100644 --- a/source/libs/scheduler/inc/schedulerInt.h +++ b/source/libs/scheduler/inc/schInt.h @@ -54,6 +54,13 @@ typedef enum { SCH_OP_FETCH, } SCH_OP_TYPE; +typedef enum { + SCH_EVENT_ENTER_API = 1, + SCH_EVENT_LEAVE_API, + SCH_EVENT_MSG, + SCH_EVENT_DROP, +} SCH_EVENT_TYPE; + typedef struct SSchTrans { void *pTrans; void *pHandle; @@ -104,6 +111,22 @@ typedef struct SSchResInfo { void* userParam; } SSchResInfo; +typedef struct SSchEvent { + SCH_EVENT_TYPE event; + void* info; +} SSchEvent; + +typedef int32_t (*schStatusEnterFp)(void* pHandle, void* pParam); +typedef int32_t (*schStatusLeaveFp)(void* pHandle, void* pParam); +typedef int32_t (*schStatusEventFp)(void* pHandle, void* pParam, void* pEvent); + +typedef struct SSchStatusFps { + EJobTaskType status; + schStatusEnterFp enterFp; + schStatusLeaveFp leaveFp; + schStatusEventFp eventFp; +} SSchStatusFps; + typedef struct SSchedulerMgmt { uint64_t taskId; // sequential taksId uint64_t sId; // schedulerId @@ -200,7 +223,7 @@ typedef struct SSchJobAttr { typedef struct { int32_t op; - bool sync; + bool syncReq; } SSchOpStatus; typedef struct SSchJob { @@ -349,7 +372,7 @@ int32_t schDecTaskFlowQuota(SSchJob *pJob, SSchTask *pTask); int32_t schCheckIncTaskFlowQuota(SSchJob *pJob, SSchTask *pTask, bool *enough); int32_t schLaunchTasksInFlowCtrlList(SSchJob *pJob, SSchTask *pTask); int32_t schLaunchTaskImpl(SSchJob *pJob, SSchTask *pTask); -int32_t schFetchFromRemote(SSchJob *pJob); +int32_t schLaunchFetchTask(SSchJob *pJob); int32_t schProcessOnTaskFailure(SSchJob *pJob, SSchTask *pTask, int32_t errCode); int32_t schBuildAndSendHbMsg(SQueryNodeEpId *nodeEpId, SArray* taskAction); int32_t schCloneSMsgSendInfo(void *src, void **dst); @@ -371,22 +394,21 @@ void schFreeRpcCtxVal(const void *arg); int32_t schMakeBrokenLinkVal(SSchJob *pJob, SSchTask *pTask, SRpcBrokenlinkVal *brokenVal, bool isHb); int32_t schAppendTaskExecNode(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, int32_t execId); int32_t schExecStaticExplainJob(SSchedulerReq *pReq, int64_t *job, bool sync); -int32_t schExecJobImpl(SSchedulerReq *pReq, SSchJob *pJob, bool sync); int32_t schUpdateJobStatus(SSchJob *pJob, int8_t newStatus); int32_t schCancelJob(SSchJob *pJob); int32_t schProcessOnJobDropped(SSchJob *pJob, int32_t errCode); uint64_t schGenTaskId(void); void schCloseJobRef(void); -int32_t schExecJob(SSchedulerReq *pReq, int64_t *pJob, SQueryResult *pRes); int32_t schAsyncExecJob(SSchedulerReq *pReq, int64_t *pJob); -int32_t schFetchRows(SSchJob *pJob); -int32_t schAsyncFetchRows(SSchJob *pJob); +int32_t schJobFetchRows(SSchJob *pJob); +int32_t schJobFetchRowsA(SSchJob *pJob); int32_t schUpdateTaskHandle(SSchJob *pJob, SSchTask *pTask, bool dropExecNode, void *handle, int32_t execId); int32_t schProcessOnTaskStatusRsp(SQueryNodeEpId* pEpId, SArray* pStatusList); void schFreeSMsgSendInfo(SMsgSendInfo *msgSendInfo); char* schGetOpStr(SCH_OP_TYPE type); int32_t schBeginOperation(SSchJob *pJob, SCH_OP_TYPE type, bool sync); -int32_t schInitJob(SSchedulerReq *pReq, SSchJob **pSchJob); +int32_t schInitJob(SSchJob **pJob, SSchedulerReq *pReq); +int32_t schExecJob(SSchJob *pJob, SSchedulerReq *pReq); int32_t schSetJobQueryRes(SSchJob* pJob, SQueryResult* pRes); int32_t schUpdateTaskCandidateAddr(SSchJob *pJob, SSchTask *pTask, SEpSet* pEpSet); int32_t schHandleRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf* pData, int32_t rspCode); diff --git a/source/libs/scheduler/src/schJob.c b/source/libs/scheduler/src/schJob.c index cb39ff3f20..e137b2b001 100644 --- a/source/libs/scheduler/src/schJob.c +++ b/source/libs/scheduler/src/schJob.c @@ -25,30 +25,13 @@ FORCE_INLINE SSchJob *schAcquireJob(int64_t refId) { qDebug("sch acquire jobId:0 FORCE_INLINE int32_t schReleaseJob(int64_t refId) { qDebug("sch release jobId:0x%"PRIx64, refId); return taosReleaseRef(schMgmt.jobRef, refId); } -int32_t schInitTask(SSchJob *pJob, SSchTask *pTask, SSubplan *pPlan, SSchLevel *pLevel) { - pTask->plan = pPlan; - pTask->level = pLevel; - pTask->execId = -1; - pTask->maxExecTimes = SCH_TASK_MAX_EXEC_TIMES; - pTask->timeoutUsec = SCH_DEFAULT_TASK_TIMEOUT_USEC; - SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_NOT_START); - pTask->taskId = schGenTaskId(); - pTask->execNodes = taosHashInit(SCH_MAX_CANDIDATE_EP_NUM, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK); - if (NULL == pTask->execNodes) { - SCH_TASK_ELOG("taosHashInit %d execNodes failed", SCH_MAX_CANDIDATE_EP_NUM); - SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); - } - - return TSDB_CODE_SUCCESS; -} - -int32_t schInitJob(SSchedulerReq *pReq, SSchJob **pSchJob) { +int32_t schInitJob(SSchJob **pSchJob, SSchedulerReq *pReq) { int32_t code = 0; int64_t refId = -1; SSchJob *pJob = taosMemoryCalloc(1, sizeof(SSchJob)); if (NULL == pJob) { qError("QID:0x%" PRIx64 " calloc %d failed", pReq->pDag->queryId, (int32_t)sizeof(SSchJob)); - SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY); } pJob->attr.explainMode = pReq->pDag->explainInfo.mode; @@ -59,6 +42,8 @@ int32_t schInitJob(SSchedulerReq *pReq, SSchJob **pSchJob) { pJob->chkKillParam = pReq->chkKillParam; pJob->userRes.execFp = pReq->execFp; pJob->userRes.userParam = pReq->execParam; + pJob->opStatus.op = SCH_OP_EXEC; + pJob->opStatus.syncReq = pReq->syncReq; if (pReq->pNodeList == NULL || taosArrayGetSize(pReq->pNodeList) <= 0) { qDebug("QID:0x%" PRIx64 " input exec nodeList is empty", pReq->pDag->queryId); @@ -105,43 +90,21 @@ int32_t schInitJob(SSchedulerReq *pReq, SSchJob **pSchJob) { SCH_JOB_DLOG("job refId:0x%" PRIx64" created", pJob->refId); - schUpdateJobStatus(pJob, JOB_TASK_STATUS_NOT_START); - *pSchJob = pJob; return TSDB_CODE_SUCCESS; _return: - if (refId < 0) { + if (NULL == pJob) { + qDestroyQueryPlan(pReq->pDag); + } else if (refId < 0) { schFreeJobImpl(pJob); } else { taosRemoveRef(schMgmt.jobRef, refId); } - SCH_RET(code); -} - - -void schFreeTask(SSchJob *pJob, SSchTask *pTask) { - schDeregisterTaskHb(pJob, pTask); - if (pTask->candidateAddrs) { - taosArrayDestroy(pTask->candidateAddrs); - } - - taosMemoryFreeClear(pTask->msg); - - if (pTask->children) { - taosArrayDestroy(pTask->children); - } - - if (pTask->parents) { - taosArrayDestroy(pTask->parents); - } - - if (pTask->execNodes) { - taosHashCleanup(pTask->execNodes); - } + SCH_RET(code); } @@ -188,8 +151,8 @@ FORCE_INLINE bool schJobNeedToStop(SSchJob *pJob, int8_t *pStatus) { return true; } - return (status == JOB_TASK_STATUS_FAILED || status == JOB_TASK_STATUS_DROPPING || - status == JOB_TASK_STATUS_SUCCEED); + return (status == JOB_TASK_STATUS_FAIL || status == JOB_TASK_STATUS_DROP || + status == JOB_TASK_STATUS_SUCC); } int32_t schUpdateJobStatus(SSchJob *pJob, int8_t newStatus) { @@ -201,7 +164,7 @@ int32_t schUpdateJobStatus(SSchJob *pJob, int8_t newStatus) { oriStatus = SCH_GET_JOB_STATUS(pJob); if (oriStatus == newStatus) { - if (newStatus == JOB_TASK_STATUS_DROPPING) { + if (newStatus == JOB_TASK_STATUS_DROP) { SCH_ERR_JRET(TSDB_CODE_SCH_JOB_IS_DROPPING); } @@ -210,39 +173,39 @@ int32_t schUpdateJobStatus(SSchJob *pJob, int8_t newStatus) { switch (oriStatus) { case JOB_TASK_STATUS_NULL: - if (newStatus != JOB_TASK_STATUS_NOT_START) { + if (newStatus != JOB_TASK_STATUS_INIT) { SCH_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); } break; - case JOB_TASK_STATUS_NOT_START: - if (newStatus != JOB_TASK_STATUS_EXECUTING && newStatus != JOB_TASK_STATUS_DROPPING) { + case JOB_TASK_STATUS_INIT: + if (newStatus != JOB_TASK_STATUS_EXEC && newStatus != JOB_TASK_STATUS_DROP) { SCH_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); } break; - case JOB_TASK_STATUS_EXECUTING: - if (newStatus != JOB_TASK_STATUS_PARTIAL_SUCCEED && newStatus != JOB_TASK_STATUS_FAILED && - newStatus != JOB_TASK_STATUS_DROPPING) { + case JOB_TASK_STATUS_EXEC: + if (newStatus != JOB_TASK_STATUS_PART_SUCC && newStatus != JOB_TASK_STATUS_FAIL && + newStatus != JOB_TASK_STATUS_DROP) { SCH_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); } break; - case JOB_TASK_STATUS_PARTIAL_SUCCEED: - if (newStatus != JOB_TASK_STATUS_FAILED && newStatus != JOB_TASK_STATUS_SUCCEED && - newStatus != JOB_TASK_STATUS_DROPPING) { + case JOB_TASK_STATUS_PART_SUCC: + if (newStatus != JOB_TASK_STATUS_FAIL && newStatus != JOB_TASK_STATUS_SUCC && + newStatus != JOB_TASK_STATUS_DROP) { SCH_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); } break; - case JOB_TASK_STATUS_SUCCEED: - case JOB_TASK_STATUS_FAILED: - if (newStatus != JOB_TASK_STATUS_DROPPING) { + case JOB_TASK_STATUS_SUCC: + case JOB_TASK_STATUS_FAIL: + if (newStatus != JOB_TASK_STATUS_DROP) { SCH_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); } break; - case JOB_TASK_STATUS_DROPPING: + case JOB_TASK_STATUS_DROP: SCH_ERR_JRET(TSDB_CODE_QRY_JOB_FREED); break; @@ -297,11 +260,11 @@ int32_t schBeginOperation(SSchJob *pJob, SCH_OP_TYPE type, bool sync) { SCH_JOB_DLOG("job start %s operation", schGetOpStr(pJob->opStatus.op)); - pJob->opStatus.sync = sync; + pJob->opStatus.syncReq = sync; switch (type) { case SCH_OP_EXEC: - SCH_ERR_JRET(schUpdateJobStatus(pJob, JOB_TASK_STATUS_EXECUTING)); + SCH_ERR_JRET(schUpdateJobStatus(pJob, JOB_TASK_STATUS_EXEC)); break; case SCH_OP_FETCH: if (!SCH_JOB_NEED_FETCH(pJob)) { @@ -309,7 +272,7 @@ int32_t schBeginOperation(SSchJob *pJob, SCH_OP_TYPE type, bool sync) { SCH_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); } - if (status != JOB_TASK_STATUS_PARTIAL_SUCCEED) { + if (status != JOB_TASK_STATUS_PART_SUCC) { SCH_JOB_ELOG("job status error for fetch, status:%s", jobTaskStatusStr(status)); SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR); } @@ -414,78 +377,8 @@ int32_t schBuildTaskRalation(SSchJob *pJob, SHashObj *planToTask) { return TSDB_CODE_SUCCESS; } -int32_t schRecordTaskSucceedNode(SSchJob *pJob, SSchTask *pTask) { - SQueryNodeAddr *addr = taosArrayGet(pTask->candidateAddrs, pTask->candidateIdx); - if (NULL == addr) { - SCH_TASK_ELOG("taosArrayGet candidate addr failed, idx:%d, size:%d", pTask->candidateIdx, - (int32_t)taosArrayGetSize(pTask->candidateAddrs)); - SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR); - } - pTask->succeedAddr = *addr; - - return TSDB_CODE_SUCCESS; -} - -int32_t schAppendTaskExecNode(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, int32_t execId) { - SSchNodeInfo nodeInfo = {.addr = *addr, .handle = NULL}; - - if (taosHashPut(pTask->execNodes, &execId, sizeof(execId), &nodeInfo, sizeof(nodeInfo))) { - SCH_TASK_ELOG("taosHashPut nodeInfo to execNodes failed, errno:%d", errno); - SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); - } - - SCH_TASK_DLOG("task execNode added, execId:%d", execId); - - return TSDB_CODE_SUCCESS; -} - -int32_t schDropTaskExecNode(SSchJob *pJob, SSchTask *pTask, void *handle, int32_t execId) { - if (NULL == pTask->execNodes) { - return TSDB_CODE_SUCCESS; - } - - if (taosHashRemove(pTask->execNodes, &execId, sizeof(execId))) { - SCH_TASK_ELOG("fail to remove execId %d from execNodeList", execId); - } else { - SCH_TASK_DLOG("execId %d removed from execNodeList", execId); - } - - if (execId != pTask->execId) { // ignore it - SCH_TASK_DLOG("execId %d is not current execId %d", execId, pTask->execId); - SCH_RET(TSDB_CODE_SCH_IGNORE_ERROR); - } - - return TSDB_CODE_SUCCESS; -} - -int32_t schUpdateTaskExecNode(SSchJob *pJob, SSchTask *pTask, void *handle, int32_t execId) { - if (taosHashGetSize(pTask->execNodes) <= 0) { - return TSDB_CODE_SUCCESS; - } - - SSchNodeInfo *nodeInfo = taosHashGet(pTask->execNodes, &execId, sizeof(execId)); - nodeInfo->handle = handle; - - SCH_TASK_DLOG("handle updated to %p for execId %d", handle, execId); - - return TSDB_CODE_SUCCESS; -} - -int32_t schUpdateTaskHandle(SSchJob *pJob, SSchTask *pTask, bool dropExecNode, void *handle, int32_t execId) { - if (dropExecNode) { - SCH_RET(schDropTaskExecNode(pJob, pTask, handle, execId)); - } - - SCH_SET_TASK_HANDLE(pTask, handle); - - schUpdateTaskExecNode(pJob, pTask, handle, execId); - - return TSDB_CODE_SUCCESS; -} - - -int32_t schRecordQueryDataSrc(SSchJob *pJob, SSchTask *pTask) { +int32_t schAppendJobDataSrc(SSchJob *pJob, SSchTask *pTask) { if (!SCH_IS_DATA_SRC_QRY_TASK(pTask)) { return TSDB_CODE_SUCCESS; } @@ -539,7 +432,7 @@ int32_t schValidateAndBuildJob(SQueryPlan *pDag, SSchJob *pJob) { int32_t taskNum = 0; SSchLevel *pLevel = NULL; - level.status = JOB_TASK_STATUS_NOT_START; + level.status = JOB_TASK_STATUS_INIT; for (int32_t i = 0; i < levelNum; ++i) { if (NULL == taosArrayPush(pJob->levels, &level)) { @@ -584,7 +477,7 @@ int32_t schValidateAndBuildJob(SQueryPlan *pDag, SSchJob *pJob) { SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY); } - SCH_ERR_JRET(schRecordQueryDataSrc(pJob, pTask)); + SCH_ERR_JRET(schAppendJobDataSrc(pJob, pTask)); if (0 != taosHashPut(planToTask, &plan, POINTER_BYTES, &pTask, POINTER_BYTES)) { SCH_TASK_ELOG("taosHashPut to planToTaks failed, taskIdx:%d", n); @@ -613,273 +506,6 @@ _return: SCH_RET(code); } -int32_t schSetAddrsFromNodeList(SSchJob *pJob, SSchTask *pTask) { - int32_t addNum = 0; - int32_t nodeNum = 0; - - if (pJob->nodeList) { - nodeNum = taosArrayGetSize(pJob->nodeList); - - for (int32_t i = 0; i < nodeNum && addNum < SCH_MAX_CANDIDATE_EP_NUM; ++i) { - SQueryNodeLoad *nload = taosArrayGet(pJob->nodeList, i); - SQueryNodeAddr *naddr = &nload->addr; - - if (NULL == taosArrayPush(pTask->candidateAddrs, naddr)) { - SCH_TASK_ELOG("taosArrayPush execNode to candidate addrs failed, addNum:%d, errno:%d", addNum, errno); - SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); - } - - SCH_TASK_DLOG("set %dth candidate addr, id %d, fqdn:%s, port:%d", i, naddr->nodeId, SCH_GET_CUR_EP(naddr)->fqdn, SCH_GET_CUR_EP(naddr)->port); - - ++addNum; - } - } - - if (addNum <= 0) { - SCH_TASK_ELOG("no available execNode as candidates, nodeNum:%d", nodeNum); - SCH_ERR_RET(TSDB_CODE_TSC_NO_EXEC_NODE); - } - - return TSDB_CODE_SUCCESS; -} - - -int32_t schSetTaskCandidateAddrs(SSchJob *pJob, SSchTask *pTask) { - if (NULL != pTask->candidateAddrs) { - return TSDB_CODE_SUCCESS; - } - - pTask->candidateIdx = 0; - pTask->candidateAddrs = taosArrayInit(SCH_MAX_CANDIDATE_EP_NUM, sizeof(SQueryNodeAddr)); - if (NULL == pTask->candidateAddrs) { - SCH_TASK_ELOG("taosArrayInit %d condidate addrs failed", SCH_MAX_CANDIDATE_EP_NUM); - SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); - } - - if (pTask->plan->execNode.epSet.numOfEps > 0) { - if (NULL == taosArrayPush(pTask->candidateAddrs, &pTask->plan->execNode)) { - SCH_TASK_ELOG("taosArrayPush execNode to candidate addrs failed, errno:%d", errno); - SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); - } - - SCH_TASK_DLOG("use execNode in plan as candidate addr, numOfEps:%d", pTask->plan->execNode.epSet.numOfEps); - - return TSDB_CODE_SUCCESS; - } - - SCH_ERR_RET(schSetAddrsFromNodeList(pJob, pTask)); - - /* - for (int32_t i = 0; i < job->dataSrcEps.numOfEps && addNum < SCH_MAX_CANDIDATE_EP_NUM; ++i) { - strncpy(epSet->fqdn[epSet->numOfEps], job->dataSrcEps.fqdn[i], sizeof(job->dataSrcEps.fqdn[i])); - epSet->port[epSet->numOfEps] = job->dataSrcEps.port[i]; - - ++epSet->numOfEps; - } - */ - - return TSDB_CODE_SUCCESS; -} - -int32_t schUpdateTaskCandidateAddr(SSchJob *pJob, SSchTask *pTask, SEpSet* pEpSet) { - if (NULL == pTask->candidateAddrs || 1 != taosArrayGetSize(pTask->candidateAddrs)) { - SCH_TASK_ELOG("not able to update cndidate addr, addr num %d", (int32_t)(pTask->candidateAddrs ? taosArrayGetSize(pTask->candidateAddrs): 0)); - SCH_ERR_RET(TSDB_CODE_APP_ERROR); - } - - SQueryNodeAddr* pAddr = taosArrayGet(pTask->candidateAddrs, 0); - - SEp* pOld = &pAddr->epSet.eps[pAddr->epSet.inUse]; - SEp* pNew = &pEpSet->eps[pEpSet->inUse]; - - SCH_TASK_DLOG("update task ep from %s:%d to %s:%d", pOld->fqdn, pOld->port, pNew->fqdn, pNew->port); - - memcpy(&pAddr->epSet, pEpSet, sizeof(pAddr->epSet)); - - return TSDB_CODE_SUCCESS; -} - - -int32_t schRemoveTaskFromExecList(SSchJob *pJob, SSchTask *pTask) { - int32_t code = taosHashRemove(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId)); - if (code) { - SCH_TASK_ELOG("task failed to rm from execTask list, code:%x", code); - SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR); - } - - return TSDB_CODE_SUCCESS; -} - - -int32_t schPushTaskToExecList(SSchJob *pJob, SSchTask *pTask) { - int32_t code = taosHashPut(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId), &pTask, POINTER_BYTES); - if (0 != code) { - if (HASH_NODE_EXIST(code)) { - SCH_TASK_ELOG("task already in execTask list, code:%x", code); - SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR); - } - - SCH_TASK_ELOG("taosHashPut task to execTask list failed, errno:%d", errno); - SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); - } - - SCH_TASK_DLOG("task added to execTask list, numOfTasks:%d", taosHashGetSize(pJob->execTasks)); - - return TSDB_CODE_SUCCESS; -} - -/* -int32_t schMoveTaskToSuccList(SSchJob *pJob, SSchTask *pTask, bool *moved) { - if (0 != taosHashRemove(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId))) { - SCH_TASK_WLOG("remove task from execTask list failed, may not exist, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); - } else { - SCH_TASK_DLOG("task removed from execTask list, numOfTasks:%d", taosHashGetSize(pJob->execTasks)); - } - - int32_t code = taosHashPut(pJob->succTasks, &pTask->taskId, sizeof(pTask->taskId), &pTask, POINTER_BYTES); - if (0 != code) { - if (HASH_NODE_EXIST(code)) { - *moved = true; - SCH_TASK_ELOG("task already in succTask list, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); - SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); - } - - SCH_TASK_ELOG("taosHashPut task to succTask list failed, errno:%d", errno); - SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); - } - - *moved = true; - - SCH_TASK_DLOG("task moved to succTask list, numOfTasks:%d", taosHashGetSize(pJob->succTasks)); - - return TSDB_CODE_SUCCESS; -} - -int32_t schMoveTaskToFailList(SSchJob *pJob, SSchTask *pTask, bool *moved) { - *moved = false; - - if (0 != taosHashRemove(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId))) { - SCH_TASK_WLOG("remove task from execTask list failed, may not exist, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); - } - - int32_t code = taosHashPut(pJob->failTasks, &pTask->taskId, sizeof(pTask->taskId), &pTask, POINTER_BYTES); - if (0 != code) { - if (HASH_NODE_EXIST(code)) { - *moved = true; - - SCH_TASK_WLOG("task already in failTask list, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); - SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); - } - - SCH_TASK_ELOG("taosHashPut task to failTask list failed, errno:%d", errno); - SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); - } - - *moved = true; - - SCH_TASK_DLOG("task moved to failTask list, numOfTasks:%d", taosHashGetSize(pJob->failTasks)); - - return TSDB_CODE_SUCCESS; -} - -int32_t schMoveTaskToExecList(SSchJob *pJob, SSchTask *pTask, bool *moved) { - if (0 != taosHashRemove(pJob->succTasks, &pTask->taskId, sizeof(pTask->taskId))) { - SCH_TASK_WLOG("remove task from succTask list failed, may not exist, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); - } - - int32_t code = taosHashPut(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId), &pTask, POINTER_BYTES); - if (0 != code) { - if (HASH_NODE_EXIST(code)) { - *moved = true; - - SCH_TASK_ELOG("task already in execTask list, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); - SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); - } - - SCH_TASK_ELOG("taosHashPut task to execTask list failed, errno:%d", errno); - SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); - } - - *moved = true; - - SCH_TASK_DLOG("task moved to execTask list, numOfTasks:%d", taosHashGetSize(pJob->execTasks)); - - return TSDB_CODE_SUCCESS; -} -*/ - -int32_t schTaskCheckSetRetry(SSchJob *pJob, SSchTask *pTask, int32_t errCode, bool *needRetry) { - if (TSDB_CODE_SCH_TIMEOUT_ERROR == errCode) { - pTask->maxExecTimes++; - if (pTask->timeoutUsec < SCH_MAX_TASK_TIMEOUT_USEC) { - pTask->timeoutUsec *= 2; - if (pTask->timeoutUsec > SCH_MAX_TASK_TIMEOUT_USEC) { - pTask->timeoutUsec = SCH_MAX_TASK_TIMEOUT_USEC; - } - } - } - - if ((pTask->execId + 1) >= pTask->maxExecTimes) { - *needRetry = false; - SCH_TASK_DLOG("task no more retry since reach max try times, execId:%d", pTask->execId); - return TSDB_CODE_SUCCESS; - } - - if (!SCH_NEED_RETRY(pTask->lastMsgType, errCode)) { - *needRetry = false; - SCH_TASK_DLOG("task no more retry cause of errCode, errCode:%x - %s", errCode, tstrerror(errCode)); - return TSDB_CODE_SUCCESS; - } - - if (SCH_IS_DATA_SRC_TASK(pTask)) { - if ((pTask->execId + 1) >= SCH_TASK_NUM_OF_EPS(&pTask->plan->execNode)) { - *needRetry = false; - SCH_TASK_DLOG("task no more retry since all ep tried, execId:%d, epNum:%d", pTask->execId, - SCH_TASK_NUM_OF_EPS(&pTask->plan->execNode)); - return TSDB_CODE_SUCCESS; - } - } else { - int32_t candidateNum = taosArrayGetSize(pTask->candidateAddrs); - - if ((pTask->candidateIdx + 1) >= candidateNum && (TSDB_CODE_SCH_TIMEOUT_ERROR != errCode)) { - *needRetry = false; - SCH_TASK_DLOG("task no more retry since all candiates tried, candidateIdx:%d, candidateNum:%d", - pTask->candidateIdx, candidateNum); - return TSDB_CODE_SUCCESS; - } - } - - *needRetry = true; - SCH_TASK_DLOG("task need the %dth retry, errCode:%x - %s", pTask->execId + 1, errCode, tstrerror(errCode)); - - return TSDB_CODE_SUCCESS; -} - -int32_t schHandleTaskRetry(SSchJob *pJob, SSchTask *pTask) { - atomic_sub_fetch_32(&pTask->level->taskLaunchedNum, 1); - - SCH_ERR_RET(schRemoveTaskFromExecList(pJob, pTask)); - SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_NOT_START); - - if (SCH_TASK_NEED_FLOW_CTRL(pJob, pTask)) { - SCH_ERR_RET(schLaunchTasksInFlowCtrlList(pJob, pTask)); - } - - schDeregisterTaskHb(pJob, pTask); - - if (SCH_IS_DATA_SRC_TASK(pTask)) { - SCH_SWITCH_EPSET(&pTask->plan->execNode); - } else { - int32_t candidateNum = taosArrayGetSize(pTask->candidateAddrs); - if (++pTask->candidateIdx >= candidateNum) { - pTask->candidateIdx = 0; - } - } - - SCH_ERR_RET(schLaunchTask(pJob, pTask)); - - return TSDB_CODE_SUCCESS; -} int32_t schSetJobQueryRes(SSchJob* pJob, SQueryResult* pRes) { pRes->code = atomic_load_32(&pJob->errCode); @@ -893,7 +519,7 @@ int32_t schSetJobQueryRes(SSchJob* pJob, SQueryResult* pRes) { int32_t schSetJobFetchRes(SSchJob* pJob, void** pData) { int32_t code = 0; if (pJob->resData && ((SRetrieveTableRsp *)pJob->resData)->completed) { - SCH_ERR_RET(schUpdateJobStatus(pJob, JOB_TASK_STATUS_SUCCEED)); + SCH_ERR_RET(schUpdateJobStatus(pJob, JOB_TASK_STATUS_SUCC)); } while (true) { @@ -989,19 +615,19 @@ int32_t schProcessOnJobFailureImpl(SSchJob *pJob, int32_t status, int32_t errCod // Note: no more task error processing, handled in function internal int32_t schProcessOnJobFailure(SSchJob *pJob, int32_t errCode) { - SCH_RET(schProcessOnJobFailureImpl(pJob, JOB_TASK_STATUS_FAILED, errCode)); + SCH_RET(schProcessOnJobFailureImpl(pJob, JOB_TASK_STATUS_FAIL, errCode)); } // Note: no more error processing, handled in function internal int32_t schProcessOnJobDropped(SSchJob *pJob, int32_t errCode) { - SCH_RET(schProcessOnJobFailureImpl(pJob, JOB_TASK_STATUS_DROPPING, errCode)); + SCH_RET(schProcessOnJobFailureImpl(pJob, JOB_TASK_STATUS_DROP, errCode)); } // Note: no more task error processing, handled in function internal int32_t schProcessOnJobPartialSuccess(SSchJob *pJob) { int32_t code = 0; - SCH_ERR_RET(schUpdateJobStatus(pJob, JOB_TASK_STATUS_PARTIAL_SUCCEED)); + SCH_ERR_RET(schUpdateJobStatus(pJob, JOB_TASK_STATUS_PART_SUCC)); schPostJobRes(pJob, SCH_OP_EXEC); @@ -1016,65 +642,21 @@ void schProcessOnDataFetched(SSchJob *pJob) { schPostJobRes(pJob, SCH_OP_FETCH); } -// Note: no more task error processing, handled in function internal -int32_t schProcessOnTaskFailure(SSchJob *pJob, SSchTask *pTask, int32_t errCode) { - int8_t status = 0; +int32_t schProcessOnExplainDone(SSchJob *pJob, SSchTask *pTask, SRetrieveTableRsp *pRsp) { + SCH_TASK_DLOG("got explain rsp, rows:%d, complete:%d", htonl(pRsp->numOfRows), pRsp->completed); - if (errCode == TSDB_CODE_SCH_TIMEOUT_ERROR) { - SCH_LOG_TASK_WAIT_TS(pTask); - } else { - SCH_LOG_TASK_END_TS(pTask); - } - - if (schJobNeedToStop(pJob, &status)) { - SCH_TASK_DLOG("task failed not processed cause of job status, job status:%s", jobTaskStatusStr(status)); - SCH_RET(atomic_load_32(&pJob->errCode)); - } + atomic_store_32(&pJob->resNumOfRows, htonl(pRsp->numOfRows)); + atomic_store_ptr(&pJob->resData, pRsp); - bool needRetry = false; - bool moved = false; - int32_t taskDone = 0; - int32_t code = 0; + SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_SUCC); - SCH_TASK_DLOG("taskOnFailure, code:%s", tstrerror(errCode)); + schProcessOnDataFetched(pJob); - SCH_ERR_JRET(schTaskCheckSetRetry(pJob, pTask, errCode, &needRetry)); - - if (!needRetry) { - SCH_TASK_ELOG("task failed and no more retry, code:%s", tstrerror(errCode)); - - if (SCH_GET_TASK_STATUS(pTask) != JOB_TASK_STATUS_EXECUTING) { - SCH_TASK_ELOG("task not in executing list, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); - SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR); - } - - SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_FAILED); - - if (SCH_IS_WAIT_ALL_JOB(pJob)) { - SCH_LOCK(SCH_WRITE, &pTask->level->lock); - pTask->level->taskFailed++; - taskDone = pTask->level->taskSucceed + pTask->level->taskFailed; - SCH_UNLOCK(SCH_WRITE, &pTask->level->lock); - - schUpdateJobErrCode(pJob, errCode); - - if (taskDone < pTask->level->taskNum) { - SCH_TASK_DLOG("need to wait other tasks, doneNum:%d, allNum:%d", taskDone, pTask->level->taskNum); - SCH_RET(errCode); - } - } - } else { - SCH_ERR_JRET(schHandleTaskRetry(pJob, pTask)); - - return TSDB_CODE_SUCCESS; - } - -_return: - - SCH_RET(schProcessOnJobFailure(pJob, errCode)); + return TSDB_CODE_SUCCESS; } -int32_t schLaunchNextLevelTasks(SSchJob *pJob, SSchTask *pTask) { + +int32_t schLaunchJobLowerLevel(SSchJob *pJob, SSchTask *pTask) { if (!SCH_IS_QUERY_JOB(pJob)) { return TSDB_CODE_SUCCESS; } @@ -1099,217 +681,6 @@ int32_t schLaunchNextLevelTasks(SSchJob *pJob, SSchTask *pTask) { return TSDB_CODE_SUCCESS; } - -// Note: no more task error processing, handled in function internal -int32_t schProcessOnTaskSuccess(SSchJob *pJob, SSchTask *pTask) { - bool moved = false; - int32_t code = 0; - - SCH_TASK_DLOG("taskOnSuccess, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); - - SCH_LOG_TASK_END_TS(pTask); - - SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_PARTIAL_SUCCEED); - - SCH_ERR_JRET(schRecordTaskSucceedNode(pJob, pTask)); - - SCH_ERR_JRET(schLaunchTasksInFlowCtrlList(pJob, pTask)); - - int32_t parentNum = pTask->parents ? (int32_t)taosArrayGetSize(pTask->parents) : 0; - if (parentNum == 0) { - int32_t taskDone = 0; - if (SCH_IS_WAIT_ALL_JOB(pJob)) { - SCH_LOCK(SCH_WRITE, &pTask->level->lock); - pTask->level->taskSucceed++; - taskDone = pTask->level->taskSucceed + pTask->level->taskFailed; - SCH_UNLOCK(SCH_WRITE, &pTask->level->lock); - - if (taskDone < pTask->level->taskNum) { - SCH_TASK_DLOG("wait all tasks, done:%d, all:%d", taskDone, pTask->level->taskNum); - return TSDB_CODE_SUCCESS; - } else if (taskDone > pTask->level->taskNum) { - SCH_TASK_ELOG("taskDone number invalid, done:%d, total:%d", taskDone, pTask->level->taskNum); - } - - if (pTask->level->taskFailed > 0) { - SCH_RET(schProcessOnJobFailure(pJob, 0)); - } else { - SCH_RET(schProcessOnJobPartialSuccess(pJob)); - } - } else { - pJob->resNode = pTask->succeedAddr; - } - - pJob->fetchTask = pTask; - - SCH_RET(schProcessOnJobPartialSuccess(pJob)); - } - - /* - if (SCH_IS_DATA_SRC_TASK(task) && job->dataSrcEps.numOfEps < SCH_MAX_CANDIDATE_EP_NUM) { - strncpy(job->dataSrcEps.fqdn[job->dataSrcEps.numOfEps], task->execAddr.fqdn, sizeof(task->execAddr.fqdn)); - job->dataSrcEps.port[job->dataSrcEps.numOfEps] = task->execAddr.port; - - ++job->dataSrcEps.numOfEps; - } - */ - - for (int32_t i = 0; i < parentNum; ++i) { - SSchTask *parent = *(SSchTask **)taosArrayGet(pTask->parents, i); - int32_t readyNum = atomic_add_fetch_32(&parent->childReady, 1); - - SCH_LOCK(SCH_WRITE, &parent->lock); - SDownstreamSourceNode source = {.type = QUERY_NODE_DOWNSTREAM_SOURCE, - .taskId = pTask->taskId, - .schedId = schMgmt.sId, - .execId = pTask->execId, - .addr = pTask->succeedAddr}; - qSetSubplanExecutionNode(parent->plan, pTask->plan->id.groupId, &source); - SCH_UNLOCK(SCH_WRITE, &parent->lock); - - if (SCH_TASK_READY_FOR_LAUNCH(readyNum, parent)) { - SCH_TASK_DLOG("all %d children task done, start to launch parent task 0x%" PRIx64, readyNum, parent->taskId); - SCH_ERR_RET(schLaunchTask(pJob, parent)); - } - } - - SCH_ERR_RET(schLaunchNextLevelTasks(pJob, pTask)); - - return TSDB_CODE_SUCCESS; - -_return: - - SCH_RET(schProcessOnJobFailure(pJob, code)); -} - -// Note: no more error processing, handled in function internal -int32_t schFetchFromRemote(SSchJob *pJob) { - int32_t code = 0; - - void *resData = atomic_load_ptr(&pJob->resData); - if (resData) { - SCH_JOB_DLOG("res already fetched, res:%p", resData); - return TSDB_CODE_SUCCESS; - } - - SCH_ERR_JRET(schBuildAndSendMsg(pJob, pJob->fetchTask, &pJob->resNode, TDMT_SCH_FETCH)); - - return TSDB_CODE_SUCCESS; - -_return: - - SCH_RET(schProcessOnTaskFailure(pJob, pJob->fetchTask, code)); -} - -int32_t schProcessOnExplainDone(SSchJob *pJob, SSchTask *pTask, SRetrieveTableRsp *pRsp) { - SCH_TASK_DLOG("got explain rsp, rows:%d, complete:%d", htonl(pRsp->numOfRows), pRsp->completed); - - atomic_store_32(&pJob->resNumOfRows, htonl(pRsp->numOfRows)); - atomic_store_ptr(&pJob->resData, pRsp); - - SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_SUCCEED); - - schProcessOnDataFetched(pJob); - - return TSDB_CODE_SUCCESS; -} - -void schDropTaskOnExecNode(SSchJob *pJob, SSchTask *pTask) { - if (NULL == pTask->execNodes) { - SCH_TASK_DLOG("no exec address, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); - return; - } - - int32_t size = (int32_t)taosHashGetSize(pTask->execNodes); - - if (size <= 0) { - SCH_TASK_DLOG("task has no execNodes, no need to drop it, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); - return; - } - - SSchNodeInfo *nodeInfo = taosHashIterate(pTask->execNodes, NULL); - while (nodeInfo) { - SCH_SET_TASK_HANDLE(pTask, nodeInfo->handle); - - schBuildAndSendMsg(pJob, pTask, &nodeInfo->addr, TDMT_SCH_DROP_TASK); - - nodeInfo = taosHashIterate(pTask->execNodes, nodeInfo); - } - - SCH_TASK_DLOG("task has been dropped on %d exec nodes", size); -} - - -int32_t schRescheduleTask(SSchJob *pJob, SSchTask *pTask) { - if (SCH_IS_DATA_SRC_QRY_TASK(pTask)) { - return TSDB_CODE_SUCCESS; - } - - SCH_LOCK_TASK(pTask); - if (SCH_TASK_TIMEOUT(pTask) && JOB_TASK_STATUS_EXECUTING == pTask->status && - pJob->fetchTask != pTask && taosArrayGetSize(pTask->candidateAddrs) > 1) { - SCH_TASK_DLOG("task execId %d will be rescheduled now", pTask->execId); - schDropTaskOnExecNode(pJob, pTask); - taosHashClear(pTask->execNodes); - schProcessOnTaskFailure(pJob, pTask, TSDB_CODE_SCH_TIMEOUT_ERROR); - } - SCH_UNLOCK_TASK(pTask); - - return TSDB_CODE_SUCCESS; -} - -int32_t schProcessOnTaskStatusRsp(SQueryNodeEpId* pEpId, SArray* pStatusList) { - int32_t taskNum = (int32_t)taosArrayGetSize(pStatusList); - SSchTask *pTask = NULL; - - qDebug("%d task status in hb rsp from nodeId:%d, fqdn:%s, port:%d", taskNum, pEpId->nodeId, pEpId->ep.fqdn, pEpId->ep.port); - - for (int32_t i = 0; i < taskNum; ++i) { - STaskStatus *taskStatus = taosArrayGet(pStatusList, i); - - qDebug("QID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d task status in server: %s", - taskStatus->queryId, taskStatus->taskId, taskStatus->execId, jobTaskStatusStr(taskStatus->status)); - - SSchJob *pJob = schAcquireJob(taskStatus->refId); - if (NULL == pJob) { - qWarn("job not found, refId:0x%" PRIx64 ",QID:0x%" PRIx64 ",TID:0x%" PRIx64, taskStatus->refId, - taskStatus->queryId, taskStatus->taskId); - // TODO DROP TASK FROM SERVER!!!! - continue; - } - - pTask = NULL; - schGetTaskInJob(pJob, taskStatus->taskId, &pTask); - if (NULL == pTask) { - // TODO DROP TASK FROM SERVER!!!! - schReleaseJob(taskStatus->refId); - continue; - } - - if (taskStatus->execId != pTask->execId) { - // TODO DROP TASK FROM SERVER!!!! - SCH_TASK_DLOG("EID %d in hb rsp mis-match", taskStatus->execId); - schReleaseJob(taskStatus->refId); - continue; - } - - if (taskStatus->status == JOB_TASK_STATUS_FAILED) { - // RECORD AND HANDLE ERROR!!!! - schReleaseJob(taskStatus->refId); - continue; - } - - if (taskStatus->status == JOB_TASK_STATUS_NOT_START) { - schRescheduleTask(pJob, pTask); - } - - schReleaseJob(taskStatus->refId); - } - - return TSDB_CODE_SUCCESS; -} - - int32_t schSaveJobQueryRes(SSchJob *pJob, SQueryTableRsp *rsp) { if (rsp->tbFName[0]) { if (NULL == pJob->execRes.res) { @@ -1331,22 +702,6 @@ int32_t schSaveJobQueryRes(SSchJob *pJob, SQueryTableRsp *rsp) { return TSDB_CODE_SUCCESS; } -int32_t schGetTaskFromList(SHashObj *pTaskList, uint64_t taskId, SSchTask **pTask) { - int32_t s = taosHashGetSize(pTaskList); - if (s <= 0) { - return TSDB_CODE_SUCCESS; - } - - SSchTask **task = taosHashGet(pTaskList, &taskId, sizeof(taskId)); - if (NULL == task || NULL == (*task)) { - return TSDB_CODE_SUCCESS; - } - - *pTask = *task; - - return TSDB_CODE_SUCCESS; -} - int32_t schGetTaskInJob(SSchJob *pJob, uint64_t taskId, SSchTask **pTask) { schGetTaskFromList(pJob->taskList, taskId, pTask); if (NULL == *pTask) { @@ -1357,113 +712,20 @@ int32_t schGetTaskInJob(SSchJob *pJob, uint64_t taskId, SSchTask **pTask) { return TSDB_CODE_SUCCESS; } -int32_t schLaunchTaskImpl(SSchJob *pJob, SSchTask *pTask) { - int8_t status = 0; - int32_t code = 0; - - atomic_add_fetch_32(&pTask->level->taskLaunchedNum, 1); - pTask->execId++; - - SCH_TASK_DLOG("start to launch task's %dth exec", pTask->execId); - - SCH_LOG_TASK_START_TS(pTask); - - if (schJobNeedToStop(pJob, &status)) { - SCH_TASK_DLOG("no need to launch task cause of job status, job status:%s", jobTaskStatusStr(status)); - - SCH_RET(atomic_load_32(&pJob->errCode)); - } - - // NOTE: race condition: the task should be put into the hash table before send msg to server - if (SCH_GET_TASK_STATUS(pTask) != JOB_TASK_STATUS_EXECUTING) { - SCH_ERR_RET(schPushTaskToExecList(pJob, pTask)); - SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_EXECUTING); - } - - SSubplan *plan = pTask->plan; - - if (NULL == pTask->msg) { // TODO add more detailed reason for failure - code = qSubPlanToString(plan, &pTask->msg, &pTask->msgLen); - if (TSDB_CODE_SUCCESS != code) { - SCH_TASK_ELOG("failed to create physical plan, code:%s, msg:%p, len:%d", tstrerror(code), pTask->msg, - pTask->msgLen); - SCH_ERR_RET(code); - } else { - SCH_TASK_DLOGL("physical plan len:%d, %s", pTask->msgLen, pTask->msg); - } - } - - SCH_ERR_RET(schSetTaskCandidateAddrs(pJob, pTask)); - - if (SCH_IS_QUERY_JOB(pJob)) { - SCH_ERR_RET(schEnsureHbConnection(pJob, pTask)); - } - - SCH_ERR_RET(schBuildAndSendMsg(pJob, pTask, NULL, plan->msgType)); - - return TSDB_CODE_SUCCESS; -} - -// Note: no more error processing, handled in function internal -int32_t schLaunchTask(SSchJob *pJob, SSchTask *pTask) { - bool enough = false; - int32_t code = 0; - - SCH_SET_TASK_HANDLE(pTask, NULL); - - if (SCH_TASK_NEED_FLOW_CTRL(pJob, pTask)) { - SCH_ERR_JRET(schCheckIncTaskFlowQuota(pJob, pTask, &enough)); - - if (enough) { - SCH_ERR_JRET(schLaunchTaskImpl(pJob, pTask)); - } - } else { - SCH_ERR_JRET(schLaunchTaskImpl(pJob, pTask)); - } - - return TSDB_CODE_SUCCESS; - -_return: - - SCH_RET(schProcessOnTaskFailure(pJob, pTask, code)); -} - -int32_t schLaunchLevelTasks(SSchJob *pJob, SSchLevel *level) { - for (int32_t i = 0; i < level->taskNum; ++i) { - SSchTask *pTask = taosArrayGet(level->subTasks, i); - - SCH_ERR_RET(schLaunchTask(pJob, pTask)); - } - - return TSDB_CODE_SUCCESS; -} int32_t schLaunchJob(SSchJob *pJob) { - SSchLevel *level = taosArrayGet(pJob->levels, pJob->levelIdx); - - SCH_ERR_RET(schChkJobNeedFlowCtrl(pJob, level)); - - SCH_ERR_RET(schLaunchLevelTasks(pJob, level)); + if (EXPLAIN_MODE_STATIC == pJob->attr.explainMode) { + SCH_ERR_RET(qExecStaticExplain(pJob->pDag, (SRetrieveTableRsp **)&pJob->resData)); + SCH_ERR_RET(schJobStatusEnter(&pJob, JOB_TASK_STATUS_PART_SUCC, NULL)); + } else { + SSchLevel *level = taosArrayGet(pJob->levels, pJob->levelIdx); + SCH_ERR_RET(schLaunchLevelTasks(pJob, level)); + } return TSDB_CODE_SUCCESS; } -void schDropTaskInHashList(SSchJob *pJob, SHashObj *list) { - if (!SCH_IS_NEED_DROP_JOB(pJob)) { - return; - } - - void *pIter = taosHashIterate(list, NULL); - while (pIter) { - SSchTask *pTask = *(SSchTask **)pIter; - - schDropTaskOnExecNode(pJob, pTask); - - pIter = taosHashIterate(list, pIter); - } -} - void schDropJobAllTasks(SSchJob *pJob) { schDropTaskInHashList(pJob, pJob->execTasks); // schDropTaskInHashList(pJob, pJob->succTasks); @@ -1487,7 +749,7 @@ void schFreeJobImpl(void *job) { qDebug("QID:0x%" PRIx64 " begin to free sch job, refId:0x%" PRIx64 ", pointer:%p", queryId, refId, pJob); - if (pJob->status == JOB_TASK_STATUS_EXECUTING) { + if (pJob->status == JOB_TASK_STATUS_EXEC) { schCancelJob(pJob); } @@ -1535,88 +797,11 @@ void schFreeJobImpl(void *job) { qDebug("QID:0x%" PRIx64 " sch job freed, refId:0x%" PRIx64 ", pointer:%p", queryId, refId, pJob); } -int32_t schLaunchStaticExplainJob(SSchedulerReq *pReq, SSchJob *pJob, bool sync) { - qDebug("QID:0x%" PRIx64 " job started", pReq->pDag->queryId); - - int32_t code = 0; -/* - SSchJob *pJob = taosMemoryCalloc(1, sizeof(SSchJob)); - if (NULL == pJob) { - qError("QID:0x%" PRIx64 " calloc %d failed", pReq->pDag->queryId, (int32_t)sizeof(SSchJob)); - code = TSDB_CODE_QRY_OUT_OF_MEMORY; - pReq->fp(NULL, pReq->cbParam, code); - SCH_ERR_RET(code); - } - - pJob->sql = pReq->sql; - pJob->reqKilled = pReq->reqKilled; - pJob->pDag = pReq->pDag; - pJob->attr.queryJob = true; - pJob->attr.explainMode = pReq->pDag->explainInfo.mode; - pJob->queryId = pReq->pDag->queryId; - pJob->userRes.execFp = pReq->fp; - pJob->userRes.userParam = pReq->cbParam; - - schUpdateJobStatus(pJob, JOB_TASK_STATUS_NOT_START); - - code = schBeginOperation(pJob, SCH_OP_EXEC, sync); - if (code) { - pReq->fp(NULL, pReq->cbParam, code); - schFreeJobImpl(pJob); - SCH_ERR_RET(code); - } -*/ - - SCH_ERR_JRET(qExecStaticExplain(pReq->pDag, (SRetrieveTableRsp **)&pJob->resData)); - -/* - int64_t refId = taosAddRef(schMgmt.jobRef, pJob); - if (refId < 0) { - SCH_JOB_ELOG("taosAddRef job failed, error:%s", tstrerror(terrno)); - SCH_ERR_JRET(terrno); - } - - if (NULL == schAcquireJob(refId)) { - SCH_JOB_ELOG("schAcquireJob job failed, refId:0x%" PRIx64, refId); - SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR); - } - - pJob->refId = refId; - - SCH_JOB_DLOG("job refId:0x%" PRIx64, pJob->refId); -*/ - - pJob->status = JOB_TASK_STATUS_PARTIAL_SUCCEED; - - SCH_JOB_DLOG("job exec done, job status:%s", SCH_GET_JOB_STATUS_STR(pJob)); - - if (!sync) { - schPostJobRes(pJob, SCH_OP_EXEC); - } else { - schEndOperation(pJob); - } - -// schReleaseJob(pJob->refId); - - SCH_RET(code); - -_return: - - schEndOperation(pJob); - if (!sync) { - pReq->execFp(NULL, pReq->execParam, code); - } - - schFreeJobImpl(pJob); - - SCH_RET(code); -} - -int32_t schFetchRows(SSchJob *pJob) { +int32_t schJobFetchRows(SSchJob *pJob) { int32_t code = 0; if (!(pJob->attr.explainMode == EXPLAIN_MODE_STATIC)) { - SCH_ERR_JRET(schFetchFromRemote(pJob)); + SCH_ERR_JRET(schLaunchFetchTask(pJob)); tsem_wait(&pJob->rspSem); } @@ -1629,7 +814,7 @@ _return: SCH_RET(code); } -int32_t schAsyncFetchRows(SSchJob *pJob) { +int32_t schJobFetchRowsA(SSchJob *pJob) { int32_t code = 0; if (pJob->attr.explainMode == EXPLAIN_MODE_STATIC) { @@ -1637,129 +822,55 @@ int32_t schAsyncFetchRows(SSchJob *pJob) { return TSDB_CODE_SUCCESS; } - SCH_ERR_RET(schFetchFromRemote(pJob)); + SCH_ERR_RET(schLaunchFetchTask(pJob)); return TSDB_CODE_SUCCESS; } - -int32_t schExecJobImpl(SSchedulerReq *pReq, SSchJob *pJob, bool sync) { - int32_t code = 0; - +int32_t schExecJob(SSchJob *pJob, SSchedulerReq *pReq) { + int32_t code = 0; qDebug("QID:0x%" PRIx64 " sch job refId 0x%"PRIx64 " started", pReq->pDag->queryId, pJob->refId); - SCH_ERR_JRET(schBeginOperation(pJob, SCH_OP_EXEC, sync)); - - if (EXPLAIN_MODE_STATIC == pReq->pDag->explainInfo.mode) { - code = schLaunchStaticExplainJob(pReq, pJob, sync); - } else { - code = schLaunchJob(pJob); - if (sync) { - SCH_JOB_DLOG("will wait for rsp now, job status:%s", SCH_GET_JOB_STATUS_STR(pJob)); - tsem_wait(&pJob->rspSem); - - schEndOperation(pJob); - } else if (code) { - schPostJobRes(pJob, SCH_OP_EXEC); - } + SCH_ERR_JRET(schLaunchJob(pJob)); + + if (pReq->syncReq) { + SCH_JOB_DLOG("sync wait for rsp now, job status:%s", SCH_GET_JOB_STATUS_STR(pJob)); + tsem_wait(&pJob->rspSem); } SCH_JOB_DLOG("job exec done, job status:%s, jobId:0x%" PRIx64, SCH_GET_JOB_STATUS_STR(pJob), pJob->refId); - SCH_RET(code); - -_return: - - if (!sync) { - pReq->execFp(NULL, pReq->execParam, code); - } - - SCH_RET(code); -} - -int32_t schDoTaskRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf* pData, int32_t rspCode) { - int32_t code = 0; - - if ((pTask->execId + 1) >= pTask->maxExecTimes) { - SCH_TASK_DLOG("task no more retry since reach max try times, execId:%d", pTask->execId); - schProcessOnJobFailure(pJob, rspCode); - return TSDB_CODE_SUCCESS; - } - - SCH_TASK_DLOG("task will be redirected now, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); - - schDropTaskOnExecNode(pJob, pTask); - taosHashClear(pTask->execNodes); - SCH_ERR_JRET(schRemoveTaskFromExecList(pJob, pTask)); - schDeregisterTaskHb(pJob, pTask); - atomic_sub_fetch_32(&pTask->level->taskLaunchedNum, 1); - taosMemoryFreeClear(pTask->msg); - pTask->msgLen = 0; - pTask->lastMsgType = 0; - memset(&pTask->succeedAddr, 0, sizeof(pTask->succeedAddr)); - - if (SCH_IS_DATA_SRC_QRY_TASK(pTask)) { - if (pData) { - SCH_ERR_JRET(schUpdateTaskCandidateAddr(pJob, pTask, pData->pEpSet)); - } - - if (SCH_TASK_NEED_FLOW_CTRL(pJob, pTask)) { - if (JOB_TASK_STATUS_EXECUTING == SCH_GET_TASK_STATUS(pTask)) { - SCH_ERR_JRET(schLaunchTasksInFlowCtrlList(pJob, pTask)); - } - } - - SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_NOT_START); - - SCH_ERR_JRET(schLaunchTask(pJob, pTask)); - - return TSDB_CODE_SUCCESS; - } - - - // merge plan - - pTask->childReady = 0; - - qClearSubplanExecutionNode(pTask->plan); - - SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_NOT_START); - - int32_t childrenNum = taosArrayGetSize(pTask->children); - for (int32_t i = 0; i < childrenNum; ++i) { - SSchTask* pChild = taosArrayGetP(pTask->children, i); - SCH_LOCK_TASK(pChild); - schDoTaskRedirect(pJob, pChild, NULL, rspCode); - SCH_UNLOCK_TASK(pChild); - } - return TSDB_CODE_SUCCESS; _return: - - code = schProcessOnTaskFailure(pJob, pTask, code); - - SCH_RET(code); + + SCH_RET(schProcessOnJobFailure(pJob, code)); } -int32_t schHandleRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf* pData, int32_t rspCode) { - int32_t code = 0; +int32_t schJobStatusEnter(SSchJob** job, int32_t status, void* param) { + SCH_ERR_RET(schUpdateJobStatus(*job, status)); - if (SCH_IS_DATA_SRC_QRY_TASK(pTask)) { - if (NULL == pData->pEpSet) { - SCH_TASK_ELOG("no epset updated while got error %s", tstrerror(rspCode)); - SCH_ERR_JRET(rspCode); + switch (status) { + case JOB_TASK_STATUS_INIT: + SCH_RET(schInitJob(job, param)); + case JOB_TASK_STATUS_EXEC: + SCH_RET(schExecJob(job, param)); + case JOB_TASK_STATUS_PART_SUCC: + default: { + SSchJob* pJob = *job; + SCH_JOB_ELOG("enter unknown job status %d", status); + SCH_RET(TSDB_CODE_SCH_STATUS_ERROR); } } - SCH_RET(schDoTaskRedirect(pJob, pTask, pData, rspCode)); + return TSDB_CODE_SUCCESS; +} -_return: - - schProcessOnTaskFailure(pJob, pTask, code); - - SCH_RET(code); +int32_t schJobStatusEvent() { + + schEndOperation(pJob); } + diff --git a/source/libs/scheduler/src/schRemote.c b/source/libs/scheduler/src/schRemote.c index 32f151f8af..479d3665a4 100644 --- a/source/libs/scheduler/src/schRemote.c +++ b/source/libs/scheduler/src/schRemote.c @@ -37,7 +37,7 @@ int32_t schValidateReceivedMsgType(SSchJob *pJob, SSchTask *pTask, int32_t msgTy TMSG_INFO(msgType)); } - if (taskStatus != JOB_TASK_STATUS_EXECUTING && taskStatus != JOB_TASK_STATUS_PARTIAL_SUCCEED) { + if (taskStatus != JOB_TASK_STATUS_EXEC && taskStatus != JOB_TASK_STATUS_PART_SUCC) { SCH_TASK_DLOG("rsp msg conflicted with task status, status:%s, rspType:%s", jobTaskStatusStr(taskStatus), TMSG_INFO(msgType)); } @@ -51,7 +51,7 @@ int32_t schValidateReceivedMsgType(SSchJob *pJob, SSchTask *pTask, int32_t msgTy SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); } - if (taskStatus != JOB_TASK_STATUS_EXECUTING && taskStatus != JOB_TASK_STATUS_PARTIAL_SUCCEED) { + if (taskStatus != JOB_TASK_STATUS_EXEC && taskStatus != JOB_TASK_STATUS_PART_SUCC) { SCH_TASK_ELOG("rsp msg conflicted with task status, status:%s, rspType:%s", jobTaskStatusStr(taskStatus), TMSG_INFO(msgType)); SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); @@ -76,7 +76,7 @@ int32_t schValidateReceivedMsgType(SSchJob *pJob, SSchTask *pTask, int32_t msgTy SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); } - if (taskStatus != JOB_TASK_STATUS_EXECUTING && taskStatus != JOB_TASK_STATUS_PARTIAL_SUCCEED) { + if (taskStatus != JOB_TASK_STATUS_EXEC && taskStatus != JOB_TASK_STATUS_PART_SUCC) { SCH_TASK_ELOG("rsp msg conflicted with task status, status:%s, rspType:%s", jobTaskStatusStr(taskStatus), TMSG_INFO(msgType)); SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); @@ -308,7 +308,7 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, ch return TSDB_CODE_SUCCESS; } - SCH_ERR_JRET(schFetchFromRemote(pJob)); + SCH_ERR_JRET(schLaunchFetchTask(pJob)); taosMemoryFreeClear(msg); @@ -325,7 +325,7 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, ch atomic_add_fetch_32(&pJob->resNumOfRows, htonl(rsp->numOfRows)); if (rsp->completed) { - SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_SUCCEED); + SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_SUCC); } SCH_TASK_DLOG("got fetch rsp, rows:%d, complete:%d", htonl(rsp->numOfRows), rsp->completed); diff --git a/source/libs/scheduler/src/schStatus.c b/source/libs/scheduler/src/schStatus.c new file mode 100644 index 0000000000..a8cac993cf --- /dev/null +++ b/source/libs/scheduler/src/schStatus.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "catalog.h" +#include "command.h" +#include "query.h" +#include "schInt.h" +#include "tmsg.h" +#include "tref.h" +#include "trpc.h" + +SSchStatusFps gSchJobFps[JOB_TASK_STATUS_MAX] = { + {JOB_TASK_STATUS_NULL, schJobStNullEnter, schJobStNullLeave, schJobStNullEvent}, + {JOB_TASK_STATUS_INIT, schJobStNullEnter, schJobStNullLeave, schJobStNullEvent}, + {JOB_TASK_STATUS_EXEC, schJobStNullEnter, schJobStNullLeave, schJobStNullEvent}, + {JOB_TASK_STATUS_PART_SUCC, schJobStNullEnter, schJobStNullLeave, schJobStNullEvent}, + {JOB_TASK_STATUS_SUCC, schJobStNullEnter, schJobStNullLeave, schJobStNullEvent}, + {JOB_TASK_STATUS_FAIL, schJobStNullEnter, schJobStNullLeave, schJobStNullEvent}, + {JOB_TASK_STATUS_DROP, schJobStNullEnter, schJobStNullLeave, schJobStNullEvent}, +}; + +SSchStatusFps gSchTaskFps[JOB_TASK_STATUS_MAX] = { + {JOB_TASK_STATUS_NULL, schTaskStatusNullEnter, schTaskStatusNullLeave, schTaskStatusNullEvent}, + {JOB_TASK_STATUS_INIT, schTaskStatusNullEnter, schTaskStatusNullLeave, schTaskStatusNullEvent}, + {JOB_TASK_STATUS_EXEC, schTaskStatusNullEnter, schTaskStatusNullLeave, schTaskStatusNullEvent}, + {JOB_TASK_STATUS_PART_SUCC, schTaskStatusNullEnter, schTaskStatusNullLeave, schTaskStatusNullEvent}, + {JOB_TASK_STATUS_SUCC, schTaskStatusNullEnter, schTaskStatusNullLeave, schTaskStatusNullEvent}, + {JOB_TASK_STATUS_FAIL, schTaskStatusNullEnter, schTaskStatusNullLeave, schTaskStatusNullEvent}, + {JOB_TASK_STATUS_DROP, schTaskStatusNullEnter, schTaskStatusNullLeave, schTaskStatusNullEvent}, +}; + + + + diff --git a/source/libs/scheduler/src/schTask.c b/source/libs/scheduler/src/schTask.c new file mode 100644 index 0000000000..ccbd1f4615 --- /dev/null +++ b/source/libs/scheduler/src/schTask.c @@ -0,0 +1,843 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "catalog.h" +#include "command.h" +#include "query.h" +#include "schedulerInt.h" +#include "tmsg.h" +#include "tref.h" +#include "trpc.h" + + + +void schFreeTask(SSchJob *pJob, SSchTask *pTask) { + schDeregisterTaskHb(pJob, pTask); + + if (pTask->candidateAddrs) { + taosArrayDestroy(pTask->candidateAddrs); + } + + taosMemoryFreeClear(pTask->msg); + + if (pTask->children) { + taosArrayDestroy(pTask->children); + } + + if (pTask->parents) { + taosArrayDestroy(pTask->parents); + } + + if (pTask->execNodes) { + taosHashCleanup(pTask->execNodes); + } +} + + +int32_t schInitTask(SSchJob *pJob, SSchTask *pTask, SSubplan *pPlan, SSchLevel *pLevel) { + pTask->plan = pPlan; + pTask->level = pLevel; + pTask->execId = -1; + pTask->maxExecTimes = SCH_TASK_MAX_EXEC_TIMES; + pTask->timeoutUsec = SCH_DEFAULT_TASK_TIMEOUT_USEC; + SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_INIT); + pTask->taskId = schGenTaskId(); + pTask->execNodes = taosHashInit(SCH_MAX_CANDIDATE_EP_NUM, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK); + if (NULL == pTask->execNodes) { + SCH_TASK_ELOG("taosHashInit %d execNodes failed", SCH_MAX_CANDIDATE_EP_NUM); + SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + return TSDB_CODE_SUCCESS; +} + +int32_t schRecordTaskSucceedNode(SSchJob *pJob, SSchTask *pTask) { + SQueryNodeAddr *addr = taosArrayGet(pTask->candidateAddrs, pTask->candidateIdx); + if (NULL == addr) { + SCH_TASK_ELOG("taosArrayGet candidate addr failed, idx:%d, size:%d", pTask->candidateIdx, + (int32_t)taosArrayGetSize(pTask->candidateAddrs)); + SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR); + } + + pTask->succeedAddr = *addr; + + return TSDB_CODE_SUCCESS; +} + +int32_t schAppendTaskExecNode(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, int32_t execId) { + SSchNodeInfo nodeInfo = {.addr = *addr, .handle = NULL}; + + if (taosHashPut(pTask->execNodes, &execId, sizeof(execId), &nodeInfo, sizeof(nodeInfo))) { + SCH_TASK_ELOG("taosHashPut nodeInfo to execNodes failed, errno:%d", errno); + SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + SCH_TASK_DLOG("task execNode added, execId:%d", execId); + + return TSDB_CODE_SUCCESS; +} + +int32_t schDropTaskExecNode(SSchJob *pJob, SSchTask *pTask, void *handle, int32_t execId) { + if (NULL == pTask->execNodes) { + return TSDB_CODE_SUCCESS; + } + + if (taosHashRemove(pTask->execNodes, &execId, sizeof(execId))) { + SCH_TASK_ELOG("fail to remove execId %d from execNodeList", execId); + } else { + SCH_TASK_DLOG("execId %d removed from execNodeList", execId); + } + + if (execId != pTask->execId) { // ignore it + SCH_TASK_DLOG("execId %d is not current execId %d", execId, pTask->execId); + SCH_RET(TSDB_CODE_SCH_IGNORE_ERROR); + } + + return TSDB_CODE_SUCCESS; +} + +int32_t schUpdateTaskExecNode(SSchJob *pJob, SSchTask *pTask, void *handle, int32_t execId) { + if (taosHashGetSize(pTask->execNodes) <= 0) { + return TSDB_CODE_SUCCESS; + } + + SSchNodeInfo *nodeInfo = taosHashGet(pTask->execNodes, &execId, sizeof(execId)); + nodeInfo->handle = handle; + + SCH_TASK_DLOG("handle updated to %p for execId %d", handle, execId); + + return TSDB_CODE_SUCCESS; +} + +int32_t schUpdateTaskHandle(SSchJob *pJob, SSchTask *pTask, bool dropExecNode, void *handle, int32_t execId) { + if (dropExecNode) { + SCH_RET(schDropTaskExecNode(pJob, pTask, handle, execId)); + } + + SCH_SET_TASK_HANDLE(pTask, handle); + + schUpdateTaskExecNode(pJob, pTask, handle, execId); + + return TSDB_CODE_SUCCESS; +} + +// Note: no more task error processing, handled in function internal +int32_t schProcessOnTaskFailure(SSchJob *pJob, SSchTask *pTask, int32_t errCode) { + int8_t status = 0; + + if (errCode == TSDB_CODE_SCH_TIMEOUT_ERROR) { + SCH_LOG_TASK_WAIT_TS(pTask); + } else { + SCH_LOG_TASK_END_TS(pTask); + } + + if (schJobNeedToStop(pJob, &status)) { + SCH_TASK_DLOG("task failed not processed cause of job status, job status:%s", jobTaskStatusStr(status)); + SCH_RET(atomic_load_32(&pJob->errCode)); + } + + bool needRetry = false; + bool moved = false; + int32_t taskDone = 0; + int32_t code = 0; + + SCH_TASK_DLOG("taskOnFailure, code:%s", tstrerror(errCode)); + + SCH_ERR_JRET(schTaskCheckSetRetry(pJob, pTask, errCode, &needRetry)); + + if (!needRetry) { + SCH_TASK_ELOG("task failed and no more retry, code:%s", tstrerror(errCode)); + + if (SCH_GET_TASK_STATUS(pTask) != JOB_TASK_STATUS_EXEC) { + SCH_TASK_ELOG("task not in executing list, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); + SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR); + } + + SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_FAIL); + + if (SCH_IS_WAIT_ALL_JOB(pJob)) { + SCH_LOCK(SCH_WRITE, &pTask->level->lock); + pTask->level->taskFailed++; + taskDone = pTask->level->taskSucceed + pTask->level->taskFailed; + SCH_UNLOCK(SCH_WRITE, &pTask->level->lock); + + schUpdateJobErrCode(pJob, errCode); + + if (taskDone < pTask->level->taskNum) { + SCH_TASK_DLOG("need to wait other tasks, doneNum:%d, allNum:%d", taskDone, pTask->level->taskNum); + SCH_RET(errCode); + } + } + } else { + SCH_ERR_JRET(schHandleTaskRetry(pJob, pTask)); + + return TSDB_CODE_SUCCESS; + } + +_return: + + SCH_RET(schProcessOnJobFailure(pJob, errCode)); +} + + + +// Note: no more task error processing, handled in function internal +int32_t schProcessOnTaskSuccess(SSchJob *pJob, SSchTask *pTask) { + bool moved = false; + int32_t code = 0; + + SCH_TASK_DLOG("taskOnSuccess, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); + + SCH_LOG_TASK_END_TS(pTask); + + SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_PART_SUCC); + + SCH_ERR_JRET(schRecordTaskSucceedNode(pJob, pTask)); + + SCH_ERR_JRET(schLaunchTasksInFlowCtrlList(pJob, pTask)); + + int32_t parentNum = pTask->parents ? (int32_t)taosArrayGetSize(pTask->parents) : 0; + if (parentNum == 0) { + int32_t taskDone = 0; + if (SCH_IS_WAIT_ALL_JOB(pJob)) { + SCH_LOCK(SCH_WRITE, &pTask->level->lock); + pTask->level->taskSucceed++; + taskDone = pTask->level->taskSucceed + pTask->level->taskFailed; + SCH_UNLOCK(SCH_WRITE, &pTask->level->lock); + + if (taskDone < pTask->level->taskNum) { + SCH_TASK_DLOG("wait all tasks, done:%d, all:%d", taskDone, pTask->level->taskNum); + return TSDB_CODE_SUCCESS; + } else if (taskDone > pTask->level->taskNum) { + SCH_TASK_ELOG("taskDone number invalid, done:%d, total:%d", taskDone, pTask->level->taskNum); + } + + if (pTask->level->taskFailed > 0) { + SCH_RET(schProcessOnJobFailure(pJob, 0)); + } else { + SCH_RET(schProcessOnJobPartialSuccess(pJob)); + } + } else { + pJob->resNode = pTask->succeedAddr; + } + + pJob->fetchTask = pTask; + + SCH_RET(schProcessOnJobPartialSuccess(pJob)); + } + + /* + if (SCH_IS_DATA_SRC_TASK(task) && job->dataSrcEps.numOfEps < SCH_MAX_CANDIDATE_EP_NUM) { + strncpy(job->dataSrcEps.fqdn[job->dataSrcEps.numOfEps], task->execAddr.fqdn, sizeof(task->execAddr.fqdn)); + job->dataSrcEps.port[job->dataSrcEps.numOfEps] = task->execAddr.port; + + ++job->dataSrcEps.numOfEps; + } + */ + + for (int32_t i = 0; i < parentNum; ++i) { + SSchTask *parent = *(SSchTask **)taosArrayGet(pTask->parents, i); + int32_t readyNum = atomic_add_fetch_32(&parent->childReady, 1); + + SCH_LOCK(SCH_WRITE, &parent->lock); + SDownstreamSourceNode source = {.type = QUERY_NODE_DOWNSTREAM_SOURCE, + .taskId = pTask->taskId, + .schedId = schMgmt.sId, + .execId = pTask->execId, + .addr = pTask->succeedAddr}; + qSetSubplanExecutionNode(parent->plan, pTask->plan->id.groupId, &source); + SCH_UNLOCK(SCH_WRITE, &parent->lock); + + if (SCH_TASK_READY_FOR_LAUNCH(readyNum, parent)) { + SCH_TASK_DLOG("all %d children task done, start to launch parent task 0x%" PRIx64, readyNum, parent->taskId); + SCH_ERR_RET(schLaunchTask(pJob, parent)); + } + } + + SCH_ERR_RET(schLaunchJobLowerLevel(pJob, pTask)); + + return TSDB_CODE_SUCCESS; + +_return: + + SCH_RET(schProcessOnJobFailure(pJob, code)); +} + +int32_t schRescheduleTask(SSchJob *pJob, SSchTask *pTask) { + if (SCH_IS_DATA_SRC_QRY_TASK(pTask)) { + return TSDB_CODE_SUCCESS; + } + + SCH_LOCK_TASK(pTask); + if (SCH_TASK_TIMEOUT(pTask) && JOB_TASK_STATUS_EXEC == pTask->status && + pJob->fetchTask != pTask && taosArrayGetSize(pTask->candidateAddrs) > 1) { + SCH_TASK_DLOG("task execId %d will be rescheduled now", pTask->execId); + schDropTaskOnExecNode(pJob, pTask); + taosHashClear(pTask->execNodes); + schProcessOnTaskFailure(pJob, pTask, TSDB_CODE_SCH_TIMEOUT_ERROR); + } + SCH_UNLOCK_TASK(pTask); + + return TSDB_CODE_SUCCESS; +} + +int32_t schDoTaskRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf* pData, int32_t rspCode) { + int32_t code = 0; + + if ((pTask->execId + 1) >= pTask->maxExecTimes) { + SCH_TASK_DLOG("task no more retry since reach max try times, execId:%d", pTask->execId); + schProcessOnJobFailure(pJob, rspCode); + return TSDB_CODE_SUCCESS; + } + + SCH_TASK_DLOG("task will be redirected now, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); + + schDropTaskOnExecNode(pJob, pTask); + taosHashClear(pTask->execNodes); + SCH_ERR_JRET(schRemoveTaskFromExecList(pJob, pTask)); + schDeregisterTaskHb(pJob, pTask); + atomic_sub_fetch_32(&pTask->level->taskLaunchedNum, 1); + taosMemoryFreeClear(pTask->msg); + pTask->msgLen = 0; + pTask->lastMsgType = 0; + memset(&pTask->succeedAddr, 0, sizeof(pTask->succeedAddr)); + + if (SCH_IS_DATA_SRC_QRY_TASK(pTask)) { + if (pData) { + SCH_ERR_JRET(schUpdateTaskCandidateAddr(pJob, pTask, pData->pEpSet)); + } + + if (SCH_TASK_NEED_FLOW_CTRL(pJob, pTask)) { + if (JOB_TASK_STATUS_EXEC == SCH_GET_TASK_STATUS(pTask)) { + SCH_ERR_JRET(schLaunchTasksInFlowCtrlList(pJob, pTask)); + } + } + + SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_INIT); + + SCH_ERR_JRET(schLaunchTask(pJob, pTask)); + + return TSDB_CODE_SUCCESS; + } + + + // merge plan + + pTask->childReady = 0; + + qClearSubplanExecutionNode(pTask->plan); + + SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_INIT); + + int32_t childrenNum = taosArrayGetSize(pTask->children); + for (int32_t i = 0; i < childrenNum; ++i) { + SSchTask* pChild = taosArrayGetP(pTask->children, i); + SCH_LOCK_TASK(pChild); + schDoTaskRedirect(pJob, pChild, NULL, rspCode); + SCH_UNLOCK_TASK(pChild); + } + + return TSDB_CODE_SUCCESS; + +_return: + + code = schProcessOnTaskFailure(pJob, pTask, code); + + SCH_RET(code); +} + +int32_t schHandleRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf* pData, int32_t rspCode) { + int32_t code = 0; + + if (SCH_IS_DATA_SRC_QRY_TASK(pTask)) { + if (NULL == pData->pEpSet) { + SCH_TASK_ELOG("no epset updated while got error %s", tstrerror(rspCode)); + SCH_ERR_JRET(rspCode); + } + } + + SCH_RET(schDoTaskRedirect(pJob, pTask, pData, rspCode)); + +_return: + + schProcessOnTaskFailure(pJob, pTask, code); + + SCH_RET(code); +} + +int32_t schPushTaskToExecList(SSchJob *pJob, SSchTask *pTask) { + int32_t code = taosHashPut(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId), &pTask, POINTER_BYTES); + if (0 != code) { + if (HASH_NODE_EXIST(code)) { + SCH_TASK_ELOG("task already in execTask list, code:%x", code); + SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR); + } + + SCH_TASK_ELOG("taosHashPut task to execTask list failed, errno:%d", errno); + SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + SCH_TASK_DLOG("task added to execTask list, numOfTasks:%d", taosHashGetSize(pJob->execTasks)); + + return TSDB_CODE_SUCCESS; +} + +/* +int32_t schMoveTaskToSuccList(SSchJob *pJob, SSchTask *pTask, bool *moved) { + if (0 != taosHashRemove(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId))) { + SCH_TASK_WLOG("remove task from execTask list failed, may not exist, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); + } else { + SCH_TASK_DLOG("task removed from execTask list, numOfTasks:%d", taosHashGetSize(pJob->execTasks)); + } + + int32_t code = taosHashPut(pJob->succTasks, &pTask->taskId, sizeof(pTask->taskId), &pTask, POINTER_BYTES); + if (0 != code) { + if (HASH_NODE_EXIST(code)) { + *moved = true; + SCH_TASK_ELOG("task already in succTask list, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); + SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); + } + + SCH_TASK_ELOG("taosHashPut task to succTask list failed, errno:%d", errno); + SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + *moved = true; + + SCH_TASK_DLOG("task moved to succTask list, numOfTasks:%d", taosHashGetSize(pJob->succTasks)); + + return TSDB_CODE_SUCCESS; +} + +int32_t schMoveTaskToFailList(SSchJob *pJob, SSchTask *pTask, bool *moved) { + *moved = false; + + if (0 != taosHashRemove(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId))) { + SCH_TASK_WLOG("remove task from execTask list failed, may not exist, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); + } + + int32_t code = taosHashPut(pJob->failTasks, &pTask->taskId, sizeof(pTask->taskId), &pTask, POINTER_BYTES); + if (0 != code) { + if (HASH_NODE_EXIST(code)) { + *moved = true; + + SCH_TASK_WLOG("task already in failTask list, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); + SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); + } + + SCH_TASK_ELOG("taosHashPut task to failTask list failed, errno:%d", errno); + SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + *moved = true; + + SCH_TASK_DLOG("task moved to failTask list, numOfTasks:%d", taosHashGetSize(pJob->failTasks)); + + return TSDB_CODE_SUCCESS; +} + +int32_t schMoveTaskToExecList(SSchJob *pJob, SSchTask *pTask, bool *moved) { + if (0 != taosHashRemove(pJob->succTasks, &pTask->taskId, sizeof(pTask->taskId))) { + SCH_TASK_WLOG("remove task from succTask list failed, may not exist, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); + } + + int32_t code = taosHashPut(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId), &pTask, POINTER_BYTES); + if (0 != code) { + if (HASH_NODE_EXIST(code)) { + *moved = true; + + SCH_TASK_ELOG("task already in execTask list, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); + SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); + } + + SCH_TASK_ELOG("taosHashPut task to execTask list failed, errno:%d", errno); + SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + *moved = true; + + SCH_TASK_DLOG("task moved to execTask list, numOfTasks:%d", taosHashGetSize(pJob->execTasks)); + + return TSDB_CODE_SUCCESS; +} +*/ + +int32_t schTaskCheckSetRetry(SSchJob *pJob, SSchTask *pTask, int32_t errCode, bool *needRetry) { + if (TSDB_CODE_SCH_TIMEOUT_ERROR == errCode) { + pTask->maxExecTimes++; + if (pTask->timeoutUsec < SCH_MAX_TASK_TIMEOUT_USEC) { + pTask->timeoutUsec *= 2; + if (pTask->timeoutUsec > SCH_MAX_TASK_TIMEOUT_USEC) { + pTask->timeoutUsec = SCH_MAX_TASK_TIMEOUT_USEC; + } + } + } + + if ((pTask->execId + 1) >= pTask->maxExecTimes) { + *needRetry = false; + SCH_TASK_DLOG("task no more retry since reach max try times, execId:%d", pTask->execId); + return TSDB_CODE_SUCCESS; + } + + if (!SCH_NEED_RETRY(pTask->lastMsgType, errCode)) { + *needRetry = false; + SCH_TASK_DLOG("task no more retry cause of errCode, errCode:%x - %s", errCode, tstrerror(errCode)); + return TSDB_CODE_SUCCESS; + } + + if (SCH_IS_DATA_SRC_TASK(pTask)) { + if ((pTask->execId + 1) >= SCH_TASK_NUM_OF_EPS(&pTask->plan->execNode)) { + *needRetry = false; + SCH_TASK_DLOG("task no more retry since all ep tried, execId:%d, epNum:%d", pTask->execId, + SCH_TASK_NUM_OF_EPS(&pTask->plan->execNode)); + return TSDB_CODE_SUCCESS; + } + } else { + int32_t candidateNum = taosArrayGetSize(pTask->candidateAddrs); + + if ((pTask->candidateIdx + 1) >= candidateNum && (TSDB_CODE_SCH_TIMEOUT_ERROR != errCode)) { + *needRetry = false; + SCH_TASK_DLOG("task no more retry since all candiates tried, candidateIdx:%d, candidateNum:%d", + pTask->candidateIdx, candidateNum); + return TSDB_CODE_SUCCESS; + } + } + + *needRetry = true; + SCH_TASK_DLOG("task need the %dth retry, errCode:%x - %s", pTask->execId + 1, errCode, tstrerror(errCode)); + + return TSDB_CODE_SUCCESS; +} + +int32_t schHandleTaskRetry(SSchJob *pJob, SSchTask *pTask) { + atomic_sub_fetch_32(&pTask->level->taskLaunchedNum, 1); + + SCH_ERR_RET(schRemoveTaskFromExecList(pJob, pTask)); + SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_INIT); + + if (SCH_TASK_NEED_FLOW_CTRL(pJob, pTask)) { + SCH_ERR_RET(schLaunchTasksInFlowCtrlList(pJob, pTask)); + } + + schDeregisterTaskHb(pJob, pTask); + + if (SCH_IS_DATA_SRC_TASK(pTask)) { + SCH_SWITCH_EPSET(&pTask->plan->execNode); + } else { + int32_t candidateNum = taosArrayGetSize(pTask->candidateAddrs); + if (++pTask->candidateIdx >= candidateNum) { + pTask->candidateIdx = 0; + } + } + + SCH_ERR_RET(schLaunchTask(pJob, pTask)); + + return TSDB_CODE_SUCCESS; +} + +int32_t schSetAddrsFromNodeList(SSchJob *pJob, SSchTask *pTask) { + int32_t addNum = 0; + int32_t nodeNum = 0; + + if (pJob->nodeList) { + nodeNum = taosArrayGetSize(pJob->nodeList); + + for (int32_t i = 0; i < nodeNum && addNum < SCH_MAX_CANDIDATE_EP_NUM; ++i) { + SQueryNodeLoad *nload = taosArrayGet(pJob->nodeList, i); + SQueryNodeAddr *naddr = &nload->addr; + + if (NULL == taosArrayPush(pTask->candidateAddrs, naddr)) { + SCH_TASK_ELOG("taosArrayPush execNode to candidate addrs failed, addNum:%d, errno:%d", addNum, errno); + SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + SCH_TASK_DLOG("set %dth candidate addr, id %d, fqdn:%s, port:%d", i, naddr->nodeId, SCH_GET_CUR_EP(naddr)->fqdn, SCH_GET_CUR_EP(naddr)->port); + + ++addNum; + } + } + + if (addNum <= 0) { + SCH_TASK_ELOG("no available execNode as candidates, nodeNum:%d", nodeNum); + SCH_ERR_RET(TSDB_CODE_TSC_NO_EXEC_NODE); + } + + return TSDB_CODE_SUCCESS; +} + + +int32_t schSetTaskCandidateAddrs(SSchJob *pJob, SSchTask *pTask) { + if (NULL != pTask->candidateAddrs) { + return TSDB_CODE_SUCCESS; + } + + pTask->candidateIdx = 0; + pTask->candidateAddrs = taosArrayInit(SCH_MAX_CANDIDATE_EP_NUM, sizeof(SQueryNodeAddr)); + if (NULL == pTask->candidateAddrs) { + SCH_TASK_ELOG("taosArrayInit %d condidate addrs failed", SCH_MAX_CANDIDATE_EP_NUM); + SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + if (pTask->plan->execNode.epSet.numOfEps > 0) { + if (NULL == taosArrayPush(pTask->candidateAddrs, &pTask->plan->execNode)) { + SCH_TASK_ELOG("taosArrayPush execNode to candidate addrs failed, errno:%d", errno); + SCH_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + SCH_TASK_DLOG("use execNode in plan as candidate addr, numOfEps:%d", pTask->plan->execNode.epSet.numOfEps); + + return TSDB_CODE_SUCCESS; + } + + SCH_ERR_RET(schSetAddrsFromNodeList(pJob, pTask)); + + /* + for (int32_t i = 0; i < job->dataSrcEps.numOfEps && addNum < SCH_MAX_CANDIDATE_EP_NUM; ++i) { + strncpy(epSet->fqdn[epSet->numOfEps], job->dataSrcEps.fqdn[i], sizeof(job->dataSrcEps.fqdn[i])); + epSet->port[epSet->numOfEps] = job->dataSrcEps.port[i]; + + ++epSet->numOfEps; + } + */ + + return TSDB_CODE_SUCCESS; +} + +int32_t schUpdateTaskCandidateAddr(SSchJob *pJob, SSchTask *pTask, SEpSet* pEpSet) { + if (NULL == pTask->candidateAddrs || 1 != taosArrayGetSize(pTask->candidateAddrs)) { + SCH_TASK_ELOG("not able to update cndidate addr, addr num %d", (int32_t)(pTask->candidateAddrs ? taosArrayGetSize(pTask->candidateAddrs): 0)); + SCH_ERR_RET(TSDB_CODE_APP_ERROR); + } + + SQueryNodeAddr* pAddr = taosArrayGet(pTask->candidateAddrs, 0); + + SEp* pOld = &pAddr->epSet.eps[pAddr->epSet.inUse]; + SEp* pNew = &pEpSet->eps[pEpSet->inUse]; + + SCH_TASK_DLOG("update task ep from %s:%d to %s:%d", pOld->fqdn, pOld->port, pNew->fqdn, pNew->port); + + memcpy(&pAddr->epSet, pEpSet, sizeof(pAddr->epSet)); + + return TSDB_CODE_SUCCESS; +} + + +int32_t schRemoveTaskFromExecList(SSchJob *pJob, SSchTask *pTask) { + int32_t code = taosHashRemove(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId)); + if (code) { + SCH_TASK_ELOG("task failed to rm from execTask list, code:%x", code); + SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR); + } + + return TSDB_CODE_SUCCESS; +} + +void schDropTaskOnExecNode(SSchJob *pJob, SSchTask *pTask) { + if (NULL == pTask->execNodes) { + SCH_TASK_DLOG("no exec address, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); + return; + } + + int32_t size = (int32_t)taosHashGetSize(pTask->execNodes); + + if (size <= 0) { + SCH_TASK_DLOG("task has no execNodes, no need to drop it, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); + return; + } + + SSchNodeInfo *nodeInfo = taosHashIterate(pTask->execNodes, NULL); + while (nodeInfo) { + SCH_SET_TASK_HANDLE(pTask, nodeInfo->handle); + + schBuildAndSendMsg(pJob, pTask, &nodeInfo->addr, TDMT_SCH_DROP_TASK); + + nodeInfo = taosHashIterate(pTask->execNodes, nodeInfo); + } + + SCH_TASK_DLOG("task has been dropped on %d exec nodes", size); +} + + + +int32_t schProcessOnTaskStatusRsp(SQueryNodeEpId* pEpId, SArray* pStatusList) { + int32_t taskNum = (int32_t)taosArrayGetSize(pStatusList); + SSchTask *pTask = NULL; + + qDebug("%d task status in hb rsp from nodeId:%d, fqdn:%s, port:%d", taskNum, pEpId->nodeId, pEpId->ep.fqdn, pEpId->ep.port); + + for (int32_t i = 0; i < taskNum; ++i) { + STaskStatus *taskStatus = taosArrayGet(pStatusList, i); + + qDebug("QID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d task status in server: %s", + taskStatus->queryId, taskStatus->taskId, taskStatus->execId, jobTaskStatusStr(taskStatus->status)); + + SSchJob *pJob = schAcquireJob(taskStatus->refId); + if (NULL == pJob) { + qWarn("job not found, refId:0x%" PRIx64 ",QID:0x%" PRIx64 ",TID:0x%" PRIx64, taskStatus->refId, + taskStatus->queryId, taskStatus->taskId); + // TODO DROP TASK FROM SERVER!!!! + continue; + } + + pTask = NULL; + schGetTaskInJob(pJob, taskStatus->taskId, &pTask); + if (NULL == pTask) { + // TODO DROP TASK FROM SERVER!!!! + schReleaseJob(taskStatus->refId); + continue; + } + + if (taskStatus->execId != pTask->execId) { + // TODO DROP TASK FROM SERVER!!!! + SCH_TASK_DLOG("EID %d in hb rsp mis-match", taskStatus->execId); + schReleaseJob(taskStatus->refId); + continue; + } + + if (taskStatus->status == JOB_TASK_STATUS_FAIL) { + // RECORD AND HANDLE ERROR!!!! + schReleaseJob(taskStatus->refId); + continue; + } + + if (taskStatus->status == JOB_TASK_STATUS_INIT) { + schRescheduleTask(pJob, pTask); + } + + schReleaseJob(taskStatus->refId); + } + + return TSDB_CODE_SUCCESS; +} + +int32_t schLaunchTaskImpl(SSchJob *pJob, SSchTask *pTask) { + int8_t status = 0; + int32_t code = 0; + + atomic_add_fetch_32(&pTask->level->taskLaunchedNum, 1); + pTask->execId++; + + SCH_TASK_DLOG("start to launch task's %dth exec", pTask->execId); + + SCH_LOG_TASK_START_TS(pTask); + + if (schJobNeedToStop(pJob, &status)) { + SCH_TASK_DLOG("no need to launch task cause of job status, job status:%s", jobTaskStatusStr(status)); + + SCH_RET(atomic_load_32(&pJob->errCode)); + } + + // NOTE: race condition: the task should be put into the hash table before send msg to server + if (SCH_GET_TASK_STATUS(pTask) != JOB_TASK_STATUS_EXEC) { + SCH_ERR_RET(schPushTaskToExecList(pJob, pTask)); + SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_EXEC); + } + + SSubplan *plan = pTask->plan; + + if (NULL == pTask->msg) { // TODO add more detailed reason for failure + code = qSubPlanToString(plan, &pTask->msg, &pTask->msgLen); + if (TSDB_CODE_SUCCESS != code) { + SCH_TASK_ELOG("failed to create physical plan, code:%s, msg:%p, len:%d", tstrerror(code), pTask->msg, + pTask->msgLen); + SCH_ERR_RET(code); + } else { + SCH_TASK_DLOGL("physical plan len:%d, %s", pTask->msgLen, pTask->msg); + } + } + + SCH_ERR_RET(schSetTaskCandidateAddrs(pJob, pTask)); + + if (SCH_IS_QUERY_JOB(pJob)) { + SCH_ERR_RET(schEnsureHbConnection(pJob, pTask)); + } + + SCH_ERR_RET(schBuildAndSendMsg(pJob, pTask, NULL, plan->msgType)); + + return TSDB_CODE_SUCCESS; +} + +// Note: no more error processing, handled in function internal +int32_t schLaunchTask(SSchJob *pJob, SSchTask *pTask) { + bool enough = false; + int32_t code = 0; + + SCH_SET_TASK_HANDLE(pTask, NULL); + + if (SCH_TASK_NEED_FLOW_CTRL(pJob, pTask)) { + SCH_ERR_JRET(schCheckIncTaskFlowQuota(pJob, pTask, &enough)); + + if (enough) { + SCH_ERR_JRET(schLaunchTaskImpl(pJob, pTask)); + } + } else { + SCH_ERR_JRET(schLaunchTaskImpl(pJob, pTask)); + } + + return TSDB_CODE_SUCCESS; + +_return: + + SCH_RET(schProcessOnTaskFailure(pJob, pTask, code)); +} + +int32_t schLaunchLevelTasks(SSchJob *pJob, SSchLevel *level) { + SCH_ERR_RET(schChkJobNeedFlowCtrl(pJob, level)); + + for (int32_t i = 0; i < level->taskNum; ++i) { + SSchTask *pTask = taosArrayGet(level->subTasks, i); + + SCH_ERR_RET(schLaunchTask(pJob, pTask)); + } + + return TSDB_CODE_SUCCESS; +} + +void schDropTaskInHashList(SSchJob *pJob, SHashObj *list) { + if (!SCH_IS_NEED_DROP_JOB(pJob)) { + return; + } + + void *pIter = taosHashIterate(list, NULL); + while (pIter) { + SSchTask *pTask = *(SSchTask **)pIter; + + schDropTaskOnExecNode(pJob, pTask); + + pIter = taosHashIterate(list, pIter); + } +} + + +// Note: no more error processing, handled in function internal +int32_t schLaunchFetchTask(SSchJob *pJob) { + int32_t code = 0; + + void *resData = atomic_load_ptr(&pJob->resData); + if (resData) { + SCH_JOB_DLOG("res already fetched, res:%p", resData); + return TSDB_CODE_SUCCESS; + } + + SCH_ERR_JRET(schBuildAndSendMsg(pJob, pJob->fetchTask, &pJob->resNode, TDMT_SCH_FETCH)); + + return TSDB_CODE_SUCCESS; + +_return: + + SCH_RET(schProcessOnTaskFailure(pJob, pJob->fetchTask, code)); +} + + diff --git a/source/libs/scheduler/src/schUtil.c b/source/libs/scheduler/src/schUtil.c index 73077cbf0f..f0ff12b56b 100644 --- a/source/libs/scheduler/src/schUtil.c +++ b/source/libs/scheduler/src/schUtil.c @@ -283,3 +283,20 @@ void schFreeSMsgSendInfo(SMsgSendInfo *msgSendInfo) { taosMemoryFree(msgSendInfo); } +int32_t schGetTaskFromList(SHashObj *pTaskList, uint64_t taskId, SSchTask **pTask) { + int32_t s = taosHashGetSize(pTaskList); + if (s <= 0) { + return TSDB_CODE_SUCCESS; + } + + SSchTask **task = taosHashGet(pTaskList, &taskId, sizeof(taskId)); + if (NULL == task || NULL == (*task)) { + return TSDB_CODE_SUCCESS; + } + + *pTask = *task; + + return TSDB_CODE_SUCCESS; +} + + diff --git a/source/libs/scheduler/src/scheduler.c b/source/libs/scheduler/src/scheduler.c index e2389c2a75..cbc6a1c17a 100644 --- a/source/libs/scheduler/src/scheduler.c +++ b/source/libs/scheduler/src/scheduler.c @@ -67,49 +67,22 @@ int32_t schedulerInit(SSchedulerCfg *cfg) { return TSDB_CODE_SUCCESS; } -int32_t schedulerExecJob(SSchedulerReq *pReq, int64_t *pJobId, SQueryResult *pRes) { - qDebug("scheduler sync exec job start"); +int32_t schedulerExecJob(SSchedulerReq *pReq, int64_t *pJobId) { + qDebug("scheduler %s exec job start", pReq->syncReq ? "SYNC" : "ASYNC"); int32_t code = 0; SSchJob *pJob = NULL; - SCH_ERR_JRET(schInitJob(pReq, &pJob)); + + SCH_ERR_RET(schJobStatusEnter(&pJob, JOB_TASK_STATUS_INIT, pReq)); + + SCH_ERR_RET(schJobStatusEnter(&pJob, JOB_TASK_STATUS_EXEC, pReq)); *pJobId = pJob->refId; - - SCH_ERR_JRET(schExecJobImpl(pReq, pJob, true)); _return: - - if (code && NULL == pJob) { - qDestroyQueryPlan(pReq->pDag); - } - - if (pJob) { - schSetJobQueryRes(pJob, pRes); - schReleaseJob(pJob->refId); - } - - return code; -} - -int32_t schedulerAsyncExecJob(SSchedulerReq *pReq, int64_t *pJobId) { - qDebug("scheduler async exec job start"); - - int32_t code = 0; - SSchJob *pJob = NULL; - SCH_ERR_JRET(schInitJob(pReq, &pJob)); - - *pJobId = pJob->refId; - - SCH_ERR_JRET(schExecJobImpl(pReq, pJob, false)); - -_return: - - if (code && NULL == pJob) { - qDestroyQueryPlan(pReq->pDag); - } if (pJob) { + schSetJobQueryRes(pJob, pReq->pQueryRes); schReleaseJob(pJob->refId); } @@ -133,14 +106,14 @@ int32_t schedulerFetchRows(int64_t job, void **pData) { SCH_ERR_RET(schBeginOperation(pJob, SCH_OP_FETCH, true)); pJob->userRes.fetchRes = pData; - code = schFetchRows(pJob); + code = schJobFetchRows(pJob); schReleaseJob(job); SCH_RET(code); } -void schedulerAsyncFetchRows(int64_t job, schedulerFetchFp fp, void* param) { +void schedulerFetchRowsA(int64_t job, schedulerFetchFp fp, void* param) { qDebug("scheduler async fetch rows start"); int32_t code = 0; @@ -159,7 +132,7 @@ void schedulerAsyncFetchRows(int64_t job, schedulerFetchFp fp, void* param) { pJob->userRes.fetchFp = fp; pJob->userRes.userParam = param; - SCH_ERR_JRET(schAsyncFetchRows(pJob)); + SCH_ERR_JRET(schJobFetchRowsA(pJob)); _return: @@ -178,7 +151,7 @@ int32_t schedulerGetTasksStatus(int64_t job, SArray *pSub) { SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); } - if (pJob->status < JOB_TASK_STATUS_NOT_START || pJob->levelNum <= 0 || NULL == pJob->levels) { + if (pJob->status < JOB_TASK_STATUS_INIT || pJob->levelNum <= 0 || NULL == pJob->levels) { qDebug("job not initialized or not executable job, refId:0x%" PRIx64, job); SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR); } diff --git a/source/libs/scheduler/test/schedulerTests.cpp b/source/libs/scheduler/test/schedulerTests.cpp index 7fe6cc22bf..245d8d362c 100644 --- a/source/libs/scheduler/test/schedulerTests.cpp +++ b/source/libs/scheduler/test/schedulerTests.cpp @@ -507,6 +507,7 @@ void* schtRunJobThread(void *aa) { SRequestConnInfo conn = {0}; conn.pTrans = mockPointer; SSchedulerReq req = {0}; + req.syncReq = false; req.pConn = &conn; req.pNodeList = qnodeList; req.pDag = &dag; @@ -514,7 +515,7 @@ void* schtRunJobThread(void *aa) { req.execFp = schtQueryCb; req.execParam = &queryDone; - code = schedulerAsyncExecJob(&req, &queryJobRefId); + code = schedulerExecJob(&req, &queryJobRefId); assert(code == 0); pJob = schAcquireJob(queryJobRefId); @@ -658,7 +659,7 @@ TEST(queryTest, normalCase) { SRequestConnInfo conn = {0}; conn.pTrans = mockPointer; - SSchedulerReq req = {0}; + SSchedulerReq req = {0}; req.pConn = &conn; req.pNodeList = qnodeList; req.pDag = &dag; @@ -666,7 +667,7 @@ TEST(queryTest, normalCase) { req.execFp = schtQueryCb; req.execParam = &queryDone; - code = schedulerAsyncExecJob(&req, &job); + code = schedulerExecJob(&req, &job); ASSERT_EQ(code, 0); @@ -769,7 +770,7 @@ TEST(queryTest, readyFirstCase) { req.sql = "select * from tb"; req.execFp = schtQueryCb; req.execParam = &queryDone; - code = schedulerAsyncExecJob(&req, &job); + code = schedulerExecJob(&req, &job); ASSERT_EQ(code, 0); @@ -877,7 +878,7 @@ TEST(queryTest, flowCtrlCase) { req.execFp = schtQueryCb; req.execParam = &queryDone; - code = schedulerAsyncExecJob(&req, &job); + code = schedulerExecJob(&req, &job); ASSERT_EQ(code, 0); From 9e00672c609cf1f895781d6f40948517b4b64827 Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Sat, 2 Jul 2022 19:48:51 +0800 Subject: [PATCH 2/9] enh: refactor scheduler code --- source/libs/planner/src/planPhysiCreater.c | 3 + source/libs/scheduler/inc/schInt.h | 10 +- source/libs/scheduler/src/schJob.c | 298 +++++++++++---------- source/libs/scheduler/src/schTask.c | 5 + 4 files changed, 169 insertions(+), 147 deletions(-) diff --git a/source/libs/planner/src/planPhysiCreater.c b/source/libs/planner/src/planPhysiCreater.c index aac9c25f77..0eb05ccbe9 100644 --- a/source/libs/planner/src/planPhysiCreater.c +++ b/source/libs/planner/src/planPhysiCreater.c @@ -552,6 +552,9 @@ static int32_t createSystemTableScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan* if (0 == strcmp(pScanLogicNode->tableName.tname, TSDB_INS_TABLE_USER_TABLES) || 0 == strcmp(pScanLogicNode->tableName.tname, TSDB_INS_TABLE_USER_TABLE_DISTRIBUTED)) { vgroupInfoToNodeAddr(pScanLogicNode->pVgroupList->vgroups, &pSubplan->execNode); + } else { + pSubplan->execNode.nodeId = MNODE_HANDLE; + pSubplan->execNode.epSet = pCxt->pPlanCxt->mgmtEpSet; } SQueryNodeLoad node = {.addr = {.nodeId = MNODE_HANDLE, .epSet = pCxt->pPlanCxt->mgmtEpSet}, .load = 0}; taosArrayPush(pCxt->pExecNodeList, &node); diff --git a/source/libs/scheduler/inc/schInt.h b/source/libs/scheduler/inc/schInt.h index ce4b9eea19..74b4dcf076 100644 --- a/source/libs/scheduler/inc/schInt.h +++ b/source/libs/scheduler/inc/schInt.h @@ -55,8 +55,8 @@ typedef enum { } SCH_OP_TYPE; typedef enum { - SCH_EVENT_ENTER_API = 1, - SCH_EVENT_LEAVE_API, + SCH_EVENT_BEGIN_OP = 1, + SCH_EVENT_END_OP, SCH_EVENT_MSG, SCH_EVENT_DROP, } SCH_EVENT_TYPE; @@ -111,6 +111,12 @@ typedef struct SSchResInfo { void* userParam; } SSchResInfo; +typedef struct SSchOpEvent { + SCH_OP_TYPE type; + bool begin; + SSchedulerReq *pReq; +} SSchOpEvent; + typedef struct SSchEvent { SCH_EVENT_TYPE event; void* info; diff --git a/source/libs/scheduler/src/schJob.c b/source/libs/scheduler/src/schJob.c index e137b2b001..893a836529 100644 --- a/source/libs/scheduler/src/schJob.c +++ b/source/libs/scheduler/src/schJob.c @@ -25,88 +25,6 @@ FORCE_INLINE SSchJob *schAcquireJob(int64_t refId) { qDebug("sch acquire jobId:0 FORCE_INLINE int32_t schReleaseJob(int64_t refId) { qDebug("sch release jobId:0x%"PRIx64, refId); return taosReleaseRef(schMgmt.jobRef, refId); } -int32_t schInitJob(SSchJob **pSchJob, SSchedulerReq *pReq) { - int32_t code = 0; - int64_t refId = -1; - SSchJob *pJob = taosMemoryCalloc(1, sizeof(SSchJob)); - if (NULL == pJob) { - qError("QID:0x%" PRIx64 " calloc %d failed", pReq->pDag->queryId, (int32_t)sizeof(SSchJob)); - SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY); - } - - pJob->attr.explainMode = pReq->pDag->explainInfo.mode; - pJob->conn = *pReq->pConn; - pJob->sql = pReq->sql; - pJob->pDag = pReq->pDag; - pJob->chkKillFp = pReq->chkKillFp; - pJob->chkKillParam = pReq->chkKillParam; - pJob->userRes.execFp = pReq->execFp; - pJob->userRes.userParam = pReq->execParam; - pJob->opStatus.op = SCH_OP_EXEC; - pJob->opStatus.syncReq = pReq->syncReq; - - if (pReq->pNodeList == NULL || taosArrayGetSize(pReq->pNodeList) <= 0) { - qDebug("QID:0x%" PRIx64 " input exec nodeList is empty", pReq->pDag->queryId); - } else { - pJob->nodeList = taosArrayDup(pReq->pNodeList); - } - - pJob->taskList = - taosHashInit(pReq->pDag->numOfSubplans, taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), false, HASH_ENTRY_LOCK); - if (NULL == pJob->taskList) { - SCH_JOB_ELOG("taosHashInit %d taskList failed", pReq->pDag->numOfSubplans); - SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY); - } - - SCH_ERR_JRET(schValidateAndBuildJob(pReq->pDag, pJob)); - - if (SCH_IS_EXPLAIN_JOB(pJob)) { - SCH_ERR_JRET(qExecExplainBegin(pReq->pDag, &pJob->explainCtx, pReq->startTs)); - } - - pJob->execTasks = - taosHashInit(pReq->pDag->numOfSubplans, taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), false, HASH_ENTRY_LOCK); - if (NULL == pJob->execTasks) { - SCH_JOB_ELOG("taosHashInit %d execTasks failed", pReq->pDag->numOfSubplans); - SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY); - } - - tsem_init(&pJob->rspSem, 0, 0); - - refId = taosAddRef(schMgmt.jobRef, pJob); - if (refId < 0) { - SCH_JOB_ELOG("taosAddRef job failed, error:%s", tstrerror(terrno)); - SCH_ERR_JRET(terrno); - } - - atomic_add_fetch_32(&schMgmt.jobNum, 1); - - if (NULL == schAcquireJob(refId)) { - SCH_JOB_ELOG("schAcquireJob job failed, refId:0x%" PRIx64, refId); - SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR); - } - - pJob->refId = refId; - - SCH_JOB_DLOG("job refId:0x%" PRIx64" created", pJob->refId); - - *pSchJob = pJob; - - return TSDB_CODE_SUCCESS; - -_return: - - if (NULL == pJob) { - qDestroyQueryPlan(pReq->pDag); - } else if (refId < 0) { - schFreeJobImpl(pJob); - } else { - taosRemoveRef(schMgmt.jobRef, refId); - } - - SCH_RET(code); -} - void schUpdateJobErrCode(SSchJob *pJob, int32_t errCode) { if (TSDB_CODE_SUCCESS == errCode) { @@ -231,66 +149,6 @@ _return: SCH_RET(code); } - -void schEndOperation(SSchJob *pJob) { - int32_t op = atomic_load_32(&pJob->opStatus.op); - if (SCH_OP_NULL == op) { - SCH_JOB_DLOG("job already not in any operation, status:%s", jobTaskStatusStr(pJob->status)); - return; - } - - atomic_store_32(&pJob->opStatus.op, SCH_OP_NULL); - - SCH_JOB_DLOG("job end %s operation", schGetOpStr(op)); -} - -int32_t schBeginOperation(SSchJob *pJob, SCH_OP_TYPE type, bool sync) { - int32_t code = 0; - int8_t status = 0; - - if (schJobNeedToStop(pJob, &status)) { - SCH_JOB_ELOG("abort op %s cause of job need to stop", schGetOpStr(type)); - SCH_ERR_JRET(pJob->errCode); - } - - if (SCH_OP_NULL != atomic_val_compare_exchange_32(&pJob->opStatus.op, SCH_OP_NULL, type)) { - SCH_JOB_ELOG("job already in %s operation", schGetOpStr(pJob->opStatus.op)); - SCH_ERR_JRET(TSDB_CODE_TSC_APP_ERROR); - } - - SCH_JOB_DLOG("job start %s operation", schGetOpStr(pJob->opStatus.op)); - - pJob->opStatus.syncReq = sync; - - switch (type) { - case SCH_OP_EXEC: - SCH_ERR_JRET(schUpdateJobStatus(pJob, JOB_TASK_STATUS_EXEC)); - break; - case SCH_OP_FETCH: - if (!SCH_JOB_NEED_FETCH(pJob)) { - SCH_JOB_ELOG("no need to fetch data, status:%s", SCH_GET_JOB_STATUS_STR(pJob)); - SCH_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); - } - - if (status != JOB_TASK_STATUS_PART_SUCC) { - SCH_JOB_ELOG("job status error for fetch, status:%s", jobTaskStatusStr(status)); - SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR); - } - break; - default: - SCH_JOB_ELOG("unknown operation type %d", type); - SCH_ERR_JRET(TSDB_CODE_TSC_APP_ERROR); - } - - return TSDB_CODE_SUCCESS; - -_return: - - schEndOperation(pJob); - - SCH_RET(code); -} - int32_t schBuildTaskRalation(SSchJob *pJob, SHashObj *planToTask) { for (int32_t i = 0; i < pJob->levelNum; ++i) { SSchLevel *pLevel = taosArrayGet(pJob->levels, i); @@ -827,6 +685,89 @@ int32_t schJobFetchRowsA(SSchJob *pJob) { return TSDB_CODE_SUCCESS; } + +int32_t schInitJob(SSchJob **pSchJob, SSchedulerReq *pReq) { + int32_t code = 0; + int64_t refId = -1; + SSchJob *pJob = taosMemoryCalloc(1, sizeof(SSchJob)); + if (NULL == pJob) { + qError("QID:0x%" PRIx64 " calloc %d failed", pReq->pDag->queryId, (int32_t)sizeof(SSchJob)); + SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + pJob->attr.explainMode = pReq->pDag->explainInfo.mode; + pJob->conn = *pReq->pConn; + pJob->sql = pReq->sql; + pJob->pDag = pReq->pDag; + pJob->chkKillFp = pReq->chkKillFp; + pJob->chkKillParam = pReq->chkKillParam; + pJob->userRes.execFp = pReq->execFp; + pJob->userRes.userParam = pReq->execParam; + pJob->opStatus.op = SCH_OP_EXEC; + pJob->opStatus.syncReq = pReq->syncReq; + + if (pReq->pNodeList == NULL || taosArrayGetSize(pReq->pNodeList) <= 0) { + qDebug("QID:0x%" PRIx64 " input exec nodeList is empty", pReq->pDag->queryId); + } else { + pJob->nodeList = taosArrayDup(pReq->pNodeList); + } + + pJob->taskList = + taosHashInit(pReq->pDag->numOfSubplans, taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), false, HASH_ENTRY_LOCK); + if (NULL == pJob->taskList) { + SCH_JOB_ELOG("taosHashInit %d taskList failed", pReq->pDag->numOfSubplans); + SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + SCH_ERR_JRET(schValidateAndBuildJob(pReq->pDag, pJob)); + + if (SCH_IS_EXPLAIN_JOB(pJob)) { + SCH_ERR_JRET(qExecExplainBegin(pReq->pDag, &pJob->explainCtx, pReq->startTs)); + } + + pJob->execTasks = + taosHashInit(pReq->pDag->numOfSubplans, taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), false, HASH_ENTRY_LOCK); + if (NULL == pJob->execTasks) { + SCH_JOB_ELOG("taosHashInit %d execTasks failed", pReq->pDag->numOfSubplans); + SCH_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + tsem_init(&pJob->rspSem, 0, 0); + + refId = taosAddRef(schMgmt.jobRef, pJob); + if (refId < 0) { + SCH_JOB_ELOG("taosAddRef job failed, error:%s", tstrerror(terrno)); + SCH_ERR_JRET(terrno); + } + + atomic_add_fetch_32(&schMgmt.jobNum, 1); + + if (NULL == schAcquireJob(refId)) { + SCH_JOB_ELOG("schAcquireJob job failed, refId:0x%" PRIx64, refId); + SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR); + } + + pJob->refId = refId; + + SCH_JOB_DLOG("job refId:0x%" PRIx64" created", pJob->refId); + + *pSchJob = pJob; + + return TSDB_CODE_SUCCESS; + +_return: + + if (NULL == pJob) { + qDestroyQueryPlan(pReq->pDag); + } else if (refId < 0) { + schFreeJobImpl(pJob); + } else { + taosRemoveRef(schMgmt.jobRef, refId); + } + + SCH_RET(code); +} + int32_t schExecJob(SSchJob *pJob, SSchedulerReq *pReq) { int32_t code = 0; qDebug("QID:0x%" PRIx64 " sch job refId 0x%"PRIx64 " started", pReq->pDag->queryId, pJob->refId); @@ -847,6 +788,69 @@ _return: SCH_RET(schProcessOnJobFailure(pJob, code)); } + +void schProcessOnOpEnd(SSchJob *pJob) { + int32_t op = atomic_load_32(&pJob->opStatus.op); + if (SCH_OP_NULL == op) { + SCH_JOB_DLOG("job already not in any operation, status:%s", jobTaskStatusStr(pJob->status)); + return; + } + + atomic_store_32(&pJob->opStatus.op, SCH_OP_NULL); + + SCH_JOB_DLOG("job end %s operation", schGetOpStr(op)); +} + +int32_t schProcessOnOpBegin(SSchJob* pJob, SSchEvent* pEvent) { + int32_t code = 0; + int8_t status = 0; + SSchOpEvent* pInfo = (SSchOpEvent*)pEvent->info; + SCH_OP_TYPE type, bool sync; + + if (schJobNeedToStop(pJob, &status)) { + SCH_JOB_ELOG("abort op %s cause of job need to stop", schGetOpStr(type)); + SCH_ERR_JRET(pJob->errCode); + } + + if (SCH_OP_NULL != atomic_val_compare_exchange_32(&pJob->opStatus.op, SCH_OP_NULL, type)) { + SCH_JOB_ELOG("job already in %s operation", schGetOpStr(pJob->opStatus.op)); + SCH_ERR_JRET(TSDB_CODE_TSC_APP_ERROR); + } + + SCH_JOB_DLOG("job start %s operation", schGetOpStr(pJob->opStatus.op)); + + pJob->opStatus.syncReq = sync; + + switch (type) { + case SCH_OP_EXEC: + SCH_ERR_JRET(schUpdateJobStatus(pJob, JOB_TASK_STATUS_EXEC)); + break; + case SCH_OP_FETCH: + if (!SCH_JOB_NEED_FETCH(pJob)) { + SCH_JOB_ELOG("no need to fetch data, status:%s", SCH_GET_JOB_STATUS_STR(pJob)); + SCH_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); + } + + if (status != JOB_TASK_STATUS_PART_SUCC) { + SCH_JOB_ELOG("job status error for fetch, status:%s", jobTaskStatusStr(status)); + SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR); + } + break; + default: + SCH_JOB_ELOG("unknown operation type %d", type); + SCH_ERR_JRET(TSDB_CODE_TSC_APP_ERROR); + } + + return TSDB_CODE_SUCCESS; + +_return: + + schEndOperation(pJob); + + SCH_RET(code); +} + + int32_t schJobStatusEnter(SSchJob** job, int32_t status, void* param) { SCH_ERR_RET(schUpdateJobStatus(*job, status)); @@ -866,9 +870,13 @@ int32_t schJobStatusEnter(SSchJob** job, int32_t status, void* param) { return TSDB_CODE_SUCCESS; } -int32_t schJobStatusEvent() { - - schEndOperation(pJob); +int32_t schJobHandleEvent(SSchJob* pJob, SSchEvent* pEvent) { + switch (pEvent->event) { + case SCH_EVENT_BEGIN_OP: + schProcessOnOpBegin(pJob, pEvent); + case SCH_EVENT_END_OP: + schProcessOnOpEnd(pJob); + } } diff --git a/source/libs/scheduler/src/schTask.c b/source/libs/scheduler/src/schTask.c index ccbd1f4615..0e1d749533 100644 --- a/source/libs/scheduler/src/schTask.c +++ b/source/libs/scheduler/src/schTask.c @@ -601,6 +601,11 @@ int32_t schSetTaskCandidateAddrs(SSchJob *pJob, SSchTask *pTask) { return TSDB_CODE_SUCCESS; } + if (SCH_IS_DATA_SRC_QRY_TASK(pTask)) { + SCH_TASK_ELOG("no execNode specifed for data src task, numOfEps:%d", pTask->plan->execNode.epSet.numOfEps); + SCH_ERR_RET(TSDB_CODE_QRY_APP_ERROR); + } + SCH_ERR_RET(schSetAddrsFromNodeList(pJob, pTask)); /* From 2f1cc7ae608aa7c75506ea3e1647e1705e0c8976 Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Sat, 2 Jul 2022 19:55:33 +0800 Subject: [PATCH 3/9] enh: refactor scheduler code --- source/libs/scheduler/src/schStatus.c | 4 ++++ source/libs/scheduler/src/scheduler.c | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/source/libs/scheduler/src/schStatus.c b/source/libs/scheduler/src/schStatus.c index a8cac993cf..1e5be8c3de 100644 --- a/source/libs/scheduler/src/schStatus.c +++ b/source/libs/scheduler/src/schStatus.c @@ -41,6 +41,10 @@ SSchStatusFps gSchTaskFps[JOB_TASK_STATUS_MAX] = { {JOB_TASK_STATUS_DROP, schTaskStatusNullEnter, schTaskStatusNullLeave, schTaskStatusNullEvent}, }; +int32_t schSwitchJobStatus(int32_t status, SSchJob* pJob, void* pParam) { + schJobStatusEnter(pJob, status, pParam); +} + diff --git a/source/libs/scheduler/src/scheduler.c b/source/libs/scheduler/src/scheduler.c index cbc6a1c17a..3f797f6c7e 100644 --- a/source/libs/scheduler/src/scheduler.c +++ b/source/libs/scheduler/src/scheduler.c @@ -75,6 +75,14 @@ int32_t schedulerExecJob(SSchedulerReq *pReq, int64_t *pJobId) { SCH_ERR_RET(schJobStatusEnter(&pJob, JOB_TASK_STATUS_INIT, pReq)); + SSchEvent event = {0}; + event.event = SCH_EVENT_BEGIN_OP; + SSchOpEvent opEvent = {0}; + opEvent.type = SCH_OP_EXEC; + opEvent.begin = true; + opEvent.pReq = pReq; + schJobHandleEvent(pJob, &event); + SCH_ERR_RET(schJobStatusEnter(&pJob, JOB_TASK_STATUS_EXEC, pReq)); *pJobId = pJob->refId; From 3ffd97591714ac78c75faaa71d934ffef96dfe96 Mon Sep 17 00:00:00 2001 From: dapan1121 <89396746@qq.com> Date: Mon, 4 Jul 2022 09:08:57 +0800 Subject: [PATCH 4/9] enh: refactor scheduler code --- include/libs/qcom/query.h | 6 +--- include/libs/scheduler/scheduler.h | 8 +++-- source/client/inc/clientInt.h | 2 +- source/client/src/clientImpl.c | 6 +++- source/client/src/clientMsgHandler.c | 2 +- source/libs/qcom/src/queryUtil.c | 2 +- source/libs/scheduler/inc/schInt.h | 4 +-- source/libs/scheduler/src/schJob.c | 42 ++++++--------------------- source/libs/scheduler/src/schStatus.c | 30 +++++++++++++++++-- source/libs/scheduler/src/schUtil.c | 14 +++++++++ source/libs/scheduler/src/scheduler.c | 35 ++++++++++------------ 11 files changed, 83 insertions(+), 68 deletions(-) diff --git a/include/libs/qcom/query.h b/include/libs/qcom/query.h index 64196aa64f..670e21fc4a 100644 --- a/include/libs/qcom/query.h +++ b/include/libs/qcom/query.h @@ -60,10 +60,6 @@ typedef struct STableComInfo { int32_t rowSize; // row size of the schema } STableComInfo; -typedef struct SQueryExecRes { - int32_t msgType; - void* res; -} SQueryExecRes; typedef struct SIndexMeta { #ifdef WINDOWS @@ -211,7 +207,7 @@ char* jobTaskStatusStr(int32_t status); SSchema createSchema(int8_t type, int32_t bytes, col_id_t colId, const char* name); -void destroyQueryExecRes(SQueryExecRes* pRes); +void destroyQueryExecRes(SExecResult* pRes); int32_t dataConverToStr(char* str, int type, void* buf, int32_t bufSize, int32_t* len); char* parseTagDatatoJson(void* p); int32_t cloneTableMeta(STableMeta* pSrc, STableMeta** pDst); diff --git a/include/libs/scheduler/scheduler.h b/include/libs/scheduler/scheduler.h index 66e1f7ed3a..5f9f65d76a 100644 --- a/include/libs/scheduler/scheduler.h +++ b/include/libs/scheduler/scheduler.h @@ -53,11 +53,12 @@ typedef struct SQueryProfileSummary { uint64_t resultSize; // generated result size in Kb. } SQueryProfileSummary; -typedef struct SQueryResult { +typedef struct SExecResult { int32_t code; uint64_t numOfRows; - SQueryExecRes res; -} SQueryResult; + int32_t msgType; + void* res; +} SExecResult; typedef struct STaskInfo { SQueryNodeAddr addr; @@ -85,6 +86,7 @@ typedef struct SSchedulerReq { schedulerChkKillFp chkKillFp; void* chkKillParam; SQueryResult* pQueryRes; + char** pFetchRes; } SSchedulerReq; diff --git a/source/client/inc/clientInt.h b/source/client/inc/clientInt.h index 737fee5125..9d2886d242 100644 --- a/source/client/inc/clientInt.h +++ b/source/client/inc/clientInt.h @@ -156,7 +156,7 @@ typedef struct SResultColumn { } SResultColumn; typedef struct SReqResultInfo { - SQueryExecRes execRes; + SExecResult execRes; const char* pRspMsg; const char* pData; TAOS_FIELD* fields; // todo, column names are not needed. diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index 63b153b6fc..0e031bd24f 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -757,7 +757,7 @@ int32_t handleQueryExecRsp(SRequestObj* pRequest) { } SEpSet epset = getEpSet_s(&pAppInfo->mgmtEp); - SQueryExecRes* pRes = &pRequest->body.resInfo.execRes; + SExecResult* pRes = &pRequest->body.resInfo.execRes; switch (pRes->msgType) { case TDMT_VND_ALTER_TABLE: @@ -1366,6 +1366,10 @@ void* doFetchRows(SRequestObj* pRequest, bool setupOneRowPtr, bool convertUcs4) } SReqResultInfo* pResInfo = &pRequest->body.resInfo; + SSchedulerReq req = { + .syncReq = true, + . + }; pRequest->code = schedulerFetchRows(pRequest->body.queryJob, (void**)&pResInfo->pData); if (pRequest->code != TSDB_CODE_SUCCESS) { pResultInfo->numOfRows = 0; diff --git a/source/client/src/clientMsgHandler.c b/source/client/src/clientMsgHandler.c index 761eebee42..dcccbb17c9 100644 --- a/source/client/src/clientMsgHandler.c +++ b/source/client/src/clientMsgHandler.c @@ -266,7 +266,7 @@ int32_t processAlterStbRsp(void* param, SDataBuf* pMsg, int32_t code) { } if (pRequest->body.queryFp != NULL) { - SQueryExecRes* pRes = &pRequest->body.resInfo.execRes; + SExecResult* pRes = &pRequest->body.resInfo.execRes; if (code == TSDB_CODE_SUCCESS) { SCatalog* pCatalog = NULL; diff --git a/source/libs/qcom/src/queryUtil.c b/source/libs/qcom/src/queryUtil.c index 1db13dd931..923224688c 100644 --- a/source/libs/qcom/src/queryUtil.c +++ b/source/libs/qcom/src/queryUtil.c @@ -200,7 +200,7 @@ SSchema createSchema(int8_t type, int32_t bytes, col_id_t colId, const char* nam return s; } -void destroyQueryExecRes(SQueryExecRes* pRes) { +void destroyQueryExecRes(SExecResult* pRes) { if (NULL == pRes || NULL == pRes->res) { return; } diff --git a/source/libs/scheduler/inc/schInt.h b/source/libs/scheduler/inc/schInt.h index 74b4dcf076..cceea452db 100644 --- a/source/libs/scheduler/inc/schInt.h +++ b/source/libs/scheduler/inc/schInt.h @@ -260,7 +260,7 @@ typedef struct SSchJob { SSchTask *fetchTask; int32_t errCode; SRWLatch resLock; - SQueryExecRes execRes; + SExecResult execRes; void *resData; //TODO free it or not int32_t resNumOfRows; SSchResInfo userRes; @@ -415,7 +415,7 @@ char* schGetOpStr(SCH_OP_TYPE type); int32_t schBeginOperation(SSchJob *pJob, SCH_OP_TYPE type, bool sync); int32_t schInitJob(SSchJob **pJob, SSchedulerReq *pReq); int32_t schExecJob(SSchJob *pJob, SSchedulerReq *pReq); -int32_t schSetJobQueryRes(SSchJob* pJob, SQueryResult* pRes); +int32_t schDumpJobExecRes(SSchJob* pJob, SQueryResult* pRes); int32_t schUpdateTaskCandidateAddr(SSchJob *pJob, SSchTask *pTask, SEpSet* pEpSet); int32_t schHandleRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf* pData, int32_t rspCode); diff --git a/source/libs/scheduler/src/schJob.c b/source/libs/scheduler/src/schJob.c index 893a836529..9f1679f5b2 100644 --- a/source/libs/scheduler/src/schJob.c +++ b/source/libs/scheduler/src/schJob.c @@ -21,11 +21,6 @@ #include "tref.h" #include "trpc.h" -FORCE_INLINE SSchJob *schAcquireJob(int64_t refId) { qDebug("sch acquire jobId:0x%"PRIx64, refId); return (SSchJob *)taosAcquireRef(schMgmt.jobRef, refId); } - -FORCE_INLINE int32_t schReleaseJob(int64_t refId) { qDebug("sch release jobId:0x%"PRIx64, refId); return taosReleaseRef(schMgmt.jobRef, refId); } - - void schUpdateJobErrCode(SSchJob *pJob, int32_t errCode) { if (TSDB_CODE_SUCCESS == errCode) { return; @@ -365,7 +360,7 @@ _return: } -int32_t schSetJobQueryRes(SSchJob* pJob, SQueryResult* pRes) { +int32_t schDumpJobExecRes(SSchJob* pJob, SQueryResult* pRes) { pRes->code = atomic_load_32(&pJob->errCode); pRes->numOfRows = pJob->resNumOfRows; pRes->res = pJob->execRes; @@ -374,7 +369,7 @@ int32_t schSetJobQueryRes(SSchJob* pJob, SQueryResult* pRes) { return TSDB_CODE_SUCCESS; } -int32_t schSetJobFetchRes(SSchJob* pJob, void** pData) { +int32_t schDumpJobFetchRes(SSchJob* pJob, void** pData) { int32_t code = 0; if (pJob->resData && ((SRetrieveTableRsp *)pJob->resData)->completed) { SCH_ERR_RET(schUpdateJobStatus(pJob, JOB_TASK_STATUS_SUCC)); @@ -407,14 +402,14 @@ int32_t schSetJobFetchRes(SSchJob* pJob, void** pData) { int32_t schNotifyUserExecRes(SSchJob* pJob) { SQueryResult* pRes = taosMemoryCalloc(1, sizeof(SQueryResult)); if (pRes) { - schSetJobQueryRes(pJob, pRes); + schDumpJobExecRes(pJob, pRes); } schEndOperation(pJob); SCH_JOB_DLOG("sch start to invoke exec cb, code: %s", tstrerror(pJob->errCode)); (*pJob->userRes.execFp)(pRes, pJob->userRes.userParam, atomic_load_32(&pJob->errCode)); - SCH_JOB_DLOG("sch end from query cb, code: %s", tstrerror(pJob->errCode)); + SCH_JOB_DLOG("sch end from exec cb, code: %s", tstrerror(pJob->errCode)); return TSDB_CODE_SUCCESS; } @@ -422,7 +417,7 @@ int32_t schNotifyUserExecRes(SSchJob* pJob) { int32_t schNotifyUserFetchRes(SSchJob* pJob) { void* pRes = NULL; - schSetJobFetchRes(pJob, &pRes); + schDumpJobFetchRes(pJob, &pRes); schEndOperation(pJob); @@ -473,7 +468,8 @@ int32_t schProcessOnJobFailureImpl(SSchJob *pJob, int32_t status, int32_t errCod // Note: no more task error processing, handled in function internal int32_t schProcessOnJobFailure(SSchJob *pJob, int32_t errCode) { - SCH_RET(schProcessOnJobFailureImpl(pJob, JOB_TASK_STATUS_FAIL, errCode)); + schProcessOnJobFailureImpl(pJob, JOB_TASK_STATUS_FAIL, errCode); + return TSDB_CODE_SUCCESS; } // Note: no more error processing, handled in function internal @@ -663,7 +659,7 @@ int32_t schJobFetchRows(SSchJob *pJob) { tsem_wait(&pJob->rspSem); } - SCH_ERR_JRET(schSetJobFetchRes(pJob, pJob->userRes.fetchRes)); + SCH_ERR_JRET(schDumpJobFetchRes(pJob, pJob->userRes.fetchRes)); _return: @@ -850,27 +846,7 @@ _return: SCH_RET(code); } - -int32_t schJobStatusEnter(SSchJob** job, int32_t status, void* param) { - SCH_ERR_RET(schUpdateJobStatus(*job, status)); - - switch (status) { - case JOB_TASK_STATUS_INIT: - SCH_RET(schInitJob(job, param)); - case JOB_TASK_STATUS_EXEC: - SCH_RET(schExecJob(job, param)); - case JOB_TASK_STATUS_PART_SUCC: - default: { - SSchJob* pJob = *job; - SCH_JOB_ELOG("enter unknown job status %d", status); - SCH_RET(TSDB_CODE_SCH_STATUS_ERROR); - } - } - - return TSDB_CODE_SUCCESS; -} - -int32_t schJobHandleEvent(SSchJob* pJob, SSchEvent* pEvent) { +int32_t schHandleJobEvent(SSchJob* pJob, SSchEvent* pEvent) { switch (pEvent->event) { case SCH_EVENT_BEGIN_OP: schProcessOnOpBegin(pJob, pEvent); diff --git a/source/libs/scheduler/src/schStatus.c b/source/libs/scheduler/src/schStatus.c index 1e5be8c3de..c6f5c23024 100644 --- a/source/libs/scheduler/src/schStatus.c +++ b/source/libs/scheduler/src/schStatus.c @@ -41,8 +41,34 @@ SSchStatusFps gSchTaskFps[JOB_TASK_STATUS_MAX] = { {JOB_TASK_STATUS_DROP, schTaskStatusNullEnter, schTaskStatusNullLeave, schTaskStatusNullEvent}, }; -int32_t schSwitchJobStatus(int32_t status, SSchJob* pJob, void* pParam) { - schJobStatusEnter(pJob, status, pParam); +int32_t schSwitchJobStatus(SSchJob** job, int32_t status, void* param) { + SCH_ERR_RET(schUpdateJobStatus(*job, status)); + + switch (status) { + case JOB_TASK_STATUS_INIT: + SCH_RET(schInitJob(job, param)); + case JOB_TASK_STATUS_EXEC: + SCH_RET(schExecJob(job, param)); + case JOB_TASK_STATUS_PART_SUCC: + default: { + SSchJob* pJob = *job; + SCH_JOB_ELOG("enter unknown job status %d", status); + SCH_RET(TSDB_CODE_SCH_STATUS_ERROR); + } + } + + return TSDB_CODE_SUCCESS; +} + +int32_t schHandleOpBeginEvent(SSchJob* pJob, SCH_OP_TYPE type, SSchedulerReq* pReq) { + SSchEvent event = {0}; + event.event = SCH_EVENT_BEGIN_OP; + SSchOpEvent opEvent = {0}; + opEvent.type = type; + opEvent.begin = true; + opEvent.pReq = pReq; + + SCH_ERR_RET(schHandleJobEvent(pJob, &event)); } diff --git a/source/libs/scheduler/src/schUtil.c b/source/libs/scheduler/src/schUtil.c index f0ff12b56b..38a04d1433 100644 --- a/source/libs/scheduler/src/schUtil.c +++ b/source/libs/scheduler/src/schUtil.c @@ -21,6 +21,20 @@ #include "tref.h" #include "trpc.h" +FORCE_INLINE SSchJob *schAcquireJob(int64_t refId) { + qDebug("sch acquire jobId:0x%"PRIx64, refId); + return (SSchJob *)taosAcquireRef(schMgmt.jobRef, refId); +} + +FORCE_INLINE int32_t schReleaseJob(int64_t refId) { + if (0 == refId) { + return TSDB_CODE_SUCCESS; + } + + qDebug("sch release jobId:0x%"PRIx64, refId); + return taosReleaseRef(schMgmt.jobRef, refId); +} + char* schGetOpStr(SCH_OP_TYPE type) { switch (type) { case SCH_OP_NULL: diff --git a/source/libs/scheduler/src/scheduler.c b/source/libs/scheduler/src/scheduler.c index 3f797f6c7e..8629bdf8b9 100644 --- a/source/libs/scheduler/src/scheduler.c +++ b/source/libs/scheduler/src/scheduler.c @@ -73,36 +73,29 @@ int32_t schedulerExecJob(SSchedulerReq *pReq, int64_t *pJobId) { int32_t code = 0; SSchJob *pJob = NULL; - SCH_ERR_RET(schJobStatusEnter(&pJob, JOB_TASK_STATUS_INIT, pReq)); + *pJobId = 0; - SSchEvent event = {0}; - event.event = SCH_EVENT_BEGIN_OP; - SSchOpEvent opEvent = {0}; - opEvent.type = SCH_OP_EXEC; - opEvent.begin = true; - opEvent.pReq = pReq; - schJobHandleEvent(pJob, &event); + SCH_ERR_RET(schSwitchJobStatus(&pJob, JOB_TASK_STATUS_INIT, pReq)); + + SCH_ERR_RET(schHandleOpBeginEvent(pJob, SCH_OP_EXEC, pReq)); - SCH_ERR_RET(schJobStatusEnter(&pJob, JOB_TASK_STATUS_EXEC, pReq)); + SCH_ERR_RET(schSwitchJobStatus(&pJob, JOB_TASK_STATUS_EXEC, pReq)); + + SCH_ERR_RET(schHandleOpEndEvent(pJob, SCH_OP_EXEC, pReq)); *pJobId = pJob->refId; _return: - if (pJob) { - schSetJobQueryRes(pJob, pReq->pQueryRes); - schReleaseJob(pJob->refId); - } + schDumpJobExecRes(pJob, pReq->pQueryRes); + + schReleaseJob(pJob->refId); return code; } -int32_t schedulerFetchRows(int64_t job, void **pData) { - qDebug("scheduler sync fetch rows start"); - - if (NULL == pData) { - SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); - } +int32_t schedulerFetchRows(int64_t job, SSchedulerReq *pReq) { + qDebug("scheduler %s fetch rows start", pReq->syncReq ? "SYNC" : "ASYNC"); int32_t code = 0; SSchJob *pJob = schAcquireJob(job); @@ -111,6 +104,10 @@ int32_t schedulerFetchRows(int64_t job, void **pData) { SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); } + SCH_ERR_RET(schHandleOpBeginEvent(pJob, SCH_OP_FETCH, pReq)); + + + SCH_ERR_RET(schBeginOperation(pJob, SCH_OP_FETCH, true)); pJob->userRes.fetchRes = pData; From b5207239b5cb2b9ff8729c2363936613414ece2d Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Tue, 5 Jul 2022 16:10:38 +0800 Subject: [PATCH 5/9] enh: refactor scheduler code --- include/libs/scheduler/scheduler.h | 5 +- include/util/taoserror.h | 2 +- source/client/src/clientImpl.c | 4 +- source/client/src/clientMain.c | 7 +- source/libs/scheduler/inc/schInt.h | 17 +- source/libs/scheduler/src/schJob.c | 285 ++++++++++-------- source/libs/scheduler/src/schRemote.c | 134 ++++---- source/libs/scheduler/src/schStatus.c | 82 ++--- source/libs/scheduler/src/schTask.c | 123 ++++---- source/libs/scheduler/src/schUtil.c | 2 + source/libs/scheduler/src/scheduler.c | 124 ++------ source/libs/scheduler/test/schedulerTests.cpp | 10 +- source/util/src/terror.c | 1 + 13 files changed, 358 insertions(+), 438 deletions(-) diff --git a/include/libs/scheduler/scheduler.h b/include/libs/scheduler/scheduler.h index 5f9f65d76a..ae4cbb498c 100644 --- a/include/libs/scheduler/scheduler.h +++ b/include/libs/scheduler/scheduler.h @@ -82,10 +82,11 @@ typedef struct SSchedulerReq { const char *sql; int64_t startTs; schedulerExecFp execFp; - void* execParam; + schedulerFetchFp fetchFp; + void* cbParam; schedulerChkKillFp chkKillFp; void* chkKillParam; - SQueryResult* pQueryRes; + SExecResult* pExecRes; char** pFetchRes; } SSchedulerReq; diff --git a/include/util/taoserror.h b/include/util/taoserror.h index b871452828..d93fb92ee5 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -388,10 +388,10 @@ int32_t* taosGetErrno(); #define TSDB_CODE_QRY_TASK_MSG_ERROR TAOS_DEF_ERROR_CODE(0, 0x0719) #define TSDB_CODE_QRY_JOB_FREED TAOS_DEF_ERROR_CODE(0, 0x071A) #define TSDB_CODE_QRY_TASK_STATUS_ERROR TAOS_DEF_ERROR_CODE(0, 0x071B) -//json #define TSDB_CODE_QRY_JSON_IN_ERROR TAOS_DEF_ERROR_CODE(0, 0x071C) #define TSDB_CODE_QRY_JSON_NOT_SUPPORT_ERROR TAOS_DEF_ERROR_CODE(0, 0x071D) #define TSDB_CODE_QRY_JSON_IN_GROUP_ERROR TAOS_DEF_ERROR_CODE(0, 0x071E) +#define TSDB_CODE_QRY_JOB_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x071F) // grant #define TSDB_CODE_GRANT_EXPIRED TAOS_DEF_ERROR_CODE(0, 0x0800) diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index 0e031bd24f..423e7982ab 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -1368,9 +1368,9 @@ void* doFetchRows(SRequestObj* pRequest, bool setupOneRowPtr, bool convertUcs4) SReqResultInfo* pResInfo = &pRequest->body.resInfo; SSchedulerReq req = { .syncReq = true, - . + .pFetchRes = &pResInfo->pData, }; - pRequest->code = schedulerFetchRows(pRequest->body.queryJob, (void**)&pResInfo->pData); + pRequest->code = schedulerFetchRows(pRequest->body.queryJob, &req); if (pRequest->code != TSDB_CODE_SUCCESS) { pResultInfo->numOfRows = 0; return NULL; diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c index f660c46d3c..4e24fb4f48 100644 --- a/source/client/src/clientMain.c +++ b/source/client/src/clientMain.c @@ -863,7 +863,12 @@ void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) { } } - schedulerFetchRowsA(pRequest->body.queryJob, fetchCallback, pRequest); + SSchedulerReq req = { + .syncReq = false, + .fetchFp = fetchCallback, + .execParam = pRequest, + }; + schedulerFetchRows(pRequest->body.queryJob, &req); } void taos_fetch_raw_block_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) { diff --git a/source/libs/scheduler/inc/schInt.h b/source/libs/scheduler/inc/schInt.h index cceea452db..2ad2fc9029 100644 --- a/source/libs/scheduler/inc/schInt.h +++ b/source/libs/scheduler/inc/schInt.h @@ -52,15 +52,9 @@ typedef enum { SCH_OP_NULL = 0, SCH_OP_EXEC, SCH_OP_FETCH, + SCH_OP_GET_STATUS, } SCH_OP_TYPE; -typedef enum { - SCH_EVENT_BEGIN_OP = 1, - SCH_EVENT_END_OP, - SCH_EVENT_MSG, - SCH_EVENT_DROP, -} SCH_EVENT_TYPE; - typedef struct SSchTrans { void *pTrans; void *pHandle; @@ -108,7 +102,7 @@ typedef struct SSchResInfo { void** fetchRes; schedulerExecFp execFp; schedulerFetchFp fetchFp; - void* userParam; + void* cbParam; } SSchResInfo; typedef struct SSchOpEvent { @@ -358,9 +352,10 @@ extern SSchedulerMgmt schMgmt; #define SCH_TASK_WLOG(param, ...) \ qWarn("QID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, pJob->queryId, SCH_TASK_ID(pTask), SCH_TASK_EID(pTask),__VA_ARGS__) -#define SCH_ERR_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { terrno = _code; return _code; } } while (0) -#define SCH_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { terrno = _code; } return _code; } while (0) -#define SCH_ERR_JRET(c) do { code = c; if (code != TSDB_CODE_SUCCESS) { terrno = code; goto _return; } } while (0) +#define SCH_SET_ERRNO(_err) do { if (TSDB_CODE_SCH_IGNORE_ERROR != (_err)) { terrno = (_err); } } while (0) +#define SCH_ERR_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { SCH_SET_ERRNO(_code); return _code; } } while (0) +#define SCH_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { SCH_SET_ERRNO(_code); } return _code; } while (0) +#define SCH_ERR_JRET(c) do { code = c; if (code != TSDB_CODE_SUCCESS) { SCH_SET_ERRNO(_code); goto _return; } } while (0) #define SCH_LOCK(type, _lock) (SCH_READ == (type) ? taosRLockLatch(_lock) : taosWLockLatch(_lock)) #define SCH_UNLOCK(type, _lock) (SCH_READ == (type) ? taosRUnLockLatch(_lock) : taosWUnLockLatch(_lock)) diff --git a/source/libs/scheduler/src/schJob.c b/source/libs/scheduler/src/schJob.c index 9f1679f5b2..d514ed2a9f 100644 --- a/source/libs/scheduler/src/schJob.c +++ b/source/libs/scheduler/src/schJob.c @@ -51,7 +51,12 @@ _return: SCH_JOB_DLOG("job errCode updated to %x - %s", errCode, tstrerror(errCode)); } - +bool schJobDone(SSchJob *pJob) { + int8_t status = SCH_GET_JOB_STATUS(pJob); + + return (status == JOB_TASK_STATUS_FAIL || status == JOB_TASK_STATUS_DROP || + status == JOB_TASK_STATUS_SUCC); +} FORCE_INLINE bool schJobNeedToStop(SSchJob *pJob, int8_t *pStatus) { int8_t status = SCH_GET_JOB_STATUS(pJob); @@ -59,13 +64,14 @@ FORCE_INLINE bool schJobNeedToStop(SSchJob *pJob, int8_t *pStatus) { *pStatus = status; } + if (schJobDone(pJob)) { + return true; + } + if ((*pJob->chkKillFp)(pJob->chkKillParam)) { schUpdateJobErrCode(pJob, TSDB_CODE_TSC_QUERY_KILLED); return true; - } - - return (status == JOB_TASK_STATUS_FAIL || status == JOB_TASK_STATUS_DROP || - status == JOB_TASK_STATUS_SUCC); + } } int32_t schUpdateJobStatus(SSchJob *pJob, int8_t newStatus) { @@ -77,10 +83,6 @@ int32_t schUpdateJobStatus(SSchJob *pJob, int8_t newStatus) { oriStatus = SCH_GET_JOB_STATUS(pJob); if (oriStatus == newStatus) { - if (newStatus == JOB_TASK_STATUS_DROP) { - SCH_ERR_JRET(TSDB_CODE_SCH_JOB_IS_DROPPING); - } - SCH_ERR_JRET(TSDB_CODE_SCH_IGNORE_ERROR); } @@ -140,7 +142,11 @@ int32_t schUpdateJobStatus(SSchJob *pJob, int8_t newStatus) { _return: - SCH_JOB_ELOG("invalid job status update, from %s to %s", jobTaskStatusStr(oriStatus), jobTaskStatusStr(newStatus)); + if (TSDB_CODE_SCH_IGNORE_ERROR == code) { + SCH_JOB_DLOG("ignore job status update, from %s to %s", jobTaskStatusStr(oriStatus), jobTaskStatusStr(newStatus)); + } else { + SCH_JOB_ELOG("invalid job status update, from %s to %s", jobTaskStatusStr(oriStatus), jobTaskStatusStr(newStatus)); + } SCH_RET(code); } @@ -360,7 +366,7 @@ _return: } -int32_t schDumpJobExecRes(SSchJob* pJob, SQueryResult* pRes) { +int32_t schDumpJobExecRes(SSchJob* pJob, SExecResult* pRes) { pRes->code = atomic_load_32(&pJob->errCode); pRes->numOfRows = pJob->resNumOfRows; pRes->res = pJob->execRes; @@ -372,7 +378,7 @@ int32_t schDumpJobExecRes(SSchJob* pJob, SQueryResult* pRes) { int32_t schDumpJobFetchRes(SSchJob* pJob, void** pData) { int32_t code = 0; if (pJob->resData && ((SRetrieveTableRsp *)pJob->resData)->completed) { - SCH_ERR_RET(schUpdateJobStatus(pJob, JOB_TASK_STATUS_SUCC)); + SCH_ERR_RET(schSwitchJobStatus(pJob, JOB_TASK_STATUS_SUCC, NULL)); } while (true) { @@ -451,9 +457,6 @@ void schPostJobRes(SSchJob *pJob, SCH_OP_TYPE op) { } int32_t schProcessOnJobFailureImpl(SSchJob *pJob, int32_t status, int32_t errCode) { - // if already FAILED, no more processing - SCH_ERR_RET(schUpdateJobStatus(pJob, status)); - schUpdateJobErrCode(pJob, errCode); int32_t code = atomic_load_32(&pJob->errCode); @@ -463,13 +466,17 @@ int32_t schProcessOnJobFailureImpl(SSchJob *pJob, int32_t status, int32_t errCod schPostJobRes(pJob, 0); - SCH_RET(code); + SCH_RET(TSDB_CODE_SCH_IGNORE_ERROR); } // Note: no more task error processing, handled in function internal int32_t schProcessOnJobFailure(SSchJob *pJob, int32_t errCode) { + if (TSDB_CODE_SCH_IGNORE_ERROR == errCode) { + return TSDB_CODE_SCH_IGNORE_ERROR; + } + schProcessOnJobFailureImpl(pJob, JOB_TASK_STATUS_FAIL, errCode); - return TSDB_CODE_SUCCESS; + return TSDB_CODE_SCH_IGNORE_ERROR; } // Note: no more error processing, handled in function internal @@ -477,19 +484,10 @@ int32_t schProcessOnJobDropped(SSchJob *pJob, int32_t errCode) { SCH_RET(schProcessOnJobFailureImpl(pJob, JOB_TASK_STATUS_DROP, errCode)); } -// Note: no more task error processing, handled in function internal int32_t schProcessOnJobPartialSuccess(SSchJob *pJob) { - int32_t code = 0; - - SCH_ERR_RET(schUpdateJobStatus(pJob, JOB_TASK_STATUS_PART_SUCC)); - schPostJobRes(pJob, SCH_OP_EXEC); return TSDB_CODE_SUCCESS; - -_return: - - SCH_RET(schProcessOnJobFailure(pJob, code)); } void schProcessOnDataFetched(SSchJob *pJob) { @@ -570,7 +568,7 @@ int32_t schGetTaskInJob(SSchJob *pJob, uint64_t taskId, SSchTask **pTask) { int32_t schLaunchJob(SSchJob *pJob) { if (EXPLAIN_MODE_STATIC == pJob->attr.explainMode) { SCH_ERR_RET(qExecStaticExplain(pJob->pDag, (SRetrieveTableRsp **)&pJob->resData)); - SCH_ERR_RET(schJobStatusEnter(&pJob, JOB_TASK_STATUS_PART_SUCC, NULL)); + SCH_ERR_RET(schSwitchJobStatus(pJob, JOB_TASK_STATUS_PART_SUCC, NULL)); } else { SSchLevel *level = taosArrayGet(pJob->levels, pJob->levelIdx); SCH_ERR_RET(schLaunchLevelTasks(pJob, level)); @@ -586,12 +584,6 @@ void schDropJobAllTasks(SSchJob *pJob) { // schDropTaskInHashList(pJob, pJob->failTasks); } -int32_t schCancelJob(SSchJob *pJob) { - // TODO - return TSDB_CODE_SUCCESS; - // TODO MOVE ALL TASKS FROM EXEC LIST TO FAIL LIST -} - void schFreeJobImpl(void *job) { if (NULL == job) { return; @@ -603,10 +595,6 @@ void schFreeJobImpl(void *job) { qDebug("QID:0x%" PRIx64 " begin to free sch job, refId:0x%" PRIx64 ", pointer:%p", queryId, refId, pJob); - if (pJob->status == JOB_TASK_STATUS_EXEC) { - schCancelJob(pJob); - } - schDropJobAllTasks(pJob); int32_t numOfLevels = taosArrayGetSize(pJob->levels); @@ -655,34 +643,21 @@ int32_t schJobFetchRows(SSchJob *pJob) { int32_t code = 0; if (!(pJob->attr.explainMode == EXPLAIN_MODE_STATIC)) { - SCH_ERR_JRET(schLaunchFetchTask(pJob)); - tsem_wait(&pJob->rspSem); + SCH_ERR_RET(schLaunchFetchTask(pJob)); + + if (pJob->opStatus.syncReq) { + SCH_JOB_DLOG("sync wait for rsp now, job status:%s", SCH_GET_JOB_STATUS_STR(pJob)); + tsem_wait(&pJob->rspSem); + schPostJobRes(pJob, SCH_OP_FETCH); + } + } else { + schPostJobRes(pJob, SCH_OP_FETCH); } - SCH_ERR_JRET(schDumpJobFetchRes(pJob, pJob->userRes.fetchRes)); - -_return: - - schEndOperation(pJob); - SCH_RET(code); } -int32_t schJobFetchRowsA(SSchJob *pJob) { - int32_t code = 0; - - if (pJob->attr.explainMode == EXPLAIN_MODE_STATIC) { - schPostJobRes(pJob, SCH_OP_FETCH); - return TSDB_CODE_SUCCESS; - } - - SCH_ERR_RET(schLaunchFetchTask(pJob)); - - return TSDB_CODE_SUCCESS; -} - - -int32_t schInitJob(SSchJob **pSchJob, SSchedulerReq *pReq) { +int32_t schInitJob(int64_t *pJobId, SSchedulerReq *pReq) { int32_t code = 0; int64_t refId = -1; SSchJob *pJob = taosMemoryCalloc(1, sizeof(SSchJob)); @@ -698,7 +673,7 @@ int32_t schInitJob(SSchJob **pSchJob, SSchedulerReq *pReq) { pJob->chkKillFp = pReq->chkKillFp; pJob->chkKillParam = pReq->chkKillParam; pJob->userRes.execFp = pReq->execFp; - pJob->userRes.userParam = pReq->execParam; + pJob->userRes.cbParam = pReq->cbParam; pJob->opStatus.op = SCH_OP_EXEC; pJob->opStatus.syncReq = pReq->syncReq; @@ -730,35 +705,28 @@ int32_t schInitJob(SSchJob **pSchJob, SSchedulerReq *pReq) { tsem_init(&pJob->rspSem, 0, 0); - refId = taosAddRef(schMgmt.jobRef, pJob); - if (refId < 0) { + pJob->refId = taosAddRef(schMgmt.jobRef, pJob); + if (pJob->refId < 0) { SCH_JOB_ELOG("taosAddRef job failed, error:%s", tstrerror(terrno)); SCH_ERR_JRET(terrno); } atomic_add_fetch_32(&schMgmt.jobNum, 1); - if (NULL == schAcquireJob(refId)) { - SCH_JOB_ELOG("schAcquireJob job failed, refId:0x%" PRIx64, refId); - SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR); - } - - pJob->refId = refId; + *pJobId = pJob->refId; SCH_JOB_DLOG("job refId:0x%" PRIx64" created", pJob->refId); - *pSchJob = pJob; - return TSDB_CODE_SUCCESS; _return: if (NULL == pJob) { qDestroyQueryPlan(pReq->pDag); - } else if (refId < 0) { + } else if (pJob->refId < 0) { schFreeJobImpl(pJob); } else { - taosRemoveRef(schMgmt.jobRef, refId); + taosRemoveRef(schMgmt.jobRef, pJob->refId); } SCH_RET(code); @@ -768,7 +736,7 @@ int32_t schExecJob(SSchJob *pJob, SSchedulerReq *pReq) { int32_t code = 0; qDebug("QID:0x%" PRIx64 " sch job refId 0x%"PRIx64 " started", pReq->pDag->queryId, pJob->refId); - SCH_ERR_JRET(schLaunchJob(pJob)); + SCH_ERR_RET(schLaunchJob(pJob)); if (pReq->syncReq) { SCH_JOB_DLOG("sync wait for rsp now, job status:%s", SCH_GET_JOB_STATUS_STR(pJob)); @@ -778,83 +746,148 @@ int32_t schExecJob(SSchJob *pJob, SSchedulerReq *pReq) { SCH_JOB_DLOG("job exec done, job status:%s, jobId:0x%" PRIx64, SCH_GET_JOB_STATUS_STR(pJob), pJob->refId); return TSDB_CODE_SUCCESS; - -_return: - - SCH_RET(schProcessOnJobFailure(pJob, code)); } -void schProcessOnOpEnd(SSchJob *pJob) { - int32_t op = atomic_load_32(&pJob->opStatus.op); - if (SCH_OP_NULL == op) { - SCH_JOB_DLOG("job already not in any operation, status:%s", jobTaskStatusStr(pJob->status)); - return; - } - - atomic_store_32(&pJob->opStatus.op, SCH_OP_NULL); - - SCH_JOB_DLOG("job end %s operation", schGetOpStr(op)); -} - -int32_t schProcessOnOpBegin(SSchJob* pJob, SSchEvent* pEvent) { - int32_t code = 0; - int8_t status = 0; - SSchOpEvent* pInfo = (SSchOpEvent*)pEvent->info; - SCH_OP_TYPE type, bool sync; - - if (schJobNeedToStop(pJob, &status)) { - SCH_JOB_ELOG("abort op %s cause of job need to stop", schGetOpStr(type)); - SCH_ERR_JRET(pJob->errCode); - } - - if (SCH_OP_NULL != atomic_val_compare_exchange_32(&pJob->opStatus.op, SCH_OP_NULL, type)) { - SCH_JOB_ELOG("job already in %s operation", schGetOpStr(pJob->opStatus.op)); - SCH_ERR_JRET(TSDB_CODE_TSC_APP_ERROR); - } - - SCH_JOB_DLOG("job start %s operation", schGetOpStr(pJob->opStatus.op)); - - pJob->opStatus.syncReq = sync; - +void schProcessOnOpEnd(SSchJob *pJob, SCH_OP_TYPE type, SSchedulerReq* pReq, int32_t errCode) { switch (type) { case SCH_OP_EXEC: - SCH_ERR_JRET(schUpdateJobStatus(pJob, JOB_TASK_STATUS_EXEC)); + int32_t op = atomic_val_compare_exchange_32(&pJob->opStatus.op, type, SCH_OP_NULL); + if (SCH_OP_NULL == op || op != type) { + SCH_JOB_ELOG("job not in %s operation, op:%s, status:%s", schGetOpStr(type), schGetOpStr(op), jobTaskStatusStr(pJob->status)); + } + + if (pReq) { + schDumpJobExecRes(pJob, pReq->pExecRes); + } break; case SCH_OP_FETCH: + int32_t op = atomic_val_compare_exchange_32(&pJob->opStatus.op, type, SCH_OP_NULL); + if (SCH_OP_NULL == op || op != type) { + SCH_JOB_ELOG("job not in %s operation, op:%s, status:%s", schGetOpStr(type), schGetOpStr(op), jobTaskStatusStr(pJob->status)); + } + break; + case SCH_OP_GET_STATUS: + errCode = TSDB_CODE_SUCCESS; + break; + default: + break; + } + + if (errCode) { + schSwitchJobStatus(pJob, JOB_TASK_STATUS_FAIL, errCode); + } + + SCH_JOB_DLOG("job end %s operation with code %s", schGetOpStr(type), tstrerror(errCode)); +} + +int32_t schProcessOnOpBegin(SSchJob* pJob, SCH_OP_TYPE type, SSchedulerReq* pReq) { + int32_t code = 0; + int8_t status = 0; + + if (schJobNeedToStop(pJob, &status)) { + SCH_JOB_ELOG("abort op %s cause of job need to stop, status:%s", schGetOpStr(type), jobTaskStatusStr(status)); + SCH_ERR_RET(TSDB_CODE_SCH_IGNORE_ERROR); + } + + switch (type) { + case SCH_OP_EXEC: + if (SCH_OP_NULL != atomic_val_compare_exchange_32(&pJob->opStatus.op, SCH_OP_NULL, type)) { + SCH_JOB_ELOG("job already in %s operation", schGetOpStr(pJob->opStatus.op)); + SCH_ERR_RET(TSDB_CODE_TSC_APP_ERROR); + } + + SCH_JOB_DLOG("job start %s operation", schGetOpStr(pJob->opStatus.op)); + + pJob->opStatus.syncReq = pReq->syncReq; + break; + case SCH_OP_FETCH: + if (SCH_OP_NULL != atomic_val_compare_exchange_32(&pJob->opStatus.op, SCH_OP_NULL, type)) { + SCH_JOB_ELOG("job already in %s operation", schGetOpStr(pJob->opStatus.op)); + SCH_ERR_RET(TSDB_CODE_TSC_APP_ERROR); + } + + SCH_JOB_DLOG("job start %s operation", schGetOpStr(pJob->opStatus.op)); + + pJob->opStatus.syncReq = pReq->syncReq; + if (!SCH_JOB_NEED_FETCH(pJob)) { SCH_JOB_ELOG("no need to fetch data, status:%s", SCH_GET_JOB_STATUS_STR(pJob)); - SCH_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); + SCH_ERR_RET(TSDB_CODE_QRY_APP_ERROR); } if (status != JOB_TASK_STATUS_PART_SUCC) { SCH_JOB_ELOG("job status error for fetch, status:%s", jobTaskStatusStr(status)); - SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR); + SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); + } + + pJob->userRes.fetchRes = pReq->pFetchRes; + pJob->userRes.fetchFp = pReq->fetchFp; + pJob->userRes.cbParam = pReq->cbParam; + + break; + case SCH_OP_GET_STATUS: + if (pJob->status < JOB_TASK_STATUS_INIT || pJob->levelNum <= 0 || NULL == pJob->levels) { + qDebug("job not initialized or not executable job, refId:0x%" PRIx64, pJob->refId); + SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); } break; default: SCH_JOB_ELOG("unknown operation type %d", type); - SCH_ERR_JRET(TSDB_CODE_TSC_APP_ERROR); + SCH_ERR_RET(TSDB_CODE_TSC_APP_ERROR); } + return TSDB_CODE_SUCCESS; +} + +void schProcessOnCbEnd(SSchJob *pJob, SSchTask *pTask, int32_t errCode) { + if (pTask) { + SCH_UNLOCK_TASK(pTask); + } + + if (errCode) { + schSwitchJobStatus(pJob, JOB_TASK_STATUS_FAIL, errCode); + } + + if (pJob) { + schReleaseJob(pJob->refId); + } +} + +int32_t schProcessOnCbBegin(SSchJob** job, SSchTask** task, uint64_t qId, int64_t rId, uint64_t tId) { + int32_t code = 0; + int8_t status = 0; + + SSchTask *pTask = NULL; + SSchJob *pJob = schAcquireJob(rId); + if (NULL == pJob) { + qWarn("QID:0x%" PRIx64 ",TID:0x%" PRIx64 "job no exist, may be dropped, refId:0x%" PRIx64, qId, tId, rId); + SCH_ERR_RET(TSDB_CODE_QRY_JOB_NOT_EXIST); + } + + int8_t status = 0; + if (schJobNeedToStop(pJob, &status)) { + SCH_TASK_ELOG("will not do further processing cause of job status %s", jobTaskStatusStr(status)); + SCH_ERR_JRET(TSDB_CODE_SCH_IGNORE_ERROR); + } + + SCH_ERR_JRET(schGetTaskInJob(pJob, tId, &pTask)); + + SCH_LOCK_TASK(pTask); + return TSDB_CODE_SUCCESS; _return: - schEndOperation(pJob); - + if (pTask) { + SCH_UNLOCK_TASK(pTask); + } + if (pJob) { + schReleaseJob(rId); + } + SCH_RET(code); } -int32_t schHandleJobEvent(SSchJob* pJob, SSchEvent* pEvent) { - switch (pEvent->event) { - case SCH_EVENT_BEGIN_OP: - schProcessOnOpBegin(pJob, pEvent); - case SCH_EVENT_END_OP: - schProcessOnOpEnd(pJob); - } -} - - diff --git a/source/libs/scheduler/src/schRemote.c b/source/libs/scheduler/src/schRemote.c index 479d3665a4..64368162e3 100644 --- a/source/libs/scheduler/src/schRemote.c +++ b/source/libs/scheduler/src/schRemote.c @@ -88,9 +88,21 @@ int32_t schValidateReceivedMsgType(SSchJob *pJob, SSchTask *pTask, int32_t msgTy } // Note: no more task error processing, handled in function internal -int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, char *msg, int32_t msgSize, - int32_t rspCode) { +int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t execId, SDataBuf *pMsg, int32_t rspCode) { int32_t code = 0; + char *msg = pMsg->pData; + int32_t msgSize = pMsg->len; + int32_t msgType = pMsg->msgType; + + bool dropExecNode = (msgType == TDMT_SCH_LINK_BROKEN || SCH_NETWORK_ERR(rspCode)); + SCH_ERR_JRET(schUpdateTaskHandle(pJob, pTask, dropExecNode, pMsg->handle, execId)); + + SCH_ERR_JRET(schValidateReceivedMsgType(pJob, pTask, msgType)); + + int32_t reqType = IsReq(pMsg) ? pMsg->msgType : (pMsg->msgType - 1); + if (SCH_NEED_REDIRECT(reqType, rspCode, pMsg->len)) { + SCH_RET(schHandleRedirect(pJob, pTask, (SDataBuf *)pMsg, rspCode)); + } switch (msgType) { case TDMT_VND_CREATE_TABLE_RSP: { @@ -362,65 +374,24 @@ _return: int32_t schHandleCallback(void *param, SDataBuf *pMsg, int32_t rspCode) { int32_t code = 0; - int32_t msgType = pMsg->msgType; SSchTaskCallbackParam *pParam = (SSchTaskCallbackParam *)param; SSchTask *pTask = NULL; + SSchJob *pJob = NULL; - SSchJob *pJob = schAcquireJob(pParam->refId); - if (NULL == pJob) { - qWarn("QID:0x%" PRIx64 ",TID:0x%" PRIx64 "taosAcquireRef job failed, may be dropped, refId:0x%" PRIx64, - pParam->queryId, pParam->taskId, pParam->refId); - SCH_ERR_JRET(TSDB_CODE_QRY_JOB_FREED); - } + SCH_TASK_DLOG("begin to handle rsp msg, type:%s, handle:%p, code:%s", TMSG_INFO(pMsg->msgType), pMsg->handle, tstrerror(rspCode)); - SCH_ERR_JRET(schGetTaskInJob(pJob, pParam->taskId, &pTask)); - - SCH_LOCK_TASK(pTask); + SCH_ERR_RET(schProcessOnCbBegin(&pJob, &pTask, pParam->queryId, pParam->refId, pParam->taskId)); - SCH_TASK_DLOG("rsp msg received, type:%s, handle:%p, code:%s", TMSG_INFO(msgType), pMsg->handle, tstrerror(rspCode)); - - if (pParam->execId != pTask->execId) { - SCH_TASK_DLOG("execId %d mis-match current execId %d", pParam->execId, pTask->execId); - goto _return; - } - - bool dropExecNode = (msgType == TDMT_SCH_LINK_BROKEN || SCH_NETWORK_ERR(rspCode)); - SCH_ERR_JRET(schUpdateTaskHandle(pJob, pTask, dropExecNode, pMsg->handle, pParam->execId)); - - int8_t status = 0; - if (schJobNeedToStop(pJob, &status)) { - SCH_TASK_ELOG("rsp will not be processed cause of job status %s, rspCode:0x%x", jobTaskStatusStr(status), rspCode); - code = atomic_load_32(&pJob->errCode); - goto _return; - } - - SCH_ERR_JRET(schValidateReceivedMsgType(pJob, pTask, msgType)); - - int32_t reqType = IsReq(pMsg) ? pMsg->msgType : (pMsg->msgType - 1); - if (SCH_NEED_REDIRECT(reqType, rspCode, pMsg->len)) { - code = schHandleRedirect(pJob, pTask, (SDataBuf *)pMsg, rspCode); - goto _return; - } - - schHandleResponseMsg(pJob, pTask, msgType, pMsg->pData, pMsg->len, rspCode); + code = schHandleResponseMsg(pJob, pTask, pParam->execId, pMsg, rspCode); pMsg->pData = NULL; -_return: - - if (pTask) { - if (code) { - schProcessOnTaskFailure(pJob, pTask, code); - } - - SCH_UNLOCK_TASK(pTask); - } - - if (pJob) { - schReleaseJob(pParam->refId); - } + schProcessOnCbEnd(pJob, pTask, code); taosMemoryFreeClear(pMsg->pData); taosMemoryFreeClear(param); + + SCH_TASK_DLOG("end to handle rsp msg, type:%s, handle:%p, code:%s", TMSG_INFO(pMsg->msgType), pMsg->handle, tstrerror(rspCode)); + SCH_RET(code); } @@ -451,6 +422,37 @@ int32_t schHandleLinkBrokenCallback(void *param, SDataBuf *pMsg, int32_t code) { } +int32_t schHandleHbCallback(void *param, SDataBuf *pMsg, int32_t code) { + SSchedulerHbRsp rsp = {0}; + SSchTaskCallbackParam *pParam = (SSchTaskCallbackParam *)param; + + if (code) { + qError("hb rsp error:%s", tstrerror(code)); + SCH_ERR_JRET(code); + } + + if (tDeserializeSSchedulerHbRsp(pMsg->pData, pMsg->len, &rsp)) { + qError("invalid hb rsp msg, size:%d", pMsg->len); + SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT); + } + + SSchTrans trans = {0}; + trans.pTrans = pParam->pTrans; + trans.pHandle = pMsg->handle; + + SCH_ERR_JRET(schUpdateHbConnection(&rsp.epId, &trans)); + + SCH_ERR_JRET(schProcessOnTaskStatusRsp(&rsp.epId, rsp.taskStatus)); + +_return: + + tFreeSSchedulerHbRsp(&rsp); + taosMemoryFree(param); + + SCH_RET(code); +} + + int32_t schMakeCallbackParam(SSchJob *pJob, SSchTask *pTask, int32_t msgType, bool isHb, SSchTrans *trans, void **pParam) { if (!isHb) { SSchTaskCallbackParam *param = taosMemoryCalloc(1, sizeof(SSchTaskCallbackParam)); @@ -692,36 +694,6 @@ _return: SCH_RET(code); } -int32_t schHandleHbCallback(void *param, SDataBuf *pMsg, int32_t code) { - SSchedulerHbRsp rsp = {0}; - SSchTaskCallbackParam *pParam = (SSchTaskCallbackParam *)param; - - if (code) { - qError("hb rsp error:%s", tstrerror(code)); - SCH_ERR_JRET(code); - } - - if (tDeserializeSSchedulerHbRsp(pMsg->pData, pMsg->len, &rsp)) { - qError("invalid hb rsp msg, size:%d", pMsg->len); - SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT); - } - - SSchTrans trans = {0}; - trans.pTrans = pParam->pTrans; - trans.pHandle = pMsg->handle; - - SCH_ERR_JRET(schUpdateHbConnection(&rsp.epId, &trans)); - - SCH_ERR_JRET(schProcessOnTaskStatusRsp(&rsp.epId, rsp.taskStatus)); - -_return: - - tFreeSSchedulerHbRsp(&rsp); - taosMemoryFree(param); - - SCH_RET(code); -} - int32_t schMakeBrokenLinkVal(SSchJob *pJob, SSchTask *pTask, SRpcBrokenlinkVal *brokenVal, bool isHb) { int32_t code = 0; int32_t msgType = TDMT_SCH_LINK_BROKEN; diff --git a/source/libs/scheduler/src/schStatus.c b/source/libs/scheduler/src/schStatus.c index c6f5c23024..55bc600eca 100644 --- a/source/libs/scheduler/src/schStatus.c +++ b/source/libs/scheduler/src/schStatus.c @@ -21,56 +21,66 @@ #include "tref.h" #include "trpc.h" -SSchStatusFps gSchJobFps[JOB_TASK_STATUS_MAX] = { - {JOB_TASK_STATUS_NULL, schJobStNullEnter, schJobStNullLeave, schJobStNullEvent}, - {JOB_TASK_STATUS_INIT, schJobStNullEnter, schJobStNullLeave, schJobStNullEvent}, - {JOB_TASK_STATUS_EXEC, schJobStNullEnter, schJobStNullLeave, schJobStNullEvent}, - {JOB_TASK_STATUS_PART_SUCC, schJobStNullEnter, schJobStNullLeave, schJobStNullEvent}, - {JOB_TASK_STATUS_SUCC, schJobStNullEnter, schJobStNullLeave, schJobStNullEvent}, - {JOB_TASK_STATUS_FAIL, schJobStNullEnter, schJobStNullLeave, schJobStNullEvent}, - {JOB_TASK_STATUS_DROP, schJobStNullEnter, schJobStNullLeave, schJobStNullEvent}, -}; - -SSchStatusFps gSchTaskFps[JOB_TASK_STATUS_MAX] = { - {JOB_TASK_STATUS_NULL, schTaskStatusNullEnter, schTaskStatusNullLeave, schTaskStatusNullEvent}, - {JOB_TASK_STATUS_INIT, schTaskStatusNullEnter, schTaskStatusNullLeave, schTaskStatusNullEvent}, - {JOB_TASK_STATUS_EXEC, schTaskStatusNullEnter, schTaskStatusNullLeave, schTaskStatusNullEvent}, - {JOB_TASK_STATUS_PART_SUCC, schTaskStatusNullEnter, schTaskStatusNullLeave, schTaskStatusNullEvent}, - {JOB_TASK_STATUS_SUCC, schTaskStatusNullEnter, schTaskStatusNullLeave, schTaskStatusNullEvent}, - {JOB_TASK_STATUS_FAIL, schTaskStatusNullEnter, schTaskStatusNullLeave, schTaskStatusNullEvent}, - {JOB_TASK_STATUS_DROP, schTaskStatusNullEnter, schTaskStatusNullLeave, schTaskStatusNullEvent}, -}; - -int32_t schSwitchJobStatus(SSchJob** job, int32_t status, void* param) { - SCH_ERR_RET(schUpdateJobStatus(*job, status)); +int32_t schSwitchJobStatus(SSchJob* pJob, int32_t status, void* param) { + int32_t code = 0; + SCH_ERR_JRET(schUpdateJobStatus(pJob, status)); switch (status) { case JOB_TASK_STATUS_INIT: - SCH_RET(schInitJob(job, param)); + break; case JOB_TASK_STATUS_EXEC: - SCH_RET(schExecJob(job, param)); + SCH_ERR_JRET(schExecJob(pJob, (SSchedulerReq*)param)); + break; case JOB_TASK_STATUS_PART_SUCC: + SCH_ERR_JRET(schProcessOnJobPartialSuccess(pJob)); + break; + case JOB_TASK_STATUS_SUCC: + break; + case JOB_TASK_STATUS_FAIL: + SCH_RET(schProcessOnJobFailure(pJob, (int32_t)param)); + break; + case JOB_TASK_STATUS_DROP: + SCH_ERR_JRET(schProcessOnJobDropped(pJob, (int32_t)param)); + + if (taosRemoveRef(schMgmt.jobRef, pJob->refId)) { + SCH_JOB_ELOG("remove job from job list failed, refId:0x%" PRIx64, pJob->refId); + } else { + SCH_JOB_DLOG("job removed from jobRef list, refId:0x%" PRIx64, pJob->refId); + } + break; default: { - SSchJob* pJob = *job; - SCH_JOB_ELOG("enter unknown job status %d", status); + SCH_JOB_ELOG("unknown job status %d", status); SCH_RET(TSDB_CODE_SCH_STATUS_ERROR); } } return TSDB_CODE_SUCCESS; + +_return: + + SCH_RET(schProcessOnJobFailure(pJob, code)); } -int32_t schHandleOpBeginEvent(SSchJob* pJob, SCH_OP_TYPE type, SSchedulerReq* pReq) { - SSchEvent event = {0}; - event.event = SCH_EVENT_BEGIN_OP; - SSchOpEvent opEvent = {0}; - opEvent.type = type; - opEvent.begin = true; - opEvent.pReq = pReq; +int32_t schHandleOpBeginEvent(int64_t jobId, SSchJob** job, SCH_OP_TYPE type, SSchedulerReq* pReq) { + SSchJob *pJob = schAcquireJob(jobId); + if (NULL == pJob) { + qError("Acquire sch job failed, may be dropped, jobId:0x%" PRIx64, jobId); + SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); + } - SCH_ERR_RET(schHandleJobEvent(pJob, &event)); + *job = pJob; + + SCH_RET(schProcessOnOpBegin(pJob, type, pReq)); +} + +void schHandleOpEndEvent(SSchJob* pJob, SCH_OP_TYPE type, SSchedulerReq* pReq, int32_t errCode) { + if (NULL == pJob) { + return; + } + + schProcessOnOpEnd(pJob, type, pReq, errCode); + + schReleaseJob(pJob->refId); } - - diff --git a/source/libs/scheduler/src/schTask.c b/source/libs/scheduler/src/schTask.c index 0e1d749533..1f89b59137 100644 --- a/source/libs/scheduler/src/schTask.c +++ b/source/libs/scheduler/src/schTask.c @@ -102,7 +102,7 @@ int32_t schDropTaskExecNode(SSchJob *pJob, SSchTask *pTask, void *handle, int32_ if (execId != pTask->execId) { // ignore it SCH_TASK_DLOG("execId %d is not current execId %d", execId, pTask->execId); - SCH_RET(TSDB_CODE_SCH_IGNORE_ERROR); + SCH_ERR_RET(TSDB_CODE_SCH_IGNORE_ERROR); } return TSDB_CODE_SUCCESS; @@ -135,18 +135,26 @@ int32_t schUpdateTaskHandle(SSchJob *pJob, SSchTask *pTask, bool dropExecNode, v // Note: no more task error processing, handled in function internal int32_t schProcessOnTaskFailure(SSchJob *pJob, SSchTask *pTask, int32_t errCode) { + if (TSDB_CODE_SCH_IGNORE_ERROR == errCode) { + return TSDB_CODE_SCH_IGNORE_ERROR; + } + int8_t status = 0; + if (schJobNeedToStop(pJob, &status)) { + SCH_TASK_DLOG("no more task failure processing cause of job status %s", jobTaskStatusStr(status)); + SCH_ERR_RET(TSDB_CODE_SCH_IGNORE_ERROR); + } + + if (SCH_GET_TASK_STATUS(pTask) != JOB_TASK_STATUS_EXEC) { + SCH_TASK_ELOG("task already not in EXEC status, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); + SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); + } if (errCode == TSDB_CODE_SCH_TIMEOUT_ERROR) { SCH_LOG_TASK_WAIT_TS(pTask); } else { SCH_LOG_TASK_END_TS(pTask); } - - if (schJobNeedToStop(pJob, &status)) { - SCH_TASK_DLOG("task failed not processed cause of job status, job status:%s", jobTaskStatusStr(status)); - SCH_RET(atomic_load_32(&pJob->errCode)); - } bool needRetry = false; bool moved = false; @@ -155,16 +163,11 @@ int32_t schProcessOnTaskFailure(SSchJob *pJob, SSchTask *pTask, int32_t errCode) SCH_TASK_DLOG("taskOnFailure, code:%s", tstrerror(errCode)); - SCH_ERR_JRET(schTaskCheckSetRetry(pJob, pTask, errCode, &needRetry)); + SCH_ERR_RET(schTaskCheckSetRetry(pJob, pTask, errCode, &needRetry)); if (!needRetry) { SCH_TASK_ELOG("task failed and no more retry, code:%s", tstrerror(errCode)); - if (SCH_GET_TASK_STATUS(pTask) != JOB_TASK_STATUS_EXEC) { - SCH_TASK_ELOG("task not in executing list, status:%s", SCH_GET_TASK_STATUS_STR(pTask)); - SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR); - } - SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_FAIL); if (SCH_IS_WAIT_ALL_JOB(pJob)) { @@ -181,14 +184,12 @@ int32_t schProcessOnTaskFailure(SSchJob *pJob, SSchTask *pTask, int32_t errCode) } } } else { - SCH_ERR_JRET(schHandleTaskRetry(pJob, pTask)); + SCH_ERR_RET(schHandleTaskRetry(pJob, pTask)); return TSDB_CODE_SUCCESS; } -_return: - - SCH_RET(schProcessOnJobFailure(pJob, errCode)); + SCH_RET(code); } @@ -204,9 +205,9 @@ int32_t schProcessOnTaskSuccess(SSchJob *pJob, SSchTask *pTask) { SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_PART_SUCC); - SCH_ERR_JRET(schRecordTaskSucceedNode(pJob, pTask)); + SCH_ERR_RET(schRecordTaskSucceedNode(pJob, pTask)); - SCH_ERR_JRET(schLaunchTasksInFlowCtrlList(pJob, pTask)); + SCH_ERR_RET(schLaunchTasksInFlowCtrlList(pJob, pTask)); int32_t parentNum = pTask->parents ? (int32_t)taosArrayGetSize(pTask->parents) : 0; if (parentNum == 0) { @@ -225,9 +226,9 @@ int32_t schProcessOnTaskSuccess(SSchJob *pJob, SSchTask *pTask) { } if (pTask->level->taskFailed > 0) { - SCH_RET(schProcessOnJobFailure(pJob, 0)); + SCH_RET(schSwitchJobStatus(pJob, JOB_TASK_STATUS_FAIL, 0)); } else { - SCH_RET(schProcessOnJobPartialSuccess(pJob)); + SCH_RET(schSwitchJobStatus(pJob, JOB_TASK_STATUS_PART_SUCC, NULL)); } } else { pJob->resNode = pTask->succeedAddr; @@ -235,7 +236,7 @@ int32_t schProcessOnTaskSuccess(SSchJob *pJob, SSchTask *pTask) { pJob->fetchTask = pTask; - SCH_RET(schProcessOnJobPartialSuccess(pJob)); + SCH_RET(schSwitchJobStatus(pJob, JOB_TASK_STATUS_PART_SUCC, NULL)); } /* @@ -269,10 +270,6 @@ int32_t schProcessOnTaskSuccess(SSchJob *pJob, SSchTask *pTask) { SCH_ERR_RET(schLaunchJobLowerLevel(pJob, pTask)); return TSDB_CODE_SUCCESS; - -_return: - - SCH_RET(schProcessOnJobFailure(pJob, code)); } int32_t schRescheduleTask(SSchJob *pJob, SSchTask *pTask) { @@ -280,15 +277,14 @@ int32_t schRescheduleTask(SSchJob *pJob, SSchTask *pTask) { return TSDB_CODE_SUCCESS; } - SCH_LOCK_TASK(pTask); if (SCH_TASK_TIMEOUT(pTask) && JOB_TASK_STATUS_EXEC == pTask->status && pJob->fetchTask != pTask && taosArrayGetSize(pTask->candidateAddrs) > 1) { SCH_TASK_DLOG("task execId %d will be rescheduled now", pTask->execId); schDropTaskOnExecNode(pJob, pTask); taosHashClear(pTask->execNodes); - schProcessOnTaskFailure(pJob, pTask, TSDB_CODE_SCH_TIMEOUT_ERROR); + + SCH_ERR_RET(schProcessOnTaskFailure(pJob, pTask, TSDB_CODE_SCH_TIMEOUT_ERROR)); } - SCH_UNLOCK_TASK(pTask); return TSDB_CODE_SUCCESS; } @@ -298,7 +294,7 @@ int32_t schDoTaskRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf* pData, int32 if ((pTask->execId + 1) >= pTask->maxExecTimes) { SCH_TASK_DLOG("task no more retry since reach max try times, execId:%d", pTask->execId); - schProcessOnJobFailure(pJob, rspCode); + schSwitchJobStatus(pJob, JOB_TASK_STATUS_FAIL, (void*)rspCode); return TSDB_CODE_SUCCESS; } @@ -353,9 +349,7 @@ int32_t schDoTaskRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf* pData, int32 _return: - code = schProcessOnTaskFailure(pJob, pTask, code); - - SCH_RET(code); + SCH_RET(schProcessOnTaskFailure(pJob, pTask, code)); } int32_t schHandleRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf* pData, int32_t rspCode) { @@ -372,9 +366,7 @@ int32_t schHandleRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf* pData, int32 _return: - schProcessOnTaskFailure(pJob, pTask, code); - - SCH_RET(code); + SCH_RET(schProcessOnTaskFailure(pJob, pTask, code)); } int32_t schPushTaskToExecList(SSchJob *pJob, SSchTask *pTask) { @@ -679,49 +671,39 @@ void schDropTaskOnExecNode(SSchJob *pJob, SSchTask *pTask) { int32_t schProcessOnTaskStatusRsp(SQueryNodeEpId* pEpId, SArray* pStatusList) { int32_t taskNum = (int32_t)taosArrayGetSize(pStatusList); SSchTask *pTask = NULL; + SSchJob *pJob = NULL; qDebug("%d task status in hb rsp from nodeId:%d, fqdn:%s, port:%d", taskNum, pEpId->nodeId, pEpId->ep.fqdn, pEpId->ep.port); for (int32_t i = 0; i < taskNum; ++i) { - STaskStatus *taskStatus = taosArrayGet(pStatusList, i); - - qDebug("QID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d task status in server: %s", - taskStatus->queryId, taskStatus->taskId, taskStatus->execId, jobTaskStatusStr(taskStatus->status)); - - SSchJob *pJob = schAcquireJob(taskStatus->refId); - if (NULL == pJob) { - qWarn("job not found, refId:0x%" PRIx64 ",QID:0x%" PRIx64 ",TID:0x%" PRIx64, taskStatus->refId, - taskStatus->queryId, taskStatus->taskId); - // TODO DROP TASK FROM SERVER!!!! - continue; - } - - pTask = NULL; - schGetTaskInJob(pJob, taskStatus->taskId, &pTask); - if (NULL == pTask) { - // TODO DROP TASK FROM SERVER!!!! - schReleaseJob(taskStatus->refId); - continue; - } - - if (taskStatus->execId != pTask->execId) { - // TODO DROP TASK FROM SERVER!!!! - SCH_TASK_DLOG("EID %d in hb rsp mis-match", taskStatus->execId); - schReleaseJob(taskStatus->refId); - continue; - } + STaskStatus *pStatus = taosArrayGet(pStatusList, i); + int32_t code = 0; - if (taskStatus->status == JOB_TASK_STATUS_FAIL) { - // RECORD AND HANDLE ERROR!!!! - schReleaseJob(taskStatus->refId); + qDebug("QID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d task status in server: %s", + pStatus->queryId, pStatus->taskId, pStatus->execId, jobTaskStatusStr(pStatus->status)); + + if (schProcessOnCbBegin(&pJob, &pTask, pStatus->queryId, pStatus->refId, pStatus->taskId)) { continue; } - if (taskStatus->status == JOB_TASK_STATUS_INIT) { - schRescheduleTask(pJob, pTask); + if (pStatus->execId != pTask->execId) { + //TODO + SCH_TASK_DLOG("execId %d mis-match current execId %d", pStatus->execId, pTask->execId); + schProcessOnCbEnd(pJob, pTask, 0); + continue; + } + + if (pStatus->status == JOB_TASK_STATUS_FAIL) { + // RECORD AND HANDLE ERROR!!!! + schProcessOnCbEnd(pJob, pTask, 0); + continue; } - schReleaseJob(taskStatus->refId); + if (pStatus->status == JOB_TASK_STATUS_INIT) { + code = schRescheduleTask(pJob, pTask); + } + + schProcessOnCbEnd(pJob, pTask, code); } return TSDB_CODE_SUCCESS; @@ -739,9 +721,8 @@ int32_t schLaunchTaskImpl(SSchJob *pJob, SSchTask *pTask) { SCH_LOG_TASK_START_TS(pTask); if (schJobNeedToStop(pJob, &status)) { - SCH_TASK_DLOG("no need to launch task cause of job status, job status:%s", jobTaskStatusStr(status)); - - SCH_RET(atomic_load_32(&pJob->errCode)); + SCH_TASK_DLOG("no need to launch task cause of job status %s", jobTaskStatusStr(status)); + SCH_ERR_RET(TSDB_CODE_SCH_IGNORE_ERROR); } // NOTE: race condition: the task should be put into the hash table before send msg to server diff --git a/source/libs/scheduler/src/schUtil.c b/source/libs/scheduler/src/schUtil.c index 38a04d1433..36a8475a34 100644 --- a/source/libs/scheduler/src/schUtil.c +++ b/source/libs/scheduler/src/schUtil.c @@ -43,6 +43,8 @@ char* schGetOpStr(SCH_OP_TYPE type) { return "EXEC"; case SCH_OP_FETCH: return "FETCH"; + case SCH_OP_GET_STATUS: + return "GET STATUS"; default: return "UNKNOWN"; } diff --git a/source/libs/scheduler/src/scheduler.c b/source/libs/scheduler/src/scheduler.c index 8629bdf8b9..65ab9c7659 100644 --- a/source/libs/scheduler/src/scheduler.c +++ b/source/libs/scheduler/src/scheduler.c @@ -73,93 +73,39 @@ int32_t schedulerExecJob(SSchedulerReq *pReq, int64_t *pJobId) { int32_t code = 0; SSchJob *pJob = NULL; - *pJobId = 0; + SCH_ERR_JRET(schInitJob(pJobId, pReq)); - SCH_ERR_RET(schSwitchJobStatus(&pJob, JOB_TASK_STATUS_INIT, pReq)); + SCH_ERR_JRET(schHandleOpBeginEvent(*pJobId, &pJob, SCH_OP_EXEC, pReq)); - SCH_ERR_RET(schHandleOpBeginEvent(pJob, SCH_OP_EXEC, pReq)); - - SCH_ERR_RET(schSwitchJobStatus(&pJob, JOB_TASK_STATUS_EXEC, pReq)); + SCH_ERR_JRET(schSwitchJobStatus(pJob, JOB_TASK_STATUS_INIT, pReq)); - SCH_ERR_RET(schHandleOpEndEvent(pJob, SCH_OP_EXEC, pReq)); - - *pJobId = pJob->refId; + SCH_ERR_JRET(schSwitchJobStatus(pJob, JOB_TASK_STATUS_EXEC, pReq)); _return: - schDumpJobExecRes(pJob, pReq->pQueryRes); - - schReleaseJob(pJob->refId); - - return code; + SCH_RET(schHandleOpEndEvent(pJob, SCH_OP_EXEC, pReq, code)); } -int32_t schedulerFetchRows(int64_t job, SSchedulerReq *pReq) { +int32_t schedulerFetchRows(int64_t jobId, SSchedulerReq *pReq) { qDebug("scheduler %s fetch rows start", pReq->syncReq ? "SYNC" : "ASYNC"); int32_t code = 0; - SSchJob *pJob = schAcquireJob(job); - if (NULL == pJob) { - qError("acquire job from jobRef list failed, may be dropped, jobId:0x%" PRIx64, job); - SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); - } + SSchJob *pJob = NULL; - SCH_ERR_RET(schHandleOpBeginEvent(pJob, SCH_OP_FETCH, pReq)); + SCH_ERR_JRET(schHandleOpBeginEvent(jobId, &pJob, SCH_OP_FETCH, pReq)); - - - SCH_ERR_RET(schBeginOperation(pJob, SCH_OP_FETCH, true)); - - pJob->userRes.fetchRes = pData; - code = schJobFetchRows(pJob); - - schReleaseJob(job); - - SCH_RET(code); -} - -void schedulerFetchRowsA(int64_t job, schedulerFetchFp fp, void* param) { - qDebug("scheduler async fetch rows start"); - - int32_t code = 0; - if (NULL == fp || NULL == param) { - SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT); - } - - SSchJob *pJob = schAcquireJob(job); - if (NULL == pJob) { - qError("acquire sch job from job list failed, may be dropped, jobId:0x%" PRIx64, job); - SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR); - } - - SCH_ERR_JRET(schBeginOperation(pJob, SCH_OP_FETCH, false)); - - pJob->userRes.fetchFp = fp; - pJob->userRes.userParam = param; - - SCH_ERR_JRET(schJobFetchRowsA(pJob)); + SCH_ERR_JRET(schJobFetchRows(pJob)); _return: - if (code) { - fp(NULL, param, code); - } - - schReleaseJob(job); + SCH_RET(schHandleOpEndEvent(pJob, SCH_OP_FETCH, pReq, code)); } -int32_t schedulerGetTasksStatus(int64_t job, SArray *pSub) { +int32_t schedulerGetTasksStatus(int64_t jobId, SArray *pSub) { int32_t code = 0; - SSchJob *pJob = schAcquireJob(job); - if (NULL == pJob) { - qDebug("acquire job from jobRef list failed, may not started or dropped, refId:0x%" PRIx64, job); - SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); - } + SSchJob *pJob = NULL; - if (pJob->status < JOB_TASK_STATUS_INIT || pJob->levelNum <= 0 || NULL == pJob->levels) { - qDebug("job not initialized or not executable job, refId:0x%" PRIx64, job); - SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR); - } + SCH_ERR_JRET(schHandleOpBeginEvent(jobId, &pJob, SCH_OP_GET_STATUS, NULL)); for (int32_t i = pJob->levelNum - 1; i >= 0; --i) { SSchLevel *pLevel = taosArrayGet(pJob->levels, i); @@ -176,23 +122,7 @@ int32_t schedulerGetTasksStatus(int64_t job, SArray *pSub) { _return: - schReleaseJob(job); - - SCH_RET(code); -} - -int32_t scheduleCancelJob(int64_t job) { - SSchJob *pJob = schAcquireJob(job); - if (NULL == pJob) { - qError("acquire job from jobRef list failed, may be dropped, jobId:0x%" PRIx64, job); - SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); - } - - int32_t code = schCancelJob(pJob); - - schReleaseJob(job); - - SCH_RET(code); + SCH_RET(schHandleOpEndEvent(pJob, SCH_OP_GET_STATUS, NULL, code)); } void schedulerStopQueryHb(void *pTrans) { @@ -203,33 +133,23 @@ void schedulerStopQueryHb(void *pTrans) { schCleanClusterHb(pTrans); } -void schedulerFreeJob(int64_t* job, int32_t errCode) { - if (0 == *job) { +void schedulerFreeJob(int64_t* jobId, int32_t errCode) { + if (0 == *jobId) { return; } - - SSchJob *pJob = schAcquireJob(*job); + + SSchJob *pJob = schAcquireJob(*jobId); if (NULL == pJob) { - qError("acquire sch job failed, may be dropped, jobId:0x%" PRIx64, *job); - *job = 0; + qError("Acquire sch job failed, may be dropped, jobId:0x%" PRIx64, *jobId); return; } - int32_t code = schProcessOnJobDropped(pJob, errCode); - if (TSDB_CODE_SCH_JOB_IS_DROPPING == code) { - SCH_JOB_DLOG("sch job is already dropping, refId:0x%" PRIx64, *job); - *job = 0; + if (schJobDone(pJob)) { return; } - SCH_JOB_DLOG("start to remove job from jobRef list, refId:0x%" PRIx64, *job); - - if (taosRemoveRef(schMgmt.jobRef, *job)) { - SCH_JOB_ELOG("remove job from job list failed, refId:0x%" PRIx64, *job); - } - - schReleaseJob(*job); - *job = 0; + schSwitchJobStatus(pJob, JOB_TASK_STATUS_DROP, (void*)errCode); + *jobId = 0; } void schedulerDestroy(void) { diff --git a/source/libs/scheduler/test/schedulerTests.cpp b/source/libs/scheduler/test/schedulerTests.cpp index 245d8d362c..1a464b78ab 100644 --- a/source/libs/scheduler/test/schedulerTests.cpp +++ b/source/libs/scheduler/test/schedulerTests.cpp @@ -513,7 +513,7 @@ void* schtRunJobThread(void *aa) { req.pDag = &dag; req.sql = "select * from tb"; req.execFp = schtQueryCb; - req.execParam = &queryDone; + req.cbParam = &queryDone; code = schedulerExecJob(&req, &queryJobRefId); assert(code == 0); @@ -665,7 +665,7 @@ TEST(queryTest, normalCase) { req.pDag = &dag; req.sql = "select * from tb"; req.execFp = schtQueryCb; - req.execParam = &queryDone; + req.cbParam = &queryDone; code = schedulerExecJob(&req, &job); ASSERT_EQ(code, 0); @@ -769,7 +769,7 @@ TEST(queryTest, readyFirstCase) { req.pDag = &dag; req.sql = "select * from tb"; req.execFp = schtQueryCb; - req.execParam = &queryDone; + req.cbParam = &queryDone; code = schedulerExecJob(&req, &job); ASSERT_EQ(code, 0); @@ -876,7 +876,7 @@ TEST(queryTest, flowCtrlCase) { req.pDag = &dag; req.sql = "select * from tb"; req.execFp = schtQueryCb; - req.execParam = &queryDone; + req.cbParam = &queryDone; code = schedulerExecJob(&req, &job); ASSERT_EQ(code, 0); @@ -989,7 +989,7 @@ TEST(insertTest, normalCase) { req.pDag = &dag; req.sql = "insert into tb values(now,1)"; req.execFp = schtQueryCb; - req.execParam = NULL; + req.cbParam = NULL; code = schedulerExecJob(&req, &insertJobRefId, &res); ASSERT_EQ(code, 0); diff --git a/source/util/src/terror.c b/source/util/src/terror.c index 6e8b8b1595..e867af86af 100644 --- a/source/util/src/terror.c +++ b/source/util/src/terror.c @@ -393,6 +393,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_QRY_TASK_DROPPING, "Task dropping") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_DUPLICATTED_OPERATION, "Duplicatted operation") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_TASK_MSG_ERROR, "Task message error") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_JOB_FREED, "Job already freed") +TAOS_DEFINE_ERROR(TSDB_CODE_QRY_JOB_NOT_EXIST, "Job not exist") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_TASK_STATUS_ERROR, "Task status error") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_JSON_IN_ERROR, "Json not support in in/notin operator") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_JSON_NOT_SUPPORT_ERROR, "Json not support in this place") From 473ac84f2f4d608559f2830c9946bc323344417a Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Tue, 5 Jul 2022 18:12:01 +0800 Subject: [PATCH 6/9] fix: fix compile errors --- include/libs/qcom/query.h | 7 +++ include/libs/scheduler/scheduler.h | 15 ++---- source/client/src/clientImpl.c | 20 ++++---- source/client/src/clientMain.c | 2 +- source/libs/scheduler/inc/schInt.h | 40 ++++++++++----- source/libs/scheduler/src/schDbg.c | 6 +-- source/libs/scheduler/src/schFlowCtrl.c | 2 +- source/libs/scheduler/src/schJob.c | 49 +++++++++++-------- source/libs/scheduler/src/schRemote.c | 6 +-- source/libs/scheduler/src/schStatus.c | 16 ++++-- source/libs/scheduler/src/schTask.c | 6 +-- source/libs/scheduler/src/schUtil.c | 2 +- source/libs/scheduler/src/scheduler.c | 4 +- source/libs/scheduler/test/schedulerTests.cpp | 34 ++++++++----- 14 files changed, 125 insertions(+), 84 deletions(-) diff --git a/include/libs/qcom/query.h b/include/libs/qcom/query.h index 617b50aacc..a93cf1f9b8 100644 --- a/include/libs/qcom/query.h +++ b/include/libs/qcom/query.h @@ -68,6 +68,13 @@ typedef struct SIndexMeta { } SIndexMeta; +typedef struct SExecResult { + int32_t code; + uint64_t numOfRows; + int32_t msgType; + void* res; +} SExecResult; + typedef struct STbVerInfo { char tbFName[TSDB_TABLE_FNAME_LEN]; int32_t sversion; diff --git a/include/libs/scheduler/scheduler.h b/include/libs/scheduler/scheduler.h index ae4cbb498c..70ac7a6304 100644 --- a/include/libs/scheduler/scheduler.h +++ b/include/libs/scheduler/scheduler.h @@ -53,13 +53,6 @@ typedef struct SQueryProfileSummary { uint64_t resultSize; // generated result size in Kb. } SQueryProfileSummary; -typedef struct SExecResult { - int32_t code; - uint64_t numOfRows; - int32_t msgType; - void* res; -} SExecResult; - typedef struct STaskInfo { SQueryNodeAddr addr; SSubQueryMsg *msg; @@ -70,7 +63,7 @@ typedef struct SSchdFetchParam { int32_t* code; } SSchdFetchParam; -typedef void (*schedulerExecFp)(SQueryResult* pResult, void* param, int32_t code); +typedef void (*schedulerExecFp)(SExecResult* pResult, void* param, int32_t code); typedef void (*schedulerFetchFp)(void* pResult, void* param, int32_t code); typedef bool (*schedulerChkKillFp)(void* param); @@ -87,7 +80,7 @@ typedef struct SSchedulerReq { schedulerChkKillFp chkKillFp; void* chkKillParam; SExecResult* pExecRes; - char** pFetchRes; + void** pFetchRes; } SSchedulerReq; @@ -95,7 +88,7 @@ int32_t schedulerInit(SSchedulerCfg *cfg); int32_t schedulerExecJob(SSchedulerReq *pReq, int64_t *pJob); -int32_t schedulerFetchRows(int64_t job, void **data); +int32_t schedulerFetchRows(int64_t jobId, SSchedulerReq *pReq); void schedulerFetchRowsA(int64_t job, schedulerFetchFp fp, void* param); @@ -119,7 +112,7 @@ void schedulerFreeJob(int64_t* job, int32_t errCode); void schedulerDestroy(void); -void schdExecCallback(SQueryResult* pResult, void* param, int32_t code); +void schdExecCallback(SExecResult* pResult, void* param, int32_t code); #ifdef __cplusplus } diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index 3d43b3a9a1..542801954f 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -628,7 +628,7 @@ _return: int32_t scheduleQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNodeList) { void* pTransporter = pRequest->pTscObj->pAppInfo->pTransporter; - SQueryResult res = {0}; + SExecResult res = {0}; SRequestConnInfo conn = {.pTrans = pRequest->pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self}; @@ -640,14 +640,14 @@ int32_t scheduleQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNodeList .sql = pRequest->sqlstr, .startTs = pRequest->metric.start, .execFp = NULL, - .execParam = NULL, + .cbParam = NULL, .chkKillFp = chkRequestKilled, - .chkKillParam = (void*)pRequest->self - .pQueryRes = &res, + .chkKillParam = (void*)pRequest->self, + .pExecRes = &res, }; int32_t code = schedulerExecJob(&req, &pRequest->body.queryJob); - pRequest->body.resInfo.execRes = res.res; + memcpy(&pRequest->body.resInfo.execRes, &res, sizeof(res)); if (code != TSDB_CODE_SUCCESS) { schedulerFreeJob(&pRequest->body.queryJob, 0); @@ -784,10 +784,10 @@ int32_t handleQueryExecRsp(SRequestObj* pRequest) { return code; } -void schedulerExecCb(SQueryResult* pResult, void* param, int32_t code) { +void schedulerExecCb(SExecResult* pResult, void* param, int32_t code) { SRequestObj* pRequest = (SRequestObj*)param; pRequest->code = code; - pRequest->body.resInfo.execRes = pResult->res; + memcpy(&pRequest->body.resInfo.execRes, pResult, sizeof(*pResult)); if (TDMT_VND_SUBMIT == pRequest->type || TDMT_VND_DELETE == pRequest->type || TDMT_VND_CREATE_TABLE == pRequest->type) { @@ -952,10 +952,10 @@ void launchAsyncQuery(SRequestObj* pRequest, SQuery* pQuery, SMetaData* pResultM .sql = pRequest->sqlstr, .startTs = pRequest->metric.start, .execFp = schedulerExecCb, - .execParam = pRequest, + .cbParam = pRequest, .chkKillFp = chkRequestKilled, .chkKillParam = (void*)pRequest->self, - .pQueryRes = NULL, + .pExecRes = NULL, }; code = schedulerExecJob(&req, &pRequest->body.queryJob); taosArrayDestroy(pNodeList); @@ -1398,7 +1398,7 @@ void* doFetchRows(SRequestObj* pRequest, bool setupOneRowPtr, bool convertUcs4) SReqResultInfo* pResInfo = &pRequest->body.resInfo; SSchedulerReq req = { .syncReq = true, - .pFetchRes = &pResInfo->pData, + .pFetchRes = (void**)&pResInfo->pData, }; pRequest->code = schedulerFetchRows(pRequest->body.queryJob, &req); if (pRequest->code != TSDB_CODE_SUCCESS) { diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c index 2550a7a47b..1267b3ee0c 100644 --- a/source/client/src/clientMain.c +++ b/source/client/src/clientMain.c @@ -862,7 +862,7 @@ void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) { SSchedulerReq req = { .syncReq = false, .fetchFp = fetchCallback, - .execParam = pRequest, + .cbParam = pRequest, }; schedulerFetchRows(pRequest->body.queryJob, &req); } diff --git a/source/libs/scheduler/inc/schInt.h b/source/libs/scheduler/inc/schInt.h index 819d51c4e7..ae120a42be 100644 --- a/source/libs/scheduler/inc/schInt.h +++ b/source/libs/scheduler/inc/schInt.h @@ -98,7 +98,7 @@ typedef struct SSchStat { } SSchStat; typedef struct SSchResInfo { - SQueryResult* queryRes; + SExecResult* execRes; void** fetchRes; schedulerExecFp execFp; schedulerFetchFp fetchFp; @@ -111,11 +111,6 @@ typedef struct SSchOpEvent { SSchedulerReq *pReq; } SSchOpEvent; -typedef struct SSchEvent { - SCH_EVENT_TYPE event; - void* info; -} SSchEvent; - typedef int32_t (*schStatusEnterFp)(void* pHandle, void* pParam); typedef int32_t (*schStatusLeaveFp)(void* pHandle, void* pParam); typedef int32_t (*schStatusEventFp)(void* pHandle, void* pParam, void* pEvent); @@ -315,9 +310,9 @@ extern SSchedulerMgmt schMgmt; #define SCH_GET_JOB_STATUS(job) atomic_load_8(&(job)->status) #define SCH_GET_JOB_STATUS_STR(job) jobTaskStatusStr(SCH_GET_JOB_STATUS(job)) -#define SCH_JOB_IN_SYNC_OP(job) ((job)->opStatus.op && (job)->opStatus.sync) -#define SCH_JOB_IN_ASYNC_EXEC_OP(job) (((job)->opStatus.op == SCH_OP_EXEC) && (!(job)->opStatus.sync)) -#define SCH_JOB_IN_ASYNC_FETCH_OP(job) (((job)->opStatus.op == SCH_OP_FETCH) && (!(job)->opStatus.sync)) +#define SCH_JOB_IN_SYNC_OP(job) ((job)->opStatus.op && (job)->opStatus.syncReq) +#define SCH_JOB_IN_ASYNC_EXEC_OP(job) ((SCH_OP_EXEC == atomic_val_compare_exchange_32(&(job)->opStatus.op, SCH_OP_EXEC, SCH_OP_NULL)) && (!(job)->opStatus.syncReq)) +#define SCH_JOB_IN_ASYNC_FETCH_OP(job) ((SCH_OP_FETCH == atomic_val_compare_exchange_32(&(job)->opStatus.op, SCH_OP_FETCH, SCH_OP_NULL)) && (!(job)->opStatus.syncReq)) #define SCH_SET_JOB_NEED_FLOW_CTRL(_job) (_job)->attr.needFlowCtrl = true #define SCH_JOB_NEED_FLOW_CTRL(_job) ((_job)->attr.needFlowCtrl) @@ -355,7 +350,7 @@ extern SSchedulerMgmt schMgmt; #define SCH_SET_ERRNO(_err) do { if (TSDB_CODE_SCH_IGNORE_ERROR != (_err)) { terrno = (_err); } } while (0) #define SCH_ERR_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { SCH_SET_ERRNO(_code); return _code; } } while (0) #define SCH_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { SCH_SET_ERRNO(_code); } return _code; } while (0) -#define SCH_ERR_JRET(c) do { code = c; if (code != TSDB_CODE_SUCCESS) { SCH_SET_ERRNO(_code); goto _return; } } while (0) +#define SCH_ERR_JRET(c) do { code = c; if (code != TSDB_CODE_SUCCESS) { SCH_SET_ERRNO(code); goto _return; } } while (0) #define SCH_LOCK(type, _lock) (SCH_READ == (type) ? taosRLockLatch(_lock) : taosWLockLatch(_lock)) #define SCH_UNLOCK(type, _lock) (SCH_READ == (type) ? taosRUnLockLatch(_lock) : taosWUnLockLatch(_lock)) @@ -408,11 +403,32 @@ int32_t schProcessOnTaskStatusRsp(SQueryNodeEpId* pEpId, SArray* pStatusList); void schFreeSMsgSendInfo(SMsgSendInfo *msgSendInfo); char* schGetOpStr(SCH_OP_TYPE type); int32_t schBeginOperation(SSchJob *pJob, SCH_OP_TYPE type, bool sync); -int32_t schInitJob(SSchJob **pJob, SSchedulerReq *pReq); +int32_t schInitJob(int64_t *pJobId, SSchedulerReq *pReq); int32_t schExecJob(SSchJob *pJob, SSchedulerReq *pReq); -int32_t schDumpJobExecRes(SSchJob* pJob, SQueryResult* pRes); +int32_t schDumpJobExecRes(SSchJob* pJob, SExecResult* pRes); int32_t schUpdateTaskCandidateAddr(SSchJob *pJob, SSchTask *pTask, SEpSet* pEpSet); int32_t schHandleRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf* pData, int32_t rspCode); +void schProcessOnOpEnd(SSchJob *pJob, SCH_OP_TYPE type, SSchedulerReq* pReq, int32_t errCode); +int32_t schProcessOnOpBegin(SSchJob* pJob, SCH_OP_TYPE type, SSchedulerReq* pReq); +void schProcessOnCbEnd(SSchJob *pJob, SSchTask *pTask, int32_t errCode); +int32_t schProcessOnCbBegin(SSchJob** job, SSchTask** task, uint64_t qId, int64_t rId, uint64_t tId); +void schDropTaskOnExecNode(SSchJob *pJob, SSchTask *pTask); +bool schJobDone(SSchJob *pJob); +int32_t schRemoveTaskFromExecList(SSchJob *pJob, SSchTask *pTask); +int32_t schLaunchJobLowerLevel(SSchJob *pJob, SSchTask *pTask); +int32_t schSwitchJobStatus(SSchJob* pJob, int32_t status, void* param); +int32_t schHandleOpBeginEvent(int64_t jobId, SSchJob** job, SCH_OP_TYPE type, SSchedulerReq* pReq); +int32_t schHandleOpEndEvent(SSchJob* pJob, SCH_OP_TYPE type, SSchedulerReq* pReq, int32_t errCode); +int32_t schHandleTaskRetry(SSchJob *pJob, SSchTask *pTask); +void schUpdateJobErrCode(SSchJob *pJob, int32_t errCode); +int32_t schTaskCheckSetRetry(SSchJob *pJob, SSchTask *pTask, int32_t errCode, bool *needRetry); +int32_t schProcessOnJobFailure(SSchJob *pJob, int32_t errCode); +int32_t schProcessOnJobPartialSuccess(SSchJob *pJob); +void schFreeTask(SSchJob *pJob, SSchTask *pTask); +void schDropTaskInHashList(SSchJob *pJob, SHashObj *list); +int32_t schLaunchLevelTasks(SSchJob *pJob, SSchLevel *level); +int32_t schGetTaskFromList(SHashObj *pTaskList, uint64_t taskId, SSchTask **pTask); +int32_t schInitTask(SSchJob *pJob, SSchTask *pTask, SSubplan *pPlan, SSchLevel *pLevel); #ifdef __cplusplus diff --git a/source/libs/scheduler/src/schDbg.c b/source/libs/scheduler/src/schDbg.c index 5c0c6fbb76..7f013b8f32 100644 --- a/source/libs/scheduler/src/schDbg.c +++ b/source/libs/scheduler/src/schDbg.c @@ -14,16 +14,16 @@ */ #include "query.h" -#include "schedulerInt.h" +#include "schInt.h" tsem_t schdRspSem; -void schdExecCallback(SQueryResult* pResult, void* param, int32_t code) { +void schdExecCallback(SExecResult* pResult, void* param, int32_t code) { if (code) { pResult->code = code; } - *(SQueryResult*)param = *pResult; + *(SExecResult*)param = *pResult; taosMemoryFree(pResult); diff --git a/source/libs/scheduler/src/schFlowCtrl.c b/source/libs/scheduler/src/schFlowCtrl.c index 85d205f5f2..6b34a394b6 100644 --- a/source/libs/scheduler/src/schFlowCtrl.c +++ b/source/libs/scheduler/src/schFlowCtrl.c @@ -13,7 +13,7 @@ * along with this program. If not, see . */ -#include "schedulerInt.h" +#include "schInt.h" #include "tmsg.h" #include "query.h" #include "catalog.h" diff --git a/source/libs/scheduler/src/schJob.c b/source/libs/scheduler/src/schJob.c index d514ed2a9f..c4923b8740 100644 --- a/source/libs/scheduler/src/schJob.c +++ b/source/libs/scheduler/src/schJob.c @@ -16,7 +16,7 @@ #include "catalog.h" #include "command.h" #include "query.h" -#include "schedulerInt.h" +#include "schInt.h" #include "tmsg.h" #include "tref.h" #include "trpc.h" @@ -72,6 +72,8 @@ FORCE_INLINE bool schJobNeedToStop(SSchJob *pJob, int8_t *pStatus) { schUpdateJobErrCode(pJob, TSDB_CODE_TSC_QUERY_KILLED); return true; } + + return false; } int32_t schUpdateJobStatus(SSchJob *pJob, int8_t newStatus) { @@ -369,7 +371,7 @@ _return: int32_t schDumpJobExecRes(SSchJob* pJob, SExecResult* pRes) { pRes->code = atomic_load_32(&pJob->errCode); pRes->numOfRows = pJob->resNumOfRows; - pRes->res = pJob->execRes; + memcpy(pRes, &pJob->execRes, sizeof(pJob->execRes)); pJob->execRes.res = NULL; return TSDB_CODE_SUCCESS; @@ -406,15 +408,13 @@ int32_t schDumpJobFetchRes(SSchJob* pJob, void** pData) { } int32_t schNotifyUserExecRes(SSchJob* pJob) { - SQueryResult* pRes = taosMemoryCalloc(1, sizeof(SQueryResult)); + SExecResult* pRes = taosMemoryCalloc(1, sizeof(SExecResult)); if (pRes) { schDumpJobExecRes(pJob, pRes); } - schEndOperation(pJob); - SCH_JOB_DLOG("sch start to invoke exec cb, code: %s", tstrerror(pJob->errCode)); - (*pJob->userRes.execFp)(pRes, pJob->userRes.userParam, atomic_load_32(&pJob->errCode)); + (*pJob->userRes.execFp)(pRes, pJob->userRes.cbParam, atomic_load_32(&pJob->errCode)); SCH_JOB_DLOG("sch end from exec cb, code: %s", tstrerror(pJob->errCode)); return TSDB_CODE_SUCCESS; @@ -425,10 +425,8 @@ int32_t schNotifyUserFetchRes(SSchJob* pJob) { schDumpJobFetchRes(pJob, &pRes); - schEndOperation(pJob); - SCH_JOB_DLOG("sch start to invoke fetch cb, code: %s", tstrerror(pJob->errCode)); - (*pJob->userRes.fetchFp)(pRes, pJob->userRes.userParam, atomic_load_32(&pJob->errCode)); + (*pJob->userRes.fetchFp)(pRes, pJob->userRes.cbParam, atomic_load_32(&pJob->errCode)); SCH_JOB_DLOG("sch end from fetch cb, code: %s", tstrerror(pJob->errCode)); return TSDB_CODE_SUCCESS; @@ -627,7 +625,7 @@ void schFreeJobImpl(void *job) { qDestroyQueryPlan(pJob->pDag); - taosMemoryFreeClear(pJob->userRes.queryRes); + taosMemoryFreeClear(pJob->userRes.execRes); taosMemoryFreeClear(pJob->resData); taosMemoryFree(pJob); @@ -648,10 +646,14 @@ int32_t schJobFetchRows(SSchJob *pJob) { if (pJob->opStatus.syncReq) { SCH_JOB_DLOG("sync wait for rsp now, job status:%s", SCH_GET_JOB_STATUS_STR(pJob)); tsem_wait(&pJob->rspSem); - schPostJobRes(pJob, SCH_OP_FETCH); + SCH_RET(schDumpJobFetchRes(pJob, pJob->userRes.fetchRes)); } } else { - schPostJobRes(pJob, SCH_OP_FETCH); + if (pJob->opStatus.syncReq) { + SCH_RET(schDumpJobFetchRes(pJob, pJob->userRes.fetchRes)); + } else { + schPostJobRes(pJob, SCH_OP_FETCH); + } } SCH_RET(code); @@ -674,8 +676,6 @@ int32_t schInitJob(int64_t *pJobId, SSchedulerReq *pReq) { pJob->chkKillParam = pReq->chkKillParam; pJob->userRes.execFp = pReq->execFp; pJob->userRes.cbParam = pReq->cbParam; - pJob->opStatus.op = SCH_OP_EXEC; - pJob->opStatus.syncReq = pReq->syncReq; if (pReq->pNodeList == NULL || taosArrayGetSize(pReq->pNodeList) <= 0) { qDebug("QID:0x%" PRIx64 " input exec nodeList is empty", pReq->pDag->queryId); @@ -750,22 +750,27 @@ int32_t schExecJob(SSchJob *pJob, SSchedulerReq *pReq) { void schProcessOnOpEnd(SSchJob *pJob, SCH_OP_TYPE type, SSchedulerReq* pReq, int32_t errCode) { + int32_t op = 0; + switch (type) { case SCH_OP_EXEC: - int32_t op = atomic_val_compare_exchange_32(&pJob->opStatus.op, type, SCH_OP_NULL); +/* + op = atomic_val_compare_exchange_32(&pJob->opStatus.op, type, SCH_OP_NULL); if (SCH_OP_NULL == op || op != type) { SCH_JOB_ELOG("job not in %s operation, op:%s, status:%s", schGetOpStr(type), schGetOpStr(op), jobTaskStatusStr(pJob->status)); } - - if (pReq) { +*/ + if (pReq && pReq->syncReq) { schDumpJobExecRes(pJob, pReq->pExecRes); } break; case SCH_OP_FETCH: - int32_t op = atomic_val_compare_exchange_32(&pJob->opStatus.op, type, SCH_OP_NULL); +/* + op = atomic_val_compare_exchange_32(&pJob->opStatus.op, type, SCH_OP_NULL); if (SCH_OP_NULL == op || op != type) { SCH_JOB_ELOG("job not in %s operation, op:%s, status:%s", schGetOpStr(type), schGetOpStr(op), jobTaskStatusStr(pJob->status)); } +*/ break; case SCH_OP_GET_STATUS: errCode = TSDB_CODE_SUCCESS; @@ -775,7 +780,7 @@ void schProcessOnOpEnd(SSchJob *pJob, SCH_OP_TYPE type, SSchedulerReq* pReq, int } if (errCode) { - schSwitchJobStatus(pJob, JOB_TASK_STATUS_FAIL, errCode); + schSwitchJobStatus(pJob, JOB_TASK_STATUS_FAIL, (void*)&errCode); } SCH_JOB_DLOG("job end %s operation with code %s", schGetOpStr(type), tstrerror(errCode)); @@ -846,7 +851,7 @@ void schProcessOnCbEnd(SSchJob *pJob, SSchTask *pTask, int32_t errCode) { } if (errCode) { - schSwitchJobStatus(pJob, JOB_TASK_STATUS_FAIL, errCode); + schSwitchJobStatus(pJob, JOB_TASK_STATUS_FAIL, (void*)&errCode); } if (pJob) { @@ -865,7 +870,6 @@ int32_t schProcessOnCbBegin(SSchJob** job, SSchTask** task, uint64_t qId, int64_ SCH_ERR_RET(TSDB_CODE_QRY_JOB_NOT_EXIST); } - int8_t status = 0; if (schJobNeedToStop(pJob, &status)) { SCH_TASK_ELOG("will not do further processing cause of job status %s", jobTaskStatusStr(status)); SCH_ERR_JRET(TSDB_CODE_SCH_IGNORE_ERROR); @@ -875,6 +879,9 @@ int32_t schProcessOnCbBegin(SSchJob** job, SSchTask** task, uint64_t qId, int64_ SCH_LOCK_TASK(pTask); + *job = pJob; + *task = pTask; + return TSDB_CODE_SUCCESS; _return: diff --git a/source/libs/scheduler/src/schRemote.c b/source/libs/scheduler/src/schRemote.c index 64368162e3..ab457847b9 100644 --- a/source/libs/scheduler/src/schRemote.c +++ b/source/libs/scheduler/src/schRemote.c @@ -16,7 +16,7 @@ #include "catalog.h" #include "command.h" #include "query.h" -#include "schedulerInt.h" +#include "schInt.h" #include "tmsg.h" #include "tref.h" #include "trpc.h" @@ -378,7 +378,7 @@ int32_t schHandleCallback(void *param, SDataBuf *pMsg, int32_t rspCode) { SSchTask *pTask = NULL; SSchJob *pJob = NULL; - SCH_TASK_DLOG("begin to handle rsp msg, type:%s, handle:%p, code:%s", TMSG_INFO(pMsg->msgType), pMsg->handle, tstrerror(rspCode)); + qDebug("begin to handle rsp msg, type:%s, handle:%p, code:%s", TMSG_INFO(pMsg->msgType), pMsg->handle, tstrerror(rspCode)); SCH_ERR_RET(schProcessOnCbBegin(&pJob, &pTask, pParam->queryId, pParam->refId, pParam->taskId)); @@ -390,7 +390,7 @@ int32_t schHandleCallback(void *param, SDataBuf *pMsg, int32_t rspCode) { taosMemoryFreeClear(pMsg->pData); taosMemoryFreeClear(param); - SCH_TASK_DLOG("end to handle rsp msg, type:%s, handle:%p, code:%s", TMSG_INFO(pMsg->msgType), pMsg->handle, tstrerror(rspCode)); + qDebug("end to handle rsp msg, type:%s, handle:%p, code:%s", TMSG_INFO(pMsg->msgType), pMsg->handle, tstrerror(rspCode)); SCH_RET(code); } diff --git a/source/libs/scheduler/src/schStatus.c b/source/libs/scheduler/src/schStatus.c index 55bc600eca..80137f1872 100644 --- a/source/libs/scheduler/src/schStatus.c +++ b/source/libs/scheduler/src/schStatus.c @@ -37,10 +37,10 @@ int32_t schSwitchJobStatus(SSchJob* pJob, int32_t status, void* param) { case JOB_TASK_STATUS_SUCC: break; case JOB_TASK_STATUS_FAIL: - SCH_RET(schProcessOnJobFailure(pJob, (int32_t)param)); + SCH_RET(schProcessOnJobFailure(pJob, (param ? *(int32_t*)param : 0))); break; case JOB_TASK_STATUS_DROP: - SCH_ERR_JRET(schProcessOnJobDropped(pJob, (int32_t)param)); + SCH_ERR_JRET(schProcessOnJobDropped(pJob, *(int32_t*)param)); if (taosRemoveRef(schMgmt.jobRef, pJob->refId)) { SCH_JOB_ELOG("remove job from job list failed, refId:0x%" PRIx64, pJob->refId); @@ -73,14 +73,22 @@ int32_t schHandleOpBeginEvent(int64_t jobId, SSchJob** job, SCH_OP_TYPE type, SS SCH_RET(schProcessOnOpBegin(pJob, type, pReq)); } -void schHandleOpEndEvent(SSchJob* pJob, SCH_OP_TYPE type, SSchedulerReq* pReq, int32_t errCode) { +int32_t schHandleOpEndEvent(SSchJob* pJob, SCH_OP_TYPE type, SSchedulerReq* pReq, int32_t errCode) { + int32_t code = errCode; + if (NULL == pJob) { - return; + SCH_RET(code); } schProcessOnOpEnd(pJob, type, pReq, errCode); + if (TSDB_CODE_SCH_IGNORE_ERROR == errCode) { + code = pJob->errCode; + } + schReleaseJob(pJob->refId); + + return code; } diff --git a/source/libs/scheduler/src/schTask.c b/source/libs/scheduler/src/schTask.c index 1f89b59137..4da8ed446b 100644 --- a/source/libs/scheduler/src/schTask.c +++ b/source/libs/scheduler/src/schTask.c @@ -16,7 +16,7 @@ #include "catalog.h" #include "command.h" #include "query.h" -#include "schedulerInt.h" +#include "schInt.h" #include "tmsg.h" #include "tref.h" #include "trpc.h" @@ -226,7 +226,7 @@ int32_t schProcessOnTaskSuccess(SSchJob *pJob, SSchTask *pTask) { } if (pTask->level->taskFailed > 0) { - SCH_RET(schSwitchJobStatus(pJob, JOB_TASK_STATUS_FAIL, 0)); + SCH_RET(schSwitchJobStatus(pJob, JOB_TASK_STATUS_FAIL, NULL)); } else { SCH_RET(schSwitchJobStatus(pJob, JOB_TASK_STATUS_PART_SUCC, NULL)); } @@ -294,7 +294,7 @@ int32_t schDoTaskRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf* pData, int32 if ((pTask->execId + 1) >= pTask->maxExecTimes) { SCH_TASK_DLOG("task no more retry since reach max try times, execId:%d", pTask->execId); - schSwitchJobStatus(pJob, JOB_TASK_STATUS_FAIL, (void*)rspCode); + schSwitchJobStatus(pJob, JOB_TASK_STATUS_FAIL, (void*)&rspCode); return TSDB_CODE_SUCCESS; } diff --git a/source/libs/scheduler/src/schUtil.c b/source/libs/scheduler/src/schUtil.c index 36a8475a34..f848dfa210 100644 --- a/source/libs/scheduler/src/schUtil.c +++ b/source/libs/scheduler/src/schUtil.c @@ -16,7 +16,7 @@ #include "catalog.h" #include "command.h" #include "query.h" -#include "schedulerInt.h" +#include "schInt.h" #include "tmsg.h" #include "tref.h" #include "trpc.h" diff --git a/source/libs/scheduler/src/scheduler.c b/source/libs/scheduler/src/scheduler.c index 65ab9c7659..ebc4014e88 100644 --- a/source/libs/scheduler/src/scheduler.c +++ b/source/libs/scheduler/src/scheduler.c @@ -16,7 +16,7 @@ #include "catalog.h" #include "command.h" #include "query.h" -#include "schedulerInt.h" +#include "schInt.h" #include "tmsg.h" #include "tref.h" #include "trpc.h" @@ -148,7 +148,7 @@ void schedulerFreeJob(int64_t* jobId, int32_t errCode) { return; } - schSwitchJobStatus(pJob, JOB_TASK_STATUS_DROP, (void*)errCode); + schSwitchJobStatus(pJob, JOB_TASK_STATUS_DROP, (void*)&errCode); *jobId = 0; } diff --git a/source/libs/scheduler/test/schedulerTests.cpp b/source/libs/scheduler/test/schedulerTests.cpp index 1a464b78ab..d6b1baf978 100644 --- a/source/libs/scheduler/test/schedulerTests.cpp +++ b/source/libs/scheduler/test/schedulerTests.cpp @@ -50,7 +50,7 @@ #pragma GCC diagnostic ignored "-Wreturn-type" #pragma GCC diagnostic ignored "-Wformat" -#include "schedulerInt.h" +#include "schInt.h" #include "stub.h" #include "tref.h" @@ -87,7 +87,7 @@ void schtInitLogFile() { } -void schtQueryCb(SQueryResult* pResult, void* param, int32_t code) { +void schtQueryCb(SExecResult* pResult, void* param, int32_t code) { assert(TSDB_CODE_SUCCESS == code); *(int32_t*)param = 1; } @@ -585,7 +585,10 @@ void* schtRunJobThread(void *aa) { atomic_store_32(&schtStartFetch, 1); void *data = NULL; - code = schedulerFetchRows(queryJobRefId, &data); + req.syncReq = true; + req.pFetchRes = &data; + + code = schedulerFetchRows(queryJobRefId, &req); assert(code == 0 || code); if (0 == code) { @@ -595,7 +598,7 @@ void* schtRunJobThread(void *aa) { } data = NULL; - code = schedulerFetchRows(queryJobRefId, &data); + code = schedulerFetchRows(queryJobRefId, &req); assert(code == 0 || code); schtFreeQueryJob(0); @@ -710,7 +713,10 @@ TEST(queryTest, normalCase) { taosThreadCreate(&(thread1), &thattr, schtCreateFetchRspThread, &job); void *data = NULL; - code = schedulerFetchRows(job, &data); + req.syncReq = true; + req.pFetchRes = &data; + + code = schedulerFetchRows(job, &req); ASSERT_EQ(code, 0); SRetrieveTableRsp *pRsp = (SRetrieveTableRsp *)data; @@ -719,7 +725,7 @@ TEST(queryTest, normalCase) { taosMemoryFreeClear(data); data = NULL; - code = schedulerFetchRows(job, &data); + code = schedulerFetchRows(job, &req); ASSERT_EQ(code, 0); ASSERT_TRUE(data == NULL); @@ -814,7 +820,9 @@ TEST(queryTest, readyFirstCase) { taosThreadCreate(&(thread1), &thattr, schtCreateFetchRspThread, &job); void *data = NULL; - code = schedulerFetchRows(job, &data); + req.syncReq = true; + req.pFetchRes = &data; + code = schedulerFetchRows(job, &req); ASSERT_EQ(code, 0); SRetrieveTableRsp *pRsp = (SRetrieveTableRsp *)data; @@ -823,7 +831,7 @@ TEST(queryTest, readyFirstCase) { taosMemoryFreeClear(data); data = NULL; - code = schedulerFetchRows(job, &data); + code = schedulerFetchRows(job, &req); ASSERT_EQ(code, 0); ASSERT_TRUE(data == NULL); @@ -926,7 +934,9 @@ TEST(queryTest, flowCtrlCase) { taosThreadCreate(&(thread1), &thattr, schtCreateFetchRspThread, &job); void *data = NULL; - code = schedulerFetchRows(job, &data); + req.syncReq = true; + req.pFetchRes = &data; + code = schedulerFetchRows(job, &req); ASSERT_EQ(code, 0); SRetrieveTableRsp *pRsp = (SRetrieveTableRsp *)data; @@ -935,7 +945,7 @@ TEST(queryTest, flowCtrlCase) { taosMemoryFreeClear(data); data = NULL; - code = schedulerFetchRows(job, &data); + code = schedulerFetchRows(job, &req); ASSERT_EQ(code, 0); ASSERT_TRUE(data == NULL); @@ -979,7 +989,7 @@ TEST(insertTest, normalCase) { TdThread thread1; taosThreadCreate(&(thread1), &thattr, schtSendRsp, &insertJobRefId); - SQueryResult res = {0}; + SExecResult res = {0}; SRequestConnInfo conn = {0}; conn.pTrans = mockPointer; @@ -991,7 +1001,7 @@ TEST(insertTest, normalCase) { req.execFp = schtQueryCb; req.cbParam = NULL; - code = schedulerExecJob(&req, &insertJobRefId, &res); + code = schedulerExecJob(&req, &insertJobRefId); ASSERT_EQ(code, 0); ASSERT_EQ(res.numOfRows, 20); From b3e8e7ba10b0ed773c4e23dc1c35e327a2b4c5be Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Tue, 5 Jul 2022 20:26:52 +0800 Subject: [PATCH 7/9] fix: fix scheduler no resp issue --- source/libs/scheduler/inc/schInt.h | 11 ++++---- source/libs/scheduler/src/schJob.c | 42 +++++++++++++++++------------ source/libs/scheduler/src/schTask.c | 6 ++--- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/source/libs/scheduler/inc/schInt.h b/source/libs/scheduler/inc/schInt.h index ae120a42be..8e8652aab5 100644 --- a/source/libs/scheduler/inc/schInt.h +++ b/source/libs/scheduler/inc/schInt.h @@ -175,7 +175,7 @@ typedef struct SSchLevel { int32_t taskNum; int32_t taskLaunchedNum; int32_t taskDoneNum; - SArray *subTasks; // Element is SQueryTask + SArray *subTasks; // Element is SSchTask } SSchLevel; typedef struct SSchTaskProfile { @@ -213,6 +213,7 @@ typedef struct SSchTask { typedef struct SSchJobAttr { EExplainMode explainMode; bool queryJob; + bool needFetch; bool needFlowCtrl; } SSchJobAttr; @@ -318,11 +319,11 @@ extern SSchedulerMgmt schMgmt; #define SCH_JOB_NEED_FLOW_CTRL(_job) ((_job)->attr.needFlowCtrl) #define SCH_TASK_NEED_FLOW_CTRL(_job, _task) (SCH_IS_DATA_SRC_QRY_TASK(_task) && SCH_JOB_NEED_FLOW_CTRL(_job) && SCH_IS_LEVEL_UNFINISHED((_task)->level)) -#define SCH_SET_JOB_TYPE(_job, type) (_job)->attr.queryJob = ((type) != SUBPLAN_TYPE_MODIFY) +#define SCH_SET_JOB_TYPE(_job, type) do { if ((type) != SUBPLAN_TYPE_MODIFY) { (_job)->attr.queryJob = true; } } while (0) #define SCH_IS_QUERY_JOB(_job) ((_job)->attr.queryJob) -#define SCH_JOB_NEED_FETCH(_job) SCH_IS_QUERY_JOB(_job) -#define SCH_IS_WAIT_ALL_JOB(_job) (!SCH_IS_QUERY_JOB(_job)) -#define SCH_IS_NEED_DROP_JOB(_job) (SCH_IS_QUERY_JOB(_job)) +#define SCH_JOB_NEED_FETCH(_job) ((_job)->attr.needFetch) +#define SCH_JOB_NEED_WAIT(_job) (!SCH_IS_QUERY_JOB(_job)) +#define SCH_JOB_NEED_DROP(_job) (SCH_IS_QUERY_JOB(_job)) #define SCH_IS_EXPLAIN_JOB(_job) (EXPLAIN_MODE_ANALYZE == (_job)->attr.explainMode) #define SCH_NETWORK_ERR(_code) ((_code) == TSDB_CODE_RPC_BROKEN_LINK || (_code) == TSDB_CODE_RPC_NETWORK_UNAVAIL) #define SCH_SUB_TASK_NETWORK_ERR(_code, _len) (SCH_NETWORK_ERR(_code) && ((_len) > 0)) diff --git a/source/libs/scheduler/src/schJob.c b/source/libs/scheduler/src/schJob.c index c4923b8740..858f68e7ae 100644 --- a/source/libs/scheduler/src/schJob.c +++ b/source/libs/scheduler/src/schJob.c @@ -230,9 +230,16 @@ int32_t schBuildTaskRalation(SSchJob *pJob, SHashObj *planToTask) { } SSchLevel *pLevel = taosArrayGet(pJob->levels, 0); - if (SCH_IS_QUERY_JOB(pJob) && pLevel->taskNum > 1) { - SCH_JOB_ELOG("invalid query plan, level:0, taskNum:%d", pLevel->taskNum); - SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR); + if (SCH_IS_QUERY_JOB(pJob)) { + if (pLevel->taskNum > 1) { + SCH_JOB_ELOG("invalid query plan, level:0, taskNum:%d", pLevel->taskNum); + SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR); + } + + SSchTask* pTask = taosArrayGet(pLevel->subTasks, 0); + if (SUBPLAN_TYPE_MODIFY != pTask->plan->subplanType) { + pJob->attr.needFetch = true; + } } return TSDB_CODE_SUCCESS; @@ -371,9 +378,12 @@ _return: int32_t schDumpJobExecRes(SSchJob* pJob, SExecResult* pRes) { pRes->code = atomic_load_32(&pJob->errCode); pRes->numOfRows = pJob->resNumOfRows; - memcpy(pRes, &pJob->execRes, sizeof(pJob->execRes)); + pRes->res = pJob->execRes.res; + pRes->msgType = pJob->execRes.msgType; pJob->execRes.res = NULL; + SCH_JOB_DLOG("execRes dumped, code: %s", tstrerror(pRes->code)); + return TSDB_CODE_SUCCESS; } @@ -434,12 +444,12 @@ int32_t schNotifyUserFetchRes(SSchJob* pJob) { void schPostJobRes(SSchJob *pJob, SCH_OP_TYPE op) { if (SCH_OP_NULL == pJob->opStatus.op) { - SCH_JOB_DLOG("job not in any op, no need to post job res, status:%s", jobTaskStatusStr(pJob->status)); + SCH_JOB_DLOG("job not in any operation, no need to post job res, status:%s", jobTaskStatusStr(pJob->status)); return; } if (op && pJob->opStatus.op != op) { - SCH_JOB_ELOG("job in op %s mis-match with expected %s", schGetOpStr(pJob->opStatus.op), schGetOpStr(op)); + SCH_JOB_ELOG("job in operation %s mis-match with expected %s", schGetOpStr(pJob->opStatus.op), schGetOpStr(op)); return; } @@ -754,23 +764,21 @@ void schProcessOnOpEnd(SSchJob *pJob, SCH_OP_TYPE type, SSchedulerReq* pReq, int switch (type) { case SCH_OP_EXEC: -/* - op = atomic_val_compare_exchange_32(&pJob->opStatus.op, type, SCH_OP_NULL); - if (SCH_OP_NULL == op || op != type) { - SCH_JOB_ELOG("job not in %s operation, op:%s, status:%s", schGetOpStr(type), schGetOpStr(op), jobTaskStatusStr(pJob->status)); - } -*/ if (pReq && pReq->syncReq) { + op = atomic_val_compare_exchange_32(&pJob->opStatus.op, type, SCH_OP_NULL); + if (SCH_OP_NULL == op || op != type) { + SCH_JOB_ELOG("job not in %s operation, op:%s, status:%s", schGetOpStr(type), schGetOpStr(op), jobTaskStatusStr(pJob->status)); + } schDumpJobExecRes(pJob, pReq->pExecRes); } break; case SCH_OP_FETCH: -/* - op = atomic_val_compare_exchange_32(&pJob->opStatus.op, type, SCH_OP_NULL); - if (SCH_OP_NULL == op || op != type) { - SCH_JOB_ELOG("job not in %s operation, op:%s, status:%s", schGetOpStr(type), schGetOpStr(op), jobTaskStatusStr(pJob->status)); + if (pReq && pReq->syncReq) { + op = atomic_val_compare_exchange_32(&pJob->opStatus.op, type, SCH_OP_NULL); + if (SCH_OP_NULL == op || op != type) { + SCH_JOB_ELOG("job not in %s operation, op:%s, status:%s", schGetOpStr(type), schGetOpStr(op), jobTaskStatusStr(pJob->status)); + } } -*/ break; case SCH_OP_GET_STATUS: errCode = TSDB_CODE_SUCCESS; diff --git a/source/libs/scheduler/src/schTask.c b/source/libs/scheduler/src/schTask.c index 4da8ed446b..be33d686c8 100644 --- a/source/libs/scheduler/src/schTask.c +++ b/source/libs/scheduler/src/schTask.c @@ -170,7 +170,7 @@ int32_t schProcessOnTaskFailure(SSchJob *pJob, SSchTask *pTask, int32_t errCode) SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_FAIL); - if (SCH_IS_WAIT_ALL_JOB(pJob)) { + if (SCH_JOB_NEED_WAIT(pJob)) { SCH_LOCK(SCH_WRITE, &pTask->level->lock); pTask->level->taskFailed++; taskDone = pTask->level->taskSucceed + pTask->level->taskFailed; @@ -212,7 +212,7 @@ int32_t schProcessOnTaskSuccess(SSchJob *pJob, SSchTask *pTask) { int32_t parentNum = pTask->parents ? (int32_t)taosArrayGetSize(pTask->parents) : 0; if (parentNum == 0) { int32_t taskDone = 0; - if (SCH_IS_WAIT_ALL_JOB(pJob)) { + if (SCH_JOB_NEED_WAIT(pJob)) { SCH_LOCK(SCH_WRITE, &pTask->level->lock); pTask->level->taskSucceed++; taskDone = pTask->level->taskSucceed + pTask->level->taskFailed; @@ -792,7 +792,7 @@ int32_t schLaunchLevelTasks(SSchJob *pJob, SSchLevel *level) { } void schDropTaskInHashList(SSchJob *pJob, SHashObj *list) { - if (!SCH_IS_NEED_DROP_JOB(pJob)) { + if (!SCH_JOB_NEED_DROP(pJob)) { return; } From 2304e12c49e3a7ee0934e5a72e392e014952ca8c Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Wed, 6 Jul 2022 08:57:10 +0800 Subject: [PATCH 8/9] fix: fix sch error handling issue --- source/libs/executor/src/dataInserter.c | 254 ++++++++++++++++++++++++ source/libs/scheduler/src/schTask.c | 7 +- 2 files changed, 258 insertions(+), 3 deletions(-) create mode 100644 source/libs/executor/src/dataInserter.c diff --git a/source/libs/executor/src/dataInserter.c b/source/libs/executor/src/dataInserter.c new file mode 100644 index 0000000000..5c65e95807 --- /dev/null +++ b/source/libs/executor/src/dataInserter.c @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "dataSinkInt.h" +#include "dataSinkMgt.h" +#include "executorimpl.h" +#include "planner.h" +#include "tcompression.h" +#include "tdatablock.h" +#include "tglobal.h" +#include "tqueue.h" + +extern SDataSinkStat gDataSinkStat; + +typedef struct SDataInserterBuf { + int32_t useSize; + int32_t allocSize; + char* pData; +} SDataInserterBuf; + +typedef struct SDataCacheEntry { + int32_t dataLen; + int32_t numOfRows; + int32_t numOfCols; + int8_t compressed; + char data[]; +} SDataCacheEntry; + +typedef struct SDataInserterHandle { + SDataSinkHandle sink; + SDataSinkManager* pManager; + SDataBlockDescNode* pSchema; + SDataDeleterNode* pDeleter; + SDeleterParam* pParam; + STaosQueue* pDataBlocks; + SDataDeleterBuf nextOutput; + int32_t status; + bool queryEnd; + uint64_t useconds; + uint64_t cachedSize; + TdThreadMutex mutex; +} SDataInserterHandle; + +static bool needCompress(const SSDataBlock* pData, int32_t numOfCols) { + if (tsCompressColData < 0 || 0 == pData->info.rows) { + return false; + } + + for (int32_t col = 0; col < numOfCols; ++col) { + SColumnInfoData* pColRes = taosArrayGet(pData->pDataBlock, col); + int32_t colSize = pColRes->info.bytes * pData->info.rows; + if (NEEDTO_COMPRESS_QUERY(colSize)) { + return true; + } + } + + return false; +} + +static void toDataCacheEntry(SDataDeleterHandle* pHandle, const SInputData* pInput, SDataDeleterBuf* pBuf) { + int32_t numOfCols = LIST_LENGTH(pHandle->pSchema->pSlots); + + SDataCacheEntry* pEntry = (SDataCacheEntry*)pBuf->pData; + pEntry->compressed = 0; + pEntry->numOfRows = pInput->pData->info.rows; + pEntry->numOfCols = taosArrayGetSize(pInput->pData->pDataBlock); + pEntry->dataLen = sizeof(SDeleterRes); + + ASSERT(1 == pEntry->numOfRows); + ASSERT(1 == pEntry->numOfCols); + + pBuf->useSize = sizeof(SDataCacheEntry); + + SColumnInfoData* pColRes = (SColumnInfoData*)taosArrayGet(pInput->pData->pDataBlock, 0); + + SDeleterRes* pRes = (SDeleterRes*)pEntry->data; + pRes->suid = pHandle->pParam->suid; + pRes->uidList = pHandle->pParam->pUidList; + pRes->skey = pHandle->pDeleter->deleteTimeRange.skey; + pRes->ekey = pHandle->pDeleter->deleteTimeRange.ekey; + pRes->affectedRows = *(int64_t*)pColRes->pData; + + pBuf->useSize += pEntry->dataLen; + + atomic_add_fetch_64(&pHandle->cachedSize, pEntry->dataLen); + atomic_add_fetch_64(&gDataSinkStat.cachedSize, pEntry->dataLen); +} + +static bool allocBuf(SDataDeleterHandle* pDeleter, const SInputData* pInput, SDataDeleterBuf* pBuf) { + uint32_t capacity = pDeleter->pManager->cfg.maxDataBlockNumPerQuery; + if (taosQueueItemSize(pDeleter->pDataBlocks) > capacity) { + qError("SinkNode queue is full, no capacity, max:%d, current:%d, no capacity", capacity, + taosQueueItemSize(pDeleter->pDataBlocks)); + return false; + } + + pBuf->allocSize = sizeof(SDataCacheEntry) + sizeof(SDeleterRes); + + pBuf->pData = taosMemoryMalloc(pBuf->allocSize); + if (pBuf->pData == NULL) { + qError("SinkNode failed to malloc memory, size:%d, code:%d", pBuf->allocSize, TAOS_SYSTEM_ERROR(errno)); + } + + return NULL != pBuf->pData; +} + +static int32_t updateStatus(SDataDeleterHandle* pDeleter) { + taosThreadMutexLock(&pDeleter->mutex); + int32_t blockNums = taosQueueItemSize(pDeleter->pDataBlocks); + int32_t status = + (0 == blockNums ? DS_BUF_EMPTY + : (blockNums < pDeleter->pManager->cfg.maxDataBlockNumPerQuery ? DS_BUF_LOW : DS_BUF_FULL)); + pDeleter->status = status; + taosThreadMutexUnlock(&pDeleter->mutex); + return status; +} + +static int32_t getStatus(SDataDeleterHandle* pDeleter) { + taosThreadMutexLock(&pDeleter->mutex); + int32_t status = pDeleter->status; + taosThreadMutexUnlock(&pDeleter->mutex); + return status; +} + +static int32_t putDataBlock(SDataSinkHandle* pHandle, const SInputData* pInput, bool* pContinue) { + SDataDeleterHandle* pDeleter = (SDataDeleterHandle*)pHandle; + SDataDeleterBuf* pBuf = taosAllocateQitem(sizeof(SDataDeleterBuf), DEF_QITEM); + if (NULL == pBuf || !allocBuf(pDeleter, pInput, pBuf)) { + return TSDB_CODE_QRY_OUT_OF_MEMORY; + } + toDataCacheEntry(pDeleter, pInput, pBuf); + taosWriteQitem(pDeleter->pDataBlocks, pBuf); + *pContinue = (DS_BUF_LOW == updateStatus(pDeleter) ? true : false); + return TSDB_CODE_SUCCESS; +} + +static void endPut(struct SDataSinkHandle* pHandle, uint64_t useconds) { + SDataDeleterHandle* pDeleter = (SDataDeleterHandle*)pHandle; + taosThreadMutexLock(&pDeleter->mutex); + pDeleter->queryEnd = true; + pDeleter->useconds = useconds; + taosThreadMutexUnlock(&pDeleter->mutex); +} + +static void getDataLength(SDataSinkHandle* pHandle, int32_t* pLen, bool* pQueryEnd) { + SDataDeleterHandle* pDeleter = (SDataDeleterHandle*)pHandle; + if (taosQueueEmpty(pDeleter->pDataBlocks)) { + *pQueryEnd = pDeleter->queryEnd; + *pLen = 0; + return; + } + + SDataDeleterBuf* pBuf = NULL; + taosReadQitem(pDeleter->pDataBlocks, (void**)&pBuf); + memcpy(&pDeleter->nextOutput, pBuf, sizeof(SDataDeleterBuf)); + taosFreeQitem(pBuf); + *pLen = ((SDataCacheEntry*)(pDeleter->nextOutput.pData))->dataLen; + *pQueryEnd = pDeleter->queryEnd; + qDebug("got data len %d, row num %d in sink", *pLen, ((SDataCacheEntry*)(pDeleter->nextOutput.pData))->numOfRows); +} + +static int32_t getDataBlock(SDataSinkHandle* pHandle, SOutputData* pOutput) { + SDataDeleterHandle* pDeleter = (SDataDeleterHandle*)pHandle; + if (NULL == pDeleter->nextOutput.pData) { + assert(pDeleter->queryEnd); + pOutput->useconds = pDeleter->useconds; + pOutput->precision = pDeleter->pSchema->precision; + pOutput->bufStatus = DS_BUF_EMPTY; + pOutput->queryEnd = pDeleter->queryEnd; + return TSDB_CODE_SUCCESS; + } + SDataCacheEntry* pEntry = (SDataCacheEntry*)(pDeleter->nextOutput.pData); + memcpy(pOutput->pData, pEntry->data, pEntry->dataLen); + pOutput->numOfRows = pEntry->numOfRows; + pOutput->numOfCols = pEntry->numOfCols; + pOutput->compressed = pEntry->compressed; + + atomic_sub_fetch_64(&pDeleter->cachedSize, pEntry->dataLen); + atomic_sub_fetch_64(&gDataSinkStat.cachedSize, pEntry->dataLen); + + taosMemoryFreeClear(pDeleter->nextOutput.pData); // todo persistent + pOutput->bufStatus = updateStatus(pDeleter); + taosThreadMutexLock(&pDeleter->mutex); + pOutput->queryEnd = pDeleter->queryEnd; + pOutput->useconds = pDeleter->useconds; + pOutput->precision = pDeleter->pSchema->precision; + taosThreadMutexUnlock(&pDeleter->mutex); + + return TSDB_CODE_SUCCESS; +} + +static int32_t destroyDataSinker(SDataSinkHandle* pHandle) { + SDataDeleterHandle* pDeleter = (SDataDeleterHandle*)pHandle; + atomic_sub_fetch_64(&gDataSinkStat.cachedSize, pDeleter->cachedSize); + taosMemoryFreeClear(pDeleter->nextOutput.pData); + while (!taosQueueEmpty(pDeleter->pDataBlocks)) { + SDataDeleterBuf* pBuf = NULL; + taosReadQitem(pDeleter->pDataBlocks, (void**)&pBuf); + taosMemoryFreeClear(pBuf->pData); + taosFreeQitem(pBuf); + } + taosCloseQueue(pDeleter->pDataBlocks); + taosThreadMutexDestroy(&pDeleter->mutex); + return TSDB_CODE_SUCCESS; +} + +static int32_t getCacheSize(struct SDataSinkHandle* pHandle, uint64_t* size) { + SDataDeleterHandle* pDispatcher = (SDataDeleterHandle*)pHandle; + + *size = atomic_load_64(&pDispatcher->cachedSize); + return TSDB_CODE_SUCCESS; +} + +int32_t createDataInserter(SDataSinkManager* pManager, const SDataSinkNode* pDataSink, DataSinkHandle* pHandle, void *pParam) { + SDataInserterHandle* inserter = taosMemoryCalloc(1, sizeof(SDataInserterHandle)); + if (NULL == inserter) { + terrno = TSDB_CODE_QRY_OUT_OF_MEMORY; + return TSDB_CODE_QRY_OUT_OF_MEMORY; + } + + SDataDeleterNode* pDeleterNode = (SDataDeleterNode *)pDataSink; + inserter->sink.fPut = putDataBlock; + inserter->sink.fEndPut = endPut; + inserter->sink.fGetLen = getDataLength; + inserter->sink.fGetData = getDataBlock; + inserter->sink.fDestroy = destroyDataSinker; + inserter->sink.fGetCacheSize = getCacheSize; + inserter->pManager = pManager; + inserter->pDeleter = pDeleterNode; + inserter->pSchema = pDataSink->pInputDataBlockDesc; + inserter->pParam = pParam; + inserter->status = DS_BUF_EMPTY; + inserter->queryEnd = false; + inserter->pDataBlocks = taosOpenQueue(); + taosThreadMutexInit(&inserter->mutex, NULL); + if (NULL == inserter->pDataBlocks) { + terrno = TSDB_CODE_QRY_OUT_OF_MEMORY; + return TSDB_CODE_QRY_OUT_OF_MEMORY; + } + *pHandle = inserter; + return TSDB_CODE_SUCCESS; +} diff --git a/source/libs/scheduler/src/schTask.c b/source/libs/scheduler/src/schTask.c index be33d686c8..e60006d75c 100644 --- a/source/libs/scheduler/src/schTask.c +++ b/source/libs/scheduler/src/schTask.c @@ -159,7 +159,6 @@ int32_t schProcessOnTaskFailure(SSchJob *pJob, SSchTask *pTask, int32_t errCode) bool needRetry = false; bool moved = false; int32_t taskDone = 0; - int32_t code = 0; SCH_TASK_DLOG("taskOnFailure, code:%s", tstrerror(errCode)); @@ -180,8 +179,10 @@ int32_t schProcessOnTaskFailure(SSchJob *pJob, SSchTask *pTask, int32_t errCode) if (taskDone < pTask->level->taskNum) { SCH_TASK_DLOG("need to wait other tasks, doneNum:%d, allNum:%d", taskDone, pTask->level->taskNum); - SCH_RET(errCode); + SCH_RET(TSDB_CODE_SCH_IGNORE_ERROR); } + + SCH_RET(atomic_load_32(&pJob->errCode)); } } else { SCH_ERR_RET(schHandleTaskRetry(pJob, pTask)); @@ -189,7 +190,7 @@ int32_t schProcessOnTaskFailure(SSchJob *pJob, SSchTask *pTask, int32_t errCode) return TSDB_CODE_SUCCESS; } - SCH_RET(code); + SCH_RET(errCode); } From 641531bc6dcef97092db1a47dc963b64fac050d6 Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Wed, 6 Jul 2022 09:09:34 +0800 Subject: [PATCH 9/9] fix: fix compile issue --- source/libs/executor/src/dataInserter.c | 30 ++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/source/libs/executor/src/dataInserter.c b/source/libs/executor/src/dataInserter.c index 5c65e95807..c424cb33fa 100644 --- a/source/libs/executor/src/dataInserter.c +++ b/source/libs/executor/src/dataInserter.c @@ -45,7 +45,7 @@ typedef struct SDataInserterHandle { SDataDeleterNode* pDeleter; SDeleterParam* pParam; STaosQueue* pDataBlocks; - SDataDeleterBuf nextOutput; + SDataInserterBuf nextOutput; int32_t status; bool queryEnd; uint64_t useconds; @@ -69,7 +69,7 @@ static bool needCompress(const SSDataBlock* pData, int32_t numOfCols) { return false; } -static void toDataCacheEntry(SDataDeleterHandle* pHandle, const SInputData* pInput, SDataDeleterBuf* pBuf) { +static void toDataCacheEntry(SDataInserterHandle* pHandle, const SInputData* pInput, SDataInserterBuf* pBuf) { int32_t numOfCols = LIST_LENGTH(pHandle->pSchema->pSlots); SDataCacheEntry* pEntry = (SDataCacheEntry*)pBuf->pData; @@ -98,7 +98,7 @@ static void toDataCacheEntry(SDataDeleterHandle* pHandle, const SInputData* pInp atomic_add_fetch_64(&gDataSinkStat.cachedSize, pEntry->dataLen); } -static bool allocBuf(SDataDeleterHandle* pDeleter, const SInputData* pInput, SDataDeleterBuf* pBuf) { +static bool allocBuf(SDataInserterHandle* pDeleter, const SInputData* pInput, SDataInserterBuf* pBuf) { uint32_t capacity = pDeleter->pManager->cfg.maxDataBlockNumPerQuery; if (taosQueueItemSize(pDeleter->pDataBlocks) > capacity) { qError("SinkNode queue is full, no capacity, max:%d, current:%d, no capacity", capacity, @@ -116,7 +116,7 @@ static bool allocBuf(SDataDeleterHandle* pDeleter, const SInputData* pInput, SDa return NULL != pBuf->pData; } -static int32_t updateStatus(SDataDeleterHandle* pDeleter) { +static int32_t updateStatus(SDataInserterHandle* pDeleter) { taosThreadMutexLock(&pDeleter->mutex); int32_t blockNums = taosQueueItemSize(pDeleter->pDataBlocks); int32_t status = @@ -127,7 +127,7 @@ static int32_t updateStatus(SDataDeleterHandle* pDeleter) { return status; } -static int32_t getStatus(SDataDeleterHandle* pDeleter) { +static int32_t getStatus(SDataInserterHandle* pDeleter) { taosThreadMutexLock(&pDeleter->mutex); int32_t status = pDeleter->status; taosThreadMutexUnlock(&pDeleter->mutex); @@ -135,8 +135,8 @@ static int32_t getStatus(SDataDeleterHandle* pDeleter) { } static int32_t putDataBlock(SDataSinkHandle* pHandle, const SInputData* pInput, bool* pContinue) { - SDataDeleterHandle* pDeleter = (SDataDeleterHandle*)pHandle; - SDataDeleterBuf* pBuf = taosAllocateQitem(sizeof(SDataDeleterBuf), DEF_QITEM); + SDataInserterHandle* pDeleter = (SDataInserterHandle*)pHandle; + SDataInserterBuf* pBuf = taosAllocateQitem(sizeof(SDataInserterBuf), DEF_QITEM); if (NULL == pBuf || !allocBuf(pDeleter, pInput, pBuf)) { return TSDB_CODE_QRY_OUT_OF_MEMORY; } @@ -147,7 +147,7 @@ static int32_t putDataBlock(SDataSinkHandle* pHandle, const SInputData* pInput, } static void endPut(struct SDataSinkHandle* pHandle, uint64_t useconds) { - SDataDeleterHandle* pDeleter = (SDataDeleterHandle*)pHandle; + SDataInserterHandle* pDeleter = (SDataInserterHandle*)pHandle; taosThreadMutexLock(&pDeleter->mutex); pDeleter->queryEnd = true; pDeleter->useconds = useconds; @@ -155,16 +155,16 @@ static void endPut(struct SDataSinkHandle* pHandle, uint64_t useconds) { } static void getDataLength(SDataSinkHandle* pHandle, int32_t* pLen, bool* pQueryEnd) { - SDataDeleterHandle* pDeleter = (SDataDeleterHandle*)pHandle; + SDataInserterHandle* pDeleter = (SDataInserterHandle*)pHandle; if (taosQueueEmpty(pDeleter->pDataBlocks)) { *pQueryEnd = pDeleter->queryEnd; *pLen = 0; return; } - SDataDeleterBuf* pBuf = NULL; + SDataInserterBuf* pBuf = NULL; taosReadQitem(pDeleter->pDataBlocks, (void**)&pBuf); - memcpy(&pDeleter->nextOutput, pBuf, sizeof(SDataDeleterBuf)); + memcpy(&pDeleter->nextOutput, pBuf, sizeof(SDataInserterBuf)); taosFreeQitem(pBuf); *pLen = ((SDataCacheEntry*)(pDeleter->nextOutput.pData))->dataLen; *pQueryEnd = pDeleter->queryEnd; @@ -172,7 +172,7 @@ static void getDataLength(SDataSinkHandle* pHandle, int32_t* pLen, bool* pQueryE } static int32_t getDataBlock(SDataSinkHandle* pHandle, SOutputData* pOutput) { - SDataDeleterHandle* pDeleter = (SDataDeleterHandle*)pHandle; + SDataInserterHandle* pDeleter = (SDataInserterHandle*)pHandle; if (NULL == pDeleter->nextOutput.pData) { assert(pDeleter->queryEnd); pOutput->useconds = pDeleter->useconds; @@ -202,11 +202,11 @@ static int32_t getDataBlock(SDataSinkHandle* pHandle, SOutputData* pOutput) { } static int32_t destroyDataSinker(SDataSinkHandle* pHandle) { - SDataDeleterHandle* pDeleter = (SDataDeleterHandle*)pHandle; + SDataInserterHandle* pDeleter = (SDataInserterHandle*)pHandle; atomic_sub_fetch_64(&gDataSinkStat.cachedSize, pDeleter->cachedSize); taosMemoryFreeClear(pDeleter->nextOutput.pData); while (!taosQueueEmpty(pDeleter->pDataBlocks)) { - SDataDeleterBuf* pBuf = NULL; + SDataInserterBuf* pBuf = NULL; taosReadQitem(pDeleter->pDataBlocks, (void**)&pBuf); taosMemoryFreeClear(pBuf->pData); taosFreeQitem(pBuf); @@ -217,7 +217,7 @@ static int32_t destroyDataSinker(SDataSinkHandle* pHandle) { } static int32_t getCacheSize(struct SDataSinkHandle* pHandle, uint64_t* size) { - SDataDeleterHandle* pDispatcher = (SDataDeleterHandle*)pHandle; + SDataInserterHandle* pDispatcher = (SDataInserterHandle*)pHandle; *size = atomic_load_64(&pDispatcher->cachedSize); return TSDB_CODE_SUCCESS;