From 51ef795d7369191804f9f13197dd6bfa7d230c76 Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Fri, 14 Jan 2022 18:58:07 +0800 Subject: [PATCH] feature/qnode --- include/util/taoserror.h | 1 + source/libs/qworker/inc/qworkerInt.h | 77 +- source/libs/qworker/src/qworker.c | 1977 ++++++++++---------------- source/libs/qworker/src/qworkerMsg.c | 605 ++++++++ source/util/src/terror.c | 8 + 5 files changed, 1451 insertions(+), 1217 deletions(-) create mode 100644 source/libs/qworker/src/qworkerMsg.c diff --git a/include/util/taoserror.h b/include/util/taoserror.h index 854d16f67d..1cd513b8c0 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -437,3 +437,4 @@ int32_t* taosGetErrno(); #endif #endif /*_TD_COMMON_TAOS_ERROR_H_*/ + \ No newline at end of file diff --git a/source/libs/qworker/inc/qworkerInt.h b/source/libs/qworker/inc/qworkerInt.h index 4030ad82ad..d3c91b9004 100644 --- a/source/libs/qworker/inc/qworkerInt.h +++ b/source/libs/qworker/inc/qworkerInt.h @@ -27,14 +27,29 @@ extern "C" { #define QWORKER_DEFAULT_SCH_TASK_NUMBER 10000 enum { - QW_READY_NOT_RECEIVED = 0, - QW_READY_RECEIVED, - QW_READY_RESPONSED, + QW_PHASE_PRE_QUERY = 1, + QW_PHASE_POST_QUERY, + QW_PHASE_PRE_CQUERY, + QW_PHASE_POST_CQUERY, + QW_PHASE_PRE_SINK, + QW_PHASE_POST_SINK, + QW_PHASE_PRE_FETCH, + QW_PHASE_POST_FETCH, }; enum { - QW_TASK_INFO_STATUS = 1, - QW_TASK_INFO_READY, + QW_EVENT_CANCEL = 1, + QW_EVENT_READY, + QW_EVENT_FETCH, + QW_EVENT_DROP, + + QW_EVENT_MAX, +}; + +enum { + QW_EVENT_NOT_RECEIVED = 0, + QW_EVENT_RECEIVED, + QW_EVENT_PROCESSED, }; enum { @@ -57,21 +72,43 @@ enum { QW_ADD_ACQUIRE, }; +typedef struct SQWMsg { + void *node; + char *msg; + int32_t msgLen; + void *connection; +} SQWMsg; + +typedef struct SQWPhaseInput { + int8_t status; + int32_t code; +} SQWPhaseInput; + +typedef struct SQWPhaseOutput { + int32_t rspCode; + bool needStop; + bool needRsp; +} SQWPhaseOutput; + + typedef struct SQWTaskStatus { - SRWLatch lock; int32_t code; int8_t status; - int8_t ready; - bool cancel; - bool drop; } SQWTaskStatus; typedef struct SQWTaskCtx { SRWLatch lock; - int8_t sinkScheduled; - int8_t queryScheduled; + int32_t phase; + + int8_t sinkInQ; + int8_t queryInQ; + + int8_t events[QW_EVENT_MAX]; + int8_t ready; + int8_t cancel; + int8_t drop; + int8_t needRsp; - bool needRsp; qTaskInfo_t taskHandle; DataSinkHandle sinkHandle; } SQWTaskCtx; @@ -95,6 +132,17 @@ typedef struct SQWorkerMgmt { putReqToQueryQFp putToQueueFp; } SQWorkerMgmt; +#define QW_FPARAMS_DEF SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId +#define QW_IDS() sId, qId, tId +#define QW_FPARAMS() mgmt, QW_IDS() + +#define QW_IS_EVENT_RECEIVED(ctx, event) ((ctx)->events[event] == QW_EVENT_RECEIVED) +#define QW_IS_EVENT_PROCESSED(ctx, event) ((ctx)->events[event] == QW_EVENT_PROCESSED) +#define QW_SET_EVENT_RECEIVED(ctx, event) ((ctx)->events[event] = QW_EVENT_RECEIVED) +#define QW_SET_EVENT_PROCESSED(ctx, event) ((ctx)->events[event] = QW_EVENT_PROCESSED) + +#define QW_IN_EXECUTOR(ctx) ((ctx)->phase == QW_PHASE_PRE_QUERY || (ctx)->phase == QW_PHASE_PRE_CQUERY || (ctx)->phase == QW_PHASE_PRE_FETCH || (ctx)->phase == QW_PHASE_PRE_SINK) + #define QW_GOT_RES_DATA(data) (true) #define QW_LOW_RES_DATA(data) (false) @@ -103,7 +151,6 @@ typedef struct SQWorkerMgmt { #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) #define QW_SET_QTID(id, qId, tId) do { *(uint64_t *)(id) = (qId); *(uint64_t *)((char *)(id) + sizeof(qId)) = (tId); } while (0) #define QW_GET_QTID(id, qId, tId) do { (qId) = *(uint64_t *)(id); (tId) = *(uint64_t *)((char *)(id) + sizeof(qId)); } while (0) -#define QW_IDS() sId, qId, tId #define QW_ERR_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { terrno = _code; return _code; } } while (0) #define QW_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { terrno = _code; } return _code; } while (0) @@ -160,10 +207,6 @@ typedef struct SQWorkerMgmt { -int32_t qwAcquireScheduler(int32_t rwType, SQWorkerMgmt *mgmt, uint64_t sId, SQWSchStatus **sch); -int32_t qwAcquireAddScheduler(int32_t rwType, SQWorkerMgmt *mgmt, uint64_t sId, SQWSchStatus **sch); -int32_t qwAcquireTask(SQWorkerMgmt *mgmt, int32_t rwType, SQWSchStatus *sch, uint64_t qId, uint64_t tId, SQWTaskStatus **task); - #ifdef __cplusplus } diff --git a/source/libs/qworker/src/qworker.c b/source/libs/qworker/src/qworker.c index 1be190065a..03f07f3f37 100644 --- a/source/libs/qworker/src/qworker.c +++ b/source/libs/qworker/src/qworker.c @@ -8,7 +8,7 @@ #include "tname.h" #include "dataSinkMgt.h" -int32_t qwValidateStatus(SQWorkerMgmt *mgmt, int8_t oriStatus, int8_t newStatus, uint64_t sId, uint64_t qId, uint64_t tId) { +int32_t qwValidateStatus(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, int8_t oriStatus, int8_t newStatus) { int32_t code = 0; if (oriStatus == newStatus) { @@ -74,105 +74,85 @@ _return: QW_RET(code); } -int32_t qwUpdateTaskInfo(SQWorkerMgmt *mgmt, SQWTaskStatus *task, int8_t type, void *data, uint64_t sId, uint64_t qId, uint64_t tId) { +int32_t qwSetTaskStatus(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SQWTaskStatus *task, int8_t status) { int32_t code = 0; int8_t origStatus = 0; - - switch (type) { - case QW_TASK_INFO_STATUS: { - int8_t newStatus = *(int8_t *)data; - QW_ERR_RET(qwValidateStatus(mgmt, task->status, newStatus, QW_IDS())); - - origStatus = task->status; - task->status = newStatus; - - QW_TASK_DLOG("task status updated from %d to %d", origStatus, newStatus); - break; + + while (true) { + origStatus = atomic_load_8(&task->status); + + QW_ERR_RET(qwValidateStatus(QW_FPARAMS(), origStatus, status)); + + if (origStatus != atomic_val_compare_exchange_8(&task->status, origStatus, status)) { + continue; } - default: - QW_TASK_ELOG("unknown task info, type:%d", type); - return TSDB_CODE_QRY_APP_ERROR; + + QW_TASK_DLOG("task status updated from %d to %d", origStatus, status); + + break; } return TSDB_CODE_SUCCESS; } -int32_t qwAddTaskHandlesToCache(SQWorkerMgmt *mgmt, uint64_t qId, uint64_t tId, qTaskInfo_t taskHandle, DataSinkHandle sinkHandle) { - char id[sizeof(qId) + sizeof(tId)] = {0}; - QW_SET_QTID(id, qId, tId); - SQWTaskCtx resCache = {0}; - resCache.taskHandle = taskHandle; - resCache.sinkHandle = sinkHandle; - - QW_LOCK(QW_WRITE, &mgmt->ctxLock); - if (0 != taosHashPut(mgmt->ctxHash, id, sizeof(id), &resCache, sizeof(SQWTaskCtx))) { - QW_UNLOCK(QW_WRITE, &mgmt->ctxLock); - QW_TASK_ELOG("taosHashPut task ctx to ctxHash failed, taskHandle:%p, sinkHandle:%p", taskHandle, sinkHandle); - return TSDB_CODE_QRY_APP_ERROR; - } - - QW_UNLOCK(QW_WRITE, &mgmt->ctxLock); - - return TSDB_CODE_SUCCESS; -} - -int32_t qwAddScheduler(int32_t rwType, SQWorkerMgmt *mgmt, uint64_t sId, SQWSchStatus **sch) { +int32_t qwAddSchedulerImpl(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, int32_t rwType, SQWSchStatus **sch) { SQWSchStatus newSch = {0}; newSch.tasksHash = taosHashInit(mgmt->cfg.maxSchTaskNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); if (NULL == newSch.tasksHash) { - QW_SCH_DLOG("taosHashInit %d failed", mgmt->cfg.maxSchTaskNum); - return TSDB_CODE_QRY_OUT_OF_MEMORY; + QW_SCH_ELOG("taosHashInit %d failed", mgmt->cfg.maxSchTaskNum); + QW_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); } - while (true) { - QW_LOCK(QW_WRITE, &mgmt->schLock); - int32_t code = taosHashPut(mgmt->schHash, &sId, sizeof(sId), &newSch, sizeof(newSch)); - if (0 != code) { - if (!HASH_NODE_EXIST(code)) { - QW_UNLOCK(QW_WRITE, &mgmt->schLock); - QW_SCH_ELOG("taosHashPut new sch to scheduleHash failed, errno:%d", errno); - taosHashCleanup(newSch.tasksHash); - return TSDB_CODE_QRY_APP_ERROR; - } - } - - QW_UNLOCK(QW_WRITE, &mgmt->schLock); - if (TSDB_CODE_SUCCESS == qwAcquireScheduler(rwType, mgmt, sId, sch)) { - if (code) { - taosHashCleanup(newSch.tasksHash); - } + QW_LOCK(QW_WRITE, &mgmt->schLock); + int32_t code = taosHashPut(mgmt->schHash, &sId, sizeof(sId), &newSch, sizeof(newSch)); + if (0 != code) { + if (!HASH_NODE_EXIST(code)) { + QW_UNLOCK(QW_WRITE, &mgmt->schLock); - return TSDB_CODE_SUCCESS; + QW_SCH_ELOG("taosHashPut new sch to scheduleHash failed, errno:%d", errno); + taosHashCleanup(newSch.tasksHash); + QW_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); } + + taosHashCleanup(newSch.tasksHash); + } + QW_UNLOCK(QW_WRITE, &mgmt->schLock); + + return TSDB_CODE_SUCCESS; +} + +int32_t qwAcquireSchedulerImpl(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, int32_t rwType, SQWSchStatus **sch, int32_t nOpt) { + while (true) { + QW_LOCK(rwType, &mgmt->schLock); + *sch = taosHashGet(mgmt->schHash, &sId, sizeof(sId)); + if (NULL == (*sch)) { + QW_UNLOCK(rwType, &mgmt->schLock); + + if (QW_NOT_EXIST_ADD == nOpt) { + QW_ERR_RET(qwAddSchedulerImpl(rwType, mgmt, sId, sch)); + + nOpt = QW_NOT_EXIST_RET_ERR; + + continue; + } else if (QW_NOT_EXIST_RET_ERR == nOpt) { + QW_RET(TSDB_CODE_QRY_SCH_NOT_EXIST); + } else { + assert(0); + } + } + + break; } return TSDB_CODE_SUCCESS; } -int32_t qwAcquireSchedulerImpl(int32_t rwType, SQWorkerMgmt *mgmt, uint64_t sId, SQWSchStatus **sch, int32_t nOpt) { - QW_LOCK(rwType, &mgmt->schLock); - *sch = taosHashGet(mgmt->schHash, &sId, sizeof(sId)); - if (NULL == (*sch)) { - QW_UNLOCK(rwType, &mgmt->schLock); - - if (QW_NOT_EXIST_ADD == nOpt) { - return qwAddScheduler(rwType, mgmt, sId, sch); - } else if (QW_NOT_EXIST_RET_ERR == nOpt) { - return TSDB_CODE_QRY_SCH_NOT_EXIST; - } else { - assert(0); - } - } - - return TSDB_CODE_SUCCESS; -} - -int32_t qwAcquireAddScheduler(int32_t rwType, SQWorkerMgmt *mgmt, uint64_t sId, SQWSchStatus **sch) { +int32_t qwAcquireAddScheduler(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, int32_t rwType, SQWSchStatus **sch) { return qwAcquireSchedulerImpl(rwType, mgmt, sId, sch, QW_NOT_EXIST_ADD); } -int32_t qwAcquireScheduler(int32_t rwType, SQWorkerMgmt *mgmt, uint64_t sId, SQWSchStatus **sch) { +int32_t qwAcquireScheduler(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, int32_t rwType, SQWSchStatus **sch) { return qwAcquireSchedulerImpl(rwType, mgmt, sId, sch, QW_NOT_EXIST_RET_ERR); } @@ -180,7 +160,7 @@ void qwReleaseScheduler(int32_t rwType, SQWorkerMgmt *mgmt) { QW_UNLOCK(rwType, &mgmt->schLock); } -int32_t qwAddTaskImpl(SQWorkerMgmt *mgmt, SQWSchStatus *sch, int32_t rwType, uint64_t qId, uint64_t tId, int32_t status, int32_t eOpt, SQWTaskStatus **task) { +int32_t qwAddTaskStatusImpl(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SQWSchStatus *sch, int32_t rwType, int32_t status, SQWTaskStatus **task) { int32_t code = 0; char id[sizeof(qId) + sizeof(tId)] = {0}; @@ -194,43 +174,42 @@ int32_t qwAddTaskImpl(SQWorkerMgmt *mgmt, SQWSchStatus *sch, int32_t rwType, uin if (0 != code) { QW_UNLOCK(QW_WRITE, &sch->tasksLock); if (HASH_NODE_EXIST(code)) { - if (QW_EXIST_ACQUIRE == eOpt && rwType && task) { - QW_ERR_RET(qwAcquireTask(mgmt, rwType, sch, qId, tId, task)); - } else if (QW_EXIST_RET_ERR == eOpt) { - return TSDB_CODE_QRY_TASK_ALREADY_EXIST; + if (rwType && task) { + QW_RET(qwAcquireTaskStatus(QW_FPARAMS(), rwType, sch, task)); } else { - assert(0); + QW_TASK_ELOG("task status already exist, id:%s", id); + QW_ERR_RET(TSDB_CODE_QRY_TASK_ALREADY_EXIST); } } else { - qError("taosHashPut queryId[%"PRIx64"] taskId[%"PRIx64"] to scheduleHash failed", qId, tId); - return TSDB_CODE_QRY_APP_ERROR; + QW_TASK_ELOG("taosHashPut to tasksHash failed, code:%x", code); + QW_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); } } - QW_UNLOCK(QW_WRITE, &sch->tasksLock); - if (QW_EXIST_ACQUIRE == eOpt && rwType && task) { - QW_ERR_RET(qwAcquireTask(mgmt, rwType, sch, qId, tId, task)); + if (rwType && task) { + QW_ERR_RET(qwAcquireTaskStatus(QW_FPARAMS(), rwType, sch, task)); } return TSDB_CODE_SUCCESS; } -int32_t qwAddTask(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, int32_t status) { +int32_t qwAddTaskStatus(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, int32_t status) { SQWSchStatus *tsch = NULL; int32_t code = 0; - QW_ERR_RET(qwAcquireAddScheduler(QW_READ, mgmt, sId, &tsch)); + QW_ERR_RET(qwAcquireAddScheduler(QW_FPARAMS(), QW_READ, &tsch)); - QW_ERR_JRET(qwAddTaskImpl(mgmt, tsch, 0, qId, tId, status, QW_EXIST_RET_ERR, NULL)); + QW_ERR_JRET(qwAddTaskStatusImpl(QW_FPARAMS(), tsch, 0, status, NULL)); _return: qwReleaseScheduler(QW_READ, mgmt); - QW_ERR_RET(code); + + QW_RET(code); } -int32_t qwAcquireTaskImpl(SQWorkerMgmt *mgmt, int32_t rwType, SQWSchStatus *sch, uint64_t qId, uint64_t tId, int32_t status, int32_t nOpt, SQWTaskStatus **task) { +int32_t qwAcquireTaskStatus(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, int32_t rwType, SQWSchStatus *sch, SQWTaskStatus **task) { char id[sizeof(qId) + sizeof(tId)] = {0}; QW_SET_QTID(id, qId, tId); @@ -238,938 +217,612 @@ int32_t qwAcquireTaskImpl(SQWorkerMgmt *mgmt, int32_t rwType, SQWSchStatus *sch, *task = taosHashGet(sch->tasksHash, id, sizeof(id)); if (NULL == (*task)) { QW_UNLOCK(rwType, &sch->tasksLock); - - if (QW_NOT_EXIST_ADD == nOpt) { - QW_ERR_RET(qwAddTaskImpl(mgmt, sch, rwType, qId, tId, status, QW_EXIST_ACQUIRE, task)); - } else if (QW_NOT_EXIST_RET_ERR == nOpt) { - return TSDB_CODE_QRY_TASK_NOT_EXIST; - } else { - assert(0); - } + QW_ERR_RET(TSDB_CODE_QRY_TASK_NOT_EXIST); } return TSDB_CODE_SUCCESS; } -int32_t qwAcquireTask(SQWorkerMgmt *mgmt, int32_t rwType, SQWSchStatus *sch, uint64_t qId, uint64_t tId, SQWTaskStatus **task) { - return qwAcquireTaskImpl(mgmt, rwType, sch, qId, tId, 0, QW_NOT_EXIST_RET_ERR, task); -} -int32_t qwAcquireAddTask(SQWorkerMgmt *mgmt, int32_t rwType, SQWSchStatus *sch, uint64_t qId, uint64_t tId, int32_t status, SQWTaskStatus **task) { - return qwAcquireTaskImpl(mgmt, rwType, sch, qId, tId, status, QW_NOT_EXIST_ADD, task); +int32_t qwAddAcquireTaskStatus(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, int32_t rwType, SQWSchStatus *sch, int32_t status, SQWTaskStatus **task) { + return qwAddTaskStatusImpl(QW_FPARAMS(), sch, rwType, status, task); } -void qwReleaseTask(int32_t rwType, SQWSchStatus *sch) { +void qwReleaseTaskStatus(int32_t rwType, SQWSchStatus *sch) { QW_UNLOCK(rwType, &sch->tasksLock); } +int32_t qwAddTaskCtxImpl(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, int32_t rwType, int32_t status, SQWTaskCtx **ctx) { + char id[sizeof(qId) + sizeof(tId)] = {0}; + QW_SET_QTID(id, qId, tId); -int32_t qwAcquireTaskCtx(int32_t rwType, SQWorkerMgmt *mgmt, uint64_t queryId, uint64_t taskId, SQWTaskCtx **handles) { - char id[sizeof(queryId) + sizeof(taskId)] = {0}; - QW_SET_QTID(id, queryId, taskId); - - QW_LOCK(rwType, &mgmt->ctxLock); - *handles = taosHashGet(mgmt->ctxHash, id, sizeof(id)); - if (NULL == (*handles)) { - QW_UNLOCK(rwType, &mgmt->ctxLock); - return TSDB_CODE_QRY_RES_CACHE_NOT_EXIST; + SQWTaskCtx ctx = {0}; + + QW_LOCK(QW_WRITE, &mgmt->ctxLock); + int32_t code = taosHashPut(mgmt->ctxHash, id, sizeof(id), &ctx, sizeof(SQWTaskCtx)); + if (0 != code) { + QW_UNLOCK(QW_WRITE, &mgmt->ctxLock); + + if (HASH_NODE_EXIST(code)) { + if (rwType && ctx) { + QW_RET(qwAcquireTaskCtx(QW_FPARAMS(), rwType, ctx)); + } else { + QW_TASK_ELOG("task ctx already exist, id:%s", id); + QW_ERR_RET(TSDB_CODE_QRY_TASK_ALREADY_EXIST); + } + } else { + QW_TASK_ELOG("taosHashPut to ctxHash failed, code:%x", code); + QW_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + } + QW_UNLOCK(QW_WRITE, &mgmt->ctxLock); + + if (rwType && ctx) { + QW_RET(qwAcquireTaskCtx(QW_FPARAMS(), rwType, ctx)); } return TSDB_CODE_SUCCESS; } -void qwReleaseTaskResCache(int32_t rwType, SQWorkerMgmt *mgmt) { +int32_t qwAddTaskCtx(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId) { + QW_RET(qwAddTaskCtxImpl(QW_FPARAMS(), 0, 0, NULL)); +} + + + +int32_t qwAcquireTaskCtx(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, int32_t rwType, SQWTaskCtx **ctx) { + char id[sizeof(qId) + sizeof(tId)] = {0}; + QW_SET_QTID(id, qId, tId); + + QW_LOCK(rwType, &mgmt->ctxLock); + *ctx = taosHashGet(mgmt->ctxHash, id, sizeof(id)); + if (NULL == (*ctx)) { + QW_UNLOCK(rwType, &mgmt->ctxLock); + QW_TASK_ELOG("ctx not in ctxHash, id:%s", id); + QW_ERR_RET(TSDB_CODE_QRY_RES_CACHE_NOT_EXIST); + } + + return TSDB_CODE_SUCCESS; +} + +int32_t qwAddAcquireTaskCtx(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, int32_t rwType, SQWTaskCtx **ctx) { + return qwAddTaskCtxImpl(QW_FPARAMS(), rwType, 0, ctx); +} + +void qwReleaseTaskCtx(int32_t rwType, SQWorkerMgmt *mgmt) { QW_UNLOCK(rwType, &mgmt->ctxLock); } -int32_t qwGetSchTasksStatus(SQWorkerMgmt *mgmt, uint64_t sId, SSchedulerStatusRsp **rsp) { - SQWSchStatus *sch = NULL; - int32_t taskNum = 0; - - QW_ERR_RET(qwAcquireScheduler(QW_READ, mgmt, sId, &sch)); - - sch->lastAccessTs = taosGetTimestampSec(); - - QW_LOCK(QW_READ, &sch->tasksLock); - - taskNum = taosHashGetSize(sch->tasksHash); - - int32_t size = sizeof(SSchedulerStatusRsp) + sizeof((*rsp)->status[0]) * taskNum; - *rsp = calloc(1, size); - if (NULL == *rsp) { - qError("calloc %d failed", size); - QW_UNLOCK(QW_READ, &sch->tasksLock); - qwReleaseScheduler(QW_READ, mgmt); - - return TSDB_CODE_QRY_OUT_OF_MEMORY; +void qwFreeTask(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SQWTaskCtx *ctx) { + if (ctx->taskHandle) { + qDestroyTask(ctx->taskHandle); + ctx->taskHandle = NULL; } - void *key = NULL; - size_t keyLen = 0; - int32_t i = 0; + // TODO + if (ctx->sinkHandle) { - void *pIter = taosHashIterate(sch->tasksHash, NULL); - while (pIter) { - SQWTaskStatus *taskStatus = (SQWTaskStatus *)pIter; - taosHashGetKey(pIter, &key, &keyLen); + } +} - QW_GET_QTID(key, (*rsp)->status[i].queryId, (*rsp)->status[i].taskId); - (*rsp)->status[i].status = taskStatus->status; - - pIter = taosHashIterate(sch->tasksHash, pIter); - } - QW_UNLOCK(QW_READ, &sch->tasksLock); - qwReleaseScheduler(QW_READ, mgmt); +// Note: NEED CTX HASH LOCKED BEFORE ENTRANCE +int32_t qwDropTaskCtx(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId) { + char id[sizeof(qId) + sizeof(tId)] = {0}; + QW_SET_QTID(id, qId, tId); + SQWTaskCtx octx; - (*rsp)->num = taskNum; + SQWTaskCtx *ctx = taosHashGet(mgmt->ctxHash, id, sizeof(id)); + if (NULL == ctx) { + QW_ERR_RET(TSDB_CODE_QRY_RES_CACHE_NOT_EXIST); + } + octx = *ctx; + + if (taosHashRemove(mgmt->ctxHash, id, sizeof(id))) { + QW_TASK_ELOG("taosHashRemove from ctx hash failed, id:%s", id); + QW_ERR_RET(TSDB_CODE_QRY_RES_CACHE_NOT_EXIST); + } + + if (octx.taskHandle) { + qDestroyTask(octx.taskHandle); + } + + if (octx.sinkHandle) { + dsDestroyDataSinker(octx.sinkHandle); + } + return TSDB_CODE_SUCCESS; } - -int32_t qwUpdateSchLastAccess(SQWorkerMgmt *mgmt, uint64_t sId) { +int32_t qwDropTaskStatus(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId) { SQWSchStatus *sch = NULL; + SQWTaskStatus *task = NULL; + int32_t code = 0; + + char id[sizeof(qId) + sizeof(tId)] = {0}; + QW_SET_QTID(id, qId, tId); - QW_ERR_RET(qwAcquireScheduler(QW_READ, mgmt, sId, &sch)); + if (qwAcquireScheduler(QW_FPARAMS(), QW_WRITE, &sch)) { + QW_TASK_WLOG("scheduler does not exist, id:%s", id); + return TSDB_CODE_SUCCESS; + } - sch->lastAccessTs = taosGetTimestampSec(); + if (qwAcquireTaskStatus(QW_FPARAMS(), QW_WRITE, sch, &task)) { + qwReleaseScheduler(QW_WRITE, mgmt); + + QW_TASK_WLOG("task does not exist, id:%s", id); + return TSDB_CODE_SUCCESS; + } - qwReleaseScheduler(QW_READ, mgmt); + if (taosHashRemove(sch->tasksHash, id, sizeof(id))) { + QW_TASK_ELOG("taosHashRemove task from hash failed, task:%p", task); + QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); + } + + QW_TASK_DLOG("task dropped, id:%d", id); + +_return: + + qwReleaseTaskStatus(QW_WRITE, sch); + qwReleaseScheduler(QW_WRITE, mgmt); + + QW_RET(code); +} + +int32_t qwUpdateTaskCtxHandles(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, qTaskInfo_t taskHandle, DataSinkHandle sinkHandle) { + SQWTaskCtx *ctx = NULL; + + QW_ERR_RET(qwAcquireTaskCtx(QW_FPARAMS(), QW_READ, &ctx)); + + ctx->taskHandle = taskHandle; + ctx->sinkHandle = sinkHandle; + + qwReleaseTaskCtx(QW_READ, mgmt); return TSDB_CODE_SUCCESS; } + int32_t qwUpdateTaskStatus(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, int8_t status) { SQWSchStatus *sch = NULL; SQWTaskStatus *task = NULL; int32_t code = 0; QW_ERR_RET(qwAcquireScheduler(QW_READ, mgmt, sId, &sch)); + QW_ERR_JRET(qwAcquireTaskStatus(mgmt, QW_READ, sch, qId, tId, &task)); - QW_ERR_JRET(qwAcquireTask(mgmt, QW_READ, sch, qId, tId, &task)); - - QW_LOCK(QW_WRITE, &task->lock); - qwUpdateTaskInfo(mgmt, task, QW_TASK_INFO_STATUS, &status, QW_IDS()); - QW_UNLOCK(QW_WRITE, &task->lock); + QW_ERR_JRET(qwSetTaskStatus(QW_FPARAMS(), task, status)); _return: - qwReleaseTask(QW_READ, sch); + qwReleaseTaskStatus(QW_READ, sch); qwReleaseScheduler(QW_READ, mgmt); QW_RET(code); } -int32_t qwGetTaskStatus(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t queryId, uint64_t taskId, int8_t *taskStatus) { - SQWSchStatus *sch = NULL; - SQWTaskStatus *task = NULL; +int32_t qwDropTask(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, bool *needRsp) { int32_t code = 0; + SQWTaskCtx *ctx = NULL; + bool locked = false; + + QW_ERR_JRET(qwAddAcquireTaskCtx(QW_FPARAMS(), QW_READ, &ctx)); - if (qwAcquireScheduler(QW_READ, mgmt, sId, &sch)) { - *taskStatus = JOB_TASK_STATUS_NULL; - return TSDB_CODE_SUCCESS; + QW_LOCK(QW_WRITE, &ctx->lock); + + locked = true; + + if (QW_IS_EVENT_RECEIVED(ctx, QW_EVENT_DROP)) { + QW_TASK_WLOG("task already dropping", NULL); + QW_ERR_JRET(TSDB_CODE_QRY_DUPLICATTED_OPERATION); } - if (qwAcquireTask(mgmt, QW_READ, sch, queryId, taskId, &task)) { - qwReleaseScheduler(QW_READ, mgmt); - - *taskStatus = JOB_TASK_STATUS_NULL; - return TSDB_CODE_SUCCESS; + if (ctx->taskHandle && QW_IN_EXECUTOR(ctx)) { + QW_ERR_JRET(qKillTask(ctx->taskHandle)); + QW_ERR_JRET(qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_DROPPING)); + } else if (ctx->phase > 0) { + QW_ERR_JRET(qwDropTaskStatus(QW_FPARAMS())); + QW_ERR_JRET(qwDropTaskCtx(QW_FPARAMS())); + + locked = false; + *needRsp = true; } - *taskStatus = task->status; - - qwReleaseTask(QW_READ, sch); - qwReleaseScheduler(QW_READ, mgmt); - - QW_RET(code); -} - - -int32_t qwCancelTask(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId) { - SQWSchStatus *sch = NULL; - SQWTaskStatus *task = NULL; - int32_t code = 0; - - QW_ERR_RET(qwAcquireAddScheduler(QW_READ, mgmt, sId, &sch)); - - QW_ERR_JRET(qwAcquireAddTask(mgmt, QW_READ, sch, qId, tId, JOB_TASK_STATUS_NOT_START, &task)); - - - QW_LOCK(QW_WRITE, &task->lock); - - task->cancel = true; - - int8_t oriStatus = task->status; - int8_t newStatus = 0; - - if (task->status == JOB_TASK_STATUS_CANCELLED || task->status == JOB_TASK_STATUS_NOT_START || task->status == JOB_TASK_STATUS_CANCELLING || task->status == JOB_TASK_STATUS_DROPPING) { - QW_UNLOCK(QW_WRITE, &task->lock); - - qwReleaseTask(QW_READ, sch); - qwReleaseScheduler(QW_READ, mgmt); - - return TSDB_CODE_SUCCESS; - } else if (task->status == JOB_TASK_STATUS_FAILED || task->status == JOB_TASK_STATUS_SUCCEED || task->status == JOB_TASK_STATUS_PARTIAL_SUCCEED) { - newStatus = JOB_TASK_STATUS_CANCELLED; - QW_ERR_JRET(qwUpdateTaskInfo(mgmt, task, QW_TASK_INFO_STATUS, &newStatus, QW_IDS())); - } else { - newStatus = JOB_TASK_STATUS_CANCELLING; - QW_ERR_JRET(qwUpdateTaskInfo(mgmt, task, QW_TASK_INFO_STATUS, &newStatus, QW_IDS())); - } - - QW_UNLOCK(QW_WRITE, &task->lock); - - qwReleaseTask(QW_READ, sch); - qwReleaseScheduler(QW_READ, mgmt); - - if (oriStatus == JOB_TASK_STATUS_EXECUTING) { - //TODO call executer to cancel subquery async - } - - return TSDB_CODE_SUCCESS; - -_return: - - if (task) { - QW_UNLOCK(QW_WRITE, &task->lock); - - qwReleaseTask(QW_READ, sch); - } - - if (sch) { - qwReleaseScheduler(QW_READ, mgmt); - } - - QW_RET(code); -} - - -// caller should make sure task is not running -int32_t qwDropTaskCtx(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId) { - char id[sizeof(qId) + sizeof(tId)] = {0}; - QW_SET_QTID(id, qId, tId); - - QW_LOCK(QW_WRITE, &mgmt->ctxLock); - SQWTaskCtx *ctx = taosHashGet(mgmt->ctxHash, id, sizeof(id)); - if (NULL == ctx) { - QW_UNLOCK(QW_WRITE, &mgmt->ctxLock); - return TSDB_CODE_QRY_RES_CACHE_NOT_EXIST; - } - - if (ctx->taskHandle) { - qDestroyTask(ctx->taskHandle); - ctx->taskHandle = NULL; - } - - if (ctx->sinkHandle) { - dsDestroyDataSinker(ctx->sinkHandle); - ctx->sinkHandle = NULL; - } - - if (taosHashRemove(mgmt->ctxHash, id, sizeof(id))) { - QW_TASK_ELOG("taosHashRemove from ctx hash failed, id:%s", id); - - QW_UNLOCK(QW_WRITE, &mgmt->ctxLock); - return TSDB_CODE_QRY_RES_CACHE_NOT_EXIST; - } - - QW_UNLOCK(QW_WRITE, &mgmt->ctxLock); - - return TSDB_CODE_SUCCESS; -} - - -int32_t qwDropTask(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId) { - SQWSchStatus *sch = NULL; - SQWTaskStatus *task = NULL; - int32_t code = 0; - - char id[sizeof(qId) + sizeof(tId)] = {0}; - QW_SET_QTID(id, qId, tId); - - qwDropTaskCtx(mgmt, sId, qId, tId); - - if (qwAcquireScheduler(QW_WRITE, mgmt, sId, &sch)) { - QW_TASK_WLOG("scheduler does not exist, sch:%p", sch); - return TSDB_CODE_SUCCESS; - } - - if (qwAcquireTask(mgmt, QW_WRITE, sch, qId, tId, &task)) { - qwReleaseScheduler(QW_WRITE, mgmt); - - QW_TASK_WLOG("task does not exist, task:%p", task); - return TSDB_CODE_SUCCESS; - } - - QW_TASK_DLOG("drop task, status:%d, code:%x, ready:%d, cancel:%d, drop:%d", task->status, task->code, task->ready, task->cancel, task->drop); - - if (taosHashRemove(sch->tasksHash, id, sizeof(id))) { - QW_TASK_ELOG("taosHashRemove task from hash failed, task:%p", task); - QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); + if (locked) { + QW_SET_EVENT_RECEIVED(ctx, QW_EVENT_DROP); } _return: - qwReleaseTask(QW_WRITE, sch); - qwReleaseScheduler(QW_WRITE, mgmt); - + if (locked) { + QW_UNLOCK(QW_WRITE, &ctx->lock); + } + + if (ctx) { + qwReleaseTaskCtx(QW_READ, mgmt); + } + QW_RET(code); } -int32_t qwCancelDropTask(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId) { - SQWSchStatus *sch = NULL; - SQWTaskStatus *task = NULL; + +int32_t qwGetResFromSink(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SQWTaskCtx *ctx, int32_t *dataLen, void **rspMsg) { + int32_t len = 0; + SRetrieveTableRsp *rsp = NULL; + bool queryEnd = false; int32_t code = 0; + SOutputData output = {0}; - QW_ERR_RET(qwAcquireAddScheduler(QW_READ, mgmt, sId, &sch)); + dsGetDataLength(ctx->sinkHandle, &len, &queryEnd); - QW_ERR_JRET(qwAcquireAddTask(mgmt, QW_READ, sch, qId, tId, JOB_TASK_STATUS_NOT_START, &task)); + if (len < 0) { + QW_TASK_ELOG("invalid length from dsGetDataLength, length:%d", len); + QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); + } - QW_LOCK(QW_WRITE, &task->lock); - - task->drop = true; - - int8_t oriStatus = task->status; - int8_t newStatus = 0; - - if (task->status == JOB_TASK_STATUS_EXECUTING) { - newStatus = JOB_TASK_STATUS_DROPPING; - QW_ERR_JRET(qwUpdateTaskInfo(mgmt, task, QW_TASK_INFO_STATUS, &newStatus, QW_IDS())); - } else if (task->status == JOB_TASK_STATUS_CANCELLING || task->status == JOB_TASK_STATUS_DROPPING || task->status == JOB_TASK_STATUS_NOT_START) { - QW_UNLOCK(QW_WRITE, &task->lock); - qwReleaseTask(QW_READ, sch); - qwReleaseScheduler(QW_READ, mgmt); + if (len == 0) { + if (queryEnd) { + code = dsGetDataBlock(ctx->sinkHandle, &output); + if (code) { + QW_TASK_ELOG("dsGetDataBlock failed, code:%x", code); + QW_ERR_RET(code); + } + QW_TASK_DLOG("no data in sink and query end", NULL); + + QW_ERR_RET(qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_SUCCEED)); + + QW_ERR_RET(qwMallocFetchRsp(len, &rsp)); + + qwBuildFetchRsp(rsp, &output, 0); + + *rspMsg = rsp; + + return TSDB_CODE_SUCCESS; + } + + QW_TASK_DLOG("no res data in sink, need response later, queryEnd:%d", queryEnd); + return TSDB_CODE_SUCCESS; - } else { - QW_UNLOCK(QW_WRITE, &task->lock); - qwReleaseTask(QW_READ, sch); - qwReleaseScheduler(QW_READ, mgmt); - - QW_ERR_RET(qwDropTask(mgmt, sId, qId, tId)); - return TSDB_CODE_SUCCESS; + } + + + // Got data from sink + + + // Note: schedule data sink firstly and will schedule query after it's done + if (output.needSchedule) { + QW_TASK_DLOG("sink need schedule, queryEnd:%d", output.queryEnd); + QW_ERR_RET(qwScheduleDataSink(handles, mgmt, sId, qId, tId, pMsg)); + } else if ((!output.queryEnd) && (DS_BUF_LOW == output.bufStatus || DS_BUF_EMPTY == output.bufStatus)) { + QW_TASK_DLOG("task not end, need to continue, bufStatus:%d", output.bufStatus); + QW_ERR_RET(qwScheduleQuery(handles, mgmt, sId, qId, tId, pMsg)); } - QW_UNLOCK(QW_WRITE, &task->lock); - - qwReleaseTask(QW_READ, sch); - qwReleaseScheduler(QW_READ, mgmt); - if (oriStatus == JOB_TASK_STATUS_EXECUTING) { - //TODO call executer to cancel subquery async - } + QW_TASK_DLOG("task got data in sink, dataLength:%d", len); + QW_ERR_RET(qwMallocFetchRsp(len, &rsp)); + + output.pData = rsp->data; + + code = dsGetDataBlock(ctx->sinkHandle, &output); + if (code) { + QW_TASK_ELOG("dsGetDataBlock failed, code:%x", code); + qwFreeFetchRsp(rsp); + QW_ERR_RET(code); + } + + queryEnd = output.queryEnd; + output.queryEnd = false; + + if (DS_BUF_EMPTY == output.bufStatus && queryEnd) { + output.queryEnd = true; + + QW_SCH_TASK_DLOG("task all fetched, status:%d", JOB_TASK_STATUS_SUCCEED); + QW_ERR_RET(qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_SUCCEED)); + } + + qwBuildFetchRsp(rsp, &output, len); + return TSDB_CODE_SUCCESS; +} + + +int32_t qwHandleTaskEvent(QW_FPARAMS_DEF, int32_t phase, SQWPhaseInput *input, SQWPhaseOutput *output) { + int32_t code = 0; + int8_t status = 0; + SQWTaskCtx *ctx = NULL; + bool locked = false; + + switch (phase) { + case QW_PHASE_PRE_QUERY: { + QW_ERR_JRET(qwAddAcquireTaskCtx(QW_FPARAMS(), QW_READ, &ctx)); + + QW_LOCK(QW_WRITE, &ctx->lock); + + locked = true; + + assert(!QW_IS_EVENT_PROCESSED(ctx, QW_EVENT_CANCEL)); + + if (QW_IS_EVENT_RECEIVED(ctx, QW_EVENT_DROP)) { + output->needStop = true; + + QW_ERR_JRET(qwDropTaskStatus(QW_FPARAMS())); + QW_ERR_JRET(qwDropTaskCtx(QW_FPARAMS())); + + output->rspCode = TSDB_CODE_QRY_TASK_DROPPED; + + // Note: ctx freed, no need to unlock it + locked = false; + } else if (QW_IS_EVENT_RECEIVED(ctx, QW_EVENT_CANCEL)) { + output->needStop = true; + + QW_ERR_JRET(qwAddTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_CANCELLED)); + qwFreeTask(QW_FPARAMS(), ctx); + + QW_SET_EVENT_PROCESSED(ctx, QW_EVENT_CANCEL); + + output->rspCode = TSDB_CODE_QRY_TASK_CANCELLED; + } + + if (!output->needStop) { + QW_ERR_JRET(qwAddTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_EXECUTING)); + } + break; + } + case QW_PHASE_POST_QUERY: { + QW_ERR_JRET(qwAddAcquireTaskCtx(QW_FPARAMS(), QW_READ, &ctx)); + + QW_LOCK(QW_WRITE, &ctx->lock); + + locked = true; + + assert(!QW_IS_EVENT_PROCESSED(ctx, QW_EVENT_CANCEL)); + + if (QW_IS_EVENT_RECEIVED(ctx, QW_EVENT_DROP)) { + output->needStop = true; + + QW_ERR_JRET(qwDropTaskStatus(QW_FPARAMS())); + QW_ERR_JRET(qwDropTaskCtx(QW_FPARAMS())); + + output->rspCode = TSDB_CODE_QRY_TASK_DROPPED; + + // Note: ctx freed, no need to unlock it + locked = false; + } else if (QW_IS_EVENT_RECEIVED(ctx, QW_EVENT_CANCEL)) { + output->needStop = true; + + QW_ERR_JRET(qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_CANCELLED)); + qwFreeTask(QW_FPARAMS(), ctx); + + QW_SET_EVENT_PROCESSED(ctx, QW_EVENT_CANCEL); + + output->rspCode = TSDB_CODE_QRY_TASK_CANCELLED; + } else if (QW_IS_EVENT_RECEIVED(ctx, QW_EVENT_READY)) { + output->needRsp = true; + + QW_SET_EVENT_PROCESSED(ctx, QW_EVENT_READY); + + output->rspCode = input.code; + } + + if (!output->needStop) { + QW_ERR_JRET(qwUpdateTaskStatus(QW_FPARAMS(), input.status)); + } + break; + } + case QW_PHASE_PRE_FETCH: { + QW_ERR_JRET(qwAddAcquireTaskCtx(QW_FPARAMS(), QW_READ, &ctx)); + + QW_LOCK(QW_WRITE, &ctx->lock); + + locked = true; + + if (QW_IS_EVENT_PROCESSED(ctx, QW_EVENT_CANCEL)) { + QW_TASK_WLOG("task already cancelled", NULL); + output->needStop = true; + output->rspCode = TSDB_CODE_QRY_TASK_CANCELLED; + QW_ERR_JRET(TSDB_CODE_QRY_TASK_CANCELLED); + } + + if (QW_IS_EVENT_RECEIVED(ctx, QW_EVENT_DROP)) { + QW_TASK_WLOG("task is dropping", NULL); + output->needStop = true; + output->rspCode = TSDB_CODE_QRY_TASK_DROPPING; + } else if (QW_IS_EVENT_RECEIVED(ctx, QW_EVENT_CANCEL)) { + QW_TASK_WLOG("task is cancelling", NULL); + output->needStop = true; + output->rspCode = TSDB_CODE_QRY_TASK_CANCELLING; + } + + if (QW_IS_EVENT_RECEIVED(ctx, QW_EVENT_FETCH)) { + QW_TASK_WLOG("last fetch not finished", NULL); + output->needStop = true; + output->rspCode = TSDB_CODE_QRY_DUPLICATTED_OPERATION; + QW_ERR_JRET(TSDB_CODE_QRY_DUPLICATTED_OPERATION); + } + + if (!QW_IS_EVENT_PROCESSED(ctx, QW_EVENT_READY)) { + QW_TASK_ELOG("query rsp are not ready", NULL); + output->needStop = true; + output->rspCode = TSDB_CODE_QRY_TASK_MSG_ERROR; + QW_ERR_JRET(TSDB_CODE_QRY_TASK_MSG_ERROR); + } + break; + } + } + _return: - if (task) { - QW_UNLOCK(QW_WRITE, &task->lock); + if (locked) { + ctx->phase = phase; - qwReleaseTask(QW_READ, sch); + QW_UNLOCK(QW_WRITE, &ctx->lock); } - if (sch) { - qwReleaseScheduler(QW_READ, mgmt); + if (ctx) { + qwReleaseTaskCtx(QW_READ, mgmt); } QW_RET(code); } -int32_t qwBuildAndSendQueryRsp(SRpcMsg *pMsg, int32_t code) { - SQueryTableRsp *pRsp = (SQueryTableRsp *)rpcMallocCont(sizeof(SQueryTableRsp)); - pRsp->code = code; - SRpcMsg rpcRsp = { - .handle = pMsg->handle, - .ahandle = pMsg->ahandle, - .pCont = pRsp, - .contLen = sizeof(*pRsp), - .code = code, - }; - - rpcSendResponse(&rpcRsp); - - return TSDB_CODE_SUCCESS; -} - -int32_t qwBuildAndSendReadyRsp(SRpcMsg *pMsg, int32_t code) { - SResReadyRsp *pRsp = (SResReadyRsp *)rpcMallocCont(sizeof(SResReadyRsp)); - pRsp->code = code; - - SRpcMsg rpcRsp = { - .handle = pMsg->handle, - .ahandle = pMsg->ahandle, - .pCont = pRsp, - .contLen = sizeof(*pRsp), - .code = code, - }; - - rpcSendResponse(&rpcRsp); - - return TSDB_CODE_SUCCESS; -} - -int32_t qwBuildAndSendStatusRsp(SRpcMsg *pMsg, SSchedulerStatusRsp *sStatus) { - int32_t size = 0; - - if (sStatus) { - size = sizeof(SSchedulerStatusRsp) + sizeof(sStatus->status[0]) * sStatus->num; - } else { - size = sizeof(SSchedulerStatusRsp); - } - - SSchedulerStatusRsp *pRsp = (SSchedulerStatusRsp *)rpcMallocCont(size); - - if (sStatus) { - memcpy(pRsp, sStatus, size); - } else { - pRsp->num = 0; - } - - SRpcMsg rpcRsp = { - .msgType = pMsg->msgType + 1, - .handle = pMsg->handle, - .ahandle = pMsg->ahandle, - .pCont = pRsp, - .contLen = size, - .code = 0, - }; - - rpcSendResponse(&rpcRsp); - - return TSDB_CODE_SUCCESS; -} - -int32_t qwInitFetchRsp(int32_t length, SRetrieveTableRsp **rsp) { - int32_t msgSize = sizeof(SRetrieveTableRsp) + length; - - SRetrieveTableRsp *pRsp = (SRetrieveTableRsp *)rpcMallocCont(msgSize); - if (NULL == pRsp) { - qError("rpcMallocCont %d failed", msgSize); - QW_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); - } - - memset(pRsp, 0, sizeof(SRetrieveTableRsp)); - - *rsp = pRsp; - - return TSDB_CODE_SUCCESS; -} - - -int32_t qwBuildAndSendFetchRsp(SRpcMsg *pMsg, SRetrieveTableRsp *pRsp, int32_t dataLength, int32_t code) { - if (NULL == pRsp) { - pRsp = (SRetrieveTableRsp *)rpcMallocCont(sizeof(SRetrieveTableRsp)); - memset(pRsp, 0, sizeof(SRetrieveTableRsp)); - dataLength = 0; - } - - SRpcMsg rpcRsp = { - .handle = pMsg->handle, - .ahandle = pMsg->ahandle, - .pCont = pRsp, - .contLen = sizeof(*pRsp) + dataLength, - .code = code, - }; - - rpcSendResponse(&rpcRsp); - - return TSDB_CODE_SUCCESS; -} - -int32_t qwBuildAndSendCancelRsp(SRpcMsg *pMsg, int32_t code) { - STaskCancelRsp *pRsp = (STaskCancelRsp *)rpcMallocCont(sizeof(STaskCancelRsp)); - pRsp->code = code; - - SRpcMsg rpcRsp = { - .handle = pMsg->handle, - .ahandle = pMsg->ahandle, - .pCont = pRsp, - .contLen = sizeof(*pRsp), - .code = code, - }; - - rpcSendResponse(&rpcRsp); - return TSDB_CODE_SUCCESS; -} - -int32_t qwBuildAndSendDropRsp(SRpcMsg *pMsg, int32_t code) { - STaskDropRsp *pRsp = (STaskDropRsp *)rpcMallocCont(sizeof(STaskDropRsp)); - pRsp->code = code; - - SRpcMsg rpcRsp = { - .handle = pMsg->handle, - .ahandle = pMsg->ahandle, - .pCont = pRsp, - .contLen = sizeof(*pRsp), - .code = code, - }; - - rpcSendResponse(&rpcRsp); - return TSDB_CODE_SUCCESS; -} - -int32_t qwBuildAndSendShowRsp(SRpcMsg *pMsg, int32_t code) { - int32_t numOfCols = 6; - int32_t msgSize = sizeof(SVShowTablesRsp) + sizeof(SSchema) * numOfCols; - - SVShowTablesRsp *pRsp = (SVShowTablesRsp *)rpcMallocCont(msgSize); - - int32_t cols = 0; - SSchema *pSchema = pRsp->metaInfo.pSchema; - - const SSchema *s = tGetTbnameColumnSchema(); - *pSchema = createSchema(s->type, htonl(s->bytes), htonl(++cols), "name"); - pSchema++; - - int32_t type = TSDB_DATA_TYPE_TIMESTAMP; - *pSchema = createSchema(type, htonl(tDataTypes[type].bytes), htonl(++cols), "created"); - pSchema++; - - type = TSDB_DATA_TYPE_SMALLINT; - *pSchema = createSchema(type, htonl(tDataTypes[type].bytes), htonl(++cols), "columns"); - pSchema++; - - *pSchema = createSchema(s->type, htonl(s->bytes), htonl(++cols), "stable"); - pSchema++; - - type = TSDB_DATA_TYPE_BIGINT; - *pSchema = createSchema(type, htonl(tDataTypes[type].bytes), htonl(++cols), "uid"); - pSchema++; - - type = TSDB_DATA_TYPE_INT; - *pSchema = createSchema(type, htonl(tDataTypes[type].bytes), htonl(++cols), "vgId"); - - assert(cols == numOfCols); - pRsp->metaInfo.numOfColumns = htonl(cols); - - SRpcMsg rpcMsg = { - .handle = pMsg->handle, - .ahandle = pMsg->ahandle, - .pCont = pRsp, - .contLen = msgSize, - .code = code, - }; - - rpcSendResponse(&rpcMsg); - return TSDB_CODE_SUCCESS; -} - -int32_t qwBuildAndSendShowFetchRsp(SRpcMsg *pMsg, SVShowTablesFetchReq* pFetchReq) { - SVShowTablesFetchRsp *pRsp = (SVShowTablesFetchRsp *)rpcMallocCont(sizeof(SVShowTablesFetchRsp)); - int32_t handle = htonl(pFetchReq->id); - - pRsp->numOfRows = 0; - SRpcMsg rpcMsg = { - .handle = pMsg->handle, - .ahandle = pMsg->ahandle, - .pCont = pRsp, - .contLen = sizeof(*pRsp), - .code = 0, - }; - - rpcSendResponse(&rpcMsg); - return TSDB_CODE_SUCCESS; -} - -int32_t qwCheckAndSendReadyRsp(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SRpcMsg *pMsg) { - SQWSchStatus *sch = NULL; - SQWTaskStatus *task = NULL; +int32_t qwProcessQuery(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SQWMsg *qwMsg) { int32_t code = 0; + bool queryRsped = false; + bool needStop = false; + struct SSubplan *plan = NULL; + int32_t rspCode = 0; + SQWPhaseInput input = {0}; + SQWPhaseOutput output = {0}; - QW_ERR_RET(qwAcquireScheduler(QW_READ, mgmt, sId, &sch)); + QW_ERR_JRET(qwHandleTaskEvent(QW_FPARAMS(), QW_PHASE_PRE_QUERY, &input, &output)); - QW_ERR_JRET(qwAcquireTask(mgmt, QW_READ, sch, qId, tId, &task)); - - QW_LOCK(QW_WRITE, &task->lock); - - if (QW_READY_NOT_RECEIVED == task->ready) { - QW_SCH_TASK_DLOG("ready not received, ready:%d", task->ready); - goto _return; - } else if (QW_READY_RECEIVED == task->ready) { - task->ready = QW_READY_RESPONSED; - int32_t rspCode = task->code; - - QW_UNLOCK(QW_WRITE, &task->lock); - qwReleaseTask(QW_READ, sch); - qwReleaseScheduler(QW_READ, mgmt); - - QW_ERR_RET(qwBuildAndSendReadyRsp(pMsg, rspCode)); - - QW_SCH_TASK_DLOG("ready response sent, ready:%d", task->ready); - - return TSDB_CODE_SUCCESS; - } else if (QW_READY_RESPONSED == task->ready) { - QW_SCH_TASK_ELOG("ready response already send, ready:%d", task->ready); - QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); - } else { - assert(0); - } - -_return: - - if (task) { - QW_UNLOCK(QW_WRITE, &task->lock); - qwReleaseTask(QW_READ, sch); - } - - qwReleaseScheduler(QW_READ, mgmt); - - QW_RET(code); -} - -int32_t qwSetAndSendReadyRsp(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SRpcMsg *pMsg) { - SQWSchStatus *sch = NULL; - SQWTaskStatus *task = NULL; - int32_t code = 0; - - QW_ERR_RET(qwAcquireScheduler(QW_READ, mgmt, sId, &sch)); - - QW_ERR_JRET(qwAcquireTask(mgmt, QW_READ, sch, qId, tId, &task)); - - QW_LOCK(QW_WRITE, &task->lock); - - int8_t status = task->status; - int32_t errCode = task->code; + needStop = output.needStop; + code = output.rspCode; - if (QW_TASK_READY(status)) { - task->ready = QW_READY_RESPONSED; - - QW_UNLOCK(QW_WRITE, &task->lock); - - QW_ERR_JRET(qwBuildAndSendReadyRsp(pMsg, errCode)); - - QW_SCH_TASK_DLOG("task ready responsed, status:%d", status); - } else { - task->ready = QW_READY_RECEIVED; - - QW_UNLOCK(QW_WRITE, &task->lock); - - QW_SCH_TASK_DLOG("task ready NOT responsed, status:%d", status); - } - -_return: - - if (task) { - qwReleaseTask(QW_READ, sch); - } - - qwReleaseScheduler(QW_READ, mgmt); - - QW_RET(code); -} - -int32_t qwCheckAndProcessTaskDrop(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, bool *needStop) { - SQWSchStatus *sch = NULL; - SQWTaskStatus *task = NULL; - int32_t code = 0; - int8_t status = JOB_TASK_STATUS_CANCELLED; - - *needStop = false; - - if (qwAcquireScheduler(QW_READ, mgmt, sId, &sch)) { - return TSDB_CODE_SUCCESS; - } - - if (qwAcquireTask(mgmt, QW_READ, sch, qId, tId, &task)) { - qwReleaseScheduler(QW_READ, mgmt); - return TSDB_CODE_SUCCESS; + if (needStop) { + QW_TASK_DLOG("task need stop", NULL); + QW_ERR_JRET(code); } - if ((!atomic_load_8(&task->cancel)) && (!atomic_load_8(&task->drop))) { - QW_TASK_ELOG("no cancel or drop but task exists, status:%d", atomic_load_8(&task->status)); - QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); - } - - *needStop = true; - - if (atomic_load_8(&task->cancel)) { - QW_LOCK(QW_WRITE, &task->lock); - code = qwUpdateTaskInfo(mgmt, task, QW_TASK_INFO_STATUS, &status, QW_IDS()); - QW_UNLOCK(QW_WRITE, &task->lock); - + code = qStringToSubplan(qwMsg->msg, &plan); + if (TSDB_CODE_SUCCESS != code) { + QW_TASK_ELOG("task string to subplan failed, code:%x", code); QW_ERR_JRET(code); } - if (task->drop) { - qwReleaseTask(QW_READ, sch); - qwReleaseScheduler(QW_READ, mgmt); - - QW_RET(qwDropTask(mgmt, sId, qId, tId)); + qTaskInfo_t pTaskInfo = NULL; + code = qCreateExecTask(node, 0, (struct SSubplan *)plan, &pTaskInfo); + if (code) { + QW_TASK_ELOG("qCreateExecTask failed, code:%x", code); + QW_ERR_JRET(code); } + + QW_ERR_JRET(qwBuildAndSendQueryRsp(pMsg, TSDB_CODE_SUCCESS)); + + queryRsped = true; + + DataSinkHandle sinkHandle = NULL; + code = qExecTask(pTaskInfo, &sinkHandle); + if (code) { + QW_TASK_ELOG("qExecTask failed, code:%x", code); + QW_ERR_JRET(code); + } + + QW_ERR_JRET(qwUpdateTaskCtxHandles(QW_FPARAMS(), pTaskInfo, sinkHandle)); _return: - qwReleaseTask(QW_READ, sch); - qwReleaseScheduler(QW_READ, mgmt); - - return TSDB_CODE_SUCCESS; -} - - -int32_t qwQueryPostProcess(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, int8_t status, int32_t errCode) { - SQWSchStatus *sch = NULL; - SQWTaskStatus *task = NULL; - int32_t code = 0; - int8_t newStatus = JOB_TASK_STATUS_CANCELLED; - - code = qwAcquireAddScheduler(QW_READ, mgmt, sId, &sch); if (code) { - QW_TASK_ELOG("sId:%"PRIx64" not in cache", sId); - QW_ERR_RET(code); - } - - code = qwAcquireTask(mgmt, QW_READ, sch, qId, tId, &task); - if (code) { - QW_TASK_ELOG("sId:%"PRIx64" queryId:%"PRIx64" taskId:%"PRIx64" not in cache", sId, qId, tId); - QW_ERR_RET(code); - } - - QW_LOCK(QW_WRITE, &task->lock); - - if (task->cancel) { - qwUpdateTaskInfo(mgmt, task, QW_TASK_INFO_STATUS, &newStatus, QW_IDS()); - } - - if (task->drop) { - QW_UNLOCK(QW_WRITE, &task->lock); - - qwReleaseTask(QW_READ, sch); - qwReleaseScheduler(QW_READ, mgmt); - - qwDropTask(mgmt, sId, qId, tId); - - return TSDB_CODE_SUCCESS; - } - - if (!(task->cancel || task->drop)) { - qwUpdateTaskInfo(mgmt, task, QW_TASK_INFO_STATUS, &status, QW_IDS()); - task->code = errCode; - } - - QW_UNLOCK(QW_WRITE, &task->lock); - - qwReleaseTask(QW_READ, sch); - qwReleaseScheduler(QW_READ, mgmt); - - return TSDB_CODE_SUCCESS; -} - -int32_t qwScheduleDataSink(SQWTaskCtx *handles, SQWorkerMgmt *mgmt, uint64_t sId, uint64_t queryId, uint64_t taskId, SRpcMsg *pMsg) { - if (atomic_load_8(&handles->sinkScheduled)) { - qDebug("data sink already scheduled"); - return TSDB_CODE_SUCCESS; + rspCode = code; } - SSinkDataReq * req = (SSinkDataReq *)rpcMallocCont(sizeof(SSinkDataReq)); - if (NULL == req) { - qError("rpcMallocCont %d failed", (int32_t)sizeof(SSinkDataReq)); - QW_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + if (!queryRsped) { + code = qwBuildAndSendQueryRsp(qwMsg->connection, rspCode); + if (TSDB_CODE_SUCCESS == rspCode && code) { + rspCode = code; + } } - req->header.vgId = mgmt->nodeId; - req->sId = sId; - req->queryId = queryId; - req->taskId = taskId; - - SRpcMsg pNewMsg = { - .handle = pMsg->handle, - .ahandle = pMsg->ahandle, - .msgType = TDMT_VND_SCHEDULE_DATA_SINK, - .pCont = req, - .contLen = sizeof(SSinkDataReq), - .code = 0, - }; - - int32_t code = (*mgmt->putToQueueFp)(mgmt->nodeObj, &pNewMsg); - if (TSDB_CODE_SUCCESS != code) { - qError("put data sink schedule msg to queue failed, code:%x", code); - rpcFreeCont(req); - QW_ERR_RET(code); + if (needStop) { + QW_RET(rspCode); } - qDebug("put data sink schedule msg to query queue"); - - return TSDB_CODE_SUCCESS; -} - -int32_t qwScheduleQuery(SQWTaskCtx *handles, SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SRpcMsg *pMsg) { - if (atomic_load_8(&handles->queryScheduled)) { - QW_SCH_TASK_ELOG("query already scheduled, queryScheduled:%d", handles->queryScheduled); - return TSDB_CODE_SUCCESS; + input.code = rspCode; + + if (TSDB_CODE_SUCCESS != rspCode) { + input.status = JOB_TASK_STATUS_FAILED; + } else { + input.status = JOB_TASK_STATUS_PARTIAL_SUCCEED; } + + QW_ERR_RET(qwHandleTaskEvent(QW_FPARAMS(), QW_PHASE_POST_QUERY, &input, &output)); - QW_ERR_RET(qwUpdateTaskStatus(mgmt, sId, qId, tId, JOB_TASK_STATUS_EXECUTING)); - - SQueryContinueReq * req = (SQueryContinueReq *)rpcMallocCont(sizeof(SQueryContinueReq)); - if (NULL == req) { - QW_SCH_TASK_ELOG("rpcMallocCont %d failed", (int32_t)sizeof(SQueryContinueReq)); - QW_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + if (queryRsped && output.needRsp) { + qwBuildAndSendReadyRsp(qwMsg->connection, output.rspCode); } - - req->header.vgId = mgmt->nodeId; - req->sId = sId; - req->queryId = qId; - req->taskId = tId; - - SRpcMsg pNewMsg = { - .handle = pMsg->handle, - .ahandle = pMsg->ahandle, - .msgType = TDMT_VND_QUERY_CONTINUE, - .pCont = req, - .contLen = sizeof(SQueryContinueReq), - .code = 0, - }; - - int32_t code = (*mgmt->putToQueueFp)(mgmt->nodeObj, &pNewMsg); - if (TSDB_CODE_SUCCESS != code) { - QW_SCH_TASK_ELOG("put query continue msg to queue failed, code:%x", code); - rpcFreeCont(req); - QW_ERR_RET(code); - } - - handles->queryScheduled = true; - - QW_SCH_TASK_DLOG("put query continue msg to query queue, vgId:%d", mgmt->nodeId); - - return TSDB_CODE_SUCCESS; + + QW_RET(rspCode); } -int32_t qwHandleFetch(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SRpcMsg *pMsg) { - SQWSchStatus *sch = NULL; - SQWTaskStatus *task = NULL; +int32_t qwProcessFetch(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SQWMsg *qwMsg) { int32_t code = 0; int32_t needRsp = true; void *data = NULL; int32_t sinkStatus = 0; - int32_t dataLength = 0; - SRetrieveTableRsp *rsp = NULL; + int32_t dataLen = 0; bool queryEnd = false; - SQWTaskCtx *handles = NULL; + bool needStop = false; + bool locked = false; + SQWTaskCtx *ctx = NULL; int8_t status = 0; + void *rsp = NULL; - QW_ERR_JRET(qwAcquireTaskCtx(QW_READ, mgmt, qId, tId, &handles)); - QW_LOCK(QW_WRITE, &handles->lock); - - if (handles->needRsp) { - QW_UNLOCK(QW_WRITE, &handles->lock); - QW_SCH_TASK_ELOG("last fetch not responsed, needRsp:%d", handles->needRsp); - QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); - } + SQWPhaseInput input = {0}; + SQWPhaseOutput output = {0}; - QW_UNLOCK(QW_WRITE, &handles->lock); - - QW_ERR_JRET(qwAcquireScheduler(QW_READ, mgmt, sId, &sch)); - QW_ERR_JRET(qwAcquireTask(mgmt, QW_READ, sch, qId, tId, &task)); - - if (task->cancel || task->drop) { - QW_SCH_TASK_ELOG("task is already cancelled or dropped, cancel:%d, drop:%d", task->cancel, task->drop); - QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); - } - - if (task->status != JOB_TASK_STATUS_EXECUTING && task->status != JOB_TASK_STATUS_PARTIAL_SUCCEED) { - QW_SCH_TASK_ELOG("invalid status %d for fetch", task->status); - QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); - } - - dsGetDataLength(handles->sinkHandle, &dataLength, &queryEnd); + QW_ERR_JRET(qwHandleTaskEvent(QW_FPARAMS(), QW_PHASE_PRE_FETCH, &input, &output)); - if (dataLength > 0) { - SOutputData output = {0}; - - QW_SCH_TASK_DLOG("task got data in sink, dataLength:%d", dataLength); - - QW_ERR_JRET(qwInitFetchRsp(dataLength, &rsp)); - - output.pData = rsp->data; - - code = dsGetDataBlock(handles->sinkHandle, &output); - if (code) { - qError("dsGetDataBlock failed, code:%x", code); - QW_ERR_JRET(code); - } - - rsp->useconds = htobe64(output.useconds); - rsp->completed = 0; - rsp->precision = output.precision; - rsp->compressed = output.compressed; - rsp->compLen = htonl(dataLength); - rsp->numOfRows = htonl(output.numOfRows); - - if (DS_BUF_EMPTY == output.bufStatus && output.queryEnd) { - rsp->completed = 1; - - status = JOB_TASK_STATUS_SUCCEED; - - QW_SCH_TASK_DLOG("task all fetched, status:%d", status); - QW_ERR_JRET(qwUpdateTaskInfo(mgmt, task, QW_TASK_INFO_STATUS, &status, QW_IDS())); - } - - // Note: schedule data sink firstly and will schedule query after it's done - if (output.needSchedule) { - QW_SCH_TASK_DLOG("sink need schedule, queryEnd:%d", output.queryEnd); - QW_ERR_JRET(qwScheduleDataSink(handles, mgmt, sId, qId, tId, pMsg)); - } else if ((!output.queryEnd) && (DS_BUF_LOW == output.bufStatus || DS_BUF_EMPTY == output.bufStatus)) { - QW_SCH_TASK_DLOG("task not end, need to continue, bufStatus:%d", output.bufStatus); - QW_ERR_JRET(qwScheduleQuery(handles, mgmt, sId, qId, tId, pMsg)); - } - } else { - if (dataLength < 0) { - QW_SCH_TASK_ELOG("invalid length from dsGetDataLength, length:%d", dataLength); - QW_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT); - } - - if (queryEnd) { - status = JOB_TASK_STATUS_SUCCEED; - - QW_SCH_TASK_DLOG("no data in sink and query end, dataLength:%d", dataLength); - - QW_ERR_JRET(qwUpdateTaskInfo(mgmt, task, QW_TASK_INFO_STATUS, &status, QW_IDS())); - } else { - assert(0 == handles->needRsp); - - // MUST IN SCHEDULE OR IN SINK SCHEDULE - - QW_SCH_TASK_DLOG("no res data in sink, need response later, queryEnd:%d", queryEnd); - - QW_LOCK(QW_WRITE, &handles->lock); - handles->needRsp = true; - QW_UNLOCK(QW_WRITE, &handles->lock); - - needRsp = false; - } + needStop = output.needStop; + code = output.rspCode; + + if (needStop) { + QW_TASK_DLOG("task need stop", NULL); + QW_ERR_JRET(code); } + QW_ERR_JRET(qwAcquireTaskCtx(QW_FPARAMS(), QW_READ, &ctx)); + + QW_LOCK(QW_WRITE, &ctx->lock); + + locked = true; + + QW_ERR_JRET(qwGetResFromSink(QW_FPARAMS(), ctx, &dataLen, &rsp)); + _return: - if (task) { - qwReleaseTask(QW_READ, sch); + if (locked) { + QW_UNLOCK(QW_WRITE, &ctx->lock); } - - if (sch) { - qwReleaseScheduler(QW_READ, mgmt); + + if (ctx) { + qwReleaseTaskCtx(QW_READ, mgmt); } if (needRsp) { - qwBuildAndSendFetchRsp(pMsg, rsp, dataLength, code); - } - - if (handles) { - qwReleaseTaskResCache(QW_READ, mgmt); + qwBuildAndSendFetchRsp(pMsg, rsp, dataLen, code); } QW_RET(code); } + +int32_t qwProcessDrop(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SQWMsg *qwMsg) { + int32_t code = 0; + bool needRsp = false; + + QW_ERR_JRET(qwDropTask(QW_FPARAMS(), &needRsp)); + +_return: + + if (TSDB_CODE_SUCCESS != code || needRsp) { + QW_ERR_RET(qwBuildAndSendDropRsp(qwMsg->connection, code)); + } + + return TSDB_CODE_SUCCESS; +} + int32_t qWorkerInit(int8_t nodeType, int32_t nodeId, SQWorkerCfg *cfg, void **qWorkerMgmt, void *nodeObj, putReqToQueryQFp fp) { if (NULL == qWorkerMgmt || NULL == nodeObj || NULL == fp) { qError("invalid param to init qworker"); @@ -1227,324 +880,6 @@ int32_t qWorkerInit(int8_t nodeType, int32_t nodeId, SQWorkerCfg *cfg, void **qW return TSDB_CODE_SUCCESS; } -int32_t qWorkerProcessQueryMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { - if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg) { - QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); - } - - int32_t code = 0; - bool queryRsped = false; - bool needStop = false; - struct SSubplan *plan = NULL; - SSubQueryMsg *msg = pMsg->pCont; - SQWorkerMgmt *mgmt = (SQWorkerMgmt *)qWorkerMgmt; - int32_t rspCode = 0; - - if (NULL == msg || pMsg->contLen <= sizeof(*msg)) { - QW_ELOG("invalid query msg, contLen:%d", pMsg->contLen); - QW_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT); - } - - msg->sId = be64toh(msg->sId); - msg->queryId = be64toh(msg->queryId); - msg->taskId = be64toh(msg->taskId); - msg->contentLen = ntohl(msg->contentLen); - - uint64_t sId = msg->sId; - uint64_t qId = msg->queryId; - uint64_t tId = msg->taskId; - - QW_ERR_JRET(qwCheckAndProcessTaskDrop(qWorkerMgmt, msg->sId, msg->queryId, msg->taskId, &needStop)); - if (needStop) { - QW_TASK_DLOG("task need stop, msgLen:%d", msg->contentLen); - qwBuildAndSendQueryRsp(pMsg, TSDB_CODE_QRY_TASK_CANCELLED); - QW_ERR_RET(TSDB_CODE_QRY_TASK_CANCELLED); - } - - QW_ERR_JRET(qwAddTask(qWorkerMgmt, sId, qId, tId, JOB_TASK_STATUS_EXECUTING)); - - code = qStringToSubplan(msg->msg, &plan); - if (TSDB_CODE_SUCCESS != code) { - QW_TASK_ELOG("string to subplan failed, code:%d", code); - QW_ERR_JRET(code); - } - - qTaskInfo_t pTaskInfo = NULL; - code = qCreateExecTask(node, 0, (struct SSubplan *)plan, &pTaskInfo); - if (code) { - QW_TASK_ELOG("qCreateExecTask failed, code:%x", code); - QW_ERR_JRET(code); - } - - QW_ERR_JRET(qwBuildAndSendQueryRsp(pMsg, TSDB_CODE_SUCCESS)); - - queryRsped = true; - - DataSinkHandle sinkHandle = NULL; - code = qExecTask(pTaskInfo, &sinkHandle); - if (code) { - QW_TASK_ELOG("qExecTask failed, code:%x", code); - QW_ERR_JRET(code); - } - - QW_ERR_JRET(qwAddTaskHandlesToCache(qWorkerMgmt, msg->queryId, msg->taskId, pTaskInfo, sinkHandle)); - -_return: - - if (code) { - rspCode = code; - } - - if (!queryRsped) { - code = qwBuildAndSendQueryRsp(pMsg, rspCode); - if (TSDB_CODE_SUCCESS == rspCode && code) { - rspCode = code; - } - } - - int8_t status = 0; - if (TSDB_CODE_SUCCESS != rspCode) { - status = JOB_TASK_STATUS_FAILED; - } else { - status = JOB_TASK_STATUS_PARTIAL_SUCCEED; - } - - qwQueryPostProcess(qWorkerMgmt, msg->sId, msg->queryId, msg->taskId, status, rspCode); - - if (queryRsped) { - qwCheckAndSendReadyRsp(qWorkerMgmt, msg->sId, msg->queryId, msg->taskId, pMsg); - } - - QW_RET(rspCode); -} - -int32_t qWorkerProcessQueryContinueMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { - int32_t code = 0; - int8_t status = 0; - bool queryDone = false; - SQueryContinueReq *req = (SQueryContinueReq *)pMsg->pCont; - bool needStop = false; - SQWTaskCtx *handles = NULL; - - QW_ERR_JRET(qwAcquireTaskCtx(QW_READ, qWorkerMgmt, req->queryId, req->taskId, &handles)); - QW_LOCK(QW_WRITE, &handles->lock); - - qTaskInfo_t taskHandle = handles->taskHandle; - DataSinkHandle sinkHandle = handles->sinkHandle; - - QW_UNLOCK(QW_WRITE, &handles->lock); - qwReleaseTaskResCache(QW_READ, qWorkerMgmt); - - QW_ERR_JRET(qwCheckAndProcessTaskDrop(qWorkerMgmt, req->sId, req->queryId, req->taskId, &needStop)); - if (needStop) { - qWarn("task need stop"); - - QW_ERR_JRET(qwAcquireTaskCtx(QW_READ, qWorkerMgmt, req->queryId, req->taskId, &handles)); - QW_LOCK(QW_WRITE, &handles->lock); - if (handles->needRsp) { - qwBuildAndSendQueryRsp(pMsg, TSDB_CODE_QRY_TASK_CANCELLED); - handles->needRsp = false; - } - QW_UNLOCK(QW_WRITE, &handles->lock); - qwReleaseTaskResCache(QW_READ, qWorkerMgmt); - - QW_ERR_RET(TSDB_CODE_QRY_TASK_CANCELLED); - } - - DataSinkHandle newHandle = NULL; - code = qExecTask(taskHandle, &newHandle); - if (code) { - qError("qExecTask failed, code:%x", code); - QW_ERR_JRET(code); - } - - if (sinkHandle != newHandle) { - qError("data sink mis-match"); - QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); - } - -_return: - - QW_ERR_JRET(qwAcquireTaskCtx(QW_READ, qWorkerMgmt, req->queryId, req->taskId, &handles)); - QW_LOCK(QW_WRITE, &handles->lock); - - if (handles->needRsp) { - code = qwBuildAndSendQueryRsp(pMsg, code); - handles->needRsp = false; - } - handles->queryScheduled = false; - - QW_UNLOCK(QW_WRITE, &handles->lock); - qwReleaseTaskResCache(QW_READ, qWorkerMgmt); - - if (TSDB_CODE_SUCCESS != code) { - status = JOB_TASK_STATUS_FAILED; - } else { - status = JOB_TASK_STATUS_PARTIAL_SUCCEED; - } - - code = qwQueryPostProcess(qWorkerMgmt, req->sId, req->queryId, req->taskId, status, code); - - QW_RET(code); -} - - - -int32_t qWorkerProcessDataSinkMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg){ - if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg) { - return TSDB_CODE_QRY_INVALID_INPUT; - } - - SSinkDataReq *msg = pMsg->pCont; - if (NULL == msg || pMsg->contLen < sizeof(*msg)) { - qError("invalid sink data msg"); - QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); - } - - //dsScheduleProcess(); - //TODO - - return TSDB_CODE_SUCCESS; -} - -int32_t qWorkerProcessReadyMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg){ - if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg) { - return TSDB_CODE_QRY_INVALID_INPUT; - } - - SResReadyReq *msg = pMsg->pCont; - if (NULL == msg || pMsg->contLen < sizeof(*msg)) { - qError("invalid task status msg"); - QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); - } - - msg->sId = htobe64(msg->sId); - msg->queryId = htobe64(msg->queryId); - msg->taskId = htobe64(msg->taskId); - - QW_ERR_RET(qwSetAndSendReadyRsp(qWorkerMgmt, msg->sId, msg->queryId, msg->taskId, pMsg)); - - return TSDB_CODE_SUCCESS; -} - -int32_t qWorkerProcessStatusMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { - if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg) { - return TSDB_CODE_QRY_INVALID_INPUT; - } - - int32_t code = 0; - SSchTasksStatusReq *msg = pMsg->pCont; - if (NULL == msg || pMsg->contLen < sizeof(*msg)) { - qError("invalid task status msg"); - QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); - } - - msg->sId = htobe64(msg->sId); - - SSchedulerStatusRsp *sStatus = NULL; - - QW_ERR_JRET(qwGetSchTasksStatus(qWorkerMgmt, msg->sId, &sStatus)); - -_return: - - QW_ERR_RET(qwBuildAndSendStatusRsp(pMsg, sStatus)); - - return TSDB_CODE_SUCCESS; -} - -int32_t qWorkerProcessFetchMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { - if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg) { - return TSDB_CODE_QRY_INVALID_INPUT; - } - - SResFetchReq *msg = pMsg->pCont; - if (NULL == msg || pMsg->contLen < sizeof(*msg)) { - QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); - } - - msg->sId = htobe64(msg->sId); - msg->queryId = htobe64(msg->queryId); - msg->taskId = htobe64(msg->taskId); - - QW_ERR_RET(qwUpdateSchLastAccess(qWorkerMgmt, msg->sId)); - - void *data = NULL; - int32_t code = 0; - - QW_ERR_RET(qwHandleFetch(qWorkerMgmt, msg->sId, msg->queryId, msg->taskId, pMsg)); - - QW_RET(code); -} - -int32_t qWorkerProcessCancelMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { - if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg) { - return TSDB_CODE_QRY_INVALID_INPUT; - } - - int32_t code = 0; - STaskCancelReq *msg = pMsg->pCont; - if (NULL == msg || pMsg->contLen < sizeof(*msg)) { - qError("invalid task cancel msg"); - QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); - } - - msg->sId = htobe64(msg->sId); - msg->queryId = htobe64(msg->queryId); - msg->taskId = htobe64(msg->taskId); - - QW_ERR_JRET(qwCancelTask(qWorkerMgmt, msg->sId, msg->queryId, msg->taskId)); - -_return: - - QW_ERR_RET(qwBuildAndSendCancelRsp(pMsg, code)); - - return TSDB_CODE_SUCCESS; -} - -int32_t qWorkerProcessDropMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { - if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg) { - return TSDB_CODE_QRY_INVALID_INPUT; - } - - int32_t code = 0; - STaskDropReq *msg = pMsg->pCont; - if (NULL == msg || pMsg->contLen < sizeof(*msg)) { - qError("invalid task drop msg"); - QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); - } - - msg->sId = htobe64(msg->sId); - msg->queryId = htobe64(msg->queryId); - msg->taskId = htobe64(msg->taskId); - - QW_ERR_JRET(qwCancelDropTask(qWorkerMgmt, msg->sId, msg->queryId, msg->taskId)); - -_return: - - QW_ERR_RET(qwBuildAndSendDropRsp(pMsg, code)); - - return TSDB_CODE_SUCCESS; -} - -int32_t qWorkerProcessShowMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { - if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg) { - return TSDB_CODE_QRY_INVALID_INPUT; - } - - int32_t code = 0; - SVShowTablesReq *pReq = pMsg->pCont; - QW_ERR_RET(qwBuildAndSendShowRsp(pMsg, code)); -} - -int32_t qWorkerProcessShowFetchMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { - if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg) { - return TSDB_CODE_QRY_INVALID_INPUT; - } - - SVShowTablesFetchReq *pFetchReq = pMsg->pCont; - QW_ERR_RET(qwBuildAndSendShowFetchRsp(pMsg, pFetchReq)); -} - void qWorkerDestroy(void **qWorkerMgmt) { if (NULL == qWorkerMgmt || NULL == *qWorkerMgmt) { return; @@ -1560,3 +895,245 @@ void qWorkerDestroy(void **qWorkerMgmt) { } +#if 0 +#endif + + + + + + + + + + + + + +int32_t qwScheduleDataSink(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SQWTaskCtx *ctx, SRpcMsg *pMsg) { + if (atomic_load_8(&handles->sinkScheduled)) { + qDebug("data sink already scheduled"); + return TSDB_CODE_SUCCESS; + } + + SSinkDataReq * req = (SSinkDataReq *)rpcMallocCont(sizeof(SSinkDataReq)); + if (NULL == req) { + qError("rpcMallocCont %d failed", (int32_t)sizeof(SSinkDataReq)); + QW_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + req->header.vgId = mgmt->nodeId; + req->sId = sId; + req->queryId = queryId; + req->taskId = taskId; + + SRpcMsg pNewMsg = { + .handle = pMsg->handle, + .ahandle = pMsg->ahandle, + .msgType = TDMT_VND_SCHEDULE_DATA_SINK, + .pCont = req, + .contLen = sizeof(SSinkDataReq), + .code = 0, + }; + + int32_t code = (*mgmt->putToQueueFp)(mgmt->nodeObj, &pNewMsg); + if (TSDB_CODE_SUCCESS != code) { + qError("put data sink schedule msg to queue failed, code:%x", code); + rpcFreeCont(req); + QW_ERR_RET(code); + } + + qDebug("put data sink schedule msg to query queue"); + + return TSDB_CODE_SUCCESS; +} + + + +int32_t qwGetSchTasksStatus(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SSchedulerStatusRsp **rsp) { + SQWSchStatus *sch = NULL; + int32_t taskNum = 0; + + QW_ERR_RET(qwAcquireScheduler(QW_READ, mgmt, sId, &sch)); + + sch->lastAccessTs = taosGetTimestampSec(); + + QW_LOCK(QW_READ, &sch->tasksLock); + + taskNum = taosHashGetSize(sch->tasksHash); + + int32_t size = sizeof(SSchedulerStatusRsp) + sizeof((*rsp)->status[0]) * taskNum; + *rsp = calloc(1, size); + if (NULL == *rsp) { + qError("calloc %d failed", size); + QW_UNLOCK(QW_READ, &sch->tasksLock); + qwReleaseScheduler(QW_READ, mgmt); + + return TSDB_CODE_QRY_OUT_OF_MEMORY; + } + + void *key = NULL; + size_t keyLen = 0; + int32_t i = 0; + + void *pIter = taosHashIterate(sch->tasksHash, NULL); + while (pIter) { + SQWTaskStatus *taskStatus = (SQWTaskStatus *)pIter; + taosHashGetKey(pIter, &key, &keyLen); + + QW_GET_QTID(key, (*rsp)->status[i].queryId, (*rsp)->status[i].taskId); + (*rsp)->status[i].status = taskStatus->status; + + pIter = taosHashIterate(sch->tasksHash, pIter); + } + + QW_UNLOCK(QW_READ, &sch->tasksLock); + qwReleaseScheduler(QW_READ, mgmt); + + (*rsp)->num = taskNum; + + return TSDB_CODE_SUCCESS; +} + + + +int32_t qwUpdateSchLastAccess(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId) { + SQWSchStatus *sch = NULL; + + QW_ERR_RET(qwAcquireScheduler(QW_READ, mgmt, sId, &sch)); + + sch->lastAccessTs = taosGetTimestampSec(); + + qwReleaseScheduler(QW_READ, mgmt); + + return TSDB_CODE_SUCCESS; +} + + +int32_t qwGetTaskStatus(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, int8_t *taskStatus) { + SQWSchStatus *sch = NULL; + SQWTaskStatus *task = NULL; + int32_t code = 0; + + if (qwAcquireScheduler(QW_READ, mgmt, sId, &sch)) { + *taskStatus = JOB_TASK_STATUS_NULL; + return TSDB_CODE_SUCCESS; + } + + if (qwAcquireTask(mgmt, QW_READ, sch, queryId, taskId, &task)) { + qwReleaseScheduler(QW_READ, mgmt); + + *taskStatus = JOB_TASK_STATUS_NULL; + return TSDB_CODE_SUCCESS; + } + + *taskStatus = task->status; + + qwReleaseTask(QW_READ, sch); + qwReleaseScheduler(QW_READ, mgmt); + + QW_RET(code); +} + + +int32_t qwCancelTask(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId) { + SQWSchStatus *sch = NULL; + SQWTaskStatus *task = NULL; + int32_t code = 0; + + QW_ERR_RET(qwAcquireAddScheduler(QW_READ, mgmt, sId, &sch)); + + QW_ERR_JRET(qwAcquireAddTask(mgmt, QW_READ, sch, qId, tId, JOB_TASK_STATUS_NOT_START, &task)); + + + QW_LOCK(QW_WRITE, &task->lock); + + task->cancel = true; + + int8_t oriStatus = task->status; + int8_t newStatus = 0; + + if (task->status == JOB_TASK_STATUS_CANCELLED || task->status == JOB_TASK_STATUS_NOT_START || task->status == JOB_TASK_STATUS_CANCELLING || task->status == JOB_TASK_STATUS_DROPPING) { + QW_UNLOCK(QW_WRITE, &task->lock); + + qwReleaseTask(QW_READ, sch); + qwReleaseScheduler(QW_READ, mgmt); + + return TSDB_CODE_SUCCESS; + } else if (task->status == JOB_TASK_STATUS_FAILED || task->status == JOB_TASK_STATUS_SUCCEED || task->status == JOB_TASK_STATUS_PARTIAL_SUCCEED) { + QW_ERR_JRET(qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_CANCELLED)); + } else { + QW_ERR_JRET(qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_CANCELLING)); + } + + QW_UNLOCK(QW_WRITE, &task->lock); + + qwReleaseTask(QW_READ, sch); + qwReleaseScheduler(QW_READ, mgmt); + + if (oriStatus == JOB_TASK_STATUS_EXECUTING) { + //TODO call executer to cancel subquery async + } + + return TSDB_CODE_SUCCESS; + +_return: + + if (task) { + QW_UNLOCK(QW_WRITE, &task->lock); + + qwReleaseTask(QW_READ, sch); + } + + if (sch) { + qwReleaseScheduler(QW_READ, mgmt); + } + + QW_RET(code); +} + + +int32_t qwScheduleQuery(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SQWTaskCtx *handles, SRpcMsg *pMsg) { + if (atomic_load_8(&handles->queryScheduled)) { + QW_SCH_TASK_ELOG("query already scheduled, queryScheduled:%d", handles->queryScheduled); + return TSDB_CODE_SUCCESS; + } + + QW_ERR_RET(qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_EXECUTING)); + + SQueryContinueReq * req = (SQueryContinueReq *)rpcMallocCont(sizeof(SQueryContinueReq)); + if (NULL == req) { + QW_SCH_TASK_ELOG("rpcMallocCont %d failed", (int32_t)sizeof(SQueryContinueReq)); + QW_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + req->header.vgId = mgmt->nodeId; + req->sId = sId; + req->queryId = qId; + req->taskId = tId; + + SRpcMsg pNewMsg = { + .handle = pMsg->handle, + .ahandle = pMsg->ahandle, + .msgType = TDMT_VND_QUERY_CONTINUE, + .pCont = req, + .contLen = sizeof(SQueryContinueReq), + .code = 0, + }; + + int32_t code = (*mgmt->putToQueueFp)(mgmt->nodeObj, &pNewMsg); + if (TSDB_CODE_SUCCESS != code) { + QW_SCH_TASK_ELOG("put query continue msg to queue failed, code:%x", code); + rpcFreeCont(req); + QW_ERR_RET(code); + } + + handles->queryScheduled = true; + + QW_SCH_TASK_DLOG("put query continue msg to query queue, vgId:%d", mgmt->nodeId); + + return TSDB_CODE_SUCCESS; +} + + + diff --git a/source/libs/qworker/src/qworkerMsg.c b/source/libs/qworker/src/qworkerMsg.c new file mode 100644 index 0000000000..5e58827238 --- /dev/null +++ b/source/libs/qworker/src/qworkerMsg.c @@ -0,0 +1,605 @@ +#include "qworker.h" +#include +#include "executor.h" +#include "planner.h" +#include "query.h" +#include "qworkerInt.h" +#include "tmsg.h" +#include "tname.h" +#include "dataSinkMgt.h" + + +int32_t qwMallocFetchRsp(int32_t length, SRetrieveTableRsp **rsp) { + int32_t msgSize = sizeof(SRetrieveTableRsp) + length; + + SRetrieveTableRsp *pRsp = (SRetrieveTableRsp *)rpcMallocCont(msgSize); + if (NULL == pRsp) { + qError("rpcMallocCont %d failed", msgSize); + QW_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + memset(pRsp, 0, sizeof(SRetrieveTableRsp)); + + *rsp = pRsp; + + return TSDB_CODE_SUCCESS; +} + +void qwBuildFetchRsp(SRetrieveTableRsp *rsp, SOutputData *input, int32_t len) { + rsp->useconds = htobe64(input->useconds); + rsp->completed = input->queryEnd; + rsp->precision = input->precision; + rsp->compressed = input->compressed; + rsp->compLen = htonl(len); + rsp->numOfRows = htonl(input->numOfRows); +} + + +void qwFreeFetchRsp(void *msg) { + rpcFreeCont(msg); +} + +int32_t qwBuildAndSendQueryRsp(void *connection, int32_t code) { + SRpcMsg *pMsg = (SRpcMsg *)connection; + SQueryTableRsp *pRsp = (SQueryTableRsp *)rpcMallocCont(sizeof(SQueryTableRsp)); + pRsp->code = code; + + SRpcMsg rpcRsp = { + .handle = pMsg->handle, + .ahandle = pMsg->ahandle, + .pCont = pRsp, + .contLen = sizeof(*pRsp), + .code = code, + }; + + rpcSendResponse(&rpcRsp); + + return TSDB_CODE_SUCCESS; +} + +int32_t qwBuildAndSendReadyRsp(void *connection, int32_t code) { + SRpcMsg *pMsg = (SRpcMsg *)connection; + SResReadyRsp *pRsp = (SResReadyRsp *)rpcMallocCont(sizeof(SResReadyRsp)); + pRsp->code = code; + + SRpcMsg rpcRsp = { + .handle = pMsg->handle, + .ahandle = pMsg->ahandle, + .pCont = pRsp, + .contLen = sizeof(*pRsp), + .code = code, + }; + + rpcSendResponse(&rpcRsp); + + return TSDB_CODE_SUCCESS; +} + +int32_t qwBuildAndSendStatusRsp(SRpcMsg *pMsg, SSchedulerStatusRsp *sStatus) { + int32_t size = 0; + + if (sStatus) { + size = sizeof(SSchedulerStatusRsp) + sizeof(sStatus->status[0]) * sStatus->num; + } else { + size = sizeof(SSchedulerStatusRsp); + } + + SSchedulerStatusRsp *pRsp = (SSchedulerStatusRsp *)rpcMallocCont(size); + + if (sStatus) { + memcpy(pRsp, sStatus, size); + } else { + pRsp->num = 0; + } + + SRpcMsg rpcRsp = { + .msgType = pMsg->msgType + 1, + .handle = pMsg->handle, + .ahandle = pMsg->ahandle, + .pCont = pRsp, + .contLen = size, + .code = 0, + }; + + rpcSendResponse(&rpcRsp); + + return TSDB_CODE_SUCCESS; +} + +int32_t qwBuildAndSendFetchRsp(SRpcMsg *pMsg, SRetrieveTableRsp *pRsp, int32_t dataLength, int32_t code) { + if (NULL == pRsp) { + pRsp = (SRetrieveTableRsp *)rpcMallocCont(sizeof(SRetrieveTableRsp)); + memset(pRsp, 0, sizeof(SRetrieveTableRsp)); + dataLength = 0; + } + + SRpcMsg rpcRsp = { + .handle = pMsg->handle, + .ahandle = pMsg->ahandle, + .pCont = pRsp, + .contLen = sizeof(*pRsp) + dataLength, + .code = code, + }; + + rpcSendResponse(&rpcRsp); + + return TSDB_CODE_SUCCESS; +} + +int32_t qwBuildAndSendCancelRsp(SRpcMsg *pMsg, int32_t code) { + STaskCancelRsp *pRsp = (STaskCancelRsp *)rpcMallocCont(sizeof(STaskCancelRsp)); + pRsp->code = code; + + SRpcMsg rpcRsp = { + .handle = pMsg->handle, + .ahandle = pMsg->ahandle, + .pCont = pRsp, + .contLen = sizeof(*pRsp), + .code = code, + }; + + rpcSendResponse(&rpcRsp); + return TSDB_CODE_SUCCESS; +} + +int32_t qwBuildAndSendDropRsp(void *connection, int32_t code) { + SRpcMsg *pMsg = (SRpcMsg *)connection; + STaskDropRsp *pRsp = (STaskDropRsp *)rpcMallocCont(sizeof(STaskDropRsp)); + pRsp->code = code; + + SRpcMsg rpcRsp = { + .handle = pMsg->handle, + .ahandle = pMsg->ahandle, + .pCont = pRsp, + .contLen = sizeof(*pRsp), + .code = code, + }; + + rpcSendResponse(&rpcRsp); + return TSDB_CODE_SUCCESS; +} + +int32_t qwBuildAndSendShowRsp(SRpcMsg *pMsg, int32_t code) { + int32_t numOfCols = 6; + int32_t msgSize = sizeof(SVShowTablesRsp) + sizeof(SSchema) * numOfCols; + + SVShowTablesRsp *pRsp = (SVShowTablesRsp *)rpcMallocCont(msgSize); + + int32_t cols = 0; + SSchema *pSchema = pRsp->metaInfo.pSchema; + + const SSchema *s = tGetTbnameColumnSchema(); + *pSchema = createSchema(s->type, htonl(s->bytes), htonl(++cols), "name"); + pSchema++; + + int32_t type = TSDB_DATA_TYPE_TIMESTAMP; + *pSchema = createSchema(type, htonl(tDataTypes[type].bytes), htonl(++cols), "created"); + pSchema++; + + type = TSDB_DATA_TYPE_SMALLINT; + *pSchema = createSchema(type, htonl(tDataTypes[type].bytes), htonl(++cols), "columns"); + pSchema++; + + *pSchema = createSchema(s->type, htonl(s->bytes), htonl(++cols), "stable"); + pSchema++; + + type = TSDB_DATA_TYPE_BIGINT; + *pSchema = createSchema(type, htonl(tDataTypes[type].bytes), htonl(++cols), "uid"); + pSchema++; + + type = TSDB_DATA_TYPE_INT; + *pSchema = createSchema(type, htonl(tDataTypes[type].bytes), htonl(++cols), "vgId"); + + assert(cols == numOfCols); + pRsp->metaInfo.numOfColumns = htonl(cols); + + SRpcMsg rpcMsg = { + .handle = pMsg->handle, + .ahandle = pMsg->ahandle, + .pCont = pRsp, + .contLen = msgSize, + .code = code, + }; + + rpcSendResponse(&rpcMsg); + return TSDB_CODE_SUCCESS; +} + +int32_t qwBuildAndSendShowFetchRsp(SRpcMsg *pMsg, SVShowTablesFetchReq* pFetchReq) { + SVShowTablesFetchRsp *pRsp = (SVShowTablesFetchRsp *)rpcMallocCont(sizeof(SVShowTablesFetchRsp)); + int32_t handle = htonl(pFetchReq->id); + + pRsp->numOfRows = 0; + SRpcMsg rpcMsg = { + .handle = pMsg->handle, + .ahandle = pMsg->ahandle, + .pCont = pRsp, + .contLen = sizeof(*pRsp), + .code = 0, + }; + + rpcSendResponse(&rpcMsg); + return TSDB_CODE_SUCCESS; +} + +int32_t qwSetAndSendReadyRsp(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SRpcMsg *pMsg) { + SQWSchStatus *sch = NULL; + SQWTaskStatus *task = NULL; + int32_t code = 0; + + QW_ERR_RET(qwAcquireScheduler(QW_READ, mgmt, sId, &sch)); + + QW_ERR_JRET(qwAcquireTask(mgmt, QW_READ, sch, qId, tId, &task)); + + QW_LOCK(QW_WRITE, &task->lock); + + int8_t status = task->status; + int32_t errCode = task->code; + + if (QW_TASK_READY(status)) { + task->ready = QW_READY_RESPONSED; + + QW_UNLOCK(QW_WRITE, &task->lock); + + QW_ERR_JRET(qwBuildAndSendReadyRsp(pMsg, errCode)); + + QW_SCH_TASK_DLOG("task ready responsed, status:%d", status); + } else { + task->ready = QW_READY_RECEIVED; + + QW_UNLOCK(QW_WRITE, &task->lock); + + QW_SCH_TASK_DLOG("task ready NOT responsed, status:%d", status); + } + +_return: + + if (task) { + qwReleaseTask(QW_READ, sch); + } + + qwReleaseScheduler(QW_READ, mgmt); + + QW_RET(code); +} + + +int32_t qwScheduleDataSink(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SQWTaskCtx *handles, SRpcMsg *pMsg) { + if (atomic_load_8(&handles->sinkScheduled)) { + qDebug("data sink already scheduled"); + return TSDB_CODE_SUCCESS; + } + + SSinkDataReq * req = (SSinkDataReq *)rpcMallocCont(sizeof(SSinkDataReq)); + if (NULL == req) { + qError("rpcMallocCont %d failed", (int32_t)sizeof(SSinkDataReq)); + QW_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + req->header.vgId = mgmt->nodeId; + req->sId = sId; + req->queryId = queryId; + req->taskId = taskId; + + SRpcMsg pNewMsg = { + .handle = pMsg->handle, + .ahandle = pMsg->ahandle, + .msgType = TDMT_VND_SCHEDULE_DATA_SINK, + .pCont = req, + .contLen = sizeof(SSinkDataReq), + .code = 0, + }; + + int32_t code = (*mgmt->putToQueueFp)(mgmt->nodeObj, &pNewMsg); + if (TSDB_CODE_SUCCESS != code) { + qError("put data sink schedule msg to queue failed, code:%x", code); + rpcFreeCont(req); + QW_ERR_RET(code); + } + + qDebug("put data sink schedule msg to query queue"); + + return TSDB_CODE_SUCCESS; +} + +int32_t qwScheduleQuery(SQWorkerMgmt *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, SQWTaskCtx *handles, SRpcMsg *pMsg) { + if (atomic_load_8(&handles->queryScheduled)) { + QW_SCH_TASK_ELOG("query already scheduled, queryScheduled:%d", handles->queryScheduled); + return TSDB_CODE_SUCCESS; + } + + QW_ERR_RET(qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_EXECUTING)); + + SQueryContinueReq * req = (SQueryContinueReq *)rpcMallocCont(sizeof(SQueryContinueReq)); + if (NULL == req) { + QW_SCH_TASK_ELOG("rpcMallocCont %d failed", (int32_t)sizeof(SQueryContinueReq)); + QW_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + req->header.vgId = mgmt->nodeId; + req->sId = sId; + req->queryId = qId; + req->taskId = tId; + + SRpcMsg pNewMsg = { + .handle = pMsg->handle, + .ahandle = pMsg->ahandle, + .msgType = TDMT_VND_QUERY_CONTINUE, + .pCont = req, + .contLen = sizeof(SQueryContinueReq), + .code = 0, + }; + + int32_t code = (*mgmt->putToQueueFp)(mgmt->nodeObj, &pNewMsg); + if (TSDB_CODE_SUCCESS != code) { + QW_SCH_TASK_ELOG("put query continue msg to queue failed, code:%x", code); + rpcFreeCont(req); + QW_ERR_RET(code); + } + + handles->queryScheduled = true; + + QW_SCH_TASK_DLOG("put query continue msg to query queue, vgId:%d", mgmt->nodeId); + + return TSDB_CODE_SUCCESS; +} + +int32_t qWorkerProcessQueryMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { + if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg) { + QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); + } + + int32_t code = 0; + SSubQueryMsg *msg = pMsg->pCont; + SQWorkerMgmt *mgmt = (SQWorkerMgmt *)qWorkerMgmt; + + if (NULL == msg || pMsg->contLen <= sizeof(*msg)) { + QW_ELOG("invalid query msg, contLen:%d", pMsg->contLen); + QW_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT); + } + + msg->sId = be64toh(msg->sId); + msg->queryId = be64toh(msg->queryId); + msg->taskId = be64toh(msg->taskId); + msg->contentLen = ntohl(msg->contentLen); + + uint64_t sId = msg->sId; + uint64_t qId = msg->queryId; + uint64_t tId = msg->taskId; + + SQWMsg qwMsg = {.node = node, .msg = msg->msg, .msgLen = msg->contentLen, .connection = pMsg}; + + QW_RET(qwProcessQuery(QW_FPARAMS(), &qwMsg)); +} + +int32_t qWorkerProcessQueryContinueMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { + int32_t code = 0; + int8_t status = 0; + bool queryDone = false; + SQueryContinueReq *req = (SQueryContinueReq *)pMsg->pCont; + bool needStop = false; + SQWTaskCtx *handles = NULL; + + QW_ERR_JRET(qwAcquireTaskCtx(QW_READ, qWorkerMgmt, req->queryId, req->taskId, &handles)); + QW_LOCK(QW_WRITE, &handles->lock); + + qTaskInfo_t taskHandle = handles->taskHandle; + DataSinkHandle sinkHandle = handles->sinkHandle; + + QW_UNLOCK(QW_WRITE, &handles->lock); + qwReleaseTaskResCache(QW_READ, qWorkerMgmt); + + QW_ERR_JRET(qwCheckAndProcessTaskDrop(qWorkerMgmt, req->sId, req->queryId, req->taskId, &needStop)); + if (needStop) { + qWarn("task need stop"); + + QW_ERR_JRET(qwAcquireTaskCtx(QW_READ, qWorkerMgmt, req->queryId, req->taskId, &handles)); + QW_LOCK(QW_WRITE, &handles->lock); + if (handles->needRsp) { + qwBuildAndSendQueryRsp(pMsg, TSDB_CODE_QRY_TASK_CANCELLED); + handles->needRsp = false; + } + QW_UNLOCK(QW_WRITE, &handles->lock); + qwReleaseTaskResCache(QW_READ, qWorkerMgmt); + + QW_ERR_RET(TSDB_CODE_QRY_TASK_CANCELLED); + } + + DataSinkHandle newHandle = NULL; + code = qExecTask(taskHandle, &newHandle); + if (code) { + qError("qExecTask failed, code:%x", code); + QW_ERR_JRET(code); + } + + if (sinkHandle != newHandle) { + qError("data sink mis-match"); + QW_ERR_JRET(TSDB_CODE_QRY_APP_ERROR); + } + +_return: + + QW_ERR_JRET(qwAcquireTaskCtx(QW_READ, qWorkerMgmt, req->queryId, req->taskId, &handles)); + QW_LOCK(QW_WRITE, &handles->lock); + + if (handles->needRsp) { + code = qwBuildAndSendQueryRsp(pMsg, code); + handles->needRsp = false; + } + handles->queryScheduled = false; + + QW_UNLOCK(QW_WRITE, &handles->lock); + qwReleaseTaskResCache(QW_READ, qWorkerMgmt); + + if (TSDB_CODE_SUCCESS != code) { + status = JOB_TASK_STATUS_FAILED; + } else { + status = JOB_TASK_STATUS_PARTIAL_SUCCEED; + } + + code = qwQueryPostProcess(qWorkerMgmt, req->sId, req->queryId, req->taskId, status, code); + + QW_RET(code); +} + + + +int32_t qWorkerProcessDataSinkMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg){ + if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg) { + return TSDB_CODE_QRY_INVALID_INPUT; + } + + SSinkDataReq *msg = pMsg->pCont; + if (NULL == msg || pMsg->contLen < sizeof(*msg)) { + qError("invalid sink data msg"); + QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); + } + + //dsScheduleProcess(); + //TODO + + return TSDB_CODE_SUCCESS; +} + +int32_t qWorkerProcessReadyMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg){ + if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg) { + return TSDB_CODE_QRY_INVALID_INPUT; + } + + SResReadyReq *msg = pMsg->pCont; + if (NULL == msg || pMsg->contLen < sizeof(*msg)) { + qError("invalid task status msg"); + QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); + } + + msg->sId = htobe64(msg->sId); + msg->queryId = htobe64(msg->queryId); + msg->taskId = htobe64(msg->taskId); + + QW_ERR_RET(qwSetAndSendReadyRsp(qWorkerMgmt, msg->sId, msg->queryId, msg->taskId, pMsg)); + + return TSDB_CODE_SUCCESS; +} + +int32_t qWorkerProcessStatusMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { + if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg) { + return TSDB_CODE_QRY_INVALID_INPUT; + } + + int32_t code = 0; + SSchTasksStatusReq *msg = pMsg->pCont; + if (NULL == msg || pMsg->contLen < sizeof(*msg)) { + qError("invalid task status msg"); + QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); + } + + msg->sId = htobe64(msg->sId); + + SSchedulerStatusRsp *sStatus = NULL; + + QW_ERR_JRET(qwGetSchTasksStatus(qWorkerMgmt, msg->sId, &sStatus)); + +_return: + + QW_ERR_RET(qwBuildAndSendStatusRsp(pMsg, sStatus)); + + return TSDB_CODE_SUCCESS; +} + +int32_t qWorkerProcessFetchMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { + if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg) { + return TSDB_CODE_QRY_INVALID_INPUT; + } + + SResFetchReq *msg = pMsg->pCont; + SQWorkerMgmt *mgmt = (SQWorkerMgmt *)qWorkerMgmt; + + if (NULL == msg || pMsg->contLen < sizeof(*msg)) { + QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); + } + + msg->sId = htobe64(msg->sId); + msg->queryId = htobe64(msg->queryId); + msg->taskId = htobe64(msg->taskId); + + uint64_t sId = msg->sId; + uint64_t qId = msg->queryId; + uint64_t tId = msg->taskId; + + SQWMsg qwMsg = {.node = node, .msg = NULL, .msgLen = 0, .connection = pMsg}; + + QW_RET(qwProcessFetch(QW_FPARAMS(), &qwMsg)); +} + +int32_t qWorkerProcessCancelMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { + if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg) { + return TSDB_CODE_QRY_INVALID_INPUT; + } + + int32_t code = 0; + STaskCancelReq *msg = pMsg->pCont; + if (NULL == msg || pMsg->contLen < sizeof(*msg)) { + qError("invalid task cancel msg"); + QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); + } + + msg->sId = htobe64(msg->sId); + msg->queryId = htobe64(msg->queryId); + msg->taskId = htobe64(msg->taskId); + + QW_ERR_JRET(qwCancelTask(qWorkerMgmt, msg->sId, msg->queryId, msg->taskId)); + +_return: + + QW_ERR_RET(qwBuildAndSendCancelRsp(pMsg, code)); + + return TSDB_CODE_SUCCESS; +} + +int32_t qWorkerProcessDropMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { + if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg) { + return TSDB_CODE_QRY_INVALID_INPUT; + } + + int32_t code = 0; + STaskDropReq *msg = pMsg->pCont; + SQWorkerMgmt *mgmt = (SQWorkerMgmt *)qWorkerMgmt; + + if (NULL == msg || pMsg->contLen < sizeof(*msg)) { + QW_ELOG("invalid task drop msg", NULL); + QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); + } + + msg->sId = htobe64(msg->sId); + msg->queryId = htobe64(msg->queryId); + msg->taskId = htobe64(msg->taskId); + + uint64_t sId = msg->sId; + uint64_t qId = msg->queryId; + uint64_t tId = msg->taskId; + + SQWMsg qwMsg = {.node = node, .msg = NULL, .msgLen = 0, .connection = pMsg}; + + QW_RET(qwProcessDrop(QW_FPARAMS(), &qwMsg)); +} + +int32_t qWorkerProcessShowMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { + if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg) { + return TSDB_CODE_QRY_INVALID_INPUT; + } + + int32_t code = 0; + SVShowTablesReq *pReq = pMsg->pCont; + QW_ERR_RET(qwBuildAndSendShowRsp(pMsg, code)); +} + +int32_t qWorkerProcessShowFetchMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg) { + if (NULL == node || NULL == qWorkerMgmt || NULL == pMsg) { + return TSDB_CODE_QRY_INVALID_INPUT; + } + + SVShowTablesFetchReq *pFetchReq = pMsg->pCont; + QW_ERR_RET(qwBuildAndSendShowFetchRsp(pMsg, pFetchReq)); +} + + diff --git a/source/util/src/terror.c b/source/util/src/terror.c index 8294bca959..5b387ffa46 100644 --- a/source/util/src/terror.c +++ b/source/util/src/terror.c @@ -353,6 +353,14 @@ TAOS_DEFINE_ERROR(TSDB_CODE_QRY_SCH_NOT_EXIST, "Scheduler not exist") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_TASK_NOT_EXIST, "Task not exist") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_TASK_ALREADY_EXIST, "Task already exist") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_RES_CACHE_NOT_EXIST, "Task result cache not exist") +TAOS_DEFINE_ERROR(TSDB_CODE_QRY_TASK_CANCELLED, "Task cancelled") +TAOS_DEFINE_ERROR(TSDB_CODE_QRY_TASK_DROPPED, "Task dropped") +TAOS_DEFINE_ERROR(TSDB_CODE_QRY_TASK_CANCELLING, "Task cancelling") +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") + + // grant TAOS_DEFINE_ERROR(TSDB_CODE_GRANT_EXPIRED, "License expired")