From 89c13efba8d395737e53fd5fc6f67708da56ab41 Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Fri, 11 Nov 2022 17:13:55 +0800 Subject: [PATCH 01/39] fix: fix query thread quit issue --- source/dnode/vnode/src/inc/vnd.h | 1 + source/dnode/vnode/src/vnd/vnodeOpen.c | 5 ++- source/dnode/vnode/src/vnd/vnodeQuery.c | 2 + source/libs/executor/inc/executorimpl.h | 11 ++++++ source/libs/executor/src/executor.c | 52 +++++++++++++++++++++++++ source/libs/executor/src/executorimpl.c | 17 +++++++- source/libs/qworker/src/qwDbg.c | 48 +++++++++++++++++++++-- source/libs/qworker/src/qwUtil.c | 2 + source/libs/qworker/src/qworker.c | 35 +++++++++++++++++ 9 files changed, 168 insertions(+), 5 deletions(-) diff --git a/source/dnode/vnode/src/inc/vnd.h b/source/dnode/vnode/src/inc/vnd.h index 8f8691cfc2..737240d314 100644 --- a/source/dnode/vnode/src/inc/vnd.h +++ b/source/dnode/vnode/src/inc/vnd.h @@ -77,6 +77,7 @@ void vnodeBufPoolReset(SVBufPool* pPool); // vnodeQuery.c int32_t vnodeQueryOpen(SVnode* pVnode); +void vnodeQueryPreClose(SVnode *pVnode); void vnodeQueryClose(SVnode* pVnode); int32_t vnodeGetTableMeta(SVnode* pVnode, SRpcMsg* pMsg, bool direct); int vnodeGetTableCfg(SVnode* pVnode, SRpcMsg* pMsg, bool direct); diff --git a/source/dnode/vnode/src/vnd/vnodeOpen.c b/source/dnode/vnode/src/vnd/vnodeOpen.c index 8c2036b97b..77d375bc45 100644 --- a/source/dnode/vnode/src/vnd/vnodeOpen.c +++ b/source/dnode/vnode/src/vnd/vnodeOpen.c @@ -242,7 +242,10 @@ _err: return NULL; } -void vnodePreClose(SVnode *pVnode) { vnodeSyncPreClose(pVnode); } +void vnodePreClose(SVnode *pVnode) { + vnodeQueryPreClose(pVnode); + vnodeSyncPreClose(pVnode); +} void vnodeClose(SVnode *pVnode) { if (pVnode) { diff --git a/source/dnode/vnode/src/vnd/vnodeQuery.c b/source/dnode/vnode/src/vnd/vnodeQuery.c index efedc12d80..9a4b5bd275 100644 --- a/source/dnode/vnode/src/vnd/vnodeQuery.c +++ b/source/dnode/vnode/src/vnd/vnodeQuery.c @@ -28,6 +28,8 @@ int vnodeQueryOpen(SVnode *pVnode) { return qWorkerInit(NODE_TYPE_VNODE, TD_VID(pVnode), (void **)&pVnode->pQuery, &pVnode->msgCb); } +void vnodeQueryPreClose(SVnode *pVnode) { qworkerStopAllTasks((void *)pVnode->pQuery); } + void vnodeQueryClose(SVnode *pVnode) { qWorkerDestroy((void **)&pVnode->pQuery); } int vnodeGetTableMeta(SVnode *pVnode, SRpcMsg *pMsg, bool direct) { diff --git a/source/libs/executor/inc/executorimpl.h b/source/libs/executor/inc/executorimpl.h index ced668cf37..20d4a5dbae 100644 --- a/source/libs/executor/inc/executorimpl.h +++ b/source/libs/executor/inc/executorimpl.h @@ -153,6 +153,16 @@ typedef struct { SSchemaWrapper* qsw; } SSchemaInfo; +typedef struct { + int32_t operatorType; + int64_t refId; +} SExchangeOpStopInfo; + +typedef struct { + SRWLatch lock; + SArray* pStopInfo; +} STaskStopInfo; + typedef struct SExecTaskInfo { STaskIdInfo id; uint32_t status; @@ -171,6 +181,7 @@ typedef struct SExecTaskInfo { SSubplan* pSubplan; struct SOperatorInfo* pRoot; SLocalFetch localFetch; + STaskStopInfo stopInfo; } SExecTaskInfo; enum { diff --git a/source/libs/executor/src/executor.c b/source/libs/executor/src/executor.c index 1cf01c8661..883d5d6544 100644 --- a/source/libs/executor/src/executor.c +++ b/source/libs/executor/src/executor.c @@ -659,6 +659,54 @@ int32_t qExecTask(qTaskInfo_t tinfo, SSDataBlock** pRes, uint64_t* useconds) { return pTaskInfo->code; } +int32_t qAppendTaskStopInfo(SExecTaskInfo* pTaskInfo, SExchangeOpStopInfo *pInfo) { + taosWLockLatch(&pTaskInfo->stopInfo.lock); + taosArrayPush(pTaskInfo->stopInfo.pStopInfo, pInfo); + taosWUnLockLatch(&pTaskInfo->stopInfo.lock); + + return TSDB_CODE_SUCCESS; +} + +int32_t stopInfoComp(void const* lp, void const* rp) { + SExchangeOpStopInfo* key = (SExchangeOpStopInfo*)lp; + SExchangeOpStopInfo* pInfo = (SExchangeOpStopInfo*)rp; + + if (key->refId < pInfo->refId) { + return -1; + } else if (key->refId > pInfo->refId) { + return 1; + } + + return 0; +} + +void qRemoveTaskStopInfo(SExecTaskInfo* pTaskInfo, SExchangeOpStopInfo *pInfo) { + taosWLockLatch(&pTaskInfo->stopInfo.lock); + int32_t idx = taosArraySearchIdx(pTaskInfo->stopInfo.pStopInfo, pInfo, stopInfoComp, TD_EQ); + if (idx >= 0) { + taosArrayRemove(pTaskInfo->stopInfo.pStopInfo, idx); + } + taosWUnLockLatch(&pTaskInfo->stopInfo.lock); + + return TSDB_CODE_SUCCESS; +} + +void qStopTaskOperators(SExecTaskInfo* pTaskInfo) { + taosWLockLatch(&pTaskInfo->stopInfo.lock); + + int32_t num = taosArrayGetSize(pTaskInfo->stopInfo.pStopInfo); + for (int32_t i = 0; i < num; ++i) { + SExchangeOpStopInfo *pStop = taosArrayGet(pTaskInfo->stopInfo.pStopInfo, i); + SExchangeInfo* pExchangeInfo = taosAcquireRef(exchangeObjRefPool, pStop->refId); + if (pExchangeInfo) { + tsem_post(&pExchangeInfo->ready); + taosReleaseRef(exchangeObjRefPool, pStop->refId); + } + } + + taosWUnLockLatch(&pTaskInfo->stopInfo.lock); +} + int32_t qAsyncKillTask(qTaskInfo_t qinfo) { SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)qinfo; @@ -667,7 +715,11 @@ int32_t qAsyncKillTask(qTaskInfo_t qinfo) { } qDebug("%s execTask async killed", GET_TASKID(pTaskInfo)); + setTaskKilled(pTaskInfo); + + qStopTaskOperators(pTaskInfo); + return TSDB_CODE_SUCCESS; } diff --git a/source/libs/executor/src/executorimpl.c b/source/libs/executor/src/executorimpl.c index 7d662f8784..2dae6f2482 100644 --- a/source/libs/executor/src/executorimpl.c +++ b/source/libs/executor/src/executorimpl.c @@ -1653,7 +1653,7 @@ int32_t appendDownstream(SOperatorInfo* p, SOperatorInfo** pDownstream, int32_t } typedef struct SFetchRspHandleWrapper { - uint32_t exchangeId; + int64_t exchangeId; int32_t sourceIndex; } SFetchRspHandleWrapper; @@ -1873,6 +1873,9 @@ static void concurrentlyLoadRemoteDataImpl(SOperatorInfo* pOperator, SExchangeIn while (1) { tsem_wait(&pExchangeInfo->ready); + if (isTaskKilled(pTaskInfo)) { + longjmp(pTaskInfo->env, TSDB_CODE_TSC_QUERY_CANCELLED); + } for (int32_t i = 0; i < totalSources; ++i) { SSourceDataInfo* pDataInfo = taosArrayGet(pExchangeInfo->pSourceDataInfo, i); @@ -1983,6 +1986,10 @@ static int32_t prepareConcurrentlyLoad(SOperatorInfo* pOperator) { pOperator->cost.openCost = taosGetTimestampUs() - startTs; tsem_wait(&pExchangeInfo->ready); + if (isTaskKilled(pTaskInfo)) { + longjmp(pTaskInfo->env, TSDB_CODE_TSC_QUERY_CANCELLED); + } + tsem_post(&pExchangeInfo->ready); return TSDB_CODE_SUCCESS; } @@ -2002,6 +2009,9 @@ static int32_t seqLoadRemoteData(SOperatorInfo* pOperator) { doSendFetchDataRequest(pExchangeInfo, pTaskInfo, pExchangeInfo->current); tsem_wait(&pExchangeInfo->ready); + if (isTaskKilled(pTaskInfo)) { + longjmp(pTaskInfo->env, TSDB_CODE_TSC_QUERY_CANCELLED); + } SSourceDataInfo* pDataInfo = taosArrayGet(pExchangeInfo->pSourceDataInfo, pExchangeInfo->current); SDownstreamSourceNode* pSource = taosArrayGet(pExchangeInfo->pSources, pExchangeInfo->current); @@ -2217,6 +2227,9 @@ SOperatorInfo* createExchangeOperatorInfo(void* pTransporter, SExchangePhysiNode pInfo->pDummyBlock = createResDataBlock(pExNode->node.pOutputDataBlockDesc); pInfo->pResultBlockList = taosArrayInit(1, POINTER_BYTES); + SExchangeOpStopInfo stopInfo = {QUERY_NODE_PHYSICAL_PLAN_EXCHANGE, pInfo->self}; + qAppendTaskStopInfo(pTaskInfo, &stopInfo); + pInfo->seqLoadData = false; pInfo->pTransporter = pTransporter; @@ -3219,6 +3232,7 @@ static SExecTaskInfo* createExecTaskInfo(uint64_t queryId, uint64_t taskId, EOPT pTaskInfo->id.queryId = queryId; pTaskInfo->execModel = model; pTaskInfo->pTableInfoList = tableListCreate(); + pTaskInfo->stopInfo.pStopInfo = taosArrayInit(4, sizeof(SExchangeOpStopInfo)); char* p = taosMemoryCalloc(1, 128); snprintf(p, 128, "TID:0x%" PRIx64 " QID:0x%" PRIx64, taskId, queryId); @@ -3832,6 +3846,7 @@ void doDestroyTask(SExecTaskInfo* pTaskInfo) { nodesDestroyNode((SNode*)pTaskInfo->pSubplan); } + taosArrayDestroy(pTaskInfo->stopInfo.pStopInfo); taosMemoryFreeClear(pTaskInfo->sql); taosMemoryFreeClear(pTaskInfo->id.str); taosMemoryFreeClear(pTaskInfo); diff --git a/source/libs/qworker/src/qwDbg.c b/source/libs/qworker/src/qwDbg.c index 1871316260..4c4a41df82 100644 --- a/source/libs/qworker/src/qwDbg.c +++ b/source/libs/qworker/src/qwDbg.c @@ -91,11 +91,53 @@ _return: void qwDbgDumpSchInfo(SQWorker *mgmt, SQWSchStatus *sch, int32_t i) { QW_LOCK(QW_READ, &sch->tasksLock); - QW_DLOG("the %dth scheduler status, hbBrokenTs:%" PRId64 ",taskNum:%d", i, sch->hbBrokenTs, - taosHashGetSize(sch->tasksHash)); + int32_t taskNum = taosHashGetSize(sch->tasksHash); + QW_DLOG("***The %dth scheduler status, hbBrokenTs:%" PRId64 ",taskNum:%d", i, sch->hbBrokenTs, taskNum); + + uint64_t qId, tId; + int32_t eId; + SQWTaskStatus *pTask = NULL; + void *pIter = taosHashIterate(sch->tasksHash, NULL); + while (pIter) { + pTask = (SQWTaskStatus *)pIter; + void *key = taosHashGetKey(pIter, NULL); + QW_GET_QTID(key, qId, tId, eId); + + QW_TASK_DLOG("job refId:%" PRIx64 ", code:%x, task status:%d", pTask->refId, pTask->code, pTask->status); + + pIter = taosHashIterate(sch->tasksHash, pIter); + } + QW_UNLOCK(QW_READ, &sch->tasksLock); } +void qwDbgDumpTasksInfo(SQWorker *mgmt) { + QW_DUMP("***Total remain ctx num %d", taosHashGetSize(mgmt->ctxHash)); + + int32_t i = 0; + SQWTaskCtx *ctx = NULL; + uint64_t qId, tId; + int32_t eId; + void *pIter = taosHashIterate(mgmt->ctxHash, NULL); + while (pIter) { + ctx = (SQWTaskCtx *)pIter; + void *key = taosHashGetKey(pIter, NULL); + QW_GET_QTID(key, qId, tId, eId); + + QW_TASK_DLOG("%p lock:%x, phase:%d, type:%d, explain:%d, needFetch:%d, localExec:%d, msgType:%d, fetchType:%d, " + "execId:%x, level:%d, queryGotData:%d, queryRsped:%d, queryEnd:%d, queryContinue:%d, queryInQueue:%d, " + "rspCode:%x, affectedRows:%" PRId64 ", taskHandle:%p, sinkHandle:%p, tbFName:%s, sver:%d, tver:%d, events:%d,%d,%d,%d,%d", + ctx, ctx->lock, ctx->phase, ctx->taskType, ctx->explain, ctx->needFetch, ctx->localExec, ctx->msgType, + ctx->fetchType, ctx->execId, ctx->level, ctx->queryGotData, ctx->queryRsped, ctx->queryEnd, ctx->queryContinue, + ctx->queryInQueue, ctx->rspCode, ctx->affectedRows, ctx->taskHandle, ctx->sinkHandle, ctx->tbInfo.tbFName, + ctx->tbInfo.sversion, ctx->tbInfo.tversion, ctx->events[QW_EVENT_CANCEL], ctx->events[QW_EVENT_READY], + ctx->events[QW_EVENT_FETCH], ctx->events[QW_EVENT_DROP], ctx->events[QW_EVENT_CQUERY]); + + pIter = taosHashIterate(mgmt->ctxHash, pIter); + } + +} + void qwDbgDumpMgmtInfo(SQWorker *mgmt) { if (!gQWDebug.dumpEnable) { return; @@ -120,7 +162,7 @@ void qwDbgDumpMgmtInfo(SQWorker *mgmt) { QW_UNLOCK(QW_READ, &mgmt->schLock); - QW_DUMP("total remain ctx num %d", taosHashGetSize(mgmt->ctxHash)); + qwDbgDumpTasksInfo(mgmt); } int32_t qwDbgBuildAndSendRedirectRsp(int32_t rspType, SRpcHandleInfo *pConn, int32_t code, SEpSet *pEpSet) { diff --git a/source/libs/qworker/src/qwUtil.c b/source/libs/qworker/src/qwUtil.c index e9ded9b269..e13791ae89 100644 --- a/source/libs/qworker/src/qwUtil.c +++ b/source/libs/qworker/src/qwUtil.c @@ -281,9 +281,11 @@ void qwFreeTaskHandle(qTaskInfo_t *taskHandle) { int32_t qwKillTaskHandle(SQWTaskCtx *ctx) { int32_t code = 0; + // Note: free/kill may in RC qTaskInfo_t taskHandle = atomic_load_ptr(&ctx->taskHandle); if (taskHandle && atomic_val_compare_exchange_ptr(&ctx->taskHandle, taskHandle, NULL)) { + qDebug("start to kill task"); code = qAsyncKillTask(taskHandle); atomic_store_ptr(&ctx->taskHandle, taskHandle); } diff --git a/source/libs/qworker/src/qworker.c b/source/libs/qworker/src/qworker.c index a7cd3db824..911a7a4594 100644 --- a/source/libs/qworker/src/qworker.c +++ b/source/libs/qworker/src/qworker.c @@ -1162,6 +1162,41 @@ _return: QW_RET(code); } +void qworkerStopAllTasks(void *qWorkerMgmt) { + SQWorker *mgmt = (SQWorker *)qWorkerMgmt; + + QW_DLOG("start to stop all tasks, taskNum:%d", taosHashGetSize(mgmt->ctxHash)); + + void *pIter = taosHashIterate(mgmt->ctxHash, NULL); + while (pIter) { + SQWTaskCtx *ctx = (SQWTaskCtx *)pIter; + void *key = taosHashGetKey(pIter, NULL); + QW_GET_QTID(key, qId, tId, eId); + + QW_LOCK(QW_WRITE, &ctx->lock); + + QW_TASK_DLOG_E("start to force stop task"); + + if (QW_EVENT_RECEIVED(ctx, QW_EVENT_DROP) || QW_EVENT_PROCESSED(ctx, QW_EVENT_DROP)) { + QW_TASK_WLOG_E("task already dropping"); + QW_UNLOCK(QW_WRITE, &ctx->lock); + + pIter = taosHashIterate(mgmt->ctxHash, pIter); + continue; + } + + if (QW_QUERY_RUNNING(ctx)) { + qwKillTaskHandle(ctx); + } else { + qwDropTask(QW_FPARAMS()); + } + + QW_UNLOCK(QW_WRITE, &ctx->lock); + + pIter = taosHashIterate(mgmt->ctxHash, pIter); + } +} + void qWorkerDestroy(void **qWorkerMgmt) { if (NULL == qWorkerMgmt || NULL == *qWorkerMgmt) { return; From f60441e2ddca794e54b1058349b7c43a8a200a17 Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Fri, 11 Nov 2022 18:44:59 +0800 Subject: [PATCH 02/39] fix: fix query thread quitting issue --- include/libs/qworker/qworker.h | 2 ++ include/util/taoserror.h | 1 + source/dnode/vnode/src/vnd/vnodeQuery.c | 2 +- source/libs/executor/inc/executorimpl.h | 1 + source/libs/executor/src/executor.c | 2 +- source/libs/qworker/inc/qwInt.h | 6 +++--- source/libs/qworker/src/qworker.c | 10 ++++++---- source/util/src/terror.c | 1 + 8 files changed, 16 insertions(+), 9 deletions(-) diff --git a/include/libs/qworker/qworker.h b/include/libs/qworker/qworker.h index 6ddd906700..2be0561ce7 100644 --- a/include/libs/qworker/qworker.h +++ b/include/libs/qworker/qworker.h @@ -94,6 +94,8 @@ int32_t qWorkerProcessHbMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, int64_ int32_t qWorkerProcessDeleteMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, SDeleteRes *pRes); +void qWorkerStopAllTasks(void *qWorkerMgmt); + void qWorkerDestroy(void **qWorkerMgmt); int32_t qWorkerGetStat(SReadHandle *handle, void *qWorkerMgmt, SQWorkerStat *pStat); diff --git a/include/util/taoserror.h b/include/util/taoserror.h index a03dc7d9f9..636decc60b 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -385,6 +385,7 @@ int32_t* taosGetErrno(); #define TSDB_CODE_QRY_JSON_NOT_SUPPORT_ERROR TAOS_DEF_ERROR_CODE(0, 0x072D) #define TSDB_CODE_QRY_JSON_IN_GROUP_ERROR TAOS_DEF_ERROR_CODE(0, 0x072E) #define TSDB_CODE_QRY_JOB_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x072F) +#define TSDB_CODE_QRY_QWORKER_QUIT TAOS_DEF_ERROR_CODE(0, 0x0730) // grant #define TSDB_CODE_GRANT_EXPIRED TAOS_DEF_ERROR_CODE(0, 0x0800) diff --git a/source/dnode/vnode/src/vnd/vnodeQuery.c b/source/dnode/vnode/src/vnd/vnodeQuery.c index 9a4b5bd275..ef0ee6ac0b 100644 --- a/source/dnode/vnode/src/vnd/vnodeQuery.c +++ b/source/dnode/vnode/src/vnd/vnodeQuery.c @@ -28,7 +28,7 @@ int vnodeQueryOpen(SVnode *pVnode) { return qWorkerInit(NODE_TYPE_VNODE, TD_VID(pVnode), (void **)&pVnode->pQuery, &pVnode->msgCb); } -void vnodeQueryPreClose(SVnode *pVnode) { qworkerStopAllTasks((void *)pVnode->pQuery); } +void vnodeQueryPreClose(SVnode *pVnode) { qWorkerStopAllTasks((void *)pVnode->pQuery); } void vnodeQueryClose(SVnode *pVnode) { qWorkerDestroy((void **)&pVnode->pQuery); } diff --git a/source/libs/executor/inc/executorimpl.h b/source/libs/executor/inc/executorimpl.h index 20d4a5dbae..07a63f9f83 100644 --- a/source/libs/executor/inc/executorimpl.h +++ b/source/libs/executor/inc/executorimpl.h @@ -1058,6 +1058,7 @@ int32_t setOutputBuf(SStreamState* pState, STimeWindow* win, SResultRow** pResul int32_t releaseOutputBuf(SStreamState* pState, SWinKey* pKey, SResultRow* pResult); int32_t saveOutputBuf(SStreamState* pState, SWinKey* pKey, SResultRow* pResult, int32_t resSize); void getNextIntervalWindow(SInterval* pInterval, STimeWindow* tw, int32_t order); +int32_t qAppendTaskStopInfo(SExecTaskInfo* pTaskInfo, SExchangeOpStopInfo *pInfo); #ifdef __cplusplus } diff --git a/source/libs/executor/src/executor.c b/source/libs/executor/src/executor.c index 883d5d6544..9b1c0caf36 100644 --- a/source/libs/executor/src/executor.c +++ b/source/libs/executor/src/executor.c @@ -688,7 +688,7 @@ void qRemoveTaskStopInfo(SExecTaskInfo* pTaskInfo, SExchangeOpStopInfo *pInfo) { } taosWUnLockLatch(&pTaskInfo->stopInfo.lock); - return TSDB_CODE_SUCCESS; + return; } void qStopTaskOperators(SExecTaskInfo* pTaskInfo) { diff --git a/source/libs/qworker/inc/qwInt.h b/source/libs/qworker/inc/qwInt.h index 36c6817595..a9eca64675 100644 --- a/source/libs/qworker/inc/qwInt.h +++ b/source/libs/qworker/inc/qwInt.h @@ -246,7 +246,7 @@ typedef struct SQWorkerMgmt { #define QW_ERR_RET(c) \ do { \ - int32_t _code = c; \ + int32_t _code = (c); \ if (_code != TSDB_CODE_SUCCESS) { \ terrno = _code; \ return _code; \ @@ -254,7 +254,7 @@ typedef struct SQWorkerMgmt { } while (0) #define QW_RET(c) \ do { \ - int32_t _code = c; \ + int32_t _code = (c); \ if (_code != TSDB_CODE_SUCCESS) { \ terrno = _code; \ } \ @@ -262,7 +262,7 @@ typedef struct SQWorkerMgmt { } while (0) #define QW_ERR_JRET(c) \ do { \ - code = c; \ + code = (c); \ if (code != TSDB_CODE_SUCCESS) { \ terrno = code; \ goto _return; \ diff --git a/source/libs/qworker/src/qworker.c b/source/libs/qworker/src/qworker.c index 911a7a4594..e45beb7e13 100644 --- a/source/libs/qworker/src/qworker.c +++ b/source/libs/qworker/src/qworker.c @@ -683,6 +683,8 @@ int32_t qwProcessCQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg) { bool queryStop = false; do { + ctx = NULL; + QW_ERR_JRET(qwHandlePrePhaseEvents(QW_FPARAMS(), QW_PHASE_PRE_CQUERY, &input, NULL)); QW_ERR_JRET(qwGetTaskCtx(QW_FPARAMS(), &ctx)); @@ -1162,11 +1164,13 @@ _return: QW_RET(code); } -void qworkerStopAllTasks(void *qWorkerMgmt) { +void qWorkerStopAllTasks(void *qWorkerMgmt) { SQWorker *mgmt = (SQWorker *)qWorkerMgmt; QW_DLOG("start to stop all tasks, taskNum:%d", taosHashGetSize(mgmt->ctxHash)); - + + uint64_t qId, tId; + int32_t eId; void *pIter = taosHashIterate(mgmt->ctxHash, NULL); while (pIter) { SQWTaskCtx *ctx = (SQWTaskCtx *)pIter; @@ -1187,8 +1191,6 @@ void qworkerStopAllTasks(void *qWorkerMgmt) { if (QW_QUERY_RUNNING(ctx)) { qwKillTaskHandle(ctx); - } else { - qwDropTask(QW_FPARAMS()); } QW_UNLOCK(QW_WRITE, &ctx->lock); diff --git a/source/util/src/terror.c b/source/util/src/terror.c index 0e6568d692..c032664ab1 100644 --- a/source/util/src/terror.c +++ b/source/util/src/terror.c @@ -377,6 +377,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_QRY_JSON_IN_ERROR, "Json not support in i TAOS_DEFINE_ERROR(TSDB_CODE_QRY_JSON_NOT_SUPPORT_ERROR, "Json not support in this place") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_JSON_IN_GROUP_ERROR, "Json not support in group/partition by") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_JOB_NOT_EXIST, "Job not exist") +TAOS_DEFINE_ERROR(TSDB_CODE_QRY_QWORKER_QUIT, "Vnode/Qnode is quitting") // grant TAOS_DEFINE_ERROR(TSDB_CODE_GRANT_EXPIRED, "License expired") From a7e197d2cb51358185578017f3fa4f50426bfd14 Mon Sep 17 00:00:00 2001 From: Cary Xu Date: Sun, 13 Nov 2022 01:54:46 +0800 Subject: [PATCH 03/39] fix(query): sum/min/max/avg query of float type from block sma --- source/libs/function/src/builtinsimpl.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 079e553b07..27771d4fc6 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -1187,7 +1187,11 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { } if (!pBuf->assign) { - pBuf->v = *(int64_t*)tval; + if (type == TSDB_DATA_TYPE_FLOAT) { + *(float*)&pBuf->v = GET_DOUBLE_VAL(tval); + } else { + pBuf->v = *(int64_t*)tval; + } if (pCtx->subsidiaries.num > 0) { index = findRowIndex(pInput->startRowIndex, pInput->numOfRows, pCol, tval); if (index >= 0) { From d3e8273bd4bcb6577b10469ab145f16a1f0c2e14 Mon Sep 17 00:00:00 2001 From: Pan YANG Date: Mon, 14 Nov 2022 10:00:38 +0800 Subject: [PATCH 04/39] docs: add historical version download link --- docs/en/28-releases/01-tdengine.md | 7 +++++-- docs/en/28-releases/02-tools.md | 8 ++++++-- docs/zh/28-releases/01-tdengine.md | 4 +++- docs/zh/28-releases/02-tools.md | 4 +++- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/docs/en/28-releases/01-tdengine.md b/docs/en/28-releases/01-tdengine.md index 74eeeb5efb..eee2f94ee1 100644 --- a/docs/en/28-releases/01-tdengine.md +++ b/docs/en/28-releases/01-tdengine.md @@ -1,9 +1,13 @@ --- sidebar_label: TDengine -title: TDengine +title: TDengine Release History and Download Links description: TDengine release history, Release Notes and download links. --- +TDengine 3.x installation packages can be downloaded at the following links: + +For TDengine 2.x installation packages by version, please visit [here](https://www.taosdata.com/all-downloads). + import Release from "/components/ReleaseV3"; ## 3.0.1.6 @@ -33,4 +37,3 @@ import Release from "/components/ReleaseV3"; ## 3.0.1.0 - diff --git a/docs/en/28-releases/02-tools.md b/docs/en/28-releases/02-tools.md index 0a96c776e0..6e8a040f8b 100644 --- a/docs/en/28-releases/02-tools.md +++ b/docs/en/28-releases/02-tools.md @@ -1,9 +1,13 @@ --- -sidebar_label: taosTools -title: taosTools +sidebar_label: taosTools +title: taosTools Release History and Download Links description: taosTools release history, Release Notes, download links. --- +taosTools installation packages can be downloaded at the following links: + +For other historical version installers, please visit [here](https://www.taosdata.com/all-downloads). + import Release from "/components/ReleaseV3"; ## 2.2.7 diff --git a/docs/zh/28-releases/01-tdengine.md b/docs/zh/28-releases/01-tdengine.md index f72735d903..4108212c55 100644 --- a/docs/zh/28-releases/01-tdengine.md +++ b/docs/zh/28-releases/01-tdengine.md @@ -4,7 +4,9 @@ title: TDengine 发布历史及下载链接 description: TDengine 发布历史、Release Notes 及下载链接 --- -各版本 TDengine 安装包下载链接如下: +TDengine 3.x 各版本安装包下载链接如下: + +TDengine 2.x 各版本安装包请访问[这里](https://www.taosdata.com/all-downloads) import Release from "/components/ReleaseV3"; diff --git a/docs/zh/28-releases/02-tools.md b/docs/zh/28-releases/02-tools.md index ac4a884f8b..28e0d4bca9 100644 --- a/docs/zh/28-releases/02-tools.md +++ b/docs/zh/28-releases/02-tools.md @@ -4,7 +4,9 @@ title: taosTools 发布历史及下载链接 description: taosTools 的发布历史、Release Notes 和下载链接 --- -各版本 taosTools 安装包下载链接如下: +taosTools 各版本安装包下载链接如下: + +其他历史版本安装包请访问[这里](https://www.taosdata.com/all-downloads) import Release from "/components/ReleaseV3"; From 49245efff4f0721bdfd51493bde0b9c1a1667c4a Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Mon, 14 Nov 2022 10:35:46 +0800 Subject: [PATCH 05/39] fix: runtime error (division by zero in builtinsimpl.c) --- source/libs/function/src/builtinsimpl.c | 117 +++++++++++++----------- 1 file changed, 62 insertions(+), 55 deletions(-) diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 27771d4fc6..d02d30dc60 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -269,7 +269,7 @@ typedef struct SModeInfo { STuplePos nullTuplePos; bool nullTupleSaved; - char pItems[]; + char pItems[]; } SModeInfo; typedef struct SDerivInfo { @@ -911,7 +911,7 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) { case TSDB_DATA_TYPE_FLOAT: { float* plist = (float*)pCol->pData; -// float val = 0; + // float val = 0; for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) { if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) { continue; @@ -919,9 +919,9 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) { numOfElem += 1; pAvgRes->count += 1; - pAvgRes->sum.dsum += plist[i]; + pAvgRes->sum.dsum += plist[i]; } -// pAvgRes->sum.dsum = val; + // pAvgRes->sum.dsum = val; break; } @@ -3011,7 +3011,7 @@ int32_t firstFunction(SqlFunctionCtx* pCtx) { } } #else - int64_t* pts = (int64_t*) pInput->pPTS->pData; + int64_t* pts = (int64_t*)pInput->pPTS->pData; for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) { if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) { continue; @@ -3115,61 +3115,61 @@ int32_t lastFunction(SqlFunctionCtx* pCtx) { } } #else - if (!pInputCol->hasNull) { - numOfElems = 1; + if (!pInputCol->hasNull) { + numOfElems = 1; - int32_t round = pInput->numOfRows >> 2; - int32_t reminder = pInput->numOfRows & 0x03; + int32_t round = pInput->numOfRows >> 2; + int32_t reminder = pInput->numOfRows & 0x03; - int32_t tick = 0; - for (int32_t i = pInput->startRowIndex; tick < round; i += 4, tick += 1) { - int64_t cts = pts[i]; - int32_t chosen = i; + int32_t tick = 0; + for (int32_t i = pInput->startRowIndex; tick < round; i += 4, tick += 1) { + int64_t cts = pts[i]; + int32_t chosen = i; - if (cts < pts[i + 1]) { - cts = pts[i + 1]; - chosen = i + 1; - } - - if (cts < pts[i + 2]) { - cts = pts[i + 2]; - chosen = i + 2; - } - - if (cts < pts[i + 3]) { - cts = pts[i + 3]; - chosen = i + 3; - } - - if (pResInfo->numOfRes == 0 || pInfo->ts < cts) { - char* data = colDataGetData(pInputCol, chosen); - doSaveCurrentVal(pCtx, i, cts, type, data); - pResInfo->numOfRes = 1; - } + if (cts < pts[i + 1]) { + cts = pts[i + 1]; + chosen = i + 1; } - for (int32_t i = pInput->startRowIndex + round * 4; i < pInput->startRowIndex + pInput->numOfRows; ++i) { - if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) { - char* data = colDataGetData(pInputCol, i); - doSaveCurrentVal(pCtx, i, pts[i], type, data); - pResInfo->numOfRes = 1; - } + if (cts < pts[i + 2]) { + cts = pts[i + 2]; + chosen = i + 2; } - } else { - for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) { - if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) { - continue; - } - numOfElems++; + if (cts < pts[i + 3]) { + cts = pts[i + 3]; + chosen = i + 3; + } - if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) { - char* data = colDataGetData(pInputCol, i); - doSaveCurrentVal(pCtx, i, pts[i], type, data); - pResInfo->numOfRes = 1; - } + if (pResInfo->numOfRes == 0 || pInfo->ts < cts) { + char* data = colDataGetData(pInputCol, chosen); + doSaveCurrentVal(pCtx, i, cts, type, data); + pResInfo->numOfRes = 1; } } + + for (int32_t i = pInput->startRowIndex + round * 4; i < pInput->startRowIndex + pInput->numOfRows; ++i) { + if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) { + char* data = colDataGetData(pInputCol, i); + doSaveCurrentVal(pCtx, i, pts[i], type, data); + pResInfo->numOfRes = 1; + } + } + } else { + for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) { + if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) { + continue; + } + + numOfElems++; + + if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) { + char* data = colDataGetData(pInputCol, i); + doSaveCurrentVal(pCtx, i, pts[i], type, data); + pResInfo->numOfRes = 1; + } + } + } #endif #endif @@ -3179,7 +3179,7 @@ int32_t lastFunction(SqlFunctionCtx* pCtx) { firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo); } -// SET_VAL(pResInfo, numOfElems, 1); + // SET_VAL(pResInfo, numOfElems, 1); return TSDB_CODE_SUCCESS; } @@ -5280,7 +5280,6 @@ int32_t sampleFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { return pInfo->numSampled; } - bool getTailFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) { #if 0 SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0); @@ -6077,11 +6076,19 @@ int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { int32_t row = 0; char st[256] = {0}; - double totalRawSize = pData->totalRows * pData->rowSize; + double averageSize = 0; + if (pData->numOfBlocks != 0) { + averageSize = ((double)pData->totalSize) / pData->numOfBlocks; + } + uint64_t totalRawSize = pData->totalRows * pData->rowSize; + double compRatio = 0; + if (totalRawSize != 0) { + compRatio = pData->totalSize * 100 / (double)totalRawSize; + } + int32_t len = sprintf(st + VARSTR_HEADER_SIZE, "Total_Blocks=[%d] Total_Size=[%.2f Kb] Average_size=[%.2f Kb] Compression_Ratio=[%.2f %c]", - pData->numOfBlocks, pData->totalSize / 1024.0, ((double)pData->totalSize) / pData->numOfBlocks, - pData->totalSize * 100 / totalRawSize, '%'); + pData->numOfBlocks, pData->totalSize / 1024.0, averageSize, compRatio, '%'); varDataSetLen(st, len); colDataAppend(pColInfo, row++, st, false); From 52c222dda84bce285496c831ee2d666573155ac5 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Mon, 14 Nov 2022 10:36:26 +0800 Subject: [PATCH 06/39] test: add asan case --- tests/parallel_test/cases.task | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task index 59c7eeede6..5baa442231 100644 --- a/tests/parallel_test/cases.task +++ b/tests/parallel_test/cases.task @@ -321,7 +321,7 @@ ,,y,script,./test.sh -f tsim/compress/compress.sim ,,y,script,./test.sh -f tsim/compress/uncompress.sim ,,y,script,./test.sh -f tsim/compute/avg.sim -,,,script,./test.sh -f tsim/compute/block_dist.sim +,,y,script,./test.sh -f tsim/compute/block_dist.sim ,,y,script,./test.sh -f tsim/compute/bottom.sim ,,y,script,./test.sh -f tsim/compute/count.sim ,,y,script,./test.sh -f tsim/compute/diff.sim From 420be42269c52f28f64d58d1fc343fee7bc93012 Mon Sep 17 00:00:00 2001 From: stephenkgu Date: Sun, 13 Nov 2022 16:45:53 +0800 Subject: [PATCH 07/39] fix: flush pages to get buffer ready for fetching --- source/libs/tdb/src/db/tdbPCache.c | 13 +- source/libs/tdb/src/db/tdbPager.c | 222 ++++++++++++++++++++++++++--- source/libs/tdb/src/inc/tdbInt.h | 5 +- 3 files changed, 214 insertions(+), 26 deletions(-) diff --git a/source/libs/tdb/src/db/tdbPCache.c b/source/libs/tdb/src/db/tdbPCache.c index bdbd6c2f3d..e7254c8bc6 100644 --- a/source/libs/tdb/src/db/tdbPCache.c +++ b/source/libs/tdb/src/db/tdbPCache.c @@ -169,7 +169,7 @@ int tdbPCacheAlter(SPCache *pCache, int32_t nPage) { SPage *tdbPCacheFetch(SPCache *pCache, const SPgid *pPgid, TXN *pTxn) { SPage *pPage; - i32 nRef; + i32 nRef = 0; tdbPCacheLock(pCache); @@ -178,14 +178,17 @@ SPage *tdbPCacheFetch(SPCache *pCache, const SPgid *pPgid, TXN *pTxn) { nRef = tdbRefPage(pPage); } - ASSERT(pPage); - tdbPCacheUnlock(pCache); // printf("thread %" PRId64 " fetch page %d pgno %d pPage %p nRef %d\n", taosGetSelfPthreadId(), pPage->id, // TDB_PAGE_PGNO(pPage), pPage, nRef); - tdbDebug("pcache/fetch page %p/%d/%d/%d", pPage, TDB_PAGE_PGNO(pPage), pPage->id, nRef); + if (pPage) { + tdbDebug("pcache/fetch page %p/%d/%d/%d", pPage, TDB_PAGE_PGNO(pPage), pPage->id, nRef); + } else { + tdbDebug("pcache/fetch page %p", pPage); + } + return pPage; } @@ -266,7 +269,7 @@ static SPage *tdbPCacheFetchImpl(SPCache *pCache, const SPgid *pPgid, TXN *pTxn) } // 4. Try a create new page - if (!pPage) { + if (!pPage && pTxn->xMalloc != NULL) { ret = tdbPageCreate(pCache->szPage, &pPage, pTxn->xMalloc, pTxn->xArg); if (ret < 0 || pPage == NULL) { // TODO diff --git a/source/libs/tdb/src/db/tdbPager.c b/source/libs/tdb/src/db/tdbPager.c index c3ae1dc739..abbad06515 100644 --- a/source/libs/tdb/src/db/tdbPager.c +++ b/source/libs/tdb/src/db/tdbPager.c @@ -27,6 +27,116 @@ typedef struct { TDB_STATIC_ASSERT(sizeof(SFileHdr) == 128, "Size of file header is not correct"); +struct hashset_st { + size_t nbits; + size_t mask; + size_t capacity; + size_t *items; + size_t nitems; + double load_factor; +}; + +static const unsigned int prime = 39; +static const unsigned int prime2 = 5009; + +hashset_t hashset_create(void) { + hashset_t set = tdbOsCalloc(1, sizeof(struct hashset_st)); + if (!set) { + return NULL; + } + + set->nbits = 4; + set->capacity = (size_t)(1 << set->nbits); + set->items = tdbOsCalloc(set->capacity, sizeof(size_t)); + if (!set->items) { + tdbOsFree(set); + return NULL; + } + set->mask = set->capacity - 1; + set->nitems = 0; + + set->load_factor = 0.75; + + return set; +} + +void hashset_destroy(hashset_t set) { + if (set) { + tdbOsFree(set->items); + tdbOsFree(set); + } +} + +int hashset_add_member(hashset_t set, void *item) { + size_t value = (size_t) item; + size_t h; + + if (value == 0) { + return -1; + } + + for (h = set->mask & (prime * value); set->items[h] != 0; h = set->mask & (h + prime2)) { + if (set->items[h] == value) { + return 0; + } + } + + set->items[h] = value; + ++set->nitems; + return 1; +} + +int hashset_add(hashset_t set, void *item) { + int ret = hashset_add_member(set, item); + + size_t old_capacity = set->capacity; + if (set->nitems >= (double)old_capacity * set->load_factor) { + size_t *old_items = set->items; + ++set->nbits; + set->capacity = (size_t)(1 << set->nbits); + set->mask = set->capacity - 1; + + set->items = tdbOsCalloc(set->capacity, sizeof(size_t)); + if (!set->items) { + return -1; + } + + set->nitems = 0; + for (size_t i = 0; i < old_capacity; ++i) { + hashset_add_member(set, (void*)old_items[i]); + } + tdbOsFree(old_items); + } + + return ret; +} + +int hashset_remove(hashset_t set, void *item) { + size_t value = (size_t) item; + + for (size_t h = set->mask & (prime * value); set->items[h] != 0; h = set->mask & (h + prime2)) { + if (set->items[h] == value) { + set->items[h] = 0; + --set->nitems; + return 1; + } + } + + return 0; +} + +int hashset_contains(hashset_t set, void *item) { + size_t value = (size_t) item; + + for (size_t h = set->mask & (prime * value); set->items[h] != 0; h = set->mask & (h + prime2)) { + if (set->items[h] == value) { + return 1; + } + } + + return 0; +} + #define TDB_PAGE_INITIALIZED(pPage) ((pPage)->pPager != NULL) static int tdbPagerInitPage(SPager *pPager, SPage *pPage, int (*initPage)(SPage *, void *, int), void *arg, @@ -209,12 +319,16 @@ int tdbPagerWrite(SPager *pPager, SPage *pPage) { tRBTreePut(&pPager->rbt, (SRBTreeNode *)pPage); // Write page to journal if neccessary - if (TDB_PAGE_PGNO(pPage) <= pPager->dbOrigSize) { + if (TDB_PAGE_PGNO(pPage) <= pPager->dbOrigSize && (pPager->jPageSet == NULL || !hashset_contains(pPager->jPageSet, (void*)((long)TDB_PAGE_PGNO(pPage))))) { ret = tdbPagerWritePageToJournal(pPager, pPage); if (ret < 0) { tdbError("failed to write page to journal since %s", tstrerror(terrno)); return -1; } + + if (pPager->jPageSet) { + hashset_add(pPager->jPageSet, (void*)((long)TDB_PAGE_PGNO(pPage))); + } } return 0; @@ -233,6 +347,7 @@ int tdbPagerBegin(SPager *pPager, TXN *pTxn) { return -1; } + pPager->jPageSet = hashset_create(); // TODO: write the size of the file pPager->inTran = 1; @@ -275,6 +390,9 @@ int tdbPagerCommit(SPager *pPager, TXN *pTxn) { pPage->isDirty = 0; tRBTreeDrop(&pPager->rbt, (SRBTreeNode *)pPage); + if (pPager->jPageSet) { + hashset_remove(pPager->jPageSet, (void*)((long)TDB_PAGE_PGNO(pPage))); + } tdbPCacheRelease(pPager->pCache, pPage, pTxn); } @@ -304,6 +422,9 @@ int tdbPagerPostCommit(SPager *pPager, TXN *pTxn) { return -1; } + if (pPager->jPageSet) { + hashset_destroy(pPager->jPageSet); + } pPager->inTran = 0; return 0; @@ -375,36 +496,61 @@ int tdbPagerAbort(SPager *pPager, TXN *pTxn) { return -1; } - tdb_fd_t jfd = tdbOsOpen(pPager->jFileName, TDB_O_RDWR, 0755); - if (jfd == NULL) { - return -1; - } + tdb_fd_t jfd = pPager->jfd; ret = tdbGetFileSize(jfd, pPager->pageSize, &journalSize); if (ret < 0) { return -1; } - // 1, read pages from jounal file - // 2, write original pages to buffered ones + u8 *pageBuf = tdbOsCalloc(1, pPager->pageSize); + if (pageBuf == NULL) { + return -1; + } - /* TODO: reset the buffered pages instead of releasing them - // loop to reset the dirty pages from file - for (pgIdx = 0, pPage = pPager->pDirty; pPage != NULL && pgIndex < journalSize; pPage = pPage->pDirtyNext, ++pgIdx) { + for (int pgIndex = 0; pgIndex < journalSize; ++pgIndex) { // read pgno & the page from journal SPgno pgno; int ret = tdbOsRead(jfd, &pgno, sizeof(pgno)); if (ret < 0) { + tdbOsFree(pageBuf); return -1; } ret = tdbOsRead(jfd, pageBuf, pPager->pageSize); if (ret < 0) { + tdbOsFree(pageBuf); + return -1; + } + + i64 offset = pPager->pageSize * (pgno - 1); + if (tdbOsLSeek(pPager->fd, offset, SEEK_SET) < 0) { + tdbError("failed to lseek fd due to %s. file:%s, offset:%" PRId64, strerror(errno), pPager->dbFileName, offset); + terrno = TAOS_SYSTEM_ERROR(errno); + tdbOsFree(pageBuf); + return -1; + } + + ret = tdbOsWrite(pPager->fd, pageBuf, pPager->pageSize); + if (ret < 0) { + tdbError("failed to write buf due to %s. file: %s, bufsize:%d", strerror(errno), pPager->dbFileName, + pPager->pageSize); + terrno = TAOS_SYSTEM_ERROR(errno); + tdbOsFree(pageBuf); return -1; } } - */ + + if (tdbOsFSync(pPager->fd) < 0) { + tdbError("failed to fsync fd due to %s. dbfile:%s", strerror(errno), pPager->dbFileName); + terrno = TAOS_SYSTEM_ERROR(errno); + tdbOsFree(pageBuf); + return -1; + } + + tdbOsFree(pageBuf); + // 3, release the dirty pages SRBTreeIter iter = tRBTreeIterCreate(&pPager->rbt, 1); SRBTreeNode *pNode = NULL; @@ -413,17 +559,55 @@ int tdbPagerAbort(SPager *pPager, TXN *pTxn) { pPage->isDirty = 0; + tRBTreeDrop(&pPager->rbt, (SRBTreeNode *)pPage); + hashset_remove(pPager->jPageSet, (void*)((long)TDB_PAGE_PGNO(pPage))); + tdbPCacheRelease(pPager->pCache, pPage, pTxn); + } + + tRBTreeCreate(&pPager->rbt, pageCmpFn); + + // 4, remove the journal file + tdbOsClose(pPager->jfd); + (void)tdbOsRemove(pPager->jFileName); + hashset_destroy(pPager->jPageSet); + + pPager->inTran = 0; + + return 0; +} + +int tdbPagerFlushPage(SPager *pPager, TXN *pTxn) { + SPage *pPage; + int ret; + + // loop to write the dirty pages to file + SRBTreeIter iter = tRBTreeIterCreate(&pPager->rbt, 1); + SRBTreeNode *pNode = NULL; + while ((pNode = tRBTreeIterNext(&iter)) != NULL) { + pPage = (SPage *)pNode; + ret = tdbPagerWritePageToDB(pPager, pPage); + if (ret < 0) { + tdbError("failed to write page to db since %s", tstrerror(terrno)); + return -1; + } + } + + tdbTrace("tdbttl commit:%p, %d/%d", pPager, pPager->dbOrigSize, pPager->dbFileSize); + pPager->dbOrigSize = pPager->dbFileSize; + + // release the page + iter = tRBTreeIterCreate(&pPager->rbt, 1); + while ((pNode = tRBTreeIterNext(&iter)) != NULL) { + pPage = (SPage *)pNode; + + pPage->isDirty = 0; + tRBTreeDrop(&pPager->rbt, (SRBTreeNode *)pPage); tdbPCacheRelease(pPager->pCache, pPage, pTxn); } tRBTreeCreate(&pPager->rbt, pageCmpFn); - // 4, remove the journal file - tdbOsClose(pPager->jfd); - (void)tdbOsRemove(pPager->jFileName); - pPager->inTran = 0; - return 0; } @@ -453,10 +637,8 @@ int tdbPagerFetchPage(SPager *pPager, SPgno *ppgno, SPage **ppPage, int (*initPa // fetch a page container memcpy(&pgid, pPager->fid, TDB_FILE_ID_LEN); pgid.pgno = pgno; - pPage = tdbPCacheFetch(pPager->pCache, &pgid, pTxn); - if (pPage == NULL) { - ASSERT(0); - return -1; + while ((pPage = tdbPCacheFetch(pPager->pCache, &pgid, pTxn)) == NULL) { + tdbPagerFlushPage(pPager, pTxn); } tdbTrace("tdbttl fetch pager:%p", pPage->pPager); diff --git a/source/libs/tdb/src/inc/tdbInt.h b/source/libs/tdb/src/inc/tdbInt.h index e5ece98b28..731b1927e7 100644 --- a/source/libs/tdb/src/inc/tdbInt.h +++ b/source/libs/tdb/src/inc/tdbInt.h @@ -384,6 +384,8 @@ struct STDB { #endif }; +typedef struct hashset_st *hashset_t; + struct SPager { char *dbFileName; char *jFileName; @@ -394,7 +396,8 @@ struct SPager { SPCache *pCache; SPgno dbFileSize; SPgno dbOrigSize; - SPage *pDirty; + //SPage *pDirty; + hashset_t jPageSet; SRBTree rbt; u8 inTran; SPager *pNext; // used by TDB From d6c389a6ccaa6b4b4da4acb8da82ca8151f6c8c2 Mon Sep 17 00:00:00 2001 From: Liu Jicong Date: Fri, 11 Nov 2022 16:01:47 +0800 Subject: [PATCH 08/39] refactor(tmq): add debug log --- source/dnode/mnode/impl/src/mndSubscribe.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/source/dnode/mnode/impl/src/mndSubscribe.c b/source/dnode/mnode/impl/src/mndSubscribe.c index a62f15f978..71e0b09e02 100644 --- a/source/dnode/mnode/impl/src/mndSubscribe.c +++ b/source/dnode/mnode/impl/src/mndSubscribe.c @@ -944,6 +944,8 @@ static int32_t mndRetrieveSubscribe(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock int32_t numOfRows = 0; SMqSubscribeObj *pSub = NULL; + mDebug("mnd show subscriptions begin"); + while (numOfRows < rowsCapacity) { pShow->pIter = sdbFetch(pSdb, SDB_SUBSCRIBE, pShow->pIter, (void **)&pSub); if (pShow->pIter == NULL) break; @@ -989,6 +991,9 @@ static int32_t mndRetrieveSubscribe(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); colDataAppend(pColInfo, numOfRows, (const char *)&pConsumerEp->consumerId, false); + mDebug("mnd show subscrptions: topic %s, consumer %" PRId64 "cgroup %s vgid %d", varDataVal(topic), + pConsumerEp->consumerId, varDataVal(cgroup), pVgEp->vgId); + // offset #if 0 // subscribe time @@ -1034,6 +1039,9 @@ static int32_t mndRetrieveSubscribe(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); colDataAppend(pColInfo, numOfRows, NULL, true); + mDebug("mnd show subscrptions(unassigned): topic %s, cgroup %s vgid %d", varDataVal(topic), varDataVal(cgroup), + pVgEp->vgId); + // offset #if 0 // subscribe time @@ -1053,6 +1061,8 @@ static int32_t mndRetrieveSubscribe(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock sdbRelease(pSdb, pSub); } + mDebug("mnd end show subscriptions"); + pShow->numOfRows += numOfRows; return numOfRows; } From a5b1cfc9a25c08e4ae1b87b480ed6cdc8f7a117a Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Mon, 14 Nov 2022 11:27:38 +0800 Subject: [PATCH 09/39] fix: extend show create table result width --- include/common/tdatablock.h | 1 + include/libs/function/taosudf.h | 2 +- include/util/types.h | 8 +++- source/client/src/clientImpl.c | 4 ++ source/common/src/tdatablock.c | 38 +++++++++++++++++ source/libs/command/src/command.c | 58 +++++++++++++------------- source/libs/parser/src/parTranslater.c | 4 +- 7 files changed, 82 insertions(+), 33 deletions(-) diff --git a/include/common/tdatablock.h b/include/common/tdatablock.h index 502ba10d33..2dc1ca821f 100644 --- a/include/common/tdatablock.h +++ b/include/common/tdatablock.h @@ -186,6 +186,7 @@ static FORCE_INLINE void colDataAppendDouble(SColumnInfoData* pColumnInfoData, u int32_t getJsonValueLen(const char* data); +int32_t colDataLenAppend(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData, uint32_t dataLen); int32_t colDataAppend(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData, bool isNull); int32_t colDataAppendNItems(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData, uint32_t numOfRows); diff --git a/include/libs/function/taosudf.h b/include/libs/function/taosudf.h index 3fe3bb7d3b..d79a569944 100644 --- a/include/libs/function/taosudf.h +++ b/include/libs/function/taosudf.h @@ -104,7 +104,7 @@ typedef int32_t (*TUdfDestroyFunc)(); } while (0) #define udfColDataSetNull_var(pColumn, row) ((pColumn->colData.varLenCol.varOffsets)[row] = -1) -typedef uint16_t VarDataLenT; // maxVarDataLen: 32767 +typedef int16_t VarDataLenT; // maxVarDataLen: 32767 #define VARSTR_HEADER_SIZE sizeof(VarDataLenT) #define varDataLen(v) ((VarDataLenT *)(v))[0] #define varDataVal(v) ((char *)(v) + VARSTR_HEADER_SIZE) diff --git a/include/util/types.h b/include/util/types.h index 8dd0947e9c..21a529559a 100644 --- a/include/util/types.h +++ b/include/util/types.h @@ -78,7 +78,7 @@ static FORCE_INLINE double taos_align_get_double(const char *pBuf) { { (*(double *)(x)) = (*(double *)(y)); } // #endif -typedef uint16_t VarDataLenT; // maxVarDataLen: 32767 +typedef int16_t VarDataLenT; // maxVarDataLen: 32767 #define VARSTR_HEADER_SIZE sizeof(VarDataLenT) #define varDataLen(v) ((VarDataLenT *)(v))[0] @@ -87,6 +87,12 @@ typedef uint16_t VarDataLenT; // maxVarDataLen: 32767 #define NCHAR_WIDTH_TO_BYTES(n) ((n)*TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE) +typedef uint32_t extVarDataLenT; +#define EXTVARSTR_HEADER_SIZE (VARSTR_HEADER_SIZE + sizeof(extVarDataLenT)) +#define extVarDataLen(v) ((*(VarDataLenT *)(v)) == -1 ? (*(extVarDataLenT*)(((VarDataLenT *)(v)) + 1)) : (*(VarDataLenT *)(v))) +#define extVarDataVal(v) ((char *)(v) + EXTVARSTR_HEADER_SIZE) +#define setExtVarDataLen(v, l) do { *(VarDataLenT *)(v) = -1; *(extVarDataLenT*)(((VarDataLenT *)(v)) + 1) = (l); } while (0) + typedef int32_t VarDataOffsetT; typedef struct tstr { diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index c3140371c4..3b8270b7e5 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -1482,6 +1482,10 @@ void doSetOneRowPtr(SReqResultInfo* pResultInfo) { pResultInfo->length[i] = varDataLen(pStart); pResultInfo->row[i] = varDataVal(pStart); + if (-1 == pResultInfo->length[i]) { + pResultInfo->length[i] = extVarDataLen(pStart); + pResultInfo->row[i] = extVarDataVal(pStart); + } } else { pResultInfo->row[i] = NULL; pResultInfo->length[i] = 0; diff --git a/source/common/src/tdatablock.c b/source/common/src/tdatablock.c index 536cbed33e..ce4fa1f909 100644 --- a/source/common/src/tdatablock.c +++ b/source/common/src/tdatablock.c @@ -62,6 +62,44 @@ int32_t getJsonValueLen(const char* data) { return dataLen; } +int32_t colDataLenAppend(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData, uint32_t dataLen) { + ASSERT(pColumnInfoData != NULL); + + int32_t type = pColumnInfoData->info.type; + if (IS_VAR_DATA_TYPE(type)) { + SVarColAttr* pAttr = &pColumnInfoData->varmeta; + if (pAttr->allocLen < pAttr->length + dataLen) { + uint32_t newSize = pAttr->allocLen; + if (newSize <= 1) { + newSize = 8; + } + + while (newSize < pAttr->length + dataLen) { + newSize = newSize * 1.5; + } + + char* buf = taosMemoryRealloc(pColumnInfoData->pData, newSize); + if (buf == NULL) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + pColumnInfoData->pData = buf; + pAttr->allocLen = newSize; + } + + uint32_t len = pColumnInfoData->varmeta.length; + pColumnInfoData->varmeta.offset[currentRow] = len; + + memcpy(pColumnInfoData->pData + len, pData, dataLen); + pColumnInfoData->varmeta.length += dataLen; + } else { + memcpy(pColumnInfoData->pData + pColumnInfoData->info.bytes * currentRow, pData, pColumnInfoData->info.bytes); + } + + return 0; +} + + int32_t colDataAppend(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData, bool isNull) { ASSERT(pColumnInfoData != NULL); diff --git a/source/libs/command/src/command.c b/source/libs/command/src/command.c index 1c2d7e1f66..0625c23a7a 100644 --- a/source/libs/command/src/command.c +++ b/source/libs/command/src/command.c @@ -330,7 +330,7 @@ void appendColumnFields(char* buf, int32_t* len, STableCfg* pCfg) { sprintf(type + strlen(type), "(%d)", (int32_t)((pSchema->bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE)); } - *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "%s`%s` %s", ((i > 0) ? ", " : ""), pSchema->name, type); + *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, "%s`%s` %s", ((i > 0) ? ", " : ""), pSchema->name, type); } } @@ -345,14 +345,14 @@ void appendTagFields(char* buf, int32_t* len, STableCfg* pCfg) { sprintf(type + strlen(type), "(%d)", (int32_t)((pSchema->bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE)); } - *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "%s`%s` %s", ((i > 0) ? ", " : ""), pSchema->name, type); + *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, "%s`%s` %s", ((i > 0) ? ", " : ""), pSchema->name, type); } } void appendTagNameFields(char* buf, int32_t* len, STableCfg* pCfg) { for (int32_t i = 0; i < pCfg->numOfTags; ++i) { SSchema* pSchema = pCfg->pSchemas + pCfg->numOfColumns + i; - *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "%s`%s`", ((i > 0) ? ", " : ""), pSchema->name); + *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, "%s`%s`", ((i > 0) ? ", " : ""), pSchema->name); } } @@ -368,7 +368,7 @@ int32_t appendTagValues(char* buf, int32_t* len, STableCfg* pCfg) { if (tTagIsJson(pTag)) { char* pJson = parseTagDatatoJson(pTag); if (pJson) { - *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "%s", pJson); + *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, "%s", pJson); taosMemoryFree(pJson); } @@ -386,11 +386,11 @@ int32_t appendTagValues(char* buf, int32_t* len, STableCfg* pCfg) { for (int32_t i = 0; i < pCfg->numOfTags; ++i) { SSchema* pSchema = pCfg->pSchemas + pCfg->numOfColumns + i; if (i > 0) { - *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, ", "); + *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, ", "); } if (j >= valueNum) { - *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "NULL"); + *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, "NULL"); continue; } @@ -404,14 +404,14 @@ int32_t appendTagValues(char* buf, int32_t* len, STableCfg* pCfg) { int32_t tlen = 0; if (IS_VAR_DATA_TYPE(type)) { - dataConverToStr(buf + VARSTR_HEADER_SIZE + *len, type, pTagVal->pData, pTagVal->nData, &tlen); + dataConverToStr(buf + EXTVARSTR_HEADER_SIZE + *len, type, pTagVal->pData, pTagVal->nData, &tlen); } else { - dataConverToStr(buf + VARSTR_HEADER_SIZE + *len, type, &pTagVal->i64, tDataTypes[type].bytes, &tlen); + dataConverToStr(buf + EXTVARSTR_HEADER_SIZE + *len, type, &pTagVal->i64, tDataTypes[type].bytes, &tlen); } *len += tlen; j++; } else { - *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "NULL"); + *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, "NULL"); } /* @@ -450,37 +450,37 @@ int32_t appendTagValues(char* buf, int32_t* len, STableCfg* pCfg) { void appendTableOptions(char* buf, int32_t* len, SDbCfgInfo* pDbCfg, STableCfg* pCfg) { if (pCfg->commentLen > 0) { - *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, " COMMENT '%s'", pCfg->pComment); + *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, " COMMENT '%s'", pCfg->pComment); } else if (0 == pCfg->commentLen) { - *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, " COMMENT ''"); + *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, " COMMENT ''"); } if (NULL != pDbCfg->pRetensions && pCfg->watermark1 > 0) { - *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, " WATERMARK %" PRId64 "a", pCfg->watermark1); + *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, " WATERMARK %" PRId64 "a", pCfg->watermark1); if (pCfg->watermark2 > 0) { - *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, ", %" PRId64 "a", pCfg->watermark2); + *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, ", %" PRId64 "a", pCfg->watermark2); } } if (NULL != pDbCfg->pRetensions && pCfg->delay1 > 0) { - *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, " MAX_DELAY %" PRId64 "a", pCfg->delay1); + *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, " MAX_DELAY %" PRId64 "a", pCfg->delay1); if (pCfg->delay2 > 0) { - *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, ", %" PRId64 "a", pCfg->delay2); + *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, ", %" PRId64 "a", pCfg->delay2); } } int32_t funcNum = taosArrayGetSize(pCfg->pFuncs); if (NULL != pDbCfg->pRetensions && funcNum > 0) { - *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, " ROLLUP("); + *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, " ROLLUP("); for (int32_t i = 0; i < funcNum; ++i) { char* pFunc = taosArrayGet(pCfg->pFuncs, i); - *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "%s%s", ((i > 0) ? ", " : ""), pFunc); + *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, "%s%s", ((i > 0) ? ", " : ""), pFunc); } - *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, ")"); + *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, ")"); } if (pCfg->ttl > 0) { - *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, " TTL %d", pCfg->ttl); + *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, " TTL %d", pCfg->ttl); } } @@ -504,33 +504,33 @@ static int32_t setCreateTBResultIntoDataBlock(SSDataBlock* pBlock, SDbCfgInfo* p int32_t len = 0; if (TSDB_SUPER_TABLE == pCfg->tableType) { - len += sprintf(buf2 + VARSTR_HEADER_SIZE, "CREATE STABLE `%s` (", tbName); + len += sprintf(buf2 + EXTVARSTR_HEADER_SIZE, "CREATE STABLE `%s` (", tbName); appendColumnFields(buf2, &len, pCfg); - len += sprintf(buf2 + VARSTR_HEADER_SIZE + len, ") TAGS ("); + len += sprintf(buf2 + EXTVARSTR_HEADER_SIZE + len, ") TAGS ("); appendTagFields(buf2, &len, pCfg); - len += sprintf(buf2 + VARSTR_HEADER_SIZE + len, ")"); + len += sprintf(buf2 + EXTVARSTR_HEADER_SIZE + len, ")"); appendTableOptions(buf2, &len, pDbCfg, pCfg); } else if (TSDB_CHILD_TABLE == pCfg->tableType) { - len += sprintf(buf2 + VARSTR_HEADER_SIZE, "CREATE TABLE `%s` USING `%s` (", tbName, pCfg->stbName); + len += sprintf(buf2 + EXTVARSTR_HEADER_SIZE, "CREATE TABLE `%s` USING `%s` (", tbName, pCfg->stbName); appendTagNameFields(buf2, &len, pCfg); - len += sprintf(buf2 + VARSTR_HEADER_SIZE + len, ") TAGS ("); + len += sprintf(buf2 + EXTVARSTR_HEADER_SIZE + len, ") TAGS ("); code = appendTagValues(buf2, &len, pCfg); if (code) { taosMemoryFree(buf2); return code; } - len += sprintf(buf2 + VARSTR_HEADER_SIZE + len, ")"); + len += sprintf(buf2 + EXTVARSTR_HEADER_SIZE + len, ")"); appendTableOptions(buf2, &len, pDbCfg, pCfg); } else { - len += sprintf(buf2 + VARSTR_HEADER_SIZE, "CREATE TABLE `%s` (", tbName); + len += sprintf(buf2 + EXTVARSTR_HEADER_SIZE, "CREATE TABLE `%s` (", tbName); appendColumnFields(buf2, &len, pCfg); - len += sprintf(buf2 + VARSTR_HEADER_SIZE + len, ")"); + len += sprintf(buf2 + EXTVARSTR_HEADER_SIZE + len, ")"); appendTableOptions(buf2, &len, pDbCfg, pCfg); } - varDataLen(buf2) = len; + setExtVarDataLen(buf2, len); - colDataAppend(pCol2, 0, buf2, false); + colDataLenAppend(pCol2, 0, buf2, len + EXTVARSTR_HEADER_SIZE); taosMemoryFree(buf2); diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 0e5cb14208..e64a370e15 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -6060,11 +6060,11 @@ static int32_t extractShowCreateTableResultSchema(int32_t* numOfCols, SSchema** } (*pSchema)[0].type = TSDB_DATA_TYPE_BINARY; - (*pSchema)[0].bytes = TSDB_TABLE_NAME_LEN; + (*pSchema)[0].bytes = SHOW_CREATE_TB_RESULT_FIELD1_LEN; strcpy((*pSchema)[0].name, "Table"); (*pSchema)[1].type = TSDB_DATA_TYPE_BINARY; - (*pSchema)[1].bytes = TSDB_MAX_BINARY_LEN; + (*pSchema)[1].bytes = SHOW_CREATE_TB_RESULT_FIELD2_LEN; strcpy((*pSchema)[1].name, "Create Table"); return TSDB_CODE_SUCCESS; From 2dd1e05cf0271e6d2147fb1aec8dd6b2bd84eabe Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Mon, 14 Nov 2022 11:41:11 +0800 Subject: [PATCH 10/39] fix(timezone): taos_options apply new timezone --- source/util/src/tconfig.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source/util/src/tconfig.c b/source/util/src/tconfig.c index c1fee37610..5250f5dfcd 100644 --- a/source/util/src/tconfig.c +++ b/source/util/src/tconfig.c @@ -271,8 +271,14 @@ static int32_t cfgSetTimezone(SConfigItem *pItem, const char *value, ECfgSrcType cfgStypeStr(stype), value, terrstr()); return -1; } - pItem->stype = stype; + + // apply new timezone + char szTimezone[TD_TIMEZONE_LEN] = {0}; + int8_t dl; + enum TdTimezone tdOffset = TdZeroZone; + taosSetSystemTimezone(value, szTimezone, &dl, &tdOffset); + return 0; } From 51861bb82ba07047939dff773318914b826448cf Mon Sep 17 00:00:00 2001 From: Minghao Li Date: Mon, 14 Nov 2022 14:20:13 +0800 Subject: [PATCH 11/39] refactor(sync): delete some code --- source/libs/sync/src/syncAppendEntriesReply.c | 37 ------------------- 1 file changed, 37 deletions(-) diff --git a/source/libs/sync/src/syncAppendEntriesReply.c b/source/libs/sync/src/syncAppendEntriesReply.c index ea4dee64f1..2e22ac98a5 100644 --- a/source/libs/sync/src/syncAppendEntriesReply.c +++ b/source/libs/sync/src/syncAppendEntriesReply.c @@ -39,43 +39,6 @@ // /\ UNCHANGED <> // -// only start once -static void syncNodeStartSnapshotOnce(SSyncNode* ths, SyncIndex beginIndex, SyncIndex endIndex, SyncTerm lastApplyTerm, - SyncAppendEntriesReply* pMsg) { - if (beginIndex > endIndex) { - sNError(ths, "snapshot param error, start:%" PRId64 ", end:%" PRId64, beginIndex, endIndex); - return; - } - - // get sender - SSyncSnapshotSender* pSender = syncNodeGetSnapshotSender(ths, &(pMsg->srcId)); - ASSERT(pSender != NULL); - - if (snapshotSenderIsStart(pSender)) { - sSError(pSender, "snapshot sender already start"); - return; - } - - SSnapshot snapshot = { - .data = NULL, .lastApplyIndex = endIndex, .lastApplyTerm = lastApplyTerm, .lastConfigIndex = SYNC_INDEX_INVALID}; - void* pReader = NULL; - SSnapshotParam readerParam = {.start = beginIndex, .end = endIndex}; - int32_t code = ths->pFsm->FpSnapshotStartRead(ths->pFsm, &readerParam, &pReader); - ASSERT(code == 0); - -#if 0 - if (pMsg->privateTerm < pSender->privateTerm) { - ASSERT(pReader != NULL); - snapshotSenderStart(pSender, readerParam, snapshot, pReader); - - } else { - if (pReader != NULL) { - ths->pFsm->FpSnapshotStopRead(ths->pFsm, pReader); - } - } -#endif -} - int32_t syncNodeOnAppendEntriesReply(SSyncNode* ths, SyncAppendEntriesReply* pMsg) { int32_t ret = 0; From d2468c5548895680d7e3a53c17fd304eeec64a91 Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Mon, 14 Nov 2022 14:22:13 +0800 Subject: [PATCH 12/39] fix: fix asan issues --- include/common/ttypes.h | 4 ++-- source/common/src/ttypes.c | 26 +++++++++++++++++-------- source/dnode/vnode/src/vnd/vnodeQuery.c | 6 ++++-- source/libs/scalar/src/filter.c | 13 ++++++++----- source/libs/scheduler/src/schRemote.c | 8 +++++--- 5 files changed, 37 insertions(+), 20 deletions(-) diff --git a/include/common/ttypes.h b/include/common/ttypes.h index bfd6a75c3a..761ffd0f1c 100644 --- a/include/common/ttypes.h +++ b/include/common/ttypes.h @@ -346,8 +346,8 @@ bool isValidDataType(int32_t type); void assignVal(char *val, const char *src, int32_t len, int32_t type); void operateVal(void *dst, void *s1, void *s2, int32_t optr, int32_t type); -void *getDataMin(int32_t type); -void *getDataMax(int32_t type); +void *getDataMin(int32_t type, void* value); +void *getDataMax(int32_t type, void* value); #ifdef __cplusplus } diff --git a/source/common/src/ttypes.c b/source/common/src/ttypes.c index a4e7a12ce4..8c5d44b8d5 100644 --- a/source/common/src/ttypes.c +++ b/source/common/src/ttypes.c @@ -61,26 +61,36 @@ tDataTypeDescriptor tDataTypes[TSDB_DATA_TYPE_MAX] = { static float floatMin = -FLT_MAX, floatMax = FLT_MAX; static double doubleMin = -DBL_MAX, doubleMax = DBL_MAX; -FORCE_INLINE void *getDataMin(int32_t type) { +FORCE_INLINE void *getDataMin(int32_t type, void* value) { switch (type) { case TSDB_DATA_TYPE_FLOAT: - return &floatMin; + *(float *)value = floatMin; + break; case TSDB_DATA_TYPE_DOUBLE: - return &doubleMin; + *(double *)value = doubleMin; + break; default: - return &tDataTypes[type].minValue; + *(int64_t *)value = tDataTypes[type].minValue; + break; } + + return value; } -FORCE_INLINE void *getDataMax(int32_t type) { +FORCE_INLINE void *getDataMax(int32_t type, void* value) { switch (type) { case TSDB_DATA_TYPE_FLOAT: - return &floatMax; + *(float *)value = floatMax; + break; case TSDB_DATA_TYPE_DOUBLE: - return &doubleMax; + *(double *)value = doubleMax; + break; default: - return &tDataTypes[type].maxValue; + *(int64_t *)value = tDataTypes[type].maxValue; + break; } + + return value; } bool isValidDataType(int32_t type) { return type >= TSDB_DATA_TYPE_NULL && type < TSDB_DATA_TYPE_MAX; } diff --git a/source/dnode/vnode/src/vnd/vnodeQuery.c b/source/dnode/vnode/src/vnd/vnodeQuery.c index ef0ee6ac0b..15769ef4c9 100644 --- a/source/dnode/vnode/src/vnd/vnodeQuery.c +++ b/source/dnode/vnode/src/vnd/vnodeQuery.c @@ -388,8 +388,10 @@ int32_t vnodeGetBatchMeta(SVnode *pVnode, SRpcMsg *pMsg) { offset += sizeof(p->msgLen); *(int32_t *)((char *)pRsp + offset) = htonl(p->rspCode); offset += sizeof(p->rspCode); - memcpy((char *)pRsp + offset, p->msg, p->msgLen); - offset += p->msgLen; + if (p->msg) { + memcpy((char *)pRsp + offset, p->msg, p->msgLen); + offset += p->msgLen; + } taosMemoryFreeClear(p->msg); } diff --git a/source/libs/scalar/src/filter.c b/source/libs/scalar/src/filter.c index df9a818fee..be085e6cbd 100644 --- a/source/libs/scalar/src/filter.c +++ b/source/libs/scalar/src/filter.c @@ -512,15 +512,17 @@ int32_t filterReuseRangeCtx(SFilterRangeCtx *ctx, int32_t type, int32_t options) } int32_t filterConvertRange(SFilterRangeCtx *cur, SFilterRange *ra, bool *notNull) { + int64_t tmp = 0; + if (!FILTER_GET_FLAG(ra->sflag, RANGE_FLG_NULL)) { - int32_t sr = cur->pCompareFunc(&ra->s, getDataMin(cur->type)); + int32_t sr = cur->pCompareFunc(&ra->s, getDataMin(cur->type, &tmp)); if (sr == 0) { FILTER_SET_FLAG(ra->sflag, RANGE_FLG_NULL); } } if (!FILTER_GET_FLAG(ra->eflag, RANGE_FLG_NULL)) { - int32_t er = cur->pCompareFunc(&ra->e, getDataMax(cur->type)); + int32_t er = cur->pCompareFunc(&ra->e, getDataMax(cur->type, &tmp)); if (er == 0) { FILTER_SET_FLAG(ra->eflag, RANGE_FLG_NULL); } @@ -696,14 +698,15 @@ int32_t filterAddRangeImpl(void *h, SFilterRange *ra, int32_t optr) { int32_t filterAddRange(void *h, SFilterRange *ra, int32_t optr) { SFilterRangeCtx *ctx = (SFilterRangeCtx *)h; - + int64_t tmp = 0; + if (FILTER_GET_FLAG(ra->sflag, RANGE_FLG_NULL)) { - SIMPLE_COPY_VALUES(&ra->s, getDataMin(ctx->type)); + SIMPLE_COPY_VALUES(&ra->s, getDataMin(ctx->type, &tmp)); // FILTER_CLR_FLAG(ra->sflag, RA_NULL); } if (FILTER_GET_FLAG(ra->eflag, RANGE_FLG_NULL)) { - SIMPLE_COPY_VALUES(&ra->e, getDataMax(ctx->type)); + SIMPLE_COPY_VALUES(&ra->e, getDataMax(ctx->type, &tmp)); // FILTER_CLR_FLAG(ra->eflag, RA_NULL); } diff --git a/source/libs/scheduler/src/schRemote.c b/source/libs/scheduler/src/schRemote.c index 22fb66d92f..a6a2a6c301 100644 --- a/source/libs/scheduler/src/schRemote.c +++ b/source/libs/scheduler/src/schRemote.c @@ -286,9 +286,11 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t execId, SDa if (pJob->execRes.res) { SSubmitRsp *sum = pJob->execRes.res; sum->affectedRows += rsp->affectedRows; - sum->nBlocks += rsp->nBlocks; - sum->pBlocks = taosMemoryRealloc(sum->pBlocks, sum->nBlocks * sizeof(*sum->pBlocks)); - memcpy(sum->pBlocks + sum->nBlocks - rsp->nBlocks, rsp->pBlocks, rsp->nBlocks * sizeof(*sum->pBlocks)); + sum->nBlocks += rsp->nBlocks; + if (rsp->nBlocks > 0 && rsp->pBlocks) { + sum->pBlocks = taosMemoryRealloc(sum->pBlocks, sum->nBlocks * sizeof(*sum->pBlocks)); + memcpy(sum->pBlocks + sum->nBlocks - rsp->nBlocks, rsp->pBlocks, rsp->nBlocks * sizeof(*sum->pBlocks)); + } taosMemoryFree(rsp->pBlocks); taosMemoryFree(rsp); } else { From c6efc1ed843363952918377f0eb09c64a0316281 Mon Sep 17 00:00:00 2001 From: shenglian zhou Date: Mon, 14 Nov 2022 14:32:34 +0800 Subject: [PATCH 13/39] fix: fix memory leak during crashgen stream and subscribe --- source/common/src/tmsg.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/common/src/tmsg.c b/source/common/src/tmsg.c index 2eb94773e9..bd8e34a395 100644 --- a/source/common/src/tmsg.c +++ b/source/common/src/tmsg.c @@ -2591,7 +2591,10 @@ int32_t tDeserializeSUseDbBatchRsp(void *buf, int32_t bufLen, SUseDbBatchRsp *pR for (int32_t i = 0; i < numOfBatch; ++i) { SUseDbRsp usedbRsp = {0}; - if (tDeserializeSUseDbRspImp(&decoder, &usedbRsp) < 0) return -1; + if (tDeserializeSUseDbRspImp(&decoder, &usedbRsp) < 0) { + tDecoderClear(&decoder); + return -1; + } taosArrayPush(pRsp->pArray, &usedbRsp); } tEndDecode(&decoder); From 7bddbb06f0c7c259dac8bdfabe32c11f70c9155f Mon Sep 17 00:00:00 2001 From: Xiaoyu Wang Date: Mon, 14 Nov 2022 14:38:51 +0800 Subject: [PATCH 14/39] fix: sanitizer error --- source/client/src/clientMain.c | 1 + source/libs/parser/src/parInsertSql.c | 1 + 2 files changed, 2 insertions(+) diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c index efa7d095c5..0aa88382fe 100644 --- a/source/client/src/clientMain.c +++ b/source/client/src/clientMain.c @@ -677,6 +677,7 @@ static void destoryCatalogReq(SCatalogReq *pCatalogReq) { taosArrayDestroy(pCatalogReq->pIndex); taosArrayDestroy(pCatalogReq->pUser); taosArrayDestroy(pCatalogReq->pTableIndex); + taosArrayDestroy(pCatalogReq->pTableCfg); taosMemoryFree(pCatalogReq); } diff --git a/source/libs/parser/src/parInsertSql.c b/source/libs/parser/src/parInsertSql.c index 7a38f48cb2..411adc680c 100644 --- a/source/libs/parser/src/parInsertSql.c +++ b/source/libs/parser/src/parInsertSql.c @@ -1364,6 +1364,7 @@ static int32_t parseCsvFile(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, break; } } + taosMemoryFree(pLine); if (TSDB_CODE_SUCCESS == code && 0 == (*pNumOfRows) && (!TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT)) && !pStmt->fileProcessing) { From aa9e935854ed1074939fca7490f62de3077d3553 Mon Sep 17 00:00:00 2001 From: Liu Jicong Date: Mon, 14 Nov 2022 14:46:50 +0800 Subject: [PATCH 15/39] enh(stream): set path max length to 1024 --- source/libs/stream/src/streamState.c | 6 +++--- source/libs/wal/src/walWrite.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/libs/stream/src/streamState.c b/source/libs/stream/src/streamState.c index 88c39c1157..aefe30116b 100644 --- a/source/libs/stream/src/streamState.c +++ b/source/libs/stream/src/streamState.c @@ -114,12 +114,12 @@ SStreamState* streamStateOpen(char* path, SStreamTask* pTask, bool specPath, int return NULL; } - char statePath[300]; + char statePath[1024]; if (!specPath) { sprintf(statePath, "%s/%d", path, pTask->taskId); } else { - memset(statePath, 0, 300); - tstrncpy(statePath, path, 300); + memset(statePath, 0, 1024); + tstrncpy(statePath, path, 1024); } if (tdbOpen(statePath, szPage, pages, &pState->db, 0) < 0) { goto _err; diff --git a/source/libs/wal/src/walWrite.c b/source/libs/wal/src/walWrite.c index b683ba1926..7ced5fae39 100644 --- a/source/libs/wal/src/walWrite.c +++ b/source/libs/wal/src/walWrite.c @@ -319,7 +319,7 @@ int32_t walEndSnapshot(SWal *pWal) { SWalFileInfo *pInfo = taosArraySearch(pWal->fileInfoSet, &tmp, compareWalFileInfo, TD_LE); if (pInfo) { if (ver >= pInfo->lastVer) { - pInfo--; + pInfo++; } if (POINTER_DISTANCE(pInfo, pWal->fileInfoSet->pData) > 0) { wDebug("vgId:%d, begin remove from %" PRId64, pWal->cfg.vgId, pInfo->firstVer); From 7420b0aaafeb17da16436ca4587df0309f75e504 Mon Sep 17 00:00:00 2001 From: Minghao Li Date: Mon, 14 Nov 2022 15:24:59 +0800 Subject: [PATCH 16/39] fix(sync): fix memory error --- source/libs/sync/src/syncMain.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/libs/sync/src/syncMain.c b/source/libs/sync/src/syncMain.c index 7ed90fb140..5ceca36aac 100644 --- a/source/libs/sync/src/syncMain.c +++ b/source/libs/sync/src/syncMain.c @@ -1832,6 +1832,9 @@ static void syncNodeEqElectTimer(void* param, void* tmrId) { SElectTimer* pElectTimer = param; SSyncNode* pNode = pElectTimer->pSyncNode; + if (pNode == NULL) return; + if (pNode->syncEqMsg == NULL) return; + SRpcMsg rpcMsg = {0}; int32_t code = syncBuildTimeout(&rpcMsg, SYNC_TIMEOUT_ELECTION, pElectTimer->logicClock, pNode->electTimerMS, pNode); From c0463e46c97548ecb106340fbe22ba4d34a6a6bf Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Mon, 14 Nov 2022 15:48:01 +0800 Subject: [PATCH 17/39] fix: truncate show create table result --- include/common/tdatablock.h | 1 - include/libs/function/taosudf.h | 2 +- include/util/types.h | 8 +---- source/client/src/clientImpl.c | 4 --- source/common/src/tdatablock.c | 38 -------------------- source/libs/command/src/command.c | 58 +++++++++++++++---------------- 6 files changed, 31 insertions(+), 80 deletions(-) diff --git a/include/common/tdatablock.h b/include/common/tdatablock.h index 2dc1ca821f..502ba10d33 100644 --- a/include/common/tdatablock.h +++ b/include/common/tdatablock.h @@ -186,7 +186,6 @@ static FORCE_INLINE void colDataAppendDouble(SColumnInfoData* pColumnInfoData, u int32_t getJsonValueLen(const char* data); -int32_t colDataLenAppend(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData, uint32_t dataLen); int32_t colDataAppend(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData, bool isNull); int32_t colDataAppendNItems(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData, uint32_t numOfRows); diff --git a/include/libs/function/taosudf.h b/include/libs/function/taosudf.h index d79a569944..5f57e203b9 100644 --- a/include/libs/function/taosudf.h +++ b/include/libs/function/taosudf.h @@ -104,7 +104,7 @@ typedef int32_t (*TUdfDestroyFunc)(); } while (0) #define udfColDataSetNull_var(pColumn, row) ((pColumn->colData.varLenCol.varOffsets)[row] = -1) -typedef int16_t VarDataLenT; // maxVarDataLen: 32767 +typedef uint16_t VarDataLenT; // maxVarDataLen: 65535 #define VARSTR_HEADER_SIZE sizeof(VarDataLenT) #define varDataLen(v) ((VarDataLenT *)(v))[0] #define varDataVal(v) ((char *)(v) + VARSTR_HEADER_SIZE) diff --git a/include/util/types.h b/include/util/types.h index 21a529559a..b49670220b 100644 --- a/include/util/types.h +++ b/include/util/types.h @@ -78,7 +78,7 @@ static FORCE_INLINE double taos_align_get_double(const char *pBuf) { { (*(double *)(x)) = (*(double *)(y)); } // #endif -typedef int16_t VarDataLenT; // maxVarDataLen: 32767 +typedef uint16_t VarDataLenT; // maxVarDataLen: 65535 #define VARSTR_HEADER_SIZE sizeof(VarDataLenT) #define varDataLen(v) ((VarDataLenT *)(v))[0] @@ -87,12 +87,6 @@ typedef int16_t VarDataLenT; // maxVarDataLen: 32767 #define NCHAR_WIDTH_TO_BYTES(n) ((n)*TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE) -typedef uint32_t extVarDataLenT; -#define EXTVARSTR_HEADER_SIZE (VARSTR_HEADER_SIZE + sizeof(extVarDataLenT)) -#define extVarDataLen(v) ((*(VarDataLenT *)(v)) == -1 ? (*(extVarDataLenT*)(((VarDataLenT *)(v)) + 1)) : (*(VarDataLenT *)(v))) -#define extVarDataVal(v) ((char *)(v) + EXTVARSTR_HEADER_SIZE) -#define setExtVarDataLen(v, l) do { *(VarDataLenT *)(v) = -1; *(extVarDataLenT*)(((VarDataLenT *)(v)) + 1) = (l); } while (0) - typedef int32_t VarDataOffsetT; typedef struct tstr { diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index 3b8270b7e5..c3140371c4 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -1482,10 +1482,6 @@ void doSetOneRowPtr(SReqResultInfo* pResultInfo) { pResultInfo->length[i] = varDataLen(pStart); pResultInfo->row[i] = varDataVal(pStart); - if (-1 == pResultInfo->length[i]) { - pResultInfo->length[i] = extVarDataLen(pStart); - pResultInfo->row[i] = extVarDataVal(pStart); - } } else { pResultInfo->row[i] = NULL; pResultInfo->length[i] = 0; diff --git a/source/common/src/tdatablock.c b/source/common/src/tdatablock.c index ce4fa1f909..536cbed33e 100644 --- a/source/common/src/tdatablock.c +++ b/source/common/src/tdatablock.c @@ -62,44 +62,6 @@ int32_t getJsonValueLen(const char* data) { return dataLen; } -int32_t colDataLenAppend(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData, uint32_t dataLen) { - ASSERT(pColumnInfoData != NULL); - - int32_t type = pColumnInfoData->info.type; - if (IS_VAR_DATA_TYPE(type)) { - SVarColAttr* pAttr = &pColumnInfoData->varmeta; - if (pAttr->allocLen < pAttr->length + dataLen) { - uint32_t newSize = pAttr->allocLen; - if (newSize <= 1) { - newSize = 8; - } - - while (newSize < pAttr->length + dataLen) { - newSize = newSize * 1.5; - } - - char* buf = taosMemoryRealloc(pColumnInfoData->pData, newSize); - if (buf == NULL) { - return TSDB_CODE_OUT_OF_MEMORY; - } - - pColumnInfoData->pData = buf; - pAttr->allocLen = newSize; - } - - uint32_t len = pColumnInfoData->varmeta.length; - pColumnInfoData->varmeta.offset[currentRow] = len; - - memcpy(pColumnInfoData->pData + len, pData, dataLen); - pColumnInfoData->varmeta.length += dataLen; - } else { - memcpy(pColumnInfoData->pData + pColumnInfoData->info.bytes * currentRow, pData, pColumnInfoData->info.bytes); - } - - return 0; -} - - int32_t colDataAppend(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData, bool isNull) { ASSERT(pColumnInfoData != NULL); diff --git a/source/libs/command/src/command.c b/source/libs/command/src/command.c index 0625c23a7a..64fec145ef 100644 --- a/source/libs/command/src/command.c +++ b/source/libs/command/src/command.c @@ -330,7 +330,7 @@ void appendColumnFields(char* buf, int32_t* len, STableCfg* pCfg) { sprintf(type + strlen(type), "(%d)", (int32_t)((pSchema->bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE)); } - *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, "%s`%s` %s", ((i > 0) ? ", " : ""), pSchema->name, type); + *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "%s`%s` %s", ((i > 0) ? ", " : ""), pSchema->name, type); } } @@ -345,14 +345,14 @@ void appendTagFields(char* buf, int32_t* len, STableCfg* pCfg) { sprintf(type + strlen(type), "(%d)", (int32_t)((pSchema->bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE)); } - *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, "%s`%s` %s", ((i > 0) ? ", " : ""), pSchema->name, type); + *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "%s`%s` %s", ((i > 0) ? ", " : ""), pSchema->name, type); } } void appendTagNameFields(char* buf, int32_t* len, STableCfg* pCfg) { for (int32_t i = 0; i < pCfg->numOfTags; ++i) { SSchema* pSchema = pCfg->pSchemas + pCfg->numOfColumns + i; - *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, "%s`%s`", ((i > 0) ? ", " : ""), pSchema->name); + *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "%s`%s`", ((i > 0) ? ", " : ""), pSchema->name); } } @@ -368,7 +368,7 @@ int32_t appendTagValues(char* buf, int32_t* len, STableCfg* pCfg) { if (tTagIsJson(pTag)) { char* pJson = parseTagDatatoJson(pTag); if (pJson) { - *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, "%s", pJson); + *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "%s", pJson); taosMemoryFree(pJson); } @@ -386,11 +386,11 @@ int32_t appendTagValues(char* buf, int32_t* len, STableCfg* pCfg) { for (int32_t i = 0; i < pCfg->numOfTags; ++i) { SSchema* pSchema = pCfg->pSchemas + pCfg->numOfColumns + i; if (i > 0) { - *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, ", "); + *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, ", "); } if (j >= valueNum) { - *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, "NULL"); + *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "NULL"); continue; } @@ -404,14 +404,14 @@ int32_t appendTagValues(char* buf, int32_t* len, STableCfg* pCfg) { int32_t tlen = 0; if (IS_VAR_DATA_TYPE(type)) { - dataConverToStr(buf + EXTVARSTR_HEADER_SIZE + *len, type, pTagVal->pData, pTagVal->nData, &tlen); + dataConverToStr(buf + VARSTR_HEADER_SIZE + *len, type, pTagVal->pData, pTagVal->nData, &tlen); } else { - dataConverToStr(buf + EXTVARSTR_HEADER_SIZE + *len, type, &pTagVal->i64, tDataTypes[type].bytes, &tlen); + dataConverToStr(buf + VARSTR_HEADER_SIZE + *len, type, &pTagVal->i64, tDataTypes[type].bytes, &tlen); } *len += tlen; j++; } else { - *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, "NULL"); + *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "NULL"); } /* @@ -450,37 +450,37 @@ int32_t appendTagValues(char* buf, int32_t* len, STableCfg* pCfg) { void appendTableOptions(char* buf, int32_t* len, SDbCfgInfo* pDbCfg, STableCfg* pCfg) { if (pCfg->commentLen > 0) { - *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, " COMMENT '%s'", pCfg->pComment); + *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, " COMMENT '%s'", pCfg->pComment); } else if (0 == pCfg->commentLen) { - *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, " COMMENT ''"); + *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, " COMMENT ''"); } if (NULL != pDbCfg->pRetensions && pCfg->watermark1 > 0) { - *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, " WATERMARK %" PRId64 "a", pCfg->watermark1); + *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, " WATERMARK %" PRId64 "a", pCfg->watermark1); if (pCfg->watermark2 > 0) { - *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, ", %" PRId64 "a", pCfg->watermark2); + *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, ", %" PRId64 "a", pCfg->watermark2); } } if (NULL != pDbCfg->pRetensions && pCfg->delay1 > 0) { - *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, " MAX_DELAY %" PRId64 "a", pCfg->delay1); + *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, " MAX_DELAY %" PRId64 "a", pCfg->delay1); if (pCfg->delay2 > 0) { - *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, ", %" PRId64 "a", pCfg->delay2); + *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, ", %" PRId64 "a", pCfg->delay2); } } int32_t funcNum = taosArrayGetSize(pCfg->pFuncs); if (NULL != pDbCfg->pRetensions && funcNum > 0) { - *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, " ROLLUP("); + *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, " ROLLUP("); for (int32_t i = 0; i < funcNum; ++i) { char* pFunc = taosArrayGet(pCfg->pFuncs, i); - *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, "%s%s", ((i > 0) ? ", " : ""), pFunc); + *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "%s%s", ((i > 0) ? ", " : ""), pFunc); } - *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, ")"); + *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, ")"); } if (pCfg->ttl > 0) { - *len += sprintf(buf + EXTVARSTR_HEADER_SIZE + *len, " TTL %d", pCfg->ttl); + *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, " TTL %d", pCfg->ttl); } } @@ -504,33 +504,33 @@ static int32_t setCreateTBResultIntoDataBlock(SSDataBlock* pBlock, SDbCfgInfo* p int32_t len = 0; if (TSDB_SUPER_TABLE == pCfg->tableType) { - len += sprintf(buf2 + EXTVARSTR_HEADER_SIZE, "CREATE STABLE `%s` (", tbName); + len += sprintf(buf2 + VARSTR_HEADER_SIZE, "CREATE STABLE `%s` (", tbName); appendColumnFields(buf2, &len, pCfg); - len += sprintf(buf2 + EXTVARSTR_HEADER_SIZE + len, ") TAGS ("); + len += sprintf(buf2 + VARSTR_HEADER_SIZE + len, ") TAGS ("); appendTagFields(buf2, &len, pCfg); - len += sprintf(buf2 + EXTVARSTR_HEADER_SIZE + len, ")"); + len += sprintf(buf2 + VARSTR_HEADER_SIZE + len, ")"); appendTableOptions(buf2, &len, pDbCfg, pCfg); } else if (TSDB_CHILD_TABLE == pCfg->tableType) { - len += sprintf(buf2 + EXTVARSTR_HEADER_SIZE, "CREATE TABLE `%s` USING `%s` (", tbName, pCfg->stbName); + len += sprintf(buf2 + VARSTR_HEADER_SIZE, "CREATE TABLE `%s` USING `%s` (", tbName, pCfg->stbName); appendTagNameFields(buf2, &len, pCfg); - len += sprintf(buf2 + EXTVARSTR_HEADER_SIZE + len, ") TAGS ("); + len += sprintf(buf2 + VARSTR_HEADER_SIZE + len, ") TAGS ("); code = appendTagValues(buf2, &len, pCfg); if (code) { taosMemoryFree(buf2); return code; } - len += sprintf(buf2 + EXTVARSTR_HEADER_SIZE + len, ")"); + len += sprintf(buf2 + VARSTR_HEADER_SIZE + len, ")"); appendTableOptions(buf2, &len, pDbCfg, pCfg); } else { - len += sprintf(buf2 + EXTVARSTR_HEADER_SIZE, "CREATE TABLE `%s` (", tbName); + len += sprintf(buf2 + VARSTR_HEADER_SIZE, "CREATE TABLE `%s` (", tbName); appendColumnFields(buf2, &len, pCfg); - len += sprintf(buf2 + EXTVARSTR_HEADER_SIZE + len, ")"); + len += sprintf(buf2 + VARSTR_HEADER_SIZE + len, ")"); appendTableOptions(buf2, &len, pDbCfg, pCfg); } - setExtVarDataLen(buf2, len); + varDataLen(buf2) = (len > 65535) ? 65535 : len; - colDataLenAppend(pCol2, 0, buf2, len + EXTVARSTR_HEADER_SIZE); + colDataAppend(pCol2, 0, buf2, false); taosMemoryFree(buf2); From 9b58176c5872175082470264a27d9e1b7c2cff35 Mon Sep 17 00:00:00 2001 From: Minghao Li Date: Mon, 14 Nov 2022 15:56:34 +0800 Subject: [PATCH 18/39] fix(sync): fix AddressSanitizer error: TD-20372 --- source/libs/sync/src/syncMain.c | 5 ++++- source/libs/sync/src/syncRaftLog.c | 13 +++++++++++-- source/libs/sync/src/syncReplication.c | 4 +++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/source/libs/sync/src/syncMain.c b/source/libs/sync/src/syncMain.c index 7ed90fb140..8bccf6840a 100644 --- a/source/libs/sync/src/syncMain.c +++ b/source/libs/sync/src/syncMain.c @@ -385,7 +385,7 @@ bool syncIsReadyForRead(int64_t rid) { if (!pSyncNode->pLogStore->syncLogIsEmpty(pSyncNode->pLogStore)) { SSyncRaftEntry* pEntry = NULL; int32_t code = pSyncNode->pLogStore->syncLogGetEntry( - pSyncNode->pLogStore, pSyncNode->pLogStore->syncLogLastIndex(pSyncNode->pLogStore), &pEntry); + pSyncNode->pLogStore, pSyncNode->pLogStore->syncLogLastIndex(pSyncNode->pLogStore), &pEntry); if (code == 0 && pEntry != NULL) { if (pEntry->originalRpcType == TDMT_SYNC_NOOP && pEntry->term == pSyncNode->pRaftStore->currentTerm) { ready = true; @@ -1832,6 +1832,9 @@ static void syncNodeEqElectTimer(void* param, void* tmrId) { SElectTimer* pElectTimer = param; SSyncNode* pNode = pElectTimer->pSyncNode; + if (pNode == NULL) return; + if (pNode->syncEqMsg == NULL) return; + SRpcMsg rpcMsg = {0}; int32_t code = syncBuildTimeout(&rpcMsg, SYNC_TIMEOUT_ELECTION, pElectTimer->logicClock, pNode->electTimerMS, pNode); diff --git a/source/libs/sync/src/syncRaftLog.c b/source/libs/sync/src/syncRaftLog.c index 7e4b18ab88..bc07781e5c 100644 --- a/source/libs/sync/src/syncRaftLog.c +++ b/source/libs/sync/src/syncRaftLog.c @@ -197,7 +197,12 @@ static int32_t raftLogAppendEntry(struct SSyncLogStore* pLogStore, SSyncRaftEntr syncMeta.isWeek = pEntry->isWeak; syncMeta.seqNum = pEntry->seqNum; syncMeta.term = pEntry->term; + + int64_t tsWriteBegin = taosGetTimestampMs(); index = walAppendLog(pWal, pEntry->originalRpcType, syncMeta, pEntry->data, pEntry->dataLen); + int64_t tsWriteEnd = taosGetTimestampMs(); + int64_t tsElapsed = tsWriteEnd - tsWriteBegin; + if (index < 0) { int32_t err = terrno; const char* errStr = tstrerror(err); @@ -210,8 +215,8 @@ static int32_t raftLogAppendEntry(struct SSyncLogStore* pLogStore, SSyncRaftEntr } pEntry->index = index; - sNTrace(pData->pSyncNode, "write index:%" PRId64 ", type:%s, origin type:%s", pEntry->index, - TMSG_INFO(pEntry->msgType), TMSG_INFO(pEntry->originalRpcType)); + sNTrace(pData->pSyncNode, "write index:%" PRId64 ", type:%s, origin type:%s, elapsed:%" PRId64, pEntry->index, + TMSG_INFO(pEntry->msgType), TMSG_INFO(pEntry->originalRpcType), tsElapsed); return 0; } @@ -236,7 +241,11 @@ int32_t raftLogGetEntry(struct SSyncLogStore* pLogStore, SyncIndex index, SSyncR taosThreadMutexLock(&(pData->mutex)); + int64_t tsBegin = taosGetTimestampMs(); code = walReadVer(pWalHandle, index); + int64_t tsEnd = taosGetTimestampMs(); + int64_t tsElapsed = tsEnd - tsBegin; + // code = walReadVerCached(pWalHandle, index); if (code != 0) { int32_t err = terrno; diff --git a/source/libs/sync/src/syncReplication.c b/source/libs/sync/src/syncReplication.c index 25d6474f67..59afe814eb 100644 --- a/source/libs/sync/src/syncReplication.c +++ b/source/libs/sync/src/syncReplication.c @@ -153,14 +153,16 @@ int32_t syncNodeSendAppendEntries(SSyncNode* pSyncNode, const SRaftId* destRaftI // save index, otherwise pMsg will be free by rpc SyncIndex saveLastSendIndex = pState->lastSendIndex; + bool update = false; if (pMsg->dataLen > 0) { saveLastSendIndex = pMsg->prevLogIndex + 1; + update = true; } syncLogSendAppendEntries(pSyncNode, pMsg, ""); syncNodeSendMsgById(destRaftId, pSyncNode, pRpcMsg); - if (pMsg->dataLen > 0) { + if (update) { pState->lastSendIndex = saveLastSendIndex; pState->lastSendTime = taosGetTimestampMs(); } From c0ad5b838be1bd79016f5f7c279a2cb32acffa79 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Mon, 14 Nov 2022 15:23:19 +0800 Subject: [PATCH 19/39] test: add asan cases --- source/dnode/mnode/impl/src/mndQuery.c | 6 ++-- tests/parallel_test/cases.task | 44 +++++++++++++------------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/source/dnode/mnode/impl/src/mndQuery.c b/source/dnode/mnode/impl/src/mndQuery.c index 2b0edfebc2..3a7c25f7f9 100644 --- a/source/dnode/mnode/impl/src/mndQuery.c +++ b/source/dnode/mnode/impl/src/mndQuery.c @@ -178,8 +178,10 @@ int32_t mndProcessBatchMetaMsg(SRpcMsg *pMsg) { offset += sizeof(p->msgLen); *(int32_t *)((char *)pRsp + offset) = htonl(p->rspCode); offset += sizeof(p->rspCode); - memcpy((char *)pRsp + offset, p->msg, p->msgLen); - offset += p->msgLen; + if (p->msg != NULL) { + memcpy((char *)pRsp + offset, p->msg, p->msgLen); + offset += p->msgLen; + } rpcFreeCont(p->msg); } diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task index 5baa442231..48215b1d47 100644 --- a/tests/parallel_test/cases.task +++ b/tests/parallel_test/cases.task @@ -9,7 +9,7 @@ ,,y,script,./test.sh -f tsim/user/basic.sim ,,y,script,./test.sh -f tsim/user/password.sim ,,y,script,./test.sh -f tsim/user/privilege_db.sim -,,,script,./test.sh -f tsim/user/privilege_sysinfo.sim +,,y,script,./test.sh -f tsim/user/privilege_sysinfo.sim ,,,script,./test.sh -f tsim/db/alter_option.sim ,,,script,./test.sh -f tsim/db/alter_replica_13.sim ,,,script,./test.sh -f tsim/db/alter_replica_31.sim @@ -23,16 +23,16 @@ ,,,script,./test.sh -f tsim/db/create_all_options.sim ,,y,script,./test.sh -f tsim/db/delete_reuse1.sim ,,y,script,./test.sh -f tsim/db/delete_reuse2.sim -,,,script,./test.sh -f tsim/db/delete_reusevnode.sim +,,y,script,./test.sh -f tsim/db/delete_reusevnode.sim ,,y,script,./test.sh -f tsim/db/delete_reusevnode2.sim -,,,script,./test.sh -f tsim/db/delete_writing1.sim -,,,script,./test.sh -f tsim/db/delete_writing2.sim +,,y,script,./test.sh -f tsim/db/delete_writing1.sim +,,y,script,./test.sh -f tsim/db/delete_writing2.sim ,,y,script,./test.sh -f tsim/db/error1.sim ,,y,script,./test.sh -f tsim/db/keep.sim ,,y,script,./test.sh -f tsim/db/len.sim ,,y,script,./test.sh -f tsim/db/repeat.sim ,,y,script,./test.sh -f tsim/db/show_create_db.sim -,,,script,./test.sh -f tsim/db/show_create_table.sim +,,y,script,./test.sh -f tsim/db/show_create_table.sim ,,y,script,./test.sh -f tsim/db/tables.sim ,,y,script,./test.sh -f tsim/db/taosdlog.sim ,,,script,./test.sh -f tsim/dnode/balance_replica1.sim @@ -80,8 +80,8 @@ ,,y,script,./test.sh -f tsim/insert/query_multi_file.sim ,,y,script,./test.sh -f tsim/insert/tcp.sim ,,y,script,./test.sh -f tsim/insert/update0.sim -,,,script,./test.sh -f tsim/insert/update1_sort_merge.sim -,,,script,./test.sh -f tsim/parser/alter__for_community_version.sim +,,y,script,./test.sh -f tsim/insert/update1_sort_merge.sim +,,y,script,./test.sh -f tsim/parser/alter__for_community_version.sim ,,y,script,./test.sh -f tsim/parser/alter_column.sim ,,y,script,./test.sh -f tsim/parser/alter_stable.sim ,,y,script,./test.sh -f tsim/parser/alter.sim @@ -92,21 +92,21 @@ ,,y,script,./test.sh -f tsim/parser/binary_escapeCharacter.sim ,,,script,./test.sh -f tsim/parser/col_arithmetic_operation.sim ,,y,script,./test.sh -f tsim/parser/columnValue_bigint.sim -,,,script,./test.sh -f tsim/parser/columnValue_bool.sim +,,y,script,./test.sh -f tsim/parser/columnValue_bool.sim ,,y,script,./test.sh -f tsim/parser/columnValue_double.sim ,,y,script,./test.sh -f tsim/parser/columnValue_float.sim ,,y,script,./test.sh -f tsim/parser/columnValue_int.sim ,,y,script,./test.sh -f tsim/parser/columnValue_smallint.sim ,,y,script,./test.sh -f tsim/parser/columnValue_tinyint.sim ,,,script,./test.sh -f tsim/parser/columnValue_unsign.sim -,,,script,./test.sh -f tsim/parser/commit.sim -,,,script,./test.sh -f tsim/parser/condition.sim +,,y,script,./test.sh -f tsim/parser/commit.sim +,,y,script,./test.sh -f tsim/parser/condition.sim ,,y,script,./test.sh -f tsim/parser/constCol.sim -,,,script,./test.sh -f tsim/parser/create_db.sim -,,,script,./test.sh -f tsim/parser/create_mt.sim +,,y,script,./test.sh -f tsim/parser/create_db.sim +,,y,script,./test.sh -f tsim/parser/create_mt.sim ,,y,script,./test.sh -f tsim/parser/create_tb_with_tag_name.sim ,,y,script,./test.sh -f tsim/parser/create_tb.sim -,,,script,./test.sh -f tsim/parser/dbtbnameValidate.sim +,,y,script,./test.sh -f tsim/parser/dbtbnameValidate.sim ,,y,script,./test.sh -f tsim/parser/distinct.sim ,,y,script,./test.sh -f tsim/parser/fill_us.sim ,,,script,./test.sh -f tsim/parser/fill.sim @@ -120,9 +120,9 @@ ,,y,script,./test.sh -f tsim/parser/import_commit1.sim ,,y,script,./test.sh -f tsim/parser/import_commit2.sim ,,y,script,./test.sh -f tsim/parser/import_commit3.sim -,,,script,./test.sh -f tsim/parser/import_file.sim +,,y,script,./test.sh -f tsim/parser/import_file.sim ,,y,script,./test.sh -f tsim/parser/import.sim -,,,script,./test.sh -f tsim/parser/insert_multiTbl.sim +,,y,script,./test.sh -f tsim/parser/insert_multiTbl.sim ,,y,script,./test.sh -f tsim/parser/insert_tb.sim ,,,script,./test.sh -f tsim/parser/join_manyblocks.sim ,,y,script,./test.sh -f tsim/parser/join_multitables.sim @@ -131,12 +131,12 @@ ,,y,script,./test.sh -f tsim/parser/last_cache.sim ,,y,script,./test.sh -f tsim/parser/last_groupby.sim ,,y,script,./test.sh -f tsim/parser/lastrow.sim -,,,script,./test.sh -f tsim/parser/lastrow2.sim +,,y,script,./test.sh -f tsim/parser/lastrow2.sim ,,y,script,./test.sh -f tsim/parser/like.sim ,,,script,./test.sh -f tsim/parser/limit.sim ,,,script,./test.sh -f tsim/parser/limit1.sim ,,y,script,./test.sh -f tsim/parser/mixed_blocks.sim -,,,script,./test.sh -f tsim/parser/nchar.sim +,,y,script,./test.sh -f tsim/parser/nchar.sim ,,,script,./test.sh -f tsim/parser/nestquery.sim ,,,script,./test.sh -f tsim/parser/null_char.sim ,,y,script,./test.sh -f tsim/parser/precision_ns.sim @@ -146,7 +146,7 @@ ,,y,script,./test.sh -f tsim/parser/select_distinct_tag.sim ,,y,script,./test.sh -f tsim/parser/select_from_cache_disk.sim ,,y,script,./test.sh -f tsim/parser/select_with_tags.sim -,,,script,./test.sh -f tsim/parser/selectResNum.sim +,,y,script,./test.sh -f tsim/parser/selectResNum.sim ,,,script,./test.sh -f tsim/parser/set_tag_vals.sim ,,y,script,./test.sh -f tsim/parser/single_row_in_tb.sim ,,,script,./test.sh -f tsim/parser/sliding.sim @@ -271,7 +271,7 @@ ,,y,script,./test.sh -f tsim/stable/tag_filter.sim ,,y,script,./test.sh -f tsim/stable/tag_modify.sim ,,y,script,./test.sh -f tsim/stable/tag_rename.sim -,,,script,./test.sh -f tsim/stable/values.sim +,,y,script,./test.sh -f tsim/stable/values.sim ,,y,script,./test.sh -f tsim/stable/vnode3.sim ,,y,script,./test.sh -f tsim/stable/metrics_idx.sim ,,,script,./test.sh -f tsim/sma/drop_sma.sim @@ -325,7 +325,7 @@ ,,y,script,./test.sh -f tsim/compute/bottom.sim ,,y,script,./test.sh -f tsim/compute/count.sim ,,y,script,./test.sh -f tsim/compute/diff.sim -,,,script,./test.sh -f tsim/compute/diff2.sim +,,y,script,./test.sh -f tsim/compute/diff2.sim ,,y,script,./test.sh -f tsim/compute/first.sim ,,y,script,./test.sh -f tsim/compute/interval.sim ,,y,script,./test.sh -f tsim/compute/last_row.sim @@ -358,7 +358,7 @@ ,,y,script,./test.sh -f tsim/vector/metrics_query.sim ,,y,script,./test.sh -f tsim/vector/metrics_tag.sim ,,y,script,./test.sh -f tsim/vector/metrics_time.sim -,,,script,./test.sh -f tsim/vector/multi.sim +,,y,script,./test.sh -f tsim/vector/multi.sim ,,y,script,./test.sh -f tsim/vector/single.sim ,,y,script,./test.sh -f tsim/vector/table_field.sim ,,y,script,./test.sh -f tsim/vector/table_mix.sim @@ -380,7 +380,7 @@ ,,y,script,./test.sh -f tsim/tag/column.sim ,,y,script,./test.sh -f tsim/tag/commit.sim ,,y,script,./test.sh -f tsim/tag/create.sim -,,,script,./test.sh -f tsim/tag/delete.sim +,,y,script,./test.sh -f tsim/tag/delete.sim ,,y,script,./test.sh -f tsim/tag/double.sim ,,y,script,./test.sh -f tsim/tag/filter.sim ,,y,script,./test.sh -f tsim/tag/float.sim From 8f55e007f4f3a8f98309b7fa9df9f28666f015ca Mon Sep 17 00:00:00 2001 From: Minghao Li Date: Mon, 14 Nov 2022 16:23:52 +0800 Subject: [PATCH 20/39] refactor(sync): add trace log --- source/libs/sync/src/syncRaftLog.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/source/libs/sync/src/syncRaftLog.c b/source/libs/sync/src/syncRaftLog.c index bc07781e5c..21f301308e 100644 --- a/source/libs/sync/src/syncRaftLog.c +++ b/source/libs/sync/src/syncRaftLog.c @@ -239,12 +239,12 @@ int32_t raftLogGetEntry(struct SSyncLogStore* pLogStore, SyncIndex index, SSyncR return -1; } + int64_t ts1 = taosGetTimestampMs(); taosThreadMutexLock(&(pData->mutex)); - int64_t tsBegin = taosGetTimestampMs(); + int64_t ts2 = taosGetTimestampMs(); code = walReadVer(pWalHandle, index); - int64_t tsEnd = taosGetTimestampMs(); - int64_t tsElapsed = tsEnd - tsBegin; + int64_t ts3 = taosGetTimestampMs(); // code = walReadVerCached(pWalHandle, index); if (code != 0) { @@ -289,6 +289,18 @@ int32_t raftLogGetEntry(struct SSyncLogStore* pLogStore, SyncIndex index, SSyncR */ taosThreadMutexUnlock(&(pData->mutex)); + int64_t ts4 = taosGetTimestampMs(); + + int64_t tsElapsed = ts4 - ts1; + int64_t tsElapsedLock = ts2 - ts1; + int64_t tsElapsedRead = ts3 - ts2; + int64_t tsElapsedBuild = ts4 - ts3; + + sNTrace(pData->pSyncNode, + "read index:%" PRId64 ", elapsed:%" PRId64 ", elapsed-lock:%" PRId64 ", elapsed-read:%" PRId64 + ", elapsed-build:%" PRId64, + index, tsElapsed, tsElapsedLock, tsElapsedRead, tsElapsedBuild); + return code; } From 1d795f5c62e4102c45b6263a234b74c5a08f7283 Mon Sep 17 00:00:00 2001 From: Cary Xu Date: Mon, 14 Nov 2022 16:27:02 +0800 Subject: [PATCH 21/39] fix: null pointer when merge col data of varchar --- source/common/src/tdatablock.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/common/src/tdatablock.c b/source/common/src/tdatablock.c index e8d5989e4d..f7b1196248 100644 --- a/source/common/src/tdatablock.c +++ b/source/common/src/tdatablock.c @@ -277,7 +277,9 @@ int32_t colDataMergeCol(SColumnInfoData* pColumnInfoData, int32_t numOfRow1, int pColumnInfoData->varmeta.allocLen = len + oldLen; } - memcpy(pColumnInfoData->pData + oldLen, pSource->pData, len); + if (pColumnInfoData->pData && pSource->pData) { // TD-20382 + memcpy(pColumnInfoData->pData + oldLen, pSource->pData, len); + } pColumnInfoData->varmeta.length = len + oldLen; } else { if (finalNumOfRows > (*capacity)) { From 349189a696e0b31fad95eba5840d9a4fdf120139 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Mon, 14 Nov 2022 16:39:25 +0800 Subject: [PATCH 22/39] fix: ingore tree.c error found by asan --- tests/parallel_test/cases.task | 2 +- tests/script/sh/checkAsan.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task index 5baa442231..31b21e3465 100644 --- a/tests/parallel_test/cases.task +++ b/tests/parallel_test/cases.task @@ -392,7 +392,7 @@ ,,y,script,./test.sh -f tsim/tag/tinyint.sim ,,y,script,./test.sh -f tsim/tag/drop_tag.sim ,,y,script,./test.sh -f tsim/tag/tbNameIn.sim -,,,script,./test.sh -f tmp/monitor.sim +,,y,script,./test.sh -f tmp/monitor.sim #system test diff --git a/tests/script/sh/checkAsan.sh b/tests/script/sh/checkAsan.sh index 4d1b0a3d6b..184dc9a88f 100755 --- a/tests/script/sh/checkAsan.sh +++ b/tests/script/sh/checkAsan.sh @@ -20,7 +20,7 @@ LOG_DIR=$TAOS_DIR/sim/tsim/asan error_num=`cat ${LOG_DIR}/*.asan | grep "ERROR" | wc -l` memory_leak=`cat ${LOG_DIR}/*.asan | grep "Direct leak" | wc -l` indirect_leak=`cat ${LOG_DIR}/*.asan | grep "Indirect leak" | wc -l` -runtime_error=`cat ${LOG_DIR}/*.asan | grep "runtime error" | wc -l` +runtime_error=`cat ${LOG_DIR}/*.asan | grep "runtime error" | grep -v "trees.c:873" | wc -l` echo -e "\033[44;32;1m"asan error_num: $error_num"\033[0m" echo -e "\033[44;32;1m"asan memory_leak: $memory_leak"\033[0m" From 5b51f97a48038ca6b9f8d70f246862ba11bf4f96 Mon Sep 17 00:00:00 2001 From: Hongze Cheng Date: Mon, 14 Nov 2022 16:52:39 +0800 Subject: [PATCH 23/39] more optimize --- source/dnode/vnode/src/inc/tsdb.h | 17 +++++------- source/dnode/vnode/src/tsdb/tsdbMemTable.c | 31 ++++++++++++++-------- source/dnode/vnode/src/tsdb/tsdbUtil.c | 20 +++++++------- 3 files changed, 36 insertions(+), 32 deletions(-) diff --git a/source/dnode/vnode/src/inc/tsdb.h b/source/dnode/vnode/src/inc/tsdb.h index ba9d68ee7f..c6e2842c32 100644 --- a/source/dnode/vnode/src/inc/tsdb.h +++ b/source/dnode/vnode/src/inc/tsdb.h @@ -108,8 +108,8 @@ static FORCE_INLINE int64_t tsdbLogicToFileSize(int64_t lSize, int32_t szPage) { #define TSDBROW_KEY(ROW) ((TSDBKEY){.version = TSDBROW_VERSION(ROW), .ts = TSDBROW_TS(ROW)}) #define tsdbRowFromTSRow(VERSION, TSROW) ((TSDBROW){.type = 0, .version = (VERSION), .pTSRow = (TSROW)}) #define tsdbRowFromBlockData(BLOCKDATA, IROW) ((TSDBROW){.type = 1, .pBlockData = (BLOCKDATA), .iRow = (IROW)}) -void tsdbRowGetColVal(TSDBROW *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal); -int32_t tPutTSDBRow(uint8_t *p, TSDBROW *pRow); +void tsdbRowGetColVal(TSDBROW *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal); +// int32_t tPutTSDBRow(uint8_t *p, TSDBROW *pRow); int32_t tsdbRowCmprFn(const void *p1, const void *p2); // SRowIter void tRowIterInit(SRowIter *pIter, TSDBROW *pRow, STSchema *pTSchema); @@ -333,6 +333,8 @@ struct SVersionRange { typedef struct SMemSkipListNode SMemSkipListNode; struct SMemSkipListNode { int8_t level; + int64_t version; + STSRow *pTSRow; SMemSkipListNode *forwards[0]; }; typedef struct SMemSkipList { @@ -772,14 +774,6 @@ static FORCE_INLINE int32_t tsdbKeyCmprFn(const void *p1, const void *p2) { #define SL_NODE_FORWARD(n, l) ((n)->forwards[l]) #define SL_NODE_BACKWARD(n, l) ((n)->forwards[(n)->level + (l)]) -#define SL_NODE_DATA(n) (&SL_NODE_BACKWARD(n, (n)->level)) - -static FORCE_INLINE int32_t tGetTSDBRow(uint8_t *p, TSDBROW *pRow) { - int32_t n = tGetI64(p, &pRow->version); - pRow->pTSRow = (STSRow *)(p + n); - n += pRow->pTSRow->len; - return n; -} static FORCE_INLINE TSDBROW *tsdbTbDataIterGet(STbDataIter *pIter) { if (pIter == NULL) return NULL; @@ -798,8 +792,9 @@ static FORCE_INLINE TSDBROW *tsdbTbDataIterGet(STbDataIter *pIter) { } } - tGetTSDBRow((uint8_t *)SL_NODE_DATA(pIter->pNode), &pIter->row); pIter->pRow = &pIter->row; + pIter->pRow->version = pIter->pNode->version; + pIter->pRow->pTSRow = pIter->pNode->pTSRow; return pIter->pRow; } diff --git a/source/dnode/vnode/src/tsdb/tsdbMemTable.c b/source/dnode/vnode/src/tsdb/tsdbMemTable.c index 654afe1b6a..998409f34e 100644 --- a/source/dnode/vnode/src/tsdb/tsdbMemTable.c +++ b/source/dnode/vnode/src/tsdb/tsdbMemTable.c @@ -21,7 +21,6 @@ #define SL_NODE_SIZE(l) (sizeof(SMemSkipListNode) + sizeof(SMemSkipListNode *) * (l)*2) #define SL_NODE_FORWARD(n, l) ((n)->forwards[l]) #define SL_NODE_BACKWARD(n, l) ((n)->forwards[(n)->level + (l)]) -#define SL_NODE_DATA(n) (&SL_NODE_BACKWARD(n, (n)->level)) #define SL_MOVE_BACKWARD 0x1 #define SL_MOVE_FROM_POS 0x2 @@ -394,7 +393,7 @@ _err: static void tbDataMovePosTo(STbData *pTbData, SMemSkipListNode **pos, TSDBKEY *pKey, int32_t flags) { SMemSkipListNode *px; SMemSkipListNode *pn; - TSDBKEY *pTKey; + TSDBKEY tKey = {0}; int32_t backward = flags & SL_MOVE_BACKWARD; int32_t fromPos = flags & SL_MOVE_FROM_POS; @@ -413,9 +412,10 @@ static void tbDataMovePosTo(STbData *pTbData, SMemSkipListNode **pos, TSDBKEY *p for (int8_t iLevel = pTbData->sl.level - 1; iLevel >= 0; iLevel--) { pn = SL_NODE_BACKWARD(px, iLevel); while (pn != pTbData->sl.pHead) { - pTKey = (TSDBKEY *)SL_NODE_DATA(pn); + tKey.version = pn->version; + tKey.ts = pn->pTSRow->ts; - int32_t c = tsdbKeyCmprFn(pTKey, pKey); + int32_t c = tsdbKeyCmprFn(&tKey, pKey); if (c <= 0) { break; } else { @@ -442,7 +442,10 @@ static void tbDataMovePosTo(STbData *pTbData, SMemSkipListNode **pos, TSDBKEY *p for (int8_t iLevel = pTbData->sl.level - 1; iLevel >= 0; iLevel--) { pn = SL_NODE_FORWARD(px, iLevel); while (pn != pTbData->sl.pTail) { - int32_t c = tsdbKeyCmprFn(SL_NODE_DATA(pn), pKey); + tKey.version = pn->version; + tKey.ts = pn->pTSRow->ts; + + int32_t c = tsdbKeyCmprFn(&tKey, pKey); if (c >= 0) { break; } else { @@ -467,8 +470,8 @@ static FORCE_INLINE int8_t tsdbMemSkipListRandLevel(SMemSkipList *pSl) { return level; } -static int32_t tbDataDoPut(SMemTable *pMemTable, STbData *pTbData, SMemSkipListNode **pos, TSDBROW *pRow, - int8_t forward) { +static int32_t tbDataDoPut(SMemTable *pMemTable, STbData *pTbData, SMemSkipListNode **pos, int64_t version, + STSRow *pRow, int8_t forward) { int32_t code = 0; int8_t level; SMemSkipListNode *pNode; @@ -477,13 +480,19 @@ static int32_t tbDataDoPut(SMemTable *pMemTable, STbData *pTbData, SMemSkipListN // node level = tsdbMemSkipListRandLevel(&pTbData->sl); ASSERT(pPool != NULL); - pNode = (SMemSkipListNode *)vnodeBufPoolMalloc(pPool, SL_NODE_SIZE(level) + tPutTSDBRow(NULL, pRow)); + pNode = (SMemSkipListNode *)vnodeBufPoolMalloc(pPool, SL_NODE_SIZE(level)); if (pNode == NULL) { code = TSDB_CODE_OUT_OF_MEMORY; goto _exit; } pNode->level = level; - tPutTSDBRow((uint8_t *)SL_NODE_DATA(pNode), pRow); + pNode->version = version; + pNode->pTSRow = vnodeBufPoolMalloc(pPool, pRow->len); + if (NULL == pNode->pTSRow) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + memcpy(pNode->pTSRow, pRow, pRow->len); for (int8_t iLevel = level - 1; iLevel >= 0; iLevel--) { SMemSkipListNode *pn = pos[iLevel]; @@ -549,7 +558,7 @@ static int32_t tsdbInsertTableDataImpl(SMemTable *pMemTable, STbData *pTbData, i key.ts = row.pTSRow->ts; nRow++; tbDataMovePosTo(pTbData, pos, &key, SL_MOVE_BACKWARD); - code = tbDataDoPut(pMemTable, pTbData, pos, &row, 0); + code = tbDataDoPut(pMemTable, pTbData, pos, version, row.pTSRow, 0); if (code) { goto _err; } @@ -570,7 +579,7 @@ static int32_t tsdbInsertTableDataImpl(SMemTable *pMemTable, STbData *pTbData, i if (SL_NODE_FORWARD(pos[0], 0) != pTbData->sl.pTail) { tbDataMovePosTo(pTbData, pos, &key, SL_MOVE_FROM_POS); } - code = tbDataDoPut(pMemTable, pTbData, pos, &row, 1); + code = tbDataDoPut(pMemTable, pTbData, pos, version, row.pTSRow, 1); if (code) { goto _err; } diff --git a/source/dnode/vnode/src/tsdb/tsdbUtil.c b/source/dnode/vnode/src/tsdb/tsdbUtil.c index 755a551e20..0aa2c6ab83 100644 --- a/source/dnode/vnode/src/tsdb/tsdbUtil.c +++ b/source/dnode/vnode/src/tsdb/tsdbUtil.c @@ -565,15 +565,15 @@ void tsdbRowGetColVal(TSDBROW *pRow, STSchema *pTSchema, int32_t iCol, SColVal * } } -int32_t tPutTSDBRow(uint8_t *p, TSDBROW *pRow) { - int32_t n = 0; +// int32_t tPutTSDBRow(uint8_t *p, TSDBROW *pRow) { +// int32_t n = 0; - n += tPutI64(p, pRow->version); - if (p) memcpy(p + n, pRow->pTSRow, pRow->pTSRow->len); - n += pRow->pTSRow->len; +// n += tPutI64(p, pRow->version); +// if (p) memcpy(p + n, pRow->pTSRow, pRow->pTSRow->len); +// n += pRow->pTSRow->len; - return n; -} +// return n; +// } int32_t tsdbRowCmprFn(const void *p1, const void *p2) { return tsdbKeyCmprFn(&TSDBROW_KEY((TSDBROW *)p1), &TSDBROW_KEY((TSDBROW *)p2)); @@ -1084,7 +1084,7 @@ static int32_t tBlockDataAppendTPRow(SBlockData *pBlockData, STSRow *pRow, STSch cv.flag = CV_FLAG_VALUE; if (IS_VAR_DATA_TYPE(pTColumn->type)) { - void *pData = (char*)pRow + *(int32_t *)(pRow->data + pTColumn->offset - sizeof(TSKEY)); + void *pData = (char *)pRow + *(int32_t *)(pRow->data + pTColumn->offset - sizeof(TSKEY)); cv.value.nData = varDataLen(pData); cv.value.pData = varDataVal(pData); } else { @@ -1106,7 +1106,7 @@ static int32_t tBlockDataAppendTPRow(SBlockData *pBlockData, STSRow *pRow, STSch cv.flag = CV_FLAG_VALUE; if (IS_VAR_DATA_TYPE(pTColumn->type)) { - void *pData = (char*)pRow + *(int32_t *)(pRow->data + pTColumn->offset - sizeof(TSKEY)); + void *pData = (char *)pRow + *(int32_t *)(pRow->data + pTColumn->offset - sizeof(TSKEY)); cv.value.nData = varDataLen(pData); cv.value.pData = varDataVal(pData); } else { @@ -1151,7 +1151,7 @@ static int32_t tBlockDataAppendKVRow(SBlockData *pBlockData, STSRow *pRow, STSch ASSERT(pTColumn->type == pColData->type); SColVal cv = {.cid = pTColumn->colId, .type = pTColumn->type}; - TDRowValT vt = TD_VTYPE_NONE; // default is NONE + TDRowValT vt = TD_VTYPE_NONE; // default is NONE SKvRowIdx *pKvIdx = NULL; while (kvIter < nKvCols) { From 901c9b8f77cfa2c64074edd7795cf3c8f9311ddf Mon Sep 17 00:00:00 2001 From: Xiaoyu Wang Date: Mon, 14 Nov 2022 16:53:01 +0800 Subject: [PATCH 24/39] fix: some problems of parser --- include/libs/nodes/querynodes.h | 5 ++--- source/libs/function/src/builtins.c | 14 +++++++------- source/libs/nodes/src/nodesUtilFuncs.c | 2 +- source/libs/parser/src/parTranslater.c | 18 ++++++++++-------- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h index a1dad1806d..d0971b013f 100644 --- a/include/libs/nodes/querynodes.h +++ b/include/libs/nodes/querynodes.h @@ -74,9 +74,8 @@ typedef struct SColumnNode { char tableName[TSDB_TABLE_NAME_LEN]; char tableAlias[TSDB_TABLE_NAME_LEN]; char colName[TSDB_COL_NAME_LEN]; - // SNode* pProjectRef; - int16_t dataBlockId; - int16_t slotId; + int16_t dataBlockId; + int16_t slotId; } SColumnNode; typedef struct SColumnRefNode { diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index d3f03e8e9c..8249a8f6b1 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -475,7 +475,7 @@ static int32_t translateNowToday(SFunctionNode* pFunc, char* pErrBuf, int32_t le // add database precision as param uint8_t dbPrec = pFunc->node.resType.precision; - int32_t code = addDbPrecisonParam(&pFunc->pParameterList, dbPrec); + int32_t code = addDbPrecisonParam(&pFunc->pParameterList, dbPrec); if (code != TSDB_CODE_SUCCESS) { return code; } @@ -1506,7 +1506,7 @@ static int32_t translateIrate(SFunctionNode* pFunc, char* pErrBuf, int32_t len) // add database precision as param uint8_t dbPrec = pFunc->node.resType.precision; - int32_t code = addDbPrecisonParam(&pFunc->pParameterList, dbPrec); + int32_t code = addDbPrecisonParam(&pFunc->pParameterList, dbPrec); if (code != TSDB_CODE_SUCCESS) { return code; } @@ -1519,7 +1519,7 @@ static int32_t translateInterp(SFunctionNode* pFunc, char* pErrBuf, int32_t len) int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList); uint8_t dbPrec = pFunc->node.resType.precision; - //if (1 != numOfParams && 3 != numOfParams && 4 != numOfParams) { + // if (1 != numOfParams && 3 != numOfParams && 4 != numOfParams) { if (1 != numOfParams) { return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName); } @@ -1835,7 +1835,7 @@ static int32_t translateCast(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { // add database precision as param uint8_t dbPrec = pFunc->node.resType.precision; - int32_t code = addDbPrecisonParam(&pFunc->pParameterList, dbPrec); + int32_t code = addDbPrecisonParam(&pFunc->pParameterList, dbPrec); if (code != TSDB_CODE_SUCCESS) { return code; } @@ -1894,7 +1894,7 @@ static int32_t translateToUnixtimestamp(SFunctionNode* pFunc, char* pErrBuf, int // add database precision as param uint8_t dbPrec = pFunc->node.resType.precision; - int32_t code = addDbPrecisonParam(&pFunc->pParameterList, dbPrec); + int32_t code = addDbPrecisonParam(&pFunc->pParameterList, dbPrec); if (code != TSDB_CODE_SUCCESS) { return code; } @@ -2474,7 +2474,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { { .name = "first", .type = FUNCTION_TYPE_FIRST, - .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC, + .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC | FUNC_MGT_KEEP_ORDER_FUNC, .translateFunc = translateFirstLast, .dynDataRequiredFunc = firstDynDataReq, .getEnvFunc = getFirstLastFuncEnv, @@ -2512,7 +2512,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { { .name = "last", .type = FUNCTION_TYPE_LAST, - .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC, + .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC | FUNC_MGT_KEEP_ORDER_FUNC, .translateFunc = translateFirstLast, .dynDataRequiredFunc = lastDynDataReq, .getEnvFunc = getFirstLastFuncEnv, diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c index 39d17153d0..cc1bae6a3c 100644 --- a/source/libs/nodes/src/nodesUtilFuncs.c +++ b/source/libs/nodes/src/nodesUtilFuncs.c @@ -622,7 +622,7 @@ void nodesDestroyNode(SNode* pNode) { } switch (nodeType(pNode)) { - case QUERY_NODE_COLUMN: // pProjectRef is weak reference, no need to release + case QUERY_NODE_COLUMN: destroyExprNode((SExprNode*)pNode); break; case QUERY_NODE_VALUE: { diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 0e5cb14208..260626f9c0 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -744,7 +744,8 @@ static bool isPrimaryKeyImpl(SNode* pExpr) { return (PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pExpr)->colId); } else if (QUERY_NODE_FUNCTION == nodeType(pExpr)) { SFunctionNode* pFunc = (SFunctionNode*)pExpr; - if (FUNCTION_TYPE_SELECT_VALUE == pFunc->funcType) { + if (FUNCTION_TYPE_SELECT_VALUE == pFunc->funcType || FUNCTION_TYPE_FIRST == pFunc->funcType || + FUNCTION_TYPE_LAST == pFunc->funcType) { return isPrimaryKeyImpl(nodesListGetNode(pFunc->pParameterList, 0)); } else if (FUNCTION_TYPE_WSTART == pFunc->funcType || FUNCTION_TYPE_WEND == pFunc->funcType) { return true; @@ -787,7 +788,6 @@ static void setColumnInfoBySchema(const SRealTableNode* pTable, const SSchema* p static void setColumnInfoByExpr(STempTableNode* pTable, SExprNode* pExpr, SColumnNode** pColRef) { SColumnNode* pCol = *pColRef; - // pCol->pProjectRef = (SNode*)pExpr; if (NULL == pExpr->pAssociation) { pExpr->pAssociation = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES); } @@ -2932,8 +2932,8 @@ static int32_t checkFill(STranslateContext* pCxt, SFillNode* pFill, SValueNode* return TSDB_CODE_SUCCESS; } - if (TSWINDOW_IS_EQUAL(pFill->timeRange, TSWINDOW_INITIALIZER) || - TSWINDOW_IS_EQUAL(pFill->timeRange, TSWINDOW_DESC_INITIALIZER)) { + if (!pCxt->createStream && (TSWINDOW_IS_EQUAL(pFill->timeRange, TSWINDOW_INITIALIZER) || + TSWINDOW_IS_EQUAL(pFill->timeRange, TSWINDOW_DESC_INITIALIZER))) { return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_FILL_TIME_RANGE); } @@ -5268,9 +5268,7 @@ static int32_t checkTopicQuery(STranslateContext* pCxt, SSelectStmt* pSelect) { } static int32_t buildCreateTopicReq(STranslateContext* pCxt, SCreateTopicStmt* pStmt, SCMCreateTopicReq* pReq) { - SName name; - tNameSetDbName(&name, pCxt->pParseCxt->acctId, pStmt->topicName, strlen(pStmt->topicName)); - tNameGetFullDbName(&name, pReq->name); + snprintf(pReq->name, sizeof(pReq->name), "%d.%s", pCxt->pParseCxt->acctId, pStmt->topicName); pReq->igExists = pStmt->ignoreExists; pReq->withMeta = pStmt->withMeta; @@ -5280,7 +5278,7 @@ static int32_t buildCreateTopicReq(STranslateContext* pCxt, SCreateTopicStmt* pS } int32_t code = TSDB_CODE_SUCCESS; - + SName name; if ('\0' != pStmt->subSTbName[0]) { pReq->subType = TOPIC_SUB_TYPE__TABLE; toName(pCxt->pParseCxt->acctId, pStmt->subDbName, pStmt->subSTbName, &name); @@ -5548,6 +5546,10 @@ static int32_t checkStreamQuery(STranslateContext* pCxt, SSelectStmt* pSelect) { crossTableWithUdaf(pSelect)) { return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_STREAM_QUERY, "Unsupported stream query"); } + if (NULL != pSelect->pSubtable && TSDB_DATA_TYPE_VARCHAR != ((SExprNode*)pSelect->pSubtable)->resType.type) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_STREAM_QUERY, + "SUBTABLE expression must be of VARCHAR type"); + } return TSDB_CODE_SUCCESS; } From cf56c38e7a49f601ad72b2e23cd34f1bdd6c3c2f Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Mon, 14 Nov 2022 17:10:25 +0800 Subject: [PATCH 25/39] fix(query): fix errors found by asan. --- source/common/src/tdatablock.c | 7 ++++++- source/dnode/vnode/src/tsdb/tsdbRead.c | 2 +- source/libs/executor/src/tsimplehash.c | 8 +++++--- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/source/common/src/tdatablock.c b/source/common/src/tdatablock.c index e8d5989e4d..0e8001708b 100644 --- a/source/common/src/tdatablock.c +++ b/source/common/src/tdatablock.c @@ -277,7 +277,12 @@ int32_t colDataMergeCol(SColumnInfoData* pColumnInfoData, int32_t numOfRow1, int pColumnInfoData->varmeta.allocLen = len + oldLen; } - memcpy(pColumnInfoData->pData + oldLen, pSource->pData, len); + if (pSource->pData != NULL) { + memcpy(pColumnInfoData->pData + oldLen, pSource->pData, len); + } else { + ASSERT(len == 0); + } + pColumnInfoData->varmeta.length = len + oldLen; } else { if (finalNumOfRows > (*capacity)) { diff --git a/source/dnode/vnode/src/tsdb/tsdbRead.c b/source/dnode/vnode/src/tsdb/tsdbRead.c index c157faecb1..af368d33e0 100644 --- a/source/dnode/vnode/src/tsdb/tsdbRead.c +++ b/source/dnode/vnode/src/tsdb/tsdbRead.c @@ -3219,7 +3219,7 @@ int32_t doMergeRowsInBuf(SIterInfo* pIter, uint64_t uid, int64_t ts, SArray* pDe static int32_t doMergeRowsInFileBlockImpl(SBlockData* pBlockData, int32_t rowIndex, int64_t key, SRowMerger* pMerger, SVersionRange* pVerRange, int32_t step) { - while (pBlockData->aTSKEY[rowIndex] == key && rowIndex < pBlockData->nRow && rowIndex >= 0) { + while (rowIndex < pBlockData->nRow && rowIndex >= 0 && pBlockData->aTSKEY[rowIndex] == key) { if (pBlockData->aVersion[rowIndex] > pVerRange->maxVer || pBlockData->aVersion[rowIndex] < pVerRange->minVer) { rowIndex += step; continue; diff --git a/source/libs/executor/src/tsimplehash.c b/source/libs/executor/src/tsimplehash.c index a5168d24ba..9fbe94200c 100644 --- a/source/libs/executor/src/tsimplehash.c +++ b/source/libs/executor/src/tsimplehash.c @@ -189,7 +189,7 @@ int32_t tSimpleHashPut(SSHashObj *pHashObj, const void *key, size_t keyLen, cons } while (pNode) { - if ((*(pHashObj->equalFp))(GET_SHASH_NODE_KEY(pNode, pNode->dataLen), key, keyLen) == 0) { + if ((keyLen == pNode->keyLen) && (*(pHashObj->equalFp))(GET_SHASH_NODE_KEY(pNode, pNode->dataLen), key, keyLen) == 0) { break; } pNode = pNode->next; @@ -213,10 +213,12 @@ int32_t tSimpleHashPut(SSHashObj *pHashObj, const void *key, size_t keyLen, cons static FORCE_INLINE SHNode *doSearchInEntryList(SSHashObj *pHashObj, const void *key, size_t keyLen, int32_t index) { SHNode *pNode = pHashObj->hashList[index]; while (pNode) { - if ((*(pHashObj->equalFp))(GET_SHASH_NODE_KEY(pNode, pNode->dataLen), key, keyLen) == 0) { + const char* p = GET_SHASH_NODE_KEY(pNode, pNode->dataLen); + ASSERT(keyLen > 0); + + if (pNode->keyLen == keyLen && ((*(pHashObj->equalFp))(p, key, keyLen) == 0)) { break; } - pNode = pNode->next; } From 10921cc09a512cf7ea1de8b71db488231b8bc3c7 Mon Sep 17 00:00:00 2001 From: Hongze Cheng Date: Mon, 14 Nov 2022 17:13:22 +0800 Subject: [PATCH 26/39] more opt --- source/dnode/vnode/src/tsdb/tsdbMemTable.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/source/dnode/vnode/src/tsdb/tsdbMemTable.c b/source/dnode/vnode/src/tsdb/tsdbMemTable.c index 998409f34e..55c7576155 100644 --- a/source/dnode/vnode/src/tsdb/tsdbMemTable.c +++ b/source/dnode/vnode/src/tsdb/tsdbMemTable.c @@ -262,30 +262,27 @@ void tsdbTbDataIterOpen(STbData *pTbData, TSDBKEY *pFrom, int8_t backward, STbDa } bool tsdbTbDataIterNext(STbDataIter *pIter) { - SMemSkipListNode *pHead = pIter->pTbData->sl.pHead; - SMemSkipListNode *pTail = pIter->pTbData->sl.pTail; - pIter->pRow = NULL; if (pIter->backward) { - ASSERT(pIter->pNode != pTail); + ASSERT(pIter->pNode != pIter->pTbData->sl.pTail); - if (pIter->pNode == pHead) { + if (pIter->pNode == pIter->pTbData->sl.pHead) { return false; } pIter->pNode = SL_NODE_BACKWARD(pIter->pNode, 0); - if (pIter->pNode == pHead) { + if (pIter->pNode == pIter->pTbData->sl.pHead) { return false; } } else { - ASSERT(pIter->pNode != pHead); + ASSERT(pIter->pNode != pIter->pTbData->sl.pHead); - if (pIter->pNode == pTail) { + if (pIter->pNode == pIter->pTbData->sl.pTail) { return false; } pIter->pNode = SL_NODE_FORWARD(pIter->pNode, 0); - if (pIter->pNode == pTail) { + if (pIter->pNode == pIter->pTbData->sl.pTail) { return false; } } From fae4fe5a755ca90685052357970e724b8a8fa907 Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Mon, 14 Nov 2022 17:13:44 +0800 Subject: [PATCH 27/39] fix(timezone): call right apply function --- source/util/src/tconfig.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/source/util/src/tconfig.c b/source/util/src/tconfig.c index 5250f5dfcd..76a312cd91 100644 --- a/source/util/src/tconfig.c +++ b/source/util/src/tconfig.c @@ -274,10 +274,7 @@ static int32_t cfgSetTimezone(SConfigItem *pItem, const char *value, ECfgSrcType pItem->stype = stype; // apply new timezone - char szTimezone[TD_TIMEZONE_LEN] = {0}; - int8_t dl; - enum TdTimezone tdOffset = TdZeroZone; - taosSetSystemTimezone(value, szTimezone, &dl, &tdOffset); + osSetTimezone(value); return 0; } From ac8eeb87afdeb1ec1e676f4887500b1eab84f50a Mon Sep 17 00:00:00 2001 From: Minghao Li Date: Mon, 14 Nov 2022 17:19:20 +0800 Subject: [PATCH 28/39] refactor(sync): modify error log --- source/libs/sync/src/syncMain.c | 8 ++++---- source/libs/sync/src/syncRaftLog.c | 12 ++++++------ source/libs/sync/src/syncUtil.c | 15 ++++++++------- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/source/libs/sync/src/syncMain.c b/source/libs/sync/src/syncMain.c index 8bccf6840a..b94d807bcc 100644 --- a/source/libs/sync/src/syncMain.c +++ b/source/libs/sync/src/syncMain.c @@ -1806,7 +1806,7 @@ static void syncNodeEqPingTimer(void* param, void* tmrId) { int32_t code = syncBuildTimeout(&rpcMsg, SYNC_TIMEOUT_PING, atomic_load_64(&pNode->pingTimerLogicClock), pNode->pingTimerMS, pNode); if (code != 0) { - sNError(pNode, "failed to build ping msg"); + sError(pNode, "failed to build ping msg"); rpcFreeCont(rpcMsg.pCont); return; } @@ -1814,7 +1814,7 @@ static void syncNodeEqPingTimer(void* param, void* tmrId) { sNTrace(pNode, "enqueue ping msg"); code = pNode->syncEqMsg(pNode->msgcb, &rpcMsg); if (code != 0) { - sNError(pNode, "failed to sync enqueue ping msg since %s", terrstr()); + sError(pNode, "failed to sync enqueue ping msg since %s", terrstr()); rpcFreeCont(rpcMsg.pCont); return; } @@ -1839,7 +1839,7 @@ static void syncNodeEqElectTimer(void* param, void* tmrId) { int32_t code = syncBuildTimeout(&rpcMsg, SYNC_TIMEOUT_ELECTION, pElectTimer->logicClock, pNode->electTimerMS, pNode); if (code != 0) { - sNError(pNode, "failed to build elect msg"); + sError(pNode, "failed to build elect msg"); taosMemoryFree(pElectTimer); return; } @@ -1849,7 +1849,7 @@ static void syncNodeEqElectTimer(void* param, void* tmrId) { code = pNode->syncEqMsg(pNode->msgcb, &rpcMsg); if (code != 0) { - sNError(pNode, "failed to sync enqueue elect msg since %s", terrstr()); + sError(pNode, "failed to sync enqueue elect msg since %s", terrstr()); rpcFreeCont(rpcMsg.pCont); taosMemoryFree(pElectTimer); return; diff --git a/source/libs/sync/src/syncRaftLog.c b/source/libs/sync/src/syncRaftLog.c index 21f301308e..b00ba3918c 100644 --- a/source/libs/sync/src/syncRaftLog.c +++ b/source/libs/sync/src/syncRaftLog.c @@ -198,9 +198,9 @@ static int32_t raftLogAppendEntry(struct SSyncLogStore* pLogStore, SSyncRaftEntr syncMeta.seqNum = pEntry->seqNum; syncMeta.term = pEntry->term; - int64_t tsWriteBegin = taosGetTimestampMs(); + int64_t tsWriteBegin = taosGetTimestampNs(); index = walAppendLog(pWal, pEntry->originalRpcType, syncMeta, pEntry->data, pEntry->dataLen); - int64_t tsWriteEnd = taosGetTimestampMs(); + int64_t tsWriteEnd = taosGetTimestampNs(); int64_t tsElapsed = tsWriteEnd - tsWriteBegin; if (index < 0) { @@ -239,12 +239,12 @@ int32_t raftLogGetEntry(struct SSyncLogStore* pLogStore, SyncIndex index, SSyncR return -1; } - int64_t ts1 = taosGetTimestampMs(); + int64_t ts1 = taosGetTimestampNs(); taosThreadMutexLock(&(pData->mutex)); - int64_t ts2 = taosGetTimestampMs(); + int64_t ts2 = taosGetTimestampNs(); code = walReadVer(pWalHandle, index); - int64_t ts3 = taosGetTimestampMs(); + int64_t ts3 = taosGetTimestampNs(); // code = walReadVerCached(pWalHandle, index); if (code != 0) { @@ -289,7 +289,7 @@ int32_t raftLogGetEntry(struct SSyncLogStore* pLogStore, SyncIndex index, SSyncR */ taosThreadMutexUnlock(&(pData->mutex)); - int64_t ts4 = taosGetTimestampMs(); + int64_t ts4 = taosGetTimestampNs(); int64_t tsElapsed = ts4 - ts1; int64_t tsElapsedLock = ts2 - ts1; diff --git a/source/libs/sync/src/syncUtil.c b/source/libs/sync/src/syncUtil.c index a575de7e56..b9a271ab9d 100644 --- a/source/libs/sync/src/syncUtil.c +++ b/source/libs/sync/src/syncUtil.c @@ -194,6 +194,7 @@ static void syncPeerState2Str(SSyncNode* pSyncNode, char* buf, int32_t bufLen) { void syncPrintNodeLog(const char* flags, ELogLevel level, int32_t dflag, SSyncNode* pNode, const char* format, ...) { if (pNode == NULL || pNode->pRaftCfg != NULL && pNode->pRaftStore == NULL || pNode->pLogStore == NULL) return; + int64_t currentTerm = pNode->pRaftStore->currentTerm; // save error code, otherwise it will be overwritten int32_t errCode = terrno; @@ -235,8 +236,8 @@ void syncPrintNodeLog(const char* flags, ELogLevel level, int32_t dflag, SSyncNo ", tm:%" PRIu64 ", cmt:%" PRId64 ", fst:%" PRId64 ", lst:%" PRId64 ", min:%" PRId64 ", snap:%" PRId64 ", snap-tm:%" PRIu64 ", sby:%d, aq:%d, bch:%d, r-num:%d, lcfg:%" PRId64 ", chging:%d, rsto:%d, dquorum:%d, elt:%" PRId64 ", hb:%" PRId64 ", %s, %s", - pNode->vgId, syncStr(pNode->state), eventLog, pNode->pRaftStore->currentTerm, pNode->commitIndex, - logBeginIndex, logLastIndex, pNode->minMatchIndex, snapshot.lastApplyIndex, snapshot.lastApplyTerm, + pNode->vgId, syncStr(pNode->state), eventLog, currentTerm, pNode->commitIndex, logBeginIndex, + logLastIndex, pNode->minMatchIndex, snapshot.lastApplyIndex, snapshot.lastApplyTerm, pNode->pRaftCfg->isStandBy, aqItems, pNode->pRaftCfg->batchSize, pNode->replicaNum, pNode->pRaftCfg->lastConfigIndex, pNode->changing, pNode->restoreFinish, quorum, pNode->electTimerLogicClock, pNode->heartbeatTimerLogicClockUser, peerStr, cfgStr); @@ -374,9 +375,9 @@ void syncLogRecvAppendEntriesReply(SSyncNode* pSyncNode, const SyncAppendEntries syncUtilU642Addr(pMsg->srcId.addr, host, sizeof(host), &port); sNTrace(pSyncNode, - "recv sync-append-entries-reply from %s:%d {term:%" PRId64 ", pterm:%" PRId64 ", success:%d, match:%" PRId64 - "}, %s", - host, port, pMsg->term, pMsg->privateTerm, pMsg->success, pMsg->matchIndex, s); + "recv sync-append-entries-reply from %s:%d {term:%" PRId64 ", pterm:%" PRId64 + ", success:%d, lsend-index:%" PRId64 ", match:%" PRId64 "}, %s", + host, port, pMsg->term, pMsg->privateTerm, pMsg->success, pMsg->lastSendIndex, pMsg->matchIndex, s); } void syncLogSendHeartbeat(SSyncNode* pSyncNode, const SyncHeartbeat* pMsg, const char* s) { @@ -511,8 +512,8 @@ void syncLogSendAppendEntries(SSyncNode* pSyncNode, const SyncAppendEntries* pMs syncUtilU642Addr(pMsg->destId.addr, host, sizeof(host), &port); sNTrace(pSyncNode, "send sync-append-entries to %s:%d, {term:%" PRId64 ", pre-index:%" PRId64 ", pre-term:%" PRId64 - ", pterm:%" PRId64 ", cmt:%" PRId64 ", datalen:%d}, %s", - host, port, pMsg->term, pMsg->prevLogIndex, pMsg->prevLogTerm, pMsg->privateTerm, pMsg->commitIndex, + ", lsend-index:%" PRId64 ", cmt:%" PRId64 ", datalen:%d}, %s", + host, port, pMsg->term, pMsg->prevLogIndex, pMsg->prevLogTerm, (pMsg->prevLogIndex + 1), pMsg->commitIndex, pMsg->dataLen, s); } From 21ba6fa328c250705b3914adeb2046a68590b70a Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Mon, 14 Nov 2022 17:25:20 +0800 Subject: [PATCH 29/39] test: add asan case --- tests/parallel_test/cases.task | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task index 48215b1d47..a8e36e98ee 100644 --- a/tests/parallel_test/cases.task +++ b/tests/parallel_test/cases.task @@ -181,12 +181,12 @@ ,,,script,./test.sh -f tsim/show/basic.sim ,,y,script,./test.sh -f tsim/table/autocreate.sim ,,y,script,./test.sh -f tsim/table/basic1.sim -,,,script,./test.sh -f tsim/table/basic2.sim +,,y,script,./test.sh -f tsim/table/basic2.sim ,,y,script,./test.sh -f tsim/table/basic3.sim ,,y,script,./test.sh -f tsim/table/bigint.sim ,,y,script,./test.sh -f tsim/table/binary.sim ,,y,script,./test.sh -f tsim/table/bool.sim -,,,script,./test.sh -f tsim/table/column_name.sim +,,y,script,./test.sh -f tsim/table/column_name.sim ,,y,script,./test.sh -f tsim/table/column_num.sim ,,y,script,./test.sh -f tsim/table/column_value.sim ,,y,script,./test.sh -f tsim/table/column2.sim @@ -208,6 +208,7 @@ ,,y,script,./test.sh -f tsim/table/tinyint.sim ,,y,script,./test.sh -f tsim/table/vgroup.sim ,,,script,./test.sh -f tsim/stream/basic0.sim -g +,,,script,./test.sh -f tsim/stream/basic1.sim ,,y,script,./test.sh -f tsim/stream/basic2.sim ,,,script,./test.sh -f tsim/stream/drop_stream.sim ,,y,script,./test.sh -f tsim/stream/fillHistoryBasic1.sim From 6aefbbf3b22a7576d32a9007e4344651edc9fec0 Mon Sep 17 00:00:00 2001 From: Hongze Cheng Date: Mon, 14 Nov 2022 17:32:09 +0800 Subject: [PATCH 30/39] more optimize --- source/dnode/vnode/src/tsdb/tsdbMemTable.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/dnode/vnode/src/tsdb/tsdbMemTable.c b/source/dnode/vnode/src/tsdb/tsdbMemTable.c index 55c7576155..ddf2949607 100644 --- a/source/dnode/vnode/src/tsdb/tsdbMemTable.c +++ b/source/dnode/vnode/src/tsdb/tsdbMemTable.c @@ -18,7 +18,8 @@ #define MEM_MIN_HASH 1024 #define SL_MAX_LEVEL 5 -#define SL_NODE_SIZE(l) (sizeof(SMemSkipListNode) + sizeof(SMemSkipListNode *) * (l)*2) +// sizeof(SMemSkipListNode) + sizeof(SMemSkipListNode *) * (l) * 2 +#define SL_NODE_SIZE(l) (sizeof(SMemSkipListNode) + ((l) << 4)) #define SL_NODE_FORWARD(n, l) ((n)->forwards[l]) #define SL_NODE_BACKWARD(n, l) ((n)->forwards[(n)->level + (l)]) From 76628a52e6cfe45b6229f0ef8252f1d76b45edbe Mon Sep 17 00:00:00 2001 From: Minghao Li Date: Mon, 14 Nov 2022 17:33:48 +0800 Subject: [PATCH 31/39] fix(sync): do not use SNError --- source/libs/sync/src/syncMain.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/source/libs/sync/src/syncMain.c b/source/libs/sync/src/syncMain.c index b94d807bcc..e802f60f30 100644 --- a/source/libs/sync/src/syncMain.c +++ b/source/libs/sync/src/syncMain.c @@ -1806,7 +1806,7 @@ static void syncNodeEqPingTimer(void* param, void* tmrId) { int32_t code = syncBuildTimeout(&rpcMsg, SYNC_TIMEOUT_PING, atomic_load_64(&pNode->pingTimerLogicClock), pNode->pingTimerMS, pNode); if (code != 0) { - sError(pNode, "failed to build ping msg"); + sError("failed to build ping msg"); rpcFreeCont(rpcMsg.pCont); return; } @@ -1814,7 +1814,7 @@ static void syncNodeEqPingTimer(void* param, void* tmrId) { sNTrace(pNode, "enqueue ping msg"); code = pNode->syncEqMsg(pNode->msgcb, &rpcMsg); if (code != 0) { - sError(pNode, "failed to sync enqueue ping msg since %s", terrstr()); + sError("failed to sync enqueue ping msg since %s", terrstr()); rpcFreeCont(rpcMsg.pCont); return; } @@ -1839,7 +1839,7 @@ static void syncNodeEqElectTimer(void* param, void* tmrId) { int32_t code = syncBuildTimeout(&rpcMsg, SYNC_TIMEOUT_ELECTION, pElectTimer->logicClock, pNode->electTimerMS, pNode); if (code != 0) { - sError(pNode, "failed to build elect msg"); + sError("failed to build elect msg"); taosMemoryFree(pElectTimer); return; } @@ -1849,7 +1849,7 @@ static void syncNodeEqElectTimer(void* param, void* tmrId) { code = pNode->syncEqMsg(pNode->msgcb, &rpcMsg); if (code != 0) { - sError(pNode, "failed to sync enqueue elect msg since %s", terrstr()); + sError("failed to sync enqueue elect msg since %s", terrstr()); rpcFreeCont(rpcMsg.pCont); taosMemoryFree(pElectTimer); return; @@ -1879,14 +1879,14 @@ static void syncNodeEqHeartbeatTimer(void* param, void* tmrId) { pNode->heartbeatTimerMS, pNode); if (code != 0) { - sNError(pNode, "failed to build heartbeat msg"); + sError("failed to build heartbeat msg"); return; } sNTrace(pNode, "enqueue heartbeat timer"); code = pNode->syncEqMsg(pNode->msgcb, &rpcMsg); if (code != 0) { - sNError(pNode, "failed to enqueue heartbeat msg since %s", terrstr()); + sError("failed to enqueue heartbeat msg since %s", terrstr()); rpcFreeCont(rpcMsg.pCont); return; } @@ -1971,7 +1971,7 @@ static int32_t syncNodeEqNoop(SSyncNode* pNode) { sNTrace(pNode, "propose msg, type:noop"); code = (*pNode->syncEqMsg)(pNode->msgcb, &rpcMsg); if (code != 0) { - sNError(pNode, "failed to propose noop msg while enqueue since %s", terrstr()); + sError("failed to propose noop msg while enqueue since %s", terrstr()); } return code; @@ -2005,7 +2005,7 @@ static int32_t syncNodeAppendNoop(SSyncNode* ths) { if (ths->state == TAOS_SYNC_STATE_LEADER) { int32_t code = ths->pLogStore->syncLogAppendEntry(ths->pLogStore, pEntry); if (code != 0) { - sNError(ths, "append noop error"); + sError("append noop error"); return -1; } } @@ -2109,7 +2109,7 @@ int32_t syncNodeOnLocalCmd(SSyncNode* ths, const SRpcMsg* pRpcMsg) { syncNodeFollowerCommit(ths, pMsg->fcIndex); } else { - sNError(ths, "error local cmd"); + sError("error local cmd"); } return 0; From 2f0dad7b1c3bef5f71849374394891bc3ac657d4 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Mon, 14 Nov 2022 18:11:33 +0800 Subject: [PATCH 32/39] test: add asan case --- tests/parallel_test/cases.task | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task index 7ff3eb89e7..1174f46e65 100644 --- a/tests/parallel_test/cases.task +++ b/tests/parallel_test/cases.task @@ -138,7 +138,7 @@ ,,y,script,./test.sh -f tsim/parser/mixed_blocks.sim ,,y,script,./test.sh -f tsim/parser/nchar.sim ,,,script,./test.sh -f tsim/parser/nestquery.sim -,,,script,./test.sh -f tsim/parser/null_char.sim +,,y,script,./test.sh -f tsim/parser/null_char.sim ,,y,script,./test.sh -f tsim/parser/precision_ns.sim ,,,script,./test.sh -f tsim/parser/projection_limit_offset.sim ,,y,script,./test.sh -f tsim/parser/regex.sim @@ -147,7 +147,7 @@ ,,y,script,./test.sh -f tsim/parser/select_from_cache_disk.sim ,,y,script,./test.sh -f tsim/parser/select_with_tags.sim ,,y,script,./test.sh -f tsim/parser/selectResNum.sim -,,,script,./test.sh -f tsim/parser/set_tag_vals.sim +,,y,script,./test.sh -f tsim/parser/set_tag_vals.sim ,,y,script,./test.sh -f tsim/parser/single_row_in_tb.sim ,,,script,./test.sh -f tsim/parser/sliding.sim ,,y,script,./test.sh -f tsim/parser/slimit_alter_tags.sim @@ -178,7 +178,7 @@ ,,,script,./test.sh -f tsim/mnode/basic3.sim ,,,script,./test.sh -f tsim/mnode/basic4.sim ,,,script,./test.sh -f tsim/mnode/basic5.sim -,,,script,./test.sh -f tsim/show/basic.sim +,,y,script,./test.sh -f tsim/show/basic.sim ,,y,script,./test.sh -f tsim/table/autocreate.sim ,,y,script,./test.sh -f tsim/table/basic1.sim ,,y,script,./test.sh -f tsim/table/basic2.sim @@ -193,9 +193,9 @@ ,,y,script,./test.sh -f tsim/table/createmulti.sim ,,y,script,./test.sh -f tsim/table/date.sim ,,y,script,./test.sh -f tsim/table/db.table.sim -,,,script,./test.sh -f tsim/table/delete_reuse1.sim -,,,script,./test.sh -f tsim/table/delete_reuse2.sim -,,,script,./test.sh -f tsim/table/delete_writing.sim +,,y,script,./test.sh -f tsim/table/delete_reuse1.sim +,,y,script,./test.sh -f tsim/table/delete_reuse2.sim +,,y,script,./test.sh -f tsim/table/delete_writing.sim ,,y,script,./test.sh -f tsim/table/describe.sim ,,y,script,./test.sh -f tsim/table/double.sim ,,y,script,./test.sh -f tsim/table/float.sim @@ -203,7 +203,7 @@ ,,y,script,./test.sh -f tsim/table/int.sim ,,y,script,./test.sh -f tsim/table/limit.sim ,,y,script,./test.sh -f tsim/table/smallint.sim -,,,script,./test.sh -f tsim/table/table_len.sim +,,y,script,./test.sh -f tsim/table/table_len.sim ,,y,script,./test.sh -f tsim/table/table.sim ,,y,script,./test.sh -f tsim/table/tinyint.sim ,,y,script,./test.sh -f tsim/table/vgroup.sim From d381b4da9331b6094807d8d39b9dbaacf0b363d0 Mon Sep 17 00:00:00 2001 From: Minghao Li Date: Mon, 14 Nov 2022 18:17:14 +0800 Subject: [PATCH 33/39] fix(sync): fix memory leak --- source/libs/sync/src/syncReplication.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/libs/sync/src/syncReplication.c b/source/libs/sync/src/syncReplication.c index 59afe814eb..6a7a2c18c1 100644 --- a/source/libs/sync/src/syncReplication.c +++ b/source/libs/sync/src/syncReplication.c @@ -72,7 +72,7 @@ int32_t syncNodeReplicateOne(SSyncNode* pSyncNode, SRaftId* pDestId, bool snapsh SRpcMsg rpcMsg = {0}; SyncAppendEntries* pMsg = NULL; - SSyncRaftEntry* pEntry; + SSyncRaftEntry* pEntry = NULL; int32_t code = pSyncNode->pLogStore->syncLogGetEntry(pSyncNode->pLogStore, nextIndex, &pEntry); if (code == 0) { @@ -99,6 +99,8 @@ int32_t syncNodeReplicateOne(SSyncNode* pSyncNode, SRaftId* pDestId, bool snapsh } } + syncEntryDestory(pEntry); + // prepare msg ASSERT(pMsg != NULL); pMsg->srcId = pSyncNode->myRaftId; From b2f9eeb5bbc2a09c9123bd27eec29bfc516d39f3 Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Mon, 14 Nov 2022 18:49:11 +0800 Subject: [PATCH 34/39] fix(query): fill operator memory leak fixed --- source/libs/executor/src/tfill.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/source/libs/executor/src/tfill.c b/source/libs/executor/src/tfill.c index ddd948a6dd..c41376b2dc 100644 --- a/source/libs/executor/src/tfill.c +++ b/source/libs/executor/src/tfill.c @@ -513,6 +513,22 @@ void* taosDestroyFillInfo(SFillInfo* pFillInfo) { // taosMemoryFreeClear(pFillInfo->pTags[i].tagVal); // } + // free pFillCol + if (pFillInfo->pFillCol) { + for (int32_t i = 0; i < pFillInfo->numOfCols; i++) { + SFillColInfo* pCol = &pFillInfo->pFillCol[i]; + if (!pCol->notFillCol) { + if (pCol->fillVal.nType == TSDB_DATA_TYPE_VARBINARY || pCol->fillVal.nType == TSDB_DATA_TYPE_VARCHAR || + pCol->fillVal.nType == TSDB_DATA_TYPE_NCHAR || pCol->fillVal.nType == TSDB_DATA_TYPE_JSON) { + if (pCol->fillVal.pz) { + taosMemoryFree(pCol->fillVal.pz); + pCol->fillVal.pz = NULL; + } + } + } + } + } + taosMemoryFreeClear(pFillInfo->pTags); taosMemoryFreeClear(pFillInfo->pFillCol); taosMemoryFreeClear(pFillInfo); From c47ac26e2165601e05221c3f752fbe177dfd4688 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Mon, 14 Nov 2022 19:12:39 +0800 Subject: [PATCH 35/39] fix: taosadapter windows install (#18124) * fix: sc create service in tdengine.iss * fix: upx on windows --- packaging/release.bat | 2 +- packaging/tools/tdengine.iss | 10 ++++++++++ tools/CMakeLists.txt | 15 ++++++++++++--- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/packaging/release.bat b/packaging/release.bat index 4ab7297f03..4c82c5ead5 100644 --- a/packaging/release.bat +++ b/packaging/release.bat @@ -39,7 +39,7 @@ if not exist %work_dir%\debug\ver-%2-x86 ( md %work_dir%\debug\ver-%2-x86 ) cd %work_dir%\debug\ver-%2-x64 -rem #call vcvarsall.bat x64 +call vcvarsall.bat x64 cmake ../../ -G "NMake Makefiles JOM" -DCMAKE_MAKE_PROGRAM=jom -DBUILD_TOOLS=true -DWEBSOCKET=true -DBUILD_HTTP=false -DBUILD_TEST=false -DVERNUMBER=%2 -DCPUTYPE=x64 cmake --build . rd /s /Q C:\TDengine diff --git a/packaging/tools/tdengine.iss b/packaging/tools/tdengine.iss index 981bee91b8..1c0c105179 100644 --- a/packaging/tools/tdengine.iss +++ b/packaging/tools/tdengine.iss @@ -61,6 +61,16 @@ Source: {#MyAppSourceDir}{#MyAppExeName}; DestDir: "{app}"; Excludes: {#MyAppExc Source: {#MyAppSourceDir}{#MyAppTaosdemoExeName}; DestDir: "{app}"; Flags: igNoreversion recursesubdirs createallsubdirs +[run] +Filename: {sys}\sc.exe; Parameters: "create taosd start= DEMAND binPath= ""C:\\TDengine\\taosd.exe --win_service""" ; Flags: runhidden +Filename: {sys}\sc.exe; Parameters: "create taosadapter start= DEMAND binPath= ""C:\\TDengine\\taosadapter.exe --win_service""" ; Flags: runhidden + +[UninstallRun] +RunOnceId: "stoptaosd"; Filename: {sys}\sc.exe; Parameters: "stop taosd" ; Flags: runhidden +RunOnceId: "stoptaosadapter"; Filename: {sys}\sc.exe; Parameters: "stop taosadapter" ; Flags: runhidden +RunOnceId: "deltaosd"; Filename: {sys}\sc.exe; Parameters: "delete taosd" ; Flags: runhidden +RunOnceId: "deltaosadapter"; Filename: {sys}\sc.exe; Parameters: "delete taosadapter" ; Flags: runhidden + [Registry] Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \ ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};C:\TDengine"; \ diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 79be05e9fc..0f3c383b9e 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -87,6 +87,7 @@ ELSE () MESSAGE("CURRENT SOURCE DIR ${CMAKE_CURRENT_SOURCE_DIR}") IF (TD_WINDOWS) + MESSAGE("Building taosAdapter on Windows") INCLUDE(ExternalProject) ExternalProject_Add(taosadapter PREFIX "taosadapter" @@ -104,14 +105,18 @@ ELSE () COMMAND go build -a -o taosadapter-debug.exe -ldflags "-X github.com/taosdata/taosadapter/v3/version.Version=${taos_version} -X github.com/taosdata/taosadapter/v3/version.CommitID=${taosadapter_commit_sha1}" INSTALL_COMMAND - COMMAND cmake -E time upx taosadapter ||: - COMMAND cmake -E copy taosadapter.exe ${CMAKE_BINARY_DIR}/build/bin + COMMAND cmake -E echo "Comparessing taosadapter.exe" + COMMAND cmake -E time upx taosadapter.exe + COMMAND cmake -E echo "Copy taosadapter.exe" + COMMAND cmake -E copy taosadapter.exe ${CMAKE_BINARY_DIR}/build/bin/taosadapter.exe COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/test/cfg/ + COMMAND cmake -E echo "Copy taosadapter.toml" COMMAND cmake -E copy ./example/config/taosadapter.toml ${CMAKE_BINARY_DIR}/test/cfg/ - COMMAND cmake -E copy ./taosadapter.service ${CMAKE_BINARY_DIR}/test/cfg/ + COMMAND cmake -E echo "Copy taosadapter-debug.exe" COMMAND cmake -E copy taosadapter-debug.exe ${CMAKE_BINARY_DIR}/build/bin ) ELSE (TD_WINDOWS) + MESSAGE("Building taosAdapter on non-Windows") INCLUDE(ExternalProject) ExternalProject_Add(taosadapter PREFIX "taosadapter" @@ -126,11 +131,15 @@ ELSE () COMMAND CGO_CFLAGS=-I${CMAKE_CURRENT_SOURCE_DIR}/../include/client CGO_LDFLAGS=-L${CMAKE_BINARY_DIR}/build/lib go build -a -ldflags "-s -w -X github.com/taosdata/taosadapter/v3/version.Version=${taos_version} -X github.com/taosdata/taosadapter/v3/version.CommitID=${taosadapter_commit_sha1}" COMMAND CGO_CFLAGS=-I${CMAKE_CURRENT_SOURCE_DIR}/../include/client CGO_LDFLAGS=-L${CMAKE_BINARY_DIR}/build/lib go build -a -o taosadapter-debug -ldflags "-X github.com/taosdata/taosadapter/v3/version.Version=${taos_version} -X github.com/taosdata/taosadapter/v3/version.CommitID=${taosadapter_commit_sha1}" INSTALL_COMMAND + COMMAND cmake -E echo "Comparessing taosadapter.exe" COMMAND upx taosadapter || : + COMMAND cmake -E echo "Copy taosadapter" COMMAND cmake -E copy taosadapter ${CMAKE_BINARY_DIR}/build/bin COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/test/cfg/ + COMMAND cmake -E echo "Copy taosadapter.toml" COMMAND cmake -E copy ./example/config/taosadapter.toml ${CMAKE_BINARY_DIR}/test/cfg/ COMMAND cmake -E copy ./taosadapter.service ${CMAKE_BINARY_DIR}/test/cfg/ + COMMAND cmake -E echo "Copy taosadapter-debug" COMMAND cmake -E copy taosadapter-debug ${CMAKE_BINARY_DIR}/build/bin ) ENDIF (TD_WINDOWS) From 7c8b2867cee0d21259419f564243fd507bdebc2b Mon Sep 17 00:00:00 2001 From: Liu Jicong Date: Mon, 14 Nov 2022 19:23:42 +0800 Subject: [PATCH 36/39] enh(stream): add stream task info into information schema --- include/common/systable.h | 1 + include/common/tmsg.h | 1 + source/common/src/systable.c | 12 ++- source/dnode/mnode/impl/src/mndShow.c | 2 + source/dnode/mnode/impl/src/mndStream.c | 108 +++++++++++++++++++++++- source/libs/wal/src/walMeta.c | 6 +- source/libs/wal/src/walWrite.c | 1 + 7 files changed, 127 insertions(+), 4 deletions(-) diff --git a/include/common/systable.h b/include/common/systable.h index 8b29525db3..57f85f16bc 100644 --- a/include/common/systable.h +++ b/include/common/systable.h @@ -46,6 +46,7 @@ extern "C" { #define TSDB_INS_TABLE_SUBSCRIPTIONS "ins_subscriptions" #define TSDB_INS_TABLE_TOPICS "ins_topics" #define TSDB_INS_TABLE_STREAMS "ins_streams" +#define TSDB_INS_TABLE_STREAM_TASKS "ins_stream_tasks" #define TSDB_PERFORMANCE_SCHEMA_DB "performance_schema" #define TSDB_PERFS_TABLE_SMAS "perf_smas" diff --git a/include/common/tmsg.h b/include/common/tmsg.h index 99c5c72e2f..3281bca96a 100644 --- a/include/common/tmsg.h +++ b/include/common/tmsg.h @@ -119,6 +119,7 @@ typedef enum _mgmt_table { TSDB_MGMT_TABLE_QUERIES, TSDB_MGMT_TABLE_VNODES, TSDB_MGMT_TABLE_APPS, + TSDB_MGMT_TABLE_STREAM_TASKS, TSDB_MGMT_TABLE_MAX, } EShowType; diff --git a/source/common/src/systable.c b/source/common/src/systable.c index d3d006ab35..c3a1f9f67e 100644 --- a/source/common/src/systable.c +++ b/source/common/src/systable.c @@ -134,7 +134,7 @@ static const SSysDbTableSchema userStbsSchema[] = { }; static const SSysDbTableSchema streamSchema[] = { - {.name = "stream_name", .bytes = SYSTABLE_SCH_DB_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, + {.name = "stream_name", .bytes = SYSTABLE_SCH_TABLE_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, {.name = "create_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP, .sysInfo = false}, {.name = "sql", .bytes = TSDB_SHOW_SQL_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, {.name = "status", .bytes = 20 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, @@ -145,6 +145,15 @@ static const SSysDbTableSchema streamSchema[] = { {.name = "trigger", .bytes = 20 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, }; +static const SSysDbTableSchema streamTaskSchema[] = { + {.name = "stream_name", .bytes = SYSTABLE_SCH_DB_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, + {.name = "task_id", .bytes = 8, .type = TSDB_DATA_TYPE_INT, .sysInfo = false}, + {.name = "node_type", .bytes = SYSTABLE_SCH_DB_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, + {.name = "node_id", .bytes = 8, .type = TSDB_DATA_TYPE_INT, .sysInfo = false}, + {.name = "level", .bytes = 20 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, + {.name = "status", .bytes = 20 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, +}; + static const SSysDbTableSchema userTblsSchema[] = { {.name = "table_name", .bytes = SYSTABLE_SCH_TABLE_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, {.name = "db_name", .bytes = SYSTABLE_SCH_DB_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, @@ -287,6 +296,7 @@ static const SSysTableMeta infosMeta[] = { {TSDB_INS_TABLE_TOPICS, topicSchema, tListLen(topicSchema), false}, {TSDB_INS_TABLE_SUBSCRIPTIONS, subscriptionSchema, tListLen(subscriptionSchema), false}, {TSDB_INS_TABLE_STREAMS, streamSchema, tListLen(streamSchema), false}, + {TSDB_INS_TABLE_STREAM_TASKS, streamTaskSchema, tListLen(streamTaskSchema), false}, {TSDB_INS_TABLE_VNODES, vnodesSchema, tListLen(vnodesSchema), true}, }; diff --git a/source/dnode/mnode/impl/src/mndShow.c b/source/dnode/mnode/impl/src/mndShow.c index b0af98b933..20c2ebb0a4 100644 --- a/source/dnode/mnode/impl/src/mndShow.c +++ b/source/dnode/mnode/impl/src/mndShow.c @@ -106,6 +106,8 @@ static int32_t convertToRetrieveType(char *name, int32_t len) { type = TSDB_MGMT_TABLE_STREAMS; } else if (strncasecmp(name, TSDB_PERFS_TABLE_APPS, len) == 0) { type = TSDB_MGMT_TABLE_APPS; + } else if (strncasecmp(name, TSDB_INS_TABLE_STREAM_TASKS, len) == 0) { + type = TSDB_MGMT_TABLE_STREAM_TASKS; } else { // ASSERT(0); } diff --git a/source/dnode/mnode/impl/src/mndStream.c b/source/dnode/mnode/impl/src/mndStream.c index 594c13f957..c649180285 100644 --- a/source/dnode/mnode/impl/src/mndStream.c +++ b/source/dnode/mnode/impl/src/mndStream.c @@ -41,6 +41,8 @@ static int32_t mndProcessStreamMetaReq(SRpcMsg *pReq); static int32_t mndGetStreamMeta(SRpcMsg *pReq, SShowObj *pShow, STableMetaRsp *pMeta); static int32_t mndRetrieveStream(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows); static void mndCancelGetNextStream(SMnode *pMnode, void *pIter); +static int32_t mndRetrieveStreamTask(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows); +static void mndCancelGetNextStreamTask(SMnode *pMnode, void *pIter); int32_t mndInitStream(SMnode *pMnode) { SSdbTable table = { @@ -62,6 +64,8 @@ int32_t mndInitStream(SMnode *pMnode) { mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_STREAMS, mndRetrieveStream); mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_STREAMS, mndCancelGetNextStream); + mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_STREAM_TASKS, mndRetrieveStreamTask); + mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_STREAM_TASKS, mndCancelGetNextStreamTask); return sdbSetTable(pMnode->pSdb, table); } @@ -891,7 +895,7 @@ static int32_t mndRetrieveStream(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pB SName n; int32_t cols = 0; - char streamName[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; + char streamName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(streamName, mndGetDbStr(pStream->name), sizeof(streamName)); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); colDataAppend(pColInfo, numOfRows, (const char *)streamName, false); @@ -953,3 +957,105 @@ static void mndCancelGetNextStream(SMnode *pMnode, void *pIter) { SSdb *pSdb = pMnode->pSdb; sdbCancelFetch(pSdb, pIter); } + +static int32_t mndRetrieveStreamTask(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rowsCapacity) { + SMnode *pMnode = pReq->info.node; + SSdb *pSdb = pMnode->pSdb; + int32_t numOfRows = 0; + SStreamObj *pStream = NULL; + + while (numOfRows < rowsCapacity) { + pShow->pIter = sdbFetch(pSdb, SDB_STREAM, pShow->pIter, (void **)&pStream); + if (pShow->pIter == NULL) break; + + // lock + taosRLockLatch(&pStream->lock); + // count task num + int32_t sz = taosArrayGetSize(pStream->tasks); + int32_t count = 0; + for (int32_t i = 0; i < sz; i++) { + SArray *pLevel = taosArrayGetP(pStream->tasks, i); + count += taosArrayGetSize(pLevel); + } + + if (numOfRows + count > rowsCapacity) { + blockDataEnsureCapacity(pBlock, numOfRows + count); + } + // add row for each task + for (int32_t i = 0; i < sz; i++) { + SArray *pLevel = taosArrayGetP(pStream->tasks, i); + int32_t levelCnt = taosArrayGetSize(pLevel); + for (int32_t j = 0; j < levelCnt; j++) { + SStreamTask *pTask = taosArrayGetP(pLevel, j); + + SColumnInfoData *pColInfo; + int32_t cols = 0; + + // stream name + char streamName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_WITH_MAXSIZE_TO_VARSTR(streamName, mndGetDbStr(pStream->name), sizeof(streamName)); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataAppend(pColInfo, numOfRows, (const char *)streamName, false); + + // task id + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataAppend(pColInfo, numOfRows, (const char *)&pTask->taskId, false); + + // node type + char nodeType[20 + VARSTR_HEADER_SIZE] = {0}; + varDataSetLen(nodeType, 5); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + if (pTask->nodeId > 0) { + memcpy(varDataVal(nodeType), "vnode", 5); + } else { + memcpy(varDataVal(nodeType), "snode", 5); + } + colDataAppend(pColInfo, numOfRows, nodeType, false); + + // node id + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + int32_t nodeId = TMAX(pTask->nodeId, 0); + colDataAppend(pColInfo, numOfRows, (const char *)&nodeId, false); + + // level + char level[20 + VARSTR_HEADER_SIZE] = {0}; + if (pTask->taskLevel == TASK_LEVEL__SOURCE) { + memcpy(varDataVal(level), "source", 6); + varDataSetLen(level, 6); + } else if (pTask->taskLevel == TASK_LEVEL__AGG) { + memcpy(varDataVal(level), "agg", 3); + varDataSetLen(level, 3); + } else if (pTask->taskLevel == TASK_LEVEL__SINK) { + memcpy(varDataVal(level), "sink", 4); + varDataSetLen(level, 4); + } else if (pTask->taskLevel == TASK_LEVEL__SINK) { + } + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataAppend(pColInfo, numOfRows, (const char *)&level, false); + + // status + char status[20 + VARSTR_HEADER_SIZE] = {0}; + char status2[20] = {0}; + strcpy(status, "normal"); + STR_WITH_MAXSIZE_TO_VARSTR(status, status2, sizeof(status)); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataAppend(pColInfo, numOfRows, (const char *)&status, false); + + numOfRows++; + } + } + + // unlock + taosRUnLockLatch(&pStream->lock); + + sdbRelease(pSdb, pStream); + } + + pShow->numOfRows += numOfRows; + return numOfRows; +} + +static void mndCancelGetNextStreamTask(SMnode *pMnode, void *pIter) { + SSdb *pSdb = pMnode->pSdb; + sdbCancelFetch(pSdb, pIter); +} diff --git a/source/libs/wal/src/walMeta.c b/source/libs/wal/src/walMeta.c index 1c6e1a2e17..6cac4b6093 100644 --- a/source/libs/wal/src/walMeta.c +++ b/source/libs/wal/src/walMeta.c @@ -124,8 +124,8 @@ static FORCE_INLINE int64_t walScanLogGetLastVer(SWal* pWal, int32_t fileIdx) { goto _err; } - char* candidate = NULL; - char* haystack = buf; + char* candidate = NULL; + char* haystack = buf; int64_t pos = 0; SWalCkHead* logContent = NULL; @@ -414,8 +414,10 @@ int walCheckAndRepairMeta(SWal* pWal) { } ASSERT(pFileInfo->fileSize == 0); // remove the empty wal log, and its idx + wInfo("vgId:%d, wal remove empty file %s", pWal->cfg.vgId, fnameStr); taosRemoveFile(fnameStr); walBuildIdxName(pWal, pFileInfo->firstVer, fnameStr); + wInfo("vgId:%d, wal remove empty file %s", pWal->cfg.vgId, fnameStr); taosRemoveFile(fnameStr); // remove its meta entry taosArrayRemove(pWal->fileInfoSet, fileIdx); diff --git a/source/libs/wal/src/walWrite.c b/source/libs/wal/src/walWrite.c index 7ced5fae39..216dd5fcb1 100644 --- a/source/libs/wal/src/walWrite.c +++ b/source/libs/wal/src/walWrite.c @@ -407,6 +407,7 @@ int32_t walRollImpl(SWal *pWal) { } walBuildLogName(pWal, newFileFirstVer, fnameStr); pLogFile = taosOpenFile(fnameStr, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_APPEND); + wDebug("vgId:%d, wal create new file for write:%s", pWal->cfg.vgId, fnameStr); if (pLogFile == NULL) { terrno = TAOS_SYSTEM_ERROR(errno); code = -1; From 344395b05a151f59b9008d1ce06b8fea60fe7dfd Mon Sep 17 00:00:00 2001 From: Xuefeng Tan <1172915550@qq.com> Date: Mon, 14 Nov 2022 20:57:29 +0800 Subject: [PATCH 37/39] fix(taosAdapter): fix log output (#18127) --- cmake/taosadapter_CMakeLists.txt.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/taosadapter_CMakeLists.txt.in b/cmake/taosadapter_CMakeLists.txt.in index 79d54f522e..cc46ef9938 100644 --- a/cmake/taosadapter_CMakeLists.txt.in +++ b/cmake/taosadapter_CMakeLists.txt.in @@ -2,7 +2,7 @@ # taosadapter ExternalProject_Add(taosadapter GIT_REPOSITORY https://github.com/taosdata/taosadapter.git - GIT_TAG 0d5663d + GIT_TAG ff7de07 SOURCE_DIR "${TD_SOURCE_DIR}/tools/taosadapter" BINARY_DIR "" #BUILD_IN_SOURCE TRUE From 6b473b7e18ce335aec7ab6bf05cc5a2cf060905f Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Mon, 14 Nov 2022 21:10:02 +0800 Subject: [PATCH 38/39] test: asan case --- tests/parallel_test/cases.task | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task index 1174f46e65..fac4210d88 100644 --- a/tests/parallel_test/cases.task +++ b/tests/parallel_test/cases.task @@ -68,7 +68,7 @@ ,,y,script,./test.sh -f tsim/insert/basic0.sim ,,y,script,./test.sh -f tsim/insert/basic1.sim ,,y,script,./test.sh -f tsim/insert/basic2.sim -,,,script,./test.sh -f tsim/insert/commit-merge0.sim +,,y,script,./test.sh -f tsim/insert/commit-merge0.sim ,,y,script,./test.sh -f tsim/insert/insert_drop.sim ,,y,script,./test.sh -f tsim/insert/insert_select.sim ,,y,script,./test.sh -f tsim/insert/null.sim @@ -109,7 +109,7 @@ ,,y,script,./test.sh -f tsim/parser/dbtbnameValidate.sim ,,y,script,./test.sh -f tsim/parser/distinct.sim ,,y,script,./test.sh -f tsim/parser/fill_us.sim -,,,script,./test.sh -f tsim/parser/fill.sim +,,y,script,./test.sh -f tsim/parser/fill.sim ,,y,script,./test.sh -f tsim/parser/first_last.sim ,,y,script,./test.sh -f tsim/parser/fourArithmetic-basic.sim ,,,script,./test.sh -f tsim/parser/function.sim From 7622361ea51c7038182b0192a73916c1280dbfa7 Mon Sep 17 00:00:00 2001 From: Pan YANG Date: Tue, 15 Nov 2022 00:28:36 +0800 Subject: [PATCH 39/39] docs: add media links --- docs/en/05-get-started/discord.svg | 7 +++++++ docs/en/05-get-started/github.svg | 6 ++++++ docs/en/05-get-started/index.md | 20 +++++++++++++++++- docs/en/05-get-started/linkedin.svg | 6 ++++++ docs/en/05-get-started/twitter.svg | 7 +++++++ docs/en/05-get-started/youtube.svg | 11 ++++++++++ docs/zh/05-get-started/channel.webp | Bin 0 -> 12650 bytes docs/zh/05-get-started/index.md | 21 +++++++++++++++---- docs/zh/05-get-started/official-account.webp | Bin 0 -> 11686 bytes docs/zh/05-get-started/tdengine.webp | Bin 24678 -> 0 bytes docs/zh/05-get-started/xiaot.webp | Bin 0 -> 12592 bytes 11 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 docs/en/05-get-started/discord.svg create mode 100644 docs/en/05-get-started/github.svg create mode 100644 docs/en/05-get-started/linkedin.svg create mode 100644 docs/en/05-get-started/twitter.svg create mode 100644 docs/en/05-get-started/youtube.svg create mode 100644 docs/zh/05-get-started/channel.webp create mode 100644 docs/zh/05-get-started/official-account.webp delete mode 100644 docs/zh/05-get-started/tdengine.webp create mode 100644 docs/zh/05-get-started/xiaot.webp diff --git a/docs/en/05-get-started/discord.svg b/docs/en/05-get-started/discord.svg new file mode 100644 index 0000000000..8218e3c3ca --- /dev/null +++ b/docs/en/05-get-started/discord.svg @@ -0,0 +1,7 @@ + + + + + diff --git a/docs/en/05-get-started/github.svg b/docs/en/05-get-started/github.svg new file mode 100644 index 0000000000..493832ceb7 --- /dev/null +++ b/docs/en/05-get-started/github.svg @@ -0,0 +1,6 @@ + + + diff --git a/docs/en/05-get-started/index.md b/docs/en/05-get-started/index.md index a6b6721383..fec734b64d 100644 --- a/docs/en/05-get-started/index.md +++ b/docs/en/05-get-started/index.md @@ -3,6 +3,12 @@ title: Get Started description: This article describes how to install TDengine and test its performance. --- +import github from './github.svg' +import discord from './discord.svg' +import twitter from './twitter.svg' +import youtube from './youtube.svg' +import linkedin from './linkedin.svg' + You can install and run TDengine on Linux/Windows/macOS machines as well as Docker containers. You can also deploy TDengine as a managed service with TDengine Cloud. The full package of TDengine includes the TDengine Server (`taosd`), TDengine Client (`taosc`), taosAdapter for connecting with third-party systems and providing a RESTful interface, a command-line interface, and some tools. In addition to connectors for multiple languages, TDengine also provides a [RESTful interface](/reference/rest-api) through [taosAdapter](/reference/taosadapter). @@ -12,4 +18,16 @@ import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; -``` \ No newline at end of file +``` + +### Join TDengine Community + + + + + + + + + +
Star GitHub

Star GitHub

Join Discord

Join Discord

Follow Twitter

Follow Twitter

Subscribe YouTube

Subscribe YouTube

Follow LinkedIn

Follow LinkedIn

diff --git a/docs/en/05-get-started/linkedin.svg b/docs/en/05-get-started/linkedin.svg new file mode 100644 index 0000000000..969c6f03af --- /dev/null +++ b/docs/en/05-get-started/linkedin.svg @@ -0,0 +1,6 @@ + + + diff --git a/docs/en/05-get-started/twitter.svg b/docs/en/05-get-started/twitter.svg new file mode 100644 index 0000000000..4825aa4ed0 --- /dev/null +++ b/docs/en/05-get-started/twitter.svg @@ -0,0 +1,7 @@ + + + + + diff --git a/docs/en/05-get-started/youtube.svg b/docs/en/05-get-started/youtube.svg new file mode 100644 index 0000000000..20747b8b6a --- /dev/null +++ b/docs/en/05-get-started/youtube.svg @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/docs/zh/05-get-started/channel.webp b/docs/zh/05-get-started/channel.webp new file mode 100644 index 0000000000000000000000000000000000000000..8dba93d411d09f1b98e5d72f69cc98c78af5ddb1 GIT binary patch literal 12650 zcmV-wF_q3zNk&FuF#rHpMM6+kP&gn~F#rG%3jv)0Dv$w?0X}UklSZT>Bq1X5kFbCZ ziD_=nUKfEc|I7CvT~rlhf5*PU6P$?LR`?6KZh|}Fe> zgYobC@A*&OU#R~U`-kw~kl(dGV|c^uBUA62eQx_l_W#&V$iKh8!vA;v>-z2f5A|!` zKi+?D|55n6_{H`M>R;@i+`nMI#eTni^T8vQ^aJ?6^N;d>-9K?Zy8LJTH~7!Vf8YQA z|499r|1<6Z{CoMg`S0%EyPw?u|NsB{-@>cwUZDTR|EPby{`dZG;v@U-`5)>3H@)%x zf&Q!hkNZ#FFQISczt=zE|A_xJ|A+Vg|Id{(u?GDml7Fcquh}@2Hds-HVBLB$bk$}* zk09r1XD^7fF6Qu4mO&7VOkWZ@))=xy|IHIsCDH8!yYr^z``I=d)i%c@urgUN5lgsE z=<6TY>X_OrUqq<%Yz!aT!1o$y1n2am zJXhQ%V9uw`K_nv1sd3NUyZb8Q`(me8x{~fCAT1^PX@mDp!84)v)PXSx6vd# zu?kG%(^m%#hkTMv3U4c$?v_jv8g-WizCrD0zu1R9gyUYcA;uZ)tOiY*j^><=&mPqp zpQ}C^7vLf+gAMUt=UzC1FCasdFyQ~AfCJqgJ1JB5k{K0FtRT=Vsu(6tfq0!+2xRo#Ykw zL!sTZtGBQPj3h0(tHD)`r=)^X9^e+6x(}cIJtins${S2q?S~7M0uVq8f^xcr3&;w( zn$p|ulZ?pEWBsgQfID9=E}s#R8GX0?&iLdxkAP-~TlQcy_nE;5-^(S4K3mS=riC!W zobhX3UonYqqnZ}#Yj5?;TNK`U8nZ=xp}9RGKs+VTo!1nn!-^r+M^D<|T+K`ZyGrux zX&c(HE?QM@l7f@-aag)A&jno5T-9YRouiJf4)? z?8GU)cb!HK z1gkj*`B!U3qE@GvOV#k!qH4x)MmRxTx=s_{D?M#9rGK|~N;fq|rm%a323AXCN5w<5 zoc-EKt0(r6j!|X2(5}^i8}-l3B~x@(3}50r<^&>F))*pi3?5D_>*-dTVTN{ze%*c| zL;iZ!!!-9~(!LjMRefe;qs^BjZIP`Vvo&@jl>Rcv=(#J7c ze3}?XL~!v9Ds;E|iP&SAk!aR@7XmdE6dDF#IyR#XUd$dGq2`x9-s^Pz6HIdWfE3L% z`P2L3sq(E7s0J##k}Fovj`d(Vz5kg+;h!-#=LVgw@k_sK?D{T(#kXR{BbB3k>FbX6iP zBAm^ zf^q2nQg!&`1Man`I($%O`Gb;OQ;2>tkD#Ab$>B8yyH6>EZBlmphWwoj)pWs7h2#&0 z&bZ(OI7(I;&8BLv*6)^q#7lO@C9_$2VXn#H@DY3b62)3yDuRwz$d*e+=)y@f$u#3R zyt7^B9x4(r;)TuCRVmXgNwkq}bn~5wU_EwwO)FW%cFE6j|Gs-3aTR8NQia)gNReT> z!8yzV)k`i5@0-O~_mFhnM#>bYTxs&WWJhsq@nHP$?}(CTo$VGGnxTRm&~W)ge4+#F z+|Cf?wAhZtF=@Dy+$z-bWJsV=cCto+ZFegYB!~rBGR~=*zEzk&0Q`BL+#MF9qZ7NO z7PJDR(co-R#*nRa89Kc>NBPC;$5JQ(vy0?X+yHhBsuUVuU)bljnl3xhE^DFnS;J^K zlrgnIy_E^-igr5tvvu%ezFISF@6;txsu;dyYM}I039)cx3P?ntmb!<4*4tW;{%<5# z;nj~x?EZ+{;jV19$=*SPIG`ab;27K*%>!Vmr6qfy%*;aR9$SiAx9$8(W92{o*@s%A z?E^Df?QV}{%5#2X;Zwx4oBD?(lWKZ*N|>ycJ>Hyi5xIK-a~L(@E$31IOEcF zn=TnU$BqD;TekFCsc{6U{^G{Tps4t;g~2*WP&M)>8|kDWid86B2iMuD(h2<3OcU zai`<*w+aZN>f}AFR&Cr+1Tu0q@4=E5jKf=b!|Dn<`2}^2wwE=xO-EGnf42r{%NQdr zn~Wf!x5p>QD@X&(UI7p-b`CX4QxD#7+DCxN5ZN%@TF78$BJ*`nJ8ZNEphq;s$iYaF zH|KrTxl4}rV6_au8ur?f?3s)ixD=J(K16I8(8{gJNxCLd;RNy+x zgPK#Y?zsxOO3O44efc544PQXqYaoFW&V;W&npY~dXbby6#_HwKR#EGsK{Kf29kG9a zl|c$n<2ZkfVOOOJb{h7+7#R^-`FfgMs>Is4KEZ+-$a-Ql63oW7sDU7Yk~f~Lv&Ru< zED%`hf)~x%Jz%~zgWNjAV&6NIm-Z6njx}UkJU=0VdY@%UBLrEpjVnx1a`7$f4Pk3z z94AQl-xcp&KJ?`{Q`jV9k*amSs&CCuVq+o){2kl$eEp2wYXhOe0QD?x?q*(x`nN)w z-?RkMP=TpX$7fgl-Ut^SC|{0n$aG_5)D==&@%VUA3^O7t3KHz8%5txhMHu@u!}7{w zSi}_asYJCSR&Q17+6_%u)G}qNXHSFc0 z%|M(JhZHptRWCl@xbeNoZ?E`fhtj;47CwgkjKl;2x^~0VZ7u?@59oP&>-qse1Ibf6 zF?Xdo2;i*5?!^7Y0oMMNEo4jOqaB}JTjber_#?Qr%a!KX9x9PRLvtGZB`IgFI-VnB zj&nYE8+Sv8sUqu)P)?P=J_5#-jPR;DjE9O8}CZf!3R)JmOw&VsKnq{uRm0Avtdf=Pd}0Ipm}5on!de&b!e15TsXY`ajld0|IFD3Ek8t(W{6nXK zq*&_qiqXUX>ZH`bdrwimC3@A`7YfrLn>l7__^YU5H2ejJlJf%(7~<#j(aQ1vyqwdP zcDdPdxZ`fu4e=h=E*m(AYY>U2netY#cimB;rM9Vx@+St0u%YYmb&tqpX*M5sA%`$) zygj!zfaWcGciH-L+CH4GOmkkl^QL}~3|jVpWdfiUF$3G*1%swF_}IO3>Wzyql4@Ir z@}4y?RefLSm~MBLz^c|EX*rc;r;AcQ*)I3T!6RkpDEDm3cGMIeu)>BSQts>j>ytsL zzI#suEb3*{uKe$0$G@`9&0ighsfrr!+fl~ZLwgn(Q+yo{K|y8**4kNOv#BWtJJ#9{RC@YVB{U1xE56i z#edb5J)3F*bgBv8<}RnMF@|g?E6*e4q_m zt97k8BfJKugJt;xDmzsIG;-3!xI%F0I`MsNLc)P8^+>UdS1ICt9w}fR^STZILjVAI zM8l7A?`#i`Njo@%ToYgyGIIOu%tSp|H-MLm%6rV;)pkz>qMq2BzwXOeY<$6XAx!)w z%3Y|d9*3!OveaNmuNmLEy(~9SR*y@G&_Aym*K1b0J5#ovZsJJql}Kb#%FUJQ{N|qP$kR-0sp~TYddbo5Bpbgvh9_6dxETU7bFy=p{8n{$q)`OMG(-*mf+o5_ILg)@AC~_zs7y&^mHbtD0RL6WSLfMh{-Za z;Jy8)$d-V@if%%9)I-V2U<$&l>PxAcq9c!N_Q$`EBf?Y z;i{=}1Upf{vNru5!sEw5axnQS>*`=B;PA$f^=!zPY!JUGrkyb;V`D_zW@$Buim1NU zOUDH)oVUId4X~gc_vezfq8a1~0VPziJ>J~M9Q-E?-#}j#PFUW<1$X7VG{_O(_S9!w zM1IW$h9#zS8}ys7(*Oxl%pW<8+-6hTlrFvV=xg??B?hXGu?qp!9|6$KpVvnXqw_2e ze15amaPBCS?yIsf%*^X_zhuB_zr%QiJvEJLm+f!&0nnkU zqPLJVcGbFiBiLs{AqZobf+m)T#+pNQj z8IDXw-$mGF`qG_6RKwFw?9G&9A~?xBX-iCi#+pTat-Bp)c3Iw)kzf3&JneWNxXNA<}#`#oEVPp5d#klBN)PdaRuI(T*K+Mfk=WC1XQnT@;0X=Ueia&@Sk z3{3#`)a|O8vE0zTtdY%_Wkb2h%H+n$$EK~m$TJAWLrGb|y6m*n4o}4!@aA}AX22|O zY=&T!9aXV#+kNjUJC=Hs+&`%-f2x)2zHX^1p%8So#A^{<18bZh{Ow#P=Nb@=_4 ze8OS0AMq}Q>FnnI9sgyh{Imzo1vMFHIg064OPaXrD0TUiVi*6^Nk5?B17m_x)P;I^ z(vqG}08y!-MmNbAw6ILOTNlrJIU#I+J$pVDHg2mm#u_M~oXB%B$l&yehPAckWk64r zIK!q`yI6SGwP)&>ap+48;6e1nX{Zy^$WZc^s{DQ zga!>-Nb&3?7bnqVjtP##VYW_L1o}`(VFU{I`Gz#_$KJy7b&^wgCwnq1a)Im{J?JR4 zt5(WE$(%y1JQm~kkp?DgV6J~c_!nGt{}oIq)F)-CZZF*38&hWq0ns#Mf3G+VAH0`j z4xb}bU~Nh>e`Jfax_VeG)#t)!ZuyAI&EwwY%RNL1V-x^7^vRfJVD1T7>_qYkT}JvS zo4N@>bar5l`R2SZ4M7m&l=LvWC!8cn?4I?0TI|q>g;JYrPRb#tK7;mDcDzX0Y=hJZ zkFD#FsqA2&?p+dcInTV(?|A2<9AljFABFsS%Zs1eol2c9vnuSpSg;m?#VwwQ7%Sv- zj>qC1%Nu%w9x+1`I6E9B_Wf%K)aHdZqsm-B@6o{gt)zho0 z7URiHI%9hRWczH+jcj*mMjTBaA`!GK2>2ljSx=y)c%`&1X3Y<(VrRRTr&Mnbpl{YC zxSzp(vLIILZbwyPca{*a*8m50Ee0{LMgLKw`gk=!d?`A<+qmcC#cV zWzA=0nBizDZknXAe`I(RT_jW)PjVm*5&qdBMq)PDSx>H@ijX+kBAU_NOi-I%+X~2& zvU=207_jY~;s#3A1f`|CZ;BAl#E9S-hn>9~r_o${8xprjqgiYWs2VP1Z4-r-HjBFH zz}6w&Ek%x&`I>mH*>IV!!gIRA0$~$x&Y*TAcf7F1G7bdgJ0)_*{Q|QxRQR1bqN5^j z4^LJg%PomO;ff5RYhU0DHa1ztc)UQ^(S({gMKa!4m}=*2{?K}{=~3VxnNbKCLvc(Pys z9;UwYq&pwcK+`g{a0($e1Q`0=s9-?N1J%mi)FQJ~bzb$tX6g~I{#w-<_6(lWA z5;m5Vr_XrZMeRVoJ5b(9&QLNt?Pqo#HX;sLuX~M;V-qujSqaTBgf45UNeMLjL9jL` zeeiuKnEq73Qy~S-ImNWwbl=gj`)rjTF`d?=+IBw%Xk*~y1u=?e8a6**MIfeL(Q$x& zrT!N^Xh>N5pUQuGh^04x^fDAPx{b5C!ymQUhlfZ3V0GJ!P7AK-P1{ zwjP>HDIQ=_l(%B5JoT7j3|{`Aix}wsuOgi&z|WKX0&mv|u4@y*p~is81j*ePvo9)FIFPT;%f_o+zx)4Ii-@5v^#e=lwDyPF+rH% za-nC2nXPV!jzrvnbul{6-E#WHq|_d4-EJiIFXGc-TDCWJk4pFdJR;`#?N8ntY@=Rl z?lOnH{x&h7Ak~i;E}V!dWdAV>@s+ZJ?pz9*bV~bZ2Uck>2T5fzqGlNVj(%s&;&e+) z=LVQ&$5SV4Z#>{EAsPhf;9jt=qi++I+vc(#pFz{azVMvwkrNeL%)#egfghlfal5aV zk);6%bnI$1=@zGvF2qVOQbck=BHdn_~ny7epQwDmQA7rwz{^98!fys z0^+{2Bi~z}Fn2)5Tu5ra3KS?&3f|MdUC-J1ze1ZI)t-7EZmmz@eZ#YJel;yGEE>j{ zQ-)`G!cx72%I`zrqxlU0CgubFIn&!?RFGfMrahBxIlm{32LOU$Qf{o?zEFKlO(U0S zwEHaJ^cpPoK*5LN@hT7#Km8C!I1@})POnMV9hE~FUIQbI@*UR2chvYYizJvOEpDr@ z%IKg1FfaB^V?ISHg5cqL_RWKx&&6@N6)g#-m@45Xu>2rL7lo%^ zl};9u`?9z}dm@(9b`3aV>S45w{O74=CX z18@xD@$vWhJ$xN`(IpMZwoBfKBXlby(&d0cn4Moau=*f9fjvFW<)6G%0A+}p$bzEd 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 Y@|UA=C`^`i?e6IRT79jv)5(hf0N>oP)c^nh literal 0 HcmV?d00001 diff --git a/docs/zh/05-get-started/index.md b/docs/zh/05-get-started/index.md index dec4d800bc..092523a556 100644 --- a/docs/zh/05-get-started/index.md +++ b/docs/zh/05-get-started/index.md @@ -3,7 +3,9 @@ title: 立即开始 description: '快速设置 TDengine 环境并体验其高效写入和查询' --- -import xiaot from './tdengine.webp' +import xiaot from './xiaot.webp' +import channel from './channel.webp' +import official_account from './official-account.webp' TDengine 完整的软件包包括服务端(taosd)、用于与第三方系统对接并提供 RESTful 接口的 taosAdapter、应用驱动(taosc)、命令行程序 (CLI,taos) 和一些工具软件。TDengine 除了提供多种语言的连接器之外,还通过 [taosAdapter](../reference/taosadapter) 提供 [RESTful 接口](../connector/rest-api)。 @@ -16,8 +18,19 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` -### 开发者技术交流群 +### 加入 TDengine 官方社区 -微信扫描下面二维码,加“小 T”为好友,即可加入“物联网大数据技术前沿群”,与大家共同交流物联网大数据技术应用、TDengine 使用问题和技巧等话题。 +微信扫描以下二维码,学习了解 TDengine 的最新技术,与大家共同交流物联网大数据技术应用、TDengine 使用问题和技巧等话题。 -小 T 的二维码 + + + + + + + + + + + +
小 T 的二维码TDengine 微信视频号TDengine 微信公众号
加入“物联网大数据技术前沿群”
与大家进行技术交流
关注 TDengine 微信视频号
收看技术直播与教学视频
关注 TDengine 微信公众号
阅读核心技术与行业案例文章
diff --git a/docs/zh/05-get-started/official-account.webp b/docs/zh/05-get-started/official-account.webp new file mode 100644 index 0000000000000000000000000000000000000000..fcbc3107fc51ca5474be653302db777de7d1e775 GIT binary patch literal 11686 zcmV;XEm_i1Nk&GVEdT&lMM6+kP&goxEdT%z2LYV{Dv$w?0X}UilSQN=q!SqT$Up|f zw6}Z{Y_Yfoy>Bntvvp8H5%o>;SdBwha3`4RWek9?B>zhP1^UhVi}cIrU%!7{{`30F z`-T0(|A(=UxBoTy3HyWgNsN0^{&Drw?VsI$V86Wn$^G;GKl}IhZ`eP|KYo8~{p0?3 zs9&gmvVKK>aQ%||@re&I=nL_$=fCAY!T$7raQM&qPx0P`{j2{M_R01G{FC|L`2X$y zj9)zd)p>jUyVMi-|MrjlpWJ`Z`=$S({&)PZ{qOl70Dn9GWB-Hwhrp-vKkGm6|H6Nb z|E>Nz|No6}!bF(v9L$$B`;t6^t+;*c>6wEmDnj4oQ)soe_W0QgCtr~i^YN&JK=M6Y zS0WR&CMnF=^pn^dbPOwV1blbB<7pA-H+E!`y#XX8nx*1cn1d!g$zQ61YxSjS~C_NBtCdn3swd)hUFV zKK_06qz^pl(edIVbu|i+qD<6~8|x=5D&9-2J#2=~x!B~6cobAct)Z4r7s!~9J#Jm_ zF&#}s893;?#|$TLHllipN?4$$jdjl9h7&UVLFxb6zD3+tzWMQ}8;dd$(2-wv+s8O@ zhyzpZEAxzilQbEW9Mvb?KU8S6EnB6fznY@o)O^8@$HQ|C;nQo4lz3N^Rw%Bi=VhF% z<&84q(b8HCWUsj(^ie}QV*d1nM~miJb{u9aHfgFD+VD2p`|#HK2%8>TjQfd>YoK`Z)8U zDUfY($#*^wFv(536@-J-avmE?(S-umV}lY>B^sMX@lpyP~sRBNbB$YdZ+$@G&;^wCWzCkjy4u{CD#o% z@RwU^CO!xa|C(;<0w|`(R7nh|D{U{vgIR$IsJ(ad`hwB0F{ z*7&zxY?*sy)Z1d`YMgbm!D=e|5cAlbH4-)*VbAUcS2w76lT75BGb)L>cm@VyB7c{& zCw^~&Bk1Gg(WhozbTlvL-Yn{elfwfJ1Tmd#vQX$u-mIF|ta4?y-rphm$WfMDs|Vsz zAgAt%)Iehw+)XG?5^PxXG z_9ZTv4tqg3h)N?*$sbYlXvf+`@?x@Q0TrH`MgoJb+F}VCaZTAV#3MSRX8V|&izX(e z9Le53YvHsGYc3eeKjJ>?DuM7p2D~_m&G+WKVq&YBf_?U5@`9Oo26%K^GsM!OXzYL; z;x0ef&?nBMgn-M@WwsfVB8%;-Rs+PI2YTa)@>ZhXWo21NFqUqQbI3t{Fw2rwEmJnt z2m}MCjc)kb#MQC8llwB*cd8XYq|99Dl`7vf2aACJlJ#ZtI^%C247}gcx(f zWbFW@n5sHm1}vqAjp<^qeHk6x7RoJ-fB?<$?Y{W+8zN>5Cu^Q`9~9M-(`tFjUhjTp zT7Tk$3Z0uaP+vvdOkha7YFBVm+g!-0@^0k_ETkKEoIVf~FsTB$vP1*cqDhf#UW7~a zPwjoI@!OGBAdQ%pY~mRQt3&<($0}3>rP0UVj^9t}b$_0Hi3KJknvsqk0#Qbwn>zSA zF#aJBjjd1^9Tz2bE^3MSwrS1YX)Dv#&RIIL8h^l(Ws95O-zx)H^o6$Ri9$5j=fqUl zNp;F=KYyhTKmIM4o3m^DZ9xIB#Fiw?4d6TpR=yOMR%ZQ8!Fo z^4L)WRwcw_TI4&Pva(pU9Vpa`mgu%$#NHhlX@7sgkwhoFdq14ZO+jQVou#(Ys&8Ne$Dkbb+ zXxHCTMv+DXiP8r_fNGSxZ?d0noUGwti+P4QD&E?*B=iKBn_|g}E}?E$Q^cQJ-M3;L~I1iNd>?^I{8X&OuFiA6F_>W0gAG#k@iFCo3*z7*4I z6~)yQQwOkwgu4y58C}fHD0;a0IkF(v{tRK(@qz&YuZ>>WnFvbv6Ni4*J^g7P@tehx zZ*>z3zwZAz`ZnxclYzSA%f4LkZ(67Qa=uIP!{UY(;ocFtQ+ES@w}E|M`tD+k9sKnG zhM)aX`4&$sqj5O`25}#boAswf@$K0mL5`BS#yZ3DTZ(wS*(WD?piM!6= zFyUaw<+*`tTR78}=-ZthIPWz>pW}!|1x2R2cCSzf(3IMmHc5ewn!Yg(aOyXm0mo@f zX6(PdeKkgp!xZf(n>l2oXTOrkJ5T>?`kN%?ssV{cv~Wk!z%m2z&K=)8Q^C8Z0RA9) znVh}}WyaET4O&z#vLn_RbFsnl(gW~65tF`-Q;nVmw0(TdIp{iFmlw@`qlTzn*4FA~ zLeg!YAxOG`&i{jS^J7sdWR1reQZduH6J@AITKtR|w#Op8nYvrif~X0J`yef*=6+~f zCAj}cf_{D9C=-=|t_#%p1e4mw_-2Blm~m%cMYUj9kJpFF(B=AbGav(lPoZSu|Fd#) zHV#v1z9wO-xqlt~Zu~nMj$g`hJIYA?ClV_P2!3}L>#94ew&kmp$)#8}!6!Uo^adoQ zn+~RydSxC+izO1a_LFKuBaVj7H*{; zhOO_$2xX1b`^;>u#Em`_Y;^r@1rsMkFb||-?N(jqA1NanOotxiBP9WUWP|zi4;>i7 z-nwV|(o%FE#G)x_PdE0O1o{jNJnF4Y+i0nxec5}p_}+tjb;=dpB6Al84CbItD@4Ic zV;yn@|4!+z01jQ}vA-wghbl5nJVwWBixdCc1{W(4lQ#2_y>bLA#n$Smz8OgC(S#!W zeN~K`iCiU%j$7B@`=Z2Y&9`jU@YX~;sfS1dfsFUj*)Wmwm7UO2$9AKqG?fxH$vzOr zz%jQCOr`5GAIBDS92LG zko;wHkFlzd5X3{|IjJyNpcUdi$U+s>O@%)e_T%}Qe32TN ztm^HeM;u@hZ-89Pu9f#o6`*UXdv$ON6f;{_ft=$It7@`b&fSFqVa*sK$TRZ3r)Q}S zeDAgcp4mal=hqwN?i3;DKkhZeIFQifr>eGB+J8uiUmoZC)Y~`5svta z!`rKB@m!x5@eTM-x^IE_IZ_fn3;gvIDh3z&u>tgl0b0()+hxGJZtv^&iN>85@No!? z=%^U}3GOgRjDy7C$iQ|n49U}VKIsrjJ}4f9e7Ui1z&gEuT*DLiHyaMC! zc#R@7q7K3-MKRySS>$RZu{5t}1&g+RN?a!lm6}U985L+l$+xb-Xe;g*3&>UR*`n|l z9uJjS9_;*9BJC!l@z{cH=dS0DG_)Vh}Mw;fHHh=Xr8|Aq6s*rVf-((6;1%FYvjGM}%vmZNugZ<&>!cnk zwdQtmJIb|?HRhsJw#>pjul`PMnRZuOm_FV@&pZ=?mT*J{rDXaBxGd%`Rr6Vz9v#s;M<~CQ((M^FY*zulnBdbILvt* zcz)YoAnUPpE?Diju$#Ch^nEDb z7nf&8bQ>Cl)l=YJTS@9q%s;o5*f6*M{g)%yln-&{^8lpq22abg+MIdxPC&wR!9;mP zhKYET$>z**k!JBFXw9YL*d0G#)k8$SXE-a|E}W^zak)_8a$3)FQ(P?aTs34b<;N_o zYfeIMA23ojP$4rB_bZic?xJ zERX+^fECPA9C*iQ@+h4GwdMz<){p&v#?P~WF>6f!e^q#*@)(+lgnAm8)HUz9`P;pZ zj+Op2WsLV*;f>KDZD*XSltRt5>P1&|JOD(Q;JrNmqhy3~w?-X7!@|$lnw7T+O8-7v zl)`l++sDrD%*W5jW>s9t>Z=}*u~i&CSf@~1@tQdn)dV}d07AMF04?NRi<-9``6qhX zcEKrz-HX!Bv4c#80>S;E92LJsNh*H@4@pc4ViG5eD)(qsQu}sI@wdETBs%Sca%~ec z33j)Qhq&i-wA$a{Wag?L~m( zp$O+#Gmw2D5KPyHebe;xg9*5fEu@6GO6}F%UsNXj_4+EyRfuVigzAn+XsPR%sy{Rz zUda}Up;-cQLSUOO)Ws!#gfTuo1XPOyM~*k9wN!Gt1vU6+Fs9(DgS+-3VMO3qA>m;@ zM>VHKH6&``b7^&!7{?ktBh@#xB8&oD=JISbT?9ScND>m*K1%{T-ek$U?b$&A3U5c?DXCxSZdR^R_)?p5PyYy2rq4S3}uZ*sXKB|4(u}?8P0;#D|NqY z(R%|#eTlXxKNwSV6+RN)1kUqNI4AwD^C~^jiL3rK^s(dF($p( zsE*!*#GwY+${n9wx+dXsA9JYVAU02XtI9;U>X(60c;LO&l#d;7{B$ZLVpWakpz+^=DA&i(fp^NyW>r0Ct^n;TS>h zmH*07CsT{E{A1ILR@&1*1#!f)C$&tK@STY{hjfUM39*f=UJH>>E5#nX3@9t{x%OWE zH&tqqf5lpO4Qu<$(@=3Bkkk!{K*R%ayO4O}|H|D`NAJ%g&cv=o*jL9xIvutz*8_`w z)|_X+wAxVsRjDI42xuJWJLd(5Y-X&^R|2RD)|9v)93Ru+g7-(2-G_%3JRxHLCdb=j zzL0bnr@k6AdKWt}NQgEXUG?E26mznkn;fi3&=%{7CE}f2=j_hVM@VeWE^k8dp?(dC z#44vpgGG%cvJwP_uyxzvww-%!;Bsv1wOoD{ch1b>$Ejz%}2HEVRAnxBWT z^*$EdP3xo3EotcglM&hePqpu=#c@FXQT5$Py3pCIcdhV@dqaA&baC1mNE=dP?8d8y z1$3_%Cm${~NeA*C7C|y%TLpXT4EujzG+ZlpM%PHV+}DYrwFHO10-vD#t5z}KYO5Jc zG(u@!ABgIS`>ZZH&3`bbfB2j%4UvH9L{2@uWX~F)o0x5!xAgVAt&0Cbn|16(Tt(85 z!9@72gSQpxTgAHTEojoDjy5at6Y#8L4=$~~UwX1aabs657~iV;_jw|i(dFwuH|iER z6pz1U-xb&ub#0;@F4h5n2u_}kPxUlat7Wy30bU%8nf1yMHzIzpKva-VEDjhGM!MJ* zYOAOswcm9)m^RS358#zXfrqk2e=Os5n2w$+1=lt`etRAl`ijPsEttG2`9_uH&BT!G zEFIbfY-=MzvpuzhY9Qm(*ba&9(Nh;b|Kjke&oSO#?m`kr=N)6edB&r>#}I%@4cTyy z7iC>_FyLye+S0l#%n$@&3HYgolv2x{sC95aa>lWf06@_@e2YWacEClEwu#}G*d$DB|F{vpXwj-0V8jLSv)qraSCfDvAJWh{ zoSjBRY=?~-&{5p=|4n$c|H<4Y6<%O4H|C+OhjDK{3BPQiNtn+f+~Y__WKG>(!$GKU z#2Rlp{4^_&k5<^TS~wjhshPa&E#Rr)*fPfZaj{lqjJ}Wz-*x@hZTScK$dztkW(D<{aSQAj;Db7uj6t~;aZ?h|>&OTUd_y@A@<}*4`Zcf^^PqxOpP`ab z&>4qqUNDA`L@IttCl9Z3f2T8*>6-zPQoRj4H+vvGN3=yj>*UbSLtN7ZMsdX#h*#PjbjXLiL0`A|JoS?LyFVU<0V~%G~MFggt#jC z@;5~}ZqbbnpV>_b>ebOf=`6_=D{6C8v^d>*d$*TBA^B``4 zd~Nz*9)S-vRY;l6#}q%m!W~FA#Fsd<5<2Z{)i4rqK$hVMa6;R(n~l~h2j8VFi(`F3 z`}oCSe%T-t{WHI8^{aK=WHeTDT1hU~#$$uU;j52o%;YfLLJ&vRT92dfA}c>&sNsdf zF}27wB3B#>$jpAsl-|}ei9n}_f~?71d)cQoI!GXzq|OdayGnTx+&-%Uzccteb|3e) zMEMWGztpnmk9(aC{(U~n?M=&^tzZ~OEPc)xnc1J-GckFtEXaj_*yaWSdC|uaFK-C- zrPfgd+#3yyGzx+TQzx=3bvP3L#;R9=3y|Wo%ib?HR2LwP{%^I&I zm#~+u^VR5+56K-0I^pd!S-n;L1zI~IX7esRB<0zs$Lt>-5FqM1P%q^H?7V_%ZgG^D zpDqbCpkLC?PH*={e4ucS119a&$P;kmyk$}z=g;5Q)+1?&Qt$n69F?~{^GR!Kpr0K> z76dY-+ltx6TWKL+ZTtE7uh;q;nq1k}QkE?6wu7Nxaag|;d&9rn0l{hQr)e0_o%Fdi zsLk5vlvfV}hEMg~B40 z((W#(8kse));?;GCDd8ZEt%3^LT^pn%N}8~;2|O9LaXy~>|rD!upoH}=Mvs&4z5W! z6X#M(wALCK0wOfe0YF*dLp!4Wg3}PlnR3b2$D!&7MV|1f3@9_rp~{Tr>)w9Mf^xC{ z=BPz{aY$!?4LlTvr4qX_NiN&Lp}(DTn1Y`4u&OI!#7FlmZ1#I}WhZS%1Xp$wVZAuv z6fm~vM*c~658YoowlyS+oni|TUnz&IOvrIc=T0%`)q5gy#X1s(&bL; zNx;3_vWjoSTqSUx0b9SE$^w#Xa|rmz4>1*#3b^+wl)sU%9dLL`4$mZ9IOILYsIY#T zwlR|-5t`PSn_PI*qrD!vLa{2PrkdhF6%ub%S{VNIpP8%7t~Rv~zyx_E@k>odl(NGG zV-hU;1XWex0u%2!e-0^8#?669zM^h?2O@2PDuvB8NTEG&PEFUaNu1p6C92k`8vSjx zj=vIOaV&auOTVkhwgD7bea$# zfc~qvsA*xp>7%Beg|!%dI<*PjcRJvXaI~p)W^(O`O>Jo5W0t0z=`E*P7sFhqg8Snh zBZ;4_gmyYhwn~_AT`Mrtv&~+kcW2ukHnND&it(&PyTVk!&QLz6%u3dFCkPMeM>&=> ze>BPG86~;}$0A#IH0a-9l$(g2mA-gtCcNz@(7F?Z zVFy}7iMBbuBuFPYLpUq_02+UMUI+X7u@qfz-b+Ca!259WgvC|$B3oHwDu_mgjkYEd z(tLu&_=dP>nx?c+-b!U1qX@$aEq`6FxA_bp<1kJZDv3=|GC@;wy@xA$TkQoYj|{T7 z2Qh!R7FbZj$8-iU7!oyLtRp*?4ClHq!^XANq7YkC%4L101A8yZ?IQM$J)P-m)gDr4 z{(h&QCQgGIBJnA2WjHtE(on0GZ}Z0FDR6+zA1?*3m5>w9O$7m7XZFz+US~OJO)YV< z_;O=#FQApZtA(pk;QabinRxqDGa85FN40M&bups4ELW@nBZ6e#J+T}RMlurU``f(s zK-2Is{;&iHrx8BLCjup>US%?4l>N)R#^w_@));)j{Sxc17+o1sPiR`j;Ms?Jda2Ai z4a@g&xObLq_hc6Ab{_sX(PrT_n_-Gx7a}Ljl+tb67+8r*ITOLcQ*^gnr#)o*1#}PZ z?qR$LU^1+o9q0%gFlawiIc6k9?wZ6O=c(oUM7;YQIBo4gbt(f-Mw~!Mq~?Us0MIUj zSAyZuy#kAXVW=(6hhkb$Q%i9MiZutqXlMx&J+v8DB$g$~Yz`}DVW?CgXWloZ0{{>Y zIE;e}nhh|bY6dCB*l@|Z*Ac!XMWKBE`W|4?6`ylLbLb5j{LqXQ3Zx9TZ$5L0!vK<(t zh{C(aOCPq--RRv({g_$(6cLGq%32#OGAf(Z)(R4~o75|Lj`y&lmC*PRJmtVLa4u{z z5?s-YGMm?5{QLyaPBvj;q93A&eYF1eD$BO}n4} zLX96L_Qfp#cr9Qy+EH@(p_V_}#~ctMH8}E#B$K@OX4wrcP^OwtCnn*@Epm-EcT?E=b0Ez<&jHpk)i{>vSN!Wq!jsf#g6k!Q~hrUBEEH!pFIn{oLZvq_-a znu_;w&rIfR8y{U^f9c*@8iIP}A-GOUp;8~2iwR#w`VZsOc>|ROm8I$R8J9l|>;rpz z3Oi#?KwQm|JU<>iPH)D7JReDO4IWwVn;Z>5ZK-6Lq!3Gx9F^chTHM%FnAbSDi?M5P zCK=2j)|$-U+iZq7Yo0xL%s&hTx`5kb6ko1@kpB*NE54+I@-Jc`0XLpg<-6na43yFT zX+0XoGquPadq3Q`-nsupw;6!Q+9rndI7B@hj(pj_@U^Ifba9k>GLz8O;RHB{+o%*| zI8TBe9W|3WVguTb?Y?iLz)@SK)G5)=XP!hBUj}-_q~65;L9?KN`YcC?qJE%o%`SX8szN(YB#4|_!ifGq$9vFRS9u3v9_OI(tW`VX14Te^~&z0Mk&QwlY3Syv=I-ML+=cR{g(gitIJ0;es0)8WrdXoxDgj zwqjBZ%3=z;D}vjUyU{5|58e*(pQ81zPPrX#8Iond!c4EurV8D4lalbOkyj@^4P#(C z?T%+H1?8$=(*ll7tV)#f)6?A|#%dzi!nauAm~s%IpCTzCiWMtBxyzcZfP@k7OfLXJ z+^C=6M*{6@s1|KZ8MAkfk>jj|>lOjXsl}BumbqP8a-romsBf(jzzN@1UtT06DER|= z{?67?^^L0Pwwr?j(mtP8O(R?isztWOv7W*5kFc0;*PbJ2XHDe`&z7E@@WWVZ|vs7Q3l6^)qAn z$x7#fTd68*E=G&;ciQ}0G$Vc##;&!MK7G7~(WED<1>jP;Ia*u+9L>r5AFK8&23{WA z;O;C2EvA*Stoj`s<~&!tS-f6^T9VkL+pqOn6oh9Qln~lEoCJ;$^%!+@x_GaclBS@+{Q6EE)0g6 zh;#(S$QGb>gWkAHFWXjb`o~dm$OPHw8H zz6uIU=i7|NG^%J?&V%iR2MW`We%uImw`%a=LET$*sd&St^e4}!k0St}4s|d4g+!vJ zL#39QXjSSUgSb^&rDq%h6)TC_HX+A|M$UW7kxfOC*;R$m<$Em8Qi4!)bc|7?Jrk7BBgzEo9AKx9ebNkPJSaL${77HjJ zD6@We&zT$wQ>@J318||=|Lv!vw`iuq<07xnmlXmU(Sz(_zvrG zA{q2p!;_!TbB19~!*lj9-5WzlbXCzYX-AiHC<%K}(~%lGrDL+VdX#MvEEuw$oi!|bQSZMB zRH3~gRlwp%REC@1HX1eg+gc(`jaK{#a*wrV^ ze>@hkNIf)8T$|qo{j>iVmz0>(&D)8GxRwZd_VA#=?<HspL wDYutnJvgZO?pT+qP}nwr$(CZQHhO?th;bIJGOCo9z!|_wSfG|Eb)=60?}0&SW>f4n?Tt0bYCBJ8%CitR*g&yUg?ShrIV-NbfAK^e^nM z37`8n<)!KV>5Kjy{s9k6*Yc(Bo9#XCjxUmZ=~M54d+y`p)$Y#k@UQMK?vLfS?t%VI z@4yea&&==C>*+h}neT~5z(?W7>&xzP?QQQl@5=Z0AbLMe=hyD1@0;)H?6q!*3q$624LIv5(xZ-6y~g=f9Y;ueU3^*Sx-zlGbJ&#}Mq#a;md(nm-@`gn0j??8U3V#C+B}2ByP{I+$4X#79#(`K9*^{%csK=?d{LmDRXqv2 zbPesF6+(dgrRFOB-28V=!fPp7U!qP&=-)y1WqfcW`DBR^F4ulkqOKxc%qUUCDP2YIxbERk zRO-%?!`vGl(wif&(nl@O-pa5Qv~VLuk889$RzRXknT??e$S((?9lRsa_KMK9VA7so zjloGRW*jqAK`zI1%13EtQwQQr3!^}?0*+-q{8D8Bx&I38x>T}S@J`>fd}D^`-Z=4Z zXbF7KZ3eAz@eh8wxmB|03ki`NkMbw_Y7_E70=MLpG@txehQ{nkF!JOa#p%|7=tHjo z3)>kk$$DX0p%9$F6ocedg)>Rxi$Lq8$mfMR9R+FvtFS{$pdLZED0&6Jf=M~Sh&6Cq zwlJ)q$<9Hkj1~-^x<=)Tv*h2KuK}rP;T2~=gHRd*GYx7L;;Nr25m;l-!on!e`?S>t zP5pm`>gOtk$OYFQRn?6@jOL;Gnwt@i>C`o1{UxJB{KG`1M@6`MjQma_iTam4!lulN z-Sfn6V)}MwavI5eyg2l)&zS7U#{T;h*j&X+j44Z6a*`GKZdYXEax;EEac1dCG((dB%TCdaf2Scov1p9W?M+oxvlU@H|}Zy52`!#TKx4hnE{IUxDgW&p=$i9UlVTz?vF9)5y?f?I{cVL zK$E>;4l762sEn$hQ^nV{Gm(i3c*3gVH+d=$5)f*Q&qUTED*T|HAyv)AV1#1|g-mtC z$t$$}Ft+`gc(P*6`)t5U0Do^i`_@2dc{VW~D&znGqm?dm4w37GdQ z9LphAAL$UAL&Y>^GI7|+?t~vfcz+EQcE^UQ+Y2aI=dLu>KfkK2$DIHjrWW>sbQq;{ zBsnIrDzC}lAHk9f~tl23m zKS_C(>g<}@y!jJMI$lU)gQw#CA{@2+_K99@!}1;w~CYJ~CWX2&&f!4l`KwE(V+vXL>Q&WPO6gRQw%UN#u> zBTx6oaci~PUc1iYEb%@Hrj9c|^$VPYux3Z6*6btdU^+@sXZgs;aVP?Vxzcg&83~Gc zhHg9)#P2c+2om0C(&}~-zLh0|9u@~gOOu$zuf1?dF2_!rH#x__%q`gWR{Yh|+@Zzsl8NB+pK`FS=D%hQ(&jH6 z>%?D=`a{5Orp{1^z34Ogcy{MtL%~KHa0@(>kL9weO3zC$^n~oHo9A{ES`qd4BsOYn zyZUr*lBr;^^fm$%bh8HJowPEJP*>pn@Het7h)abBb7Pn&Cj6o?Yv6ux9oM7n)KYQ= zC73Td(`0u|-&!17DDu z->5uEhkWG4I^43k57L`qUZY#}efV4neZ+epCiz`>8u)V|iaOd18bIog!Rz*(?muna z(}WRwbe~uvvPP_F&WiS?L7og_9-;gHeVNHx-XELnqF{0^=l5i@ik!=xTE;l)%8_(U zv1+p&SbvV-rHp^7@MTm=%YxSsJoaLP4Cs|MDpb516*KaV=_^3P^#fRCO(k#9ak z|Cp_poexN1uYAm$!-KHPv46LTSm3y(6sm-E(IC;avqdq8HOf%*Lh^jkM!ru(FY}t} zmi1@h)1m^i1Pr=E2FE`2JoKmHLyqPF=s=s4$~JUqz7|J$0M0HqW8O1_5H!eurgGpF zyA@5r@zW)EdwJqbsO}D|o86y4=a5KVNHJe}LOw_{oZOC1VAw_)s-aK)k8p@MbTG5_ z(3~{G-ZH8Ay2SmJefC*h=kAG7O^_Z__8Q5B|9{`-TJ>hJ7VZcj1zkuzXC>29SXHfr9V}&Y=opQ|?UBl@IJ(gvu(VmK(y25~vv}d1L?<(p-4flk zMwG^*<-1bc>~ucE?ph>_V;$r(@4pA5ZG=+)BW_D}3b1W2nr*Or`8t1&--QiIsu1;& zzi3INFf_R2dU3A6xN-@ksG7s{D@oZ{l4aE#`N|5Vh4**+hzuDvj9u450kxRl5H)t4ZOYtT~xZjE&@2rpzK4&FLg*dE__P*cx-ndXAN!8he;ZVITil^S? z9suzV(Fh}B2dxPvCKK_trO}j|AAP)-_(i3fN z6}~t(gAAM*d(lKSqgy)n&MuXaD-<8a=LZpap9xJu~1ZD!VRVnT7=PZKe zm!&I?eL*Gm4Nym~iK)eF<3|wp$$}B#d!P_}-pF!@7@3v(p0+O*_z5JqT{BK>HX9{F z#QxQzN`7`vr7mLkN?$%%Il6N|pkeGC?Dq`LB-G@~!jgs=I8e4#+rkWGL=5u3Xg4Zi z52{O54hX`~_p52cxebkn-P(H#Fr0wVzg(i;F9j0xJcfQvb3}l}RLQ=ki0H7X%W3;t zZ#xKv(+9(}aIBxEEvpOdKdjas$+$!Q`t~7~t#z*71`$iLyViSnGoH=a7cVlQ`3(N} zP4@II z-hB#0+Egk^AElUiGph{Qo0^zzT8bH^YerLIj8N0BXH@_gN+Oppn^|GWs^+Ec3}yht z;3re#2$I0%s_$OL2UO;<2Tb$|u($41bn>V-PW$w8lZ*}Wgq6wM(fCo$wN9_c`LpWHQ^Ito_qDcy<(jCU~{xW ziaKCpBf4_$LX_}*UA(WQln7{R4>WB*EflS`e7`DzIY8atBm;6JL6n5QT=AJ_%;0$D z$<^y*D7fu#UCUbke`YoRCq4w<5Agf9gZ3X61pww`@Igz?rh4QKDe$!y^R5Z3ismrl zz%PST+w6Xl`3i zu#SE{it%NCVQSKZ-wMy%^qzM*EnDf{8b00{xnlZ`M+)9>g5eEsU_r!P5>Ex8;$3WpMe7T=b*BJmz zht(C(LURgFb06BHZ*7Z$hm&k+WO=P(j!|e4_f{u&7_}Q%D#X;zf z8dI`1QW=RWFGlOpH|q_NI`A-)n{JsrJe9G9^8G4Ooo6CpC3h1Ae!F)Q@Y;DZhEu;l z+JhreR8S^Fz4gUSwHC}MM51U*iiWW8{|Y}>yq-fG0MrCtAoCWBoLyujZYWdFcr>IJ zxlT}?r9DO$T_*r3wqnxynk#r5Puer1|D)}CJ?2bge|sk#&~fzy$4Oi@q2zg?y>aGE z{f64GG<1$Dp4JRepr!d+B(9&GF%I{Yhp2MJK6fPU4!+xTH*dU(K65UU$Mj$|dJQV& zbi_OvEX3?+k*?X4TUEKdrM)URYvNVX2&RcjQMSZS@vRMA3VK`Rnj}Q(K6U0aF$e_S z0z1FE?~Ioi{h6K=DDMo?;uL}bDfD+bIU{a)4NvjR?-0xC-!yXYY{T-QPpWb&6$GyZ zFPi8i7m!#ie?ia`oGc#X?(ooMPOlo!aD&q2*&_ z?Wc&gj#PT!1!Xu__!7Y>yl9fzZsakl3XH@l-YK@Vxo=xcW8u2$pM@qyCXKdy zD2FETPhMD0m~E6}L??%m6emMmKUq5#bAU)PLpdla|-rO;6c(lz4uS}#^U@Lk#3EjZU_7{Q82!-y@kzyOzQP!z{g z<0ZtQ?WdO%xj(Vj~S@b`khd;(~53pbPHi~ z!|av-c0%YM0t}F(lB+bA&j{?i2o3|h9d5~y7J7;*iZ4M*B&^zR2r@05Ji5+(UC9@$= zig7I;?MhyTR&Di>DGyHxCx;9{H5i(Kl^ZupNjj75V+Ay*W;@*GnKJZe&0-)VkXAA< zquE5SJu4n5)E=c9ci5Oy;wWw<=7*kq-};ihZ2ON}{=8q~gH8?J)gVrlS(w#GIs8j< z@H2WSKMTb%AAf$@mtfU5K%#RhD(YrL%z4}=yRH9*o?9wA1$ZKE@xX&aY@2Yv2#-fw z260Au>P@4XCMl3plF|JD@ukpMexp|KG-b&vHtKM$NaKhOv`MQ?&C?9-Z(a|*bG>y7 z>W?yIYboIdYBrfnYxmD3Xb9CXZQWN8bbSkC=ywQUp0ADTRG7H&NT6_S!4F< zP}W}K!6QhNn-ut;@u7^x&h_t|9pQ>XvU~?BC|9e~TqGs{)z3YAD?=Pdk z@DP%6@C$W@o@`5JG$3uFPC&)rd$G}^vYt%OJI*zr1UQIEafv*GFNjKObOF-NY!H(w zcygza$qp%7yvg9(4$4ui@?gTQ=x%n5Gfn}^auHcM0Wy=2o3LrRMUW4oKzPN-);au1w)=$Rtkx_ck!{qx$Ggmi zXWl@DqK{pl$XQ@xHGftSMD)H)!ECGmM76ry?!vRik>-H*Lsh24oYu>j)i!_!{^JW& zXy%@~3#2K?swsnEq~T&WAK@!TuprsXSy=K<&kcdO^> zJC3-!!{ZcqM(6v4!)7lcG-kur9f(`)BMbvWy>LhQ?bPKNoE8&vccP*Fm~bWx`O|TB zE}I=Ol?WJa3Vsp?S9#L)H&Y9Kz5+;0M|BSNdY8JWYWD@K=LV4ObR`8uAtd#oz~7A> z@wbSbAp#h|HyT=yK&z5X$jiJLM$O6viANDu9f4IHN=szTW87eg>MOGHJF~|xXPK;U z@qDWR)+;Re9*6Hclr`XG674-u!3SLwB>(DCGiSn;4#U9k+C^;`3&tL&Fy$R~ zR0WSP*sDdQsS9ZxIGo<;Iww{tnD^EkBh zij9m}aqc=R2GEr$%bY6WA?+#~&v5%G995(P^JlW1+~4^KqZpvH&ICFrQ-?0-QT=&y z1^LfR<2Q=cs_^{R;{#JUk~{slVsLx*{`SicZa<1^@+EM4yD<#3&_5sSa7e%9(C@Uh z$mv!7+qAib*(t{J77oX;EEzH(Yz6t>-TNS%i*hH~Ubxs0-Rz6>SE1FE$#2WH(F?~*?ilBzyL z^BCcom2hDdd~NGKgf~qhHot4gnjo>F9CljI>Aw@A%gx%u*-e^ z9^u3)5Mg`)2EMyt-l^7|=gzO5`8)#dTJ!CHv#nhU4JVnPFd9wjVC4gFBBbz#VNNWa zuuui=MugFNW70G_O%pk=E5W1mxG&b7XIS8M^-R(RS)Wx@lwDJUaxAE$=|9nIs$A7qw5+RY;|_{wBr@!V#r}k-aO1(4 z)V;_M>$x@snG!7h+1wU z1=iI3+d*us@j(UyKrMKlo3WO}dt*se72qHiTxz5yUvnQ7v%+*ifs_@uRl$LD1gf=?xn7vehJIM`fWG9Mh&|ZgGl+QPqdO`8yt}o$@wSj3D32 z^1xDq<7OOPXPFZ;A(yl3J+P+NyGPg5W%Hw>s8G@>L)L2l22Xh!Q zjkC+0xnaz`HK80+p}3MbF%)CVtf|v)&QzPS{Fgyb?Y+(7^^Szc!id6a1Px~srsMEo zEaAE5PN3bQYOBM0fSOghN(NQh)HP89e?24iG-%%qKt*SqxL!U}^l-7RorF@X(iuIh$2)xM_Dh9{FqTq#(7mypQbWz#(8}H!eb8F!6%A z9yRgnL#6MrsGdElmqMVaj%8oUq<>^-Y|SM?MfrFZnL5Z*8M_&uQFOn@)4m_Y$%A9# z#k7_07`6Ivp`Ban<)|8dQRxA?iBu+?l8$Yu&@zs|Fi=cOLrTHCfod}f+4Hc#r0n5-M$nHfBCylzSM6> zpzg1*d$&=i87X5ZEwAEsC$i@&#b!aAsheYqcq0}e;?Yyo)-jY^{XqE=fgZb$MW}V+ z+3>DRfLGXfhvrVEc`Bis3_aTR6D16%7Z9kA9p)D6z>aCXXjxGPiimvb`hGngoHx>9 z`vMuGjj!t_4$9`kKh{_s;4`_nK@47IfGnkCt=^C=C5|+tYZeuhU)+ov7*r0&5qmjm z&VQHvSJDmW82&^c@#LK`KqVjKFV2{R=apJ3TV zS!HADHR7>hg9CTsoRJ6DT* z&o=@zc<>M8Pc{NuhQRt{Wk(X^6k|+22+Qph25w^0s3-T@qYsqmwSZyxQwat!SivNI z3=NBjsJKV#gL6sN0^pI{DoK=xu|7DF+R10|+^jl5r7H+v4tq5Z(acixnRP!U$Wrw# za>LWPaiYH`$E&lrY3;X=DnU~^P-Q{f(8tjZXqGB0@WfzPlBAWlqkEBErr~SVNNd^o zF4;L>(Mh&PS1pR4`{XM7ZYDHnYfy8?-qFM;-*-*0{?=b(_rCQfYn(*Ac5n>;1pU)U zdk6>Q|C~JfD%w#EK?)^N1wVZ$M#))~wo-2gbAwR}t(#dkkPb*R3z+qz;u~!j^(mxE zyiIkbOE;_h>OB{>@w`@cdl4#Tw-#$6i+!@$GQlAljb^_3$q&sbp&nAY38s$C=+4}T zhYP5;I}_rEM1$=a?+H?!SCURF#g%N}F-pGhd4wF<7iBme-0SL`?>-%$9%MHsD{<$CS^j%tn=Iq8IpBr!}X>ORDuUsJm=E3O2m1``63>5F%t#E6`W|-tFUmHm-N0@fojcGb*@TZWq&) zTk0cNy;5xHuCSoY_%=F~T4o(lCh$7tD`m9v4a;jnw%hbUrmh>N_APImooD2J+hS|X zkxVEQ55&{K2yHF!{N=PAC>no6fi!-UtHn!v#GTI)>d&{uM}1~ zffz5P?g~M}2V)PcL(c;FCcl77wWxCZ{zl%GBdsmd;b4bbH6^!2qa!uZrYE3vJMFXm z-WWy*FKsrh;en}{W~gB(O7YT2P2o788+tUd0Bp)2uTIsZg9Vq`!Oom`-GISBUv)k@ zv5hrSnNf3Lg0scE;P_imv^<)GGTKD#A(7j*MZDH#gPG4w1Qyg#lZ%nYUv}7<+!Zq# zE(Xf(qc7hgO8CWpLtwx++du`B`>QwJCttDVB4!~zs}|nDxm(^iGGrd}@o^7DP1h9% zBCV^cBwgc|g)<*7kYv+CL*(-V4)1u*AY?L2=uEqkYW~__m_cc_!vDGP?;(ZXUQaN^ zsEusz2)q!D#Q%75J>fd$DDdef3;5@!}Hfk`74{5`tfUdKGZ_hSps--tFQkqKUa6U^K6zMA8qiR9OBSH|`L8+hd zHaZR7w^3p!OD--iq!cY)p*I5K+2Cn>8Zga}WwkB5{Ur6JkJ%TBb)Cf~O*hd=923{3 zi$X1jJ3>j4j7i@G@gj`(F;8>FhD*tYxr zolFtV?HR%Pk&H(ygy{f29*`y@fAg>#yS;NTBkq?E9N~+gEo>@;Ln5dsl-ymmPS1`} zsjvEKPZnLJcCE05A@4A9Gz`RCYrQe01usxSg5>K&Tb;9WbjUu@X1kavWy`?AlriZj zlbm6siYQhX<~S&N)!OYm+FRdjBl|=W0v?@ZO>(e(-XUm+ga6ZS1+Gf_2d@Abrm*E2S`MnpnS$ydTFK64Sb(! zKkRKUQ8?vmD7kn{{(>E@@v$h5yuiVp%q+y8AI`KEq4e&|for&swXoR8#G z(4ibL2faT);bEzZeBC#$u}^^$bM;4}p(;WCn8(r6yxSAGbwc$tCh#TP+I(ijOCpWg zdoi0G-)>rSw#>0!!Zm+c`?*-GX>V2gLtejY#OfK;&O6;anP;-6fKch`;-Nn1Xl9>R zE={|MGyup`r38vVU;=AG*khK&S6yV1R9$)&7+>1c6 zvUw#`L)V%2O~E{d@N*mn_BeE5m6WVMON9Ei#98Yp#c}Er&Xe#t|4c(B>g26Ic>pek zkP=t1-}l_)q7qx15h-Tyw@>1@ulU?I%THgcg33hl=E{5|@Z@Y89g;6glgHJ*zX2-a zJOx_**7!@!#J0RHrVf4WitM>~-j3P<#UC5hCnF!?|AsRZL2Li? zFtLU!s^?{ofuFq}$;gEmWEw+R&zpnJ)Sqw_fQf5%XTGH^*nP<}RzQjWzXN zfOOZg2TU}EPDuA@i7OVFmM9{xB>_&Y>I4@+%s%PpKvAO&S%G=_%X4U_UvzA^OagbX zFt8v=eAH7<{6_rdd=B!B?I3_0p+Fc!@NhR7|X zu_Pxl?D&tbP|`6$1)QuDC98iQVY^PU`VO}Li6jNa;-)0N253TJUVd+V)1Vh^qcrKHwV~KERa7U~{)mvm&Ey#6WDV5Ms0d@dI*CAc1Ou`qbAzsoc2*0f6 zL$oxdcfj`P4Ud^JCDNIRnOg|)*7NDxQw*um9&DQ5=lZ^(?oCOPL76xYLI`L6t4rJQM=$R=ewxk@I}2>0xb(W z5`?b0r8^xup<@tgBhavCYeEG0dFrrevZRu+Sy%o1JFp9Ukp9XdO;<+n+zy!uiy?@< zRYU)z*1umhIFKnN-)=)vE7Vd-!2<-q{|tVZgV~L|>Gi1yW-fTpp&w~rYsG%zSX?tv z##*8rX&FmyfWu3-aG{8#b}2nVuwf&ftFfFCMuGTjICnRX5ds0do559HIJ z5I|4*vfbOP{qRfHnfWR}R1aFrbs%5=J$KX51PuX(kmno8{B^Up3;8}v;aQ*+FGK{=ZCna1TcCRX!GGX72tXhij`w8d6) zoELdKI5qNB|BBC`C~lLQj(tDogVlDNquY5Ua~Vc>lQ0Fz4yM-XBg}q(Hhloq?|U4! zjQ~z{2GsrI7Jd=H6mn7X$lKL~x&~qri+>By-kWW-gpJ8VtgnvH*g`>1jIf8NR7vQnhJU{x3IrLKJVm!k# zG0ORIg#=xJ928eK-432is!@34@QG!Qbg2p@?6_nUK<%4M$fjTfClbA?j$Rpk(~k)f z^TXHhTmY6VyhvNVTI5RcBVIU-lxY2TG4t0ew*o$TfwJV;g3wv2boHn_uV`fRBxj{8 z7AUaVj9>o4AMvzm*ren_hZt$pPg=PAWH{jc+?x+Q>GGo0xe~yyetfzPbh$K;{-*si zh|^hFla6MOa`%gLFyY!3Jgoas%cUG?GW3zIUieGTdEqQNy5RE%WfPJed0|`)ak?GX z?$w|Cyl1_6p3?;cYDorr?Mb=;ojcGTuDlVRfV@hzFcQH~Q7A&a_ECfrll&W|Y4yoG zQzw$XcSg8&daWVsC2?B!gj<-uG5GCz3hz(fW{86b#xR=G{BRr13Bdo_?!oIlY6<3M zZPww&wYnhYG&4ltqqJl9OjCbh#E#&T9zN9am~LHl=iySm=^RCF-UFqWd(2U0kX5JJ>2jSnk|5W4$xQlyZKf#cC{OkA&-jUH9H+i1~NQ6k*Pr<_ zLsv_?*v6N-r|@vEUh4)fc*WkIv5s?#s<)d4wL1=>XiCBSOeJR^2rz%d!dHhQR=n!o}bDm@{IJT^jIw!cmh^A1D zte1%(Xp(|`%>_B&Q>m4AG7E?NIQt#1mm=VvwP>F$ebu=g4t(5%5Un`7zGufBK_GPC zM3sTqelRBV3x6^j@H|8amCl!^OM$fq3 zzQMoD@~7572zo)B5>OgBxF+%xApm~0knaMw++jgo(MwrEA%wd9X&`qVBA!XmG^<5s zaFrit39w+A=#I%$m)l5QNDfP_j)|0wD~#y#%k=$97LZ{$PFD4C$3!OT>EyYcGiL+} z2GOK-8CO9;pm(8`i8uyDhL&U|ia=!Mrv)0kY|4F$BsWboTZ6b=xN`U3k6W>#^1O$l%S$fbljOCu6nh*ktI zfM&GXedbFGa{iV8%n=gwBo;9_ZpDp+m?IU*9fX@=oI#4McA zpxHJ26C$K04#iv7_cLWILteIguUBMLk-Odx&AGDU<9`5F`WxIj)|l$9q~1~PTAkUZ zD^CA_KE-}0xFzMIQV)Z;w)7YrlX*X4^}prG;a)kbom_Ul)K!#hxLOAyhM_d@$HyUkjJ$YpNF_oncr z5-VOTm`Q{Z4R6?V{JfcXq3wssHx46Pyl^}=J5dONe^9bcNSJ9}<6jxwNrXXPC`bI( z$Y1_YOOf)?ihx{C?aeVBPgCTcj!vhd6>xtxfMK!Op-&W>(-_YL*n5_hSp?REN^432tpLNo53$A`1n3Se>i5Y~INnG{{fT9v0@MWpI#gFHEYobVZtW+WD`Ri*l4j zsYO9U1o7MQvB~V9f!iVn5$4r)bXl4z7f`qIHgMgE z{#drb0Z-qgIsj^0L4E4aRwU2O$pwnjM%iM4>+G99PsV9WCq!l)wxQU%W1(Sktmw04 zSe;(4Zc+t}s{j6?WT3y#oC6l_ln^5(g`TMQvbuCP0!oLHF&VeE&@`$nnOgzvutm8@ z$;ftqoU)xcwA&qV>>}PZ?Zk*SvrKME;#14=ds_OKSu6H)q1iHqNV0T^aVjV{xgh}{ z5a&h7zGNro3VSRZ?yLi#`@^`>Rf#H6h!cLe*MlYw$joTKPDItKGe=ltcyd8a5lbjr zF-v<{;STNGqYsY-^$>esFfW;5vwYPZ@X}lmd1DUgvEy1_-eTIB`MOBF;j;UdIKPn; zwF8<^a@={7lf>FWW!gxK4W-k@R|L)yGlioYMvxEOuRUC2aJl6jmpXQ!el+JyfB6cl zO=_d|s<;9VDf)?g1p0pkxq~1zk#!SF%Y+4GLfBsBycJTVFMs`ttk^i|6kq3qP^0!Q{K4(zfZ~ zwGvYP?Bw3bFpA>b%@{NA)S@Y*o+amZ*+K}JrlZ2+A4YX6%`KulxLWlilv&a2%Eg?* z8?|MmKy!MR-;-(luKO1yv2?^RTWF{4#1cx?WXLGZ?jj{?$uFg-DeUdTlRf%DcV^ntFGJ58qW0Npj zv`&eYs_%rDrw)c#@Xi`Ym+k>4Qu$?G-D?olhkmMrN2cNk*=)QaVbFr!NZypV#aqr8 zIf%CI-<-Fla@if7+yYX&Q!#1do@NfK2&u-d&VvM%Gn+t|U~yLxQ1H$Ss^YZK))#SWkz*1KmZ;1XJp z#A^)vg&SU2A|mt>mtVqriEv>i7DN$3&qAjs13?ZkQz|SVw!B3U(uxvqY)&-$w(B<2 zGvJwB_t4|hZ2tT4>g z;2aemfqdi0AWT4?qzqOYtQ1CE=}ns4g^{!$RmQT$$(^0S0U-;#FhjKGT1YXW4tqFa znvcWj)h!)PQmbRY@h_H2A$-Pt!tc@w8a4gI>7Av`<5*ynZAJ#H@8+=TG0_zFDa@Mn zdljW9r{t{LW=}zVRjgUUioIPLqWqC;b)Wcv4dRK*{kG9aS>DU)+~@4%&LQ(h)1T$< zGPF&ti%loVZqhyahaD+qh~;UgO-Ltzf8*m#9{Gr%mS$@9DrWpqQ(o^4Q4AN5@YIajxbaQOJTEz5u}yDMWbAeIc;i5{l)JSFmGo@*FAGey z!s8@$G!9=S()iKJtPJ6q=w#^Sv~Kc7lIwP)$8Q;n((Ty>AanGG71XJSNGl-MZXzdzXcc%c_pV*ey8VL{%~@_43MftwEIJ@nxyKRqa)|0z zRAvIbbvIBU#`syXAF}NPIWX$dsw`XHJIe}neT-%yJUYq<`2b}O97^V1(bd7|D&|Ip zNzTSwfdhE#`2l7h(Z>VkUbh?}AeH=FL^o3@+jA>vD!~Ec1!0ThhLz`hu`kDvgPyR~ z5_)n&o%kJAhVZ}-BDBTM0+68=`peg18jA@zE$$p4)@5=JYQ0IdE<{M;4a1K*CczW1 zu)S0q1`c1^n$@ABUPfb5UgZKMq>&?jq0{3n+`806%U`&tZma?hni8}l>MU-I zny5Ym#7Y-(xxjr(PqDazhEp~MnT0t{y#4-FuX?la3UuJTdzjX$!6QH`xrcg64Pm|m zf&3z6ee=2FqhfPU0X%wXxwgHNouWo3J%&H5{aXD z3`3ix$xr!O`oibRK~cw~8yN{Y;-U6PT5D-{a05<27RAW=nqt_@454FChK&{pU9+$~ zAV0t{yDeAokH=^71DhOt1GY#ZC}q@yQpe>Ln60MLU44`XsQaT;TKT^LdiHS3FLqqN zr<9-t2eb7=Yt_S)WZ&mF&u$jS@p-(4Ys4xB0C#nqOYO7QIg#ZIq3r!B#);Bp2}~y2 zIr*&-to-8K7KzuBkaE>Zf0sxFAhY-zdOvTV@??XtgVn(v_bP4eNe7L+O`;2s5l82Q z`k+^nYIPioK}CiAo+AqvzIFZ*AKp*N@Y;&^AIv(dxC302hG_TpN99)x~Oh#u%Yb1{DfdjLsyEqnWOGOfX@w<*dW(uQn=I10Je|K#->lvzl zWMj$Rx)*~5q)as#FW;GQ&Q@N2$&T|^SiKE94$+0EQz(oH<4??Rgw`#ruD=hs9AVIa zE!S=20RxJ>CcF~*(o2{hBqxLmhgwQc9H-BHuDvcgq}E-PDSb#jjQJuSfnOQ=Iq-!N zY+owZASrZU+FAV7!QvqI=+28@ti>QgC91LB;fFQ1+OB1s7B=ClU8W~E4#1V?18>#m z*@23WZ}^E3PZJA0Uy-UqUKGk^3v*^9-8xHMH$y^a53JRLqpY)ED*zA`*$$I~sI&3K zfQz#@*`oj*`I>?k9jx^fW~A`(6ab#v84nb`E+ND z?*}LPVC+JUqnh^J=J>Rkiw(H+Yif{#FDtc1vDAB$+ontb)78F(3XJ9((Za~D_~-aO z^jNj}$AdxN5FF|(j0MrGYOC*I?t<>$Sv|^EL-`(LG^``38}0!eqJ-9~&7s50E95*z z>erH*J2YW5%wDkdZ@;8I_kyL^g%DoGZX|hr_~Uy#o-w5SmoGvX5LqKTGg*pw9aNRP z!fb;foC$hZa}_cwIg)0zpq~$h0_I%m)Z}neoUo=cU*Z+3^P z5^MCD%BNoC(T_RD)k;X&sKbN>S4Xu{3%YupcpIhobe}iCWN_u>B`une~^N*)u#iS+F`B9q4l6IXpP^DKdzq#x+Lee6^$!{&-%5 z+xA5w-&dcZFttI80qV)IBXs_9CzXG_FK(u6deX8kx7fnj|I@n^B-%WDbF4KmS#zSw z>CVyc^F4qWHH|gEU?c1x+Ojz1qU#6yT)+|(AJhdFg(0MlqiL18PCH?t8+oMI(ZpT_ zunTe}(=R2M0fdojC|;?VX(q8d#d@~2=K8uyf^MBreBN9DmYY|(BLbxG!XR(XNB6tF z)9$APG^SK*>O$KaRWob!v&SK=&~fE!J+gk_0|-l zJrKpHqE9$Q0|X#GSO(>~5;)rJPtYw9v*;>|i0GU)*W|I*dc9|8p;?)p2Ek#{a!&ugHn!%^e z5Sd?ZgK?QHRBiz)qlPxM*iajB|7K^-CnD>NbL4ug@0xT*0M3OSWr~VgZB3VP$UGM1 zRhJb$p$SK^-@UQYmcBfS7FWL%NS zWtGCRC$u#x`)_6X?r3G)SkH|1x{KN##*bsD_Netld zx`^B}89=| z?|R#){p_Ar;2lO|XDprtrgxPH1{A$VeP;_Xi`dM8jO=+*iP0blbZRE#nrC4N|VS-Bu%F9qetor0>9ph2o~TbUo7TQ@$G9u;x0c9S%FQR8onf4NQN26IM=hyE*Gvb@i;$k4W}Z}c&hoWJs!L7R;l{hBx4p}{5#)kX8x*oLuX*&{}l0+ zQE>oEmxH@YaECAihr!)taJS$-xF@)V;O;QETd+WIcXxMp0>J{CxBI^Rs!yM~)u+0; z|Moq%Yug@b=U=_DeX1zv11`9)WcyapR%d24qkk3^oObf}N0Tzw(CaPiU(U;t(2NPQ zrKJDpC&{g?JF}Fg@6zuoTW0tmF8(;Re(x~aYPzfMC1n@c`!e#lu*W7-pAW^K*A)=F zV--Zfhs2sYpa&87`&<;>3UY%dK8e+zt6c3eH#^$ARhU*e0aYH!vg?8Q0_|o+$-W>Xvb?W2;3Y%ZY7QfHaSk>)mL-h84UiaG|~7 z^xiNaP7OO?Y4ZD=HrbouIRuMyMgQysNn{p)RGM$PIG%qRZ~IyJy-D-K+FWaZ$cYTs z@vCSGV1Xuh7Dh%LeSkD$)Ie$kgexQdXh>9?687zjnIB_&;4oXAJEdbK+I7IofY^gelLi60xP2k?F5 zO;_F?G09HqJ=7TIhkD?!7e>Wynz8yk+UIGrz;LBvglmR7go?YZ>u!Dvu^4xPc6Pa0 z_|q-DolIY07D0$>Om11}$}Z_-z|pPut$z5)cK=wjbFPwai;NqwikhJn$Eog#!(v6) z#j>@@Iw5(l%)I7GXRM;*%MQMZ>}&6CD!Dv)^iCvj_}#)WEpvU=CvRgA?}STLPU-eW z)-xNjYZHlRyuoX386Ea46FWDxC4RY_U=L07s*2QsUsb4bN7uy0llxEG)f8@#w-J{jFlp6EQ*5K%qbET4Fzl6 zitns=kWf)KJOsZZFgyYdXPdD$q*gr<3U>CzJxi_<(!XfHkPC7J8_vj|2R$03y2kkG z3VSkQJkl(?n~9kuPZ-q}Fz{NHp0TMm4lC3r^PSdUvk|Q~E<9^aGJO01F(^adzp84G zIb_Kb@me@@OQBl)^Sa%=_Bs4s=xAb#olU8KV3e!osX9}ba6g2 zUZjYq8htoy|8OcQ)qposgdwv;T}XTLpR!0L>2L+3l1*-mSh*W>=TI|dCE81V65|1R zg1!pFZ?k45bdp1=R3S|}1&81iq#_Yw*um$IDof?1^Ou4EzyBg)LDwvehv#~$Z;?tk zgX+{9S%mVJAbCjgraT!Yg#c{^dtL@N#wFjSxPAGksRVP;%<6&Fsv+V;dF_ZkWsV)wGd1e&=38#~;|5d)+w^LX-VrXo=bX4kpQB}40;^rxfKYAlG7qZe)$(VjhNhu1r4+@H{I zWcV57F2aC@zU}=Dx!5^YP)c4l9!1l)+YT)=dVV2Psn*?Mb_5_iteMR8=UJC(G`AQX z-us74ltMRi? zQiFh;MOewLmQ?yPQ_o>2Dc?xm*Vg2qGPk-z4{iaJ{L z8ATRXh)BUf&xj(zRG$jqq<+f7;-BSB%V@q~W*90L)Rfnhi98YRCfVw*yK~{picHRaDYRwwJlV=)fyW^{1tP(2sC&lQzvj|3 z?KlD>iyp;?Iy9#4({#O}>{SfV2QDAd=~|Iz8H_P`|FIWdA~)wiX=`4DeiuSZP@7gGsTllC;G z2R(avUupbtxEz^85|fdCTph!lQw-g=4I+^4NEYXABP^xdXpQY|)cVCZ|7makheFc6 zAhjZ69+}d%{6Uz%$^7q%0S!Q=O=7cghKd*&x`YRGp+-(j(iz@-=^mCD`7WI9OtCx} zD#r?xlly|#LX@3OED4oi{3epR%hXQdmA;PP02D6q&;f`o&{=_7qkS|)*s|DhyU346a z+cEXP=xIJ_X_V^T(tB+ZGjk*%!)L_YIbNc9TvVsE;{BMwHVM_ZNBLiaYC3{MS!0mT zAXJtbY|GWQBQForwBgktd``MqaEkvwsHP7*-fQpr>7AgrB{3zb9rBkSfc%5t_t6{W!K&%eG-^vMG@&hxvW6 z$W%6F?;9W7M~Qp(l1Dut4o{6Oo*Gcd!iZDZgK)kb%n_^HvoHRc{sxz;9W2qc^<@{? zZSr)*VSTaLaf6E%%t80Go{~9k*2}Xc%Pdp(wf`L-t1{d6^atRek6ohw*Hz7_&GJ$3eIaL{`9yq7X?;DG z-_@;Q_@OF`L`Dve1uZ{Oxp_zw!%PinPD1e%$I=_OfNDsKiV9A(jjR>ooVEiUK)?1G zG_iO&nY6m?A_#>(ohV9ty2)zsuuf1KRVN8m>B?LA}5o@wRIXEAbFDVk3zUnIG zR~Gk1GJWEkl)|Fhwwkh7Q1E~PRBtYIiUr}ypkW7=Tci~aV5MrL7QeO*+ifV}y*__a z78dgtkhQ&^%Ze+dK-hqY&s<#S;8>M#S6+XHaB4ee5Q@Q0By57HIy4 zXjTeWjwRyPpPIT>(wS!X)`Qzhn2jVRX*h=*w*CtN=7dx~5q%^o44lVxG(R%!ApBf3 zKyv<^B?+nIQ+|w>^Ct>z)eqG16?V*9oq}o8o~^qgr)F)mLz%AnzU^_a!TFPQOof%d z)gq_dxw_UkPWN^5KqumiE!glFIR zed&np6wE{r)g*8-=xvR+6gcwP=t!{tI5yV`B-|v3Q*h@c{&QTly`_H4mTQp-ZV(64v z`>i4am6HR+$a`03Gb?m2jTk4O=;z~CKPwW{8k{pbFQf4*R994PXF%43B(SCQ} zYeD77wHM1qMTo}{;Xl)828{V6OW_v0;M~SpJ-vT z0?#S$9JVf`j(!BHcI{%+=O{ecP>|JyNG$obR^?`fyZOST!r`MH8pWO zGc^Jzypk^I5-addm3_s;IfPub_GU0@YP9`ALBjKkH3$CG0x(0dR|0Cf52gK`HK~O4 z$ZgzR{o^K>j!4k1?vLfsSk&4&XJxdt`Gmwl2+}^w?PS(p7ZUof4I~7Vp>5LkyzkKXjmpOk^0X6J2=-_UelFAkgzK#K3k-HL;qJi%X>T4 zE3M&xfq;G8LaPL&HP&&M1q|ULar}?CXcg3nPde3SRkGA$Bp=_S_Q<&&D_J_lAhGJZ zb%Ft-B`H}_ysyH(yha%EJd}ry??aFCjHLGao4GUMZ5}X?;xvp0@w4lkZ&kmA)|4pZGbb?;n#m(((bhIxuCHTo*?#{&rBMm$(6kldkpmEUqGb6J1a7jrqg)Uc01r+&(zRT}qXDr9j zhqxp113Xv47mW;JWSV}TV%Wm>!8@b+*eQfLNKiH8AxgO;OR-mTz#bA*2iTQ#g#8OY z&yR%~V*lk&W&5apJy(VQ8E-9R`KQxCvzfkHVWL+N9Hka=%2Y=yb;veNZ)>=`CyC_&TLY(}o; z&tdS5ui4TIe?1ZD_$s06mRV?h8y}5~gmSI9{h~cM)t~DXvOsprpBjs&Du65r)}6-J zPWG5my=`olnh0?o*1LhoOj{>8UYw6hpReQ0Wg>*Bb#^ESo=x_`$w_6QTkRy_l7Zsb)eTkgJrP)v^%E2V`%nMy3QK;0%pr4lx%NC7s9 zV>SSJv`zq1-HlEa>Ufvluh!OUo?|!AfM@szgT*(|gxqw1idLt%e_=vf1o3<-G{N?? zndQj~Gr)C}vo|i-2%o3sVjwA?JB%9p&R1PAic?CH?i}E&7q+^|JJ_I&#%l96W*R!Y z8!N2Nko(MkKQ{zVb6gWmXe)1+{kxL2Zux^cKq$YB(%o|lxofle>%6gxU4!>&)Py%r z^!_(t4CU_)2}xvQ`ZifmfH?gUJS#Y3jX;9+nlH79135EL5(Mh-lii z>(BrKfC7+tw8 zjrl`74ui+vDO0fcc-akBWa8-Ww=^Zqj0eUJ7pTj&A7436Cj3lNd*OwtR$Tx@x>+~E zC2ku^isW5pu3!b(k4i`GHa{m=6)t*zwRxgsp_45fmDmE;u_}@V{4PiJsl8YRTH|Sf zd@=lL$dseF_b_uOEMI3)e+FB}NT1Nu3F%skU%vdNq%=B*3>Sh+mQHPvl<7nUSu=hE zVddhr9pXu1#ANia#R z&mVxYLb+6I20r_>Ow+k`cO2ut=VLp6|CK>;^%gL5zGw?VAQj+jdWU!h* zpgSCs&jK1Bj3W&`zAC&tD(r*@ADk36lRFn{k@1jLnk+63al&Z2w*lK#TbM-3ug%De z&r^Zy-_*V1H22WaAsDi7I8U^h@28_)Cwe;)$+LB0uDo`@$7#xGc!N_ixdLVzT(s6Y< zyeYi+F)$8b1J4}MH2q`|_#-)eTOpPQp^{ho$h*MlGipSe=z0jRVUq1!1X1sux`EMB z^-Ttj>H4xrSc@n36r5Vo!tc@dE1tT!yvHFOE9{S@1zC_OTsPqww$2^J%5UE{g2%gSZ>6VR`0?*PMaS z%kCqx(&}W=??em^bQC9&1Qx*Zf+_nS(@%;sTg5N$?bKkU+@p~!7s?&nhRehFj32Y4 zgcQ1;(;o#%V&Z=(F4C^>+0=$w1RiYUo6O|`t5UBhQ)gIVbUlgPmDp!C%!Lw^mRDbA z(Xv^S1nf1_T~;rtg%?i(RDRWTJy}fp@6pVgjH2E7Ml`hC_C8hg9z1Sy;yy#4M-Z)s z0G6*_J)A8VH=*0qcMV^QR#D8VttjI1K6iAxE91Au+LI)F{PbYslND*rPD^L#Sxy1F zyjTbnU)*ZbGEG=;EYGllUS>};AeZ~}At<@=h(}VpJU74gtZ5PPb##%~phNHBM2)ki z6l@0uE@!FE`A=N4_?q7lr-S%`*=QZG@i@ubSzxzfE4{r&te~`&8LL?b>e}Wsy@&z- zACsOFok=g^C#+Gw=;$EIq*F6uYtnnFZZw2mIaO7pI=tDm@|SY2j^RTwNNFxqY)|WW zBMw@9oQOS5c|%R|LMiEKK40^lS{Lcl0;p>X>1F5Ui2psYo(Ac2r1Wm*n4{@ch9An- zncL+NMQU&z9C{5LQKN{qe<>Cgo^!icy+?VW=V*P>&CT@7&@sQ=(0e=QO+nx;GEDY{ zQh;06@`gxh1|8BsnJ5h?X1Uk*lDq{)42^Q^(q>bJR!PaLJ+UPx!^^P34D%E>^a3$8 z2}@rGejhZK8Q;t|W0zGtb;C(?@rfAmqJTY>Jg@!g+6~3V@FP7nfH2eBQbcVT8wes8 zghG=D5S0CIiO{PqgzqfD>NZ0dC3p6x-Z$|zYr&;cT#Ln|au?+kmiV|^flje8gUsNY z4zGa#3dEzN3oER*sVcgjvU$Pv5%*vFft3H$#aUA8?_O2Pl!=`8YCE~^)8|H7S74@6 z|Ai27>kL>lO`i`f%y3=#T{>RZ<5~{>on$6%dMwph1iaG6dAVBZo$Yt$b`+TdJGiQP z@^M+9e@&4-j|Xcq+1k-rp4`ZO7gf5DO$dr{eVA|{Z>#LKHmfFwLt8tyu6IftWG%#5 z4>WKwcM9@BM>7ts6Hc3rT#VNWi%#Mv={bvfIvn>JAF zpV$>Cx06-&Gg17!dz@~V5YAe*{_%H3Ngs;Q8yT<8<7ri7uX@u;K)5v1_Q0R~fini!HQXSo$@h5e#b~@L4aV zn1Tale@KMP>MDSBZpeIY#)jbc^2?3B>m^~{*WxVN$S*&(nONhOY3$~S0-`wSr|UE% zyV~f|j@A2q9vxgwy1(&CCJy9CTK8sT31Z(`j_ltp&B@y%f5;wx*>#DVW~fEE`DEPa zv^F*Y3Y=J@HAvO2&8y2}nk64CYNx_3ArF#cXb_1Lh`Rv6F*udvH_Kz_EKaDW=SB1Q9#zKxtYrr5@S!$Z*8X10O-+K60ii=VqOs+w?S zB+74w$v={cT%#KUsAv}Kl-L@n2umD22T?h#&OTA6jcV0sZ7~x2tM6={4A*of6T=jK zgFFRS7oOD+8atU?HqM1hi#(<3QaOj|7!8<5X`vN^c6^kaI3xUi^&8F?Dn z{#5WY$3R7sqX$QsQMsvMDoGPMky=%qbcdn71AG4O_!q3ermMg}9HJch=cpw?Xc+PF*fC-P8vLAv5+KqQ#8aDRN2hZd9=Kj#)XJ zalbO52h9PRi!sxNGEZV{qdULsrsSH{Ycn>L%Ff+txku@P4kY}``s=q^7eQq^w$(^u zOd{_iB`x$CB4=NmKuZSQ3g5t_?dYB9_C?chN3QVS=k`HB42o2$p|cgz)4)yxL)cug4pV37t z$FKQt0vFmWzx*2H%}v~?!ESjbC=D-!dJTb@jNVKM3RDO(#T|lSlhyF9?9;&-{>QL}y^FdlRslYabhCMO~5OSFWT<3DZ9-_tN#Ej{q16Y#WKb3+8!qwu>mW zAZbKvQWM6ox&l}q$-HRd#lL*;V#IR@GNg5Z0D!cvyiD7_Hi**RwpIXuk`jRFUw{li zfWZa8{X;PS1^|Wxfbf4Y0H6Rv`v0*y4C8-uU;%&#TLAojbM*iD|Crpr`EU1sJyJXX zfb=hdXXoVPNPzi&7zP#&0R5kJ4t91Z%>SMWh5et3ur5%z|HVa!|IPVV>_7H@01=09 A6#xJL diff --git a/docs/zh/05-get-started/xiaot.webp b/docs/zh/05-get-started/xiaot.webp new file mode 100644 index 0000000000000000000000000000000000000000..91b3b3ef681a590c8526c92e91e58596a09a4085 GIT binary patch literal 12592 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