diff --git a/cmake/cmake.define b/cmake/cmake.define index eb95feaf82..a794d927ad 100644 --- a/cmake/cmake.define +++ b/cmake/cmake.define @@ -131,7 +131,7 @@ IF(TD_WINDOWS) SET(COMMON_FLAGS "/w /D_WIN32 /DWIN32 /Zi /MTd") ENDIF() - SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO") + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO /FORCE:MULTIPLE") # IF (MSVC AND (MSVC_VERSION GREATER_EQUAL 1900)) # SET(COMMON_FLAGS "${COMMON_FLAGS} /Wv:18") diff --git a/cmake/libuv_CMakeLists.txt.in b/cmake/libuv_CMakeLists.txt.in index 3bfb52fe9b..1d59418462 100644 --- a/cmake/libuv_CMakeLists.txt.in +++ b/cmake/libuv_CMakeLists.txt.in @@ -2,7 +2,7 @@ # libuv ExternalProject_Add(libuv GIT_REPOSITORY https://github.com/libuv/libuv.git - GIT_TAG v1.48.0 + GIT_TAG v1.49.2 SOURCE_DIR "${TD_CONTRIB_DIR}/libuv" BINARY_DIR "${TD_CONTRIB_DIR}/libuv" CONFIGURE_COMMAND "" diff --git a/deps/arm/dm_static/libdmodule.a b/deps/arm/dm_static/libdmodule.a index 06d509b51b..b197930062 100644 Binary files a/deps/arm/dm_static/libdmodule.a and b/deps/arm/dm_static/libdmodule.a differ diff --git a/deps/darwin/arm/dm_static/libdmodule.a b/deps/darwin/arm/dm_static/libdmodule.a index 2bede61caa..c4e1214bc5 100644 Binary files a/deps/darwin/arm/dm_static/libdmodule.a and b/deps/darwin/arm/dm_static/libdmodule.a differ diff --git a/deps/darwin/x64/dm_static/libdmodule.a b/deps/darwin/x64/dm_static/libdmodule.a index ae1abc5dfc..3613ce21c2 100644 Binary files a/deps/darwin/x64/dm_static/libdmodule.a and b/deps/darwin/x64/dm_static/libdmodule.a differ diff --git a/deps/mips/dm_static/libdmodule.a b/deps/mips/dm_static/libdmodule.a index b60727d440..ce437c6d1b 100644 Binary files a/deps/mips/dm_static/libdmodule.a and b/deps/mips/dm_static/libdmodule.a differ diff --git a/deps/win/x64/dm_static/dmodule.lib b/deps/win/x64/dm_static/dmodule.lib index 55afb81e3f..955b11b7c3 100644 Binary files a/deps/win/x64/dm_static/dmodule.lib and b/deps/win/x64/dm_static/dmodule.lib differ diff --git a/deps/x86/dm_static/libdmodule.a b/deps/x86/dm_static/libdmodule.a index f2d3f600ce..84fc6c382d 100644 Binary files a/deps/x86/dm_static/libdmodule.a and b/deps/x86/dm_static/libdmodule.a differ diff --git a/docs/en/14-reference/01-components/01-taosd.md b/docs/en/14-reference/01-components/01-taosd.md index 77b6dd27e0..81bfd2ecad 100644 --- a/docs/en/14-reference/01-components/01-taosd.md +++ b/docs/en/14-reference/01-components/01-taosd.md @@ -73,6 +73,9 @@ After modifying configuration file parameters, you need to restart the *taosd* s |tagFilterCache | |Not supported |Whether to cache tag filter results| |queryBufferSize | |Supported, effective after restart|Not effective yet| |queryRspPolicy | |Supported, effective immediately |Query response strategy| +|queryUseMemoryPool | |Not supported |Whether query will use memory pool to manage memory, default value: 1 (on); 0: off, 1: on| +|minReservedMemorySize | |Not supported |The minimum reserved system available memory size, all memory except reserved can be used for queries, unit: MB, default reserved size is 20% of system physical memory, value range 1024-1000000000| +|singleQueryMaxMemorySize| |Not supported |The memory limit that a single query can use on a single node (dnode), exceeding this limit will return an error, unit: MB, default value: 0 (no limit), value range 0-1000000000| |filterScalarMode | |Not supported |Force scalar filter mode, 0: off; 1: on, default value 0| |queryPlannerTrace | |Supported, effective immediately |Internal parameter, whether the query plan outputs detailed logs| |queryNodeChunkSize | |Supported, effective immediately |Internal parameter, chunk size of the query plan| diff --git a/docs/en/14-reference/09-error-code.md b/docs/en/14-reference/09-error-code.md index bf5e5767cf..1d3ea3f9a1 100644 --- a/docs/en/14-reference/09-error-code.md +++ b/docs/en/14-reference/09-error-code.md @@ -286,6 +286,9 @@ This document details the server error codes that may be encountered when using | 0x80000729 | Task message error | Query message error | Preserve the scene and logs, report issue on GitHub | | 0x8000072B | Task status error | Subquery status error | Preserve the scene and logs, report issue on GitHub | | 0x8000072F | Job not exist | Query JOB no longer exists | Preserve the scene and logs, report issue on GitHub | +| 0x80000739 | Query memory upper limit is reached | Single query memory upper limit is reached | Modify memory upper limit size or optimize SQL | +| 0x8000073A | Query memory exhausted | Query memory in dnode is exhausted | Limit concurrent queries or add more physical memory | +| 0x8000073B | Timeout for long time no fetch | Query without fetch for a long time | Correct application to fetch data asap | ## grant diff --git a/docs/zh/14-reference/01-components/01-taosd.md b/docs/zh/14-reference/01-components/01-taosd.md index 7428495691..da86fadf2b 100644 --- a/docs/zh/14-reference/01-components/01-taosd.md +++ b/docs/zh/14-reference/01-components/01-taosd.md @@ -69,6 +69,9 @@ taosd 命令行参数如下 |tagFilterCache | |不支持动态修改 |是否缓存标签过滤结果| |queryBufferSize | |支持动态修改 重启生效 |暂不生效| |queryRspPolicy | |支持动态修改 立即生效 |查询响应策略| +|queryUseMemoryPool | |不支持动态修改 |查询是否使用内存池管理内存,默认值:1(打开); 0: 关闭,1: 打开| +|minReservedMemorySize | |不支持动态修改 |最小预留的系统可用内存数量,除预留外的内存都可以被用于查询,单位:MB,默认预留大小为系统物理内存的 20%,取值范围 1024 - 1000000000| +|singleQueryMaxMemorySize| |不支持动态修改 |单个查询在单个节点(dnode)上可以使用的内存上限,超过该上限将返回错误,单位:MB,默认值:0(无上限),取值范围 0 - 1000000000| |filterScalarMode | |不支持动态修改 |强制使用标量过滤模式,0:关闭;1:开启,默认值 0| |queryPlannerTrace | |支持动态修改 立即生效 |内部参数,查询计划是否输出详细日志| |queryNodeChunkSize | |支持动态修改 立即生效 |内部参数,查询计划的块大小| diff --git a/docs/zh/14-reference/09-error-code.md b/docs/zh/14-reference/09-error-code.md index 0a3e904cbc..2bebe2406b 100644 --- a/docs/zh/14-reference/09-error-code.md +++ b/docs/zh/14-reference/09-error-code.md @@ -296,6 +296,9 @@ description: TDengine 服务端的错误码列表和详细说明 | 0x80000729 | Task message error | 查询消息错误 | 保留现场和日志,github上报issue | | 0x8000072B | Task status error | 子查询状态错误 | 保留现场和日志,github上报issue | | 0x8000072F | Job not exist | 查询JOB已经不存在 | 保留现场和日志,github上报issue | +| 0x80000739 | Query memory upper limit is reached | 单个查询达到内存使用上限 | 设置合理的内存上限或调整 SQL 语句 | +| 0x8000073A | Query memory exhausted | dnode查询内存到达使用上限 | 设置合理的内存上限或调整并发查询量或增大系统内存 | +| 0x8000073B | Timeout for long time no fetch | 查询被长时间中断未恢复 | 调整应用实现尽快 fetch 数据 | ## grant diff --git a/include/common/tglobal.h b/include/common/tglobal.h index cb27e76b35..638e5e0278 100644 --- a/include/common/tglobal.h +++ b/include/common/tglobal.h @@ -79,6 +79,18 @@ extern int32_t tsTagFilterResCacheSize; extern int32_t tsBypassFlag; // queue & threads +extern int32_t tsQueryMinConcurrentTaskNum; +extern int32_t tsQueryMaxConcurrentTaskNum; +extern int32_t tsQueryConcurrentTaskNum; +extern int32_t tsSingleQueryMaxMemorySize; +extern int8_t tsQueryUseMemoryPool; +extern int8_t tsMemPoolFullFunc; +//extern int32_t tsQueryBufferPoolSize; +extern int32_t tsMinReservedMemorySize; +extern int64_t tsCurrentAvailMemorySize; +extern int8_t tsNeedTrim; +extern int32_t tsQueryNoFetchTimeoutSec; +extern int32_t tsNumOfQueryThreads; extern int32_t tsNumOfRpcThreads; extern int32_t tsNumOfRpcSessions; extern int32_t tsShareConnLimit; diff --git a/include/common/tmsg.h b/include/common/tmsg.h index 9215ef6cf6..b26d98f4b4 100644 --- a/include/common/tmsg.h +++ b/include/common/tmsg.h @@ -2782,7 +2782,7 @@ int32_t tDeserializeSResFetchReq(void* buf, int32_t bufLen, SResFetchReq* pReq); typedef struct { SMsgHead header; - uint64_t sId; + uint64_t clientId; } SSchTasksStatusReq; typedef struct { @@ -2812,7 +2812,7 @@ typedef struct SQueryNodeEpId { typedef struct { SMsgHead header; - uint64_t sId; + uint64_t clientId; SQueryNodeEpId epId; SArray* taskAction; // SArray } SSchedulerHbReq; diff --git a/include/common/tmsgcb.h b/include/common/tmsgcb.h index 0c61aa5a51..6752287ed1 100644 --- a/include/common/tmsgcb.h +++ b/include/common/tmsgcb.h @@ -47,7 +47,7 @@ typedef int32_t (*GetQueueSizeFp)(void* pMgmt, int32_t vgId, EQueueType qtype); typedef int32_t (*SendReqFp)(const SEpSet* pEpSet, SRpcMsg* pMsg); typedef void (*SendRspFp)(SRpcMsg* pMsg); typedef void (*RegisterBrokenLinkArgFp)(struct SRpcMsg* pMsg); -typedef void (*ReleaseHandleFp)(SRpcHandleInfo* pHandle, int8_t type); +typedef void (*ReleaseHandleFp)(SRpcHandleInfo* pHandle, int8_t type, int32_t status); typedef void (*ReportStartup)(const char* name, const char* desc); typedef struct { @@ -76,7 +76,7 @@ int32_t tmsgSendReq(const SEpSet* epSet, SRpcMsg* pMsg); int32_t tmsgSendSyncReq(const SEpSet* epSet, SRpcMsg* pMsg); void tmsgSendRsp(SRpcMsg* pMsg); void tmsgRegisterBrokenLinkArg(SRpcMsg* pMsg); -void tmsgReleaseHandle(SRpcHandleInfo* pHandle, int8_t type); +void tmsgReleaseHandle(SRpcHandleInfo* pHandle, int8_t type, int32_t code); void tmsgReportStartup(const char* name, const char* desc); bool tmsgUpdateDnodeInfo(int32_t* dnodeId, int64_t* clusterId, char* fqdn, uint16_t* port); void tmsgUpdateDnodeEpSet(SEpSet* epset); diff --git a/include/libs/executor/dataSinkMgt.h b/include/libs/executor/dataSinkMgt.h index 130de8c030..9267a74bb7 100644 --- a/include/libs/executor/dataSinkMgt.h +++ b/include/libs/executor/dataSinkMgt.h @@ -29,6 +29,9 @@ extern "C" { #define DS_BUF_FULL 2 #define DS_BUF_EMPTY 3 +#define DS_FLAG_USE_MEMPOOL (1 << 0) + + struct SSDataBlock; typedef struct SDeleterRes { @@ -84,7 +87,7 @@ typedef struct SOutputData { * @param pHandle output * @return error code */ -int32_t dsCreateDataSinker(void* pSinkManager, const SDataSinkNode* pDataSink, DataSinkHandle* pHandle, void* pParam, const char* id); +int32_t dsCreateDataSinker(void* pSinkManager, SDataSinkNode** ppDataSink, DataSinkHandle* pHandle, void* pParam, const char* id); int32_t dsDataSinkGetCacheSize(SDataSinkStat* pStat); @@ -131,6 +134,9 @@ void dsScheduleProcess(void* ahandle, void* pItem); */ void dsDestroyDataSinker(DataSinkHandle handle); +int32_t dsGetSinkFlags(DataSinkHandle handle, uint64_t* pFlags); + + #ifdef __cplusplus } #endif diff --git a/include/libs/executor/executor.h b/include/libs/executor/executor.h index 99bf81b08d..883c5f7b99 100644 --- a/include/libs/executor/executor.h +++ b/include/libs/executor/executor.h @@ -58,6 +58,7 @@ typedef struct { struct SStorageAPI api; void* pWorkerCb; + bool localExec; } SReadHandle; // in queue mode, data streams are seperated by msg @@ -167,6 +168,7 @@ int32_t qExecTaskOpt(qTaskInfo_t tinfo, SArray* pResList, uint64_t* useconds, bo int32_t qExecTask(qTaskInfo_t tinfo, SSDataBlock** pBlock, uint64_t* useconds); +int32_t qExecutorInit(void); void qResetTaskCode(qTaskInfo_t tinfo); void qCleanExecTaskBlockBuf(qTaskInfo_t tinfo); diff --git a/include/libs/nodes/plannodes.h b/include/libs/nodes/plannodes.h index ad9ac26121..3e95f1e286 100644 --- a/include/libs/nodes/plannodes.h +++ b/include/libs/nodes/plannodes.h @@ -631,7 +631,7 @@ typedef struct SDownstreamSourceNode { SQueryNodeAddr addr; uint64_t clientId; uint64_t taskId; - uint64_t schedId; + uint64_t sId; int32_t execId; int32_t fetchMsgType; bool localExec; diff --git a/include/libs/qworker/qworker.h b/include/libs/qworker/qworker.h index cb4e359727..6e73e94b01 100644 --- a/include/libs/qworker/qworker.h +++ b/include/libs/qworker/qworker.h @@ -113,6 +113,11 @@ int32_t qWorkerProcessLocalFetch(void *pMgmt, uint64_t sId, uint64_t qId, uint64 int32_t qWorkerDbgEnableDebug(char *option); +void qWorkerRetireJob(uint64_t jobId, uint64_t clientId, int32_t errCode); + +void qWorkerRetireJobs(int64_t retireSize, int32_t errCode); + + #ifdef __cplusplus } #endif diff --git a/include/libs/transport/trpc.h b/include/libs/transport/trpc.h index cfa3f44f7f..7b3fb5bb79 100644 --- a/include/libs/transport/trpc.h +++ b/include/libs/transport/trpc.h @@ -171,7 +171,7 @@ void *rpcReallocCont(void *ptr, int64_t contLen); int32_t rpcSendRequest(void *thandle, const SEpSet *pEpSet, SRpcMsg *pMsg, int64_t *rid); int32_t rpcSendResponse(const SRpcMsg *pMsg); int32_t rpcRegisterBrokenLinkArg(SRpcMsg *msg); -int32_t rpcReleaseHandle(void *handle, int8_t type); // just release conn to rpc instance, no close sock +int32_t rpcReleaseHandle(void *handle, int8_t type, int32_t code); // just release conn to rpc instance, no close sock // These functions will not be called in the child process int32_t rpcSendRequestWithCtx(void *thandle, const SEpSet *pEpSet, SRpcMsg *pMsg, int64_t *rid, SRpcCtx *ctx); diff --git a/include/os/os.h b/include/os/os.h index 4314148685..a9c5ce5679 100644 --- a/include/os/os.h +++ b/include/os/os.h @@ -110,6 +110,7 @@ extern "C" { #include "osLz4.h" #include "osMath.h" #include "osMemory.h" +#include "osMemPool.h" #include "osRand.h" #include "osSemaphore.h" #include "osSignal.h" diff --git a/include/os/osMemPool.h b/include/os/osMemPool.h new file mode 100644 index 0000000000..78cdf15b49 --- /dev/null +++ b/include/os/osMemPool.h @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef _TD_OS_MEMPOOL_H_ +#define _TD_OS_MEMPOOL_H_ + +#include "os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MEMPOOL_MAX_CHUNK_SIZE (1 << 30) +#define MEMPOOL_MIN_CHUNK_SIZE (1 << 20) + +typedef enum MemPoolEvictPolicy { + E_EVICT_ALL = 1, + E_EVICT_NONE, + E_EVICT_AUTO, + E_EVICT_MAX_VALUE, // no used +} MemPoolEvictPolicy; + +typedef struct SMemPoolJob { + uint64_t jobId; + uint64_t clientId; + + int32_t remainSession; + + int64_t allocMemSize; + int64_t maxAllocMemSize; +} SMemPoolJob; + +typedef struct SMPStatItem { + int64_t inErr; + int64_t exec; + int64_t succ; + int64_t fail; +} SMPStatItem; + +typedef struct SMPStatItemExt { + int64_t inErr; + int64_t exec; + int64_t succ; + int64_t fail; + int64_t origExec; + int64_t origSucc; + int64_t origFail; +} SMPStatItemExt; + +typedef struct SMPMemoryStat { + SMPStatItem memMalloc; + SMPStatItem memCalloc; + SMPStatItemExt memRealloc; + SMPStatItem memStrdup; + SMPStatItem memStrndup; + SMPStatItem memFree; + SMPStatItem memTrim; + + SMPStatItem chunkMalloc; + SMPStatItem chunkRecycle; + SMPStatItem chunkReUse; + SMPStatItem chunkFree; +} SMPMemoryStat; + +typedef struct SMPStatDetail { + SMPMemoryStat times; + SMPMemoryStat bytes; +} SMPStatDetail; + + +typedef void (*mpDecConcSessionNum)(void); +typedef void (*mpIncConcSessionNum)(void); +typedef void (*mpSetConcSessionNum)(int32_t); +typedef void (*mpReserveFailFp)(int64_t, int32_t); +typedef void (*mpReserveReachFp)(uint64_t, uint64_t, int32_t); +typedef void (*mpCfgUpdate)(void*, void*); + +typedef struct SMemPoolCallBack { + //mpDecConcSessionNum decSessFp; + //mpIncConcSessionNum incSessFp; + //mpSetConcSessionNum setSessFp; + mpReserveFailFp failFp; + mpReserveReachFp reachFp; + //mpCfgUpdate cfgUpdateFp; +} SMemPoolCallBack; + + +typedef struct SMemPoolCfg { + //bool reserveMode; + int64_t reserveSize; + //int32_t *upperLimitSize; //MB + //int64_t retireUnitSize; + int32_t *jobQuota; //MB + int32_t chunkSize; + int32_t threadNum; + MemPoolEvictPolicy evicPolicy; + SMemPoolCallBack cb; +} SMemPoolCfg; + +#define MEMPOOL_GET_ALLOC_SIZE(_dstat) ((_dstat)->bytes.memMalloc.succ + (_dstat)->bytes.memCalloc.succ + (_dstat)->bytes.memRealloc.succ + (_dstat)->bytes.memStrdup.succ + (_dstat)->bytes.memStrndup.succ) +#define MEMPOOL_GET_FREE_SIZE(_dstat) ((_dstat)->bytes.memRealloc.origSucc + (_dstat)->bytes.memFree.succ) +#define MEMPOOL_GET_USED_SIZE(_dstat) (MEMPOOL_GET_ALLOC_SIZE(_dstat) - MEMPOOL_GET_FREE_SIZE(_dstat)) + + +int32_t taosMemPoolOpen(char* poolName, SMemPoolCfg* cfg, void** poolHandle); +void *taosMemPoolMalloc(void* poolHandle, void* session, int64_t size, char* fileName, int32_t lineNo); +void *taosMemPoolCalloc(void* poolHandle, void* session, int64_t num, int64_t size, char* fileName, int32_t lineNo); +void *taosMemPoolRealloc(void* poolHandle, void* session, void *ptr, int64_t size, char* fileName, int32_t lineNo); +char *taosMemPoolStrdup(void* poolHandle, void* session, const char *ptr, char* fileName, int32_t lineNo); +char *taosMemPoolStrndup(void* poolHandle, void* session, const char *ptr, int64_t size, char* fileName, int32_t lineNo); +void taosMemPoolFree(void* poolHandle, void* session, void *ptr, char* fileName, int32_t lineNo); +int64_t taosMemPoolGetMemorySize(void* poolHandle, void* session, void *ptr, char* fileName, int32_t lineNo); +int32_t taosMemPoolTrim(void* poolHandle, void* session, int32_t size, char* fileName, int32_t lineNo, bool* trimed); +void *taosMemPoolMallocAlign(void* poolHandle, void* session, uint32_t alignment, int64_t size, char* fileName, int32_t lineNo); +void taosMemPoolClose(void* poolHandle); +void taosMemPoolModDestroy(void); +void taosAutoMemoryFree(void *ptr); +int32_t taosMemPoolInitSession(void* poolHandle, void** ppSession, void* pJob, char *sessionId); +void taosMemPoolDestroySession(void* poolHandle, void* session); +int32_t taosMemPoolCallocJob(uint64_t jobId, uint64_t cId, void** ppJob); +void taosMemPoolCfgUpdate(void* poolHandle, SMemPoolCfg* pCfg); +void taosMemPoolPrintStat(void* poolHandle, void* session, char* procName); +int32_t taosMemPoolTryLockPool(void* poolHandle, bool readLock); +void taosMemPoolUnLockPool(void* poolHandle, bool readLock); +void taosMemPoolGetUsedSizeBegin(void* poolHandle, int64_t* usedSize, bool* needEnd); +void taosMemPoolGetUsedSizeEnd(void* poolHandle); +int32_t taosMemPoolGetSessionStat(void* session, SMPStatDetail** ppStat, int64_t* allocSize, int64_t* maxAllocSize); +void taosMemPoolSchedTrim(void); +int32_t taosMemoryPoolInit(mpReserveFailFp, mpReserveReachFp); + + +#define taosMemPoolFreeClear(ptr) \ + do { \ + if (ptr) { \ + taosMemPoolFree((void *)ptr); \ + (ptr) = NULL; \ + } \ + } while (0) + + +#ifndef BUILD_TEST +extern void* gMemPoolHandle; +extern threadlocal void* threadPoolSession; +extern threadlocal bool threadPoolEnabled; +extern int8_t tsMemPoolFullFunc; + + +#define taosEnableMemPoolUsage(_session) do { threadPoolSession = _session; tsEnableRandErr = true;} while (0) +#define taosDisableMemPoolUsage() do { threadPoolSession = NULL; tsEnableRandErr = false;} while (0) + +#define taosSaveDisableMemPoolUsage(_enable, _randErr) do { (_enable) = threadPoolEnabled; (_randErr) = tsEnableRandErr; threadPoolEnabled = false; tsEnableRandErr = false;} while (0) +#define taosRestoreEnableMemPoolUsage(_enable, _randErr) do { threadPoolEnabled = (_enable); tsEnableRandErr = (_randErr);} while (0) + + +#define taosMemoryMalloc(_size) ((threadPoolEnabled && threadPoolSession) ? (taosMemPoolMalloc(gMemPoolHandle, threadPoolSession, _size, (char*)__FILE__, __LINE__)) : (taosMemMalloc(_size))) +#define taosMemoryCalloc(_num, _size) ((threadPoolEnabled && threadPoolSession) ? (taosMemPoolCalloc(gMemPoolHandle, threadPoolSession, _num, _size, (char*)__FILE__, __LINE__)) : (taosMemCalloc(_num, _size))) +#define taosMemoryRealloc(_ptr, _size) ((threadPoolEnabled && threadPoolSession) ? (taosMemPoolRealloc(gMemPoolHandle, threadPoolSession, _ptr, _size, (char*)__FILE__, __LINE__)) : (taosMemRealloc(_ptr, _size))) +#define taosStrdup(_ptr) ((threadPoolEnabled && threadPoolSession) ? (taosMemPoolStrdup(gMemPoolHandle, threadPoolSession, _ptr, (char*)__FILE__, __LINE__)) : (taosStrdupi(_ptr))) +#define taosStrndup(_ptr, _size) ((threadPoolEnabled && threadPoolSession) ? (taosMemPoolStrndup(gMemPoolHandle, threadPoolSession, _ptr, _size, (char*)__FILE__, __LINE__)) : (taosStrndupi(_ptr, _size))) +#define taosMemoryFree(_ptr) ((threadPoolEnabled && threadPoolSession) ? (taosMemPoolFree(gMemPoolHandle, threadPoolSession, _ptr, (char*)__FILE__, __LINE__)) : (taosMemFree(_ptr))) +#define taosMemorySize(_ptr) ((threadPoolEnabled && threadPoolSession) ? (taosMemPoolGetMemorySize(gMemPoolHandle, threadPoolSession, _ptr, (char*)__FILE__, __LINE__)) : (taosMemSize(_ptr))) +#define taosMemoryTrim(_size, _trimed) ((threadPoolEnabled && threadPoolSession) ? (taosMemPoolTrim(gMemPoolHandle, threadPoolSession, _size, (char*)__FILE__, __LINE__, _trimed)) : (taosMemTrim(_size, _trimed))) +#define taosMemoryMallocAlign(_alignment, _size) ((threadPoolEnabled && threadPoolSession) ? (taosMemPoolMallocAlign(gMemPoolHandle, threadPoolSession, _alignment, _size, (char*)__FILE__, __LINE__)) : (taosMemMallocAlign(_alignment, _size))) +#else +#define taosEnableMemoryPoolUsage(_pool, _session) +#define taosDisableMemoryPoolUsage() +#define taosSaveDisableMemoryPoolUsage() +#define taosRestoreEnableMemoryPoolUsage() + +#define taosMemoryMalloc(_size) taosMemMalloc(_size) +#define taosMemoryCalloc(_num, _size) taosMemCalloc(_num, _size) +#define taosMemoryRealloc(_ptr, _size) taosMemRealloc(_ptr, _size) +#define taosStrdup(_ptr) taosStrdupi(_ptr) +#define taosStrndup(_ptr, _size) taosStrndupi(_ptr, _size) +#define taosMemoryFree(_ptr) taosMemFree(_ptr) +#define taosMemorySize(_ptr) taosMemSize(_ptr) +#define taosMemoryTrim(_size, _trimed) taosMemTrim(_size, _trimed) +#define taosMemoryMallocAlign(_alignment, _size) taosMemMallocAlign(_alignment, _size) + +#endif + +#define taosMemoryFreeClear(ptr) \ + do { \ + if (ptr) { \ + taosMemoryFree((void *)ptr); \ + (ptr) = NULL; \ + } \ + } while (0) + + +#ifdef __cplusplus +} +#endif + +#endif /*_TD_OS_MEMPOOL_H_*/ diff --git a/include/os/osMemory.h b/include/os/osMemory.h index 0cb4534d83..51e57820b9 100644 --- a/include/os/osMemory.h +++ b/include/os/osMemory.h @@ -36,35 +36,32 @@ extern "C" { #endif // ifndef ALLOW_FORBID_FUNC #endif // if !defined(WINDOWS) -// #define taosMemoryMalloc malloc -// #define taosMemoryCalloc calloc -// #define taosMemoryRealloc realloc -// #define taosMemoryFree free - int32_t taosMemoryDbgInit(); int32_t taosMemoryDbgInitRestore(); -void *taosMemoryMalloc(int64_t size); -void *taosMemoryCalloc(int64_t num, int64_t size); -void *taosMemoryRealloc(void *ptr, int64_t size); -char *taosStrdup(const char *ptr); -void taosMemoryFree(void *ptr); -int64_t taosMemorySize(void *ptr); +void *taosMemMalloc(int64_t size); +void *taosMemCalloc(int64_t num, int64_t size); +void *taosMemRealloc(void *ptr, int64_t size); +char *taosStrdupi(const char *ptr); +char *taosStrndupi(const char *ptr, int64_t size); +void taosMemFree(void *ptr); +int64_t taosMemSize(void *ptr); void taosPrintBackTrace(); -void taosMemoryTrim(int32_t size); -void *taosMemoryMallocAlign(uint32_t alignment, int64_t size); +int32_t taosMemTrim(int32_t size, bool* trimed); +void *taosMemMallocAlign(uint32_t alignment, int64_t size); #define TAOS_MEMSET(_s, _c, _n) ((void)memset(_s, _c, _n)) #define TAOS_MEMCPY(_d, _s, _n) ((void)memcpy(_d, _s, _n)) #define TAOS_MEMMOVE(_d, _s, _n) ((void)memmove(_d, _s, _n)) -#define taosMemoryFreeClear(ptr) \ +#define taosMemFreeClear(ptr) \ do { \ if (ptr) { \ - taosMemoryFree((void *)ptr); \ + taosMemFree((void *)ptr); \ (ptr) = NULL; \ } \ } while (0) +#include "osMemPool.h" #define TAOS_MEMORY_REALLOC(ptr, len) \ do { \ void *tmp = taosMemoryRealloc(ptr, (len)); \ diff --git a/include/os/osString.h b/include/os/osString.h index a841771a46..63c7aca58c 100644 --- a/include/os/osString.h +++ b/include/os/osString.h @@ -84,6 +84,7 @@ int64_t tsnprintf(char *dst, int64_t size, const char *format, ...); #define TAOS_STRNCAT(_dst, _src, len) ((void)strncat(_dst, _src, len)) char *tstrdup(const char *src); +char *tstrndup(const char *str, int64_t size); int32_t taosUcs4len(TdUcs4 *ucs4); int32_t taosStr2int64(const char *str, int64_t *val); int32_t taosStr2int32(const char *str, int32_t *val); @@ -126,7 +127,6 @@ double taosStr2Double(const char *str, char **pEnd); float taosStr2Float(const char *str, char **pEnd); int32_t taosHex2Ascii(const char *z, uint32_t n, void **data, uint32_t *size); int32_t taosAscii2Hex(const char *z, uint32_t n, void **data, uint32_t *size); -char *taosStrndup(const char *s, int n); // int32_t taosBin2Ascii(const char *z, uint32_t n, void** data, uint32_t* size); bool isHex(const char *z, uint32_t n); bool isValidateHex(const char *z, uint32_t n); diff --git a/include/os/osSysinfo.h b/include/os/osSysinfo.h index d292b326d5..1f4dfe3809 100644 --- a/include/os/osSysinfo.h +++ b/include/os/osSysinfo.h @@ -45,6 +45,7 @@ int32_t taosGetCpuInstructions(char* sse42, char* avx, char* avx2, char* fma, ch int32_t taosGetTotalMemory(int64_t *totalKB); int32_t taosGetProcMemory(int64_t *usedKB); int32_t taosGetSysMemory(int64_t *usedKB); +int32_t taosGetSysAvailMemory(int64_t *availSize); int32_t taosGetDiskSize(char *dataDir, SDiskSize *diskSize); int32_t taosGetProcIODelta(int64_t *rchars, int64_t *wchars, int64_t *read_bytes, int64_t *write_bytes); void taosSetDefaultProcIODelta(int64_t *rchars, int64_t *wchars, int64_t *read_bytes, int64_t *write_bytes); diff --git a/include/util/taoserror.h b/include/util/taoserror.h index a6f703ed55..74460bc911 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -645,6 +645,9 @@ int32_t taosGetErrSize(); #define TSDB_CODE_QRY_FILTER_RANGE_ERROR TAOS_DEF_ERROR_CODE(0, 0x0736) #define TSDB_CODE_QRY_FILTER_INVALID_TYPE TAOS_DEF_ERROR_CODE(0, 0x0737) #define TSDB_CODE_QRY_TASK_SUCC_TO_PARTSUSS TAOS_DEF_ERROR_CODE(0, 0x0738) +#define TSDB_CODE_QRY_REACH_QMEM_THRESHOLD TAOS_DEF_ERROR_CODE(0, 0x0739) +#define TSDB_CODE_QRY_QUERY_MEM_EXHAUSTED TAOS_DEF_ERROR_CODE(0, 0x073A) +#define TSDB_CODE_QRY_NO_FETCH_TIMEOUT TAOS_DEF_ERROR_CODE(0, 0x073B) // grant #define TSDB_CODE_GRANT_EXPIRED TAOS_DEF_ERROR_CODE(0, 0x0800) diff --git a/include/util/tconfig.h b/include/util/tconfig.h index cc4c605ad4..b1bd144d77 100644 --- a/include/util/tconfig.h +++ b/include/util/tconfig.h @@ -136,6 +136,7 @@ void cfgUnLock(SConfig *pCfg); // clang-format off int32_t cfgAddBool(SConfig *pCfg, const char *name, bool defaultVal, int8_t scope, int8_t dynScope,int8_t category); int32_t cfgAddInt32(SConfig *pCfg, const char *name, int32_t defaultVal, int64_t minval, int64_t maxval, int8_t scope, int8_t dynScope,int8_t category); +int32_t cfgAddInt32Ex(SConfig *pCfg, const char *name, int32_t defaultVal, int64_t minval, int64_t maxval, int8_t scope, int8_t dynScope,int8_t category); int32_t cfgAddInt64(SConfig *pCfg, const char *name, int64_t defaultVal, int64_t minval, int64_t maxval, int8_t scope, int8_t dynScope,int8_t category); int32_t cfgAddFloat(SConfig *pCfg, const char *name, float defaultVal, float minval, float maxval, int8_t scope, int8_t dynScope,int8_t category); int32_t cfgAddString(SConfig *pCfg, const char *name, const char *defaultVal, int8_t scope, int8_t dynScope,int8_t category); diff --git a/include/util/tdef.h b/include/util/tdef.h index d6d14005f4..c23b073d42 100644 --- a/include/util/tdef.h +++ b/include/util/tdef.h @@ -655,6 +655,8 @@ typedef enum { ANAL_ALGO_TYPE_END, } EAnalAlgoType; +#define MIN_RESERVE_MEM_SIZE 1024 // MB + #ifdef __cplusplus } #endif diff --git a/include/util/theap.h b/include/util/theap.h index b795db6aea..abef2ab391 100644 --- a/include/util/theap.h +++ b/include/util/theap.h @@ -87,6 +87,8 @@ BoundedQueue* createBoundedQueue(uint32_t maxSize, pq_comp_fn fn, FDelete delete void taosBQSetFn(BoundedQueue* q, pq_comp_fn fn); +void taosBQClear(BoundedQueue* q); + void destroyBoundedQueue(BoundedQueue* q); /* diff --git a/include/util/tlockfree.h b/include/util/tlockfree.h index 24e83f23ca..8c884dafae 100644 --- a/include/util/tlockfree.h +++ b/include/util/tlockfree.h @@ -72,6 +72,7 @@ void taosInitRWLatch(SRWLatch *pLatch); void taosWLockLatch(SRWLatch *pLatch); void taosWUnLockLatch(SRWLatch *pLatch); void taosRLockLatch(SRWLatch *pLatch); +int32_t taosRTryLockLatch(SRWLatch *pLatch); void taosRUnLockLatch(SRWLatch *pLatch); int32_t taosWTryLockLatch(SRWLatch *pLatch); diff --git a/include/util/tlog.h b/include/util/tlog.h index 78ca6ffe15..d0e42e3660 100644 --- a/include/util/tlog.h +++ b/include/util/tlog.h @@ -77,6 +77,7 @@ int32_t taosInitLog(const char *logName, int32_t maxFiles, bool tsc); void taosCloseLog(); void taosResetLog(); void taosDumpData(uint8_t *msg, int32_t len); +void taosSetNoNewFile(); void taosPrintLog(const char *flags, int32_t level, int32_t dflag, const char *format, ...) #ifdef __GNUC__ diff --git a/include/util/tmempool.h b/include/util/tmempool.h deleted file mode 100644 index 7a5aca7b34..0000000000 --- a/include/util/tmempool.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -#ifndef _TD_UTIL_MEMPOOL_H_ -#define _TD_UTIL_MEMPOOL_H_ - -#include "os.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void *mpool_h; - -mpool_h taosMemPoolInit(int32_t maxNum, int32_t blockSize); -char *taosMemPoolMalloc(mpool_h handle); -void taosMemPoolFree(mpool_h handle, char *p); -void taosMemPoolCleanUp(mpool_h handle); - -#ifdef __cplusplus -} -#endif - -#endif /*_TD_UTIL_MEMPOOL_H_*/ diff --git a/include/util/tpagedbuf.h b/include/util/tpagedbuf.h index 71cee62d2e..045716d3ca 100644 --- a/include/util/tpagedbuf.h +++ b/include/util/tpagedbuf.h @@ -50,7 +50,7 @@ typedef struct SDiskbasedBufStatis { * @param handle * @return */ -int32_t createDiskbasedBuf(SDiskbasedBuf** pBuf, int32_t pagesize, int32_t inMemBufSize, const char* id, +int32_t createDiskbasedBuf(SDiskbasedBuf** pBuf, int32_t pagesize, int64_t inMemBufSize, const char* id, const char* dir); /** diff --git a/include/util/ttimer.h b/include/util/ttimer.h index 4111a8ca28..53a8f0a19f 100644 --- a/include/util/ttimer.h +++ b/include/util/ttimer.h @@ -39,6 +39,8 @@ bool taosTmrStop(tmr_h tmrId); bool taosTmrStopA(tmr_h *tmrId); +bool taosTmrIsStopped(tmr_h* timerId); + bool taosTmrReset(TAOS_TMR_CALLBACK fp, int32_t mseconds, void *param, void *handle, tmr_h *pTmrId); #ifdef __cplusplus diff --git a/source/client/src/clientEnv.c b/source/client/src/clientEnv.c index a3ffa7f3c2..c58d3bd4df 100644 --- a/source/client/src/clientEnv.c +++ b/source/client/src/clientEnv.c @@ -689,7 +689,7 @@ void doDestroyRequest(void *p) { SRequestObj *pRequest = (SRequestObj *)p; uint64_t reqId = pRequest->requestId; - tscTrace("begin to destroy request %" PRIx64 " p:%p", reqId, pRequest); + tscDebug("begin to destroy request 0x%" PRIx64 " p:%p", reqId, pRequest); int64_t nextReqRefId = pRequest->relation.nextRefId; @@ -731,7 +731,7 @@ void doDestroyRequest(void *p) { taosMemoryFreeClear(pRequest->effectiveUser); taosMemoryFreeClear(pRequest->sqlstr); taosMemoryFree(pRequest); - tscTrace("end to destroy request %" PRIx64 " p:%p", reqId, pRequest); + tscDebug("end to destroy request %" PRIx64 " p:%p", reqId, pRequest); destroyNextReq(nextReqRefId); } @@ -955,7 +955,7 @@ void taos_init_imp(void) { taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_ENTRY_LOCK); if (NULL == appInfo.pInstMap || NULL == appInfo.pInstMapByClusterId) { (void)printf("failed to allocate memory when init appInfo\n"); - tscInitRes = TSDB_CODE_OUT_OF_MEMORY; + tscInitRes = terrno; return; } taosHashSetFreeFp(appInfo.pInstMap, destroyAppInst); diff --git a/source/client/src/clientHb.c b/source/client/src/clientHb.c index 23b3b0315f..b3e288c816 100644 --- a/source/client/src/clientHb.c +++ b/source/client/src/clientHb.c @@ -595,6 +595,7 @@ static int32_t hbAsyncCallBack(void *param, SDataBuf *pMsg, int32_t code) { } SAppInstInfo *pInst = pAppHbMgr->pAppInstInfo; + if (code != 0) { pInst->onlineDnodes = pInst->totalDnodes ? 0 : -1; tscDebug("hb rsp error %s, update server status %d/%d", tstrerror(code), pInst->onlineDnodes, pInst->totalDnodes); @@ -1338,7 +1339,6 @@ static void *hbThreadFunc(void *param) { } void *buf = taosMemoryMalloc(tlen); if (buf == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; tFreeClientHbBatchReq(pReq); // hbClearReqInfo(pAppHbMgr); break; @@ -1352,7 +1352,6 @@ static void *hbThreadFunc(void *param) { SMsgSendInfo *pInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo)); if (pInfo == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; tFreeClientHbBatchReq(pReq); // hbClearReqInfo(pAppHbMgr); taosMemoryFree(buf); @@ -1364,7 +1363,6 @@ static void *hbThreadFunc(void *param) { pInfo->msgType = TDMT_MND_HEARTBEAT; pInfo->param = taosMemoryMalloc(sizeof(int32_t)); if (pInfo->param == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; tFreeClientHbBatchReq(pReq); // hbClearReqInfo(pAppHbMgr); taosMemoryFree(buf); @@ -1372,7 +1370,7 @@ static void *hbThreadFunc(void *param) { break; } *(int32_t *)pInfo->param = i; - pInfo->paramFreeFp = taosMemoryFree; + pInfo->paramFreeFp = taosAutoMemoryFree; pInfo->requestId = generateRequestId(); pInfo->requestObjRefId = 0; @@ -1458,7 +1456,7 @@ int32_t appHbMgrInit(SAppInstInfo *pAppInstInfo, char *key, SAppHbMgr **pAppHbMg (*pAppHbMgr)->reportBytes = 0; (*pAppHbMgr)->key = taosStrdup(key); if ((*pAppHbMgr)->key == NULL) { - TSC_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY); + TSC_ERR_JRET(terrno); } // init app info diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index e5e304bc79..c2a199e9c1 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -126,7 +126,7 @@ int32_t taos_connect_internal(const char* ip, const char* user, const char* pass char* key = getClusterKey(user, secretEncrypt, ip, port); if (NULL == key) { - TSC_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + TSC_ERR_RET(terrno); } tscInfo("connecting to server, numOfEps:%d inUse:%d user:%s db:%s key:%s", epSet.epSet.numOfEps, epSet.epSet.inUse, user, db, key); @@ -1820,11 +1820,10 @@ int32_t doProcessMsgFromServerImpl(SRpcMsg* pMsg, SEpSet* pEpSet) { .handleRefId = pMsg->info.refId, .pEpSet = pEpSet}; - if (pMsg->code != TSDB_CODE_OUT_OF_MEMORY && pMsg->contLen > 0) { + if (pMsg->contLen > 0) { buf.pData = taosMemoryCalloc(1, pMsg->contLen); if (buf.pData == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - pMsg->code = TSDB_CODE_OUT_OF_MEMORY; + pMsg->code = terrno; } else { (void)memcpy(buf.pData, pMsg->pCont, pMsg->contLen); } @@ -2957,7 +2956,6 @@ TAOS_RES* taosQueryImpl(TAOS* taos, const char* sql, bool validateOnly, int8_t s SSyncQueryParam* param = taosMemoryCalloc(1, sizeof(SSyncQueryParam)); if (NULL == param) { - terrno = TSDB_CODE_OUT_OF_MEMORY; return NULL; } int32_t code = tsem_init(¶m->sem, 0, 0); @@ -2998,7 +2996,6 @@ TAOS_RES* taosQueryImplWithReqid(TAOS* taos, const char* sql, bool validateOnly, SSyncQueryParam* param = taosMemoryCalloc(1, sizeof(SSyncQueryParam)); if (param == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; return NULL; } int32_t code = tsem_init(¶m->sem, 0, 0); diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c index d80c7df2e4..3d22c26fa7 100644 --- a/source/client/src/clientMain.c +++ b/source/client/src/clientMain.c @@ -292,7 +292,6 @@ TAOS *taos_connect(const char *ip, const char *user, const char *pass, const cha int64_t *rid = taosMemoryCalloc(1, sizeof(int64_t)); if (NULL == rid) { tscError("out of memory when taos connect to %s:%u, user:%s db:%s", ip, port, user, db); - terrno = TSDB_CODE_OUT_OF_MEMORY; return NULL; } *rid = pObj->id; @@ -424,7 +423,7 @@ void taos_fetch_whitelist_a(TAOS *taos, __taos_async_whitelist_fn_t fp, void *pa void *pReq = taosMemoryMalloc(msgLen); if (pReq == NULL) { - fp(param, TSDB_CODE_OUT_OF_MEMORY, taos, 0, NULL); + fp(param, terrno, taos, 0, NULL); releaseTscObj(connId); return; } @@ -438,7 +437,7 @@ void taos_fetch_whitelist_a(TAOS *taos, __taos_async_whitelist_fn_t fp, void *pa SFetchWhiteListInfo *pParam = taosMemoryMalloc(sizeof(SFetchWhiteListInfo)); if (pParam == NULL) { - fp(param, TSDB_CODE_OUT_OF_MEMORY, taos, 0, NULL); + fp(param, terrno, taos, 0, NULL); taosMemoryFree(pReq); releaseTscObj(connId); return; @@ -449,7 +448,7 @@ void taos_fetch_whitelist_a(TAOS *taos, __taos_async_whitelist_fn_t fp, void *pa pParam->userParam = param; SMsgSendInfo *pSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo)); if (pSendInfo == NULL) { - fp(param, TSDB_CODE_OUT_OF_MEMORY, taos, 0, NULL); + fp(param, terrno, taos, 0, NULL); taosMemoryFree(pParam); taosMemoryFree(pReq); releaseTscObj(connId); diff --git a/source/client/src/clientRawBlockWrite.c b/source/client/src/clientRawBlockWrite.c index 76aec26ff4..830144c12a 100644 --- a/source/client/src/clientRawBlockWrite.c +++ b/source/client/src/clientRawBlockWrite.c @@ -1348,7 +1348,7 @@ end: destroyRequest(pRequest); tDecoderClear(&coder); qDestroyQuery(pQuery); - taosArrayDestroyP(pTagList, taosMemoryFree); + taosArrayDestroyP(pTagList, NULL); return code; } @@ -1563,7 +1563,7 @@ static int32_t taosAlterTable(TAOS* taos, void* meta, int32_t metaLen) { req.source = TD_REQ_FROM_TAOX; tEncodeSize(tEncodeSVAlterTbReq, &req, tlen, code); if (code != 0) { - code = TSDB_CODE_OUT_OF_MEMORY; + code = terrno; goto end; } tlen += sizeof(SMsgHead); @@ -1577,7 +1577,7 @@ static int32_t taosAlterTable(TAOS* taos, void* meta, int32_t metaLen) { code = tEncodeSVAlterTbReq(&coder, &req); if (code != 0) { tEncoderClear(&coder); - code = TSDB_CODE_OUT_OF_MEMORY; + code = terrno; goto end; } tEncoderClear(&coder); diff --git a/source/client/src/clientSml.c b/source/client/src/clientSml.c index cc96d61b18..376dea895c 100644 --- a/source/client/src/clientSml.c +++ b/source/client/src/clientSml.c @@ -444,7 +444,7 @@ int32_t smlParseEndLine(SSmlHandle *info, SSmlLineInfo *elements, SSmlKv *kvTs) } clearColValArraySml(info->currTableDataCtx->pValues); - taosArrayClearP(info->escapedStringList, taosMemoryFree); + taosArrayClearP(info->escapedStringList, NULL); if (unlikely(ret != TSDB_CODE_SUCCESS)) { uError("SML:0x%" PRIx64 " %s smlBuildCol error:%d", info->id, __FUNCTION__, ret); return ret; @@ -1270,7 +1270,7 @@ void smlDestroyInfo(SSmlHandle *info) { taosArrayDestroy(info->valueJsonArray); taosArrayDestroyEx(info->preLineTagKV, freeSSmlKv); - taosArrayDestroyP(info->escapedStringList, taosMemoryFree); + taosArrayDestroyP(info->escapedStringList, NULL); if (!info->dataFormat) { for (int i = 0; i < info->lineNum; i++) { @@ -1536,7 +1536,7 @@ int32_t smlClearForRerun(SSmlHandle *info) { SML_CHECK_NULL(info->lines); } - taosArrayClearP(info->escapedStringList, taosMemoryFree); + taosArrayClearP(info->escapedStringList, NULL); if(info->protocol == TSDB_SML_JSON_PROTOCOL) { taosMemoryFreeClear(info->preLine.tags); } diff --git a/source/client/src/clientSmlLine.c b/source/client/src/clientSmlLine.c index b54f4e0beb..4ae02bd7f7 100644 --- a/source/client/src/clientSmlLine.c +++ b/source/client/src/clientSmlLine.c @@ -134,7 +134,7 @@ int32_t smlParseValue(SSmlKv *pVal, SSmlMsgBuf *msg) { void* data = NULL; uint32_t size = 0; if(taosHex2Ascii(pVal->value + NCHAR_ADD_LEN - 1, pVal->length - NCHAR_ADD_LEN, &data, &size) < 0){ - return TSDB_CODE_OUT_OF_MEMORY; + return terrno; } if (size + VARSTR_HEADER_SIZE > TSDB_MAX_VARBINARY_LEN) { diff --git a/source/client/src/clientStmt.c b/source/client/src/clientStmt.c index 9cad219614..6fb923ae38 100644 --- a/source/client/src/clientStmt.c +++ b/source/client/src/clientStmt.c @@ -300,7 +300,7 @@ int32_t stmtCacheBlock(STscStmt* pStmt) { STableDataCxt** pSrc = taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName)); if (!pSrc) { - return TSDB_CODE_OUT_OF_MEMORY; + return terrno; } STableDataCxt* pDst = NULL; @@ -355,7 +355,7 @@ int32_t stmtParseSql(STscStmt* pStmt) { STableDataCxt** pSrc = (STableDataCxt**)taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName)); if (NULL == pSrc || NULL == *pSrc) { - return TSDB_CODE_OUT_OF_MEMORY; + return terrno; } STableDataCxt* pTableCtx = *pSrc; @@ -845,13 +845,11 @@ TAOS_STMT* stmtInit(STscObj* taos, int64_t reqid, TAOS_STMT_OPTIONS* pOptions) { pStmt = taosMemoryCalloc(1, sizeof(STscStmt)); if (NULL == pStmt) { - terrno = TSDB_CODE_OUT_OF_MEMORY; return NULL; } pStmt->sql.pTableCache = taosHashInit(100, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK); if (NULL == pStmt->sql.pTableCache) { - terrno = TSDB_CODE_OUT_OF_MEMORY; taosMemoryFree(pStmt); return NULL; } @@ -876,13 +874,11 @@ TAOS_STMT* stmtInit(STscObj* taos, int64_t reqid, TAOS_STMT_OPTIONS* pOptions) { pStmt->sql.siInfo.mgmtEpSet = getEpSet_s(&pStmt->taos->pAppInfo->mgmtEp); pStmt->sql.siInfo.pTableHash = tSimpleHashInit(100, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY)); if (NULL == pStmt->sql.siInfo.pTableHash) { - terrno = TSDB_CODE_OUT_OF_MEMORY; (void)stmtClose(pStmt); return NULL; } pStmt->sql.siInfo.pTableCols = taosArrayInit(STMT_TABLE_COLS_NUM, POINTER_BYTES); if (NULL == pStmt->sql.siInfo.pTableCols) { - terrno = TSDB_CODE_OUT_OF_MEMORY; (void)stmtClose(pStmt); return NULL; } @@ -948,7 +944,7 @@ int stmtPrepare(TAOS_STMT* stmt, const char* sql, unsigned long length) { int32_t stmtInitStbInterlaceTableInfo(STscStmt* pStmt) { STableDataCxt** pSrc = taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName)); if (!pSrc) { - return TSDB_CODE_OUT_OF_MEMORY; + return terrno; } STableDataCxt* pDst = NULL; diff --git a/source/client/src/clientStmt2.c b/source/client/src/clientStmt2.c index f03879f199..2f68b99c81 100644 --- a/source/client/src/clientStmt2.c +++ b/source/client/src/clientStmt2.c @@ -275,7 +275,7 @@ static int32_t stmtParseSql(STscStmt2* pStmt) { STableDataCxt** pSrc = (STableDataCxt**)taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName)); if (NULL == pSrc || NULL == *pSrc) { - return TSDB_CODE_OUT_OF_MEMORY; + return terrno; } STableDataCxt* pTableCtx = *pSrc; @@ -295,7 +295,7 @@ static int32_t stmtParseSql(STscStmt2* pStmt) { if (NULL == pStmt->sql.pBindInfo) { pStmt->sql.pBindInfo = taosMemoryMalloc(pTableCtx->boundColsInfo.numOfBound * sizeof(*pStmt->sql.pBindInfo)); if (NULL == pStmt->sql.pBindInfo) { - return TSDB_CODE_OUT_OF_MEMORY; + return terrno; } } @@ -540,7 +540,7 @@ static int32_t stmtGetFromCache(STscStmt2* pStmt) { if (taosHashPut(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName), &pNewBlock, POINTER_BYTES)) { - STMT_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + STMT_ERR_RET(terrno); } pStmt->exec.pCurrBlock = pNewBlock; @@ -630,7 +630,7 @@ static int32_t stmtGetFromCache(STscStmt2* pStmt) { if (taosHashPut(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName), &pNewBlock, POINTER_BYTES)) { - STMT_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + STMT_ERR_RET(terrno); } pStmt->exec.pCurrBlock = pNewBlock; @@ -766,13 +766,11 @@ TAOS_STMT2* stmtInit2(STscObj* taos, TAOS_STMT2_OPTION* pOptions) { pStmt = taosMemoryCalloc(1, sizeof(STscStmt2)); if (NULL == pStmt) { - terrno = TSDB_CODE_OUT_OF_MEMORY; return NULL; } pStmt->sql.pTableCache = taosHashInit(100, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK); if (NULL == pStmt->sql.pTableCache) { - terrno = TSDB_CODE_OUT_OF_MEMORY; taosMemoryFree(pStmt); return NULL; } @@ -798,7 +796,6 @@ TAOS_STMT2* stmtInit2(STscObj* taos, TAOS_STMT2_OPTION* pOptions) { pStmt->sql.siInfo.mgmtEpSet = getEpSet_s(&pStmt->taos->pAppInfo->mgmtEp); pStmt->sql.siInfo.pTableHash = tSimpleHashInit(100, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY)); if (NULL == pStmt->sql.siInfo.pTableHash) { - terrno = TSDB_CODE_OUT_OF_MEMORY; (void)stmtClose(pStmt); return NULL; } @@ -894,7 +891,7 @@ int stmtPrepare2(TAOS_STMT2* stmt, const char* sql, unsigned long length) { static int32_t stmtInitStbInterlaceTableInfo(STscStmt2* pStmt) { STableDataCxt** pSrc = taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName)); if (!pSrc) { - return TSDB_CODE_OUT_OF_MEMORY; + return terrno; } STableDataCxt* pDst = NULL; @@ -1199,7 +1196,7 @@ static int32_t stmtCacheBlock(STscStmt2* pStmt) { STableDataCxt** pSrc = taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName)); if (!pSrc) { - return TSDB_CODE_OUT_OF_MEMORY; + return terrno; } STableDataCxt* pDst = NULL; @@ -1266,7 +1263,7 @@ static int32_t stmtBackupQueryFields(STscStmt2* pStmt) { pRes->fields = taosMemoryMalloc(size); pRes->userFields = taosMemoryMalloc(size); if (NULL == pRes->fields || NULL == pRes->userFields) { - STMT_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + STMT_ERR_RET(terrno); } (void)memcpy(pRes->fields, pStmt->exec.pRequest->body.resInfo.fields, size); (void)memcpy(pRes->userFields, pStmt->exec.pRequest->body.resInfo.userFields, size); @@ -1284,7 +1281,7 @@ static int32_t stmtRestoreQueryFields(STscStmt2* pStmt) { if (NULL == pStmt->exec.pRequest->body.resInfo.fields) { pStmt->exec.pRequest->body.resInfo.fields = taosMemoryMalloc(size); if (NULL == pStmt->exec.pRequest->body.resInfo.fields) { - STMT_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + STMT_ERR_RET(terrno); } (void)memcpy(pStmt->exec.pRequest->body.resInfo.fields, pRes->fields, size); } @@ -1292,7 +1289,7 @@ static int32_t stmtRestoreQueryFields(STscStmt2* pStmt) { if (NULL == pStmt->exec.pRequest->body.resInfo.userFields) { pStmt->exec.pRequest->body.resInfo.userFields = taosMemoryMalloc(size); if (NULL == pStmt->exec.pRequest->body.resInfo.userFields) { - STMT_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + STMT_ERR_RET(terrno); } (void)memcpy(pStmt->exec.pRequest->body.resInfo.userFields, pRes->userFields, size); } diff --git a/source/client/src/clientTmq.c b/source/client/src/clientTmq.c index 902e581bfd..b254f6eb8b 100644 --- a/source/client/src/clientTmq.c +++ b/source/client/src/clientTmq.c @@ -45,7 +45,7 @@ tDecoderInit(&decoder, POINTER_SHIFT(pMsg->pData, sizeof(SMqRspHead)), pMsg->len - sizeof(SMqRspHead)); \ if (FUNC(&decoder, DATA) < 0) { \ tDecoderClear(&decoder); \ - code = TSDB_CODE_OUT_OF_MEMORY; \ + code = terrno; \ goto END;\ }\ tDecoderClear(&decoder);\ @@ -534,7 +534,7 @@ int32_t tmq_list_append(tmq_list_t* list, const char* src) { void tmq_list_destroy(tmq_list_t* list) { if (list == NULL) return; SArray* container = &list->container; - taosArrayDestroyP(container, taosMemoryFree); + taosArrayDestroyP(container, NULL); } int32_t tmq_list_get_size(const tmq_list_t* list) { @@ -659,7 +659,7 @@ static int32_t doSendCommitMsg(tmq_t* tmq, int32_t vgId, SEpSet* epSet, STqOffse pMsgSendInfo->requestId = generateRequestId(); pMsgSendInfo->requestObjRefId = 0; pMsgSendInfo->param = pParam; - pMsgSendInfo->paramFreeFp = taosMemoryFree; + pMsgSendInfo->paramFreeFp = taosAutoMemoryFree; pMsgSendInfo->fp = tmqCommitCb; pMsgSendInfo->msgType = TDMT_VND_TMQ_COMMIT_OFFSET; @@ -1385,7 +1385,7 @@ static int32_t askEp(tmq_t* pTmq, void* param, bool sync, bool updateEpSet) { sendInfo->requestId = generateRequestId(); sendInfo->requestObjRefId = 0; sendInfo->param = pParam; - sendInfo->paramFreeFp = taosMemoryFree; + sendInfo->paramFreeFp = taosAutoMemoryFree; sendInfo->fp = askEpCb; sendInfo->msgType = TDMT_MND_TMQ_ASK_EP; @@ -1552,7 +1552,7 @@ static void tmqMgmtInit(void) { tmqMgmt.timer = taosTmrInit(1000, 100, 360000, "TMQ"); if (tmqMgmt.timer == NULL) { - tmqInitRes = TSDB_CODE_OUT_OF_MEMORY; + tmqInitRes = terrno; } tmqMgmt.rsetId = taosOpenRef(10000, tmqFreeImpl); @@ -1886,7 +1886,7 @@ int32_t tmq_subscribe(tmq_t* tmq, const tmq_list_t* topic_list) { } END: - taosArrayDestroyP(req.topicNames, taosMemoryFree); + taosArrayDestroyP(req.topicNames, NULL); return code; } @@ -2177,7 +2177,7 @@ static int32_t doTmqPollImpl(tmq_t* pTmq, SMqClientTopic* pTopic, SMqClientVg* p sendInfo->requestId = req.reqId; sendInfo->requestObjRefId = 0; sendInfo->param = pParam; - sendInfo->paramFreeFp = taosMemoryFree; + sendInfo->paramFreeFp = taosAutoMemoryFree; sendInfo->fp = tmqPollCb; sendInfo->msgType = TDMT_VND_TMQ_CONSUME; @@ -2520,7 +2520,7 @@ int32_t tmq_unsubscribe(tmq_t* tmq) { tmq_list_t* lst = tmq_list_new(); if (lst == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; + code = terrno; goto END; } code = tmq_subscribe(tmq, lst); @@ -2701,10 +2701,12 @@ int32_t tmq_commit_sync(tmq_t* tmq, const TAOS_RES* pRes) { tqErrorC("failed to allocate memory for sync commit"); return terrno; } - if (tsem2_init(&pInfo->sem, 0, 0) != 0) { + + code = tsem2_init(&pInfo->sem, 0, 0); + if (code != 0) { tqErrorC("failed to init sem for sync commit"); taosMemoryFree(pInfo); - return TSDB_CODE_OUT_OF_MEMORY; + return code; } pInfo->code = 0; @@ -2778,9 +2780,10 @@ int32_t tmq_commit_offset_sync(tmq_t* tmq, const char* pTopicName, int32_t vgId, return terrno; } - if (tsem2_init(&pInfo->sem, 0, 0) != 0) { + code = tsem2_init(&pInfo->sem, 0, 0); + if (code != 0) { taosMemoryFree(pInfo); - return TSDB_CODE_OUT_OF_MEMORY; + return code; } pInfo->code = 0; @@ -2847,6 +2850,7 @@ end: } } + int32_t tmqGetNextResInfo(TAOS_RES* res, bool convertUcs4, SReqResultInfo** pResInfo) { SMqRspObj* pRspObj = (SMqRspObj*)res; SMqDataRsp* data = &pRspObj->dataRsp; @@ -2966,9 +2970,10 @@ static int32_t tmCommittedCb(void* param, SDataBuf* pMsg, int32_t code) { if (pMsg) { SDecoder decoder = {0}; tDecoderInit(&decoder, (uint8_t*)pMsg->pData, pMsg->len); - if (tDecodeMqVgOffset(&decoder, &pParam->vgOffset) < 0) { + int32_t err = tDecodeMqVgOffset(&decoder, &pParam->vgOffset); + if (err < 0) { tOffsetDestroy(&pParam->vgOffset.offset); - code = TSDB_CODE_OUT_OF_MEMORY; + code = err; goto end; } tDecoderClear(&decoder); @@ -3261,8 +3266,9 @@ int32_t tmq_get_topic_assignment(tmq_t* tmq, const char* pTopicName, tmq_topic_a code = terrno; goto end; } - if (tsem2_init(&pCommon->rsp, 0, 0) != 0) { - code = TSDB_CODE_OUT_OF_MEMORY; + + code = tsem2_init(&pCommon->rsp, 0, 0); + if (code != 0) { goto end; } (void)taosThreadMutexInit(&pCommon->mutex, 0); @@ -3296,7 +3302,7 @@ int32_t tmq_get_topic_assignment(tmq_t* tmq, const char* pTopicName, tmq_topic_a int32_t msgSize = tSerializeSMqPollReq(NULL, 0, &req); if (msgSize < 0) { taosMemoryFree(pParam); - code = TSDB_CODE_OUT_OF_MEMORY; + code = msgSize; goto end; } @@ -3307,10 +3313,11 @@ int32_t tmq_get_topic_assignment(tmq_t* tmq, const char* pTopicName, tmq_topic_a goto end; } - if (tSerializeSMqPollReq(msg, msgSize, &req) < 0) { + msgSize = tSerializeSMqPollReq(msg, msgSize, &req); + if (msgSize < 0) { taosMemoryFree(msg); taosMemoryFree(pParam); - code = TSDB_CODE_OUT_OF_MEMORY; + code = msgSize; goto end; } @@ -3326,7 +3333,7 @@ int32_t tmq_get_topic_assignment(tmq_t* tmq, const char* pTopicName, tmq_topic_a sendInfo->requestId = req.reqId; sendInfo->requestObjRefId = 0; sendInfo->param = pParam; - sendInfo->paramFreeFp = taosMemoryFree; + sendInfo->paramFreeFp = taosAutoMemoryFree; sendInfo->fp = tmqGetWalInfoCb; sendInfo->msgType = TDMT_VND_TMQ_VG_WALINFO; diff --git a/source/common/src/msg/streamMsg.c b/source/common/src/msg/streamMsg.c index c92ab52ac1..76baf6be2c 100644 --- a/source/common/src/msg/streamMsg.c +++ b/source/common/src/msg/streamMsg.c @@ -403,7 +403,7 @@ _exit: } void tCleanupStreamDispatchReq(SStreamDispatchReq* pReq) { - taosArrayDestroyP(pReq->data, taosMemoryFree); + taosArrayDestroyP(pReq->data, NULL); taosArrayDestroy(pReq->dataLen); } diff --git a/source/common/src/msg/tmsg.c b/source/common/src/msg/tmsg.c index eed1d594a8..918c2a7330 100644 --- a/source/common/src/msg/tmsg.c +++ b/source/common/src/msg/tmsg.c @@ -9393,7 +9393,7 @@ int32_t tSerializeSSchedulerHbReq(void *buf, int32_t bufLen, SSchedulerHbReq *pR tEncoderInit(&encoder, buf, bufLen); TAOS_CHECK_EXIT(tStartEncode(&encoder)); - TAOS_CHECK_EXIT(tEncodeU64(&encoder, pReq->sId)); + TAOS_CHECK_EXIT(tEncodeU64(&encoder, pReq->clientId)); TAOS_CHECK_EXIT(tEncodeI32(&encoder, pReq->epId.nodeId)); TAOS_CHECK_EXIT(tEncodeU16(&encoder, pReq->epId.ep.port)); TAOS_CHECK_EXIT(tEncodeCStr(&encoder, pReq->epId.ep.fqdn)); @@ -9440,7 +9440,7 @@ int32_t tDeserializeSSchedulerHbReq(void *buf, int32_t bufLen, SSchedulerHbReq * tDecoderInit(&decoder, (char *)buf + headLen, bufLen - headLen); TAOS_CHECK_EXIT(tStartDecode(&decoder)); - TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pReq->sId)); + TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pReq->clientId)); TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pReq->epId.nodeId)); TAOS_CHECK_EXIT(tDecodeU16(&decoder, &pReq->epId.ep.port)); TAOS_CHECK_EXIT(tDecodeCStrTo(&decoder, pReq->epId.ep.fqdn)); @@ -11350,11 +11350,11 @@ int32_t tDecodeMqDataRsp(SDecoder *pDecoder, SMqDataRsp *pRsp) { static void tDeleteMqDataRspCommon(SMqDataRsp *pRsp) { taosArrayDestroy(pRsp->blockDataLen); pRsp->blockDataLen = NULL; - taosArrayDestroyP(pRsp->blockData, (FDelete)taosMemoryFree); + taosArrayDestroyP(pRsp->blockData, NULL); pRsp->blockData = NULL; taosArrayDestroyP(pRsp->blockSchema, (FDelete)tDeleteSchemaWrapper); pRsp->blockSchema = NULL; - taosArrayDestroyP(pRsp->blockTbName, (FDelete)taosMemoryFree); + taosArrayDestroyP(pRsp->blockTbName, NULL); pRsp->blockTbName = NULL; tOffsetDestroy(&pRsp->reqOffset); tOffsetDestroy(&pRsp->rspOffset); @@ -11416,7 +11416,7 @@ void tDeleteSTaosxRsp(SMqDataRsp *pRsp) { taosArrayDestroy(pRsp->createTableLen); pRsp->createTableLen = NULL; - taosArrayDestroyP(pRsp->createTableReq, (FDelete)taosMemoryFree); + taosArrayDestroyP(pRsp->createTableReq, NULL); pRsp->createTableReq = NULL; } @@ -12975,7 +12975,7 @@ _exit: void tDeleteMqBatchMetaRsp(SMqBatchMetaRsp *pRsp) { taosMemoryFreeClear(pRsp->pMetaBuff); - taosArrayDestroyP(pRsp->batchMetaReq, taosMemoryFree); + taosArrayDestroyP(pRsp->batchMetaReq, NULL); taosArrayDestroy(pRsp->batchMetaLen); pRsp->batchMetaReq = NULL; pRsp->batchMetaLen = NULL; diff --git a/source/common/src/tglobal.c b/source/common/src/tglobal.c index f620db240a..d339af7718 100644 --- a/source/common/src/tglobal.c +++ b/source/common/src/tglobal.c @@ -63,13 +63,28 @@ char tsEncryptKey[17] = {0}; int32_t tsMaxShellConns = 50000; int32_t tsShellActivityTimer = 3; // second +// memory pool +int8_t tsMemPoolFullFunc = 0; +int8_t tsQueryUseMemoryPool = 1; +int32_t tsQueryBufferPoolSize = 0; // MB +int32_t tsSingleQueryMaxMemorySize = 0; // MB +int32_t tsMinReservedMemorySize = 0; // MB +int64_t tsCurrentAvailMemorySize = 0; +int8_t tsNeedTrim = 0; + // queue & threads +int32_t tsQueryMinConcurrentTaskNum = 1; +int32_t tsQueryMaxConcurrentTaskNum = 0; +int32_t tsQueryConcurrentTaskNum = 0; +int32_t tsQueryNoFetchTimeoutSec = 3600 * 5; + int32_t tsNumOfRpcThreads = 1; int32_t tsNumOfRpcSessions = 30000; int32_t tsShareConnLimit = 10; int32_t tsReadTimeout = 900; int32_t tsTimeToGetAvailableConn = 500000; +int32_t tsNumOfQueryThreads = 0; int32_t tsNumOfCommitThreads = 2; int32_t tsNumOfTaskQueueThreads = 16; int32_t tsNumOfMnodeQueryThreads = 16; @@ -802,6 +817,12 @@ static int32_t taosAddServerCfg(SConfig *pCfg) { TAOS_CHECK_RETURN(cfgAddInt32(pCfg, "queryRspPolicy", tsQueryRspPolicy, 0, 1, CFG_SCOPE_SERVER, CFG_DYN_SERVER,CFG_CATEGORY_GLOBAL)); TAOS_CHECK_RETURN(cfgAddInt32(pCfg, "numOfCommitThreads", tsNumOfCommitThreads, 1, 1024, CFG_SCOPE_SERVER, CFG_DYN_SERVER_LAZY,CFG_CATEGORY_LOCAL)); TAOS_CHECK_RETURN(cfgAddInt32(pCfg, "retentionSpeedLimitMB", tsRetentionSpeedLimitMB, 0, 1024, CFG_SCOPE_SERVER, CFG_DYN_SERVER,CFG_CATEGORY_GLOBAL)); + TAOS_CHECK_RETURN(cfgAddBool(pCfg, "queryUseMemoryPool", tsQueryUseMemoryPool, CFG_SCOPE_SERVER, CFG_DYN_NONE,CFG_CATEGORY_LOCAL) != 0); + TAOS_CHECK_RETURN(cfgAddBool(pCfg, "memPoolFullFunc", tsMemPoolFullFunc, CFG_SCOPE_SERVER, CFG_DYN_NONE,CFG_CATEGORY_LOCAL) != 0); + TAOS_CHECK_RETURN(cfgAddInt32(pCfg, "singleQueryMaxMemorySize", tsSingleQueryMaxMemorySize, 0, 1000000000, CFG_SCOPE_SERVER, CFG_DYN_NONE,CFG_CATEGORY_LOCAL) != 0); + //TAOS_CHECK_RETURN(cfgAddInt32(pCfg, "queryBufferPoolSize", tsQueryBufferPoolSize, 0, 1000000000, CFG_SCOPE_SERVER, CFG_DYN_ENT_SERVER) != 0); + TAOS_CHECK_RETURN(cfgAddInt32Ex(pCfg, "minReservedMemorySize", 0, 1024, 1000000000, CFG_SCOPE_SERVER, CFG_DYN_NONE,CFG_CATEGORY_LOCAL) != 0); + TAOS_CHECK_RETURN(cfgAddInt32(pCfg, "queryNoFetchTimeoutSec", tsQueryNoFetchTimeoutSec, 60, 1000000000, CFG_SCOPE_SERVER, CFG_DYN_ENT_SERVER,CFG_CATEGORY_LOCAL) != 0); TAOS_CHECK_RETURN(cfgAddInt32(pCfg, "numOfMnodeReadThreads", tsNumOfMnodeReadThreads, 1, 1024, CFG_SCOPE_SERVER, CFG_DYN_SERVER_LAZY,CFG_CATEGORY_LOCAL)); TAOS_CHECK_RETURN(cfgAddInt32(pCfg, "numOfVnodeQueryThreads", tsNumOfVnodeQueryThreads, 1, 1024, CFG_SCOPE_SERVER, CFG_DYN_SERVER_LAZY,CFG_CATEGORY_LOCAL)); @@ -1764,6 +1785,21 @@ static int32_t taosSetServerCfg(SConfig *pCfg) { TAOS_CHECK_GET_CFG_ITEM(pCfg, pItem, "experimental"); tsExperimental = pItem->bval; + TAOS_CHECK_GET_CFG_ITEM(pCfg, pItem, "queryUseMemoryPool"); + tsQueryUseMemoryPool = pItem->bval; + + TAOS_CHECK_GET_CFG_ITEM(pCfg, pItem, "memPoolFullFunc"); + tsMemPoolFullFunc = pItem->bval; + + TAOS_CHECK_GET_CFG_ITEM(pCfg, pItem, "singleQueryMaxMemorySize"); + tsSingleQueryMaxMemorySize = pItem->i32; + + // TAOS_CHECK_GET_CFG_ITEM(pCfg, pItem, "queryBufferPoolSize"); + // tsQueryBufferPoolSize = pItem->i32; + + TAOS_CHECK_GET_CFG_ITEM(pCfg, pItem, "minReservedMemorySize"); + tsMinReservedMemorySize = pItem->i32; + // GRANT_CFG_GET; TAOS_RETURN(TSDB_CODE_SUCCESS); } @@ -2404,7 +2440,8 @@ static int32_t taosCfgDynamicOptionsForServer(SConfig *pCfg, const char *name) { {"bypassFlag", &tsBypassFlag}, {"arbHeartBeatIntervalSec", &tsArbHeartBeatIntervalSec}, {"arbCheckSyncIntervalSec", &tsArbCheckSyncIntervalSec}, - {"arbSetAssignedTimeoutSec", &tsArbSetAssignedTimeoutSec}}; + {"arbSetAssignedTimeoutSec", &tsArbSetAssignedTimeoutSec}, + {"queryNoFetchTimeoutSec", &tsQueryNoFetchTimeoutSec}}; if ((code = taosCfgSetOption(debugOptions, tListLen(debugOptions), pItem, true)) != TSDB_CODE_SUCCESS) { code = taosCfgSetOption(options, tListLen(options), pItem, false); diff --git a/source/dnode/mgmt/exe/dmMain.c b/source/dnode/mgmt/exe/dmMain.c index c5aab38835..ddaf1d3c13 100644 --- a/source/dnode/mgmt/exe/dmMain.c +++ b/source/dnode/mgmt/exe/dmMain.c @@ -26,6 +26,7 @@ #endif #include "dmUtil.h" #include "tcs.h" +#include "qworker.h" #if defined(CUS_NAME) || defined(CUS_PROMPT) || defined(CUS_EMAIL) #include "cus_name.h" @@ -477,6 +478,13 @@ int mainWindows(int argc, char **argv) { taosCleanupArgs(); return code; } + + if ((code = taosMemoryPoolInit(qWorkerRetireJobs, qWorkerRetireJob)) != 0) { + dError("failed to init memPool, error:0x%x", code); + taosCloseLog(); + taosCleanupArgs(); + return code; + } if ((tsCharsetCxt = taosConvInit(tsCharset)) == NULL) { dError("failed to init conv"); diff --git a/source/dnode/mgmt/mgmt_dnode/src/dmWorker.c b/source/dnode/mgmt/mgmt_dnode/src/dmWorker.c index 1d89233277..e55a78075a 100644 --- a/source/dnode/mgmt/mgmt_dnode/src/dmWorker.c +++ b/source/dnode/mgmt/mgmt_dnode/src/dmWorker.c @@ -221,9 +221,12 @@ static void *dmMonitorThreadFp(void *param) { trimCount = (trimCount + 1) % TRIM_FREQ; if (trimCount == 0) { - taosMemoryTrim(0); + taosMemoryTrim(0, NULL); } } + if (atomic_val_compare_exchange_8(&tsNeedTrim, 1, 0)) { + taosMemoryTrim(0, NULL); + } } return NULL; diff --git a/source/dnode/mgmt/mgmt_mnode/src/mmWorker.c b/source/dnode/mgmt/mgmt_mnode/src/mmWorker.c index e8e7a75889..cfdc09f29e 100644 --- a/source/dnode/mgmt/mgmt_mnode/src/mmWorker.c +++ b/source/dnode/mgmt/mgmt_mnode/src/mmWorker.c @@ -220,6 +220,8 @@ int32_t mmStartWorker(SMnodeMgmt *pMgmt) { return code; } + tsNumOfQueryThreads += tsNumOfMnodeQueryThreads; + SSingleWorkerCfg fCfg = { .min = tsNumOfMnodeFetchThreads, .max = tsNumOfMnodeFetchThreads, diff --git a/source/dnode/mgmt/mgmt_qnode/src/qmWorker.c b/source/dnode/mgmt/mgmt_qnode/src/qmWorker.c index 65c2bb9bf3..ab5b70079a 100644 --- a/source/dnode/mgmt/mgmt_qnode/src/qmWorker.c +++ b/source/dnode/mgmt/mgmt_qnode/src/qmWorker.c @@ -104,8 +104,8 @@ int32_t qmStartWorker(SQnodeMgmt *pMgmt) { int32_t code = 0; SSingleWorkerCfg queryCfg = { - .min = tsNumOfVnodeQueryThreads, - .max = tsNumOfVnodeQueryThreads, + .min = tsNumOfQnodeQueryThreads, + .max = tsNumOfQnodeQueryThreads, .name = "qnode-query", .fp = (FItem)qmProcessQueue, .param = pMgmt, @@ -117,6 +117,8 @@ int32_t qmStartWorker(SQnodeMgmt *pMgmt) { return code; } + tsNumOfQueryThreads += tsNumOfQnodeQueryThreads; + SSingleWorkerCfg fetchCfg = { .min = tsNumOfQnodeFetchThreads, .max = tsNumOfQnodeFetchThreads, diff --git a/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c b/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c index 9c436a3dfa..c22adec9b4 100644 --- a/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c +++ b/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c @@ -456,6 +456,8 @@ int32_t vmStartWorker(SVnodeMgmt *pMgmt) { pQPool->max = tsNumOfVnodeQueryThreads; if ((code = tQueryAutoQWorkerInit(pQPool)) != 0) return code; + tsNumOfQueryThreads += tsNumOfVnodeQueryThreads; + SAutoQWorkerPool *pStreamPool = &pMgmt->streamPool; pStreamPool->name = "vnode-stream"; pStreamPool->ratio = tsRatioOfVnodeStreamThreads; diff --git a/source/dnode/mgmt/node_mgmt/src/dmEnv.c b/source/dnode/mgmt/node_mgmt/src/dmEnv.c index 6d4ebe424a..1708a0c8d9 100644 --- a/source/dnode/mgmt/node_mgmt/src/dmEnv.c +++ b/source/dnode/mgmt/node_mgmt/src/dmEnv.c @@ -220,6 +220,7 @@ void dmCleanup() { dInfo("dnode env is cleaned up"); + taosMemPoolClose(gMemPoolHandle); taosCleanupCfg(); taosCloseLog(); } diff --git a/source/dnode/mgmt/node_mgmt/src/dmTransport.c b/source/dnode/mgmt/node_mgmt/src/dmTransport.c index 5f396a520a..acd95d4b43 100644 --- a/source/dnode/mgmt/node_mgmt/src/dmTransport.c +++ b/source/dnode/mgmt/node_mgmt/src/dmTransport.c @@ -368,7 +368,9 @@ static inline int32_t dmSendSyncReq(const SEpSet *pEpSet, SRpcMsg *pMsg) { static inline void dmRegisterBrokenLinkArg(SRpcMsg *pMsg) { (void)rpcRegisterBrokenLinkArg(pMsg); } -static inline void dmReleaseHandle(SRpcHandleInfo *pHandle, int8_t type) { (void)rpcReleaseHandle(pHandle, type); } +static inline void dmReleaseHandle(SRpcHandleInfo *pHandle, int8_t type, int32_t status) { + (void)rpcReleaseHandle(pHandle, type, status); +} static bool rpcRfp(int32_t code, tmsg_t msgType) { if (code == TSDB_CODE_RPC_NETWORK_UNAVAIL || code == TSDB_CODE_RPC_BROKEN_LINK || code == TSDB_CODE_MNODE_NOT_FOUND || diff --git a/source/dnode/mnode/impl/src/mndConsumer.c b/source/dnode/mnode/impl/src/mndConsumer.c index 0538a5fe83..fbce8f544a 100644 --- a/source/dnode/mnode/impl/src/mndConsumer.c +++ b/source/dnode/mnode/impl/src/mndConsumer.c @@ -614,7 +614,7 @@ int32_t mndProcessSubscribeReq(SRpcMsg *pMsg) { END: mndTransDrop(pTrans); tDeleteSMqConsumerObj(pConsumerNew); - taosArrayDestroyP(subscribe.topicNames, (FDelete)taosMemoryFree); + taosArrayDestroyP(subscribe.topicNames, NULL); return (code == TSDB_CODE_TMQ_NO_NEED_REBALANCE || code == TSDB_CODE_MND_CONSUMER_NOT_EXIST) ? 0 : code; } diff --git a/source/dnode/mnode/impl/src/mndDef.c b/source/dnode/mnode/impl/src/mndDef.c index 33ea98d906..7ea0ba67bd 100644 --- a/source/dnode/mnode/impl/src/mndDef.c +++ b/source/dnode/mnode/impl/src/mndDef.c @@ -351,10 +351,10 @@ END: void tClearSMqConsumerObj(SMqConsumerObj *pConsumer) { if (pConsumer == NULL) return; - taosArrayDestroyP(pConsumer->currentTopics, (FDelete)taosMemoryFree); - taosArrayDestroyP(pConsumer->rebNewTopics, (FDelete)taosMemoryFree); - taosArrayDestroyP(pConsumer->rebRemovedTopics, (FDelete)taosMemoryFree); - taosArrayDestroyP(pConsumer->assignedTopics, (FDelete)taosMemoryFree); + taosArrayDestroyP(pConsumer->currentTopics, NULL); + taosArrayDestroyP(pConsumer->rebNewTopics, NULL); + taosArrayDestroyP(pConsumer->rebRemovedTopics, NULL); + taosArrayDestroyP(pConsumer->assignedTopics, NULL); } void tDeleteSMqConsumerObj(SMqConsumerObj *pConsumer) { diff --git a/source/dnode/mnode/impl/src/mndStb.c b/source/dnode/mnode/impl/src/mndStb.c index eb6c326d1e..ae1afdb0db 100644 --- a/source/dnode/mnode/impl/src/mndStb.c +++ b/source/dnode/mnode/impl/src/mndStb.c @@ -627,9 +627,12 @@ static void *mndBuildVDropStbReq(SMnode *pMnode, SVgObj *pVgroup, SStbObj *pStb, void *pBuf = POINTER_SHIFT(pHead, sizeof(SMsgHead)); tEncoderInit(&encoder, pBuf, contLen - sizeof(SMsgHead)); - terrno = tEncodeSVDropStbReq(&encoder, &req); + int32_t code = tEncodeSVDropStbReq(&encoder, &req); tEncoderClear(&encoder); - if (terrno != 0) return NULL; + if (code != 0) { + terrno = code; + return NULL; + } *pContLen = contLen; return pHead; diff --git a/source/dnode/mnode/impl/src/mndUser.c b/source/dnode/mnode/impl/src/mndUser.c index 6a9d67fc83..b281ddba86 100644 --- a/source/dnode/mnode/impl/src/mndUser.c +++ b/source/dnode/mnode/impl/src/mndUser.c @@ -213,7 +213,7 @@ int32_t ipWhiteMgtUpdate(SMnode *pMnode, char *user, SIpWhiteList *pNew) { _OVER: (void)taosThreadRwlockUnlock(&ipWhiteMgt.rw); - taosArrayDestroyP(fqdns, (FDelete)taosMemoryFree); + taosArrayDestroyP(fqdns, NULL); if (code < 0) { mError("failed to update ip white list for user: %s at line %d since %s", user, lino, tstrerror(code)); } @@ -640,8 +640,8 @@ int32_t mndFetchAllIpWhite(SMnode *pMnode, SHashObj **ppIpWhiteTab) { } _OVER: - taosArrayDestroyP(fqdns, taosMemoryFree); - taosArrayDestroyP(pUserNames, taosMemoryFree); + taosArrayDestroyP(fqdns, NULL); + taosArrayDestroyP(pUserNames, NULL); if (code < 0) { mError("failed to fetch all ip white list at line %d since %s", lino, tstrerror(code)); @@ -1899,13 +1899,13 @@ static int32_t mndProcessCreateUserReq(SRpcMsg *pReq) { if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS; char detail[1000] = {0}; - (void)sprintf(detail, "enable:%d, superUser:%d, sysInfo:%d, password:xxx", createReq.enable, createReq.superUser, - createReq.sysInfo); + TAOS_UNUSED(snprintf(detail, sizeof(detail), "enable:%d, superUser:%d, sysInfo:%d, password:xxx", createReq.enable, + createReq.superUser, createReq.sysInfo)); char operation[15] = {0}; if (createReq.isImport == 1) { - (void)strcpy(operation, "importUser"); + tstrncpy(operation, "importUser", sizeof(operation)); } else { - (void)strcpy(operation, "createUser"); + tstrncpy(operation, "createUser", sizeof(operation)); } auditRecord(pReq, pMnode->clusterId, operation, "", createReq.user, detail, strlen(detail)); @@ -2502,9 +2502,10 @@ static int32_t mndProcessAlterUserReq(SRpcMsg *pReq) { if (alterReq.alterType == TSDB_ALTER_USER_PASSWD) { char detail[1000] = {0}; - (void)sprintf(detail, "alterType:%s, enable:%d, superUser:%d, sysInfo:%d, createdb:%d, tabName:%s, password:xxx", - mndUserAuditTypeStr(alterReq.alterType), alterReq.enable, alterReq.superUser, alterReq.sysInfo, - alterReq.createdb ? 1 : 0, alterReq.tabName); + (void)snprintf(detail, sizeof(detail), + "alterType:%s, enable:%d, superUser:%d, sysInfo:%d, createdb:%d, tabName:%s, password:xxx", + mndUserAuditTypeStr(alterReq.alterType), alterReq.enable, alterReq.superUser, alterReq.sysInfo, + alterReq.createdb ? 1 : 0, alterReq.tabName); auditRecord(pReq, pMnode->clusterId, "alterUser", "", alterReq.user, detail, strlen(detail)); } else if (alterReq.alterType == TSDB_ALTER_USER_SUPERUSER || alterReq.alterType == TSDB_ALTER_USER_ENABLE || alterReq.alterType == TSDB_ALTER_USER_SYSINFO || alterReq.alterType == TSDB_ALTER_USER_CREATEDB) { @@ -2877,8 +2878,8 @@ static int32_t mndLoopHash(SHashObj *hash, char *priType, SSDataBlock *pBlock, i SNode *pAst = NULL; int32_t sqlLen = 0; size_t bufSz = strlen(value) + 1; - if (bufSz < 5) bufSz = 5; - TAOS_MEMORY_REALLOC(*sql, bufSz + 1); + if (bufSz < 6) bufSz = 6; + TAOS_MEMORY_REALLOC(*sql, bufSz); if (*sql == NULL) { code = terrno; goto _exit; @@ -2892,12 +2893,12 @@ static int32_t mndLoopHash(SHashObj *hash, char *priType, SSDataBlock *pBlock, i if (nodesStringToNode(value, &pAst) == 0) { if (nodesNodeToSQL(pAst, *sql, bufSz, &sqlLen) != 0) { sqlLen = 5; - (void)sprintf(*sql, "error"); + (void)snprintf(*sql, bufSz, "error"); } nodesDestroyNode(pAst); } else { sqlLen = 5; - (void)sprintf(*sql, "error"); + (void)snprintf(*sql, bufSz, "error"); } STR_WITH_MAXSIZE_TO_VARSTR((*condition), (*sql), pShow->pMeta->pSchemas[cols].bytes); diff --git a/source/dnode/vnode/src/sma/smaRollup.c b/source/dnode/vnode/src/sma/smaRollup.c index 5a515b1440..7d83dbcf84 100644 --- a/source/dnode/vnode/src/sma/smaRollup.c +++ b/source/dnode/vnode/src/sma/smaRollup.c @@ -308,7 +308,7 @@ static int32_t tdSetRSmaInfoItemParams(SSma *pSma, SRSmaParam *param, SRSmaStat if (!pStreamTask->exec.qmsg) { TAOS_RETURN(terrno); } - (void)sprintf(pStreamTask->exec.qmsg, "%s", RSMA_EXEC_TASK_FLAG); + TAOS_UNUSED(snprintf(pStreamTask->exec.qmsg, strlen(RSMA_EXEC_TASK_FLAG) + 1, "%s", RSMA_EXEC_TASK_FLAG)); pStreamTask->chkInfo.checkpointId = streamMetaGetLatestCheckpointId(pStreamTask->pMeta); tdRSmaTaskInit(pStreamTask->pMeta, pItem, &pStreamTask->id); diff --git a/source/dnode/vnode/src/tsdb/tsdbFS2.c b/source/dnode/vnode/src/tsdb/tsdbFS2.c index d3495422b0..2ff5a8ca6d 100644 --- a/source/dnode/vnode/src/tsdb/tsdbFS2.c +++ b/source/dnode/vnode/src/tsdb/tsdbFS2.c @@ -946,7 +946,7 @@ int32_t tsdbFSEditCommit(STFileSystem *fs) { arg->tsdb = fs->tsdb; arg->fid = fset->fid; - code = vnodeAsync(&fset->channel, EVA_PRIORITY_HIGH, tsdbMerge, taosMemoryFree, arg, NULL); + code = vnodeAsync(&fset->channel, EVA_PRIORITY_HIGH, tsdbMerge, taosAutoMemoryFree, arg, NULL); TSDB_CHECK_CODE(code, lino, _exit); fset->mergeScheduled = true; } diff --git a/source/dnode/vnode/src/tsdb/tsdbReadUtil.c b/source/dnode/vnode/src/tsdb/tsdbReadUtil.c index 5f77d03efc..df2279d3fe 100644 --- a/source/dnode/vnode/src/tsdb/tsdbReadUtil.c +++ b/source/dnode/vnode/src/tsdb/tsdbReadUtil.c @@ -150,7 +150,7 @@ _end: void clearBlockScanInfoBuf(SBlockInfoBuf* pBuf) { if (pBuf == NULL) return; if (pBuf->pData != NULL) { - taosArrayDestroyP(pBuf->pData, (FDelete)taosMemoryFree); + taosArrayDestroyP(pBuf->pData, NULL); pBuf->pData = NULL; } } diff --git a/source/dnode/vnode/src/vnd/vnodeCommit.c b/source/dnode/vnode/src/vnd/vnodeCommit.c index 3ebcf50858..42860f851c 100644 --- a/source/dnode/vnode/src/vnd/vnodeCommit.c +++ b/source/dnode/vnode/src/vnd/vnodeCommit.c @@ -106,6 +106,8 @@ static int32_t vnodeGetBufPoolToUse(SVnode *pVnode) { if (code && code != TSDB_CODE_TIMEOUT_ERROR) { TSDB_CHECK_CODE(code, lino, _exit); } + + code = 0; } } } diff --git a/source/dnode/vnode/src/vnd/vnodeSvr.c b/source/dnode/vnode/src/vnd/vnodeSvr.c index b1c206bdae..aff6990012 100644 --- a/source/dnode/vnode/src/vnd/vnodeSvr.c +++ b/source/dnode/vnode/src/vnd/vnodeSvr.c @@ -1321,7 +1321,7 @@ _exit: taosArrayDestroy(tbUids); tDecoderClear(&decoder); tEncoderClear(&encoder); - taosArrayDestroyP(tbNames, taosMemoryFree); + taosArrayDestroyP(tbNames, NULL); return rcode; } diff --git a/source/libs/catalog/src/catalog.c b/source/libs/catalog/src/catalog.c index c194b51b07..199bac5246 100644 --- a/source/libs/catalog/src/catalog.c +++ b/source/libs/catalog/src/catalog.c @@ -519,7 +519,7 @@ int32_t ctgGetTbDistVgInfo(SCatalog* pCtg, SRequestConnInfo* pConn, SName* pTabl vgList = taosArrayInit(1, sizeof(SVgroupInfo)); if (NULL == vgList) { ctgError("taosArrayInit %d failed", (int32_t)sizeof(SVgroupInfo)); - CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY); + CTG_ERR_JRET(terrno); } if (NULL == taosArrayPush(vgList, &vgroupInfo)) { @@ -877,13 +877,13 @@ int32_t catalogInit(SCatalogCfg* cfg) { gCtgMgmt.timer = taosTmrInit(0, 0, 0, "catalog"); if (NULL == gCtgMgmt.timer) { qError("init timer failed, error:%s", tstrerror(terrno)); - CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + CTG_ERR_RET(terrno); } gCtgMgmt.cacheTimer = taosTmrStart(ctgProcessTimerEvent, CTG_DEFAULT_CACHE_MON_MSEC, NULL, gCtgMgmt.timer); if (NULL == gCtgMgmt.cacheTimer) { qError("start cache timer failed"); - CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + CTG_ERR_RET(terrno); } CTG_ERR_RET(ctgStartUpdateThread()); diff --git a/source/libs/catalog/src/ctgAsync.c b/source/libs/catalog/src/ctgAsync.c index e3f7ad4811..e21c1a6486 100644 --- a/source/libs/catalog/src/ctgAsync.c +++ b/source/libs/catalog/src/ctgAsync.c @@ -1173,12 +1173,16 @@ int32_t ctgDumpTbIndexRes(SCtgTask* pTask) { SCtgJob* pJob = pTask->pJob; if (NULL == pJob->jobRes.pTableIndex) { SArray* pRes = taosArrayInit(pJob->tbIndexNum, sizeof(SMetaRes)); + if (NULL == pRes) { + CTG_ERR_RET(terrno); + } + if (atomic_val_compare_exchange_ptr(&pJob->jobRes.pTableIndex, NULL, pRes)) { taosArrayDestroy(pRes); } if (NULL == pJob->jobRes.pTableIndex) { - CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + CTG_ERR_RET(TSDB_CODE_CTG_INTERNAL_ERROR); } } @@ -1198,12 +1202,16 @@ int32_t ctgDumpTbCfgRes(SCtgTask* pTask) { SCtgJob* pJob = pTask->pJob; if (NULL == pJob->jobRes.pTableCfg) { SArray* pRes = taosArrayInit(pJob->tbCfgNum, sizeof(SMetaRes)); + if (NULL == pRes) { + CTG_ERR_RET(terrno); + } + if (atomic_val_compare_exchange_ptr(&pJob->jobRes.pTableCfg, NULL, pRes)) { taosArrayDestroy(pRes); } if (NULL == pJob->jobRes.pTableCfg) { - CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + CTG_ERR_RET(TSDB_CODE_CTG_INTERNAL_ERROR); } } @@ -1223,12 +1231,16 @@ int32_t ctgDumpTbTagRes(SCtgTask* pTask) { SCtgJob* pJob = pTask->pJob; if (NULL == pJob->jobRes.pTableTag) { SArray* pRes = taosArrayInit(pJob->tbTagNum, sizeof(SMetaRes)); + if (NULL == pRes) { + CTG_ERR_RET(terrno); + } + if (atomic_val_compare_exchange_ptr(&pJob->jobRes.pTableTag, NULL, pRes)) { taosArrayDestroy(pRes); } if (NULL == pJob->jobRes.pTableTag) { - CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + CTG_ERR_RET(TSDB_CODE_CTG_INTERNAL_ERROR); } } diff --git a/source/libs/catalog/src/ctgCache.c b/source/libs/catalog/src/ctgCache.c index 9db3913375..ef5da66bfe 100644 --- a/source/libs/catalog/src/ctgCache.c +++ b/source/libs/catalog/src/ctgCache.c @@ -3729,7 +3729,7 @@ int32_t ctgGetTbNamesFromCache(SCatalog *pCtg, SRequestConnInfo *pConn, SCtgTbNa for (int32_t i = 0; i < tbNum; ++i) { CTG_ERR_JRET(ctgAddFetch(&ctx->pFetchs, dbIdx, i, fetchIdx, baseResIdx + i, flag)); if (NULL == taosArrayPush(ctx->pResList, &(SMetaData){0})) { - CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY); + CTG_ERR_JRET(terrno); } } @@ -3863,7 +3863,7 @@ int32_t ctgGetViewsFromCache(SCatalog *pCtg, SRequestConnInfo *pConn, SCtgViewsC taosMemoryFree(pViewMeta->querySql); taosMemoryFree(pViewMeta->user); taosMemoryFree(pViewMeta); - CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + CTG_ERR_RET(terrno); } pViewMeta->pSchema = taosMemoryMalloc(pViewMeta->numOfCols * sizeof(SSchema)); if (pViewMeta->pSchema == NULL) { diff --git a/source/libs/catalog/src/ctgRemote.c b/source/libs/catalog/src/ctgRemote.c index 46a615aeed..ec93b7dee2 100644 --- a/source/libs/catalog/src/ctgRemote.c +++ b/source/libs/catalog/src/ctgRemote.c @@ -34,9 +34,10 @@ int32_t ctgHandleBatchRsp(SCtgJob* pJob, SCtgTaskCallbackParam* cbParam, SDataBu SBatchRspMsg* pRsp = NULL; if (TSDB_CODE_SUCCESS == rspCode && pMsg->pData && (pMsg->len > 0)) { - if (tDeserializeSBatchRsp(pMsg->pData, pMsg->len, &batchRsp) < 0) { + code = tDeserializeSBatchRsp(pMsg->pData, pMsg->len, &batchRsp); + if (code < 0) { ctgError("tDeserializeSBatchRsp failed, msgLen:%d", pMsg->len); - CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + CTG_ERR_RET(code); } msgNum = taosArrayGetSize(batchRsp.pRsps); @@ -673,7 +674,7 @@ int32_t ctgAddBatch(SCatalog* pCtg, int32_t vgId, SRequestConnInfo* pConn, SCtgT newBatch.batchId = atomic_add_fetch_32(&pJob->batchId, 1); if (0 != taosHashPut(pBatchs, &vgId, sizeof(vgId), &newBatch, sizeof(newBatch))) { - CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY); + CTG_ERR_JRET(terrno); } ctgDebug("task %d %s req added to batch %d, target vgId %d", pTask->taskId, TMSG_INFO(msgType), newBatch.batchId, @@ -778,7 +779,7 @@ int32_t ctgBuildBatchReqMsg(SCtgBatch* pBatch, int32_t vgId, void** msg, int32_t int32_t msgSize = tSerializeSBatchReq(NULL, 0, &batchReq); if (msgSize < 0) { qError("tSerializeSBatchReq failed"); - CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + CTG_ERR_RET(msgSize); } *msg = taosMemoryCalloc(1, msgSize); @@ -786,9 +787,10 @@ int32_t ctgBuildBatchReqMsg(SCtgBatch* pBatch, int32_t vgId, void** msg, int32_t qError("calloc batchReq msg failed, size:%d", msgSize); CTG_ERR_RET(terrno); } - if (tSerializeSBatchReq(*msg, msgSize, &batchReq) < 0) { + msgSize = tSerializeSBatchReq(*msg, msgSize, &batchReq); + if (msgSize < 0) { qError("tSerializeSBatchReq failed"); - CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + CTG_ERR_RET(msgSize); } *pSize = msgSize; @@ -835,7 +837,7 @@ int32_t ctgGetQnodeListFromMnode(SCatalog* pCtg, SRequestConnInfo* pConn, SArray char* msg = NULL; int32_t msgLen = 0; int32_t reqType = TDMT_MND_QNODE_LIST; - void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemoryMalloc : (MallocType)rpcMallocCont; + void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemMalloc : (MallocType)rpcMallocCont; ctgDebug("try to get qnode list from mnode, mgmtEpInUse:%d", pConn->mgmtEps.inUse); @@ -892,7 +894,7 @@ int32_t ctgGetDnodeListFromMnode(SCatalog* pCtg, SRequestConnInfo* pConn, SArray char* msg = NULL; int32_t msgLen = 0; int32_t reqType = TDMT_MND_DNODE_LIST; - void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemoryMalloc : (MallocType)rpcMallocCont; + void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemMalloc : (MallocType)rpcMallocCont; ctgDebug("try to get dnode list from mnode, mgmtEpInUse:%d", pConn->mgmtEps.inUse); @@ -946,7 +948,7 @@ int32_t ctgGetDBVgInfoFromMnode(SCatalog* pCtg, SRequestConnInfo* pConn, SBuildU int32_t msgLen = 0; int32_t reqType = TDMT_MND_USE_DB; SCtgTask* pTask = tReq ? tReq->pTask : NULL; - void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemoryMalloc : (MallocType)rpcMallocCont; + void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemMalloc : (MallocType)rpcMallocCont; ctgDebug("try to get db vgInfo from mnode, dbFName:%s", input->db); @@ -1001,7 +1003,7 @@ int32_t ctgGetDBCfgFromMnode(SCatalog* pCtg, SRequestConnInfo* pConn, const char char* msg = NULL; int32_t msgLen = 0; int32_t reqType = TDMT_MND_GET_DB_CFG; - void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemoryMalloc : (MallocType)rpcMallocCont; + void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemMalloc : (MallocType)rpcMallocCont; ctgDebug("try to get db cfg from mnode, dbFName:%s", dbFName); @@ -1059,7 +1061,7 @@ int32_t ctgGetIndexInfoFromMnode(SCatalog* pCtg, SRequestConnInfo* pConn, const char* msg = NULL; int32_t msgLen = 0; int32_t reqType = TDMT_MND_GET_INDEX; - void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemoryMalloc : (MallocType)rpcMallocCont; + void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemMalloc : (MallocType)rpcMallocCont; ctgDebug("try to get index from mnode, indexName:%s", indexName); @@ -1117,7 +1119,7 @@ int32_t ctgGetTbIndexFromMnode(SCatalog* pCtg, SRequestConnInfo* pConn, SName* n char* msg = NULL; int32_t msgLen = 0; int32_t reqType = TDMT_MND_GET_TABLE_INDEX; - void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemoryMalloc : (MallocType)rpcMallocCont; + void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemMalloc : (MallocType)rpcMallocCont; char tbFName[TSDB_TABLE_FNAME_LEN]; ctgDebug("try to get tb index from mnode, tbFName:%s", tbFName); @@ -1183,7 +1185,7 @@ int32_t ctgGetUdfInfoFromMnode(SCatalog* pCtg, SRequestConnInfo* pConn, const ch char* msg = NULL; int32_t msgLen = 0; int32_t reqType = TDMT_MND_RETRIEVE_FUNC; - void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemoryMalloc : (MallocType)rpcMallocCont; + void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemMalloc : (MallocType)rpcMallocCont; ctgDebug("try to get udf info from mnode, funcName:%s", funcName); @@ -1241,7 +1243,7 @@ int32_t ctgGetUserDbAuthFromMnode(SCatalog* pCtg, SRequestConnInfo* pConn, const char* msg = NULL; int32_t msgLen = 0; int32_t reqType = TDMT_MND_GET_USER_AUTH; - void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemoryMalloc : (MallocType)rpcMallocCont; + void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemMalloc : (MallocType)rpcMallocCont; ctgDebug("try to get user auth from mnode, user:%s", user); @@ -1304,7 +1306,7 @@ int32_t ctgGetTbMetaFromMnodeImpl(SCatalog* pCtg, SRequestConnInfo* pConn, const int32_t reqType = TDMT_MND_TABLE_META; char tbFName[TSDB_TABLE_FNAME_LEN]; (void)snprintf(tbFName, sizeof(tbFName), "%s.%s", dbFName, tbName); - void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemoryMalloc : (MallocType)rpcMallocCont; + void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemMalloc : (MallocType)rpcMallocCont; ctgDebug("try to get table meta from mnode, tbFName:%s", tbFName); @@ -1370,7 +1372,7 @@ int32_t ctgGetTbMetaFromVnode(SCatalog* pCtg, SRequestConnInfo* pConn, const SNa int32_t reqType = (pTask && pTask->type == CTG_TASK_GET_TB_NAME ? TDMT_VND_TABLE_NAME : TDMT_VND_TABLE_META); char tbFName[TSDB_TABLE_FNAME_LEN]; (void)snprintf(tbFName, sizeof(tbFName), "%s.%s", dbFName, pTableName->tname); - void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemoryMalloc : (MallocType)rpcMallocCont; + void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemMalloc : (MallocType)rpcMallocCont; SEp* pEp = &vgroupInfo->epSet.eps[vgroupInfo->epSet.inUse]; ctgDebug("try to get table meta from vnode, vgId:%d, ep num:%d, ep %s:%d, tbFName:%s", vgroupInfo->vgId, @@ -1443,8 +1445,7 @@ int32_t ctgGetTableCfgFromVnode(SCatalog* pCtg, SRequestConnInfo* pConn, const S int32_t msgLen = 0; int32_t reqType = TDMT_VND_TABLE_CFG; char tbFName[TSDB_TABLE_FNAME_LEN]; - - void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemoryMalloc : (MallocType)rpcMallocCont; + void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemMalloc : (MallocType)rpcMallocCont; char dbFName[TSDB_DB_FNAME_LEN]; (void)tNameGetFullDbName(pTableName, dbFName); SBuildTableInput bInput = {.vgId = vgroupInfo->vgId, .dbFName = dbFName, .tbName = (char*)pTableName->tname}; @@ -1518,7 +1519,7 @@ int32_t ctgGetTableCfgFromMnode(SCatalog* pCtg, SRequestConnInfo* pConn, const S int32_t msgLen = 0; int32_t reqType = TDMT_MND_TABLE_CFG; char tbFName[TSDB_TABLE_FNAME_LEN]; - void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemoryMalloc : (MallocType)rpcMallocCont; + void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemMalloc : (MallocType)rpcMallocCont; char dbFName[TSDB_DB_FNAME_LEN]; (void)tNameGetFullDbName(pTableName, dbFName); SBuildTableInput bInput = {.vgId = 0, .dbFName = dbFName, .tbName = (char*)pTableName->tname}; @@ -1580,7 +1581,7 @@ int32_t ctgGetSvrVerFromMnode(SCatalog* pCtg, SRequestConnInfo* pConn, char** ou char* msg = NULL; int32_t msgLen = 0; int32_t reqType = TDMT_MND_SERVER_VERSION; - void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemoryMalloc : (MallocType)rpcMallocCont; + void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemMalloc : (MallocType)rpcMallocCont; qDebug("try to get svr ver from mnode"); @@ -1634,7 +1635,7 @@ int32_t ctgGetViewInfoFromMnode(SCatalog* pCtg, SRequestConnInfo* pConn, SName* int32_t msgLen = 0; int32_t reqType = TDMT_MND_VIEW_META; SCtgTask* pTask = tReq ? tReq->pTask : NULL; - void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemoryMalloc : (MallocType)rpcMallocCont; + void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemMalloc : (MallocType)rpcMallocCont; char fullName[TSDB_TABLE_FNAME_LEN]; int32_t code = tNameExtractFullName(pName, fullName); if (code) { @@ -1696,7 +1697,7 @@ int32_t ctgGetTbTSMAFromMnode(SCatalog* pCtg, SRequestConnInfo* pConn, const SNa char* msg = NULL; int32_t msgLen = 0; SCtgTask* pTask = tReq ? tReq->pTask : NULL; - void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemoryMalloc : (MallocType)rpcMallocCont; + void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemMalloc : (MallocType)rpcMallocCont; char tbFName[TSDB_TABLE_FNAME_LEN]; int32_t code = tNameExtractFullName(name, tbFName); if (code) { @@ -1768,7 +1769,7 @@ int32_t ctgGetStreamProgressFromVnode(SCatalog* pCtg, SRequestConnInfo* pConn, c } SCtgTask* pTask = tReq ? tReq->pTask : NULL; - void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemoryMalloc : (MallocType)rpcMallocCont; + void* (*mallocFp)(int64_t) = pTask ? (MallocType)taosMemMalloc : (MallocType)rpcMallocCont; SEp* pEp = &vgroupInfo->epSet.eps[vgroupInfo->epSet.inUse]; ctgDebug("try to get stream progress from vnode, vgId:%d, ep num:%d, ep %s:%d, target:%s", vgroupInfo->vgId, diff --git a/source/libs/catalog/src/ctgUtil.c b/source/libs/catalog/src/ctgUtil.c index f8591b2121..5ab19c4419 100644 --- a/source/libs/catalog/src/ctgUtil.c +++ b/source/libs/catalog/src/ctgUtil.c @@ -1620,7 +1620,7 @@ int32_t ctgCloneVgInfo(SDBVgInfo* src, SDBVgInfo** dst) { taosHashCancelIterate(src->vgHash, pIter); taosHashCleanup((*dst)->vgHash); taosMemoryFreeClear(*dst); - CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + CTG_ERR_RET(terrno); } pIter = taosHashIterate(src->vgHash, pIter); @@ -1787,7 +1787,7 @@ static int32_t ctgCloneDbVgroup(void* pSrc, void** ppDst) { } *ppDst = taosArrayDup((const SArray*)pSrc, NULL); - return (*ppDst) ? TSDB_CODE_SUCCESS : TSDB_CODE_OUT_OF_MEMORY; + return (*ppDst) ? TSDB_CODE_SUCCESS : terrno; #else return TSDB_CODE_CTG_INTERNAL_ERROR; #endif @@ -1824,7 +1824,7 @@ static int32_t ctgCloneDbInfo(void* pSrc, void** ppDst) { #if 0 SDbInfo* pDst = taosMemoryMalloc(sizeof(SDbInfo)); if (NULL == pDst) { - return TSDB_CODE_OUT_OF_MEMORY; + return terrno; } TAOS_MEMCPY(pDst, pSrc, sizeof(SDbInfo)); @@ -2263,13 +2263,13 @@ static int32_t ctgCloneMetaDataArray(SArray* pSrc, __array_item_dup_fn_t copyFun int32_t size = taosArrayGetSize(pSrc); *pDst = taosArrayInit(size, sizeof(SMetaRes)); if (NULL == *pDst) { - return TSDB_CODE_OUT_OF_MEMORY; + return terrno; } for (int32_t i = 0; i < size; ++i) { SMetaRes* pRes = taosArrayGet(pSrc, i); SMetaRes res = {.code = pRes->code, .pRes = copyFunc(pRes->pRes)}; if (NULL == res.pRes) { - return TSDB_CODE_OUT_OF_MEMORY; + return terrno; } taosArrayPush(*pDst, &res); } @@ -2630,11 +2630,11 @@ int32_t ctgBuildViewNullRes(SCtgTask* pTask, SCtgViewsCtx* pCtx) { int32_t dupViewMetaFromRsp(SViewMetaRsp* pRsp, SViewMeta* pViewMeta) { pViewMeta->querySql = tstrdup(pRsp->querySql); if (NULL == pViewMeta->querySql) { - CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + CTG_ERR_RET(terrno); } pViewMeta->user = tstrdup(pRsp->user); if (NULL == pViewMeta->user) { - CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + CTG_ERR_RET(terrno); } pViewMeta->version = pRsp->version; pViewMeta->viewId = pRsp->viewId; diff --git a/source/libs/command/src/explain.c b/source/libs/command/src/explain.c index 60944d8a02..0778d5d5f8 100644 --- a/source/libs/command/src/explain.c +++ b/source/libs/command/src/explain.c @@ -2056,7 +2056,7 @@ static int32_t qExplainPrepareCtx(SQueryPlan *pDag, SExplainCtx **pCtx) { if (0 != taosHashPut(groupHash, &plan->id.groupId, sizeof(plan->id.groupId), &group, sizeof(group))) { qError("taosHashPut to explainGroupHash failed, taskIdx:%d", n); - QRY_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY); + QRY_ERR_JRET(terrno); } } diff --git a/source/libs/executor/inc/dataSinkInt.h b/source/libs/executor/inc/dataSinkInt.h index 01bc762a1d..7df3439fc1 100644 --- a/source/libs/executor/inc/dataSinkInt.h +++ b/source/libs/executor/inc/dataSinkInt.h @@ -39,6 +39,7 @@ typedef void (*FGetDataLength)(struct SDataSinkHandle* pHandle, int64_t* pLen, i typedef int32_t (*FGetDataBlock)(struct SDataSinkHandle* pHandle, SOutputData* pOutput); typedef int32_t (*FDestroyDataSinker)(struct SDataSinkHandle* pHandle); typedef int32_t (*FGetCacheSize)(struct SDataSinkHandle* pHandle, uint64_t* size); +typedef int32_t (*FGetSinkFlags)(struct SDataSinkHandle* pHandle, uint64_t* flags); typedef struct SDataSinkHandle { FPutDataBlock fPut; @@ -48,12 +49,13 @@ typedef struct SDataSinkHandle { FGetDataBlock fGetData; FDestroyDataSinker fDestroy; FGetCacheSize fGetCacheSize; + FGetSinkFlags fGetFlags; } SDataSinkHandle; -int32_t createDataDispatcher(SDataSinkManager* pManager, const SDataSinkNode* pDataSink, DataSinkHandle* pHandle); -int32_t createDataDeleter(SDataSinkManager* pManager, const SDataSinkNode* pDataSink, DataSinkHandle* pHandle, +int32_t createDataDispatcher(SDataSinkManager* pManager, SDataSinkNode** ppDataSink, DataSinkHandle* pHandle); +int32_t createDataDeleter(SDataSinkManager* pManager, SDataSinkNode** ppDataSink, DataSinkHandle* pHandle, void* pParam); -int32_t createDataInserter(SDataSinkManager* pManager, const SDataSinkNode* pDataSink, DataSinkHandle* pHandle, +int32_t createDataInserter(SDataSinkManager* pManager, SDataSinkNode** ppDataSink, DataSinkHandle* pHandle, void* pParam); #ifdef __cplusplus diff --git a/source/libs/executor/inc/executorInt.h b/source/libs/executor/inc/executorInt.h index aebf5d97b6..48afa78251 100644 --- a/source/libs/executor/inc/executorInt.h +++ b/source/libs/executor/inc/executorInt.h @@ -942,7 +942,7 @@ void updateLoadRemoteInfo(SLoadRemoteDataInfo* pInfo, int64_t numOfRows, int3 struct SOperatorInfo* pOperator); STimeWindow getFirstQualifiedTimeWindow(int64_t ts, STimeWindow* pWindow, SInterval* pInterval, int32_t order); -int32_t getBufferPgSize(int32_t rowSize, uint32_t* defaultPgsz, uint32_t* defaultBufsz); +int32_t getBufferPgSize(int32_t rowSize, uint32_t* defaultPgsz, int64_t* defaultBufsz); extern void doDestroyExchangeOperatorInfo(void* param); diff --git a/source/libs/executor/src/aggregateoperator.c b/source/libs/executor/src/aggregateoperator.c index 94bf791ef8..5713726501 100644 --- a/source/libs/executor/src/aggregateoperator.c +++ b/source/libs/executor/src/aggregateoperator.c @@ -581,7 +581,7 @@ int32_t doInitAggInfoSup(SAggSupporter* pAggSup, SqlFunctionCtx* pCtx, int32_t n } uint32_t defaultPgsz = 0; - uint32_t defaultBufsz = 0; + int64_t defaultBufsz = 0; code = getBufferPgSize(pAggSup->resultRowSize, &defaultPgsz, &defaultBufsz); if (code) { qError("failed to get buff page size, rowSize:%d", pAggSup->resultRowSize); diff --git a/source/libs/executor/src/anomalywindowoperator.c b/source/libs/executor/src/anomalywindowoperator.c index 3bc9c806b0..dd1a52022e 100644 --- a/source/libs/executor/src/anomalywindowoperator.c +++ b/source/libs/executor/src/anomalywindowoperator.c @@ -131,11 +131,18 @@ int32_t createAnomalywindowOperatorInfo(SOperatorInfo* downstream, SPhysiNode* p int32_t itemSize = sizeof(int32_t) + pInfo->aggSup.resultRowSize + pInfo->anomalyKey.bytes; pInfo->anomalySup.pResultRow = taosMemoryCalloc(1, itemSize); + if (pInfo->anomalySup.pResultRow == NULL) { + code = terrno; + goto _error; + } pInfo->anomalySup.blocks = taosArrayInit(16, sizeof(SSDataBlock*)); + if (pInfo->anomalySup.blocks == NULL) { + code = terrno; + goto _error; + } pInfo->anomalySup.windows = taosArrayInit(16, sizeof(STimeWindow)); - - if (pInfo->anomalySup.windows == NULL || pInfo->anomalySup.blocks == NULL || pInfo->anomalySup.pResultRow == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; + if (pInfo->anomalySup.windows == NULL) { + code = terrno; goto _error; } @@ -269,8 +276,8 @@ static int32_t anomalyCacheBlock(SAnomalyWindowOperatorInfo* pInfo, SSDataBlock* int32_t code = createOneDataBlock(pSrc, true, &pDst); if (code != 0) return code; - if (pDst == NULL) return TSDB_CODE_OUT_OF_MEMORY; - if (taosArrayPush(pInfo->anomalySup.blocks, &pDst) == NULL) return TSDB_CODE_OUT_OF_MEMORY; + if (pDst == NULL) return code; + if (taosArrayPush(pInfo->anomalySup.blocks, &pDst) == NULL) return terrno; return 0; } @@ -664,4 +671,4 @@ int32_t createAnomalywindowOperatorInfo(SOperatorInfo* downstream, SPhysiNode* p } void destroyForecastInfo(void* param) {} -#endif \ No newline at end of file +#endif diff --git a/source/libs/executor/src/dataDeleter.c b/source/libs/executor/src/dataDeleter.c index c284e9a8a9..1ef8317232 100644 --- a/source/libs/executor/src/dataDeleter.c +++ b/source/libs/executor/src/dataDeleter.c @@ -41,6 +41,7 @@ typedef struct SDataCacheEntry { typedef struct SDataDeleterHandle { SDataSinkHandle sink; SDataSinkManager* pManager; + SDataSinkNode* pSinkNode; SDataBlockDescNode* pSchema; SDataDeleterNode* pDeleter; SDeleterParam* pParam; @@ -50,6 +51,7 @@ typedef struct SDataDeleterHandle { bool queryEnd; uint64_t useconds; uint64_t cachedSize; + uint64_t flags; TdThreadMutex mutex; } SDataDeleterHandle; @@ -111,7 +113,7 @@ static int32_t allocBuf(SDataDeleterHandle* pDeleter, const SInputData* pInput, if (taosQueueItemSize(pDeleter->pDataBlocks) > capacity) { qError("SinkNode queue is full, no capacity, max:%d, current:%d, no capacity", capacity, taosQueueItemSize(pDeleter->pDataBlocks)); - return TSDB_CODE_OUT_OF_MEMORY; + return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR; } pBuf->allocSize = sizeof(SDataCacheEntry) + sizeof(SDeleterRes); @@ -257,6 +259,8 @@ static int32_t destroyDataSinker(SDataSinkHandle* pHandle) { } taosCloseQueue(pDeleter->pDataBlocks); (void)taosThreadMutexDestroy(&pDeleter->mutex); + nodesDestroyNode((SNode*)pDeleter->pSinkNode); + pDeleter->pSinkNode = NULL; taosMemoryFree(pDeleter->pManager); @@ -270,8 +274,18 @@ static int32_t getCacheSize(struct SDataSinkHandle* pHandle, uint64_t* size) { return TSDB_CODE_SUCCESS; } -int32_t createDataDeleter(SDataSinkManager* pManager, const SDataSinkNode* pDataSink, DataSinkHandle* pHandle, + +static int32_t getSinkFlags(struct SDataSinkHandle* pHandle, uint64_t* pFlags) { + SDataDeleterHandle* pDispatcher = (SDataDeleterHandle*)pHandle; + + *pFlags = atomic_load_64(&pDispatcher->flags); + return TSDB_CODE_SUCCESS; +} + + +int32_t createDataDeleter(SDataSinkManager* pManager, SDataSinkNode** ppDataSink, DataSinkHandle* pHandle, void* pParam) { + SDataSinkNode* pDataSink = *ppDataSink; int32_t code = TSDB_CODE_SUCCESS; if (pParam == NULL) { code = TSDB_CODE_QRY_INVALID_INPUT; @@ -296,9 +310,12 @@ int32_t createDataDeleter(SDataSinkManager* pManager, const SDataSinkNode* pData deleter->sink.fGetData = getDataBlock; deleter->sink.fDestroy = destroyDataSinker; deleter->sink.fGetCacheSize = getCacheSize; + deleter->sink.fGetFlags = getSinkFlags; deleter->pManager = pManager; deleter->pDeleter = pDeleterNode; deleter->pSchema = pDataSink->pInputDataBlockDesc; + deleter->pSinkNode = pDataSink; + *ppDataSink = NULL; deleter->pParam = pParam; deleter->status = DS_BUF_EMPTY; @@ -307,6 +324,7 @@ int32_t createDataDeleter(SDataSinkManager* pManager, const SDataSinkNode* pData if (code) { goto _end; } + deleter->flags = DS_FLAG_USE_MEMPOOL; code = taosThreadMutexInit(&deleter->mutex, NULL); if (code) { goto _end; @@ -323,6 +341,9 @@ _end: } else { taosMemoryFree(pManager); } + + nodesDestroyNode((SNode *)*ppDataSink); + *ppDataSink = NULL; return code; } diff --git a/source/libs/executor/src/dataDispatcher.c b/source/libs/executor/src/dataDispatcher.c index f255d0b95c..e28658cd2a 100644 --- a/source/libs/executor/src/dataDispatcher.c +++ b/source/libs/executor/src/dataDispatcher.c @@ -43,6 +43,7 @@ typedef struct SDataDispatchHandle { SDataSinkHandle sink; SDataSinkManager* pManager; SDataBlockDescNode* pSchema; + SDataSinkNode* pSinkNode; STaosQueue* pDataBlocks; SDataDispatchBuf nextOutput; int32_t outPutColCounts; @@ -50,6 +51,7 @@ typedef struct SDataDispatchHandle { bool queryEnd; uint64_t useconds; uint64_t cachedSize; + uint64_t flags; void* pCompressBuf; int32_t bufSize; TdThreadMutex mutex; @@ -355,6 +357,7 @@ static int32_t destroyDataSinker(SDataSinkHandle* pHandle) { SDataDispatchHandle* pDispatcher = (SDataDispatchHandle*)pHandle; (void)atomic_sub_fetch_64(&gDataSinkStat.cachedSize, pDispatcher->cachedSize); taosMemoryFreeClear(pDispatcher->nextOutput.pData); + nodesDestroyNode((SNode*)pDispatcher->pSinkNode); while (!taosQueueEmpty(pDispatcher->pDataBlocks)) { SDataDispatchBuf* pBuf = NULL; @@ -381,6 +384,13 @@ static int32_t getCacheSize(struct SDataSinkHandle* pHandle, uint64_t* size) { return TSDB_CODE_SUCCESS; } +static int32_t getSinkFlags(struct SDataSinkHandle* pHandle, uint64_t* pFlags) { + SDataDispatchHandle* pDispatcher = (SDataDispatchHandle*)pHandle; + + *pFlags = atomic_load_64(&pDispatcher->flags); + return TSDB_CODE_SUCCESS; +} + static int32_t blockDescNodeCheck(SDataBlockDescNode* pInputDataBlockDesc) { if(tsSafetyCheckLevel == TSDB_SAFETY_CHECK_LEVELL_NEVER) { return TSDB_CODE_SUCCESS; @@ -428,12 +438,13 @@ int32_t getOutputColCounts(SDataBlockDescNode* pInputDataBlockDesc) { return numOfCols; } -int32_t createDataDispatcher(SDataSinkManager* pManager, const SDataSinkNode* pDataSink, DataSinkHandle* pHandle) { +int32_t createDataDispatcher(SDataSinkManager* pManager, SDataSinkNode** ppDataSink, DataSinkHandle* pHandle) { int32_t code; + SDataSinkNode* pDataSink = *ppDataSink; code = blockDescNodeCheck(pDataSink->pInputDataBlockDesc); if (code) { qError("failed to check input data block desc, code:%d", code); - return code; + goto _return; } SDataDispatchHandle* dispatcher = taosMemoryCalloc(1, sizeof(SDataDispatchHandle)); @@ -448,10 +459,12 @@ int32_t createDataDispatcher(SDataSinkManager* pManager, const SDataSinkNode* pD dispatcher->sink.fGetData = getDataBlock; dispatcher->sink.fDestroy = destroyDataSinker; dispatcher->sink.fGetCacheSize = getCacheSize; - + dispatcher->sink.fGetFlags = getSinkFlags; dispatcher->pManager = pManager; pManager = NULL; dispatcher->pSchema = pDataSink->pInputDataBlockDesc; + dispatcher->pSinkNode = pDataSink; + *ppDataSink = NULL; dispatcher->outPutColCounts = getOutputColCounts(dispatcher->pSchema); dispatcher->status = DS_BUF_EMPTY; dispatcher->queryEnd = false; @@ -466,6 +479,8 @@ int32_t createDataDispatcher(SDataSinkManager* pManager, const SDataSinkNode* pD goto _return; } + dispatcher->flags = DS_FLAG_USE_MEMPOOL; + *pHandle = dispatcher; return TSDB_CODE_SUCCESS; @@ -476,5 +491,9 @@ _return: if (dispatcher) { dsDestroyDataSinker(dispatcher); } + + nodesDestroyNode((SNode *)*ppDataSink); + *ppDataSink = NULL; + return terrno; } diff --git a/source/libs/executor/src/dataInserter.c b/source/libs/executor/src/dataInserter.c index b29bef1f1e..ec041cba70 100644 --- a/source/libs/executor/src/dataInserter.c +++ b/source/libs/executor/src/dataInserter.c @@ -45,6 +45,7 @@ typedef struct SDataInserterHandle { bool fullOrderColList; uint64_t useconds; uint64_t cachedSize; + uint64_t flags; TdThreadMutex mutex; tsem_t ready; bool explain; @@ -138,7 +139,7 @@ static int32_t sendSubmitRequest(SDataInserterHandle* pInserter, void* pMsg, int pParam->pInserter = pInserter; pMsgSendInfo->param = pParam; - pMsgSendInfo->paramFreeFp = taosMemoryFree; + pMsgSendInfo->paramFreeFp = taosAutoMemoryFree; pMsgSendInfo->msgInfo.pData = pMsg; pMsgSendInfo->msgInfo.len = msgLen; pMsgSendInfo->msgType = TDMT_VND_SUBMIT; @@ -434,6 +435,9 @@ static int32_t destroyDataSinker(SDataSinkHandle* pHandle) { taosMemoryFree(pInserter->pSchema); taosMemoryFree(pInserter->pParam); taosHashCleanup(pInserter->pCols); + nodesDestroyNode((SNode *)pInserter->pNode); + pInserter->pNode = NULL; + (void)taosThreadMutexDestroy(&pInserter->mutex); taosMemoryFree(pInserter->pManager); @@ -447,8 +451,16 @@ static int32_t getCacheSize(struct SDataSinkHandle* pHandle, uint64_t* size) { return TSDB_CODE_SUCCESS; } -int32_t createDataInserter(SDataSinkManager* pManager, const SDataSinkNode* pDataSink, DataSinkHandle* pHandle, +static int32_t getSinkFlags(struct SDataSinkHandle* pHandle, uint64_t* pFlags) { + SDataInserterHandle* pDispatcher = (SDataInserterHandle*)pHandle; + + *pFlags = atomic_load_64(&pDispatcher->flags); + return TSDB_CODE_SUCCESS; +} + +int32_t createDataInserter(SDataSinkManager* pManager, SDataSinkNode** ppDataSink, DataSinkHandle* pHandle, void* pParam) { + SDataSinkNode* pDataSink = *ppDataSink; SDataInserterHandle* inserter = taosMemoryCalloc(1, sizeof(SDataInserterHandle)); if (NULL == inserter) { taosMemoryFree(pParam); @@ -462,12 +474,14 @@ int32_t createDataInserter(SDataSinkManager* pManager, const SDataSinkNode* pDat inserter->sink.fGetData = NULL; inserter->sink.fDestroy = destroyDataSinker; inserter->sink.fGetCacheSize = getCacheSize; + inserter->sink.fGetFlags = getSinkFlags; inserter->pManager = pManager; inserter->pNode = pInserterNode; inserter->pParam = pParam; inserter->status = DS_BUF_EMPTY; inserter->queryEnd = false; inserter->explain = pInserterNode->explain; + *ppDataSink = NULL; int64_t suid = 0; int32_t code = pManager->pAPI->metaFn.getTableSchema(inserter->pParam->readHandle->vnode, pInserterNode->tableId, @@ -521,5 +535,8 @@ _return: taosMemoryFree(pManager); } + nodesDestroyNode((SNode *)*ppDataSink); + *ppDataSink = NULL; + return terrno; } diff --git a/source/libs/executor/src/dataSinkMgt.c b/source/libs/executor/src/dataSinkMgt.c index 55fc520477..255dc901d6 100644 --- a/source/libs/executor/src/dataSinkMgt.c +++ b/source/libs/executor/src/dataSinkMgt.c @@ -39,23 +39,23 @@ int32_t dsDataSinkGetCacheSize(SDataSinkStat* pStat) { return TSDB_CODE_SUCCESS; } -int32_t dsCreateDataSinker(void* pSinkManager, const SDataSinkNode* pDataSink, DataSinkHandle* pHandle, void* pParam, const char* id) { +int32_t dsCreateDataSinker(void* pSinkManager, SDataSinkNode** ppDataSink, DataSinkHandle* pHandle, void* pParam, const char* id) { SDataSinkManager* pManager = pSinkManager; - switch ((int)nodeType(pDataSink)) { + switch ((int)nodeType(*ppDataSink)) { case QUERY_NODE_PHYSICAL_PLAN_DISPATCH: - return createDataDispatcher(pManager, pDataSink, pHandle); + return createDataDispatcher(pManager, ppDataSink, pHandle); case QUERY_NODE_PHYSICAL_PLAN_DELETE: { - return createDataDeleter(pManager, pDataSink, pHandle, pParam); + return createDataDeleter(pManager, ppDataSink, pHandle, pParam); } case QUERY_NODE_PHYSICAL_PLAN_QUERY_INSERT: { - return createDataInserter(pManager, pDataSink, pHandle, pParam); + return createDataInserter(pManager, ppDataSink, pHandle, pParam); } default: break; } taosMemoryFree(pSinkManager); - qError("invalid input node type:%d, %s", nodeType(pDataSink), id); + qError("invalid input node type:%d, %s", nodeType(*ppDataSink), id); return TSDB_CODE_QRY_INVALID_INPUT; } @@ -101,3 +101,9 @@ void dsDestroyDataSinker(DataSinkHandle handle) { (void)pHandleImpl->fDestroy(pHandleImpl); taosMemoryFree(pHandleImpl); } + +int32_t dsGetSinkFlags(DataSinkHandle handle, uint64_t* pFlags) { + SDataSinkHandle* pHandleImpl = (SDataSinkHandle*)handle; + return pHandleImpl->fGetFlags(pHandleImpl, pFlags); +} + diff --git a/source/libs/executor/src/exchangeoperator.c b/source/libs/executor/src/exchangeoperator.c index 7222f2d297..7c4a4adaca 100644 --- a/source/libs/executor/src/exchangeoperator.c +++ b/source/libs/executor/src/exchangeoperator.c @@ -354,15 +354,15 @@ static int32_t initExchangeOperator(SExchangePhysiNode* pExNode, SExchangeInfo* pInfo->pSources = taosArrayInit(numOfSources, sizeof(SDownstreamSourceNode)); if (pInfo->pSources == NULL) { - qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_OUT_OF_MEMORY)); + qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno)); return terrno; } if (pExNode->node.dynamicOp) { pInfo->pHashSources = tSimpleHashInit(numOfSources * 2, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT)); if (NULL == pInfo->pHashSources) { - qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_OUT_OF_MEMORY)); - return TSDB_CODE_OUT_OF_MEMORY; + qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno)); + return terrno; } } @@ -370,7 +370,7 @@ static int32_t initExchangeOperator(SExchangePhysiNode* pExNode, SExchangeInfo* SDownstreamSourceNode* pNode = (SDownstreamSourceNode*)nodesListGetNode((SNodeList*)pExNode->pSrcEndPoints, i); if (!pNode) { qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno)); - return TSDB_CODE_OUT_OF_MEMORY; + return terrno; } void* tmp = taosArrayPush(pInfo->pSources, pNode); if (!tmp) { @@ -640,16 +640,16 @@ int32_t doSendFetchDataRequest(SExchangeInfo* pExchangeInfo, SExecTaskInfo* pTas if (pSource->localExec) { SDataBuf pBuf = {0}; - int32_t code = (*pTaskInfo->localFetch.fp)(pTaskInfo->localFetch.handle, pSource->schedId, pTaskInfo->id.queryId, + int32_t code = (*pTaskInfo->localFetch.fp)(pTaskInfo->localFetch.handle, pSource->sId, pTaskInfo->id.queryId, pSource->clientId, pSource->taskId, 0, pSource->execId, &pBuf.pData, pTaskInfo->localFetch.explainRes); code = loadRemoteDataCallback(pWrapper, &pBuf, code); - QUERY_CHECK_CODE(code, lino, _end); taosMemoryFree(pWrapper); + QUERY_CHECK_CODE(code, lino, _end); } else { SResFetchReq req = {0}; req.header.vgId = pSource->addr.nodeId; - req.sId = pSource->schedId; + req.sId = pSource->sId; req.clientId = pSource->clientId; req.taskId = pSource->taskId; req.queryId = pTaskInfo->id.queryId; @@ -668,7 +668,7 @@ int32_t doSendFetchDataRequest(SExchangeInfo* pExchangeInfo, SExecTaskInfo* pTas int32_t msgSize = tSerializeSResFetchReq(NULL, 0, &req); if (msgSize < 0) { - pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY; + pTaskInfo->code = msgSize; taosMemoryFree(pWrapper); freeOperatorParam(req.pOpParam, OP_GET_PARAM); return pTaskInfo->code; @@ -676,14 +676,15 @@ int32_t doSendFetchDataRequest(SExchangeInfo* pExchangeInfo, SExecTaskInfo* pTas void* msg = taosMemoryCalloc(1, msgSize); if (NULL == msg) { - pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY; + pTaskInfo->code = terrno; taosMemoryFree(pWrapper); freeOperatorParam(req.pOpParam, OP_GET_PARAM); return pTaskInfo->code; } - if (tSerializeSResFetchReq(msg, msgSize, &req) < 0) { - pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY; + msgSize = tSerializeSResFetchReq(msg, msgSize, &req); + if (msgSize < 0) { + pTaskInfo->code = msgSize; taosMemoryFree(pWrapper); taosMemoryFree(msg); freeOperatorParam(req.pOpParam, OP_GET_PARAM); @@ -703,18 +704,19 @@ int32_t doSendFetchDataRequest(SExchangeInfo* pExchangeInfo, SExecTaskInfo* pTas taosMemoryFreeClear(msg); taosMemoryFree(pWrapper); qError("%s prepare message %d failed", GET_TASKID(pTaskInfo), (int32_t)sizeof(SMsgSendInfo)); - pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY; + pTaskInfo->code = terrno; return pTaskInfo->code; } pMsgSendInfo->param = pWrapper; - pMsgSendInfo->paramFreeFp = taosMemoryFree; + pMsgSendInfo->paramFreeFp = taosAutoMemoryFree; pMsgSendInfo->msgInfo.pData = msg; pMsgSendInfo->msgInfo.len = msgSize; pMsgSendInfo->msgType = pSource->fetchMsgType; pMsgSendInfo->fp = loadRemoteDataCallback; int64_t transporterId = 0; + void* poolHandle = NULL; code = asyncSendMsgToServer(pExchangeInfo->pTransporter, &pSource->addr.epSet, &transporterId, pMsgSendInfo); QUERY_CHECK_CODE(code, lino, _end); int64_t* pRpcHandle = taosArrayGet(pExchangeInfo->pFetchRpcHandles, sourceIndex); @@ -898,7 +900,7 @@ int32_t doExtractResultBlocks(SExchangeInfo* pExchangeInfo, SSourceDataInfo* pDa blockDataCleanup(pb); } else { code = createOneDataBlock(pExchangeInfo->pDummyBlock, false, &pb); - QUERY_CHECK_NULL(pb, code, lino, _end, TSDB_CODE_OUT_OF_MEMORY); + QUERY_CHECK_NULL(pb, code, lino, _end, code); } int32_t compLen = *(int32_t*)pStart; @@ -1055,7 +1057,7 @@ int32_t addSingleExchangeSource(SOperatorInfo* pOperator, SExchangeOperatorBasic void* tmp = taosArrayPush(pExchangeInfo->pSourceDataInfo, &dataInfo); if (!tmp) { - qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_OUT_OF_MEMORY)); + qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno)); return terrno; } pIdx->inUseIdx = taosArrayGetSize(pExchangeInfo->pSourceDataInfo) - 1; diff --git a/source/libs/executor/src/executil.c b/source/libs/executor/src/executil.c index ccb7005dbd..cce754a8c8 100644 --- a/source/libs/executor/src/executil.c +++ b/source/libs/executor/src/executil.c @@ -332,7 +332,6 @@ SArray* createSortInfo(SNodeList* pNodeList) { SArray* pList = taosArrayInit(numOfCols, sizeof(SBlockOrderInfo)); if (pList == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; return pList; } @@ -342,7 +341,7 @@ SArray* createSortInfo(SNodeList* pNodeList) { qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno)); taosArrayDestroy(pList); pList = NULL; - terrno = TSDB_CODE_OUT_OF_MEMORY; + terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR; break; } SBlockOrderInfo bi = {0}; @@ -355,7 +354,6 @@ SArray* createSortInfo(SNodeList* pNodeList) { if (!tmp) { taosArrayDestroy(pList); pList = NULL; - terrno = TSDB_CODE_OUT_OF_MEMORY; break; } } @@ -1129,7 +1127,7 @@ static int32_t optimizeTbnameInCondImpl(void* pVnode, SArray* pExistedUidList, S if (numOfExisted > 0) { uHash = taosHashInit(numOfExisted / 0.7, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK); if (!uHash) { - qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_OUT_OF_MEMORY)); + qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno)); return terrno; } @@ -1330,7 +1328,7 @@ static int32_t copyExistedUids(SArray* pUidTagList, const SArray* pUidList) { STUidTagInfo info = {.uid = *uid}; void* tmp = taosArrayPush(pUidTagList, &info); if (!tmp) { - qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_OUT_OF_MEMORY)); + qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno)); return code; } } @@ -1356,15 +1354,13 @@ static int32_t doFilterByTagCond(STableListInfo* pListInfo, SArray* pUidList, SN tagFilterAssist ctx = {0}; ctx.colHash = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_SMALLINT), false, HASH_NO_LOCK); if (ctx.colHash == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - code = TSDB_CODE_OUT_OF_MEMORY; + code = terrno; QUERY_CHECK_CODE(code, lino, end); } ctx.cInfoList = taosArrayInit(4, sizeof(SColumnInfo)); if (ctx.cInfoList == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - code = TSDB_CODE_OUT_OF_MEMORY; + code = terrno; QUERY_CHECK_CODE(code, lino, end); } @@ -1705,6 +1701,7 @@ int32_t getGroupIdFromTagsVal(void* pVnode, uint64_t uid, SNodeList* pGroupNode, nodesDestroyList(groupNew); pAPI->metaReaderFn.clearReader(&mr); + return TSDB_CODE_SUCCESS; } @@ -1716,7 +1713,6 @@ SArray* makeColumnArrayFromList(SNodeList* pNodeList) { size_t numOfCols = LIST_LENGTH(pNodeList); SArray* pList = taosArrayInit(numOfCols, sizeof(SColumn)); if (pList == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; return NULL; } @@ -1724,7 +1720,7 @@ SArray* makeColumnArrayFromList(SNodeList* pNodeList) { SColumnNode* pColNode = (SColumnNode*)nodesListGetNode(pNodeList, i); if (!pColNode) { taosArrayDestroy(pList); - qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_OUT_OF_MEMORY)); + qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR)); return NULL; } @@ -1740,7 +1736,7 @@ SArray* makeColumnArrayFromList(SNodeList* pNodeList) { void* tmp = taosArrayPush(pList, &c); if (!tmp) { taosArrayDestroy(pList); - qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_OUT_OF_MEMORY)); + qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno)); return NULL; } } @@ -1835,7 +1831,6 @@ static SResSchema createResSchema(int32_t type, int32_t bytes, int32_t slotId, i static SColumn* createColumn(int32_t blockId, int32_t slotId, int32_t colId, SDataType* pType, EColumnType colType) { SColumn* pCol = taosMemoryCalloc(1, sizeof(SColumn)); if (pCol == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; return NULL; } @@ -2174,7 +2169,7 @@ SqlFunctionCtx* createSqlFunctionCtx(SExprInfo* pExprInfo, int32_t numOfOutput, } bool tmp = pCtx->fpSet.getEnv(pExpr->pExpr->_function.pFunctNode, &env); if (!tmp) { - code = TSDB_CODE_OUT_OF_MEMORY; + code = terrno; QUERY_CHECK_CODE(code, lino, _end); } } else { @@ -2187,7 +2182,7 @@ SqlFunctionCtx* createSqlFunctionCtx(SExprInfo* pExprInfo, int32_t numOfOutput, if (pCtx->sfp.getEnv != NULL) { bool tmp = pCtx->sfp.getEnv(pExpr->pExpr->_function.pFunctNode, &env); if (!tmp) { - code = TSDB_CODE_OUT_OF_MEMORY; + code = terrno; QUERY_CHECK_CODE(code, lino, _end); } } @@ -2236,6 +2231,8 @@ _end: } taosMemoryFreeClear(*rowEntryInfoOffset); taosMemoryFreeClear(pFuncCtx); + + terrno = code; return NULL; } return pFuncCtx; @@ -3073,6 +3070,7 @@ SNodeList* makeColsNodeArrFromSortKeys(SNodeList* pSortKeys) { int32_t code = nodesListMakeAppend(&ret, pSortKey->pExpr); if (code != TSDB_CODE_SUCCESS) { qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code)); + terrno = code; return NULL; } } @@ -3098,3 +3096,4 @@ _end: } return code; } + diff --git a/source/libs/executor/src/executor.c b/source/libs/executor/src/executor.c index a0e31a8a3e..dffab1b163 100644 --- a/source/libs/executor/src/executor.c +++ b/source/libs/executor/src/executor.c @@ -441,6 +441,7 @@ static int32_t filterUnqualifiedTables(const SStreamScanInfo* pScanInfo, const S } _end: + pAPI->metaReaderFn.clearReader(&mr); (*ppArrayRes) = qa; @@ -599,6 +600,11 @@ void qUpdateOperatorParam(qTaskInfo_t tinfo, void* pParam) { ((SExecTaskInfo*)tinfo)->paramSet = false; } +int32_t qExecutorInit(void) { + taosThreadOnce(&initPoolOnce, initRefPool); + return TSDB_CODE_SUCCESS; +} + int32_t qCreateExecTask(SReadHandle* readHandle, int32_t vgId, uint64_t taskId, SSubplan* pSubplan, qTaskInfo_t* pTaskInfo, DataSinkHandle* handle, int8_t compressResult, char* sql, EOPTR_EXEC_MODEL model) { @@ -630,8 +636,18 @@ int32_t qCreateExecTask(SReadHandle* readHandle, int32_t vgId, uint64_t taskId, goto _error; } + SDataSinkNode* pSink = NULL; + if (readHandle->localExec) { + code = nodesCloneNode((SNode *)pSubplan->pDataSink, (SNode **)&pSink); + if (code != TSDB_CODE_SUCCESS) { + qError("failed to nodesCloneNode, srcType:%d, code:%s, %s", nodeType(pSubplan->pDataSink), tstrerror(code), (*pTask)->id.str); + taosMemoryFree(pSinkManager); + goto _error; + } + } + // pSinkParam has been freed during create sinker. - code = dsCreateDataSinker(pSinkManager, pSubplan->pDataSink, handle, pSinkParam, (*pTask)->id.str); + code = dsCreateDataSinker(pSinkManager, readHandle->localExec ? &pSink : &pSubplan->pDataSink, handle, pSinkParam, (*pTask)->id.str); if (code) { qError("s-task:%s failed to create data sinker, code:%s", (*pTask)->id.str, tstrerror(code)); } @@ -726,7 +742,7 @@ int32_t qExecTaskOpt(qTaskInfo_t tinfo, SArray* pResList, uint64_t* useconds, bo QUERY_CHECK_CODE(code, lino, _end); void* tmp = taosArrayPush(pTaskInfo->pResultBlockList, &p1); - QUERY_CHECK_NULL(tmp, code, lino, _end, TSDB_CODE_OUT_OF_MEMORY); + QUERY_CHECK_NULL(tmp, code, lino, _end, terrno); p = p1; } else { void* tmp = taosArrayGet(pTaskInfo->pResultBlockList, blockIndex); @@ -881,7 +897,7 @@ int32_t qAppendTaskStopInfo(SExecTaskInfo* pTaskInfo, SExchangeOpStopInfo* pInfo taosWUnLockLatch(&pTaskInfo->stopInfo.lock); if (!tmp) { - qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_OUT_OF_MEMORY)); + qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno)); return terrno; } return TSDB_CODE_SUCCESS; @@ -1570,8 +1586,7 @@ void qProcessRspMsg(void* parent, SRpcMsg* pMsg, SEpSet* pEpSet) { if (pMsg->contLen > 0) { buf.pData = taosMemoryCalloc(1, pMsg->contLen); if (buf.pData == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - pMsg->code = TSDB_CODE_OUT_OF_MEMORY; + pMsg->code = terrno; } else { memcpy(buf.pData, pMsg->pCont, pMsg->contLen); } @@ -1590,7 +1605,6 @@ SArray* qGetQueriedTableListInfo(qTaskInfo_t tinfo) { code = getTableListInfo(pTaskInfo, &plist); if (code || plist == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; return NULL; } diff --git a/source/libs/executor/src/executorInt.c b/source/libs/executor/src/executorInt.c index b8d15aad31..51e7cd896a 100644 --- a/source/libs/executor/src/executorInt.c +++ b/source/libs/executor/src/executorInt.c @@ -438,9 +438,6 @@ static int32_t doCreateConstantValColumnSMAInfo(SInputColumnInfoData* pInput, SF return terrno; } pInput->pColumnDataAgg[paramIndex] = da; - if (da == NULL) { - return TSDB_CODE_OUT_OF_MEMORY; - } } else { da = pInput->pColumnDataAgg[paramIndex]; } @@ -974,7 +971,7 @@ void destroyExprInfo(SExprInfo* pExpr, int32_t numOfExprs) { } } -int32_t getBufferPgSize(int32_t rowSize, uint32_t* defaultPgsz, uint32_t* defaultBufsz) { +int32_t getBufferPgSize(int32_t rowSize, uint32_t* defaultPgsz, int64_t* defaultBufsz) { *defaultPgsz = 4096; uint32_t last = *defaultPgsz; while (*defaultPgsz < rowSize * 4) { @@ -1056,7 +1053,7 @@ int32_t initExprSupp(SExprSupp* pSup, SExprInfo* pExprInfo, int32_t numOfExpr, S if (pSup->pExprInfo != NULL) { pSup->pCtx = createSqlFunctionCtx(pExprInfo, numOfExpr, &pSup->rowEntryInfoOffset, pStore); if (pSup->pCtx == NULL) { - return TSDB_CODE_OUT_OF_MEMORY; + return terrno; } } @@ -1145,7 +1142,7 @@ int32_t createDataSinkParam(SDataSinkNode* pNode, void** pParam, SExecTaskInfo* if (!pTable) { taosArrayDestroy(pDeleterParam->pUidList); taosMemoryFree(pDeleterParam); - return TSDB_CODE_OUT_OF_MEMORY; + return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR; } void* tmp = taosArrayPush(pDeleterParam->pUidList, &pTable->uid); if (!tmp) { diff --git a/source/libs/executor/src/filloperator.c b/source/libs/executor/src/filloperator.c index bcbd3f7563..5dbd490223 100644 --- a/source/libs/executor/src/filloperator.c +++ b/source/libs/executor/src/filloperator.c @@ -387,10 +387,10 @@ static int32_t initFillInfo(SFillOperatorInfo* pInfo, SExprInfo* pExpr, int32_t return terrno; } - if (pInfo->pFillInfo == NULL || pInfo->p == NULL) { + if (pInfo->pFillInfo == NULL) { taosMemoryFree(pInfo->pFillInfo); taosMemoryFree(pInfo->p); - return TSDB_CODE_OUT_OF_MEMORY; + return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR; } else { return TSDB_CODE_SUCCESS; } diff --git a/source/libs/executor/src/groupcacheoperator.c b/source/libs/executor/src/groupcacheoperator.c index d47ab366b6..bdcdeb2c32 100644 --- a/source/libs/executor/src/groupcacheoperator.c +++ b/source/libs/executor/src/groupcacheoperator.c @@ -384,7 +384,7 @@ void freeGcBlkBufInfo(void* ptr) { static int32_t addBlkToDirtyBufList(SGroupCacheOperatorInfo* pGCache, SGcDownstreamCtx* pCtx, SGcBlkCacheInfo* pCache, SGcBlkBufInfo* pBufInfo) { if (0 != taosHashPut(pCache->pDirtyBlk, &pBufInfo->basic.blkId, sizeof(pBufInfo->basic.blkId), pBufInfo, sizeof(*pBufInfo))) { freeGcBlkBufInfo(pBufInfo); - return TSDB_CODE_OUT_OF_MEMORY; + return terrno; } pBufInfo = taosHashGet(pCache->pDirtyBlk, &pBufInfo->basic.blkId, sizeof(pBufInfo->basic.blkId)); if (NULL == pBufInfo) { @@ -906,7 +906,7 @@ static int32_t addNewGroupData(struct SOperatorInfo* pOperator, SOperatorParam* *ppGrp = taosHashGet(pGrpHash, &uid, sizeof(uid)); if (NULL == *ppGrp) { - return TSDB_CODE_OUT_OF_MEMORY; + return terrno; } QRY_ERR_RET(initNewGroupData(pCtx, *ppGrp, pParam->downstreamIdx, vgId, pGCache->batchFetch, pGcParam->needCache)); @@ -1147,12 +1147,12 @@ static int32_t groupCacheSessionWait(struct SOperatorInfo* pOperator, SGcDownstr if (NULL == pGroup->waitQueue) { pGroup->waitQueue = taosArrayInit(1, POINTER_BYTES); if (NULL == pGroup->waitQueue) { - QRY_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY); + QRY_ERR_JRET(terrno); } } if (NULL == taosArrayPush(pGroup->waitQueue, &pSession)) { - QRY_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY); + QRY_ERR_JRET(terrno); } if (!pSession->semInit) { @@ -1413,7 +1413,7 @@ static int32_t initGroupCacheDownstreamCtx(SOperatorInfo* pOperator) { pCtx->lastBlkUid = 0; pCtx->pVgTbHash = tSimpleHashInit(10, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT)); if (NULL == pCtx->pVgTbHash) { - return TSDB_CODE_OUT_OF_MEMORY; + return terrno; } tSimpleHashSetFreeFp(pCtx->pVgTbHash, freeSGcVgroupCtx); diff --git a/source/libs/executor/src/groupoperator.c b/source/libs/executor/src/groupoperator.c index d6e3d26267..08b4ce240e 100644 --- a/source/libs/executor/src/groupoperator.c +++ b/source/libs/executor/src/groupoperator.c @@ -614,7 +614,6 @@ SSDataBlock* createBlockDataNotLoaded(const SOperatorInfo* pOperator, SSDataBloc if (pDataBlock->pBlockAgg) { pDstBlock->pBlockAgg = taosMemoryCalloc(numOfCols, sizeof(SColumnDataAgg)); if (pDstBlock->pBlockAgg == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; blockDataDestroy(pDstBlock); return NULL; } @@ -1161,7 +1160,7 @@ int32_t createPartitionOperatorInfo(SOperatorInfo* downstream, SPartitionPhysiNo } uint32_t defaultPgsz = 0; - uint32_t defaultBufsz = 0; + int64_t defaultBufsz = 0; pInfo->binfo.pRes = createDataBlockFromDescNode(pPartNode->node.pOutputDataBlockDesc); QUERY_CHECK_NULL(pInfo->binfo.pRes, code, lino, _error, terrno); diff --git a/source/libs/executor/src/hashjoinoperator.c b/source/libs/executor/src/hashjoinoperator.c index 27efd59c12..64ce62cb66 100644 --- a/source/libs/executor/src/hashjoinoperator.c +++ b/source/libs/executor/src/hashjoinoperator.c @@ -804,7 +804,7 @@ static int32_t hJoinAddRowToHashImpl(SHJoinOperatorInfo* pJoin, SGroupData* pGro pRow->next = NULL; if (tSimpleHashPut(pJoin->pKeyHash, pTable->keyData, keyLen, &group, sizeof(group))) { taosMemoryFree(pRow); - return TSDB_CODE_OUT_OF_MEMORY; + return terrno; } } else { pRow->next = pGroup->rows; @@ -1201,7 +1201,7 @@ int32_t createHashJoinOperatorInfo(SOperatorInfo** pDownstream, int32_t numOfDow size_t hashCap = pInfo->pBuild->inputStat.inputRowNum > 0 ? (pInfo->pBuild->inputStat.inputRowNum * 1.5) : 1024; pInfo->pKeyHash = tSimpleHashInit(hashCap, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY)); if (pInfo->pKeyHash == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; + code = terrno; goto _return; } diff --git a/source/libs/executor/src/mergeoperator.c b/source/libs/executor/src/mergeoperator.c index 0dfe89e10e..81e43560e3 100644 --- a/source/libs/executor/src/mergeoperator.c +++ b/source/libs/executor/src/mergeoperator.c @@ -331,7 +331,7 @@ int32_t openNonSortMergeOperator(SOperatorInfo* pOperator) { pNonSortMergeInfo->pSourceStatus = taosMemoryCalloc(pOperator->numOfDownstream, sizeof(*pNonSortMergeInfo->pSourceStatus)); if (NULL == pNonSortMergeInfo->pSourceStatus) { - pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY; + pTaskInfo->code = terrno; return pTaskInfo->code; } diff --git a/source/libs/executor/src/operator.c b/source/libs/executor/src/operator.c index 67603c965b..5d25a81f6f 100644 --- a/source/libs/executor/src/operator.c +++ b/source/libs/executor/src/operator.c @@ -722,7 +722,7 @@ int32_t getOperatorExplainExecInfo(SOperatorInfo* operatorInfo, SArray* pExecInf code = getOperatorExplainExecInfo(operatorInfo->pDownstream[i], pExecInfoList); if (code != TSDB_CODE_SUCCESS) { // taosMemoryFreeClear(*pRes); - return TSDB_CODE_OUT_OF_MEMORY; + return code; } } diff --git a/source/libs/executor/src/querytask.c b/source/libs/executor/src/querytask.c index 37461382dd..c6a1900b41 100644 --- a/source/libs/executor/src/querytask.c +++ b/source/libs/executor/src/querytask.c @@ -102,7 +102,6 @@ int32_t createExecTaskInfo(SSubplan* pPlan, SExecTaskInfo** pTaskInfo, SReadHand int32_t code = doCreateTask(pPlan->id.queryId, taskId, vgId, model, &pHandle->api, pTaskInfo); if (*pTaskInfo == NULL || code != 0) { nodesDestroyNode((SNode*)pPlan); - taosMemoryFree(sql); return code; } @@ -112,7 +111,16 @@ int32_t createExecTaskInfo(SSubplan* pPlan, SExecTaskInfo** pTaskInfo, SReadHand } } - TSWAP((*pTaskInfo)->sql, sql); + if (NULL != sql) { + (*pTaskInfo)->sql = taosStrdup(sql); + if (NULL == (*pTaskInfo)->sql) { + code = terrno; + nodesDestroyNode((SNode*)pPlan); + doDestroyTask(*pTaskInfo); + (*pTaskInfo) = NULL; + return code; + } + } (*pTaskInfo)->pSubplan = pPlan; (*pTaskInfo)->pWorkerCb = pHandle->pWorkerCb; diff --git a/source/libs/executor/src/scanoperator.c b/source/libs/executor/src/scanoperator.c index cc4258b84b..1060cbcffe 100644 --- a/source/libs/executor/src/scanoperator.c +++ b/source/libs/executor/src/scanoperator.c @@ -1167,7 +1167,7 @@ static int32_t createTableListInfoFromParam(SOperatorInfo* pOperator) { if (TSDB_CODE_DUP_KEY == terrno) { continue; } - return TSDB_CODE_OUT_OF_MEMORY; + return terrno; } info.uid = *pUid; @@ -4572,11 +4572,10 @@ int32_t createStreamScanOperatorInfo(SReadHandle* pHandle, STableScanPhysiNode* int32_t numOfTags; SExprInfo* pTagExpr = createExpr(pTableScanNode->pTags, &numOfTags); if (pTagExpr == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; goto _error; } - if (initExprSupp(&pInfo->tagCalSup, pTagExpr, numOfTags, &pTaskInfo->storageAPI.functionStore) != 0) { - code = TSDB_CODE_OUT_OF_MEMORY; + code = initExprSupp(&pInfo->tagCalSup, pTagExpr, numOfTags, &pTaskInfo->storageAPI.functionStore); + if (code != 0) { goto _error; } } @@ -5173,7 +5172,7 @@ static int32_t doTagScanFromMetaEntryNext(SOperatorInfo* pOperator, SSDataBlock* while (pInfo->curPos < size && pRes->info.rows < pOperator->resultInfo.capacity) { code = doTagScanOneTable(pOperator, pRes, &mr, &pTaskInfo->storageAPI); - if (code != TSDB_CODE_OUT_OF_MEMORY) { + if (code != TSDB_CODE_OUT_OF_MEMORY && code != TSDB_CODE_QRY_REACH_QMEM_THRESHOLD && code != TSDB_CODE_QRY_QUERY_MEM_EXHAUSTED) { // ignore other error code = TSDB_CODE_SUCCESS; } diff --git a/source/libs/executor/src/sortoperator.c b/source/libs/executor/src/sortoperator.c index a6ca20c5ee..ed073d21a0 100644 --- a/source/libs/executor/src/sortoperator.c +++ b/source/libs/executor/src/sortoperator.c @@ -112,10 +112,10 @@ int32_t createSortOperatorInfo(SOperatorInfo* downstream, SSortPhysiNode* pSortN goto _error; } SNodeList* pSortColsNodeArr = makeColsNodeArrFromSortKeys(pSortNode->pSortKeys); - if (!pSortColsNodeArr) code = TSDB_CODE_OUT_OF_MEMORY; + if (!pSortColsNodeArr) code = terrno; if (TSDB_CODE_SUCCESS == code) { pGroupIdCalc->pSortColsArr = makeColumnArrayFromList(pSortColsNodeArr); - if (!pGroupIdCalc->pSortColsArr) code = TSDB_CODE_OUT_OF_MEMORY; + if (!pGroupIdCalc->pSortColsArr) code = terrno; nodesClearList(pSortColsNodeArr); } if (TSDB_CODE_SUCCESS == code) { diff --git a/source/libs/executor/src/streameventwindowoperator.c b/source/libs/executor/src/streameventwindowoperator.c index 29b3f473ba..fa6008eba7 100644 --- a/source/libs/executor/src/streameventwindowoperator.c +++ b/source/libs/executor/src/streameventwindowoperator.c @@ -549,7 +549,7 @@ void doStreamEventSaveCheckpoint(SOperatorInfo* pOperator) { int32_t len = doStreamEventEncodeOpState(NULL, 0, pOperator); void* buf = taosMemoryCalloc(1, len); if (!buf) { - qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_OUT_OF_MEMORY)); + qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno)); return; } void* pBuf = buf; diff --git a/source/libs/executor/src/streamtimewindowoperator.c b/source/libs/executor/src/streamtimewindowoperator.c index e576e0d920..91af218a7e 100644 --- a/source/libs/executor/src/streamtimewindowoperator.c +++ b/source/libs/executor/src/streamtimewindowoperator.c @@ -1466,7 +1466,7 @@ void doStreamIntervalSaveCheckpoint(SOperatorInfo* pOperator) { int32_t len = doStreamIntervalEncodeOpState(NULL, 0, pOperator); void* buf = taosMemoryCalloc(1, len); if (!buf) { - qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_OUT_OF_MEMORY)); + qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno)); return; } void* pBuf = buf; diff --git a/source/libs/executor/src/sysscanoperator.c b/source/libs/executor/src/sysscanoperator.c index 6d21f43889..4e949a6b8b 100644 --- a/source/libs/executor/src/sysscanoperator.c +++ b/source/libs/executor/src/sysscanoperator.c @@ -609,7 +609,6 @@ static SSDataBlock* sysTableScanUserCols(SOperatorInfo* pOperator) { } if (!pInfo->pCur || !pInfo->pSchema) { - terrno = TSDB_CODE_OUT_OF_MEMORY; qError("sysTableScanUserCols failed since %s", terrstr()); blockDataDestroy(pDataBlock); pInfo->loadInfo.totalRows = 0; @@ -1014,7 +1013,7 @@ static int32_t sysTableGetGeomText(char* iGeom, int32_t nGeom, char** output, in char* outputWKT = NULL; if (nGeom == 0) { - if (!(*output = taosStrdup(""))) code = TSDB_CODE_OUT_OF_MEMORY; + if (!(*output = taosStrdup(""))) code = terrno; *nOutput = 0; return code; } @@ -1112,8 +1111,9 @@ static int32_t sysTableUserTagsFillOneTableTags(const SSysTableScanInfo* pInfo, code = sysTableGetGeomText(tagVal.pData, tagVal.nData, &tagData, &tagLen); QUERY_CHECK_CODE(code, lino, _end); } else if (tagType == TSDB_DATA_TYPE_VARBINARY) { - if (taosAscii2Hex(tagVal.pData, tagVal.nData, (void**)&tagData, &tagLen) < 0) { - qError("varbinary for systable failed since %s", tstrerror(TSDB_CODE_OUT_OF_MEMORY)); + code = taosAscii2Hex(tagVal.pData, tagVal.nData, (void**)&tagData, &tagLen); + if (code < 0) { + qError("varbinary for systable failed since %s", tstrerror(code)); } } else if (IS_VAR_DATA_TYPE(tagType)) { tagData = (char*)tagVal.pData; @@ -1438,7 +1438,7 @@ static int32_t doSetUserTableMetaInfo(SStoreMetaReader* pMetaReaderFn, SStoreMet SMetaReader mr1 = {0}; pMetaReaderFn->initReader(&mr1, pVnode, META_READER_NOLOCK, pMetaFn); - + int64_t suid = pMReader->me.ctbEntry.suid; code = pMetaReaderFn->getTableEntryByUid(&mr1, suid); if (code != TSDB_CODE_SUCCESS) { @@ -1601,6 +1601,7 @@ static SSDataBlock* sysTableBuildUserTablesByUids(SOperatorInfo* pOperator) { SMetaReader mr = {0}; pAPI->metaReaderFn.initReader(&mr, pInfo->readHandle.vnode, META_READER_LOCK, &pAPI->metaFn); + code = doSetUserTableMetaInfo(&pAPI->metaReaderFn, &pAPI->metaFn, pInfo->readHandle.vnode, &mr, *uid, dbname, vgId, p, numOfRows, GET_TASKID(pTaskInfo)); @@ -1748,7 +1749,7 @@ static SSDataBlock* sysTableBuildUserTables(SOperatorInfo* pOperator) { SMetaReader mr = {0}; pAPI->metaReaderFn.initReader(&mr, pInfo->readHandle.vnode, META_READER_NOLOCK, &pAPI->metaFn); - + uint64_t suid = pInfo->pCur->mr.me.ctbEntry.suid; code = pAPI->metaReaderFn.getTableEntryByUid(&mr, suid); if (code != TSDB_CODE_SUCCESS) { @@ -2396,7 +2397,7 @@ static SSDataBlock* sysTableScanFromMNode(SOperatorInfo* pOperator, SSysTableSca SMsgSendInfo* pMsgSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo)); if (NULL == pMsgSendInfo) { qError("%s prepare message %d failed", GET_TASKID(pTaskInfo), (int32_t)sizeof(SMsgSendInfo)); - pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY; + pTaskInfo->code = terrno; taosMemoryFree(buf1); return NULL; } diff --git a/source/libs/executor/src/timewindowoperator.c b/source/libs/executor/src/timewindowoperator.c index c2aa07dacc..52b5e0eb19 100644 --- a/source/libs/executor/src/timewindowoperator.c +++ b/source/libs/executor/src/timewindowoperator.c @@ -630,7 +630,7 @@ static void doInterpUnclosedTimeWindow(SOperatorInfo* pOperatorInfo, int32_t num int32_t ret = setTimeWindowOutputBuf(pResultRowInfo, &w, (scanFlag == MAIN_SCAN), &pResult, groupId, pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo); if (ret != TSDB_CODE_SUCCESS) { - T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY); + T_LONG_JMP(pTaskInfo->env, ret); } if(isResultRowInterpolated(pResult, RESULT_ROW_END_INTERP)) { @@ -711,7 +711,7 @@ static bool filterWindowWithLimit(SIntervalAggOperatorInfo* pOperatorInfo, STime if (pOperatorInfo->limit == 0) return true; if (pOperatorInfo->pBQ == NULL) { - pOperatorInfo->pBQ = createBoundedQueue(pOperatorInfo->limit - 1, tsKeyCompFn, taosMemoryFree, pOperatorInfo); + pOperatorInfo->pBQ = createBoundedQueue(pOperatorInfo->limit - 1, tsKeyCompFn, taosAutoMemoryFree, pOperatorInfo); QUERY_CHECK_NULL(pOperatorInfo->pBQ, code, lino, _end, terrno); } @@ -780,7 +780,7 @@ static bool hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResul int32_t ret = setTimeWindowOutputBuf(pResultRowInfo, &win, (scanFlag == MAIN_SCAN), &pResult, tableGroupId, pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo); if (ret != TSDB_CODE_SUCCESS || pResult == NULL) { - T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY); + T_LONG_JMP(pTaskInfo->env, ret); } TSKEY ekey = ascScan ? win.ekey : win.skey; @@ -827,7 +827,7 @@ static bool hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResul int32_t code = setTimeWindowOutputBuf(pResultRowInfo, &nextWin, (scanFlag == MAIN_SCAN), &pResult, tableGroupId, pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo); if (code != TSDB_CODE_SUCCESS || pResult == NULL) { - T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY); + T_LONG_JMP(pTaskInfo->env, code); } ekey = ascScan ? nextWin.ekey : nextWin.skey; @@ -2271,7 +2271,7 @@ static void doMergeIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo* setTimeWindowOutputBuf(pResultRowInfo, &win, (scanFlag == MAIN_SCAN), &pResult, tableGroupId, pExprSup->pCtx, numOfOutput, pExprSup->rowEntryInfoOffset, &iaInfo->aggSup, pTaskInfo); if (ret != TSDB_CODE_SUCCESS || pResult == NULL) { - T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY); + T_LONG_JMP(pTaskInfo->env, ret); } TSKEY ekey = ascScan ? win.ekey : win.skey; @@ -2312,7 +2312,7 @@ static void doMergeIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo* int32_t code = outputPrevIntervalResult(pOperatorInfo, tableGroupId, pResultBlock, &win); if (code != TSDB_CODE_SUCCESS) { qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code)); - T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY); + T_LONG_JMP(pTaskInfo->env, code); } STimeWindow nextWin = win; @@ -2329,7 +2329,7 @@ static void doMergeIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo* setTimeWindowOutputBuf(pResultRowInfo, &nextWin, (scanFlag == MAIN_SCAN), &pResult, tableGroupId, pExprSup->pCtx, numOfOutput, pExprSup->rowEntryInfoOffset, &iaInfo->aggSup, pTaskInfo); if (code != TSDB_CODE_SUCCESS || pResult == NULL) { - T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY); + T_LONG_JMP(pTaskInfo->env, code); } ekey = ascScan ? nextWin.ekey : nextWin.skey; @@ -2354,7 +2354,7 @@ static void doMergeIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo* code = outputPrevIntervalResult(pOperatorInfo, tableGroupId, pResultBlock, &nextWin); if (code != TSDB_CODE_SUCCESS) { qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code)); - T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY); + T_LONG_JMP(pTaskInfo->env, code); } } diff --git a/source/libs/executor/test/queryPlanTests.cpp b/source/libs/executor/test/queryPlanTests.cpp index 5d397be623..8126e53bd6 100755 --- a/source/libs/executor/test/queryPlanTests.cpp +++ b/source/libs/executor/test/queryPlanTests.cpp @@ -1647,7 +1647,7 @@ SNode* qptMakeDownstreamSrcNode(SNode** ppNode) { pDs->addr.nodeId = qptCtx.param.vnode.vgId; memcpy(&pDs->addr.epSet, &qptCtx.param.vnode.epSet, sizeof(pDs->addr.epSet)); pDs->taskId = (QPT_CORRECT_HIGH_PROB() && qptCtx.buildCtx.pCurrTask) ? qptCtx.buildCtx.pCurrTask->id.taskId : taosRand(); - pDs->schedId = QPT_CORRECT_HIGH_PROB() ? qptCtx.param.schedulerId : taosRand(); + pDs->sId = QPT_CORRECT_HIGH_PROB() ? 0 : taosRand(); pDs->execId = taosRand(); pDs->fetchMsgType = QPT_CORRECT_HIGH_PROB() ? (QPT_RAND_BOOL_V ? TDMT_SCH_FETCH : TDMT_SCH_MERGE_FETCH) : taosRand(); pDs->localExec = QPT_RAND_BOOL_V; @@ -3133,7 +3133,7 @@ void qptExecPlan(SReadHandle* pReadHandle, SNode* pNode, SExecTaskInfo* pTaskInf case QUERY_NODE_PHYSICAL_PLAN_QUERY_INSERT: case QUERY_NODE_PHYSICAL_PLAN_DELETE: { DataSinkHandle handle = NULL; - qptCtx.result.code = dsCreateDataSinker(NULL, (SDataSinkNode*)pNode, &handle, NULL, NULL); + qptCtx.result.code = dsCreateDataSinker(NULL, (SDataSinkNode**)&pNode, &handle, NULL, NULL); dsDestroyDataSinker(handle); break; } diff --git a/source/libs/function/src/tpercentile.c b/source/libs/function/src/tpercentile.c index 73f400c93e..405049fe6f 100644 --- a/source/libs/function/src/tpercentile.c +++ b/source/libs/function/src/tpercentile.c @@ -44,7 +44,7 @@ static int32_t loadDataFromFilePage(tMemBucket *pMemBucket, int32_t slotIdx, SFi pIdList = *(SArray **)p; } else { taosMemoryFree(*buffer); - return TSDB_CODE_OUT_OF_MEMORY; + return terrno; } int32_t offset = 0; diff --git a/source/libs/nodes/src/nodesCloneFuncs.c b/source/libs/nodes/src/nodesCloneFuncs.c index 27c642470d..22f6dc7418 100644 --- a/source/libs/nodes/src/nodesCloneFuncs.c +++ b/source/libs/nodes/src/nodesCloneFuncs.c @@ -836,6 +836,44 @@ static int32_t physiProjectCopy(const SProjectPhysiNode* pSrc, SProjectPhysiNode return TSDB_CODE_SUCCESS; } +static int32_t dataSinkNodeCopy(const SDataSinkNode* pSrc, SDataSinkNode* pDst) { + CLONE_NODE_FIELD_EX(pInputDataBlockDesc, SDataBlockDescNode*); + return TSDB_CODE_SUCCESS; +} + +static int32_t physiDispatchCopy(const SDataDispatcherNode* pSrc, SDataDispatcherNode* pDst) { + COPY_BASE_OBJECT_FIELD(sink, dataSinkNodeCopy); + return TSDB_CODE_SUCCESS; +} + +static int32_t physiInserterCopy(const SDataInserterNode* pSrc, SDataInserterNode* pDst) { + COPY_BASE_OBJECT_FIELD(sink, dataSinkNodeCopy); + return TSDB_CODE_SUCCESS; +} + +static int32_t physiQueryInserterCopy(const SQueryInserterNode* pSrc, SQueryInserterNode* pDst) { + COPY_BASE_OBJECT_FIELD(sink, dataSinkNodeCopy); + CLONE_NODE_LIST_FIELD(pCols); + COPY_SCALAR_FIELD(tableId); + COPY_SCALAR_FIELD(stableId); + COPY_SCALAR_FIELD(tableType); + COPY_CHAR_ARRAY_FIELD(tableName); + COPY_SCALAR_FIELD(vgId); + COPY_OBJECT_FIELD(epSet, sizeof(SEpSet)); + COPY_SCALAR_FIELD(explain); + return TSDB_CODE_SUCCESS; +} + +static int32_t physiDeleterCopy(const SDataDeleterNode* pSrc, SDataDeleterNode* pDst) { + COPY_BASE_OBJECT_FIELD(sink, dataSinkNodeCopy); + COPY_SCALAR_FIELD(tableId); + COPY_SCALAR_FIELD(tableType); + COPY_CHAR_ARRAY_FIELD(tableFName); + COPY_CHAR_ARRAY_FIELD(tsColName); + COPY_OBJECT_FIELD(deleteTimeRange, sizeof(STimeWindow)); + return TSDB_CODE_SUCCESS; +} + static int32_t dataBlockDescCopy(const SDataBlockDescNode* pSrc, SDataBlockDescNode* pDst) { COPY_SCALAR_FIELD(dataBlockId); CLONE_NODE_LIST_FIELD(pSlots); @@ -858,7 +896,7 @@ static int32_t downstreamSourceCopy(const SDownstreamSourceNode* pSrc, SDownstre COPY_OBJECT_FIELD(addr, sizeof(SQueryNodeAddr)); COPY_SCALAR_FIELD(clientId); COPY_SCALAR_FIELD(taskId); - COPY_SCALAR_FIELD(schedId); + COPY_SCALAR_FIELD(sId); COPY_SCALAR_FIELD(execId); COPY_SCALAR_FIELD(fetchMsgType); COPY_SCALAR_FIELD(localExec); @@ -1091,6 +1129,18 @@ int32_t nodesCloneNode(const SNode* pNode, SNode** ppNode) { case QUERY_NODE_PHYSICAL_PLAN_PROJECT: code = physiProjectCopy((const SProjectPhysiNode*)pNode, (SProjectPhysiNode*)pDst); break; + case QUERY_NODE_PHYSICAL_PLAN_DISPATCH: + code = physiDispatchCopy((const SDataDispatcherNode*)pNode, (SDataDispatcherNode*)pDst); + break; + //case QUERY_NODE_PHYSICAL_PLAN_INSERT: + // code = physiInserterCopy((const SDataInserterNode*)pNode, (SDataInserterNode*)pDst); + // break; + case QUERY_NODE_PHYSICAL_PLAN_QUERY_INSERT: + code = physiQueryInserterCopy((const SQueryInserterNode*)pNode, (SQueryInserterNode*)pDst); + break; + case QUERY_NODE_PHYSICAL_PLAN_DELETE: + code = physiDeleterCopy((const SDataDeleterNode*)pNode, (SDataDeleterNode*)pDst); + break; default: break; } diff --git a/source/libs/nodes/src/nodesCodeFuncs.c b/source/libs/nodes/src/nodesCodeFuncs.c index 88f920b47f..c12cef9feb 100644 --- a/source/libs/nodes/src/nodesCodeFuncs.c +++ b/source/libs/nodes/src/nodesCodeFuncs.c @@ -5333,7 +5333,7 @@ static int32_t jsonToColumnDefNode(const SJson* pJson, void* pObj) { static const char* jkDownstreamSourceAddr = "Addr"; static const char* jkDownstreamSourceClientId = "ClientId"; static const char* jkDownstreamSourceTaskId = "TaskId"; -static const char* jkDownstreamSourceSchedId = "SchedId"; +static const char* jkDownstreamSourceSeriousId = "SeriousId"; static const char* jkDownstreamSourceExecId = "ExecId"; static const char* jkDownstreamSourceFetchMsgType = "FetchMsgType"; @@ -5348,7 +5348,7 @@ static int32_t downstreamSourceNodeToJson(const void* pObj, SJson* pJson) { code = tjsonAddIntegerToObject(pJson, jkDownstreamSourceTaskId, pNode->taskId); } if (TSDB_CODE_SUCCESS == code) { - code = tjsonAddIntegerToObject(pJson, jkDownstreamSourceSchedId, pNode->schedId); + code = tjsonAddIntegerToObject(pJson, jkDownstreamSourceSeriousId, pNode->sId); } if (TSDB_CODE_SUCCESS == code) { code = tjsonAddIntegerToObject(pJson, jkDownstreamSourceExecId, pNode->execId); @@ -5371,7 +5371,7 @@ static int32_t jsonToDownstreamSourceNode(const SJson* pJson, void* pObj) { code = tjsonGetUBigIntValue(pJson, jkDownstreamSourceTaskId, &pNode->taskId); } if (TSDB_CODE_SUCCESS == code) { - code = tjsonGetUBigIntValue(pJson, jkDownstreamSourceSchedId, &pNode->schedId); + code = tjsonGetUBigIntValue(pJson, jkDownstreamSourceSeriousId, &pNode->sId); } if (TSDB_CODE_SUCCESS == code) { code = tjsonGetIntValue(pJson, jkDownstreamSourceExecId, &pNode->execId); diff --git a/source/libs/nodes/src/nodesMsgFuncs.c b/source/libs/nodes/src/nodesMsgFuncs.c index 4992c2a06b..930a88aea0 100644 --- a/source/libs/nodes/src/nodesMsgFuncs.c +++ b/source/libs/nodes/src/nodesMsgFuncs.c @@ -1761,7 +1761,7 @@ static int32_t downstreamSourceNodeInlineToMsg(const void* pObj, STlvEncoder* pE code = tlvEncodeValueU64(pEncoder, pNode->taskId); } if (TSDB_CODE_SUCCESS == code) { - code = tlvEncodeValueU64(pEncoder, pNode->schedId); + code = tlvEncodeValueU64(pEncoder, pNode->sId); } if (TSDB_CODE_SUCCESS == code) { code = tlvEncodeValueI32(pEncoder, pNode->execId); @@ -1788,7 +1788,7 @@ static int32_t msgToDownstreamSourceNodeInlineToMsg(STlvDecoder* pDecoder, void* code = tlvDecodeValueU64(pDecoder, &pNode->taskId); } if (TSDB_CODE_SUCCESS == code) { - code = tlvDecodeValueU64(pDecoder, &pNode->schedId); + code = tlvDecodeValueU64(pDecoder, &pNode->sId); } if (TSDB_CODE_SUCCESS == code) { code = tlvDecodeValueI32(pDecoder, &pNode->execId); diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c index 847b921ddf..4baddf5362 100644 --- a/source/libs/nodes/src/nodesUtilFuncs.c +++ b/source/libs/nodes/src/nodesUtilFuncs.c @@ -1079,7 +1079,7 @@ void nodesDestroyNode(SNode* pNode) { taosMemoryFreeClear(pReal->pMeta); taosMemoryFreeClear(pReal->pVgroupList); taosArrayDestroyEx(pReal->pSmaIndexes, destroySmaIndex); - taosArrayDestroyP(pReal->tsmaTargetTbVgInfo, taosMemoryFree); + taosArrayDestroyP(pReal->tsmaTargetTbVgInfo, NULL); taosArrayDestroy(pReal->tsmaTargetTbInfo); break; } @@ -1627,7 +1627,7 @@ void nodesDestroyNode(SNode* pNode) { nodesDestroyList(pLogicNode->pTags); nodesDestroyNode(pLogicNode->pSubtable); taosArrayDestroyEx(pLogicNode->pFuncTypes, destroyFuncParam); - taosArrayDestroyP(pLogicNode->pTsmaTargetTbVgInfo, taosMemoryFree); + taosArrayDestroyP(pLogicNode->pTsmaTargetTbVgInfo, NULL); taosArrayDestroy(pLogicNode->pTsmaTargetTbInfo); break; } @@ -2012,7 +2012,7 @@ int32_t nodesMakeList(SNodeList** ppListOut) { int32_t nodesListAppend(SNodeList* pList, SNode* pNode) { if (NULL == pList || NULL == pNode) { - return TSDB_CODE_FAILED; + return TSDB_CODE_INVALID_PARA; } SListCell* p = NULL; int32_t code = nodesCalloc(1, sizeof(SListCell), (void**)&p); diff --git a/source/libs/parser/src/parAstParser.c b/source/libs/parser/src/parAstParser.c index 3aa60c283e..e122c922ba 100644 --- a/source/libs/parser/src/parAstParser.c +++ b/source/libs/parser/src/parAstParser.c @@ -46,7 +46,7 @@ int32_t buildQueryAfterParse(SQuery** pQuery, SNode* pRootNode, int16_t placehol int32_t parse(SParseContext* pParseCxt, SQuery** pQuery) { SAstCreateContext cxt; initAstCreateContext(pParseCxt, &cxt); - void* pParser = ParseAlloc((FMalloc)taosMemoryMalloc); + void* pParser = ParseAlloc((FMalloc)taosMemMalloc); if (!pParser) return terrno; int32_t i = 0; while (1) { @@ -88,7 +88,7 @@ int32_t parse(SParseContext* pParseCxt, SQuery** pQuery) { } abort_parse: - ParseFree(pParser, (FFree)taosMemoryFree); + ParseFree(pParser, (FFree)taosAutoMemoryFree); if (TSDB_CODE_SUCCESS == cxt.errCode) { int32_t code = buildQueryAfterParse(pQuery, cxt.pRootNode, cxt.placeholderNo, &cxt.pPlaceholderValues); if (TSDB_CODE_SUCCESS != code) { diff --git a/source/libs/parser/src/parInsertSql.c b/source/libs/parser/src/parInsertSql.c index c5e9ad4ae4..9090ae7a4d 100644 --- a/source/libs/parser/src/parInsertSql.c +++ b/source/libs/parser/src/parInsertSql.c @@ -1852,7 +1852,7 @@ static int32_t doGetStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* tstrncpy(pStmt->usingTableName.dbname, pStmt->targetTableName.dbname, sizeof(pStmt->usingTableName.dbname)); pStmt->usingTableName.type = 1; - + pStmt->pTableMeta->tableType = TSDB_CHILD_TABLE; // set the table type to child table for parse cache *bFoundTbName = true; } } else if (pCols->pColIndex[i] < numOfCols) { diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 6313eaf383..d1675ee1cc 100755 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -4322,7 +4322,7 @@ static int32_t setTableTsmas(STranslateContext* pCxt, SName* pName, SRealTableNo if (TSDB_CODE_SUCCESS == code && pRealTable->pTsmas && (pRealTable->pMeta->tableType == TSDB_CHILD_TABLE || pRealTable->pMeta->tableType == TSDB_NORMAL_TABLE)) { if (pRealTable->tsmaTargetTbVgInfo) { - taosArrayDestroyP(pRealTable->tsmaTargetTbVgInfo, taosMemoryFree); + taosArrayDestroyP(pRealTable->tsmaTargetTbVgInfo, NULL); pRealTable->tsmaTargetTbVgInfo = NULL; } char buf[TSDB_TABLE_FNAME_LEN + TSDB_TABLE_NAME_LEN + 1]; @@ -6926,7 +6926,7 @@ static int32_t setEqualTbnameTableVgroups(STranslateContext* pCxt, SSelectStmt* taosMemoryFreeClear(vgsInfo); } } - taosArrayDestroyP(pTbNames, taosMemoryFree); + taosArrayDestroyP(pTbNames, NULL); if (code) break; } if (TSDB_CODE_SUCCESS != code) { diff --git a/source/libs/qcom/src/queryUtil.c b/source/libs/qcom/src/queryUtil.c index 22141c33ee..690d38aac0 100644 --- a/source/libs/qcom/src/queryUtil.c +++ b/source/libs/qcom/src/queryUtil.c @@ -625,7 +625,7 @@ int32_t cloneDbVgInfo(SDBVgInfo* pSrc, SDBVgInfo** pDst) { qError("taosHashPut failed, vgId:%d", vgInfo->vgId); taosHashCancelIterate(pSrc->vgHash, pIter); freeVgInfo(*pDst); - return TSDB_CODE_OUT_OF_MEMORY; + return terrno; } pIter = taosHashIterate(pSrc->vgHash, pIter); diff --git a/source/libs/qcom/src/querymsg.c b/source/libs/qcom/src/querymsg.c index 9d9c169c05..0ee61726e3 100644 --- a/source/libs/qcom/src/querymsg.c +++ b/source/libs/qcom/src/querymsg.c @@ -64,7 +64,7 @@ int32_t queryBuildUseDbOutput(SUseDbOutput *pOut, SUseDbRsp *usedbRsp) { qDebug("the %dth vgroup, id %d, epNum %d, current %s port %d", i, pVgInfo->vgId, pVgInfo->epSet.numOfEps, pVgInfo->epSet.eps[pVgInfo->epSet.inUse].fqdn, pVgInfo->epSet.eps[pVgInfo->epSet.inUse].port); if (0 != taosHashPut(pOut->dbVgroup->vgHash, &pVgInfo->vgId, sizeof(int32_t), pVgInfo, sizeof(SVgroupInfo))) { - return TSDB_CODE_OUT_OF_MEMORY; + return terrno; } } diff --git a/source/libs/qworker/inc/qwInt.h b/source/libs/qworker/inc/qwInt.h index 6d81baf91a..53e1c3d288 100644 --- a/source/libs/qworker/inc/qwInt.h +++ b/source/libs/qworker/inc/qwInt.h @@ -28,6 +28,7 @@ extern "C" { #include "tref.h" #include "trpc.h" #include "ttimer.h" +#include "theap.h" #define QW_DEFAULT_SCHEDULER_NUMBER 100 #define QW_DEFAULT_TASK_NUMBER 10000 @@ -37,6 +38,24 @@ extern "C" { #define QW_SCH_TIMEOUT_MSEC 180000 #define QW_MIN_RES_ROWS 16384 +#define QW_THREAD_MAX_SCHED_TASK_NUM 10 + +#define QW_QUERY_MEM_POOL_NAME "Query" +#define QW_MAX_RETIRE_JOB_NUM 10000 + +#define QW_DEFAULT_THREAD_TASK_NUM 3 + +#define QW_RETIRE_JOB_BATCH_NUM 5 + +#define QW_DEFAULT_TIMEOUT_INTERVAL_SECS 600 + +enum { + QW_CONC_TASK_LEVEL_LOW = 1, + QW_CONC_TASK_LEVEL_MIDDLE, + QW_CONC_TASK_LEVEL_HIGH, + QW_CONC_TASK_LEVEL_FULL +}; + enum { QW_PHASE_PRE_QUERY = 1, QW_PHASE_POST_QUERY, @@ -112,6 +131,27 @@ typedef struct SQWTaskStatus { int8_t status; } SQWTaskStatus; +typedef struct SQWSessionInfo { + void *mgmt; + uint64_t sId; + uint64_t qId; + uint64_t cId; + uint64_t tId; + int64_t rId; + int32_t eId; + void *sessionMp; +} SQWSessionInfo; + +typedef struct SQWJobInfo { + int8_t retired; + int32_t errCode; + SMemPoolJob* memInfo; + + SRWLatch lock; + int8_t destroyed; + SHashObj* pSessions; +} SQWJobInfo; + typedef struct SQWTaskCtx { SRWLatch lock; int8_t phase; @@ -134,6 +174,7 @@ typedef struct SQWTaskCtx { bool queryExecDone; bool queryInQueue; bool explainRsped; + bool sinkWithMemPool; int32_t rspCode; int64_t affectedRows; // for insert ...select stmt @@ -142,10 +183,15 @@ typedef struct SQWTaskCtx { int8_t events[QW_EVENT_MAX]; - SArray *explainRes; - void *taskHandle; - void *sinkHandle; - SArray *tbInfo; // STbVerInfo + SArray *explainRes; + void *taskHandle; + void *sinkHandle; + SArray *tbInfo; // STbVerInfo + + int64_t lastAckTs; + + void *memPoolSession; + SQWJobInfo *pJobInfo; } SQWTaskCtx; typedef struct SQWSchStatus { @@ -201,7 +247,8 @@ typedef struct SQWorker { SQWStat stat; int32_t *destroyed; - int8_t nodeStopped; + int8_t nodeStopped; + int32_t lastChkTs; } SQWorker; typedef struct SQWorkerMgmt { @@ -212,13 +259,43 @@ typedef struct SQWorkerMgmt { int32_t paramIdx; } SQWorkerMgmt; -#define QW_CTX_NOT_EXISTS_ERR_CODE(mgmt) \ - (atomic_load_8(&(mgmt)->nodeStopped) ? TSDB_CODE_VND_STOPPED : TSDB_CODE_QRY_TASK_CTX_NOT_EXIST) + +typedef struct SQWRetireCtx { + BoundedQueue* pJobQueue; +} SQWRetireCtx; + +typedef struct SQueryExecStat { + int64_t taskInitNum; + int64_t taskRunNum; + int64_t taskExecDestroyNum; + int64_t taskSinkDestroyNum; + int64_t taskDestroyNum; +} SQueryExecStat; + +typedef struct SQueryMgmt { + SRWLatch taskMgmtLock; + int32_t concTaskLevel; + SHashObj* pJobInfo; + SQueryExecStat stat; +} SQueryMgmt; + +#define QW_CTX_NOT_EXISTS_ERR_CODE(mgmt) (atomic_load_8(&(mgmt)->nodeStopped) ? TSDB_CODE_VND_STOPPED : TSDB_CODE_QRY_TASK_CTX_NOT_EXIST) #define QW_FPARAMS_DEF SQWorker *mgmt, uint64_t sId, uint64_t qId, uint64_t cId, uint64_t tId, int64_t rId, int32_t eId #define QW_IDS() sId, qId, cId, tId, rId, eId #define QW_FPARAMS() mgmt, QW_IDS() +extern SQueryMgmt gQueryMgmt; + +#define QW_SINK_ENABLE_MEMPOOL(_ctx) \ + do { \ + if ((_ctx)->sinkWithMemPool) { \ + taosEnableMemPoolUsage((_ctx)->memPoolSession); \ + } \ + } while (0) + +#define QW_SINK_DISABLE_MEMPOOL() taosDisableMemPoolUsage() + #define QW_STAT_INC(_item, _n) (void)atomic_add_fetch_64(&(_item), _n) #define QW_STAT_DEC(_item, _n) (void)atomic_sub_fetch_64(&(_item), _n) #define QW_STAT_GET(_item) atomic_load_64(&(_item)) @@ -257,6 +334,19 @@ typedef struct SQWorkerMgmt { #define QW_FETCH_RUNNING(ctx) ((ctx)->inFetch) #define QW_QUERY_NOT_STARTED(ctx) (QW_GET_PHASE(ctx) == -1) +#define QW_SET_QCID(id, qId, cId) \ + do { \ + *(uint64_t *)(id) = (qId); \ + *(uint64_t *)((char *)(id) + sizeof(qId)) = (cId); \ + } while (0) + +#define QW_GET_QCID(id, qId, cId) \ + do { \ + (qId) = *(uint64_t *)(id); \ + (cId) = *(uint64_t *)((char *)(id) + sizeof(qId)); \ + } while (0) + + #define QW_SET_QTID(id, qId, cId, tId, eId) \ do { \ *(uint64_t *)(id) = (qId); \ @@ -273,6 +363,18 @@ typedef struct SQWorkerMgmt { (eId) = *(int32_t *)((char *)(id) + sizeof(qId) + sizeof(cId) + sizeof(tId)); \ } while (0) +#define QW_SET_TEID(id, tId, eId) \ + do { \ + *(uint64_t *)(id) = (tId); \ + *(uint32_t *)((char *)(id) + sizeof(tId)) = (eId); \ + } while (0) + +#define QW_GET_TEID(id, tId, eId) \ + do { \ + (tId) = *(uint64_t *)(id); \ + (eId) = *(uint32_t *)((char *)(id) + sizeof(tId)); \ + } while (0) + #define QW_ERR_RET(c) \ do { \ int32_t _code = (c); \ @@ -309,33 +411,33 @@ typedef struct SQWorkerMgmt { } \ } while (0) -#define QW_SCH_ELOG(param, ...) qError("QW:%p SID:%" PRIx64 " " param, mgmt, sId, __VA_ARGS__) -#define QW_SCH_DLOG(param, ...) qDebug("QW:%p SID:%" PRIx64 " " param, mgmt, sId, __VA_ARGS__) +#define QW_SCH_ELOG(param, ...) qError("QW:%p clientId:%" PRIx64 " " param, mgmt, clientId, __VA_ARGS__) +#define QW_SCH_DLOG(param, ...) qDebug("QW:%p clientId:%" PRIx64 " " param, mgmt, clientId, __VA_ARGS__) #define QW_TASK_ELOG(param, ...) \ - qError("QID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, qId, cId, tId, eId, __VA_ARGS__) + qError("QID:0x%" PRIx64 ",SID:%" PRId64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, qId, sId, cId, tId, eId, __VA_ARGS__) #define QW_TASK_WLOG(param, ...) \ - qWarn("QID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, qId, cId, tId, eId, __VA_ARGS__) + qWarn("QID:0x%" PRIx64 ",SID:%" PRId64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, qId, sId, cId, tId, eId, __VA_ARGS__) #define QW_TASK_DLOG(param, ...) \ - qDebug("QID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, qId, cId, tId, eId, __VA_ARGS__) + qDebug("QID:0x%" PRIx64 ",SID:%" PRId64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, qId, sId, cId, tId, eId, __VA_ARGS__) #define QW_TASK_DLOGL(param, ...) \ - qDebugL("QID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, qId, cId, tId, eId, __VA_ARGS__) + qDebugL("QID:0x%" PRIx64 ",SID:%" PRId64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, qId, sId, cId, tId, eId, __VA_ARGS__) #define QW_TASK_ELOG_E(param) \ - qError("QID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, qId, cId, tId, eId) + qError("QID:0x%" PRIx64 ",SID:%" PRId64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, qId, sId, cId, tId, eId) #define QW_TASK_WLOG_E(param) \ - qWarn("QID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, qId, cId, tId, eId) + qWarn("QID:0x%" PRIx64 ",SID:%" PRId64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, qId, sId, cId, tId, eId) #define QW_TASK_DLOG_E(param) \ - qDebug("QID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, qId, cId, tId, eId) + qDebug("QID:0x%" PRIx64 ",SID:%" PRId64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, qId, sId, cId, tId, eId) #define QW_SCH_TASK_ELOG(param, ...) \ - qError("QW:%p SID:0x%" PRIx64 ",QID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, mgmt, sId, \ + qError("QW:%p SID:%" PRId64 ",QID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, mgmt, sId, \ qId, cId, tId, eId, __VA_ARGS__) #define QW_SCH_TASK_WLOG(param, ...) \ - qWarn("QW:%p SID:0x%" PRIx64 ",QID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, mgmt, sId, qId, \ + qWarn("QW:%p SID:%" PRId64 ",QID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, mgmt, sId, qId, \ cId, tId, eId, __VA_ARGS__) #define QW_SCH_TASK_DLOG(param, ...) \ - qDebug("QW:%p SID:0x%" PRIx64 ",QID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, mgmt, sId, \ + qDebug("QW:%p SID:%" PRId64 ",QID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, mgmt, sId, \ qId, cId, tId, eId, __VA_ARGS__) #define QW_LOCK_DEBUG(...) \ @@ -414,7 +516,7 @@ static FORCE_INLINE int32_t qwRelease(int64_t refId) { return taosReleaseRef(gQw char *qwPhaseStr(int32_t phase); char *qwBufStatusStr(int32_t bufStatus); -int32_t qwAcquireAddScheduler(SQWorker *mgmt, uint64_t sId, int32_t rwType, SQWSchStatus **sch); +int32_t qwAcquireAddScheduler(SQWorker *mgmt, uint64_t clientId, int32_t rwType, SQWSchStatus **sch); void qwReleaseScheduler(int32_t rwType, SQWorker *mgmt); int32_t qwAddTaskStatus(QW_FPARAMS_DEF, int32_t status); int32_t qwAcquireTaskCtx(QW_FPARAMS_DEF, SQWTaskCtx **ctx); @@ -430,10 +532,11 @@ void qwSetHbParam(int64_t refId, SQWHbParam **pParam); int32_t qwUpdateTimeInQueue(SQWorker *mgmt, int64_t ts, EQueueType type); int64_t qwGetTimeInQueue(SQWorker *mgmt, EQueueType type); void qwClearExpiredSch(SQWorker *mgmt, SArray *pExpiredSch); -int32_t qwAcquireScheduler(SQWorker *mgmt, uint64_t sId, int32_t rwType, SQWSchStatus **sch); -void qwFreeTaskCtx(SQWTaskCtx *ctx); +int32_t qwAcquireScheduler(SQWorker *mgmt, uint64_t clientId, int32_t rwType, SQWSchStatus **sch); +void qwFreeTaskCtx(QW_FPARAMS_DEF, SQWTaskCtx *ctx); int32_t qwHandleTaskComplete(QW_FPARAMS_DEF, SQWTaskCtx *ctx); +void qwDbgDumpJobsInfo(void); void qwDbgDumpMgmtInfo(SQWorker *mgmt); int32_t qwDbgValidateStatus(QW_FPARAMS_DEF, int8_t oriStatus, int8_t newStatus, bool *ignore, bool dynamicTask); int32_t qwDbgBuildAndSendRedirectRsp(int32_t rspType, SRpcHandleInfo *pConn, int32_t code, SEpSet *pEpSet); @@ -442,6 +545,16 @@ void qwDbgSimulateRedirect(SQWMsg *qwMsg, SQWTaskCtx *ctx, bool *rsped); void qwDbgSimulateSleep(void); void qwDbgSimulateDead(QW_FPARAMS_DEF, SQWTaskCtx *ctx, bool *rsped); int32_t qwSendExplainResponse(QW_FPARAMS_DEF, SQWTaskCtx *ctx); +int32_t qwInitQueryPool(void); +void qwDestroyJobInfo(void* job); +bool qwStopTask(QW_FPARAMS_DEF, SQWTaskCtx *ctx, bool forceStop, int32_t errCode); +void qwStopAllTasks(SQWorker *mgmt); +void qwChkDropTimeoutQuery(SQWorker *mgmt, int32_t currTs); +bool qwRetireJob(SQWJobInfo* pJob); +void qwDestroySession(QW_FPARAMS_DEF, SQWJobInfo *pJobInfo, void* session); +int32_t qwInitSession(QW_FPARAMS_DEF, SQWTaskCtx *ctx, void** ppSession); +void qwFreeTaskHandle(SQWTaskCtx *ctx); +void qwFreeSinkHandle(SQWTaskCtx *ctx); #ifdef __cplusplus } diff --git a/source/libs/qworker/inc/qwMsg.h b/source/libs/qworker/inc/qwMsg.h index 6d57a3df46..366b9d09f1 100644 --- a/source/libs/qworker/inc/qwMsg.h +++ b/source/libs/qworker/inc/qwMsg.h @@ -36,7 +36,7 @@ int32_t qwProcessDelete(QW_FPARAMS_DEF, SQWMsg *qwMsg, SDeleteRes *pRes); int32_t qwBuildAndSendDropRsp(SRpcHandleInfo *pConn, int32_t code); int32_t qwBuildAndSendCancelRsp(SRpcHandleInfo *pConn, int32_t code); -int32_t qwBuildAndSendFetchRsp(int32_t rspType, SRpcHandleInfo *pConn, SRetrieveTableRsp *pRsp, int32_t dataLength, +int32_t qwBuildAndSendFetchRsp(SQWTaskCtx *ctx, int32_t rspType, SRpcHandleInfo *pConn, SRetrieveTableRsp *pRsp, int32_t dataLength, int32_t code); void qwBuildFetchRsp(void *msg, SOutputData *input, int32_t len, int32_t rawDataLen, bool qComplete); int32_t qwBuildAndSendCQueryMsg(QW_FPARAMS_DEF, SRpcHandleInfo *pConn); @@ -47,7 +47,7 @@ void qwFreeFetchRsp(void *msg); int32_t qwMallocFetchRsp(int8_t rpcMalloc, int32_t length, SRetrieveTableRsp **rsp); int32_t qwBuildAndSendHbRsp(SRpcHandleInfo *pConn, SSchedulerHbRsp *rsp, int32_t code); int32_t qwRegisterQueryBrokenLinkArg(QW_FPARAMS_DEF, SRpcHandleInfo *pConn); -int32_t qwRegisterHbBrokenLinkArg(SQWorker *mgmt, uint64_t sId, SRpcHandleInfo *pConn); +int32_t qwRegisterHbBrokenLinkArg(SQWorker *mgmt, uint64_t clientId, SRpcHandleInfo *pConn); int32_t qwBuildAndSendDropMsg(QW_FPARAMS_DEF, SRpcHandleInfo *pConn); #ifdef __cplusplus diff --git a/source/libs/qworker/src/qwDbg.c b/source/libs/qworker/src/qwDbg.c index 5cef253cae..f4015ea28d 100644 --- a/source/libs/qworker/src/qwDbg.c +++ b/source/libs/qworker/src/qwDbg.c @@ -100,7 +100,7 @@ void qwDbgDumpSchInfo(SQWorker *mgmt, SQWSchStatus *sch, int32_t i) { int32_t taskNum = taosHashGetSize(sch->tasksHash); QW_DLOG("***The %dth scheduler status, hbBrokenTs:%" PRId64 ",taskNum:%d", i, sch->hbBrokenTs, taskNum); - uint64_t qId, cId, tId; + uint64_t qId, cId, tId, sId = 0; int32_t eId; SQWTaskStatus *pTask = NULL; void *pIter = taosHashIterate(sch->tasksHash, NULL); @@ -122,19 +122,20 @@ void qwDbgDumpTasksInfo(SQWorker *mgmt) { int32_t i = 0; SQWTaskCtx *ctx = NULL; - uint64_t qId, cId, tId; + uint64_t qId, cId, tId, sId; int32_t eId; void *pIter = taosHashIterate(mgmt->ctxHash, NULL); while (pIter) { ctx = (SQWTaskCtx *)pIter; void *key = taosHashGetKey(pIter, NULL); QW_GET_QTID(key, qId, cId, tId, eId); + sId = ctx->sId; QW_TASK_DLOG("%p lock:%x, phase:%d, type:%d, explain:%d, needFetch:%d, localExec:%d, queryMsgType:%d, " - "sId:%" PRId64 ", level:%d, queryGotData:%d, queryRsped:%d, queryEnd:%d, queryContinue:%d, queryInQueue:%d, " + "level:%d, queryGotData:%d, queryRsped:%d, queryEnd:%d, queryContinue:%d, queryInQueue:%d, " "rspCode:%x, affectedRows:%" PRId64 ", taskHandle:%p, sinkHandle:%p, tbNum:%d, events:%d,%d,%d,%d,%d", ctx, ctx->lock, ctx->phase, ctx->taskType, ctx->explain, ctx->needFetch, ctx->localExec, ctx->queryMsgType, - ctx->sId, ctx->level, ctx->queryGotData, ctx->queryRsped, ctx->queryEnd, ctx->queryContinue, + ctx->level, ctx->queryGotData, ctx->queryRsped, ctx->queryEnd, ctx->queryContinue, ctx->queryInQueue, ctx->rspCode, ctx->affectedRows, ctx->taskHandle, ctx->sinkHandle, (int32_t)taosArrayGetSize(ctx->tbInfo), 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]); @@ -171,6 +172,37 @@ void qwDbgDumpMgmtInfo(SQWorker *mgmt) { qwDbgDumpTasksInfo(mgmt); } +void qwDbgDumpJobsInfo(void) { + if (!gQWDebug.dumpEnable) { + return; + } + + qDebug("total remain job num %d, task initNum:%" PRId64 " - %" PRId64 ", task destroyNum:%" PRId64 " - %" PRId64 " - %" PRId64, + taosHashGetSize(gQueryMgmt.pJobInfo), atomic_load_64(&gQueryMgmt.stat.taskInitNum), atomic_load_64(&gQueryMgmt.stat.taskRunNum), + atomic_load_64(&gQueryMgmt.stat.taskExecDestroyNum), atomic_load_64(&gQueryMgmt.stat.taskSinkDestroyNum), + atomic_load_64(&gQueryMgmt.stat.taskDestroyNum)); + + size_t keyLen = 0; + char* id = NULL; + int32_t jobIdx = 0; + SQWJobInfo* pJob = (SQWJobInfo*)taosHashIterate(gQueryMgmt.pJobInfo, NULL); + while (NULL != pJob) { + qDebug("QID:0x%" PRIx64 " CID:0x%" PRIx64 " the %dth remain job", pJob->memInfo->jobId, pJob->memInfo->clientId, jobIdx++); + + int32_t sessionIdx = 0; + SQWSessionInfo* pSession = (SQWSessionInfo*)taosHashIterate(pJob->pSessions, NULL); + while (NULL != pSession) { + qDebug("QID:0x%" PRIx64 ",SID:%" PRId64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d the %dth remain session", + pSession->qId, pSession->sId, pSession->cId, pSession->tId, pSession->eId, sessionIdx++); + + pSession = (SQWSessionInfo*)taosHashIterate(pJob->pSessions, pSession); + } + + pJob = (SQWJobInfo *)taosHashIterate(gQueryMgmt.pJobInfo, pJob); + } +} + + int32_t qwDbgBuildAndSendRedirectRsp(int32_t rspType, SRpcHandleInfo *pConn, int32_t code, SEpSet *pEpSet) { int32_t contLen = 0; char *rsp = NULL; diff --git a/source/libs/qworker/src/qwMem.c b/source/libs/qworker/src/qwMem.c new file mode 100644 index 0000000000..5d69e14260 --- /dev/null +++ b/source/libs/qworker/src/qwMem.c @@ -0,0 +1,213 @@ +#include "qwInt.h" +#include "qworker.h" + +void qwSetConcurrentTaskNumCb(int32_t taskNum) { + int32_t finTaskNum = TMIN(taskNum, tsNumOfQueryThreads * QW_DEFAULT_THREAD_TASK_NUM); + + if (tsQueryMaxConcurrentTaskNum > 0) { + finTaskNum = TMIN(taskNum, tsQueryMaxConcurrentTaskNum); + } + finTaskNum = TMAX(finTaskNum, tsQueryMinConcurrentTaskNum); + + atomic_store_32(&tsQueryConcurrentTaskNum, finTaskNum); + + atomic_store_32(&gQueryMgmt.concTaskLevel, QW_CONC_TASK_LEVEL_FULL); +} + +void qwDecConcurrentTaskNumCb(void) { + int32_t concTaskLevel = atomic_load_32(&gQueryMgmt.concTaskLevel); + if (concTaskLevel <= QW_CONC_TASK_LEVEL_LOW) { + qError("Unable to decrease concurrent task num, current task level:%d", concTaskLevel); + return; + } + + //TODO +} + +void qwIncConcurrentTaskNumCb(void) { + int32_t concTaskLevel = atomic_load_32(&gQueryMgmt.concTaskLevel); + if (concTaskLevel >= QW_CONC_TASK_LEVEL_FULL) { + qError("Unable to increase concurrent task num, current task level:%d", concTaskLevel); + return; + } + + //TODO +} + +int32_t qwInitJobInfo(QW_FPARAMS_DEF, SQWJobInfo* pJob) { + pJob->pSessions= taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK); + if (NULL == pJob->pSessions) { + QW_TASK_ELOG("fail to init session hash, code: 0x%x", terrno); + return terrno; + } + + int32_t code = taosMemPoolCallocJob(qId, cId, (void**)&pJob->memInfo); + if (TSDB_CODE_SUCCESS != code) { + taosHashCleanup(pJob->pSessions); + pJob->pSessions = NULL; + return code; + } + + return code; +} + + +int32_t qwInitJobHash(void) { + int32_t code = TSDB_CODE_SUCCESS; + SHashObj* pHash = NULL; + + if (NULL == atomic_load_ptr(&gQueryMgmt.pJobInfo)) { + pHash = taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK); + if (NULL == pHash) { + qError("init job hash failed, error:0x%x", terrno); + return terrno; + } + + if (NULL != atomic_val_compare_exchange_ptr(&gQueryMgmt.pJobInfo, NULL, pHash)) { + taosHashCleanup(pHash); + return code; + } + + taosHashSetFreeFp(gQueryMgmt.pJobInfo, qwDestroyJobInfo); + } + + return code; +} + + +void qwDestroySession(QW_FPARAMS_DEF, SQWJobInfo *pJobInfo, void* session) { + char id[sizeof(tId) + sizeof(eId) + 1] = {0}; + QW_SET_TEID(id, tId, eId); + + (void)taosHashRemove(pJobInfo->pSessions, id, sizeof(id)); + + taosMemPoolDestroySession(gMemPoolHandle, session); + + int32_t remainSessions = atomic_sub_fetch_32(&pJobInfo->memInfo->remainSession, 1); + + QW_TASK_DLOG("task session destoryed, remainSessions:%d", remainSessions); + + if (0 == remainSessions) { + QW_LOCK(QW_WRITE, &pJobInfo->lock); + if (/*0 == taosHashGetSize(pJobInfo->pSessions) && */0 == atomic_load_32(&pJobInfo->memInfo->remainSession)) { + atomic_store_8(&pJobInfo->destroyed, 1); + QW_UNLOCK(QW_WRITE, &pJobInfo->lock); + + char id2[sizeof(qId) + sizeof(cId) + 1] = {0}; + QW_SET_QCID(id2, qId, cId); + (void)taosHashRemove(gQueryMgmt.pJobInfo, id2, sizeof(id2)); + + QW_TASK_DLOG_E("the whole query job removed"); + } else { + QW_TASK_DLOG("job not removed, remainSessions:%d, %d", taosHashGetSize(pJobInfo->pSessions), pJobInfo->memInfo->remainSession); + QW_UNLOCK(QW_WRITE, &pJobInfo->lock); + } + } +} + +int32_t qwRetrieveJobInfo(QW_FPARAMS_DEF, SQWJobInfo** ppJob) { + int32_t code = TSDB_CODE_SUCCESS; + SQWJobInfo* pJob = NULL; + char id[sizeof(qId) + sizeof(cId) + 1] = {0}; + + if (NULL == gQueryMgmt.pJobInfo) { + QW_ERR_RET(qwInitJobHash()); + } + + QW_SET_QCID(id, qId, cId); + + while (true) { + pJob = (SQWJobInfo*)taosHashAcquire(gQueryMgmt.pJobInfo, id, sizeof(id)); + if (NULL == pJob) { + SQWJobInfo jobInfo = {0}; + code = qwInitJobInfo(QW_FPARAMS(), &jobInfo); + if (TSDB_CODE_SUCCESS != code) { + return code; + } + + code = taosHashPut(gQueryMgmt.pJobInfo, id, sizeof(id), &jobInfo, sizeof(jobInfo)); + if (TSDB_CODE_SUCCESS != code) { + qwDestroyJobInfo(&jobInfo); + if (TSDB_CODE_DUP_KEY == code) { + code = TSDB_CODE_SUCCESS; + continue; + } + + QW_TASK_ELOG("fail to put job to job hash, error: %s", tstrerror(code)); + return code; + } + + QW_TASK_DLOG_E("job added to hash"); + + pJob = (SQWJobInfo*)taosHashAcquire(gQueryMgmt.pJobInfo, id, sizeof(id)); + if (NULL == pJob) { + QW_TASK_WLOG_E("job not in job hash, may be dropped"); + continue; + } + } + + QW_LOCK(QW_READ, &pJob->lock); + if (atomic_load_8(&pJob->destroyed)) { + QW_UNLOCK(QW_READ, &pJob->lock); + continue; + } + + atomic_add_fetch_32(&pJob->memInfo->remainSession, 1); + QW_UNLOCK(QW_READ, &pJob->lock); + + break; + } + + *ppJob = pJob; + + return code; +} + +int32_t qwInitSession(QW_FPARAMS_DEF, SQWTaskCtx *ctx, void** ppSession) { + int32_t code = TSDB_CODE_SUCCESS; + SQWJobInfo* pJob = NULL; + SQWSessionInfo session = {.mgmt = mgmt, + .sId = sId, + .qId = qId, + .cId = cId, + .tId = tId, + .rId = rId, + .eId = eId + }; + + do { + QW_ERR_JRET(qwRetrieveJobInfo(QW_FPARAMS(), &pJob)); + + ctx->pJobInfo = pJob; + + char id[sizeof(tId) + sizeof(eId) + 1] = {0}; + QW_SET_TEID(id, tId, eId); + + QW_ERR_JRET(taosMemPoolInitSession(gMemPoolHandle, ppSession, pJob->memInfo, id)); + session.sessionMp = *ppSession; + + code = taosHashPut(pJob->pSessions, id, sizeof(id), &session, sizeof(session)); + if (TSDB_CODE_SUCCESS != code) { + QW_TASK_ELOG("fail to put session into query session hash, code: 0x%x", code); + QW_ERR_JRET(code); + } + + break; + } while (true); + + QW_TASK_DLOG_E("session initialized"); + +_return: + + if (NULL != pJob) { + if (TSDB_CODE_SUCCESS != code) { + qwDestroySession(QW_FPARAMS(), pJob, *ppSession); + } + + taosHashRelease(gQueryMgmt.pJobInfo, pJob); + } + + return code; +} + + diff --git a/source/libs/qworker/src/qwMsg.c b/source/libs/qworker/src/qwMsg.c index 7dbad90cc0..0452a05fe4 100644 --- a/source/libs/qworker/src/qwMsg.c +++ b/source/libs/qworker/src/qwMsg.c @@ -73,7 +73,7 @@ int32_t qwBuildAndSendQueryRsp(int32_t rspType, SRpcHandleInfo *pConn, int32_t c int32_t msgSize = tSerializeSQueryTableRsp(NULL, 0, &rsp); if (msgSize < 0) { qError("tSerializeSQueryTableRsp failed"); - QW_RET(TSDB_CODE_OUT_OF_MEMORY); + QW_RET(msgSize); } void *pRsp = rpcMallocCont(msgSize); @@ -82,9 +82,10 @@ int32_t qwBuildAndSendQueryRsp(int32_t rspType, SRpcHandleInfo *pConn, int32_t c QW_RET(terrno); } - if (tSerializeSQueryTableRsp(pRsp, msgSize, &rsp) < 0) { + msgSize = tSerializeSQueryTableRsp(pRsp, msgSize, &rsp); + if (msgSize < 0) { qError("tSerializeSQueryTableRsp %d failed", msgSize); - QW_RET(TSDB_CODE_OUT_OF_MEMORY); + QW_RET(msgSize); } SRpcMsg rpcRsp = { @@ -162,7 +163,7 @@ int32_t qwBuildAndSendHbRsp(SRpcHandleInfo *pConn, SSchedulerHbRsp *pStatus, int return TSDB_CODE_SUCCESS; } -int32_t qwBuildAndSendFetchRsp(int32_t rspType, SRpcHandleInfo *pConn, SRetrieveTableRsp *pRsp, int32_t dataLength, +int32_t qwBuildAndSendFetchRsp(SQWTaskCtx *ctx, int32_t rspType, SRpcHandleInfo *pConn, SRetrieveTableRsp *pRsp, int32_t dataLength, int32_t code) { if (NULL == pRsp) { pRsp = (SRetrieveTableRsp *)rpcMallocCont(sizeof(SRetrieveTableRsp)); @@ -184,6 +185,10 @@ int32_t qwBuildAndSendFetchRsp(int32_t rspType, SRpcHandleInfo *pConn, SRetrieve rpcRsp.info.compressed = pRsp->compressed; tmsgSendRsp(&rpcRsp); + if (NULL != ctx) { + ctx->lastAckTs = taosGetTimestampSec(); + } + return TSDB_CODE_SUCCESS; } @@ -241,7 +246,7 @@ int32_t qwBuildAndSendDropMsg(QW_FPARAMS_DEF, SRpcHandleInfo *pConn) { int32_t msgSize = tSerializeSTaskDropReq(NULL, 0, &qMsg); if (msgSize < 0) { QW_SCH_TASK_ELOG("tSerializeSTaskDropReq get size, msgSize:%d", msgSize); - QW_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + QW_ERR_RET(msgSize); } void *msg = rpcMallocCont(msgSize); @@ -249,11 +254,12 @@ int32_t qwBuildAndSendDropMsg(QW_FPARAMS_DEF, SRpcHandleInfo *pConn) { QW_SCH_TASK_ELOG("rpcMallocCont %d failed", msgSize); QW_ERR_RET(terrno); } - - if (tSerializeSTaskDropReq(msg, msgSize, &qMsg) < 0) { + + msgSize = tSerializeSTaskDropReq(msg, msgSize, &qMsg); + if (msgSize < 0) { QW_SCH_TASK_ELOG("tSerializeSTaskDropReq failed, msgSize:%d", msgSize); rpcFreeCont(msg); - QW_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + QW_ERR_RET(msgSize); } SRpcMsg pNewMsg = { @@ -279,7 +285,7 @@ int32_t qwBuildAndSendCQueryMsg(QW_FPARAMS_DEF, SRpcHandleInfo *pConn) { SQueryContinueReq *req = (SQueryContinueReq *)rpcMallocCont(sizeof(SQueryContinueReq)); if (NULL == req) { QW_SCH_TASK_ELOG("rpcMallocCont %d failed", (int32_t)sizeof(SQueryContinueReq)); - QW_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + QW_ERR_RET(terrno); } req->header.vgId = mgmt->nodeId; @@ -322,7 +328,7 @@ int32_t qwRegisterQueryBrokenLinkArg(QW_FPARAMS_DEF, SRpcHandleInfo *pConn) { int32_t msgSize = tSerializeSTaskDropReq(NULL, 0, &qMsg); if (msgSize < 0) { QW_SCH_TASK_ELOG("tSerializeSTaskDropReq get size, msgSize:%d", msgSize); - QW_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + QW_ERR_RET(msgSize); } void *msg = rpcMallocCont(msgSize); @@ -330,11 +336,12 @@ int32_t qwRegisterQueryBrokenLinkArg(QW_FPARAMS_DEF, SRpcHandleInfo *pConn) { QW_SCH_TASK_ELOG("rpcMallocCont %d failed", msgSize); QW_ERR_RET(terrno); } - - if (tSerializeSTaskDropReq(msg, msgSize, &qMsg) < 0) { + + msgSize = tSerializeSTaskDropReq(msg, msgSize, &qMsg); + if (msgSize < 0) { QW_SCH_TASK_ELOG("tSerializeSTaskDropReq failed, msgSize:%d", msgSize); rpcFreeCont(msg); - QW_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + QW_ERR_RET(msgSize); } SRpcMsg brokenMsg = { @@ -350,25 +357,27 @@ int32_t qwRegisterQueryBrokenLinkArg(QW_FPARAMS_DEF, SRpcHandleInfo *pConn) { return TSDB_CODE_SUCCESS; } -int32_t qwRegisterHbBrokenLinkArg(SQWorker *mgmt, uint64_t sId, SRpcHandleInfo *pConn) { +int32_t qwRegisterHbBrokenLinkArg(SQWorker *mgmt, uint64_t clientId, SRpcHandleInfo *pConn) { SSchedulerHbReq req = {0}; req.header.vgId = mgmt->nodeId; - req.sId = sId; + req.clientId = clientId; int32_t msgSize = tSerializeSSchedulerHbReq(NULL, 0, &req); if (msgSize < 0) { QW_SCH_ELOG("tSerializeSSchedulerHbReq hbReq failed, size:%d", msgSize); - QW_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + QW_ERR_RET(msgSize); } void *msg = rpcMallocCont(msgSize); if (NULL == msg) { QW_SCH_ELOG("calloc %d failed", msgSize); QW_ERR_RET(terrno); } - if (tSerializeSSchedulerHbReq(msg, msgSize, &req) < 0) { + + msgSize = tSerializeSSchedulerHbReq(msg, msgSize, &req); + if (msgSize < 0) { QW_SCH_ELOG("tSerializeSSchedulerHbReq hbReq failed, size:%d", msgSize); rpcFreeCont(msg); - QW_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + QW_ERR_RET(msgSize); } SRpcMsg brokenMsg = { @@ -720,6 +729,7 @@ int32_t qWorkerProcessHbMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, int64_ int32_t code = 0; SSchedulerHbReq req = {0}; SQWorker *mgmt = (SQWorker *)qWorkerMgmt; + uint64_t clientId = 0; QW_ERR_RET(qwUpdateTimeInQueue(mgmt, ts, FETCH_QUEUE)); QW_STAT_INC(mgmt->stat.msgStat.hbProcessed, 1); @@ -735,7 +745,8 @@ int32_t qWorkerProcessHbMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, int64_ QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); } - uint64_t sId = req.sId; + clientId = req.clientId; + SQWMsg qwMsg = {.node = node, .msg = NULL, .msgLen = 0, .code = pMsg->code, .connInfo = pMsg->info}; if (TSDB_CODE_RPC_BROKEN_LINK == pMsg->code) { QW_SCH_DLOG("receive Hb msg due to network broken, error:%s", tstrerror(pMsg->code)); diff --git a/source/libs/qworker/src/qwUtil.c b/source/libs/qworker/src/qwUtil.c index 917579deb0..2809f05590 100644 --- a/source/libs/qworker/src/qwUtil.c +++ b/source/libs/qworker/src/qwUtil.c @@ -70,7 +70,7 @@ int32_t qwSetTaskStatus(QW_FPARAMS_DEF, SQWTaskStatus *task, int8_t status, bool return TSDB_CODE_SUCCESS; } -int32_t qwAddSchedulerImpl(SQWorker *mgmt, uint64_t sId, int32_t rwType) { +int32_t qwAddSchedulerImpl(SQWorker *mgmt, uint64_t clientId, int32_t rwType) { SQWSchStatus newSch = {0}; newSch.tasksHash = taosHashInit(mgmt->cfg.maxSchTaskNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); @@ -82,14 +82,14 @@ int32_t qwAddSchedulerImpl(SQWorker *mgmt, uint64_t sId, int32_t rwType) { } QW_LOCK(QW_WRITE, &mgmt->schLock); - int32_t code = taosHashPut(mgmt->schHash, &sId, sizeof(sId), &newSch, sizeof(newSch)); + int32_t code = taosHashPut(mgmt->schHash, &clientId, sizeof(clientId), &newSch, sizeof(newSch)); if (0 != code) { if (!HASH_NODE_EXIST(code)) { QW_UNLOCK(QW_WRITE, &mgmt->schLock); QW_SCH_ELOG("taosHashPut new sch to scheduleHash failed, errno:%d", errno); taosHashCleanup(newSch.tasksHash); - QW_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + QW_ERR_RET(code); } taosHashCleanup(newSch.tasksHash); @@ -99,15 +99,15 @@ int32_t qwAddSchedulerImpl(SQWorker *mgmt, uint64_t sId, int32_t rwType) { return TSDB_CODE_SUCCESS; } -int32_t qwAcquireSchedulerImpl(SQWorker *mgmt, uint64_t sId, int32_t rwType, SQWSchStatus **sch, int32_t nOpt) { +int32_t qwAcquireSchedulerImpl(SQWorker *mgmt, uint64_t clientId, int32_t rwType, SQWSchStatus **sch, int32_t nOpt) { while (true) { QW_LOCK(rwType, &mgmt->schLock); - *sch = taosHashGet(mgmt->schHash, &sId, sizeof(sId)); + *sch = taosHashGet(mgmt->schHash, &clientId, sizeof(clientId)); if (NULL == (*sch)) { QW_UNLOCK(rwType, &mgmt->schLock); if (QW_NOT_EXIST_ADD == nOpt) { - QW_ERR_RET(qwAddSchedulerImpl(mgmt, sId, rwType)); + QW_ERR_RET(qwAddSchedulerImpl(mgmt, clientId, rwType)); nOpt = QW_NOT_EXIST_RET_ERR; @@ -126,12 +126,12 @@ int32_t qwAcquireSchedulerImpl(SQWorker *mgmt, uint64_t sId, int32_t rwType, SQW return TSDB_CODE_SUCCESS; } -int32_t qwAcquireAddScheduler(SQWorker *mgmt, uint64_t sId, int32_t rwType, SQWSchStatus **sch) { - return qwAcquireSchedulerImpl(mgmt, sId, rwType, sch, QW_NOT_EXIST_ADD); +int32_t qwAcquireAddScheduler(SQWorker *mgmt, uint64_t clientId, int32_t rwType, SQWSchStatus **sch) { + return qwAcquireSchedulerImpl(mgmt, clientId, rwType, sch, QW_NOT_EXIST_ADD); } -int32_t qwAcquireScheduler(SQWorker *mgmt, uint64_t sId, int32_t rwType, SQWSchStatus **sch) { - return qwAcquireSchedulerImpl(mgmt, sId, rwType, sch, QW_NOT_EXIST_RET_ERR); +int32_t qwAcquireScheduler(SQWorker *mgmt, uint64_t clientId, int32_t rwType, SQWSchStatus **sch) { + return qwAcquireSchedulerImpl(mgmt, clientId, rwType, sch, QW_NOT_EXIST_RET_ERR); } void qwReleaseScheduler(int32_t rwType, SQWorker *mgmt) { QW_UNLOCK(rwType, &mgmt->schLock); } @@ -144,6 +144,7 @@ int32_t qwAcquireTaskStatus(QW_FPARAMS_DEF, int32_t rwType, SQWSchStatus *sch, S *task = taosHashGet(sch->tasksHash, id, sizeof(id)); if (NULL == (*task)) { QW_UNLOCK(rwType, &sch->tasksLock); + QW_TASK_ELOG_E("task status not exists"); QW_ERR_RET(TSDB_CODE_QRY_TASK_NOT_EXIST); } @@ -173,7 +174,7 @@ int32_t qwAddTaskStatusImpl(QW_FPARAMS_DEF, SQWSchStatus *sch, int32_t rwType, i } } else { QW_TASK_ELOG("taosHashPut to tasksHash failed, error:%x - %s", code, tstrerror(code)); - QW_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + QW_ERR_RET(code); } } QW_UNLOCK(QW_WRITE, &sch->tasksLock); @@ -190,7 +191,7 @@ int32_t qwAddTaskStatusImpl(QW_FPARAMS_DEF, SQWSchStatus *sch, int32_t rwType, i int32_t qwAddTaskStatus(QW_FPARAMS_DEF, int32_t status) { SQWSchStatus *tsch = NULL; int32_t code = 0; - QW_ERR_RET(qwAcquireAddScheduler(mgmt, sId, QW_READ, &tsch)); + QW_ERR_RET(qwAcquireAddScheduler(mgmt, cId, QW_READ, &tsch)); QW_ERR_JRET(qwAddTaskStatusImpl(QW_FPARAMS(), tsch, 0, status, NULL)); @@ -253,10 +254,12 @@ int32_t qwAddTaskCtxImpl(QW_FPARAMS_DEF, bool acquire, SQWTaskCtx **ctx) { } } else { QW_TASK_ELOG("taosHashPut to ctxHash failed, error:%x", code); - QW_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + QW_ERR_RET(code); } } + atomic_add_fetch_64(&gQueryMgmt.stat.taskInitNum, 1); + if (acquire && ctx) { QW_RET(qwAcquireTaskCtx(QW_FPARAMS(), ctx)); } else if (ctx) { @@ -272,17 +275,34 @@ int32_t qwAddAcquireTaskCtx(QW_FPARAMS_DEF, SQWTaskCtx **ctx) { return qwAddTask void qwReleaseTaskCtx(SQWorker *mgmt, void *ctx) { taosHashRelease(mgmt->ctxHash, ctx); } -void qwFreeTaskHandle(qTaskInfo_t *taskHandle) { +void qwFreeTaskHandle(SQWTaskCtx *ctx) { // Note: free/kill may in RC - qTaskInfo_t otaskHandle = atomic_load_ptr(taskHandle); - if (otaskHandle && atomic_val_compare_exchange_ptr(taskHandle, otaskHandle, NULL)) { - tsEnableRandErr = true; + qTaskInfo_t otaskHandle = atomic_load_ptr(&ctx->taskHandle); + if (otaskHandle && otaskHandle == atomic_val_compare_exchange_ptr(&ctx->taskHandle, otaskHandle, NULL)) { + taosEnableMemPoolUsage(ctx->memPoolSession); qDestroyTask(otaskHandle); - tsEnableRandErr = false; + taosDisableMemPoolUsage(); + + atomic_add_fetch_64(&gQueryMgmt.stat.taskExecDestroyNum, 1); + qDebug("task handle destroyed"); } } +void qwFreeSinkHandle(SQWTaskCtx *ctx) { + // Note: free/kill may in RC + void *osinkHandle = atomic_load_ptr(&ctx->sinkHandle); + if (osinkHandle && osinkHandle == atomic_val_compare_exchange_ptr(&ctx->sinkHandle, osinkHandle, NULL)) { + QW_SINK_ENABLE_MEMPOOL(ctx); + dsDestroyDataSinker(osinkHandle); + QW_SINK_DISABLE_MEMPOOL(); + + atomic_add_fetch_64(&gQueryMgmt.stat.taskSinkDestroyNum, 1); + + qDebug("sink handle destroyed"); + } +} + int32_t qwKillTaskHandle(SQWTaskCtx *ctx, int32_t rspCode) { int32_t code = 0; @@ -297,9 +317,9 @@ int32_t qwKillTaskHandle(SQWTaskCtx *ctx, int32_t rspCode) { QW_RET(code); } -void qwFreeTaskCtx(SQWTaskCtx *ctx) { +void qwFreeTaskCtx(QW_FPARAMS_DEF, SQWTaskCtx *ctx) { if (ctx->ctrlConnInfo.handle) { - tmsgReleaseHandle(&ctx->ctrlConnInfo, TAOS_CONN_SERVER); + tmsgReleaseHandle(&ctx->ctrlConnInfo, TAOS_CONN_SERVER, ctx->rspCode); } ctx->ctrlConnInfo.handle = NULL; @@ -307,15 +327,15 @@ void qwFreeTaskCtx(SQWTaskCtx *ctx) { // NO need to release dataConnInfo - qwFreeTaskHandle(&ctx->taskHandle); + qwFreeTaskHandle(ctx); - if (ctx->sinkHandle) { - dsDestroyDataSinker(ctx->sinkHandle); - ctx->sinkHandle = NULL; - qDebug("sink handle destroyed"); - } + qwFreeSinkHandle(ctx); taosArrayDestroy(ctx->tbInfo); + + if (gMemPoolHandle && ctx->memPoolSession) { + qwDestroySession(QW_FPARAMS(), ctx->pJobInfo, ctx->memPoolSession); + } } static void freeExplainExecItem(void *param) { @@ -323,20 +343,19 @@ static void freeExplainExecItem(void *param) { taosMemoryFree(pInfo->verboseInfo); } - int32_t qwSendExplainResponse(QW_FPARAMS_DEF, SQWTaskCtx *ctx) { - int32_t code = TSDB_CODE_SUCCESS; + int32_t code = TSDB_CODE_SUCCESS; qTaskInfo_t taskHandle = ctx->taskHandle; ctx->explainRsped = true; - + SArray *execInfoList = taosArrayInit(4, sizeof(SExplainExecInfo)); if (NULL == execInfoList) { QW_ERR_JRET(terrno); } - + QW_ERR_JRET(qGetExplainExecInfo(taskHandle, execInfoList)); - + if (ctx->localExec) { SExplainLocalRsp localRsp = {0}; localRsp.rsp.numOfPlans = taosArrayGetSize(execInfoList); @@ -354,7 +373,7 @@ int32_t qwSendExplainResponse(QW_FPARAMS_DEF, SQWTaskCtx *ctx) { if (NULL == taosArrayPush(ctx->explainRes, &localRsp)) { QW_ERR_JRET(terrno); } - + taosArrayDestroy(execInfoList); execInfoList = NULL; } else { @@ -374,12 +393,11 @@ _return: return code; } - - int32_t qwDropTaskCtx(QW_FPARAMS_DEF) { char id[sizeof(qId) + sizeof(cId) + sizeof(tId) + sizeof(eId)] = {0}; QW_SET_QTID(id, qId, cId, tId, eId); SQWTaskCtx octx; + int32_t code = TSDB_CODE_SUCCESS; SQWTaskCtx *ctx = taosHashGet(mgmt->ctxHash, id, sizeof(id)); if (NULL == ctx) { @@ -389,22 +407,30 @@ int32_t qwDropTaskCtx(QW_FPARAMS_DEF) { octx = *ctx; + if (ctx->pJobInfo && TSDB_CODE_SUCCESS != ctx->pJobInfo->errCode) { + QW_UPDATE_RSP_CODE(ctx, ctx->pJobInfo->errCode); + } + atomic_store_ptr(&ctx->taskHandle, NULL); atomic_store_ptr(&ctx->sinkHandle, NULL); + atomic_store_ptr(&ctx->pJobInfo, NULL); + atomic_store_ptr(&ctx->memPoolSession, NULL); QW_SET_EVENT_PROCESSED(ctx, QW_EVENT_DROP); if (taosHashRemove(mgmt->ctxHash, id, sizeof(id))) { QW_TASK_ELOG_E("taosHashRemove from ctx hash failed"); - QW_ERR_RET(QW_CTX_NOT_EXISTS_ERR_CODE(mgmt)); + code = QW_CTX_NOT_EXISTS_ERR_CODE(mgmt); } - qwFreeTaskCtx(&octx); + qwFreeTaskCtx(QW_FPARAMS(), &octx); ctx->tbInfo = NULL; QW_TASK_DLOG_E("task ctx dropped"); + + atomic_add_fetch_64(&gQueryMgmt.stat.taskDestroyNum, 1); - return TSDB_CODE_SUCCESS; + return code; } int32_t qwDropTaskStatus(QW_FPARAMS_DEF) { @@ -415,7 +441,7 @@ int32_t qwDropTaskStatus(QW_FPARAMS_DEF) { char id[sizeof(qId) + sizeof(cId) + sizeof(tId) + sizeof(eId)] = {0}; QW_SET_QTID(id, qId, cId, tId, eId); - if (qwAcquireScheduler(mgmt, sId, QW_WRITE, &sch)) { + if (qwAcquireScheduler(mgmt, cId, QW_WRITE, &sch)) { QW_TASK_WLOG_E("scheduler does not exist"); return TSDB_CODE_SUCCESS; } @@ -449,7 +475,7 @@ int32_t qwUpdateTaskStatus(QW_FPARAMS_DEF, int8_t status, bool dynamicTask) { SQWTaskStatus *task = NULL; int32_t code = 0; - QW_ERR_RET(qwAcquireScheduler(mgmt, sId, QW_READ, &sch)); + QW_ERR_RET(qwAcquireScheduler(mgmt, cId, QW_READ, &sch)); QW_ERR_JRET(qwAcquireTaskStatus(QW_FPARAMS(), QW_READ, sch, &task)); QW_ERR_JRET(qwSetTaskStatus(QW_FPARAMS(), task, status, dynamicTask)); @@ -464,7 +490,6 @@ _return: QW_RET(code); } - int32_t qwHandleDynamicTaskEnd(QW_FPARAMS_DEF) { char id[sizeof(qId) + sizeof(cId) + sizeof(tId) + sizeof(eId)] = {0}; QW_SET_QTID(id, qId, cId, tId, eId); @@ -525,16 +550,17 @@ void qwSetHbParam(int64_t refId, SQWHbParam **pParam) { } int32_t qwSaveTbVersionInfo(qTaskInfo_t pTaskInfo, SQWTaskCtx *ctx) { - char dbFName[TSDB_DB_FNAME_LEN]; - char tbName[TSDB_TABLE_NAME_LEN]; + char dbFName[TSDB_DB_FNAME_LEN]; + char tbName[TSDB_TABLE_NAME_LEN]; STbVerInfo tbInfo; - int32_t i = 0; - int32_t code = TSDB_CODE_SUCCESS; - bool tbGet = false; + int32_t i = 0; + int32_t code = TSDB_CODE_SUCCESS; + bool tbGet = false; while (true) { tbGet = false; - code = qGetQueryTableSchemaVersion(pTaskInfo, dbFName, TSDB_DB_FNAME_LEN, tbName, TSDB_TABLE_NAME_LEN, &tbInfo.sversion, &tbInfo.tversion, i, &tbGet); + code = qGetQueryTableSchemaVersion(pTaskInfo, dbFName, TSDB_DB_FNAME_LEN, tbName, TSDB_TABLE_NAME_LEN, + &tbInfo.sversion, &tbInfo.tversion, i, &tbGet); if (TSDB_CODE_SUCCESS != code || !tbGet) { break; } @@ -551,11 +577,11 @@ int32_t qwSaveTbVersionInfo(qTaskInfo_t pTaskInfo, SQWTaskCtx *ctx) { QW_ERR_RET(terrno); } } - + if (NULL == taosArrayPush(ctx->tbInfo, &tbInfo)) { QW_ERR_RET(terrno); } - + i++; } @@ -567,6 +593,9 @@ void qwCloseRef(void) { if (atomic_load_32(&gQwMgmt.qwNum) <= 0 && gQwMgmt.qwRef >= 0) { taosCloseRef(gQwMgmt.qwRef); // ignore error gQwMgmt.qwRef = -1; + + taosHashCleanup(gQueryMgmt.pJobInfo); + gQueryMgmt.pJobInfo = NULL; } taosWUnLockLatch(&gQwMgmt.lock); } @@ -585,20 +614,22 @@ void qwDestroyImpl(void *pMgmt) { if (taosTmrStop(mgmt->hbTimer)) { qTrace("stop qworker hb timer may failed"); } - + mgmt->hbTimer = NULL; taosTmrCleanUp(mgmt->timer); - uint64_t qId, cId, tId; + uint64_t qId, cId, tId, sId; int32_t eId; + int64_t rId = 0; void *pIter = taosHashIterate(mgmt->ctxHash, NULL); while (pIter) { SQWTaskCtx *ctx = (SQWTaskCtx *)pIter; void *key = taosHashGetKey(pIter, NULL); QW_GET_QTID(key, qId, cId, tId, eId); + sId = ctx->sId; - qwFreeTaskCtx(ctx); + qwFreeTaskCtx(QW_FPARAMS(), ctx); QW_TASK_DLOG_E("task ctx freed"); pIter = taosHashIterate(mgmt->ctxHash, pIter); taskCount++; @@ -634,7 +665,7 @@ int32_t qwOpenRef(void) { if (gQwMgmt.qwRef < 0) { taosWUnLockLatch(&gQwMgmt.lock); qError("init qworker ref failed"); - QW_RET(TSDB_CODE_OUT_OF_MEMORY); + QW_RET(gQwMgmt.qwRef); } } taosWUnLockLatch(&gQwMgmt.lock); @@ -686,25 +717,172 @@ void qwClearExpiredSch(SQWorker *mgmt, SArray *pExpiredSch) { int32_t code = TSDB_CODE_SUCCESS; int32_t num = taosArrayGetSize(pExpiredSch); for (int32_t i = 0; i < num; ++i) { - uint64_t *sId = taosArrayGet(pExpiredSch, i); + uint64_t *clientId = taosArrayGet(pExpiredSch, i); SQWSchStatus *pSch = NULL; - if (NULL == sId) { - qError("get the %dth sch failed, code:%x", i, terrno); + if (NULL == clientId) { + qError("get the %dth client failed, code:%x", i, terrno); break; } - code = qwAcquireScheduler(mgmt, *sId, QW_WRITE, &pSch); + code = qwAcquireScheduler(mgmt, *clientId, QW_WRITE, &pSch); if (TSDB_CODE_SUCCESS != code) { - qError("acquire sch %" PRIx64 " failed, code:%x", *sId, code); + qError("acquire client %" PRIx64 " failed, code:%x", *clientId, code); continue; } if (taosHashGetSize(pSch->tasksHash) <= 0) { qwDestroySchStatus(pSch); - code = taosHashRemove(mgmt->schHash, sId, sizeof(*sId)); - qDebug("sch %" PRIx64 " destroy result code:%x", *sId, code); + code = taosHashRemove(mgmt->schHash, clientId, sizeof(*clientId)); + qDebug("client %" PRIx64 " destroy result code:%x", *clientId, code); } qwReleaseScheduler(QW_WRITE, mgmt); } } + +void qwDestroyJobInfo(void *job) { + if (NULL == job) { + return; + } + + SQWJobInfo *pJob = (SQWJobInfo *)job; + + taosMemoryFreeClear(pJob->memInfo); + taosHashCleanup(pJob->pSessions); + pJob->pSessions = NULL; +} + +bool qwStopTask(QW_FPARAMS_DEF, SQWTaskCtx *ctx, bool forceStop, int32_t errCode) { + int32_t code = TSDB_CODE_SUCCESS; + bool resFreed = false; + + QW_LOCK(QW_WRITE, &ctx->lock); + + QW_TASK_DLOG("start to stop task, forceStop:%d, error:%s", forceStop, tstrerror(errCode)); + + if ((!forceStop) && (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); + + return resFreed; + } + + if (QW_QUERY_RUNNING(ctx)) { + code = qwKillTaskHandle(ctx, errCode); + if (TSDB_CODE_SUCCESS != code) { + QW_TASK_ELOG("task running, async kill failed, error: %x", code); + } else { + QW_TASK_DLOG_E("task running, async killed"); + } + } else if (QW_FETCH_RUNNING(ctx)) { + QW_TASK_DLOG_E("task fetching"); + QW_UPDATE_RSP_CODE(ctx, errCode); + if (forceStop) { + QW_SET_EVENT_RECEIVED(ctx, QW_EVENT_DROP); + QW_TASK_DLOG_E("update drop received"); + } + } else if (forceStop) { + QW_UPDATE_RSP_CODE(ctx, errCode); + code = qwDropTask(QW_FPARAMS()); + if (TSDB_CODE_SUCCESS != code) { + QW_TASK_ELOG("task drop failed, error: %x", code); + } else { + QW_TASK_DLOG_E("task dropped"); + resFreed = true; + } + } else { + QW_UPDATE_RSP_CODE(ctx, errCode); + + qwFreeTaskHandle(ctx); + qwFreeSinkHandle(ctx); + + resFreed = true; + + QW_TASK_DLOG_E("task resources freed"); + } + + QW_UNLOCK(QW_WRITE, &ctx->lock); + + return resFreed; +} + +bool qwRetireTask(QW_FPARAMS_DEF, int32_t errCode) { + SQWTaskCtx *ctx = NULL; + + int32_t code = qwAcquireTaskCtx(QW_FPARAMS(), &ctx); + if (TSDB_CODE_SUCCESS != code) { + return false; + } + + bool retired = qwStopTask(QW_FPARAMS(), ctx, false, errCode); + + qwReleaseTaskCtx(mgmt, ctx); + + return retired; +} + +bool qwRetireJob(SQWJobInfo *pJob) { + if (NULL == pJob) { + return false; + } + + bool retired = true; + void *pIter = taosHashIterate(pJob->pSessions, NULL); + while (pIter) { + SQWSessionInfo *pSession = (SQWSessionInfo *)pIter; + + if (!qwRetireTask((SQWorker *)pSession->mgmt, pSession->sId, pSession->qId, pSession->cId, pSession->tId, pSession->rId, pSession->eId, pJob->errCode)) { + retired = false; + } + + pIter = taosHashIterate(pJob->pSessions, pIter); + } + + return retired; +} + + +void qwStopAllTasks(SQWorker *mgmt) { + uint64_t qId, cId, tId, sId; + int32_t eId; + int64_t rId = 0; + + void *pIter = taosHashIterate(mgmt->ctxHash, NULL); + while (pIter) { + SQWTaskCtx *ctx = (SQWTaskCtx *)pIter; + void *key = taosHashGetKey(pIter, NULL); + QW_GET_QTID(key, qId, cId, tId, eId); + + sId = ctx->sId; + + (void)qwStopTask(QW_FPARAMS(), ctx, true, TSDB_CODE_VND_STOPPED); + + pIter = taosHashIterate(mgmt->ctxHash, pIter); + } +} + + +void qwChkDropTimeoutQuery(SQWorker *mgmt, int32_t currTs) { + uint64_t qId, cId, tId, sId; + int32_t eId; + int64_t rId = 0; + + void *pIter = taosHashIterate(mgmt->ctxHash, NULL); + while (pIter) { + SQWTaskCtx *ctx = (SQWTaskCtx *)pIter; + if (((ctx->lastAckTs <= 0) || (currTs - ctx->lastAckTs) < tsQueryNoFetchTimeoutSec) && (!QW_EVENT_RECEIVED(ctx, QW_EVENT_DROP))) { + pIter = taosHashIterate(mgmt->ctxHash, pIter); + continue; + } + + void *key = taosHashGetKey(pIter, NULL); + QW_GET_QTID(key, qId, cId, tId, eId); + + sId = ctx->sId; + + (void)qwStopTask(QW_FPARAMS(), ctx, true, (QW_EVENT_RECEIVED(ctx, QW_EVENT_DROP)) ? ctx->rspCode : TSDB_CODE_QRY_NO_FETCH_TIMEOUT); + + pIter = taosHashIterate(mgmt->ctxHash, pIter); + } +} + diff --git a/source/libs/qworker/src/qworker.c b/source/libs/qworker/src/qworker.c index aae31480e2..50af01cd6f 100644 --- a/source/libs/qworker/src/qworker.c +++ b/source/libs/qworker/src/qworker.c @@ -18,71 +18,23 @@ SQWorkerMgmt gQwMgmt = { .qwNum = 0, }; -void qwStopAllTasks(SQWorker *mgmt) { - uint64_t qId, cId, tId, sId; - int32_t eId; - int64_t rId = 0; - int32_t code = TSDB_CODE_SUCCESS; +TdThreadOnce gQueryPoolInit = PTHREAD_ONCE_INIT; +SQueryMgmt gQueryMgmt = {0}; - void *pIter = taosHashIterate(mgmt->ctxHash, NULL); - while (pIter) { - SQWTaskCtx *ctx = (SQWTaskCtx *)pIter; - void *key = taosHashGetKey(pIter, NULL); - QW_GET_QTID(key, qId, cId, tId, eId); - - QW_LOCK(QW_WRITE, &ctx->lock); - - sId = ctx->sId; - - 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)) { - code = qwKillTaskHandle(ctx, TSDB_CODE_VND_STOPPED); - if (TSDB_CODE_SUCCESS != code) { - QW_TASK_ELOG("task running, async kill failed, error: %x", code); - } else { - QW_TASK_DLOG_E("task running, async killed"); - } - } else if (QW_FETCH_RUNNING(ctx)) { - QW_UPDATE_RSP_CODE(ctx, TSDB_CODE_VND_STOPPED); - QW_SET_EVENT_RECEIVED(ctx, QW_EVENT_DROP); - QW_TASK_DLOG_E("task fetching, update drop received"); - } else { - code = qwDropTask(QW_FPARAMS()); - if (TSDB_CODE_SUCCESS != code) { - QW_TASK_ELOG("task drop failed, error: %x", code); - } else { - QW_TASK_DLOG_E("task dropped"); - } - } - - QW_UNLOCK(QW_WRITE, &ctx->lock); - - pIter = taosHashIterate(mgmt->ctxHash, pIter); - } -} int32_t qwProcessHbLinkBroken(SQWorker *mgmt, SQWMsg *qwMsg, SSchedulerHbReq *req) { int32_t code = 0; SSchedulerHbRsp rsp = {0}; SQWSchStatus *sch = NULL; - QW_ERR_RET(qwAcquireScheduler(mgmt, req->sId, QW_READ, &sch)); + QW_ERR_RET(qwAcquireScheduler(mgmt, req->clientId, QW_READ, &sch)); QW_LOCK(QW_WRITE, &sch->hbConnLock); sch->hbBrokenTs = taosGetTimestampMs(); if (qwMsg->connInfo.handle == sch->hbConnInfo.handle) { - tmsgReleaseHandle(&sch->hbConnInfo, TAOS_CONN_SERVER); + tmsgReleaseHandle(&sch->hbConnInfo, TAOS_CONN_SERVER, 0); sch->hbConnInfo.handle = NULL; sch->hbConnInfo.ahandle = NULL; @@ -100,20 +52,29 @@ int32_t qwProcessHbLinkBroken(SQWorker *mgmt, SQWMsg *qwMsg, SSchedulerHbReq *re int32_t qwHandleTaskComplete(QW_FPARAMS_DEF, SQWTaskCtx *ctx) { qTaskInfo_t taskHandle = ctx->taskHandle; + int32_t code = TSDB_CODE_SUCCESS; ctx->queryExecDone = true; if (TASK_TYPE_TEMP == ctx->taskType && taskHandle) { if (ctx->explain && !ctx->explainRsped) { - QW_ERR_RET(qwSendExplainResponse(QW_FPARAMS(), ctx)); + QW_ERR_JRET(qwSendExplainResponse(QW_FPARAMS(), ctx)); } if (!ctx->needFetch) { + QW_SINK_ENABLE_MEMPOOL(ctx); dsGetDataLength(ctx->sinkHandle, &ctx->affectedRows, NULL, NULL); + QW_SINK_DISABLE_MEMPOOL(); } } - return TSDB_CODE_SUCCESS; +_return: + + if ((!ctx->dynamicTask) && (!ctx->explain || ctx->explainRsped)) { + qwFreeTaskHandle(ctx); + } + + return code; } int32_t qwSendQueryRsp(QW_FPARAMS_DEF, int32_t msgType, SQWTaskCtx *ctx, int32_t rspCode, bool quickRsp) { @@ -123,6 +84,7 @@ int32_t qwSendQueryRsp(QW_FPARAMS_DEF, int32_t msgType, SQWTaskCtx *ctx, int32_t QW_TASK_DLOG("query msg rsped, handle:%p, code:%x - %s", ctx->ctrlConnInfo.handle, rspCode, tstrerror(rspCode)); } + ctx->lastAckTs = taosGetTimestampSec(); ctx->queryRsped = true; } @@ -151,7 +113,7 @@ int32_t qwExecTask(QW_FPARAMS_DEF, SQWTaskCtx *ctx, bool *queryStop) { if (NULL == pResList) { QW_ERR_RET(terrno); } - + while (true) { QW_TASK_DLOG("start to execTask, loopIdx:%d", i++); @@ -161,9 +123,10 @@ int32_t qwExecTask(QW_FPARAMS_DEF, SQWTaskCtx *ctx, bool *queryStop) { if (taskHandle) { qwDbgSimulateSleep(); - tsEnableRandErr = true; + taosEnableMemPoolUsage(ctx->memPoolSession); code = qExecTaskOpt(taskHandle, pResList, &useconds, &hasMore, &localFetch); - tsEnableRandErr = false; + taosDisableMemPoolUsage(); + if (code) { if (code != TSDB_CODE_OPS_NOT_SUPPORT) { QW_TASK_ELOG("qExecTask failed, code:%x - %s", code, tstrerror(code)); @@ -184,7 +147,10 @@ int32_t qwExecTask(QW_FPARAMS_DEF, SQWTaskCtx *ctx, bool *queryStop) { } SInputData inputData = {.pData = pRes}; + QW_SINK_ENABLE_MEMPOOL(ctx); code = dsPutDataBlock(sinkHandle, &inputData, &qcontinue); + QW_SINK_DISABLE_MEMPOOL(); + if (code) { QW_TASK_ELOG("dsPutDataBlock failed, code:%x - %s", code, tstrerror(code)); QW_ERR_JRET(code); @@ -212,7 +178,9 @@ int32_t qwExecTask(QW_FPARAMS_DEF, SQWTaskCtx *ctx, bool *queryStop) { ctx->queryExecDone = true; } + QW_SINK_ENABLE_MEMPOOL(ctx); dsEndPut(sinkHandle, useconds); + QW_SINK_DISABLE_MEMPOOL(); if (queryStop) { *queryStop = true; @@ -245,7 +213,11 @@ int32_t qwExecTask(QW_FPARAMS_DEF, SQWTaskCtx *ctx, bool *queryStop) { _return: taosArrayDestroy(pResList); - + + if (TSDB_CODE_SUCCESS != code) { + qwFreeTaskHandle(ctx); + } + QW_RET(code); } @@ -261,7 +233,7 @@ bool qwTaskNotInExec(SQWTaskCtx *ctx) { int32_t qwGenerateSchHbRsp(SQWorker *mgmt, SQWSchStatus *sch, SQWHbInfo *hbInfo) { int32_t taskNum = 0; int32_t code = TSDB_CODE_SUCCESS; - + hbInfo->connInfo = sch->hbConnInfo; hbInfo->rsp.epId = sch->hbEpId; @@ -325,7 +297,9 @@ int32_t qwGetQueryResFromSink(QW_FPARAMS_DEF, SQWTaskCtx *ctx, int32_t *dataLen, *pRawDataLen = 0; while (true) { + QW_SINK_ENABLE_MEMPOOL(ctx); dsGetDataLength(ctx->sinkHandle, &len, &rawLen, &queryEnd); + QW_SINK_DISABLE_MEMPOOL(); if (len < 0) { QW_TASK_ELOG("invalid length from dsGetDataLength, length:%" PRId64 "", len); @@ -334,7 +308,10 @@ int32_t qwGetQueryResFromSink(QW_FPARAMS_DEF, SQWTaskCtx *ctx, int32_t *dataLen, if (len == 0) { if (queryEnd) { + QW_SINK_ENABLE_MEMPOOL(ctx); code = dsGetDataBlock(ctx->sinkHandle, &output); + QW_SINK_DISABLE_MEMPOOL(); + if (code) { QW_TASK_ELOG("dsGetDataBlock failed, code:%x - %s", code, tstrerror(code)); QW_ERR_JRET(code); @@ -377,7 +354,10 @@ int32_t qwGetQueryResFromSink(QW_FPARAMS_DEF, SQWTaskCtx *ctx, int32_t *dataLen, ((int32_t *)output.pData)[1] = rawLen; output.pData += sizeof(int32_t) * 2; + QW_SINK_ENABLE_MEMPOOL(ctx); code = dsGetDataBlock(ctx->sinkHandle, &output); + QW_SINK_DISABLE_MEMPOOL(); + if (code) { QW_TASK_ELOG("dsGetDataBlock failed, code:%x - %s", code, tstrerror(code)); QW_ERR_JRET(code); @@ -419,7 +399,7 @@ int32_t qwGetQueryResFromSink(QW_FPARAMS_DEF, SQWTaskCtx *ctx, int32_t *dataLen, _return: *rspMsg = pRsp; - + return code; } @@ -430,7 +410,9 @@ int32_t qwGetDeleteResFromSink(QW_FPARAMS_DEF, SQWTaskCtx *ctx, SDeleteRes *pRes int32_t code = 0; SOutputData output = {0}; + QW_SINK_ENABLE_MEMPOOL(ctx); dsGetDataLength(ctx->sinkHandle, &len, &rawLen, &queryEnd); + QW_SINK_DISABLE_MEMPOOL(); if (len <= 0 || len != sizeof(SDeleterRes)) { QW_TASK_ELOG("invalid length from dsGetDataLength, length:%" PRId64, len); @@ -442,7 +424,10 @@ int32_t qwGetDeleteResFromSink(QW_FPARAMS_DEF, SQWTaskCtx *ctx, SDeleteRes *pRes QW_ERR_RET(terrno); } + QW_SINK_ENABLE_MEMPOOL(ctx); code = dsGetDataBlock(ctx->sinkHandle, &output); + QW_SINK_DISABLE_MEMPOOL(); + if (code) { QW_TASK_ELOG("dsGetDataBlock failed, code:%x - %s", code, tstrerror(code)); taosMemoryFree(output.pData); @@ -491,13 +476,16 @@ int32_t qwQuickRspFetchReq(QW_FPARAMS_DEF, SQWTaskCtx *ctx, SQWMsg *qwMsg, int32 qwBuildFetchRsp(rsp, &sOutput, dataLen, rawLen, qComplete); if (qComplete) { atomic_store_8((int8_t *)&ctx->queryEnd, true); + if (!ctx->dynamicTask) { + qwFreeSinkHandle(ctx); + } } } qwMsg->connInfo = ctx->dataConnInfo; QW_SET_EVENT_PROCESSED(ctx, QW_EVENT_FETCH); - QW_ERR_RET(qwBuildAndSendFetchRsp(ctx->fetchMsgType + 1, &qwMsg->connInfo, rsp, dataLen, code)); + QW_ERR_RET(qwBuildAndSendFetchRsp(ctx, ctx->fetchMsgType + 1, &qwMsg->connInfo, rsp, dataLen, code)); rsp = NULL; QW_TASK_DLOG("fetch rsp send, handle:%p, code:%x - %s, dataLen:%d", qwMsg->connInfo.handle, code, tstrerror(code), @@ -523,7 +511,9 @@ int32_t qwStartDynamicTaskNewExec(QW_FPARAMS_DEF, SQWTaskCtx *ctx, SQWMsg *qwMsg ctx->queryEnd = false; #endif + QW_SINK_ENABLE_MEMPOOL(ctx); dsReset(ctx->sinkHandle); + QW_SINK_DISABLE_MEMPOOL(); qUpdateOperatorParam(ctx->taskHandle, qwMsg->msg); @@ -551,17 +541,20 @@ int32_t qwHandlePrePhaseEvents(QW_FPARAMS_DEF, int8_t phase, SQWPhaseInput *inpu QW_LOCK(QW_WRITE, &ctx->lock); - QW_SET_PHASE(ctx, phase); + if (ctx->pJobInfo && (atomic_load_8(&ctx->pJobInfo->retired) || atomic_load_32(&ctx->pJobInfo->errCode))) { + QW_TASK_ELOG("job already failed, error:%s", tstrerror(ctx->pJobInfo->errCode)); + QW_ERR_JRET(ctx->pJobInfo->errCode); + } if (atomic_load_8((int8_t *)&ctx->queryEnd) && !ctx->dynamicTask) { - QW_TASK_ELOG_E("query already end"); + QW_TASK_ELOG("query already end, phase:%d", phase); QW_ERR_JRET(TSDB_CODE_QW_MSG_ERROR); } switch (phase) { case QW_PHASE_PRE_QUERY: { if (QW_EVENT_PROCESSED(ctx, QW_EVENT_DROP)) { - QW_TASK_ELOG("task already dropped at wrong phase %s", qwPhaseStr(phase)); + QW_TASK_ELOG("task already dropped at phase %s", qwPhaseStr(phase)); QW_ERR_JRET(TSDB_CODE_QRY_TASK_STATUS_ERROR); } @@ -631,6 +624,8 @@ int32_t qwHandlePrePhaseEvents(QW_FPARAMS_DEF, int8_t phase, SQWPhaseInput *inpu QW_ERR_JRET(ctx->rspCode); } + QW_SET_PHASE(ctx, phase); + _return: if (ctx) { @@ -640,7 +635,7 @@ _return: qwReleaseTaskCtx(mgmt, ctx); } - if (code != TSDB_CODE_SUCCESS) { + if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_QRY_TASK_CTX_NOT_EXIST) { QW_TASK_ELOG("end to handle event at phase %s, code:%s", qwPhaseStr(phase), tstrerror(code)); } else { QW_TASK_DLOG("end to handle event at phase %s, code:%s", qwPhaseStr(phase), tstrerror(code)); @@ -712,7 +707,8 @@ _return: } if (code) { - (void)qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_FAIL, ctx->dynamicTask); // already in error, ignore new error + (void)qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_FAIL, + ctx->dynamicTask); // already in error, ignore new error } QW_UNLOCK(QW_WRITE, &ctx->lock); @@ -744,6 +740,10 @@ int32_t qwPreprocessQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg) { ctx->sId = sId; ctx->phase = -1; + if (NULL != gMemPoolHandle) { + QW_ERR_JRET(qwInitSession(QW_FPARAMS(), ctx, &ctx->memPoolSession)); + } + QW_ERR_JRET(qwAddTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_INIT)); QW_ERR_JRET(qwSendQueryRsp(QW_FPARAMS(), qwMsg->msgType + 1, ctx, code, true)); @@ -752,9 +752,15 @@ _return: if (ctx) { QW_UPDATE_RSP_CODE(ctx, code); + if (code) { + (void)qwDropTask(QW_FPARAMS()); + } + qwReleaseTaskCtx(mgmt, ctx); } + QW_TASK_DLOG("task preprocess %s, code:%s", code ? "failed": "succeed", tstrerror(code)); + return code; } @@ -776,19 +782,20 @@ int32_t qwProcessQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg, char *sql) { ctx->queryMsgType = qwMsg->msgType; ctx->localExec = false; + taosEnableMemPoolUsage(ctx->memPoolSession); code = qMsgToSubplan(qwMsg->msg, qwMsg->msgLen, &plan); + taosDisableMemPoolUsage(); + if (TSDB_CODE_SUCCESS != code) { - code = TSDB_CODE_INVALID_MSG; QW_TASK_ELOG("task physical plan to subplan failed, code:%x - %s", code, tstrerror(code)); QW_ERR_JRET(code); } - tsEnableRandErr = true; + taosEnableMemPoolUsage(ctx->memPoolSession); code = qCreateExecTask(qwMsg->node, mgmt->nodeId, tId, plan, &pTaskInfo, &sinkHandle, qwMsg->msgInfo.compressMsg, sql, OPTR_EXEC_MODEL_BATCH); - tsEnableRandErr = false; - - sql = NULL; + taosDisableMemPoolUsage(); + if (code) { QW_TASK_ELOG("qCreateExecTask failed, code:%x - %s", code, tstrerror(code)); qDestroyTask(pTaskInfo); @@ -801,8 +808,14 @@ int32_t qwProcessQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg, char *sql) { QW_ERR_JRET(TSDB_CODE_APP_ERROR); } + atomic_add_fetch_64(&gQueryMgmt.stat.taskRunNum, 1); + + uint64_t flags = 0; + dsGetSinkFlags(sinkHandle, &flags); + ctx->level = plan->level; ctx->dynamicTask = qIsDynamicExecTask(pTaskInfo); + ctx->sinkWithMemPool = flags & DS_FLAG_USE_MEMPOOL; atomic_store_ptr(&ctx->taskHandle, pTaskInfo); atomic_store_ptr(&ctx->sinkHandle, sinkHandle); @@ -869,12 +882,15 @@ int32_t qwProcessCQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg) { if (qComplete) { atomic_store_8((int8_t *)&ctx->queryEnd, true); atomic_store_8((int8_t *)&ctx->queryContinue, 0); + if (!ctx->dynamicTask) { + qwFreeSinkHandle(ctx); + } } qwMsg->connInfo = ctx->dataConnInfo; QW_SET_EVENT_PROCESSED(ctx, QW_EVENT_FETCH); - QW_ERR_JRET(qwBuildAndSendFetchRsp(ctx->fetchMsgType + 1, &qwMsg->connInfo, rsp, dataLen, code)); + QW_ERR_JRET(qwBuildAndSendFetchRsp(ctx, ctx->fetchMsgType + 1, &qwMsg->connInfo, rsp, dataLen, code)); rsp = NULL; QW_TASK_DLOG("fetch rsp send, handle:%p, code:%x - %s, dataLen:%d", qwMsg->connInfo.handle, code, @@ -897,13 +913,13 @@ int32_t qwProcessCQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg) { QW_SET_EVENT_PROCESSED(ctx, QW_EVENT_FETCH); qwMsg->connInfo = ctx->dataConnInfo; - code = qwBuildAndSendFetchRsp(ctx->fetchMsgType + 1, &qwMsg->connInfo, NULL, 0, code); + code = qwBuildAndSendFetchRsp(ctx, ctx->fetchMsgType + 1, &qwMsg->connInfo, NULL, 0, code); if (TSDB_CODE_SUCCESS != code) { - QW_TASK_ELOG("fetch rsp send fail, handle:%p, code:%x - %s, dataLen:%d", qwMsg->connInfo.handle, code, tstrerror(code), - 0); + QW_TASK_ELOG("fetch rsp send fail, handle:%p, code:%x - %s, dataLen:%d", qwMsg->connInfo.handle, code, + tstrerror(code), 0); } else { - QW_TASK_DLOG("fetch rsp send, handle:%p, code:%x - %s, dataLen:%d", qwMsg->connInfo.handle, code, tstrerror(code), - 0); + QW_TASK_DLOG("fetch rsp send, handle:%p, code:%x - %s, dataLen:%d", qwMsg->connInfo.handle, code, + tstrerror(code), 0); } } @@ -958,6 +974,9 @@ int32_t qwProcessFetch(QW_FPARAMS_DEF, SQWMsg *qwMsg) { qwBuildFetchRsp(rsp, &sOutput, dataLen, rawDataLen, qComplete); if (qComplete) { atomic_store_8((int8_t *)&ctx->queryEnd, true); + if (!ctx->dynamicTask) { + qwFreeSinkHandle(ctx); + } } } @@ -1003,10 +1022,10 @@ _return: } if (!rsped) { - code = qwBuildAndSendFetchRsp(qwMsg->msgType + 1, &qwMsg->connInfo, rsp, dataLen, code); + code = qwBuildAndSendFetchRsp(ctx, qwMsg->msgType + 1, &qwMsg->connInfo, rsp, dataLen, code); if (TSDB_CODE_SUCCESS != code) { - QW_TASK_ELOG("fetch rsp send fail, msgType:%s, handle:%p, code:%x - %s, dataLen:%d", TMSG_INFO(qwMsg->msgType + 1), - qwMsg->connInfo.handle, code, tstrerror(code), dataLen); + QW_TASK_ELOG("fetch rsp send fail, msgType:%s, handle:%p, code:%x - %s, dataLen:%d", + TMSG_INFO(qwMsg->msgType + 1), qwMsg->connInfo.handle, code, tstrerror(code), dataLen); } else { QW_TASK_DLOG("fetch rsp send, msgType:%s, handle:%p, code:%x - %s, dataLen:%d", TMSG_INFO(qwMsg->msgType + 1), qwMsg->connInfo.handle, code, tstrerror(code), dataLen); @@ -1057,9 +1076,10 @@ _return: if (code) { if (ctx) { QW_UPDATE_RSP_CODE(ctx, code); - (void)qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_FAIL, ctx->dynamicTask); // task already failed, no more error handling + (void)qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_FAIL, + ctx->dynamicTask); // task already failed, no more error handling } else { - tmsgReleaseHandle(&qwMsg->connInfo, TAOS_CONN_SERVER); + tmsgReleaseHandle(&qwMsg->connInfo, TAOS_CONN_SERVER, code); } } @@ -1069,7 +1089,7 @@ _return: if (ctx) { if (qwMsg->connInfo.handle != ctx->ctrlConnInfo.handle) { - tmsgReleaseHandle(&qwMsg->connInfo, TAOS_CONN_SERVER); + tmsgReleaseHandle(&qwMsg->connInfo, TAOS_CONN_SERVER, 0); } qwReleaseTaskCtx(mgmt, ctx); @@ -1111,7 +1131,8 @@ _return: if (code) { if (ctx) { QW_UPDATE_RSP_CODE(ctx, code); - (void)qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_FAIL, ctx->dynamicTask); // task already failed, no more error handling + (void)qwUpdateTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_FAIL, + ctx->dynamicTask); // task already failed, no more error handling } } @@ -1135,15 +1156,15 @@ int32_t qwProcessHb(SQWorker *mgmt, SQWMsg *qwMsg, SSchedulerHbReq *req) { QW_RET(qwProcessHbLinkBroken(mgmt, qwMsg, req)); } - QW_ERR_JRET(qwAcquireAddScheduler(mgmt, req->sId, QW_READ, &sch)); - QW_ERR_JRET(qwRegisterHbBrokenLinkArg(mgmt, req->sId, &qwMsg->connInfo)); + QW_ERR_JRET(qwAcquireAddScheduler(mgmt, req->clientId, QW_READ, &sch)); + QW_ERR_JRET(qwRegisterHbBrokenLinkArg(mgmt, req->clientId, &qwMsg->connInfo)); sch->hbBrokenTs = 0; QW_LOCK(QW_WRITE, &sch->hbConnLock); if (sch->hbConnInfo.handle) { - tmsgReleaseHandle(&sch->hbConnInfo, TAOS_CONN_SERVER); + tmsgReleaseHandle(&sch->hbConnInfo, TAOS_CONN_SERVER, 0); sch->hbConnInfo.handle = NULL; } @@ -1152,8 +1173,9 @@ int32_t qwProcessHb(SQWorker *mgmt, SQWMsg *qwMsg, SSchedulerHbReq *req) { QW_UNLOCK(QW_WRITE, &sch->hbConnLock); - QW_DLOG("hb connection updated, sId:%" PRIx64 ", nodeId:%d, fqdn:%s, port:%d, handle:%p, ahandle:%p", req->sId, - req->epId.nodeId, req->epId.ep.fqdn, req->epId.ep.port, qwMsg->connInfo.handle, qwMsg->connInfo.ahandle); + QW_DLOG("hb connection updated, clientId:%" PRIx64 ", nodeId:%d, fqdn:%s, port:%d, handle:%p, ahandle:%p", + req->clientId, req->epId.nodeId, req->epId.ep.fqdn, req->epId.ep.port, qwMsg->connInfo.handle, + qwMsg->connInfo.ahandle); qwReleaseScheduler(QW_READ, mgmt); @@ -1163,7 +1185,7 @@ _return: code = qwBuildAndSendHbRsp(&qwMsg->connInfo, &rsp, code); if (code) { - tmsgReleaseHandle(&qwMsg->connInfo, TAOS_CONN_SERVER); + tmsgReleaseHandle(&qwMsg->connInfo, TAOS_CONN_SERVER, 0); qwMsg->connInfo.handle = NULL; } @@ -1189,13 +1211,20 @@ void qwProcessHbTimerEvent(void *param, void *tmrId) { SQWHbInfo *rspList = NULL; SArray *pExpiredSch = NULL; int32_t code = 0; + int32_t currTs = taosGetTimestampSec(); qwDbgDumpMgmtInfo(mgmt); + qwDbgDumpJobsInfo(); if (gQWDebug.forceStop) { qwStopAllTasks(mgmt); } + if (mgmt->lastChkTs > 0 && (currTs - mgmt->lastChkTs) >= QW_DEFAULT_TIMEOUT_INTERVAL_SECS) { + qwChkDropTimeoutQuery(mgmt, currTs); + mgmt->lastChkTs = currTs; + } + QW_LOCK(QW_READ, &mgmt->schLock); int32_t schNum = taosHashGetSize(mgmt->schHash); @@ -1204,7 +1233,7 @@ void qwProcessHbTimerEvent(void *param, void *tmrId) { if (taosTmrReset(qwProcessHbTimerEvent, QW_DEFAULT_HEARTBEAT_MSEC, param, mgmt->timer, &mgmt->hbTimer)) { qError("reset qworker hb timer error, timer stoppped"); } - (void)qwRelease(refId); // ignore error + (void)qwRelease(refId); // ignore error return; } @@ -1218,7 +1247,7 @@ void qwProcessHbTimerEvent(void *param, void *tmrId) { if (taosTmrReset(qwProcessHbTimerEvent, QW_DEFAULT_HEARTBEAT_MSEC, param, mgmt->timer, &mgmt->hbTimer)) { qError("reset qworker hb timer error, timer stoppped"); } - (void)qwRelease(refId); // ignore error + (void)qwRelease(refId); // ignore error return; } @@ -1229,13 +1258,13 @@ void qwProcessHbTimerEvent(void *param, void *tmrId) { while (pIter) { SQWSchStatus *sch1 = (SQWSchStatus *)pIter; if (NULL == sch1->hbConnInfo.handle) { - uint64_t *sId = taosHashGetKey(pIter, NULL); - QW_TLOG("cancel send hb to sch %" PRIx64 " cause of no connection handle", *sId); + uint64_t *clientId = taosHashGetKey(pIter, NULL); + QW_TLOG("cancel send hb to client %" PRIx64 " cause of no connection handle", *clientId); if (sch1->hbBrokenTs > 0 && ((currentMs - sch1->hbBrokenTs) > QW_SCH_TIMEOUT_MSEC) && taosHashGetSize(sch1->tasksHash) <= 0) { - if (NULL == taosArrayPush(pExpiredSch, sId)) { - QW_ELOG("add sId 0x%" PRIx64 " to expiredSch failed, code:%x", *sId, terrno); + if (NULL == taosArrayPush(pExpiredSch, clientId)) { + QW_ELOG("add clientId 0x%" PRIx64 " to expiredSch failed, code:%x", *clientId, terrno); taosHashCancelIterate(mgmt->schHash, pIter); break; } @@ -1260,7 +1289,7 @@ _return: QW_UNLOCK(QW_READ, &mgmt->schLock); for (int32_t j = 0; j < i; ++j) { - (void)qwBuildAndSendHbRsp(&rspList[j].connInfo, &rspList[j].rsp, code); // ignore error + (void)qwBuildAndSendHbRsp(&rspList[j].connInfo, &rspList[j].rsp, code); // ignore error /*QW_DLOG("hb rsp send, handle:%p, code:%x - %s, taskNum:%d", rspList[j].connInfo.handle, code, tstrerror(code),*/ /*(rspList[j].rsp.taskStatus ? (int32_t)taosArrayGetSize(rspList[j].rsp.taskStatus) : 0));*/ tFreeSSchedulerHbRsp(&rspList[j].rsp); @@ -1277,7 +1306,7 @@ _return: qError("reset qworker hb timer error, timer stoppped"); } - (void)qwRelease(refId); // ignore error + (void)qwRelease(refId); // ignore error } int32_t qwProcessDelete(QW_FPARAMS_DEF, SQWMsg *qwMsg, SDeleteRes *pRes) { @@ -1288,15 +1317,14 @@ int32_t qwProcessDelete(QW_FPARAMS_DEF, SQWMsg *qwMsg, SDeleteRes *pRes) { SQWTaskCtx ctx = {0}; code = qMsgToSubplan(qwMsg->msg, qwMsg->msgLen, &plan); + if (TSDB_CODE_SUCCESS != code) { code = TSDB_CODE_INVALID_MSG; QW_TASK_ELOG("task physical plan to subplan failed, code:%x - %s", code, tstrerror(code)); QW_ERR_JRET(code); } - tsEnableRandErr = true; code = qCreateExecTask(qwMsg->node, mgmt->nodeId, tId, plan, &pTaskInfo, &sinkHandle, 0, NULL, OPTR_EXEC_MODEL_BATCH); - tsEnableRandErr = false; if (code) { QW_TASK_ELOG("qCreateExecTask failed, code:%x - %s", code, tstrerror(code)); @@ -1313,18 +1341,24 @@ int32_t qwProcessDelete(QW_FPARAMS_DEF, SQWMsg *qwMsg, SDeleteRes *pRes) { ctx.taskHandle = pTaskInfo; ctx.sinkHandle = sinkHandle; + uint64_t flags = 0; + dsGetSinkFlags(sinkHandle, &flags); + + ctx.sinkWithMemPool = flags & DS_FLAG_USE_MEMPOOL; + QW_ERR_JRET(qwExecTask(QW_FPARAMS(), &ctx, NULL)); QW_ERR_JRET(qwGetDeleteResFromSink(QW_FPARAMS(), &ctx, pRes)); _return: - qwFreeTaskCtx(&ctx); + qwFreeTaskCtx(QW_FPARAMS(), &ctx); QW_RET(TSDB_CODE_SUCCESS); } int32_t qWorkerInit(int8_t nodeType, int32_t nodeId, void **qWorkerMgmt, const SMsgCb *pMsgCb) { + int32_t code = TSDB_CODE_SUCCESS; if (NULL == qWorkerMgmt || (pMsgCb && pMsgCb->mgmt == NULL)) { qError("invalid param to init qworker"); QW_RET(TSDB_CODE_QRY_INVALID_INPUT); @@ -1335,7 +1369,7 @@ int32_t qWorkerInit(int8_t nodeType, int32_t nodeId, void **qWorkerMgmt, const S TAOS_MEMSET(gQwMgmt.param, 0, sizeof(gQwMgmt.param)); } - int32_t code = qwOpenRef(); + code = qwOpenRef(); if (code) { (void)atomic_sub_fetch_32(&gQwMgmt.qwNum, 1); QW_RET(code); @@ -1370,7 +1404,7 @@ int32_t qWorkerInit(int8_t nodeType, int32_t nodeId, void **qWorkerMgmt, const S mgmt->timer = taosTmrInit(0, 0, 0, "qworker"); if (NULL == mgmt->timer) { qError("init timer failed, error:%s", tstrerror(terrno)); - QW_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY); + QW_ERR_JRET(terrno); } mgmt->nodeType = nodeType; @@ -1393,9 +1427,13 @@ int32_t qWorkerInit(int8_t nodeType, int32_t nodeId, void **qWorkerMgmt, const S mgmt->hbTimer = taosTmrStart(qwProcessHbTimerEvent, QW_DEFAULT_HEARTBEAT_MSEC, (void *)param, mgmt->timer); if (NULL == mgmt->hbTimer) { qError("start hb timer failed"); - QW_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY); + QW_ERR_JRET(terrno); } + QW_ERR_JRET(qExecutorInit()); + + mgmt->lastChkTs = taosGetTimestampSec(); + *qWorkerMgmt = mgmt; qDebug("qworker initialized, type:%d, id:%d, handle:%p", mgmt->nodeType, mgmt->nodeId, mgmt); @@ -1405,7 +1443,7 @@ int32_t qWorkerInit(int8_t nodeType, int32_t nodeId, void **qWorkerMgmt, const S _return: if (mgmt->refId >= 0) { - (void)qwRelease(mgmt->refId); // ignore error + (void)qwRelease(mgmt->refId); // ignore error } else { taosHashCleanup(mgmt->schHash); taosHashCleanup(mgmt->ctxHash); @@ -1506,8 +1544,9 @@ int32_t qWorkerProcessLocalQuery(void *pMgmt, uint64_t sId, uint64_t qId, uint64 if (NULL == rHandle.pMsgCb) { QW_ERR_JRET(terrno); } - + rHandle.pMsgCb->clientRpc = qwMsg->connInfo.handle; + rHandle.localExec = true; code = qCreateExecTask(&rHandle, mgmt->nodeId, tId, plan, &pTaskInfo, &sinkHandle, 0, NULL, OPTR_EXEC_MODEL_BATCH); if (code) { @@ -1575,6 +1614,9 @@ int32_t qWorkerProcessLocalFetch(void *pMgmt, uint64_t sId, uint64_t qId, uint64 qwBuildFetchRsp(rsp, &sOutput, dataLen, rawLen, qComplete); if (qComplete) { atomic_store_8((int8_t *)&ctx->queryEnd, true); + if (!ctx->dynamicTask) { + qwFreeSinkHandle(ctx); + } } break; @@ -1590,3 +1632,70 @@ _return: QW_RET(code); } + +void qWorkerRetireJob(uint64_t jobId, uint64_t clientId, int32_t errCode) { + char id[sizeof(jobId) + sizeof(clientId) + 1] = {0}; + QW_SET_QCID(id, jobId, clientId); + + SQWJobInfo *pJob = (SQWJobInfo *)taosHashGet(gQueryMgmt.pJobInfo, id, sizeof(id)); + if (NULL == pJob) { + qError("QID:0x%" PRIx64 " CID:0x%" PRIx64 " fail to get job from job hash", jobId, clientId); + return; + } + + if (0 == atomic_val_compare_exchange_32(&pJob->errCode, 0, errCode) && + 0 == atomic_val_compare_exchange_8(&pJob->retired, 0, 1)) { + qDebug("QID:0x%" PRIx64 " CID:0x%" PRIx64 " mark retired, errCode: 0x%x, allocSize:%" PRId64, jobId, clientId, + errCode, atomic_load_64(&pJob->memInfo->allocMemSize)); + + (void)qwRetireJob(pJob); + } else { + qDebug("QID:0x%" PRIx64 " already retired, retired: %d, errCode: 0x%x, allocSize:%" PRId64, jobId, + atomic_load_8(&pJob->retired), atomic_load_32(&pJob->errCode), atomic_load_64(&pJob->memInfo->allocMemSize)); + } +} + +void qWorkerRetireJobs(int64_t retireSize, int32_t errCode) { + qDebug("need to retire jobs in batch, targetRetireSize:%" PRId64 ", remainJobNum:%d, task initNum:%" PRId64 " - %" PRId64 + ", task destroyNum:%" PRId64 " - %" PRId64 " - %" PRId64, + retireSize, taosHashGetSize(gQueryMgmt.pJobInfo), atomic_load_64(&gQueryMgmt.stat.taskInitNum), atomic_load_64(&gQueryMgmt.stat.taskRunNum), + atomic_load_64(&gQueryMgmt.stat.taskExecDestroyNum), atomic_load_64(&gQueryMgmt.stat.taskSinkDestroyNum), + atomic_load_64(&gQueryMgmt.stat.taskDestroyNum)); + + SQWJobInfo* pJob = (SQWJobInfo*)taosHashIterate(gQueryMgmt.pJobInfo, NULL); + int32_t jobNum = 0; + int32_t alreadyJobNum = 0; + int64_t retiredSize = 0; + while (retiredSize < retireSize && NULL != pJob && jobNum < QW_RETIRE_JOB_BATCH_NUM) { + if (atomic_load_8(&pJob->retired)) { + pJob = (SQWJobInfo*)taosHashIterate(gQueryMgmt.pJobInfo, pJob); + alreadyJobNum++; + continue; + } + + if (0 == atomic_val_compare_exchange_32(&pJob->errCode, 0, errCode) && 0 == atomic_val_compare_exchange_8(&pJob->retired, 0, 1)) { + int64_t aSize = atomic_load_64(&pJob->memInfo->allocMemSize); + bool retired = qwRetireJob(pJob); + + retiredSize += aSize; + + jobNum++; + + qDebug("QID:0x%" PRIx64 " CID:0x%" PRIx64 " job mark retired in batch, retired:%d, usedSize:%" PRId64 ", retireSize:%" PRId64, + pJob->memInfo->jobId, pJob->memInfo->clientId, retired, aSize, retireSize); + } else { + qDebug("QID:0x%" PRIx64 " CID:0x%" PRIx64 " job may already failed, errCode:%s", pJob->memInfo->jobId, pJob->memInfo->clientId, tstrerror(pJob->errCode)); + } + + pJob = (SQWJobInfo *)taosHashIterate(gQueryMgmt.pJobInfo, pJob); + } + + taosHashCancelIterate(gQueryMgmt.pJobInfo, pJob); + + qDebug("job retire in batch done, [prev:%d, curr:%d, total:%d] jobs, direct retiredSize:%" PRId64 " targetRetireSize:%" PRId64 + ", task initNum:%" PRId64 " - %" PRId64 ", task destroyNum:%" PRId64 " - %" PRId64 " - %" PRId64, + alreadyJobNum, jobNum, taosHashGetSize(gQueryMgmt.pJobInfo), retiredSize, retireSize, + atomic_load_64(&gQueryMgmt.stat.taskInitNum), atomic_load_64(&gQueryMgmt.stat.taskRunNum), + atomic_load_64(&gQueryMgmt.stat.taskExecDestroyNum), atomic_load_64(&gQueryMgmt.stat.taskSinkDestroyNum), + atomic_load_64(&gQueryMgmt.stat.taskDestroyNum)); +} diff --git a/source/libs/scalar/src/scalar.c b/source/libs/scalar/src/scalar.c index 8c6db7b8ce..9a369cd4c4 100644 --- a/source/libs/scalar/src/scalar.c +++ b/source/libs/scalar/src/scalar.c @@ -51,7 +51,6 @@ int32_t sclCreateColumnInfoData(SDataType *pType, int32_t numOfRows, SScalarPara int32_t code = colInfoDataEnsureCapacity(pColumnData, numOfRows, true); if (code != TSDB_CODE_SUCCESS) { - terrno = TSDB_CODE_OUT_OF_MEMORY; colDataDestroy(pColumnData); taosMemoryFree(pColumnData); return terrno; @@ -1235,7 +1234,7 @@ EDealRes sclRewriteFunction(SNode **pNode, SScalarCtx *ctx) { sclError("calloc %d failed", len); sclFreeParam(&output); nodesDestroyNode((SNode *)res); - ctx->code = TSDB_CODE_OUT_OF_MEMORY; + ctx->code = terrno; return DEAL_RES_ERROR; } (void)memcpy(res->datum.p, output.columnData->pData, len); @@ -1246,7 +1245,7 @@ EDealRes sclRewriteFunction(SNode **pNode, SScalarCtx *ctx) { sclError("calloc %d failed", (int)(varDataTLen(output.columnData->pData) + 1)); sclFreeParam(&output); nodesDestroyNode((SNode *)res); - ctx->code = TSDB_CODE_OUT_OF_MEMORY; + ctx->code = terrno; return DEAL_RES_ERROR; } (void)memcpy(res->datum.p, output.columnData->pData, varDataTLen(output.columnData->pData)); @@ -1440,7 +1439,7 @@ EDealRes sclRewriteCaseWhen(SNode **pNode, SScalarCtx *ctx) { sclError("calloc %d failed", (int)(varDataTLen(output.columnData->pData) + 1)); sclFreeParam(&output); nodesDestroyNode((SNode *)res); - ctx->code = TSDB_CODE_OUT_OF_MEMORY; + ctx->code = terrno; return DEAL_RES_ERROR; } (void)memcpy(res->datum.p, output.columnData->pData, varDataTLen(output.columnData->pData)); @@ -1494,7 +1493,7 @@ EDealRes sclWalkFunction(SNode *pNode, SScalarCtx *ctx) { } if (taosHashPut(ctx->pRes, &pNode, POINTER_BYTES, &output, sizeof(output))) { - ctx->code = TSDB_CODE_OUT_OF_MEMORY; + ctx->code = terrno; sclFreeParam(&output); return DEAL_RES_ERROR; } @@ -1513,7 +1512,7 @@ EDealRes sclWalkLogic(SNode *pNode, SScalarCtx *ctx) { } if (taosHashPut(ctx->pRes, &pNode, POINTER_BYTES, &output, sizeof(output))) { - ctx->code = TSDB_CODE_OUT_OF_MEMORY; + ctx->code = terrno; sclFreeParam(&output); return DEAL_RES_ERROR; } @@ -1532,7 +1531,7 @@ EDealRes sclWalkOperator(SNode *pNode, SScalarCtx *ctx) { } if (taosHashPut(ctx->pRes, &pNode, POINTER_BYTES, &output, sizeof(output))) { - ctx->code = TSDB_CODE_OUT_OF_MEMORY; + ctx->code = terrno; sclFreeParam(&output); return DEAL_RES_ERROR; } @@ -1613,7 +1612,7 @@ EDealRes sclWalkCaseWhen(SNode *pNode, SScalarCtx *ctx) { } if (taosHashPut(ctx->pRes, &pNode, POINTER_BYTES, &output, sizeof(output))) { - ctx->code = TSDB_CODE_OUT_OF_MEMORY; + ctx->code = terrno; return DEAL_RES_ERROR; } diff --git a/source/libs/scalar/src/sclvector.c b/source/libs/scalar/src/sclvector.c index 393bb947cf..fd1bd927b0 100644 --- a/source/libs/scalar/src/sclvector.c +++ b/source/libs/scalar/src/sclvector.c @@ -1078,7 +1078,7 @@ int32_t vectorConvertSingleCol(SScalarParam *input, SScalarParam *output, int32_ int32_t code = sclCreateColumnInfoData(&t, input->numOfRows, output); if (code != TSDB_CODE_SUCCESS) { - return TSDB_CODE_OUT_OF_MEMORY; + return code; } code = vectorConvertSingleColImpl(input, output, NULL, startIndex, numOfRows); diff --git a/source/libs/scalar/test/filter/filterTests.cpp b/source/libs/scalar/test/filter/filterTests.cpp index 8bbadd0e22..98eded7363 100644 --- a/source/libs/scalar/test/filter/filterTests.cpp +++ b/source/libs/scalar/test/filter/filterTests.cpp @@ -74,7 +74,7 @@ int32_t flttMakeValueNode(SNode **pNode, int32_t dataType, void *value) { if (IS_VAR_DATA_TYPE(dataType)) { vnode->datum.p = (char *)taosMemoryMalloc(varDataTLen(value)); if (NULL == vnode->datum.p) { - FLT_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + FLT_ERR_RET(terrno); } varDataCopy(vnode->datum.p, value); vnode->node.resType.bytes = varDataLen(value); diff --git a/source/libs/scalar/test/scalar/scalarTests.cpp b/source/libs/scalar/test/scalar/scalarTests.cpp index 6a5188f208..3eae06d9bb 100644 --- a/source/libs/scalar/test/scalar/scalarTests.cpp +++ b/source/libs/scalar/test/scalar/scalarTests.cpp @@ -94,7 +94,7 @@ int32_t scltAppendReservedSlot(SArray *pBlockList, int16_t *dataBlockId, int16_t SSDataBlock *res = NULL; int32_t code = createDataBlock(&res); if (code != 0 || NULL == res->pDataBlock) { - SCL_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + SCL_ERR_RET(code); } SColumnInfoData idata = {0}; @@ -121,7 +121,7 @@ int32_t scltAppendReservedSlot(SArray *pBlockList, int16_t *dataBlockId, int16_t } if (NULL == taosArrayPush(pBlockList, &res)) { - SCL_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + SCL_ERR_RET(terrno); } *dataBlockId = taosArrayGetSize(pBlockList) - 1; res->info.id.blockId = *dataBlockId; @@ -161,7 +161,7 @@ int32_t scltMakeValueNode(SNode **pNode, int32_t dataType, void *value) { if (IS_VAR_DATA_TYPE(dataType)) { vnode->datum.p = (char *)taosMemoryMalloc(varDataTLen(value)); if (NULL == vnode->datum.p) { - SCL_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + SCL_ERR_RET(terrno); } varDataCopy(vnode->datum.p, value); vnode->node.resType.bytes = varDataTLen(value); @@ -1385,7 +1385,7 @@ int32_t makeCalculate(void *json, void *key, int32_t rightType, void *rightData, SCL_ERR_RET(makeJsonArrow(&src, &opNode, json, (char *)key)); if (NULL == taosArrayPush(blockList, &src)) { - SCL_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + SCL_ERR_RET(terrno); } SCL_ERR_RET(makeOperator(&opNode, blockList, opType, rightType, rightData, isReverse)); @@ -2483,7 +2483,7 @@ TEST(columnTest, greater_and_lower) { int32_t scltMakeDataBlock(SScalarParam **pInput, int32_t type, void *pVal, int32_t num, bool setVal) { SScalarParam *input = (SScalarParam *)taosMemoryCalloc(1, sizeof(SScalarParam)); if (NULL == input) { - SCL_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + SCL_ERR_RET(terrno); } int32_t bytes; switch (type) { @@ -2515,7 +2515,7 @@ int32_t scltMakeDataBlock(SScalarParam **pInput, int32_t type, void *pVal, int32 input->columnData = (SColumnInfoData *)taosMemoryCalloc(1, sizeof(SColumnInfoData)); if (NULL == input->columnData) { - SCL_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + SCL_ERR_RET(terrno); } input->numOfRows = num; diff --git a/source/libs/scheduler/inc/schInt.h b/source/libs/scheduler/inc/schInt.h index ef643852ea..607f43a06f 100644 --- a/source/libs/scheduler/inc/schInt.h +++ b/source/libs/scheduler/inc/schInt.h @@ -144,7 +144,7 @@ typedef struct SSchedulerCfg { typedef struct SSchedulerMgmt { uint64_t clientId; // unique clientId uint64_t taskId; // sequential taksId - uint64_t sId; // schedulerId + uint64_t seriousId; // sequential seriousId SSchedulerCfg cfg; bool exit; int32_t jobRef; @@ -163,6 +163,7 @@ typedef struct SSchCallbackParamHeader { typedef struct SSchTaskCallbackParam { SSchCallbackParamHeader head; uint64_t queryId; + uint64_t seriousId; int64_t refId; uint64_t clientId; uint64_t taskId; @@ -218,6 +219,7 @@ typedef struct SSchRedirectCtx { } SSchRedirectCtx; typedef struct SSchTimerParam { + int8_t exit; int64_t rId; uint64_t queryId; uint64_t taskId; @@ -226,6 +228,8 @@ typedef struct SSchTimerParam { typedef struct SSchTask { uint64_t clientId; // current client id uint64_t taskId; // task id + uint64_t seriousId; + uint64_t failedSeriousId; SRWLatch lock; // task reentrant lock int32_t maxExecTimes; // task max exec times int32_t maxRetryTimes; // task max retry times @@ -254,6 +258,7 @@ typedef struct SSchTask { SArray *parents; // the data destination tasks, get data from current task, element is SQueryTask* void *handle; // task send handle bool registerdHb; // registered in hb + SSchTimerParam delayLaunchPar; } SSchTask; typedef struct SSchJobAttr { @@ -274,6 +279,7 @@ typedef struct { typedef struct SSchJob { int64_t refId; uint64_t queryId; + uint64_t seriousId; SSchJobAttr attr; int32_t levelNum; int32_t taskNum; @@ -406,8 +412,13 @@ extern SSchedulerMgmt schMgmt; (SCH_NETWORK_ERR(_code) && ((_task)->level->level > (_job)->levelIdx)) #define SCH_TASK_RETRY_NETWORK_ERR(_task, _code) (SCH_NETWORK_ERR(_code) && (_task)->redirectCtx.inRedirect) +#if 0 #define SCH_JOB_NEED_RETRY(_job, _task, _msgType, _code) \ (SCH_REDIRECT_MSGTYPE(_msgType) && SCH_TOP_LEVEL_NETWORK_ERR(_job, _task, _code)) +#else +#define SCH_JOB_NEED_RETRY(_job, _task, _msgType, _code) \ + (SCH_REDIRECT_MSGTYPE(_msgType) && (NEED_SCHEDULER_REDIRECT_ERROR(_code) || SCH_NETWORK_ERR(_code))) +#endif #define SCH_TASKSET_NEED_RETRY(_job, _task, _msgType, _code) \ (SCH_REDIRECT_MSGTYPE(_msgType) && \ (NEED_SCHEDULER_REDIRECT_ERROR(_code) || SCH_LOW_LEVEL_NETWORK_ERR((_job), (_task), (_code)) || \ @@ -451,23 +462,23 @@ extern SSchedulerMgmt schMgmt; (_task)->profile.endTs = us; \ } while (0) -#define SCH_JOB_ELOG(param, ...) qError("QID:0x%" PRIx64 " " param, pJob->queryId, __VA_ARGS__) -#define SCH_JOB_DLOG(param, ...) qDebug("QID:0x%" PRIx64 " " param, pJob->queryId, __VA_ARGS__) +#define SCH_JOB_ELOG(param, ...) qError("QID:0x%" PRIx64 ",SID:%" PRId64 " " param, pJob->queryId, pJob->seriousId, __VA_ARGS__) +#define SCH_JOB_DLOG(param, ...) qDebug("QID:0x%" PRIx64 ",SID:%" PRId64 " " param, pJob->queryId, pJob->seriousId, __VA_ARGS__) #define SCH_TASK_ELOG(param, ...) \ - qError("QID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, pJob->queryId, SCH_CLIENT_ID(pTask), \ + qError("QID:0x%" PRIx64 ",SID:%" PRId64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, pJob->queryId, pJob->seriousId, SCH_CLIENT_ID(pTask), \ SCH_TASK_ID(pTask), SCH_TASK_EID(pTask), __VA_ARGS__) #define SCH_TASK_DLOG(param, ...) \ - qDebug("QID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, pJob->queryId, SCH_CLIENT_ID(pTask), \ + qDebug("QID:0x%" PRIx64 ",SID:%" PRId64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, pJob->queryId, pJob->seriousId, SCH_CLIENT_ID(pTask), \ SCH_TASK_ID(pTask), SCH_TASK_EID(pTask), __VA_ARGS__) #define SCH_TASK_TLOG(param, ...) \ - qTrace("QID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, pJob->queryId, SCH_CLIENT_ID(pTask), \ + qTrace("QID:0x%" PRIx64 ",SID:%" PRId64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, pJob->queryId, pJob->seriousId, SCH_CLIENT_ID(pTask), \ SCH_TASK_ID(pTask), SCH_TASK_EID(pTask), __VA_ARGS__) #define SCH_TASK_DLOGL(param, ...) \ - qDebugL("QID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, pJob->queryId, SCH_CLIENT_ID(pTask), \ + qDebugL("QID:0x%" PRIx64 ",SID:%" PRId64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, pJob->queryId, pJob->seriousId, SCH_CLIENT_ID(pTask), \ SCH_TASK_ID(pTask), SCH_TASK_EID(pTask), __VA_ARGS__) #define SCH_TASK_WLOG(param, ...) \ - qWarn("QID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, pJob->queryId, SCH_CLIENT_ID(pTask), \ + qWarn("QID:0x%" PRIx64 ",SID:%" PRId64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 ",EID:%d " param, pJob->queryId, pJob->seriousId, SCH_CLIENT_ID(pTask), \ SCH_TASK_ID(pTask), SCH_TASK_EID(pTask), __VA_ARGS__) #define SCH_SET_ERRNO(_err) \ @@ -618,7 +629,7 @@ void schCloseJobRef(void); int32_t schAsyncExecJob(SSchedulerReq *pReq, int64_t *pJob); int32_t schJobFetchRows(SSchJob *pJob); int32_t schJobFetchRowsA(SSchJob *pJob); -int32_t schUpdateTaskHandle(SSchJob *pJob, SSchTask *pTask, bool dropExecNode, void *handle, int32_t execId); +int32_t schUpdateTaskHandle(SSchJob *pJob, SSchTask *pTask, bool dropExecNode, void *handle, uint64_t seriousId, int32_t execId); int32_t schProcessOnTaskStatusRsp(SQueryNodeEpId *pEpId, SArray *pStatusList); int32_t schDumpEpSet(SEpSet *pEpSet, char **ppRes); char *schGetOpStr(SCH_OP_TYPE type); @@ -649,6 +660,7 @@ void schDropTaskInHashList(SSchJob *pJob, SHashObj *list); int32_t schNotifyTaskInHashList(SSchJob *pJob, SHashObj *list, ETaskNotifyType type, SSchTask *pTask); int32_t schLaunchLevelTasks(SSchJob *pJob, SSchLevel *level); void schGetTaskFromList(SHashObj *pTaskList, uint64_t taskId, SSchTask **pTask); +void schStopTaskDelayTimer(SSchJob *pJob, SSchTask* pTask, bool syncOp); int32_t schValidateSubplan(SSchJob *pJob, SSubplan *pSubplan, int32_t level, int32_t idx, int32_t taskNum); int32_t schInitTask(SSchJob *pJob, SSchTask *pTask, SSubplan *pPlan, SSchLevel *pLevel); int32_t schSwitchTaskCandidateAddr(SSchJob *pJob, SSchTask *pTask); diff --git a/source/libs/scheduler/src/schJob.c b/source/libs/scheduler/src/schJob.c index 375a316185..25052d2c15 100644 --- a/source/libs/scheduler/src/schJob.c +++ b/source/libs/scheduler/src/schJob.c @@ -345,6 +345,9 @@ int32_t schValidateAndBuildJob(SQueryPlan *pDag, SSchJob *pJob) { pJob->levelNum = levelNum; SCH_RESET_JOB_LEVEL_IDX(pJob); + + atomic_add_fetch_64(&pJob->seriousId, 1); + SCH_JOB_DLOG("job seriousId set to 0x%" PRIx64, pJob->seriousId); SSchLevel level = {0}; SNodeListNode *plans = NULL; @@ -674,7 +677,7 @@ int32_t schLaunchJobLowerLevel(SSchJob *pJob, SSchTask *pTask) { continue; } - SCH_ERR_RET(schLaunchTask(pJob, pTask)); + SCH_ERR_RET(schDelayLaunchTask(pJob, pTask)); } } @@ -994,17 +997,34 @@ int32_t schChkResetJobRetry(SSchJob *pJob, int32_t rspCode) { return TSDB_CODE_SUCCESS; } -int32_t schResetJobForRetry(SSchJob *pJob, int32_t rspCode, bool *inRetry) { - int8_t origInRetry = atomic_val_compare_exchange_8(&pJob->inRetry, 0, 1); - if (0 != origInRetry) { - SCH_JOB_DLOG("job already in retry, origInRetry: %d", pJob->inRetry); - return TSDB_CODE_SCH_IGNORE_ERROR; +int32_t schResetJobForRetry(SSchJob *pJob, SSchTask *pTask, int32_t rspCode, bool *inRetry) { + while (true) { + if (pTask->seriousId < atomic_load_64(&pJob->seriousId)) { + SCH_TASK_DLOG("task sId %" PRId64 " is smaller than current job sId %" PRId64, pTask->seriousId, pJob->seriousId); + return TSDB_CODE_SCH_IGNORE_ERROR; + } + + int8_t origInRetry = atomic_val_compare_exchange_8(&pJob->inRetry, 0, 1); + if (0 != origInRetry) { + SCH_JOB_DLOG("job already in retry, origInRetry: %d", pJob->inRetry); + taosUsleep(1); + continue; + } + + if (pTask->seriousId < atomic_load_64(&pJob->seriousId)) { + SCH_TASK_DLOG("task sId %" PRId64 " is smaller than current job sId %" PRId64, pTask->seriousId, pJob->seriousId); + return TSDB_CODE_SCH_IGNORE_ERROR; + } + + break; } *inRetry = true; SCH_ERR_RET(schChkResetJobRetry(pJob, rspCode)); + atomic_add_fetch_64(&pJob->seriousId, 1); + int32_t code = 0; int32_t numOfLevels = taosArrayGetSize(pJob->levels); for (int32_t i = 0; i < numOfLevels; ++i) { @@ -1031,13 +1051,19 @@ int32_t schResetJobForRetry(SSchJob *pJob, int32_t rspCode, bool *inRetry) { SCH_UNLOCK_TASK(pTask); SCH_RET(code); } - qClearSubplanExecutionNode(pTask->plan); schResetTaskForRetry(pJob, pTask); + + SCH_LOCK(SCH_WRITE, &pTask->planLock); + qClearSubplanExecutionNode(pTask->plan); + SCH_UNLOCK(SCH_WRITE, &pTask->planLock); + SCH_UNLOCK_TASK(pTask); } } SCH_RESET_JOB_LEVEL_IDX(pJob); + + SCH_JOB_DLOG("update job sId to %" PRId64, pJob->seriousId); return TSDB_CODE_SUCCESS; } @@ -1053,7 +1079,7 @@ int32_t schHandleJobRetry(SSchJob *pJob, SSchTask *pTask, SDataBuf *pMsg, int32_ SCH_TASK_DLOG("start to redirect all job tasks cause of error: %s", tstrerror(rspCode)); - SCH_ERR_JRET(schResetJobForRetry(pJob, rspCode, &inRetry)); + SCH_ERR_JRET(schResetJobForRetry(pJob, pTask, rspCode, &inRetry)); SCH_ERR_JRET(schLaunchJob(pJob)); diff --git a/source/libs/scheduler/src/schRemote.c b/source/libs/scheduler/src/schRemote.c index 3321fdb4b5..fd255f53cf 100644 --- a/source/libs/scheduler/src/schRemote.c +++ b/source/libs/scheduler/src/schRemote.c @@ -142,7 +142,7 @@ int32_t schProcessExplainRsp(SSchJob *pJob, SSchTask *pTask, SExplainRsp *rsp) { return TSDB_CODE_SUCCESS; } -int32_t schProcessResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t execId, SDataBuf *pMsg, int32_t rspCode) { +int32_t schProcessResponseMsg(SSchJob *pJob, SSchTask *pTask, SDataBuf *pMsg, int32_t rspCode) { int32_t code = 0; int32_t msgSize = pMsg->len; int32_t msgType = pMsg->msgType; @@ -444,27 +444,38 @@ _return: // Note: no more task error processing, handled in function internal -int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t execId, SDataBuf *pMsg, int32_t rspCode) { +int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, uint64_t seriousId, int32_t execId, SDataBuf *pMsg, int32_t rspCode) { int32_t code = 0; int32_t msgType = pMsg->msgType; bool dropExecNode = (msgType == TDMT_SCH_LINK_BROKEN || SCH_NETWORK_ERR(rspCode)); if (SCH_IS_QUERY_JOB(pJob)) { - SCH_ERR_JRET(schUpdateTaskHandle(pJob, pTask, dropExecNode, pMsg->handle, execId)); + SCH_ERR_JRET(schUpdateTaskHandle(pJob, pTask, dropExecNode, pMsg->handle, seriousId, execId)); } SCH_ERR_JRET(schValidateRspMsgType(pJob, pTask, msgType)); + if (pTask->seriousId < atomic_load_64(&pJob->seriousId)) { + SCH_TASK_DLOG("task sId %" PRId64 " is smaller than current job sId %" PRId64, pTask->seriousId, pJob->seriousId); + SCH_ERR_JRET(TSDB_CODE_SCH_IGNORE_ERROR); + } + int32_t reqType = IsReq(pMsg) ? pMsg->msgType : (pMsg->msgType - 1); +#if 0 if (SCH_JOB_NEED_RETRY(pJob, pTask, reqType, rspCode)) { SCH_RET(schHandleJobRetry(pJob, pTask, (SDataBuf *)pMsg, rspCode)); } else if (SCH_TASKSET_NEED_RETRY(pJob, pTask, reqType, rspCode)) { SCH_RET(schHandleTaskSetRetry(pJob, pTask, (SDataBuf *)pMsg, rspCode)); } +#else + if (SCH_JOB_NEED_RETRY(pJob, pTask, reqType, rspCode)) { + SCH_RET(schHandleJobRetry(pJob, pTask, (SDataBuf *)pMsg, rspCode)); + } +#endif pTask->redirectCtx.inRedirect = false; - SCH_RET(schProcessResponseMsg(pJob, pTask, execId, pMsg, rspCode)); + SCH_RET(schProcessResponseMsg(pJob, pTask, pMsg, rspCode)); _return: @@ -482,7 +493,7 @@ int32_t schHandleCallback(void *param, SDataBuf *pMsg, int32_t rspCode) { tstrerror(rspCode)); SCH_ERR_JRET(schProcessOnCbBegin(&pJob, &pTask, pParam->queryId, pParam->refId, pParam->taskId)); - code = schHandleResponseMsg(pJob, pTask, pParam->execId, pMsg, rspCode); + code = schHandleResponseMsg(pJob, pTask, pParam->seriousId, pParam->execId, pMsg, rspCode); pMsg->pData = NULL; schProcessOnCbEnd(pJob, pTask, code); @@ -500,10 +511,10 @@ _return: int32_t schHandleDropCallback(void *param, SDataBuf *pMsg, int32_t code) { SSchTaskCallbackParam *pParam = (SSchTaskCallbackParam *)param; - qDebug("QID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 " drop task rsp received, code:0x%x", pParam->queryId, - pParam->clientId, pParam->taskId, code); + qDebug("QID:0x%" PRIx64 ",SID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 " drop task rsp received, code:0x%x", + pParam->queryId, pParam->seriousId, pParam->clientId, pParam->taskId, code); // called if drop task rsp received code - (void)rpcReleaseHandle(pMsg->handle, TAOS_CONN_CLIENT); // ignore error + (void)rpcReleaseHandle(pMsg->handle, TAOS_CONN_CLIENT, 0); // ignore error if (pMsg->handle == NULL) { qError("sch handle is NULL, may be already released and mem lea"); @@ -517,8 +528,8 @@ int32_t schHandleDropCallback(void *param, SDataBuf *pMsg, int32_t code) { int32_t schHandleNotifyCallback(void *param, SDataBuf *pMsg, int32_t code) { SSchTaskCallbackParam *pParam = (SSchTaskCallbackParam *)param; - qDebug("QID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 " task notify rsp received, code:0x%x", pParam->queryId, - pParam->clientId, pParam->taskId, code); + qDebug("QID:0x%" PRIx64 ",SID:0x%" PRIx64 ",CID:0x%" PRIx64 ",TID:0x%" PRIx64 " task notify rsp received, code:0x%x", + pParam->queryId, pParam->seriousId, pParam->clientId, pParam->taskId, code); if (pMsg) { taosMemoryFree(pMsg->pData); taosMemoryFree(pMsg->pEpSet); @@ -529,7 +540,7 @@ int32_t schHandleNotifyCallback(void *param, SDataBuf *pMsg, int32_t code) { int32_t schHandleLinkBrokenCallback(void *param, SDataBuf *pMsg, int32_t code) { SSchCallbackParamHeader *head = (SSchCallbackParamHeader *)param; - (void)rpcReleaseHandle(pMsg->handle, TAOS_CONN_CLIENT); // ignore error + (void)rpcReleaseHandle(pMsg->handle, TAOS_CONN_CLIENT, 0); // ignore error qDebug("handle %p is broken", pMsg->handle); @@ -559,7 +570,7 @@ int32_t schHandleHbCallback(void *param, SDataBuf *pMsg, int32_t code) { if (code) { qError("hb rsp error:%s", tstrerror(code)); - (void)rpcReleaseHandle(pMsg->handle, TAOS_CONN_CLIENT); // ignore error + (void)rpcReleaseHandle(pMsg->handle, TAOS_CONN_CLIENT, 0); // ignore error SCH_ERR_JRET(code); } @@ -594,6 +605,7 @@ int32_t schMakeCallbackParam(SSchJob *pJob, SSchTask *pTask, int32_t msgType, bo } param->queryId = pJob->queryId; + param->seriousId = pTask->seriousId; param->refId = pJob->refId; param->clientId = SCH_CLIENT_ID(pTask); param->taskId = SCH_TASK_ID(pTask); @@ -651,7 +663,7 @@ int32_t schGenerateCallBackInfo(SSchJob *pJob, SSchTask *pTask, void *msg, uint3 SCH_ERR_JRET(terrno); } - msgSendInfo->paramFreeFp = taosMemoryFree; + msgSendInfo->paramFreeFp = taosAutoMemoryFree; SCH_ERR_JRET(schMakeCallbackParam(pJob, pTask, msgType, isHb, trans, &msgSendInfo->param)); SCH_ERR_JRET(schGetCallbackFp(msgType, &msgSendInfo->fp)); @@ -822,7 +834,7 @@ int32_t schMakeHbRpcCtx(SSchJob *pJob, SSchTask *pTask, SRpcCtx *pCtx) { param->pTrans = pJob->conn.pTrans; pMsgSendInfo->param = param; - pMsgSendInfo->paramFreeFp = taosMemoryFree; + pMsgSendInfo->paramFreeFp = taosAutoMemoryFree; pMsgSendInfo->fp = fp; SRpcCtxVal ctxVal = {.val = pMsgSendInfo, .clone = schCloneSMsgSendInfo}; @@ -942,7 +954,7 @@ int32_t schCloneSMsgSendInfo(void *src, void **dst) { pDst->param = NULL; SCH_ERR_JRET(schCloneCallbackParam(pSrc->param, (SSchCallbackParamHeader **)&pDst->param)); - pDst->paramFreeFp = taosMemoryFree; + pDst->paramFreeFp = taosAutoMemoryFree; *dst = pDst; @@ -1042,7 +1054,7 @@ int32_t schBuildAndSendHbMsg(SQueryNodeEpId *nodeEpId, SArray *taskAction) { int32_t msgType = TDMT_SCH_QUERY_HEARTBEAT; req.header.vgId = nodeEpId->nodeId; - req.sId = schMgmt.sId; + req.clientId = schMgmt.clientId; TAOS_MEMCPY(&req.epId, nodeEpId, sizeof(SQueryNodeEpId)); SCH_LOCK(SCH_READ, &schMgmt.hbLock); @@ -1137,7 +1149,7 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, case TDMT_VND_DELETE: { SVDeleteReq req = {0}; req.header.vgId = addr->nodeId; - req.sId = schMgmt.sId; + req.sId = pTask->seriousId; req.queryId = pJob->queryId; req.clientId = pTask->clientId; req.taskId = pTask->taskId; @@ -1171,7 +1183,7 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, SSubQueryMsg qMsg; qMsg.header.vgId = addr->nodeId; qMsg.header.contLen = 0; - qMsg.sId = schMgmt.sId; + qMsg.sId = pTask->seriousId; qMsg.queryId = pJob->queryId; qMsg.clientId = pTask->clientId; qMsg.taskId = pTask->taskId; @@ -1227,7 +1239,7 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, case TDMT_SCH_MERGE_FETCH: { SResFetchReq req = {0}; req.header.vgId = addr->nodeId; - req.sId = schMgmt.sId; + req.sId = pTask->seriousId; req.queryId = pJob->queryId; req.clientId = pTask->clientId; req.taskId = pTask->taskId; @@ -1255,7 +1267,7 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, STaskDropReq qMsg; qMsg.header.vgId = addr->nodeId; qMsg.header.contLen = 0; - qMsg.sId = schMgmt.sId; + qMsg.sId = pTask->seriousId; qMsg.queryId = pJob->queryId; qMsg.clientId = pTask->clientId; qMsg.taskId = pTask->taskId; @@ -1285,7 +1297,7 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, SCH_ERR_RET(schMakeHbRpcCtx(pJob, pTask, &rpcCtx)); SSchedulerHbReq req = {0}; - req.sId = schMgmt.sId; + req.clientId = schMgmt.clientId; req.header.vgId = addr->nodeId; req.epId.nodeId = addr->nodeId; TAOS_MEMCPY(&req.epId.ep, SCH_GET_CUR_EP(addr), sizeof(SEp)); @@ -1313,7 +1325,7 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, STaskNotifyReq qMsg; qMsg.header.vgId = addr->nodeId; qMsg.header.contLen = 0; - qMsg.sId = schMgmt.sId; + qMsg.sId = pTask->seriousId; qMsg.queryId = pJob->queryId; qMsg.clientId = pTask->clientId; qMsg.taskId = pTask->taskId; diff --git a/source/libs/scheduler/src/schTask.c b/source/libs/scheduler/src/schTask.c index 37249b5418..cb8a68fe4f 100644 --- a/source/libs/scheduler/src/schTask.c +++ b/source/libs/scheduler/src/schTask.c @@ -63,8 +63,10 @@ int32_t schInitTask(SSchJob *pJob, SSchTask *pTask, SSubplan *pPlan, SSchLevel * pTask->plan = pPlan; pTask->level = pLevel; + pTask->seriousId = pJob->seriousId; pTask->execId = -1; pTask->failedExecId = -2; + pTask->failedSeriousId = 0; pTask->timeoutUsec = SCH_DEFAULT_TASK_TIMEOUT_USEC; pTask->clientId = getClientId(); pTask->taskId = schGenTaskId(); @@ -161,16 +163,18 @@ int32_t schUpdateTaskExecNode(SSchJob *pJob, SSchTask *pTask, void *handle, int3 return TSDB_CODE_SUCCESS; } -int32_t schUpdateTaskHandle(SSchJob *pJob, SSchTask *pTask, bool dropExecNode, void *handle, int32_t execId) { +int32_t schUpdateTaskHandle(SSchJob *pJob, SSchTask *pTask, bool dropExecNode, void *handle, uint64_t seriousId, int32_t execId) { if (dropExecNode) { SCH_RET(schDropTaskExecNode(pJob, pTask, handle, execId)); } SCH_ERR_RET(schUpdateTaskExecNode(pJob, pTask, handle, execId)); - if ((execId != pTask->execId || execId <= pTask->failedExecId) || pTask->waitRetry) { // ignore it - SCH_TASK_DLOG("handle not updated since execId %d is already not current execId %d, waitRetry %d", execId, - pTask->execId, pTask->waitRetry); + if ((seriousId != pTask->seriousId || seriousId <= pTask->failedSeriousId) || + (execId != pTask->execId || execId <= pTask->failedExecId) || pTask->waitRetry) { // ignore it + SCH_TASK_DLOG("handle not updated since seriousId:0x%" PRIx64 " or execId:%d is not lastest," + "current seriousId:0x%" PRIx64 " execId %d, failedSeriousId:0x%" PRIx64 " failedExecId:%d, waitRetry %d", + seriousId, execId, pTask->seriousId, pTask->execId, pTask->failedSeriousId, pTask->failedExecId, pTask->waitRetry); SCH_ERR_RET(TSDB_CODE_SCH_IGNORE_ERROR); } @@ -185,6 +189,7 @@ int32_t schProcessOnTaskFailure(SSchJob *pJob, SSchTask *pTask, int32_t errCode) } pTask->failedExecId = pTask->execId; + pTask->failedSeriousId = pTask->seriousId; int8_t jobStatus = 0; if (schJobNeedToStop(pJob, &jobStatus)) { @@ -308,7 +313,7 @@ int32_t schProcessOnTaskSuccess(SSchJob *pJob, SSchTask *pTask) { .type = QUERY_NODE_DOWNSTREAM_SOURCE, .clientId = pTask->clientId, .taskId = pTask->taskId, - .schedId = schMgmt.sId, + .sId = pTask->seriousId, .execId = pTask->execId, .addr = pTask->succeedAddr, .fetchMsgType = SCH_FETCH_TYPE(pTask), @@ -326,7 +331,13 @@ int32_t schProcessOnTaskSuccess(SSchJob *pJob, SSchTask *pTask) { if (SCH_TASK_READY_FOR_LAUNCH(readyNum, parent)) { SCH_TASK_DLOG("all %d children task done, start to launch parent task 0x%" PRIx64, readyNum, parent->taskId); - SCH_ERR_RET(schLaunchTask(pJob, parent)); + + parent->seriousId = pJob->seriousId; + TSWAP(pTask, parent); + SCH_TASK_DLOG("task seriousId set to 0x%" PRIx64, pTask->seriousId); + TSWAP(pTask, parent); + + SCH_ERR_RET(schDelayLaunchTask(pJob, parent)); } } @@ -403,9 +414,11 @@ int32_t schChkUpdateRedirectCtx(SSchJob *pJob, SSchTask *pTask, SEpSet *pEpSet, pCtx->periodMs = tsRedirectMaxPeriod; } - int64_t leftTime = tsMaxRetryWaitTime - lastTime; - pTask->delayExecMs = leftTime < pCtx->periodMs ? leftTime : pCtx->periodMs; - + if (SCH_IS_DATA_BIND_TASK(pTask)) { + int64_t leftTime = tsMaxRetryWaitTime - lastTime; + pTask->delayExecMs = leftTime < pCtx->periodMs ? leftTime : pCtx->periodMs; + } + pCtx->roundTimes = 0; goto _return; @@ -424,12 +437,11 @@ _return: void schResetTaskForRetry(SSchJob *pJob, SSchTask *pTask) { pTask->waitRetry = true; - schDropTaskOnExecNode(pJob, pTask); if (pTask->delayTimer) { - if (!taosTmrStopA(&pTask->delayTimer)) { - SCH_TASK_WLOG("stop task delayTimer failed, may stopped, status:%d", pTask->status); - } + taosTmrStop(pTask->delayTimer); } + + schDropTaskOnExecNode(pJob, pTask); taosHashClear(pTask->execNodes); (void)schRemoveTaskFromExecList(pJob, pTask); // ignore error schDeregisterTaskHb(pJob, pTask); @@ -565,6 +577,7 @@ int32_t schHandleTaskSetRetry(SSchJob *pJob, SSchTask *pTask, SDataBuf *pData, i SCH_ERR_JRET(schResetTaskSetLevelInfo(pJob, pTask)); SCH_RESET_JOB_LEVEL_IDX(pJob); + atomic_add_fetch_64(&pJob->seriousId, 1); code = schDoTaskRedirect(pJob, pTask, pData, rspCode); @@ -585,11 +598,11 @@ int32_t schPushTaskToExecList(SSchJob *pJob, SSchTask *pTask) { int32_t code = taosHashPut(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId), &pTask, POINTER_BYTES); if (0 != code) { if (HASH_NODE_EXIST(code)) { - SCH_TASK_ELOG("task already in execTask list, code:%x", code); - SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR); + SCH_TASK_DLOG("task already in execTask list, code:%x", code); + return TSDB_CODE_SUCCESS; } - SCH_TASK_ELOG("taosHashPut task to execTask list failed, errno:%d", errno); + SCH_TASK_ELOG("taosHashPut task to execTask list failed, errno:0x%x", errno); SCH_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); } @@ -745,6 +758,10 @@ int32_t schTaskCheckSetRetry(SSchJob *pJob, SSchTask *pTask, int32_t errCode, bo int32_t schHandleTaskRetry(SSchJob *pJob, SSchTask *pTask) { (void)atomic_sub_fetch_32(&pTask->level->taskLaunchedNum, 1); + if (pTask->delayTimer) { + taosTmrStop(pTask->delayTimer); + } + (void)schRemoveTaskFromExecList(pJob, pTask); // ignore error SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_INIT); @@ -767,7 +784,7 @@ int32_t schHandleTaskRetry(SSchJob *pJob, SSchTask *pTask) { SCH_ERR_RET(schSwitchTaskCandidateAddr(pJob, pTask)); } - SCH_ERR_RET(schLaunchTask(pJob, pTask)); + SCH_ERR_RET(schDelayLaunchTask(pJob, pTask)); return TSDB_CODE_SUCCESS; } @@ -1103,7 +1120,10 @@ int32_t schLaunchRemoteTask(SSchJob *pJob, SSchTask *pTask) { int32_t code = 0; if (NULL == pTask->msg) { // TODO add more detailed reason for failure + SCH_LOCK(SCH_WRITE, &pTask->planLock); code = qSubPlanToMsg(plan, &pTask->msg, &pTask->msgLen); + SCH_UNLOCK(SCH_WRITE, &pTask->planLock); + if (TSDB_CODE_SUCCESS != code) { SCH_TASK_ELOG("failed to create physical plan, code:%s, msg:%p, len:%d", tstrerror(code), pTask->msg, pTask->msgLen); @@ -1154,7 +1174,7 @@ int32_t schLaunchLocalTask(SSchJob *pJob, SSchTask *pTask) { } } - SCH_ERR_JRET(qWorkerProcessLocalQuery(schMgmt.queryMgmt, schMgmt.sId, pJob->queryId, pTask->clientId, pTask->taskId, + SCH_ERR_JRET(qWorkerProcessLocalQuery(schMgmt.queryMgmt, pJob->seriousId, pJob->queryId, pTask->clientId, pTask->taskId, pJob->refId, pTask->execId, &qwMsg, explainRes)); if (SCH_IS_EXPLAIN_JOB(pJob)) { @@ -1188,14 +1208,21 @@ int32_t schLaunchTaskImpl(void *param) { SCH_LOCK_TASK(pTask); } - int8_t status = 0; - int32_t code = 0; - - (void)atomic_add_fetch_32(&pTask->level->taskLaunchedNum, 1); pTask->execId++; pTask->retryTimes++; pTask->waitRetry = false; + int8_t status = 0; + int32_t code = 0; + + if (atomic_load_64(&pTask->seriousId) < atomic_load_64(&pJob->seriousId)) { + SCH_TASK_DLOG("task seriousId:0x%" PRIx64 " is smaller than job seriousId:0x%" PRIx64 ", skip launch", + pTask->seriousId, pJob->seriousId); + goto _return; + } + + (void)atomic_add_fetch_32(&pTask->level->taskLaunchedNum, 1); + SCH_TASK_DLOG("start to launch %s task, execId %d, retry %d", SCH_IS_LOCAL_EXEC_TASK(pJob, pTask) ? "LOCAL" : "REMOTE", pTask->execId, pTask->retryTimes); @@ -1294,43 +1321,47 @@ void schHandleTimerEvent(void *param, void *tmrId) { SSchJob *pJob = NULL; int32_t code = 0; + qDebug("delayTimer %" PRIuPTR " is launched", (uintptr_t)tmrId); + int64_t rId = pTimerParam->rId; uint64_t queryId = pTimerParam->queryId; uint64_t taskId = pTimerParam->taskId; - taosMemoryFree(pTimerParam); if (schProcessOnCbBegin(&pJob, &pTask, queryId, rId, taskId)) { return; } - code = schLaunchTask(pJob, pTask); + if (0 == atomic_load_8(&pTask->delayLaunchPar.exit)) { + code = schLaunchTask(pJob, pTask); + } else { + SCH_TASK_DLOG("task will not be launched since query job exiting, status: %d", pTask->status); + } schProcessOnCbEnd(pJob, pTask, code); } int32_t schDelayLaunchTask(SSchJob *pJob, SSchTask *pTask) { if (pTask->delayExecMs > 0) { - SSchTimerParam *param = taosMemoryMalloc(sizeof(SSchTimerParam)); - if (NULL == param) { - SCH_TASK_ELOG("taosMemoryMalloc %d failed", (int)sizeof(SSchTimerParam)); - SCH_ERR_RET(terrno); - } + pTask->delayLaunchPar.rId = pJob->refId; + pTask->delayLaunchPar.queryId = pJob->queryId; + pTask->delayLaunchPar.taskId = pTask->taskId; - param->rId = pJob->refId; - param->queryId = pJob->queryId; - param->taskId = pTask->taskId; + SCH_ERR_RET(schPushTaskToExecList(pJob, pTask)); + SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_EXEC); if (NULL == pTask->delayTimer) { - pTask->delayTimer = taosTmrStart(schHandleTimerEvent, pTask->delayExecMs, (void *)param, schMgmt.timer); + pTask->delayTimer = taosTmrStart(schHandleTimerEvent, pTask->delayExecMs, (void *)&pTask->delayLaunchPar, schMgmt.timer); if (NULL == pTask->delayTimer) { SCH_TASK_ELOG("start delay timer failed, handle:%p", schMgmt.timer); SCH_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); } + SCH_TASK_DLOG("task delayTimer %" PRIuPTR " is started", (uintptr_t)pTask->delayTimer); + return TSDB_CODE_SUCCESS; } - if (taosTmrReset(schHandleTimerEvent, pTask->delayExecMs, (void *)param, schMgmt.timer, &pTask->delayTimer)) { + if (taosTmrReset(schHandleTimerEvent, pTask->delayExecMs, (void *)&pTask->delayLaunchPar, schMgmt.timer, &pTask->delayTimer)) { SCH_TASK_ELOG("taosTmrReset delayExec timer failed, handle:%p", schMgmt.timer); } @@ -1345,8 +1376,11 @@ int32_t schLaunchLevelTasks(SSchJob *pJob, SSchLevel *level) { for (int32_t i = 0; i < level->taskNum; ++i) { SSchTask *pTask = taosArrayGet(level->subTasks, i); + pTask->seriousId = pJob->seriousId; + + SCH_TASK_DLOG("task seriousId set to 0x%" PRIx64, pTask->seriousId); - SCH_ERR_RET(schLaunchTask(pJob, pTask)); + SCH_ERR_RET(schDelayLaunchTask(pJob, pTask)); } return TSDB_CODE_SUCCESS; @@ -1361,12 +1395,11 @@ void schDropTaskInHashList(SSchJob *pJob, SHashObj *list) { while (pIter) { SSchTask *pTask = *(SSchTask **)pIter; - SCH_LOCK_TASK(pTask); if (pTask->delayTimer) { - if (!taosTmrStopA(&pTask->delayTimer)) { - SCH_TASK_WLOG("stop delayTimer failed, status:%d", pTask->status); - } + schStopTaskDelayTimer(pJob, pTask, true); } + + SCH_LOCK_TASK(pTask); schDropTaskOnExecNode(pJob, pTask); SCH_UNLOCK_TASK(pTask); @@ -1414,7 +1447,7 @@ int32_t schExecLocalFetch(SSchJob *pJob, SSchTask *pTask) { } } - SCH_ERR_JRET(qWorkerProcessLocalFetch(schMgmt.queryMgmt, schMgmt.sId, pJob->queryId, pTask->clientId, pTask->taskId, + SCH_ERR_JRET(qWorkerProcessLocalFetch(schMgmt.queryMgmt, pJob->seriousId, pJob->queryId, pTask->clientId, pTask->taskId, pJob->refId, pTask->execId, &pRsp, explainRes)); if (SCH_IS_EXPLAIN_JOB(pJob)) { diff --git a/source/libs/scheduler/src/schUtil.c b/source/libs/scheduler/src/schUtil.c index ac34099417..1eb7dd5281 100644 --- a/source/libs/scheduler/src/schUtil.c +++ b/source/libs/scheduler/src/schUtil.c @@ -22,7 +22,7 @@ #include "tref.h" #include "trpc.h" -FORCE_INLINE int32_t schAcquireJob(int64_t refId, SSchJob** ppJob) { +FORCE_INLINE int32_t schAcquireJob(int64_t refId, SSchJob **ppJob) { qDebug("sch acquire jobId:0x%" PRIx64, refId); *ppJob = (SSchJob *)taosAcquireRef(schMgmt.jobRef, refId); if (NULL == *ppJob) { @@ -41,7 +41,7 @@ FORCE_INLINE int32_t schReleaseJob(int64_t refId) { return taosReleaseRef(schMgmt.jobRef, refId); } -FORCE_INLINE int32_t schReleaseJobEx(int64_t refId, int32_t* released) { +FORCE_INLINE int32_t schReleaseJobEx(int64_t refId, int32_t *released) { if (0 == refId) { return TSDB_CODE_SUCCESS; } @@ -50,7 +50,7 @@ FORCE_INLINE int32_t schReleaseJobEx(int64_t refId, int32_t* released) { return taosReleaseRefEx(schMgmt.jobRef, refId, released); } -int32_t schDumpEpSet(SEpSet *pEpSet, char** ppRes) { +int32_t schDumpEpSet(SEpSet *pEpSet, char **ppRes) { *ppRes = NULL; if (NULL == pEpSet) { return TSDB_CODE_SUCCESS; @@ -89,7 +89,7 @@ char *schGetOpStr(SCH_OP_TYPE type) { } void schFreeHbTrans(SSchHbTrans *pTrans) { - (void)rpcReleaseHandle((void *)pTrans->trans.pHandleId, TAOS_CONN_CLIENT); + (void)rpcReleaseHandle((void *)pTrans->trans.pHandleId, TAOS_CONN_CLIENT, 0); schFreeRpcCtx(&pTrans->rpcCtx); } @@ -202,11 +202,12 @@ void schDeregisterTaskHb(SSchJob *pJob, SSchTask *pTask) { SQueryNodeAddr *addr = taosArrayGet(pTask->candidateAddrs, pTask->candidateIdx); if (NULL == addr) { - SCH_TASK_ELOG("fail to get the %dth condidateAddr in task, totalNum:%d", pTask->candidateIdx, (int32_t)taosArrayGetSize(pTask->candidateAddrs)); + SCH_TASK_ELOG("fail to get the %dth condidateAddr in task, totalNum:%d", pTask->candidateIdx, + (int32_t)taosArrayGetSize(pTask->candidateAddrs)); return; } - SQueryNodeEpId epId = {0}; + SQueryNodeEpId epId = {0}; epId.nodeId = addr->nodeId; @@ -240,11 +241,12 @@ int32_t schEnsureHbConnection(SSchJob *pJob, SSchTask *pTask) { SQueryNodeAddr *addr = taosArrayGet(pTask->candidateAddrs, pTask->candidateIdx); if (NULL == addr) { - SCH_TASK_ELOG("fail to get the %dth condidateAddr in task, totalNum:%d", pTask->candidateIdx, (int32_t)taosArrayGetSize(pTask->candidateAddrs)); + SCH_TASK_ELOG("fail to get the %dth condidateAddr in task, totalNum:%d", pTask->candidateIdx, + (int32_t)taosArrayGetSize(pTask->candidateAddrs)); return TSDB_CODE_SCH_INTERNAL_ERROR; } - SQueryNodeEpId epId = {0}; + SQueryNodeEpId epId = {0}; epId.nodeId = addr->nodeId; @@ -276,8 +278,8 @@ int32_t schUpdateHbConnection(SQueryNodeEpId *epId, SSchTrans *trans) { SCH_UNLOCK(SCH_WRITE, &hb->lock); SCH_UNLOCK(SCH_READ, &schMgmt.hbLock); - qDebug("hb connection updated, sId:0x%" PRIx64 ", nodeId:%d, fqdn:%s, port:%d, pTrans:%p, pHandle:%p", schMgmt.sId, - epId->nodeId, epId->ep.fqdn, epId->ep.port, trans->pTrans, trans->pHandle); + qDebug("hb connection updated, nodeId:%d, fqdn:%s, port:%d, pTrans:%p, pHandle:%p", epId->nodeId, epId->ep.fqdn, + epId->ep.port, trans->pTrans, trans->pHandle); return TSDB_CODE_SUCCESS; } @@ -323,7 +325,8 @@ uint64_t schGenUUID(void) { uint64_t pid = taosGetPId(); int32_t val = atomic_add_fetch_32(&requestSerialId, 1); - uint64_t id = ((uint64_t)((hashId & 0x0FFF)) << 52) | ((pid & 0x0FFF) << 40) | ((ts & 0xFFFFFF) << 16) | (val & 0xFFFF); + uint64_t id = + ((uint64_t)((hashId & 0x0FFF)) << 52) | ((pid & 0x0FFF) << 40) | ((ts & 0xFFFFFF) << 16) | (val & 0xFFFF); return id; } #endif @@ -373,17 +376,17 @@ void schGetTaskFromList(SHashObj *pTaskList, uint64_t taskId, SSchTask **pTask) *pTask = *task; } -int32_t schValidateSubplan(SSchJob *pJob, SSubplan* pSubplan, int32_t level, int32_t idx, int32_t taskNum) { +int32_t schValidateSubplan(SSchJob *pJob, SSubplan *pSubplan, int32_t level, int32_t idx, int32_t taskNum) { if (NULL == pSubplan) { SCH_JOB_ELOG("fail to get the %dth subplan, taskNum: %d, level: %d", idx, taskNum, level); SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); } - + if (QUERY_NODE_PHYSICAL_SUBPLAN != nodeType(pSubplan)) { SCH_JOB_ELOG("invalid subplan type, level:%d, subplanNodeType:%d", level, nodeType(pSubplan)); SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); } - + if (pSubplan->subplanType < SUBPLAN_TYPE_MERGE || pSubplan->subplanType > SUBPLAN_TYPE_COMPUTE) { SCH_JOB_ELOG("invalid subplanType %d, level:%d, subplan idx:%d", pSubplan->subplanType, level, idx); SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); @@ -396,15 +399,17 @@ int32_t schValidateSubplan(SSchJob *pJob, SSubplan* pSubplan, int32_t level, int if (SCH_IS_DATA_BIND_PLAN(pSubplan)) { if (pSubplan->execNode.epSet.numOfEps <= 0) { - SCH_JOB_ELOG("no execNode specifed for data src plan %d, numOfEps:%d", pSubplan->subplanType, pSubplan->execNode.epSet.numOfEps); + SCH_JOB_ELOG("no execNode specifed for data src plan %d, numOfEps:%d", pSubplan->subplanType, + pSubplan->execNode.epSet.numOfEps); SCH_ERR_RET(TSDB_CODE_SCH_DATA_SRC_EP_MISS); } if (pSubplan->execNode.epSet.inUse >= pSubplan->execNode.epSet.numOfEps) { - SCH_JOB_ELOG("invalid epset inUse %d for data src plan %d, numOfEps:%d", pSubplan->execNode.epSet.inUse, pSubplan->subplanType, pSubplan->execNode.epSet.numOfEps); + SCH_JOB_ELOG("invalid epset inUse %d for data src plan %d, numOfEps:%d", pSubplan->execNode.epSet.inUse, + pSubplan->subplanType, pSubplan->execNode.epSet.numOfEps); SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); } } - + if (NULL == pSubplan->pNode && pSubplan->subplanType != SUBPLAN_TYPE_MODIFY) { SCH_JOB_ELOG("empty plan root node, level:%d, subplan idx:%d, subplanType:%d", level, idx, pSubplan->subplanType); SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); @@ -418,4 +423,23 @@ int32_t schValidateSubplan(SSchJob *pJob, SSubplan* pSubplan, int32_t level, int return TSDB_CODE_SUCCESS; } +void schStopTaskDelayTimer(SSchJob *pJob, SSchTask *pTask, bool syncOp) { + SCH_TASK_DLOG("try to stop task delayTimer %" PRIuPTR, (uintptr_t)pTask->delayTimer); + tmr_h delayTimer = pTask->delayTimer; + atomic_store_8(&pTask->delayLaunchPar.exit, 1); + + if (!taosTmrStopA(&pTask->delayTimer)) { + SCH_TASK_DLOG("task delayTimer %" PRIuPTR " not stopped", (uintptr_t)delayTimer); + + if (syncOp) { + while (!taosTmrIsStopped(&delayTimer)) { + taosMsleep(1); + } + + SCH_TASK_DLOG("task delayTimer %" PRIuPTR " is stopped", (uintptr_t)delayTimer); + } else { + SCH_TASK_WLOG("stop task delayTimer %" PRIuPTR " failed, may stopped, status:%d", (uintptr_t)delayTimer, pTask->status); + } + } +} diff --git a/source/libs/scheduler/src/scheduler.c b/source/libs/scheduler/src/scheduler.c index db9ecd6025..21659d9cd5 100644 --- a/source/libs/scheduler/src/scheduler.c +++ b/source/libs/scheduler/src/scheduler.c @@ -56,12 +56,7 @@ int32_t schedulerInit() { SCH_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); } - if (taosGetSystemUUIDU64(&schMgmt.sId)) { - qError("generate schedulerId failed, errno:%d", errno); - SCH_ERR_RET(TSDB_CODE_QRY_SYS_ERROR); - } - - qInfo("scheduler 0x%" PRIx64 " initialized, maxJob:%u", schMgmt.sId, schMgmt.cfg.maxJobNum); + qInfo("scheduler 0x%" PRIx64 " initialized, maxJob:%u", getClientId(), schMgmt.cfg.maxJobNum); return TSDB_CODE_SUCCESS; } @@ -172,7 +167,7 @@ void schedulerFreeJob(int64_t *jobId, int32_t errCode) { SSchJob *pJob = NULL; (void)schAcquireJob(*jobId, &pJob); if (NULL == pJob) { - qWarn("Acquire sch job failed, may be dropped, jobId:0x%" PRIx64, *jobId); + qDebug("Acquire sch job failed, may be dropped, jobId:0x%" PRIx64, *jobId); return; } diff --git a/source/libs/scheduler/test/schedulerTests.cpp b/source/libs/scheduler/test/schedulerTests.cpp index 6e13e37e88..a9878ec9a9 100644 --- a/source/libs/scheduler/test/schedulerTests.cpp +++ b/source/libs/scheduler/test/schedulerTests.cpp @@ -54,7 +54,7 @@ namespace { -extern "C" int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t execId, SDataBuf *pMsg, +extern "C" int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, uint64_t sId, int32_t execId, SDataBuf *pMsg, int32_t rspCode); extern "C" int32_t schHandleCallback(void *param, const SDataBuf *pMsg, int32_t rspCode); @@ -591,7 +591,7 @@ void *schtSendRsp(void *param) { msg.msgType = TDMT_VND_SUBMIT_RSP; msg.pData = rmsg; - (void)schHandleResponseMsg(pJob, task, task->execId, &msg, 0); + (void)schHandleResponseMsg(pJob, task, task->seriousId, task->execId, &msg, 0); pIter = taosHashIterate(pJob->execTasks, pIter); } @@ -621,7 +621,7 @@ void *schtCreateFetchRspThread(void *param) { msg.msgType = TDMT_SCH_MERGE_FETCH_RSP; msg.pData = rmsg; - code = schHandleResponseMsg(pJob, pJob->fetchTask, pJob->fetchTask->execId, &msg, 0); + code = schHandleResponseMsg(pJob, pJob->fetchTask, pJob->fetchTask->seriousId, pJob->fetchTask->execId, &msg, 0); (void)schReleaseJob(job); @@ -925,7 +925,7 @@ TEST(queryTest, normalCase) { msg.msgType = TDMT_SCH_QUERY_RSP; msg.pData = rmsg; - code = schHandleResponseMsg(pJob, task, task->execId, &msg, 0); + code = schHandleResponseMsg(pJob, task, task->seriousId, task->execId, &msg, 0); ASSERT_EQ(code, 0); pIter = taosHashIterate(pJob->execTasks, pIter); @@ -941,7 +941,7 @@ TEST(queryTest, normalCase) { msg.msgType = TDMT_SCH_QUERY_RSP; msg.pData = rmsg; - code = schHandleResponseMsg(pJob, task, task->execId, &msg, 0); + code = schHandleResponseMsg(pJob, task, task->seriousId, task->execId, &msg, 0); ASSERT_EQ(code, 0); } @@ -1040,7 +1040,7 @@ TEST(queryTest, readyFirstCase) { msg.msgType = TDMT_SCH_QUERY_RSP; msg.pData = rmsg; - code = schHandleResponseMsg(pJob, task, task->execId, &msg, 0); + code = schHandleResponseMsg(pJob, task, task->seriousId, task->execId, &msg, 0); ASSERT_EQ(code, 0); pIter = taosHashIterate(pJob->execTasks, pIter); @@ -1057,7 +1057,7 @@ TEST(queryTest, readyFirstCase) { msg.msgType = TDMT_SCH_QUERY_RSP; msg.pData = rmsg; - code = schHandleResponseMsg(pJob, task, task->execId, &msg, 0); + code = schHandleResponseMsg(pJob, task, task->seriousId, task->execId, &msg, 0); ASSERT_EQ(code, 0); } @@ -1163,7 +1163,7 @@ TEST(queryTest, flowCtrlCase) { msg.msgType = TDMT_SCH_QUERY_RSP; msg.pData = rmsg; - code = schHandleResponseMsg(pJob, task, task->execId, &msg, 0); + code = schHandleResponseMsg(pJob, task, task->seriousId, task->execId, &msg, 0); ASSERT_EQ(code, 0); } diff --git a/source/libs/stream/src/streamBackendRocksdb.c b/source/libs/stream/src/streamBackendRocksdb.c index fcfda71dd4..65c1f659c9 100644 --- a/source/libs/stream/src/streamBackendRocksdb.c +++ b/source/libs/stream/src/streamBackendRocksdb.c @@ -4771,8 +4771,8 @@ int32_t dbChkpGetDelta(SDbChkp* p, int64_t chkpId, SArray* list) { return TSDB_CODE_OUT_OF_RANGE; } - taosArrayClearP(p->pAdd, taosMemoryFree); - taosArrayClearP(p->pDel, taosMemoryFree); + taosArrayClearP(p->pAdd, NULL); + taosArrayClearP(p->pDel, NULL); taosHashClear(p->pSstTbl[1 - p->idx]); TdDirPtr pDir = taosOpenDir(p->buf); @@ -4849,8 +4849,8 @@ int32_t dbChkpGetDelta(SDbChkp* p, int64_t chkpId, SArray* list) { int32_t code = compareHashTable(p->pSstTbl[p->idx], p->pSstTbl[1 - p->idx], p->pAdd, p->pDel); if (code != 0) { // dead code - taosArrayClearP(p->pAdd, taosMemoryFree); - taosArrayClearP(p->pDel, taosMemoryFree); + taosArrayClearP(p->pAdd, NULL); + taosArrayClearP(p->pDel, NULL); taosHashClear(p->pSstTbl[1 - p->idx]); p->update = 0; return code; @@ -4946,9 +4946,9 @@ void dbChkpDestroy(SDbChkp* pChkp) { taosMemoryFree(pChkp->buf); taosMemoryFree(pChkp->path); - taosArrayDestroyP(pChkp->pSST, taosMemoryFree); - taosArrayDestroyP(pChkp->pAdd, taosMemoryFree); - taosArrayDestroyP(pChkp->pDel, taosMemoryFree); + taosArrayDestroyP(pChkp->pSST, NULL); + taosArrayDestroyP(pChkp->pAdd, NULL); + taosArrayDestroyP(pChkp->pDel, NULL); taosHashCleanup(pChkp->pSstTbl[0]); taosHashCleanup(pChkp->pSstTbl[1]); @@ -5124,8 +5124,8 @@ int32_t dbChkpDumpTo(SDbChkp* p, char* dname, SArray* list) { TAOS_UNUSED(taosCloseFile(&pFile)); // clear delta data buf - taosArrayClearP(p->pAdd, taosMemoryFree); - taosArrayClearP(p->pDel, taosMemoryFree); + taosArrayClearP(p->pAdd, NULL); + taosArrayClearP(p->pDel, NULL); code = 0; _ERROR: diff --git a/source/libs/stream/src/streamCheckpoint.c b/source/libs/stream/src/streamCheckpoint.c index 01cd201a1b..876cd1b472 100644 --- a/source/libs/stream/src/streamCheckpoint.c +++ b/source/libs/stream/src/streamCheckpoint.c @@ -816,7 +816,7 @@ int32_t uploadCheckpointData(SStreamTask* pTask, int64_t checkpointId, int64_t d stDebug("s-task:%s remove redundant files in uploading checkpointId:%" PRId64 " data", idStr, checkpointId); } - taosArrayDestroyP(toDelFiles, taosMemoryFree); + taosArrayDestroyP(toDelFiles, NULL); double el = (taosGetTimestampMs() - now) / 1000.0; if (code == TSDB_CODE_SUCCESS) { diff --git a/source/libs/stream/src/streamDispatch.c b/source/libs/stream/src/streamDispatch.c index b4fcf1edc9..ad9be63674 100644 --- a/source/libs/stream/src/streamDispatch.c +++ b/source/libs/stream/src/streamDispatch.c @@ -71,7 +71,7 @@ static int32_t tInitStreamDispatchReq(SStreamDispatchReq* pReq, const SStreamTas pReq->data = taosArrayInit(numOfBlocks, POINTER_BYTES); pReq->dataLen = taosArrayInit(numOfBlocks, sizeof(int32_t)); if (pReq->data == NULL || pReq->dataLen == NULL) { - taosArrayDestroyP(pReq->data, taosMemoryFree); + taosArrayDestroyP(pReq->data, NULL); taosArrayDestroy(pReq->dataLen); return terrno; } @@ -234,7 +234,7 @@ int32_t streamSendCheckMsg(SStreamTask* pTask, const SStreamTaskCheckReq* pReq, void destroyDispatchMsg(SStreamDispatchReq* pReq, int32_t numOfVgroups) { for (int32_t i = 0; i < numOfVgroups; i++) { - taosArrayDestroyP(pReq[i].data, taosMemoryFree); + taosArrayDestroyP(pReq[i].data, NULL); taosArrayDestroy(pReq[i].dataLen); } diff --git a/source/libs/tfs/src/tfs.c b/source/libs/tfs/src/tfs.c index 2c97a9ac85..4ac72e8918 100644 --- a/source/libs/tfs/src/tfs.c +++ b/source/libs/tfs/src/tfs.c @@ -202,8 +202,6 @@ bool tfsIsSameFile(const STfsFile *pFile1, const STfsFile *pFile2) { char nameBuf1[TMPNAME_LEN], nameBuf2[TMPNAME_LEN]; tstrncpy(nameBuf1, pFile1->rname, TMPNAME_LEN); tstrncpy(nameBuf2, pFile2->rname, TMPNAME_LEN); - nameBuf1[TMPNAME_LEN - 1] = 0; - nameBuf2[TMPNAME_LEN - 1] = 0; TAOS_UNUSED(taosRealPath(nameBuf1, NULL, TMPNAME_LEN)); TAOS_UNUSED(taosRealPath(nameBuf2, NULL, TMPNAME_LEN)); if (strncmp(nameBuf1, nameBuf2, TMPNAME_LEN) != 0) return false; @@ -592,7 +590,16 @@ static int32_t tfsFormatDir(char *idir, char *odir) { wordfree(&wep); TAOS_RETURN(code); } - strcpy(odir, tmp); + + int32_t dirLen = strlen(tmp); + if (dirLen < 0 || dirLen >= TSDB_FILENAME_LEN) { + wordfree(&wep); + code = TSDB_CODE_OUT_OF_RANGE; + fError("failed to mount %s to FS since %s, real path:%s, len:%d", idir, tstrerror(code), tmp, dirLen); + TAOS_RETURN(code); + } + + tstrncpy(odir, tmp, TSDB_FILENAME_LEN); wordfree(&wep); TAOS_RETURN(0); diff --git a/source/libs/transport/inc/transComm.h b/source/libs/transport/inc/transComm.h index 6ec5f74f62..44559f2db2 100644 --- a/source/libs/transport/inc/transComm.h +++ b/source/libs/transport/inc/transComm.h @@ -311,8 +311,8 @@ void transRefCliHandle(void* handle); int32_t transUnrefCliHandle(void* handle); int32_t transGetRefCount(void* handle); -int32_t transReleaseCliHandle(void* handle); -int32_t transReleaseSrvHandle(void* handle); +int32_t transReleaseCliHandle(void* handle, int32_t status); +int32_t transReleaseSrvHandle(void* handle, int32_t status); int32_t transSendRequest(void* pInit, const SEpSet* pEpSet, STransMsg* pReq, STransCtx* pCtx); int32_t transSendRecv(void* pInit, const SEpSet* pEpSet, STransMsg* pReq, STransMsg* pRsp); diff --git a/source/libs/transport/src/tmsgcb.c b/source/libs/transport/src/tmsgcb.c index fab80bde9c..e87011f097 100644 --- a/source/libs/transport/src/tmsgcb.c +++ b/source/libs/transport/src/tmsgcb.c @@ -70,7 +70,9 @@ void tmsgSendRsp(SRpcMsg* pMsg) { void tmsgRegisterBrokenLinkArg(SRpcMsg* pMsg) { (*defaultMsgCb.registerBrokenLinkArgFp)(pMsg); } -void tmsgReleaseHandle(SRpcHandleInfo* pHandle, int8_t type) { (*defaultMsgCb.releaseHandleFp)(pHandle, type); } +void tmsgReleaseHandle(SRpcHandleInfo* pHandle, int8_t type, int32_t status) { + (*defaultMsgCb.releaseHandleFp)(pHandle, type, status); +} void tmsgReportStartup(const char* name, const char* desc) { (*defaultMsgCb.reportStartupFp)(name, desc); } diff --git a/source/libs/transport/src/trans.c b/source/libs/transport/src/trans.c index de129773a0..d7576005d7 100644 --- a/source/libs/transport/src/trans.c +++ b/source/libs/transport/src/trans.c @@ -23,7 +23,7 @@ void (*taosCloseHandle[])(void* arg) = {transCloseServer, transCloseClient}; void (*taosRefHandle[])(void* handle) = {transRefSrvHandle, transRefCliHandle}; void (*taosUnRefHandle[])(void* handle) = {transUnrefSrvHandle, NULL}; -int (*transReleaseHandle[])(void* handle) = {transReleaseSrvHandle, transReleaseCliHandle}; +int (*transReleaseHandle[])(void* handle, int32_t status) = {transReleaseSrvHandle, transReleaseCliHandle}; static int32_t transValidLocalFqdn(const char* localFqdn, uint32_t* ip) { int32_t code = taosGetIpv4FromFqdn(localFqdn, ip); @@ -158,7 +158,6 @@ void* rpcMallocCont(int64_t contLen) { char* start = taosMemoryCalloc(1, size); if (start == NULL) { tError("failed to malloc msg, size:%" PRId64, size); - terrno = TSDB_CODE_OUT_OF_MEMORY; return NULL; } else { tTrace("malloc mem:%p size:%" PRId64, start, size); @@ -217,7 +216,9 @@ void rpcRefHandle(void* handle, int8_t type) { (*taosRefHandle[type])(handle); } void rpcUnrefHandle(void* handle, int8_t type) { (*taosUnRefHandle[type])(handle); } int32_t rpcRegisterBrokenLinkArg(SRpcMsg* msg) { return transRegisterMsg(msg); } -int32_t rpcReleaseHandle(void* handle, int8_t type) { return (*transReleaseHandle[type])(handle); } +int32_t rpcReleaseHandle(void* handle, int8_t type, int32_t status) { + return (*transReleaseHandle[type])(handle, status); +} // client only int32_t rpcSetDefaultAddr(void* thandle, const char* ip, const char* fqdn) { diff --git a/source/libs/transport/src/transCli.c b/source/libs/transport/src/transCli.c index 7ac0b3e148..468d9d9b50 100644 --- a/source/libs/transport/src/transCli.c +++ b/source/libs/transport/src/transCli.c @@ -561,9 +561,39 @@ int32_t cliBuildRespFromCont(SCliReq* pReq, STransMsg* pResp, STransMsgHead* pHe pResp->info.handle = (void*)qid; return 0; } + +int8_t cliMayNotifyUserOnRecvReleaseExcept(SCliConn* conn, STransMsgHead* pHead, SCliReq* pReq) { + int32_t code = 0; + if (pHead->code == 0 || pHead->msgType != TDMT_SCH_TASK_RELEASE) { + return 0; + } + // no ahandle, no need to notify user + if (pReq == NULL || pReq->ctx == NULL || pReq->ctx->ahandle == NULL) { + return 0; + } + + SCliThrd* pThrd = conn->hostThrd; + STransMsg resp = {.code = pHead->code}; + int64_t qId = taosHton64(pHead->qid); + STraceId* trace = &pHead->traceId; + code = cliBuildExceptResp(pThrd, pReq, &resp); + if (code != 0) { + tGWarn("%s conn %p failed to build except resp for req:%" PRId64 " since %s", CONN_GET_INST_LABEL(conn), conn, qId, + tstrerror(code)); + } + code = cliNotifyCb(conn, NULL, &resp); + if (code != 0) { + tGWarn("%s conn %p failed to notify user for req:%" PRId64 " since %s", CONN_GET_INST_LABEL(conn), conn, qId, + tstrerror(code)); + } + + destroyReq(pReq); + return 1; +} int32_t cliHandleState_mayHandleReleaseResp(SCliConn* conn, STransMsgHead* pHead) { int32_t code = 0; SCliThrd* pThrd = conn->hostThrd; + int8_t notifyUser = 0; if (pHead->msgType == TDMT_SCH_TASK_RELEASE || pHead->msgType == TDMT_SCH_TASK_RELEASE + 1) { int64_t qId = taosHton64(pHead->qid); STraceId* trace = &pHead->traceId; @@ -603,7 +633,11 @@ int32_t cliHandleState_mayHandleReleaseResp(SCliConn* conn, STransMsgHead* pHead removeReqFromSendQ(pReq); STraceId* trace = &pReq->msg.info.traceId; tGDebug("start to free msg %p", pReq); - destroyReqWrapper(pReq, pThrd); + + if (cliMayNotifyUserOnRecvReleaseExcept(conn, pHead, pReq)) { + } else { + destroyReqWrapper(pReq, pThrd); + } } taosMemoryFree(pHead); return 1; @@ -1265,6 +1299,8 @@ static void cliHandleException(SCliConn* conn) { if (conn->registered) { int8_t ref = transGetRefCount(conn); if (ref == 0 && !uv_is_closing((uv_handle_t*)conn->stream)) { +// tTrace("%s conn %p fd %d,%d,%d,%p uv_closed", CONN_GET_INST_LABEL(conn), conn, conn->stream->u.fd, +// conn->stream->io_watcher.fd, conn->stream->accepted_fd, conn->stream->queued_fds); uv_close((uv_handle_t*)conn->stream, cliDestroy); } } @@ -1593,6 +1629,8 @@ static int32_t cliDoConn(SCliThrd* pThrd, SCliConn* conn) { TAOS_CHECK_GOTO(terrno, &lino, _exception1); } + tTrace("%s conn %p fd %d openend", pInst->label, conn, fd); + int ret = uv_tcp_open((uv_tcp_t*)conn->stream, fd); if (ret != 0) { tError("%s conn %p failed to set stream since %s", transLabel(pInst), conn, uv_err_name(ret)); @@ -1808,9 +1846,7 @@ FORCE_INLINE int32_t cliBuildExceptResp(SCliThrd* pThrd, SCliReq* pReq, STransMs STrans* pInst = pThrd->pInst; - SReqCtx* pCtx = pReq ? pReq->ctx : NULL; - STransMsg resp = {0}; - // resp.code = (conn->connnected ? TSDB_CODE_RPC_BROKEN_LINK : TSDB_CODE_RPC_NETWORK_UNAVAIL); + SReqCtx* pCtx = pReq ? pReq->ctx : NULL; pResp->msgType = pReq ? pReq->msg.msgType + 1 : 0; pResp->info.cliVer = pInst->compatibilityVer; pResp->info.ahandle = pCtx ? pCtx->ahandle : 0; @@ -3128,15 +3164,18 @@ SCliThrd* transGetWorkThrd(STrans* trans, int64_t handle) { SCliThrd* pThrd = transGetWorkThrdFromHandle(trans, handle); return pThrd; } -int32_t transReleaseCliHandle(void* handle) { +int32_t transReleaseCliHandle(void* handle, int32_t status) { int32_t code = 0; SCliThrd* pThrd = transGetWorkThrdFromHandle(NULL, (int64_t)handle); if (pThrd == NULL) { return TSDB_CODE_RPC_BROKEN_LINK; } - STransMsg tmsg = { - .msgType = TDMT_SCH_TASK_RELEASE, .info.handle = handle, .info.ahandle = (void*)0, .info.qId = (int64_t)handle}; + STransMsg tmsg = {.msgType = TDMT_SCH_TASK_RELEASE, + .info.handle = handle, + .info.ahandle = (void*)0, + .info.qId = (int64_t)handle, + code = status}; TRACE_SET_MSGID(&tmsg.info.traceId, tGenIdPI64()); diff --git a/source/libs/transport/src/transSvr.c b/source/libs/transport/src/transSvr.c index ecbdd0db84..941444953d 100644 --- a/source/libs/transport/src/transSvr.c +++ b/source/libs/transport/src/transSvr.c @@ -1862,7 +1862,7 @@ void transUnrefSrvHandle(void* handle) { } } -int32_t transReleaseSrvHandle(void* handle) { +int32_t transReleaseSrvHandle(void* handle, int32_t status) { int32_t code = 0; SRpcHandleInfo* info = handle; SExHandle* exh = info->handle; @@ -1875,7 +1875,7 @@ int32_t transReleaseSrvHandle(void* handle) { ASYNC_ERR_JRET(pThrd); STransMsg tmsg = {.msgType = TDMT_SCH_TASK_RELEASE, - .code = 0, + .code = status, .info.handle = exh, .info.ahandle = NULL, .info.refId = refId, diff --git a/source/libs/transport/test/transUT.cpp b/source/libs/transport/test/transUT.cpp index 8e396d59d7..a50ff47253 100644 --- a/source/libs/transport/test/transUT.cpp +++ b/source/libs/transport/test/transUT.cpp @@ -96,7 +96,7 @@ class Client { } void SendAndRecvNoHandle(SRpcMsg *req, SRpcMsg *resp) { if (req->info.handle != NULL) { - rpcReleaseHandle(req->info.handle, TAOS_CONN_CLIENT); + rpcReleaseHandle(req->info.handle, TAOS_CONN_CLIENT, 0); req->info.handle = NULL; } SendAndRecv(req, resp); @@ -191,7 +191,7 @@ static void processReleaseHandleCb(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet) rpcMsg.code = 0; rpcSendResponse(&rpcMsg); - rpcReleaseHandle(&pMsg->info, TAOS_CONN_SERVER); + rpcReleaseHandle(&pMsg->info, TAOS_CONN_SERVER, 0); } static void processRegisterFailure(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet) { { @@ -366,7 +366,7 @@ TEST_F(TransEnv, cliPersistHandle) { //} handle = resp.info.handle; } - rpcReleaseHandle(handle, TAOS_CONN_CLIENT); + rpcReleaseHandle(handle, TAOS_CONN_CLIENT, 0); for (int i = 0; i < 10; i++) { SRpcMsg req = {0}; req.msgType = 1; diff --git a/source/libs/transport/test/transUT2.cpp b/source/libs/transport/test/transUT2.cpp index 54d23b1f64..d6b336b014 100644 --- a/source/libs/transport/test/transUT2.cpp +++ b/source/libs/transport/test/transUT2.cpp @@ -106,7 +106,7 @@ class Client { } void SendAndRecvNoHandle(SRpcMsg *req, SRpcMsg *resp) { if (req->info.handle != NULL) { - rpcReleaseHandle(req->info.handle, TAOS_CONN_CLIENT); + rpcReleaseHandle(req->info.handle, TAOS_CONN_CLIENT, 0); req->info.handle = NULL; } SendAndRecv(req, resp); @@ -201,7 +201,7 @@ static void processReleaseHandleCb(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet) rpcMsg.code = 0; rpcSendResponse(&rpcMsg); - rpcReleaseHandle(&pMsg->info, TAOS_CONN_SERVER); + rpcReleaseHandle(&pMsg->info, TAOS_CONN_SERVER, 0); } static void processRegisterFailure(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet) { // { diff --git a/source/os/CMakeLists.txt b/source/os/CMakeLists.txt index 96deaa4196..6b33e68377 100644 --- a/source/os/CMakeLists.txt +++ b/source/os/CMakeLists.txt @@ -14,6 +14,7 @@ target_include_directories( PUBLIC "${TD_SOURCE_DIR}/contrib/pthread" PUBLIC "${TD_SOURCE_DIR}/contrib/iconv" PUBLIC "${TD_SOURCE_DIR}/contrib/msvcregex" + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/inc" ) # iconv if(TD_WINDOWS) diff --git a/source/os/src/osMemory.c b/source/os/src/osMemory.c index f4aa966d2b..fdbf4853ad 100644 --- a/source/os/src/osMemory.c +++ b/source/os/src/osMemory.c @@ -260,7 +260,7 @@ int32_t taosMemoryDbgInitRestore() { #endif } -void *taosMemoryMalloc(int64_t size) { +void *taosMemMalloc(int64_t size) { #ifdef USE_TD_MEMORY void *tmp = malloc(size + sizeof(TdMemoryInfo)); if (tmp == NULL) return NULL; @@ -290,7 +290,7 @@ void *taosMemoryMalloc(int64_t size) { #endif } -void *taosMemoryCalloc(int64_t num, int64_t size) { +void *taosMemCalloc(int64_t num, int64_t size) { #ifdef USE_TD_MEMORY int32_t memorySize = num * size; char *tmp = calloc(memorySize + sizeof(TdMemoryInfo), 1); @@ -322,7 +322,7 @@ void *taosMemoryCalloc(int64_t num, int64_t size) { #endif } -void *taosMemoryRealloc(void *ptr, int64_t size) { +void *taosMemRealloc(void *ptr, int64_t size) { #ifdef USE_TD_MEMORY if (ptr == NULL) return taosMemoryMalloc(size); @@ -360,7 +360,7 @@ void *taosMemoryRealloc(void *ptr, int64_t size) { #endif } -char *taosStrdup(const char *ptr) { +char *taosStrdupi(const char *ptr) { #ifdef USE_TD_MEMORY if (ptr == NULL) return NULL; @@ -390,7 +390,8 @@ char *taosStrdup(const char *ptr) { #endif } -void taosMemoryFree(void *ptr) { + +void taosMemFree(void *ptr) { if (NULL == ptr) return; #ifdef USE_TD_MEMORY TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)((char *)ptr - sizeof(TdMemoryInfo)); @@ -406,7 +407,7 @@ void taosMemoryFree(void *ptr) { #endif } -int64_t taosMemorySize(void *ptr) { +int64_t taosMemSize(void *ptr) { if (ptr == NULL) return 0; #ifdef USE_TD_MEMORY @@ -427,16 +428,22 @@ int64_t taosMemorySize(void *ptr) { #endif } -void taosMemoryTrim(int32_t size) { +int32_t taosMemTrim(int32_t size, bool* trimed) { #if defined(WINDOWS) || defined(DARWIN) || defined(_ALPINE) // do nothing - return; + return TSDB_CODE_SUCCESS; #else - (void)malloc_trim(size); + if (trimed) { + *trimed = malloc_trim(size); + } else { + malloc_trim(size); + } + + return TSDB_CODE_SUCCESS; #endif } -void *taosMemoryMallocAlign(uint32_t alignment, int64_t size) { +void *taosMemMallocAlign(uint32_t alignment, int64_t size) { #ifdef USE_TD_MEMORY return NULL; #else @@ -461,7 +468,7 @@ void *taosMemoryMallocAlign(uint32_t alignment, int64_t size) { } return p; #else - return taosMemoryMalloc(size); + return taosMemMalloc(size); #endif #endif } diff --git a/source/os/src/osString.c b/source/os/src/osString.c index 147f0462eb..380e9f84d3 100644 --- a/source/os/src/osString.c +++ b/source/os/src/osString.c @@ -75,7 +75,7 @@ char *strsep(char **stringp, const char *delim) { /* NOTREACHED */ } /* Duplicate a string, up to at most size characters */ -char *taosStrndup(const char *s, int size) { +char *taosStrndupi(const char *s, int64_t size) { if (s == NULL) return NULL; size_t l; char *s2; @@ -104,7 +104,7 @@ char *stpncpy(char *dest, const char *src, int n) { return memset(dest, '\0', n - size); } #else -char *taosStrndup(const char *s, int size) { +char *taosStrndupi(const char *s, int64_t size) { if (s == NULL) { return NULL; } @@ -116,6 +116,20 @@ char *taosStrndup(const char *s, int size) { } #endif +char *tstrndup(const char *str, int64_t size) { +#ifdef WINDOWS + return taosStrndupi(str, size); +#else + char* p = strndup(str, size); + if (str != NULL && NULL == p) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + } + return p; + +#endif +} + + int32_t taosStr2int64(const char *str, int64_t *val) { if (str == NULL || val == NULL) { return TSDB_CODE_INVALID_PARA; diff --git a/source/os/src/osSysinfo.c b/source/os/src/osSysinfo.c index dc3258bf9c..526f1a33e4 100644 --- a/source/os/src/osSysinfo.c +++ b/source/os/src/osSysinfo.c @@ -779,6 +779,59 @@ int32_t taosGetProcMemory(int64_t *usedKB) { #endif } +int32_t taosGetSysAvailMemory(int64_t *availSize) { +#ifdef WINDOWS + MEMORYSTATUSEX memsStat; + memsStat.dwLength = sizeof(memsStat); + if (!GlobalMemoryStatusEx(&memsStat)) { + return -1; + } + + int64_t nMemFree = memsStat.ullAvailPhys; + int64_t nMemTotal = memsStat.ullTotalPhys; + + *availSize = nMemTotal - nMemFree; + return 0; +#elif defined(_TD_DARWIN_64) + *availSize = 0; + return 0; +#else + TdFilePtr pFile = taosOpenFile("/proc/meminfo", TD_FILE_READ | TD_FILE_STREAM); + if (pFile == NULL) { + return terrno; + } + + ssize_t bytes = 0; + char line[128] = {0}; + int32_t expectedSize = 13; //"MemAvailable:" + while (!taosEOFFile(pFile)) { + bytes = taosGetsFile(pFile, sizeof(line), line); + if (bytes < 0) { + break; + } + if (line[0] != 'M' && line[3] != 'A') { + line[0] = 0; + continue; + } + if (0 == strncmp(line, "MemAvailable:", expectedSize)) { + break; + } + } + + if (0 == line[0]) { + return TSDB_CODE_UNSUPPORT_OS; + } + + char tmp[32]; + (void)sscanf(line, "%s %" PRId64, tmp, availSize); + + *availSize *= 1024; + + (void)taosCloseFile(&pFile); + return 0; +#endif +} + int32_t taosGetSysMemory(int64_t *usedKB) { OS_PARAM_CHECK(usedKB); #ifdef WINDOWS diff --git a/source/util/inc/tmempoolInt.h b/source/util/inc/tmempoolInt.h new file mode 100755 index 0000000000..183ce3ee04 --- /dev/null +++ b/source/util/inc/tmempoolInt.h @@ -0,0 +1,549 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef _TD_MEMPOOL_INT_H_ +#define _TD_MEMPOOL_INT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "os.h" +#include "tlockfree.h" +#include "thash.h" +#include "tglobal.h" + +#define MP_CHUNK_CACHE_ALLOC_BATCH_SIZE 1000 +#define MP_NSCHUNK_CACHE_ALLOC_BATCH_SIZE 500 +#define MP_SESSION_CACHE_ALLOC_BATCH_SIZE 100 + +#define MP_MAX_KEEP_FREE_CHUNK_NUM 1000 +#define MP_MAX_MALLOC_MEM_SIZE 0xFFFFFFFFFF + +#define MP_DEFAULT_MEM_CHK_INTERVAL_MS 10 +#define MP_MIN_MEM_CHK_INTERVAL_MS 1 +#define MP_MEMORY_TRIM_INTERVAL_TIMES 500 + + +#define MP_RETIRE_HIGH_THRESHOLD_PERCENT (0.95) +#define MP_RETIRE_MID_THRESHOLD_PERCENT (0.9) +#define MP_RETIRE_LOW_THRESHOLD_PERCENT (0.85) +#define MP_RETIRE_UNIT_PERCENT (0.1) +#define MP_RETIRE_UNIT_MIN_SIZE (50 * 1048576L) +#define MP_CFG_UPDATE_MIN_RESERVE_SIZE (50 * 1024 * 1048576L) + +#define MP_DEFAULT_RESERVE_MEM_PERCENT 20 +#define MP_MIN_FREE_SIZE_AFTER_RESERVE (4 * 1024 * 1048576L) +#define MP_MIN_MEM_POOL_SIZE (5 * 1024 * 1048576L) + + +// FLAGS AREA +#define MP_CHUNK_FLAG_IN_USE (1 << 0) +#define MP_CHUNK_FLAG_NS_CHUNK (1 << 1) + + +// STAT FLAGS +#define MP_LOG_FLAG_ALL_MEM (1 << 0) +#define MP_LOG_FLAG_ALL_CHUNK (1 << 1) +#define MP_LOG_FLAG_ALL_POS (1 << 2) +#define MP_LOG_FLAG_ALL_SESSION (1 << 3) +#define MP_LOG_FLAG_ALL_NODE (1 << 4) +#define MP_LOG_FLAG_ALL_POOL (1 << 5) + +#define MP_LOG_FLAG_SOME_POS (1 << 6) +#define MP_LOG_FLAG_SOME_SESSION (1 << 7) +#define MP_LOG_FLAG_SOME_NODE (1 << 8) +#define MP_LOG_FLAG_SOME_POOL (1 << 9) + +#define MP_STAT_FLAG_LOG_ALL (0xFFFFFFFFFFFFFFFF) + + +// STAT PROCESURE FLAGS +#define MP_STAT_PROC_FLAG_EXEC (1 << 0) +#define MP_STAT_PROC_FLAG_INPUT_ERR (1 << 1) +#define MP_STAT_PROC_FLAG_RES_SUCC (1 << 2) +#define MP_STAT_PROC_FLAG_RES_FAIL (1 << 3) + +// CTRL FUNC FLAGS +#define MP_CTRL_FLAG_PRINT_STAT (1 << 0) +#define MP_CTRL_FLAG_CHECK_STAT (1 << 1) +#define MP_CTRL_FLAG_LOCK_DBG (1 << 2) +#define MP_CTRL_FLAG_LOG_MAXSIZE (1 << 3) + + +typedef enum EMPStatLogItem { + E_MP_STAT_LOG_MEM_MALLOC = 1, + E_MP_STAT_LOG_MEM_CALLOC, + E_MP_STAT_LOG_MEM_REALLOC, + E_MP_STAT_LOG_MEM_FREE, + E_MP_STAT_LOG_MEM_STRDUP, + E_MP_STAT_LOG_MEM_STRNDUP, + E_MP_STAT_LOG_MEM_TRIM, + + E_MP_STAT_LOG_CHUNK_MALLOC, + E_MP_STAT_LOG_CHUNK_RECYCLE, + E_MP_STAT_LOG_CHUNK_REUSE, + E_MP_STAT_LOG_CHUNK_FREE, +} EMPStatLogItem; + +// MEM HEADER FLAGS +#define MP_MEM_HEADER_FLAG_NS_CHUNK (1 << 0) + +typedef struct SMPMemHeader { + uint64_t flags:24; + uint64_t size:40; +} SMPMemHeader; + +typedef struct SMPMemTailer { + uint8_t tail; +} SMPMemTailer; + +typedef struct SMPListNode { + void *pNext; +} SMPListNode; + +typedef struct SMPChunk { + SMPListNode list; + char *pMemStart; + int32_t flags; + /* KEEP ABOVE SAME WITH SMPNSChunk */ + + uint32_t offset; +} SMPChunk; + +typedef struct SMPNSChunk { + SMPListNode list; + char *pMemStart; + int32_t flags; + /* KEEP ABOVE SAME WITH SMPChunk */ + + uint64_t offset; + uint64_t memBytes; +} SMPNSChunk; + + +typedef struct SMPCacheGroup { + int32_t nodesNum; + int32_t idleOffset; + void *pNodes; + void* pNext; +} SMPCacheGroup; + +typedef struct SMPStatInput { + char* file; + int64_t size; + int64_t origSize; + int32_t procFlags; + int32_t line; + void* pMem; + void* pOrigMem; +} SMPStatInput; + + +typedef struct SMPCtrlInfo { + int64_t statFlags; + int64_t funcFlags; +} SMPCtrlInfo; + +typedef struct SMPStatSession { + int64_t initSucc; + int64_t initFail; + int64_t destroyNum; +} SMPStatSession; + +typedef struct SMPAllocStat { + int64_t allocTimes; + int64_t allocBytes; + //int64_t freeIDs[]; // TODO +} SMPAllocStat; + +typedef struct SMPFreeStat { + int64_t freeTimes; + int64_t freeBytes; +} SMPFreeStat; + +typedef struct SMPFileLineId { + uint32_t fileId; + int32_t line; +} SMPFileLineId; + +typedef struct SMPFileLine { + SMPFileLineId fl; + int64_t size; +} SMPFileLine; + +typedef struct SMPStatPos { + int64_t logErrTimes; + SHashObj* fileHash; // fileId => fileName + SHashObj* remainHash; // pointer => SMPFileLine + SHashObj* allocHash; // alloc fl => SMPAllocStat + SHashObj* freeHash; // free fl => SMPFreeStat +} SMPStatPos; + +typedef struct SMPStatInfo { + SMPStatDetail statDetail; + SMPStatSession statSession; + SHashObj* sessStat; + SHashObj* nodeStat; + SMPStatPos posStat; +} SMPStatInfo; + + +typedef struct SMPJob { + SMemPoolJob job; // KEEP IT FIRST + SMPStatInfo stat; +} SMPJob; + +typedef struct SMPSessionChunk { + int64_t allocChunkNum; + int64_t allocChunkMemSize; + int64_t reUseChunkNum; + + int32_t srcChunkNum; + SMPChunk *srcChunkHead; + SMPChunk *srcChunkTail; + + int32_t inUseChunkNum; + SMPChunk *inUseChunkHead; + SMPChunk *inUseChunkTail; + + SMPNSChunk *inUseNSChunkHead; + SMPNSChunk *inUseNSChunkTail; + + SMPChunk *reUseChunkHead; + SMPChunk *reUseChunkTail; + + SMPNSChunk *reUseNSChunkHead; + SMPNSChunk *reUseNSChunkTail; +} SMPSessionChunk; + +typedef struct SMPSession { + //SMPListNode list; + + char* sessionId; + SMPJob* pJob; + SMPCtrlInfo ctrl; + int64_t allocMemSize; + int64_t maxAllocMemSize; + + //SMPSessionChunk chunk; + + SMPStatInfo stat; +} SMPSession; + +typedef struct SMPCacheGroupInfo { + int16_t nodeSize; + int64_t allocNum; + int32_t groupNum; + SMPCacheGroup *pGrpHead; + void *pIdleList; +} SMPCacheGroupInfo; + +typedef struct SMPChunkMgmt { + int32_t maxChunkNum; + int16_t maxDiscardSize; + double threadChunkReserveNum; + int64_t allocChunkNum; + int64_t allocChunkSize; + int64_t allocNSChunkNum; + int64_t allocNSChunkSize; + + SMPCacheGroupInfo chunkCache; + SMPCacheGroupInfo NSChunkCache; + + int32_t readyChunkNum; + int32_t readyChunkReserveNum; + int32_t readyChunkLowNum; + int32_t readyChunkGotNum; + SRWLatch readyChunkLock; + SMPChunk *readyChunkHead; + SMPChunk *readyChunkTail; + + int64_t readyNSChunkNum; + SMPChunk *readyNSChunkHead; + SMPChunk *readyNSChunkTail; +} SMPChunkMgmt; + + +typedef struct SMemPool { + char *name; + int16_t slotId; + SRWLatch cfgLock; + SMemPoolCfg cfg; + //int64_t retireThreshold[3]; + int64_t retireUnit; + + int64_t maxAllocMemSize; + int64_t allocMemSize; + + SMPCacheGroupInfo sessionCache; + + SMPChunkMgmt chunk; + + SMPStatInfo stat; +} SMemPool; + +typedef enum EMPMemStrategy { + E_MP_STRATEGY_DIRECT = 1, + E_MP_STRATEGY_CHUNK, +} EMPMemStrategy; + +typedef struct SMPMsgQueue { + SMemPool* pPool; + int8_t lowLevelRetire; + int8_t midLevelRetire; +} SMPMsgQueue; + +typedef struct SMemPoolMgmt { + EMPMemStrategy strategy; + SMPCtrlInfo ctrl; + SArray* poolList; + SRWLatch poolLock; + TdThread poolMgmtThread; + SMPMsgQueue msgQueue; + tsem2_t threadSem; + int8_t modExit; + int64_t waitMs; + int32_t code; + int8_t needTrim; +} SMemPoolMgmt; + +extern SMemPoolMgmt gMPMgmt; + + +typedef int32_t (*mpAllocFunc)(SMemPool*, SMPSession*, int64_t*, uint32_t, void**); +typedef void (*mpFreeFunc)(SMemPool*, SMPSession*, void *, int64_t*); +typedef int64_t (*mpGetSizeFunc)(SMemPool*, SMPSession*, void*); +typedef int32_t (*mpReallocFunc)(SMemPool*, SMPSession*, void **, int64_t*, int64_t*); +typedef int32_t (*mpInitSessionFunc)(SMemPool*, SMPSession*); +typedef int32_t (*mpInitFunc)(SMemPool*, char*, SMemPoolCfg*); +typedef int32_t (*mpUpdateCfgFunc)(SMemPool*); +typedef int32_t (*mpTrimFunc)(SMemPool*, SMPSession*, int32_t, bool*); + +typedef struct SMPStrategyFp { + mpInitFunc initFp; + mpAllocFunc allocFp; + mpFreeFunc freeFp; + mpGetSizeFunc getSizeFp; + mpReallocFunc reallocFp; + mpInitSessionFunc initSessionFp; + mpUpdateCfgFunc updateCfgFp; + mpTrimFunc trimFp; +} SMPStrategyFp; + +#define MP_GET_FLAG(st, f) ((st) & (f)) +#define MP_SET_FLAG(st, f) (st) |= (f) +#define MP_CLR_FLAG(st, f) (st) &= (~f) + +enum { + MP_READ = 1, + MP_WRITE, +}; + +#define MP_STAT_FORMAT "%-8s => inErr:%10" PRId64 ", exec:%12" PRId64 ", succ:%12" PRId64 ", fail:%12" PRId64 +#define MP_STAT_ORIG_FORMAT "%-8s => inErr:%10" PRId64 ", exec:%12" PRId64 ", succ:%12" PRId64 ", fail:%12" PRId64 ", oExec:%12" PRId64 ", oSucc:%12" PRId64 ", oFail:%12" PRId64 + +#define MP_STAT_VALUE(_name, _item) _name, (_item).inErr, (_item).exec, (_item).succ, (_item).fail +#define MP_STAT_ORIG_VALUE(_name, _item) _name, (_item).inErr, (_item).exec, (_item).succ, (_item).fail, (_item).origExec, (_item).origSucc, (_item).origFail + +#define MP_INIT_MEM_HEADER(_header, _size, _nsChunk) \ + do { \ + (_header)->size = _size; \ + if (_nsChunk) { \ + MP_SET_FLAG((_header)->flags, MP_MEM_HEADER_FLAG_NS_CHUNK); \ + } \ + } while (0) + +#define MP_ADD_TO_CHUNK_LIST(_chunkHead, _chunkTail, _chunkNum, _chunk) \ + do { \ + if (NULL == _chunkHead) { \ + _chunkHead = _chunk; \ + _chunkTail = _chunk; \ + } else { \ + (_chunkTail)->list.pNext = _chunk; \ + (_chunkTail) = _chunk; \ + } \ + (_chunkNum)++; \ + } while (0) + +#define TD_RWLATCH_WRITE_FLAG_COPY 0x40000000 + +#define MP_TRY_LOCK(type, _lock, _res) \ + do { \ + if (MP_READ == (type)) { \ + if (MP_GET_FLAG(gMPMgmt.ctrl.funcFlags, MP_CTRL_FLAG_LOCK_DBG)) { \ + ASSERTS(atomic_load_32((_lock)) >= 0, "invalid lock value before try read lock"); \ + uDebug("MP TRY RLOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + } \ + (_res) = taosRTryLockLatch(_lock); \ + if (MP_GET_FLAG(gMPMgmt.ctrl.funcFlags, MP_CTRL_FLAG_LOCK_DBG)) { \ + uDebug("MP TRY RLOCK%p:%d %s, %s:%d E", (_lock), atomic_load_32(_lock), (_res) ? "failed" : "succeed", __FILE__, __LINE__); \ + ASSERTS((_res) ? atomic_load_32((_lock)) >= 0 : atomic_load_32((_lock)) > 0, "invalid lock value after try read lock"); \ + } \ + } else { \ + if (MP_GET_FLAG(gMPMgmt.ctrl.funcFlags, MP_CTRL_FLAG_LOCK_DBG)) { \ + ASSERTS(atomic_load_32((_lock)) >= 0, "invalid lock value before try write lock"); \ + uDebug("MP TRY WLOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + } \ + (_res) = taosWTryLockLatch(_lock); \ + if (MP_GET_FLAG(gMPMgmt.ctrl.funcFlags, MP_CTRL_FLAG_LOCK_DBG)) { \ + uDebug("MP TRY WLOCK%p:%d %s, %s:%d E", (_lock), atomic_load_32(_lock), (_res) ? "failed" : "succeed", __FILE__, __LINE__); \ + ASSERTS((_res) ? atomic_load_32((_lock)) >= 0 : atomic_load_32((_lock)) == TD_RWLATCH_WRITE_FLAG_COPY, "invalid lock value after try write lock"); \ + } \ + } \ + } while (0) + + +#define MP_LOCK(type, _lock) \ + do { \ + if (MP_READ == (type)) { \ + if (MP_GET_FLAG(gMPMgmt.ctrl.funcFlags, MP_CTRL_FLAG_LOCK_DBG)) { \ + ASSERTS(atomic_load_32((_lock)) >= 0, "invalid lock value before read lock"); \ + uDebug("MP RLOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + } \ + taosRLockLatch(_lock); \ + if (MP_GET_FLAG(gMPMgmt.ctrl.funcFlags, MP_CTRL_FLAG_LOCK_DBG)) { \ + uDebug("MP RLOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + ASSERTS(atomic_load_32((_lock)) > 0, "invalid lock value after read lock"); \ + } \ + } else { \ + if (MP_GET_FLAG(gMPMgmt.ctrl.funcFlags, MP_CTRL_FLAG_LOCK_DBG)) { \ + ASSERTS(atomic_load_32((_lock)) >= 0, "invalid lock value before write lock"); \ + uDebug("MP WLOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + } \ + taosWLockLatch(_lock); \ + if (MP_GET_FLAG(gMPMgmt.ctrl.funcFlags, MP_CTRL_FLAG_LOCK_DBG)) { \ + uDebug("MP WLOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + ASSERTS(atomic_load_32((_lock)) == TD_RWLATCH_WRITE_FLAG_COPY, "invalid lock value after write lock"); \ + } \ + } \ + } while (0) + +#define MP_UNLOCK(type, _lock) \ + do { \ + if (MP_READ == (type)) { \ + if (MP_GET_FLAG(gMPMgmt.ctrl.funcFlags, MP_CTRL_FLAG_LOCK_DBG)) { \ + ASSERTS(atomic_load_32((_lock)) > 0, "invalid lock value before read unlock"); \ + uDebug("MP RULOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + } \ + taosRUnLockLatch(_lock); \ + if (MP_GET_FLAG(gMPMgmt.ctrl.funcFlags, MP_CTRL_FLAG_LOCK_DBG)) { \ + uDebug("MP RULOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + ASSERTS(atomic_load_32((_lock)) >= 0, "invalid lock value after read unlock"); \ + } \ + } else { \ + if (MP_GET_FLAG(gMPMgmt.ctrl.funcFlags, MP_CTRL_FLAG_LOCK_DBG)) { \ + ASSERTS(atomic_load_32((_lock)) == TD_RWLATCH_WRITE_FLAG_COPY, "invalid lock value before write unlock"); \ + uDebug("MP WULOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + } \ + taosWUnLockLatch(_lock); \ + if (MP_GET_FLAG(gMPMgmt.ctrl.funcFlags, MP_CTRL_FLAG_LOCK_DBG)) { \ + uDebug("MP WULOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + ASSERTS(atomic_load_32((_lock)) >= 0, "invalid lock value after write unlock"); \ + } \ + } \ + } while (0) + + +#define MP_ERR_RET(c) \ + do { \ + int32_t _code = c; \ + if (_code != TSDB_CODE_SUCCESS) { \ + terrno = _code; \ + return _code; \ + } \ + } while (0) + +#define MP_RET(c) \ + do { \ + int32_t _code = c; \ + if (_code != TSDB_CODE_SUCCESS) { \ + terrno = _code; \ + } \ + return _code; \ + } while (0) + +#define MP_ERR_JRET(c) \ + do { \ + code = c; \ + if (code != TSDB_CODE_SUCCESS) { \ + terrno = code; \ + goto _return; \ + } \ + } while (0) + +#define MP_CHECK_QUOTA(_pool, _job, _size) do { \ + if (*(_pool)->cfg.jobQuota > 0) { \ + int64_t cAllocSize = atomic_add_fetch_64(&(_job)->job.allocMemSize, (_size)); \ + if (cAllocSize > (*(_pool)->cfg.jobQuota * 1048576L)) { \ + uWarn("job 0x%" PRIx64 " remainSession:%d allocSize %" PRId64 " is over than quota %dMB", (_job)->job.jobId, (_job)->job.remainSession, cAllocSize, *(_pool)->cfg.jobQuota); \ + (_pool)->cfg.cb.reachFp(pJob->job.jobId, (_job)->job.clientId, TSDB_CODE_QRY_REACH_QMEM_THRESHOLD); \ + mpSchedTrim(NULL); \ + terrno = TSDB_CODE_QRY_REACH_QMEM_THRESHOLD; \ + return NULL; \ + } else { \ + uDebug("job 0x%" PRIx64 " remainSession:%d allocSize %" PRId64 " is lower than quota %dMB", (_job)->job.jobId, (_job)->job.remainSession, cAllocSize, *(_pool)->cfg.jobQuota); \ + } \ + } \ + if (atomic_load_64(&tsCurrentAvailMemorySize) <= ((_pool)->cfg.reserveSize + (_size))) { \ + uWarn("%s pool sysAvailMemSize %" PRId64 " can't alloc %" PRId64" while keeping reserveSize %" PRId64 " bytes", \ + (_pool)->name, atomic_load_64(&tsCurrentAvailMemorySize), (_size), (_pool)->cfg.reserveSize); \ + (_pool)->cfg.cb.reachFp((_job)->job.jobId, (_job)->job.clientId, TSDB_CODE_QRY_QUERY_MEM_EXHAUSTED); \ + mpSchedTrim(NULL); \ + terrno = TSDB_CODE_QRY_QUERY_MEM_EXHAUSTED; \ + return NULL; \ + } \ + } while (0) + + +// direct +void* mpDirectAlloc(SMemPool* pPool, SMPJob* pJob, int64_t size); +void* mpDirectAlignAlloc(SMemPool* pPool, SMPJob* pJob, uint32_t alignment, int64_t size); +void* mpDirectCalloc(SMemPool* pPool, SMPJob* pJob, int64_t num, int64_t size); +void mpDirectFree(SMemPool* pPool, SMPJob* pJob, void *ptr); +void* mpDirectRealloc(SMemPool* pPool, SMPJob* pJob, void* ptr, int64_t size); +void* mpDirectStrdup(SMemPool* pPool, SMPJob* pJob, const void* ptr); +void* mpDirectStrndup(SMemPool* pPool, SMPJob* pJob, const void* ptr, int64_t size); + +int32_t mpDirectFullAlloc(SMemPool* pPool, SMPSession* pSession, int64_t* size, uint32_t alignment, void** ppRes); +int64_t mpDirectGetMemSize(SMemPool* pPool, SMPSession* pSession, void *ptr); +void mpDirectFullFree(SMemPool* pPool, SMPSession* pSession, void *ptr, int64_t* origSize); +int32_t mpDirectFullRealloc(SMemPool* pPool, SMPSession* pSession, void **pPtr, int64_t* size, int64_t* origSize); +int32_t mpDirectTrim(SMemPool* pPool, SMPSession* pSession, int32_t size, bool* trimed); + +// chunk +int32_t mpChunkInit(SMemPool* pPool, char* poolName, SMemPoolCfg* cfg); +int64_t mpChunkGetMemSize(SMemPool* pPool, SMPSession* pSession, void *ptr); +int32_t mpChunkAlloc(SMemPool* pPool, SMPSession* pSession, int64_t* size, uint32_t alignment, void** ppRes); +void mpChunkFree(SMemPool* pPool, SMPSession* pSession, void *ptr, int64_t* origSize); +int32_t mpChunkRealloc(SMemPool* pPool, SMPSession* pSession, void **pPtr, int64_t* size, int64_t* origSize); +int32_t mpChunkInitSession(SMemPool* pPool, SMPSession* pSession); +int32_t mpChunkUpdateCfg(SMemPool* pPool); + + +int32_t mpPopIdleNode(SMemPool* pPool, SMPCacheGroupInfo* pInfo, void** ppRes); +int32_t mpChkFullQuota(SMemPool* pPool, SMPSession* pSession, int64_t size); +void mpUpdateAllocSize(SMemPool* pPool, SMPSession* pSession, int64_t size, int64_t addSize); +int32_t mpAddCacheGroup(SMemPool* pPool, SMPCacheGroupInfo* pInfo, SMPCacheGroup* pHead); +int32_t mpMalloc(SMemPool* pPool, SMPSession* pSession, int64_t* size, uint32_t alignment, void** ppRes); +void mpSchedTrim(int64_t* loopTimes); + + + +#ifdef __cplusplus +} +#endif + +#endif /* _TD_MEMPOOL_INT_H_ */ diff --git a/source/util/src/mpChunk.c b/source/util/src/mpChunk.c new file mode 100755 index 0000000000..2c1c415c04 --- /dev/null +++ b/source/util/src/mpChunk.c @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#define _DEFAULT_SOURCE +#include "osMemPool.h" +#include "tmempoolInt.h" +#include "tlog.h" +#include "tutil.h" + +#if 0 +int32_t mpChunkNew(SMemPool* pPool, SMPChunk** ppChunk) { + SMPChunk* pChunk = NULL; + MP_ERR_RET(mpPopIdleNode(pPool, &pPool->chunk.chunkCache, (void**)&pChunk)); + + pChunk->pMemStart = taosMemMalloc(pPool->cfg.chunkSize); + if (NULL == pChunk->pMemStart) { + uError("add new chunk, memory malloc %d failed, code: 0x%x", pPool->cfg.chunkSize, terrno); + return terrno; + } + + pPool->chunk.allocChunkNum++; + pPool->chunk.allocChunkSize += pPool->cfg.chunkSize; + + *ppChunk = pChunk; + + return TSDB_CODE_SUCCESS; +} + + +int32_t mpChunkNewNS(SMemPool* pPool, SMPNSChunk** ppChunk, int64_t chunkSize) { + SMPNSChunk* pChunk = NULL; + MP_ERR_RET(mpPopIdleNode(pPool, &pPool->chunk.NSChunkCache, (void**)&pChunk)); + + pChunk->pMemStart = taosMemMalloc(chunkSize); + if (NULL == pChunk->pMemStart) { + uError("add new NS chunk, memory malloc %" PRId64 " failed, code: 0x%x", chunkSize, terrno); + return terrno; + } + + pChunk->memBytes = chunkSize; + MP_SET_FLAG(pChunk->flags, MP_CHUNK_FLAG_NS_CHUNK); + + pPool->chunk.allocNSChunkNum++; + pPool->chunk.allocNSChunkSize += pPool->cfg.chunkSize; + + *ppChunk = pChunk; + + return TSDB_CODE_SUCCESS; +} + + +int32_t mpChunkPrepare(SMemPool* pPool, int32_t num) { + SMPChunk* pChunk = NULL; + for (int32_t i = 0; i < num; ++i) { + MP_ERR_RET(mpChunkNew(pPool, &pChunk)); + + pPool->chunk.readyChunkTail->list.pNext = pChunk; + pPool->chunk.readyChunkTail = pChunk; + + atomic_add_fetch_32(&pPool->chunk.readyChunkNum, 1); + } + + return TSDB_CODE_SUCCESS; +} + + +int32_t mpChunkEnsureCapacity(SMemPool* pPool, SMPChunkMgmt* pChunk) { + if (E_EVICT_ALL == pPool->cfg.evicPolicy) { + return TSDB_CODE_SUCCESS; + } + + int32_t readyMissNum = pChunk->readyChunkReserveNum - atomic_load_32(&pChunk->readyChunkNum); + if (readyMissNum <= 0) { + return TSDB_CODE_SUCCESS; + } + + MP_ERR_RET(mpChunkPrepare(pPool, readyMissNum)); + + return TSDB_CODE_SUCCESS; +} + +void mpChunkNotifyLowNum(SMemPool* pPool) { + +} + +int32_t mpChunkRetrieve(SMemPool* pPool, SMPChunk** ppChunk) { + SMPCacheGroup* pCache = NULL; + SMPChunk* pChunk = NULL; + int32_t readyChunkNum = atomic_sub_fetch_32(&pPool->chunk.readyChunkNum, 1); + if (readyChunkNum >= 0) { + if (atomic_add_fetch_32(&pPool->chunk.readyChunkGotNum, 1) == pPool->chunk.readyChunkLowNum) { + mpChunkNotifyLowNum(pPool); + } + + pChunk = (SMPChunk*)atomic_load_ptr(&pPool->chunk.readyChunkHead->list.pNext); + while (atomic_val_compare_exchange_ptr(&pPool->chunk.readyChunkHead->list.pNext, pChunk, pChunk->list.pNext) != pChunk) { + pChunk = (SMPChunk*)atomic_load_ptr(&pPool->chunk.readyChunkHead->list.pNext); + } + + *ppChunk = pChunk; + + return TSDB_CODE_SUCCESS; + } else { + atomic_add_fetch_32(&pPool->chunk.readyChunkNum, 1); + } + + MP_RET(mpChunkNew(pPool, ppChunk)); +} + +int32_t mpChunkRetrieveFromSession(SMemPool* pPool, SMPSession* pSession, int64_t size, SMPChunk** ppChunk, SMPChunk** ppPreChunk) { + SMPChunk* pChunk = pSession->chunk.srcChunkHead; + while (NULL != pChunk) { + if ((pChunk->offset + size) <= pPool->cfg.chunkSize) { + *ppChunk = pChunk; + break; + } + + *ppPreChunk = pChunk; + pChunk = (SMPChunk*)pChunk->list.pNext; + } + + if (NULL == *ppChunk) { + *ppPreChunk = NULL; + } + + return TSDB_CODE_SUCCESS; +} + +int32_t mpChunkAllocMem(SMemPool* pPool, SMPSession* pSession, int64_t size, uint32_t alignment, void** ppRes) { + int32_t code = TSDB_CODE_SUCCESS; + SMPChunk* pChunk = NULL, *preSrcChunk = NULL; + void* pRes = NULL; + int64_t totalSize = size + sizeof(SMPMemHeader) + sizeof(SMPMemTailer); + + if (pSession->chunk.srcChunkNum > 0) { + MP_ERR_JRET(mpChunkRetrieveFromSession(pPool, pSession, totalSize, &pChunk, &preSrcChunk)); + } + + if (NULL == pChunk) { + MP_ERR_JRET(mpChunkNew(pPool, &pChunk)); + + pSession->chunk.allocChunkNum++; + pSession->chunk.allocChunkMemSize += pPool->cfg.chunkSize; + mpUpdateAllocSize(pPool, pSession, totalSize, 0); + + MP_ADD_TO_CHUNK_LIST(pSession->chunk.srcChunkHead, pSession->chunk.srcChunkTail, pSession->chunk.srcChunkNum, pChunk); + MP_ADD_TO_CHUNK_LIST(pSession->chunk.inUseChunkHead, pSession->chunk.inUseChunkTail, pSession->chunk.inUseChunkNum, pChunk); + } + + SMPMemHeader* pHeader = (SMPMemHeader*)(pChunk->pMemStart + pChunk->offset); + MP_INIT_MEM_HEADER(pHeader, size, false); + + pRes = (void*)(pHeader + 1); + pChunk->offset += totalSize; + + if (pChunk->offset >= (pPool->cfg.chunkSize - pPool->chunk.maxDiscardSize)) { + if (NULL == preSrcChunk) { + pSession->chunk.srcChunkHead = NULL; + pSession->chunk.srcChunkTail = NULL; + } else { + preSrcChunk->list.pNext = pChunk->list.pNext; + } + + pSession->chunk.srcChunkNum--; + } + + +_return: + + *ppRes = pRes; + + return code; +} + +int32_t mpChunkNSAllocMem(SMemPool* pPool, SMPSession* pSession, int64_t size, uint32_t alignment, void** ppRes) { + int32_t code = TSDB_CODE_SUCCESS; + SMPNSChunk* pChunk = NULL; + void* pRes = NULL; + int64_t totalSize = size + sizeof(SMPMemHeader) + sizeof(SMPMemTailer) + alignment; + + MP_ERR_JRET(mpChunkNewNS(pPool, &pChunk, totalSize)); + SMPMemHeader* pHeader = (SMPMemHeader*)pChunk->pMemStart; + MP_INIT_MEM_HEADER(pHeader, size, false); + + pRes = (void*)(pHeader + 1); + + pSession->chunk.allocChunkNum++; + pSession->chunk.allocChunkMemSize += totalSize; + mpUpdateAllocSize(pPool, pSession, totalSize, 0); + + if (NULL == pSession->chunk.inUseNSChunkHead) { + pSession->chunk.inUseNSChunkHead = pChunk; + pSession->chunk.inUseNSChunkTail = pChunk; + } else { + pSession->chunk.inUseNSChunkTail->list.pNext = pChunk; + } + +_return: + + *ppRes = pRes; + + return code; +} + + +int32_t mpChunkInit(SMemPool* pPool, char* poolName, SMemPoolCfg* cfg) { + SMPChunkMgmt* pChunk = &pPool->chunk; + pChunk->threadChunkReserveNum = 1; + + pChunk->chunkCache.nodeSize = sizeof(SMPChunk); + pChunk->NSChunkCache.groupNum = MP_NSCHUNK_CACHE_ALLOC_BATCH_SIZE; + pChunk->NSChunkCache.nodeSize = sizeof(SMPNSChunk); + + MP_ERR_RET(mpAddCacheGroup(pPool, &pChunk->chunkCache, NULL)); + MP_ERR_RET(mpAddCacheGroup(pPool, &pChunk->NSChunkCache, NULL)); + + MP_ERR_RET(mpPopIdleNode(pPool, &pChunk->chunkCache, (void**)&pChunk->readyChunkHead)); + pChunk->readyChunkTail = pChunk->readyChunkHead; + + MP_ERR_RET(mpChunkEnsureCapacity(pPool, pChunk)); + + return TSDB_CODE_SUCCESS; +} + + +int64_t mpChunkGetMemSize(SMemPool* pPool, SMPSession* pSession, void *ptr) { + SMPMemHeader* pHeader = (SMPMemHeader*)ptr - 1; + return pHeader->size; +} + +int32_t mpChunkAlloc(SMemPool* pPool, SMPSession* pSession, int64_t* size, uint32_t alignment, void** ppRes) { + MP_RET((*size > pPool->cfg.chunkSize) ? mpChunkNSAllocMem(pPool, pSession, *size, alignment, ppRes) : mpChunkAllocMem(pPool, pSession, *size, alignment, ppRes)); +} + + +void mpChunkFree(SMemPool* pPool, SMPSession* pSession, void *ptr, int64_t* origSize) { + int64_t oSize = mpChunkGetMemSize(pPool, pSession, ptr); + if (origSize) { + *origSize = oSize; + } + + // TODO + + atomic_sub_fetch_64(&pSession->allocMemSize, oSize); + atomic_sub_fetch_64(&pPool->allocMemSize, oSize); +} + + +int32_t mpChunkRealloc(SMemPool* pPool, SMPSession* pSession, void **pPtr, int64_t* size, int64_t* origSize) { + int32_t code = TSDB_CODE_SUCCESS; + + if (*origSize >= *size) { + SMPMemHeader* pHeader = (SMPMemHeader*)((char*)*pPtr - sizeof(SMPMemHeader)); + pHeader->size = *size; + return TSDB_CODE_SUCCESS; + } + + void* res = NULL; + MP_ERR_JRET(mpMalloc(pPool, pSession, size, 0, &res)); + SMPMemHeader* pOrigHeader = (SMPMemHeader*)((char*)*pPtr - sizeof(SMPMemHeader)); + SMPMemHeader* pNewHeader = (SMPMemHeader*)((char*)res - sizeof(SMPMemHeader)); + + TAOS_MEMCPY(res, *pPtr, *origSize); + mpChunkFree(pPool, pSession, *pPtr, NULL); + *pPtr = res; + + return TSDB_CODE_SUCCESS; + +_return: + + mpChunkFree(pPool, pSession, *pPtr, NULL); + + return code; +} + +int32_t mpChunkInitSession(SMemPool* pPool, SMPSession* pSession) { + int32_t code = TSDB_CODE_SUCCESS; + SMPChunk* pChunk = NULL; + + MP_ERR_RET(mpChunkRetrieve(pPool, &pChunk)); + + pSession->chunk.allocChunkNum = 1; + pSession->chunk.allocChunkMemSize = pPool->cfg.chunkSize; + + MP_ADD_TO_CHUNK_LIST(pSession->chunk.srcChunkHead, pSession->chunk.srcChunkTail, pSession->chunk.srcChunkNum, pChunk); + MP_ADD_TO_CHUNK_LIST(pSession->chunk.inUseChunkHead, pSession->chunk.inUseChunkTail, pSession->chunk.inUseChunkNum, pChunk); + + return code; +} + +int32_t mpChunkUpdateCfg(SMemPool* pPool) { +/* + pPool->chunk.maxChunkNum = pPool->cfg.freeSize / pPool->cfg.chunkSize; + if (pPool->chunk.maxChunkNum <= 0) { + uError("invalid memory pool max chunk num, freeSize:%" PRId64 ", chunkSize:%d", pPool->cfg.freeSize, pPool->cfg.chunkSize); + return TSDB_CODE_INVALID_MEM_POOL_PARAM; + } + + pPool->chunk.readyChunkReserveNum = TMIN(pPool->cfg.threadNum * pPool->chunk.threadChunkReserveNum, pPool->chunk.maxChunkNum); + + pPool->chunk.chunkCache.groupNum = TMAX(pPool->chunk.maxChunkNum / 10, MP_CHUNK_CACHE_ALLOC_BATCH_SIZE); +*/ + return TSDB_CODE_SUCCESS; +} + +#endif + diff --git a/source/util/src/mpDirect.c b/source/util/src/mpDirect.c new file mode 100755 index 0000000000..d93f479be1 --- /dev/null +++ b/source/util/src/mpDirect.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#define _DEFAULT_SOURCE +#include "osMemPool.h" +#include "tmempoolInt.h" +#include "tlog.h" +#include "tutil.h" + +void* mpDirectAlloc(SMemPool* pPool, SMPJob* pJob, int64_t size) { + MP_CHECK_QUOTA(pPool, pJob, size); + + return taosMemMalloc(size); +} + + +void* mpDirectAlignAlloc(SMemPool* pPool, SMPJob* pJob, uint32_t alignment, int64_t size) { + MP_CHECK_QUOTA(pPool, pJob, size); + + return taosMemMallocAlign(alignment, size); +} + + +void* mpDirectCalloc(SMemPool* pPool, SMPJob* pJob, int64_t num, int64_t size) { + int64_t tSize = num * size; + MP_CHECK_QUOTA(pPool, pJob, tSize); + + return taosMemCalloc(num, size); +} + +void mpDirectFree(SMemPool* pPool, SMPJob* pJob, void *ptr) { + if (*pPool->cfg.jobQuota > 0) { + (void)atomic_sub_fetch_64(&pJob->job.allocMemSize, taosMemSize(ptr)); + } + taosMemFree(ptr); +} + + +void* mpDirectRealloc(SMemPool* pPool, SMPJob* pJob, void* ptr, int64_t size) { + int32_t code = TSDB_CODE_SUCCESS; + + if (NULL == ptr) { + return mpDirectAlloc(pPool, pJob, size); + } + + if (0 == size) { + mpDirectFree(pPool, pJob, ptr); + return NULL; + } + + int64_t oSize = taosMemSize(ptr); + + MP_CHECK_QUOTA(pPool, pJob, size - oSize); + + return taosMemRealloc(ptr, size); +} + +void* mpDirectStrdup(SMemPool* pPool, SMPJob* pJob, const void* ptr) { + if (NULL == ptr) { + return NULL; + } + + int64_t oSize = strlen(ptr); + MP_CHECK_QUOTA(pPool, pJob, oSize); + + return taosStrdupi(ptr); +} + +void* mpDirectStrndup(SMemPool* pPool, SMPJob* pJob, const void* ptr, int64_t size) { + if (NULL == ptr) { + return NULL; + } + + int64_t oSize = strlen(ptr); + MP_CHECK_QUOTA(pPool, pJob, TMIN(oSize, size) + 1); + + return taosStrndupi(ptr, size); +} + + + + +int64_t mpDirectGetMemSize(SMemPool* pPool, SMPSession* pSession, void *ptr) { + return taosMemSize(ptr); +} + +void mpDirectFullFree(SMemPool* pPool, SMPSession* pSession, void *ptr, int64_t* origSize) { + int64_t oSize = taosMemSize(ptr); + if (origSize) { + *origSize = oSize; + } + + MP_LOCK(MP_READ, &pPool->cfgLock); // tmp test + + taosMemFree(ptr); + + if (NULL != pSession) { + (void)atomic_sub_fetch_64(&pSession->allocMemSize, oSize); + (void)atomic_sub_fetch_64(&pSession->pJob->job.allocMemSize, oSize); + } + + (void)atomic_sub_fetch_64(&pPool->allocMemSize, oSize); + + MP_UNLOCK(MP_READ, &pPool->cfgLock); +} + + + +int32_t mpDirectFullAlloc(SMemPool* pPool, SMPSession* pSession, int64_t* size, uint32_t alignment, void** ppRes) { + int32_t code = TSDB_CODE_SUCCESS; + void* res = NULL; + int64_t nSize = *size; + + MP_LOCK(MP_READ, &pPool->cfgLock); + + MP_ERR_JRET(mpChkFullQuota(pPool, pSession, *size)); + + res = alignment ? taosMemMallocAlign(alignment, *size) : taosMemMalloc(*size); + if (NULL != res) { + nSize = taosMemSize(res); + mpUpdateAllocSize(pPool, pSession, nSize, nSize - *size); + } else { + if (NULL != pSession) { + (void)atomic_sub_fetch_64(&pSession->pJob->job.allocMemSize, *size); + } + + (void)atomic_sub_fetch_64(&pPool->allocMemSize, *size); + + uError("malloc %" PRId64 " alignment %d failed, code: 0x%x", *size, alignment, terrno); + + code = terrno; + } + +_return: + + MP_UNLOCK(MP_READ, &pPool->cfgLock); + + *ppRes = res; + *size = nSize; + + MP_RET(code); +} + +int32_t mpDirectFullRealloc(SMemPool* pPool, SMPSession* pSession, void **pPtr, int64_t* size, int64_t* origSize) { + int32_t code = TSDB_CODE_SUCCESS; + int64_t nSize = *size; + + MP_LOCK(MP_READ, &pPool->cfgLock); + + MP_ERR_JRET(mpChkFullQuota(pPool, pSession, *size - *origSize)); + + *pPtr = taosMemRealloc(*pPtr, *size); + if (NULL != *pPtr) { + nSize = taosMemSize(*pPtr); + mpUpdateAllocSize(pPool, pSession, nSize - *origSize, nSize - *size + *origSize); + } else { + MP_ERR_JRET(terrno); + } + +_return: + + MP_UNLOCK(MP_READ, &pPool->cfgLock); + + if (code) { + mpDirectFullFree(pPool, pSession, *pPtr, origSize); + *pPtr = NULL; + } + + *size = nSize; + + return TSDB_CODE_SUCCESS; +} + +int32_t mpDirectTrim(SMemPool* pPool, SMPSession* pSession, int32_t size, bool* trimed) { + return taosMemTrim(size, trimed); +} + + diff --git a/source/util/src/tarray.c b/source/util/src/tarray.c index b94bb512e2..b41e186e96 100644 --- a/source/util/src/tarray.c +++ b/source/util/src/tarray.c @@ -394,8 +394,14 @@ void taosArrayClearP(SArray* pArray, void (*fp)(void*)) { // fp(TARRAY_GET_ELEM(pArray, i)); // } if (pArray) { - for (int32_t i = 0; i < pArray->size; i++) { - fp(*(void**)TARRAY_GET_ELEM(pArray, i)); + if (NULL == fp) { + for (int32_t i = 0; i < pArray->size; i++) { + taosMemoryFree(*(void**)TARRAY_GET_ELEM(pArray, i)); + } + } else { + for (int32_t i = 0; i < pArray->size; i++) { + fp(*(void**)TARRAY_GET_ELEM(pArray, i)); + } } } taosArrayClear(pArray); @@ -410,8 +416,14 @@ void taosArrayDestroy(SArray* pArray) { void taosArrayDestroyP(SArray* pArray, FDelete fp) { if (pArray) { - for (int32_t i = 0; i < pArray->size; i++) { - fp(*(void**)TARRAY_GET_ELEM(pArray, i)); + if (NULL == fp) { + for (int32_t i = 0; i < pArray->size; i++) { + taosMemoryFree(*(void**)TARRAY_GET_ELEM(pArray, i)); + } + } else { + for (int32_t i = 0; i < pArray->size; i++) { + fp(*(void**)TARRAY_GET_ELEM(pArray, i)); + } } taosArrayDestroy(pArray); } @@ -566,4 +578,4 @@ void taosArraySwap(SArray* a, SArray* b) { void* data = a->pData; a->pData = b->pData; b->pData = data; -} \ No newline at end of file +} diff --git a/source/util/src/tconfig.c b/source/util/src/tconfig.c index c419a34577..cf9bfe525f 100644 --- a/source/util/src/tconfig.c +++ b/source/util/src/tconfig.c @@ -746,6 +746,18 @@ int32_t cfgAddBool(SConfig *pCfg, const char *name, bool defaultVal, int8_t scop return cfgAddItem(pCfg, &item, name); } +int32_t cfgAddInt32Ex(SConfig *pCfg, const char *name, int32_t defaultVal, int64_t minval, int64_t maxval, int8_t scope, + int8_t dynScope) { + SConfigItem item = {.dtype = CFG_DTYPE_INT32, + .i32 = defaultVal, + .imin = minval, + .imax = maxval, + .scope = scope, + .dynScope = dynScope}; + return cfgAddItem(pCfg, &item, name); +} + + int32_t cfgAddInt32(SConfig *pCfg, const char *name, int32_t defaultVal, int64_t minval, int64_t maxval, int8_t scope, int8_t dynScope, int8_t category) { if (defaultVal < minval || defaultVal > maxval) { diff --git a/source/util/src/terror.c b/source/util/src/terror.c index 7995ba8578..a2a94f053d 100644 --- a/source/util/src/terror.c +++ b/source/util/src/terror.c @@ -515,6 +515,9 @@ TAOS_DEFINE_ERROR(TSDB_CODE_QRY_FILTER_NOT_SUPPORT_TYPE, "Not supported range t TAOS_DEFINE_ERROR(TSDB_CODE_QRY_FILTER_WRONG_OPTR_TYPE, "Wrong operator type") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_FILTER_RANGE_ERROR, "Wrong filter range") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_FILTER_INVALID_TYPE, "Invalid filter type") +TAOS_DEFINE_ERROR(TSDB_CODE_QRY_REACH_QMEM_THRESHOLD, "Query memory upper limit is reached") +TAOS_DEFINE_ERROR(TSDB_CODE_QRY_QUERY_MEM_EXHAUSTED, "Query memory exhausted") +TAOS_DEFINE_ERROR(TSDB_CODE_QRY_NO_FETCH_TIMEOUT, "Timeout for long time no fetch") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_TASK_SUCC_TO_PARTSUSS, "Change task status from success to partial success") // grant diff --git a/source/util/src/thash.c b/source/util/src/thash.c index 88fe6618b9..562fef2027 100644 --- a/source/util/src/thash.c +++ b/source/util/src/thash.c @@ -318,6 +318,7 @@ int32_t taosHashPut(SHashObj *pHashObj, const void *key, size_t keyLen, const vo return terrno = TSDB_CODE_INVALID_PTR; } + int32_t code = TSDB_CODE_SUCCESS; uint32_t hashVal = (*pHashObj->hashFp)(key, (uint32_t)keyLen); // need the resize process, write lock applied @@ -327,10 +328,15 @@ int32_t taosHashPut(SHashObj *pHashObj, const void *key, size_t keyLen, const vo taosHashWUnlock(pHashObj); } + SHashNode *pNewNode = doCreateHashNode(key, keyLen, data, size, hashVal); + if (pNewNode == NULL) { + code = terrno; + return code; + } + // disable resize taosHashRLock(pHashObj); - int32_t code = TSDB_CODE_SUCCESS; uint32_t slot = HASH_INDEX(hashVal, pHashObj->capacity); SHashEntry *pe = pHashObj->hashList[slot]; @@ -350,33 +356,22 @@ int32_t taosHashPut(SHashObj *pHashObj, const void *key, size_t keyLen, const vo if (pNode == NULL) { // no data in hash table with the specified key, add it into hash table - SHashNode *pNewNode = doCreateHashNode(key, keyLen, data, size, hashVal); - if (pNewNode == NULL) { - // terrno = TSDB_CODE_OUT_OF_MEMORY; - code = terrno; - goto _exit; - } - pushfrontNodeInEntryList(pe, pNewNode); (void)atomic_add_fetch_64(&pHashObj->size, 1); } else { // not support the update operation, return error if (pHashObj->enableUpdate) { - SHashNode *pNewNode = doCreateHashNode(key, keyLen, data, size, hashVal); - if (pNewNode == NULL) { - // terrno = TSDB_CODE_OUT_OF_MEMORY; - code = terrno; - goto _exit; - } - doUpdateHashNode(pHashObj, pe, prev, pNode, pNewNode); } else { + taosMemoryFreeClear(pNewNode); terrno = TSDB_CODE_DUP_KEY; code = terrno; goto _exit; } } + _exit: + taosHashEntryWUnlock(pHashObj, pe); taosHashRUnlock(pHashObj); return code; diff --git a/source/util/src/theap.c b/source/util/src/theap.c index 600bc2b998..d2348ba6b5 100644 --- a/source/util/src/theap.c +++ b/source/util/src/theap.c @@ -218,7 +218,7 @@ void destroyPriorityQueue(PriorityQueue* pq) { if (pq->deleteFn) taosArrayDestroyP(pq->container, pq->deleteFn); else - taosArrayDestroy(pq->container); + taosArrayDestroyP(pq->container, NULL); taosMemoryFree(pq); } @@ -308,7 +308,11 @@ PriorityQueueNode* taosPQPush(PriorityQueue* pq, const PriorityQueueNode* node) void taosPQPop(PriorityQueue* pq) { PriorityQueueNode* top = taosPQTop(pq); - if (pq->deleteFn) pq->deleteFn(top->data); + if (pq->deleteFn) { + pq->deleteFn(top->data); + } else { + taosMemoryFree(top->data); + } pqRemove(pq, 0); } @@ -342,6 +346,13 @@ BoundedQueue* createBoundedQueue(uint32_t maxSize, pq_comp_fn fn, FDelete delete void taosBQSetFn(BoundedQueue* q, pq_comp_fn fn) { taosPQSetFn(q->queue, fn); } +void taosBQClear(BoundedQueue* q) { + if (q->queue->deleteFn) + taosArrayClearEx(q->queue->container, q->queue->deleteFn); + else + taosArrayClear(q->queue->container); +} + void destroyBoundedQueue(BoundedQueue* q) { if (!q) return; destroyPriorityQueue(q->queue); @@ -356,8 +367,10 @@ PriorityQueueNode* taosBQPush(BoundedQueue* q, PriorityQueueNode* n) { } else { void* p = top->data; top->data = n->data; - n->data = p; - if (q->queue->deleteFn) q->queue->deleteFn(n->data); + if (q->queue->deleteFn) { + n->data = p; + q->queue->deleteFn(n->data); + } } return pqHeapify(q->queue, 0, taosBQSize(q)); } else { diff --git a/source/util/src/tlockfree.c b/source/util/src/tlockfree.c index 1961b404b5..9af2e739e0 100644 --- a/source/util/src/tlockfree.c +++ b/source/util/src/tlockfree.c @@ -91,4 +91,21 @@ void taosRLockLatch(SRWLatch *pLatch) { } } +// no reentrant +int32_t taosRTryLockLatch(SRWLatch *pLatch) { + SRWLatch oLatch, nLatch; + oLatch = atomic_load_32(pLatch); + if (oLatch) { + return -1; + } + + nLatch = oLatch + 1; + if (atomic_val_compare_exchange_32(pLatch, oLatch, nLatch) == oLatch) { + return 0; + } + + return -1; +} + + void taosRUnLockLatch(SRWLatch *pLatch) { (void)atomic_fetch_sub_32(pLatch, 1); } diff --git a/source/util/src/tlog.c b/source/util/src/tlog.c index 7a5852f329..c3d78b7c17 100644 --- a/source/util/src/tlog.c +++ b/source/util/src/tlog.c @@ -299,6 +299,10 @@ int32_t taosInitLog(const char *logName, int32_t maxFiles, bool tsc) { return 0; } +void taosSetNoNewFile() { + tsLogObj.openInProgress = 1; +} + static void taosStopLog() { if (tsLogObj.logHandle) { tsLogObj.logHandle->stop = 1; @@ -398,12 +402,12 @@ typedef struct { } OldFileKeeper; static OldFileKeeper *taosOpenNewFile() { char keepName[PATH_MAX + 20]; - sprintf(keepName, "%s.%d", tsLogObj.logName, tsLogObj.flag); + TAOS_UNUSED(snprintf(keepName, sizeof(keepName), "%s.%d", tsLogObj.logName, tsLogObj.flag)); tsLogObj.flag ^= 1; tsLogObj.lines = 0; char name[PATH_MAX + 20]; - sprintf(name, "%s.%d", tsLogObj.logName, tsLogObj.flag); + TAOS_UNUSED(snprintf(name, sizeof(name), "%s.%d", tsLogObj.logName, tsLogObj.flag)); TAOS_UNUSED(taosUmaskFile(0)); @@ -439,9 +443,9 @@ static OldFileKeeper *taosOpenNewFile() { static void *taosThreadToCloseOldFile(void *param) { if (!param) return NULL; - taosWLockLatch(&tsLogRotateLatch); OldFileKeeper *oldFileKeeper = (OldFileKeeper *)param; taosSsleep(20); + taosWLockLatch(&tsLogRotateLatch); taosCloseLogByFd(oldFileKeeper->pOldFile); taosKeepOldLog(oldFileKeeper->keepName); taosMemoryFree(oldFileKeeper); @@ -578,22 +582,22 @@ static void decideLogFileName(const char *fn, int32_t maxFileNum) { } if (strlen(fn) < PATH_MAX) { - strcpy(tsLogObj.logName, fn); + tstrncpy(tsLogObj.logName, fn, PATH_MAX); } } static void decideLogFileNameFlag() { - char name[PATH_MAX + 50] = "\0"; + char name[PATH_MAX] = "\0"; int64_t logstat0_mtime = 0; int64_t logstat1_mtime = 0; bool log0Exist = false; bool log1Exist = false; - if (strlen(tsLogObj.logName) < PATH_MAX + 50 - 2) { - strcpy(name, tsLogObj.logName); - strcat(name, ".0"); + int32_t logNameLen = strlen(tsLogObj.logName) + 2; + if (logNameLen < PATH_MAX) { + TAOS_UNUSED(snprintf(name, PATH_MAX, "%s%s", tsLogObj.logName, ".0")); log0Exist = taosStatFile(name, NULL, &logstat0_mtime, NULL) == 0; - name[strlen(name) - 1] = '1'; + name[logNameLen - 1] = '1'; log1Exist = taosStatFile(name, NULL, &logstat1_mtime, NULL) == 0; } @@ -627,8 +631,15 @@ static int32_t taosInitNormalLog(const char *logName, int32_t maxFileNum) { processLogFileName(logName, maxFileNum); - char name[PATH_MAX + 50] = "\0"; - (void)sprintf(name, "%s.%d", tsLogObj.logName, tsLogObj.flag); + int32_t logNameLen = strlen(tsLogObj.logName) + 2; // logName + ".0" or ".1" + + if (logNameLen < 0 || logNameLen >= PATH_MAX) { + uError("log name:%s is invalid since length:%d is out of range", logName, logNameLen); + return TSDB_CODE_INVALID_CFG; + } + + char name[PATH_MAX] = "\0"; + (void)snprintf(name, sizeof(name), "%s.%d", tsLogObj.logName, tsLogObj.flag); (void)taosThreadMutexInit(&tsLogObj.logMutex, NULL); TAOS_UNUSED(taosUmaskFile(0)); @@ -657,19 +668,19 @@ static int32_t taosInitNormalLog(const char *logName, int32_t maxFileNum) { return terrno; } - (void)sprintf(name, "==================================================\n"); + (void)snprintf(name, sizeof(name), "==================================================\n"); if (taosWriteFile(tsLogObj.logHandle->pFile, name, (uint32_t)strlen(name)) <= 0) { TAOS_UNUSED(printf("failed to write to log file:%s, reason:%s\n", name, tstrerror(terrno))); taosUnLockLogFile(tsLogObj.logHandle->pFile); return terrno; } - (void)sprintf(name, " new log file \n"); + (void)snprintf(name, sizeof(name), " new log file \n"); if (taosWriteFile(tsLogObj.logHandle->pFile, name, (uint32_t)strlen(name)) <= 0) { TAOS_UNUSED(printf("failed to write to log file:%s, reason:%s\n", name, tstrerror(terrno))); taosUnLockLogFile(tsLogObj.logHandle->pFile); return terrno; } - (void)sprintf(name, "==================================================\n"); + (void)snprintf(name, sizeof(name), "==================================================\n"); if (taosWriteFile(tsLogObj.logHandle->pFile, name, (uint32_t)strlen(name)) <= 0) { TAOS_UNUSED(printf("failed to write to log file:%s, reason:%s\n", name, tstrerror(terrno))); taosUnLockLogFile(tsLogObj.logHandle->pFile); @@ -706,13 +717,13 @@ static inline int32_t taosBuildLogHead(char *buffer, const char *flags) { TAOS_UNUSED(taosGetTimeOfDay(&timeSecs)); time_t curTime = timeSecs.tv_sec; ptm = taosLocalTime(&curTime, &Tm, NULL, 0, NULL); - if (ptm == NULL){ - uError("%s failed to get local time, code:%d", __FUNCTION__ , errno); + if (ptm == NULL) { + uError("%s failed to get local time, code:%d", __FUNCTION__, errno); return 0; } - return sprintf(buffer, "%02d/%02d %02d:%02d:%02d.%06d %08" PRId64 " %s %s", ptm->tm_mon + 1, ptm->tm_mday, - ptm->tm_hour, ptm->tm_min, ptm->tm_sec, (int32_t)timeSecs.tv_usec, taosGetSelfPthreadId(), - LOG_EDITION_FLG, flags); + return snprintf(buffer, LOG_MAX_STACK_LINE_BUFFER_SIZE, "%02d/%02d %02d:%02d:%02d.%06d %08" PRId64 " %s %s", + ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, (int32_t)timeSecs.tv_usec, + taosGetSelfPthreadId(), LOG_EDITION_FLG, flags); } static inline void taosPrintLogImp(ELogLevel level, int32_t dflag, const char *buffer, int32_t len) { @@ -871,6 +882,7 @@ void taosPrintSlowLog(const char *format, ...) { taosMemoryFree(buffer); } +#if 0 void taosDumpData(unsigned char *msg, int32_t len) { if (!osLogSpaceAvailable()) return; taosUpdateLogNums(DEBUG_DUMP); @@ -894,6 +906,7 @@ void taosDumpData(unsigned char *msg, int32_t len) { TAOS_UNUSED(taosWriteFile(tsLogObj.logHandle->pFile, temp, (uint32_t)pos)); } +#endif static void taosCloseLogByFd(TdFilePtr pFile) { if (pFile != NULL) { diff --git a/source/util/src/tmempool.c b/source/util/src/tmempool.c index 2e8fdc2b17..4189efd684 100644 --- a/source/util/src/tmempool.c +++ b/source/util/src/tmempool.c @@ -14,114 +14,1767 @@ */ #define _DEFAULT_SOURCE -#include "tmempool.h" +#include "osMemPool.h" +#include "tmempoolInt.h" #include "tlog.h" #include "tutil.h" +#include "taos.h" +#include "tglobal.h" -typedef struct { - int32_t numOfFree; /* number of free slots */ - int32_t first; /* the first free slot */ - int32_t numOfBlock; /* the number of blocks */ - int32_t blockSize; /* block size in bytes */ - int32_t *freeList; /* the index list */ - char *pool; /* the actual mem block */ - TdThreadMutex mutex; -} pool_t; +static TdThreadOnce gMPoolInit = PTHREAD_ONCE_INIT; +void* gMemPoolHandle = NULL; +threadlocal void* threadPoolSession = NULL; +threadlocal bool threadPoolEnabled = true; -mpool_h taosMemPoolInit(int32_t numOfBlock, int32_t blockSize) { - int32_t i; - pool_t *pool_p; +SMemPoolMgmt gMPMgmt = {0}; +SMPStrategyFp gMPFps[] = { + {NULL}, + {NULL, mpDirectFullAlloc, mpDirectFullFree, mpDirectGetMemSize, mpDirectFullRealloc, NULL, NULL, mpDirectTrim}, + //{mpChunkInit, mpChunkAlloc, mpChunkFree, mpChunkGetMemSize, mpChunkRealloc, mpChunkInitSession, mpChunkUpdateCfg, NULL} +}; - if (numOfBlock <= 1 || blockSize <= 1) { - uError("invalid parameter in memPoolInit\n"); - return NULL; + +int32_t mpCheckCfg(SMemPoolCfg* cfg) { + if (cfg->chunkSize < MEMPOOL_MIN_CHUNK_SIZE || cfg->chunkSize > MEMPOOL_MAX_CHUNK_SIZE) { + uError("invalid memory pool chunkSize:%d", cfg->chunkSize); + return TSDB_CODE_INVALID_PARA; } - pool_p = (pool_t *)taosMemoryMalloc(sizeof(pool_t)); - if (pool_p == NULL) { - uError("mempool malloc failed\n"); - return NULL; + if (cfg->evicPolicy <= 0 || cfg->evicPolicy >= E_EVICT_MAX_VALUE) { + uError("invalid memory pool evicPolicy:%d", cfg->evicPolicy); + return TSDB_CODE_INVALID_PARA; + } + + if (cfg->threadNum <= 0) { + uError("invalid memory pool threadNum:%d", cfg->threadNum); + return TSDB_CODE_INVALID_PARA; + } + + return TSDB_CODE_SUCCESS; +} + + +void mpFreeCacheGroup(SMPCacheGroup* pGrp) { + if (NULL == pGrp) { + return; + } + + taosMemoryFree(pGrp->pNodes); + taosMemoryFree(pGrp); +} + + +int32_t mpAddCacheGroup(SMemPool* pPool, SMPCacheGroupInfo* pInfo, SMPCacheGroup* pHead) { + SMPCacheGroup* pGrp = NULL; + if (NULL == pInfo->pGrpHead) { + pInfo->pGrpHead = taosMemoryCalloc(1, sizeof(*pInfo->pGrpHead)); + if (NULL == pInfo->pGrpHead) { + uError("malloc pGrpHead failed, error:%s", tstrerror(terrno)); + MP_ERR_RET(terrno); + } + + pGrp = pInfo->pGrpHead; } else { - (void)memset(pool_p, 0, sizeof(pool_t)); + pGrp = (SMPCacheGroup*)taosMemoryCalloc(1, sizeof(SMPCacheGroup)); + if (NULL == pInfo->pGrpHead) { + uError("malloc SMPCacheGroup failed, error:%s", tstrerror(terrno)); + MP_ERR_RET(terrno); + } + pGrp->pNext = pHead; } - pool_p->blockSize = blockSize; - pool_p->numOfBlock = numOfBlock; - pool_p->pool = (char *)taosMemoryMalloc((size_t)(blockSize * numOfBlock)); - pool_p->freeList = (int32_t *)taosMemoryMalloc(sizeof(int32_t) * (size_t)numOfBlock); - - if (pool_p->pool == NULL || pool_p->freeList == NULL) { - uError("failed to allocate memory\n"); - taosMemoryFreeClear(pool_p->freeList); - taosMemoryFreeClear(pool_p->pool); - taosMemoryFreeClear(pool_p); - return NULL; + pGrp->nodesNum = pInfo->groupNum; + pGrp->pNodes = taosMemoryCalloc(pGrp->nodesNum, pInfo->nodeSize); + if (NULL == pGrp->pNodes) { + uError("calloc %d %d nodes in cache group failed", pGrp->nodesNum, pInfo->nodeSize); + MP_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); } - (void)taosThreadMutexInit(&(pool_p->mutex), NULL); + if (pHead && atomic_val_compare_exchange_ptr(&pInfo->pGrpHead, pHead, pGrp) != pHead) { + mpFreeCacheGroup(pGrp); + return TSDB_CODE_SUCCESS; + } - (void)memset(pool_p->pool, 0, (size_t)(blockSize * numOfBlock)); - for (i = 0; i < pool_p->numOfBlock; ++i) pool_p->freeList[i] = i; + atomic_add_fetch_64(&pInfo->allocNum, pGrp->nodesNum); - pool_p->first = 0; - pool_p->numOfFree = pool_p->numOfBlock; - - return (mpool_h)pool_p; + return TSDB_CODE_SUCCESS; } -char *taosMemPoolMalloc(mpool_h handle) { - char *pos = NULL; - pool_t *pool_p = (pool_t *)handle; +void mpDestroyCacheGroup(SMPCacheGroupInfo* pInfo) { + SMPCacheGroup* pGrp = pInfo->pGrpHead; + SMPCacheGroup* pNext = NULL; + while (NULL != pGrp) { + pNext = pGrp->pNext; - (void)taosThreadMutexLock(&(pool_p->mutex)); + mpFreeCacheGroup(pGrp); - if (pool_p->numOfFree > 0) { - pos = pool_p->pool + pool_p->blockSize * (pool_p->freeList[pool_p->first]); - pool_p->first++; - pool_p->first = pool_p->first % pool_p->numOfBlock; - pool_p->numOfFree--; + pGrp = pNext; } - - (void)taosThreadMutexUnlock(&(pool_p->mutex)); - - if (pos == NULL) uDebug("mempool: out of memory"); - return pos; } -void taosMemPoolFree(mpool_h handle, char *pMem) { - int32_t index; - pool_t *pool_p = (pool_t *)handle; - if (pMem == NULL) return; +int32_t mpPopIdleNode(SMemPool* pPool, SMPCacheGroupInfo* pInfo, void** ppRes) { + SMPCacheGroup* pGrp = NULL; + SMPListNode* pNode = NULL; + + while (true) { + pNode = (SMPListNode*)atomic_load_ptr(&pInfo->pIdleList); + if (NULL == pNode) { + break; + } - index = (int32_t)(pMem - pool_p->pool) % pool_p->blockSize; - if (index != 0) { - uError("invalid free address:%p\n", pMem); + if (atomic_val_compare_exchange_ptr(&pInfo->pIdleList, pNode, pNode->pNext) != pNode) { + continue; + } + + pNode->pNext = NULL; + goto _return; + } + + while (true) { + pGrp = atomic_load_ptr(&pInfo->pGrpHead); + int32_t offset = atomic_fetch_add_32(&pGrp->idleOffset, 1); + if (offset < pGrp->nodesNum) { + pNode = (SMPListNode*)((char*)pGrp->pNodes + offset * pInfo->nodeSize); + break; + } else { + atomic_sub_fetch_32(&pGrp->idleOffset, 1); + } + + MP_ERR_RET(mpAddCacheGroup(pPool, pInfo, pGrp)); + } + +_return: + + *ppRes = pNode; + + return TSDB_CODE_SUCCESS; +} + +void mpPushIdleNode(SMemPool* pPool, SMPCacheGroupInfo* pInfo, SMPListNode* pNode) { + SMPCacheGroup* pGrp = NULL; + SMPListNode* pOrig = NULL; + + while (true) { + pOrig = (SMPListNode*)atomic_load_ptr(&pInfo->pIdleList); + pNode->pNext = pOrig; + + if (atomic_val_compare_exchange_ptr(&pInfo->pIdleList, pOrig, pNode) != pOrig) { + continue; + } + + break; + } +} + + +int32_t mpUpdateCfg(SMemPool* pPool) { + if (gMPFps[gMPMgmt.strategy].updateCfgFp) { + MP_ERR_RET((*gMPFps[gMPMgmt.strategy].updateCfgFp)(pPool)); + } + + uDebug("memPool %s cfg updated, reserveSize:%" PRId64 ", jobQuota:%dMB, threadNum:%d", + pPool->name, pPool->cfg.reserveSize, *pPool->cfg.jobQuota, pPool->cfg.threadNum); + + return TSDB_CODE_SUCCESS; +} + +uint32_t mpFileIdHashFp(const char* fileId, uint32_t len) { + return *(uint32_t*)fileId; +} + +void mpDestroyPosStat(SMPStatPos* pStat) { + taosHashCleanup(pStat->fileHash); + pStat->fileHash = NULL; + taosHashCleanup(pStat->remainHash); + pStat->remainHash = NULL; + taosHashCleanup(pStat->allocHash); + pStat->allocHash = NULL; + taosHashCleanup(pStat->freeHash); + pStat->freeHash = NULL; +} + +int32_t mpInitPosStat(SMPStatPos* pStat, bool sessionStat) { + pStat->remainHash = taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK); + if (NULL == pStat->remainHash) { + uError("memPool init posStat remainHash failed, error:%s, sessionStat:%d", tstrerror(terrno), sessionStat); + return terrno; + } + + pStat->allocHash = taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK); + if (NULL == pStat->allocHash) { + uError("memPool init posStat allocHash failed, error:%s, sessionStat:%d", tstrerror(terrno), sessionStat); + return terrno; + } + + pStat->freeHash = taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK); + if (NULL == pStat->freeHash) { + uError("memPool init posStat freeHash failed, error:%s, sessionStat:%d", tstrerror(terrno), sessionStat); + return terrno; + } + + pStat->fileHash = taosHashInit(1024, mpFileIdHashFp, false, HASH_ENTRY_LOCK); + if (NULL == pStat->fileHash) { + uError("memPool init posStat fileHash failed, error:%s, sessionStat:%d", tstrerror(terrno), sessionStat); + return terrno; + } + + uDebug("memPool stat initialized, sessionStat:%d", sessionStat); + + return TSDB_CODE_SUCCESS; +} + +int32_t mpInit(SMemPool* pPool, char* poolName, SMemPoolCfg* cfg) { +// MP_ERR_RET(mpCheckCfg(cfg)); + + TAOS_MEMCPY(&pPool->cfg, cfg, sizeof(*cfg)); + + pPool->name = taosStrdup(poolName); + if (NULL == pPool->name) { + uError("calloc memory pool name %s failed", poolName); + MP_ERR_RET(terrno); + } + + MP_ERR_RET(mpUpdateCfg(pPool)); + + pPool->sessionCache.groupNum = MP_SESSION_CACHE_ALLOC_BATCH_SIZE; + pPool->sessionCache.nodeSize = sizeof(SMPSession); + + MP_ERR_RET(mpAddCacheGroup(pPool, &pPool->sessionCache, NULL)); + + if (gMPFps[gMPMgmt.strategy].initFp) { + MP_ERR_RET((*gMPFps[gMPMgmt.strategy].initFp)(pPool, poolName, cfg)); + } + + if (tsMemPoolFullFunc) { + MP_ERR_RET(mpInitPosStat(&pPool->stat.posStat, false)); + } + + return TSDB_CODE_SUCCESS; +} + +FORCE_INLINE void mpUpdateMaxAllocSize(int64_t* pMaxAllocMemSize, int64_t newSize) { + int64_t maxAllocMemSize = atomic_load_64(pMaxAllocMemSize); + while (true) { + if (newSize <= maxAllocMemSize) { + break; + } + + if (maxAllocMemSize == atomic_val_compare_exchange_64(pMaxAllocMemSize, maxAllocMemSize, newSize)) { + break; + } + + maxAllocMemSize = atomic_load_64(pMaxAllocMemSize); + } +} + +void mpUpdateAllocSize(SMemPool* pPool, SMPSession* pSession, int64_t size, int64_t addSize) { + if (addSize) { + if (NULL != pSession) { + atomic_add_fetch_64(&pSession->pJob->job.allocMemSize, addSize); + } + atomic_add_fetch_64(&pPool->allocMemSize, addSize); + } + + if (NULL != pSession) { + int64_t allocMemSize = atomic_add_fetch_64(&pSession->allocMemSize, size); + mpUpdateMaxAllocSize(&pSession->maxAllocMemSize, allocMemSize); + + allocMemSize = atomic_load_64(&pSession->pJob->job.allocMemSize); + mpUpdateMaxAllocSize(&pSession->pJob->job.maxAllocMemSize, allocMemSize); + } + + if (MP_GET_FLAG(gMPMgmt.ctrl.funcFlags, MP_CTRL_FLAG_LOG_MAXSIZE)) { + int64_t allocMemSize = atomic_load_64(&pPool->allocMemSize); + mpUpdateMaxAllocSize(&pPool->maxAllocMemSize, allocMemSize); + } +} + +int32_t mpPutRetireMsgToQueue(SMemPool* pPool, bool retireLowLevel) { + if (retireLowLevel) { + if (0 == atomic_val_compare_exchange_8(&gMPMgmt.msgQueue.lowLevelRetire, 0, 1)) { + atomic_store_ptr(&gMPMgmt.msgQueue.pPool, pPool); + MP_ERR_RET(tsem2_post(&gMPMgmt.threadSem)); + } + + return TSDB_CODE_SUCCESS; + } + + if (0 == atomic_val_compare_exchange_8(&gMPMgmt.msgQueue.midLevelRetire, 0, 1)) { + atomic_store_ptr(&gMPMgmt.msgQueue.pPool, pPool); + MP_ERR_RET(tsem2_post(&gMPMgmt.threadSem)); + } + + return TSDB_CODE_SUCCESS; +} + + +int32_t mpChkFullQuota(SMemPool* pPool, SMPSession* pSession, int64_t size) { + int32_t code = TSDB_CODE_SUCCESS; + if (NULL == pSession) { + (void)atomic_add_fetch_64(&pPool->allocMemSize, size); + return code; + } + + SMPJob* pJob = pSession->pJob; + int64_t cAllocSize = atomic_add_fetch_64(&pJob->job.allocMemSize, size); + int64_t quota = atomic_load_32(pPool->cfg.jobQuota); + if (quota > 0 && cAllocSize > (quota * 1048576L)) { + code = TSDB_CODE_QRY_REACH_QMEM_THRESHOLD; + uWarn("job 0x%" PRIx64 " allocSize %" PRId64 " is over than quota %" PRId64, pJob->job.jobId, cAllocSize, quota); + pPool->cfg.cb.reachFp(pJob->job.jobId, pJob->job.clientId, code); + mpSchedTrim(NULL); + (void)atomic_sub_fetch_64(&pJob->job.allocMemSize, size); + MP_RET(code); + } + + if (atomic_load_64(&tsCurrentAvailMemorySize) <= (pPool->cfg.reserveSize + size)) { + code = TSDB_CODE_QRY_QUERY_MEM_EXHAUSTED; + uWarn("%s pool sysAvailMemSize %" PRId64 " can't alloc %" PRId64" while keeping reserveSize %" PRId64 " bytes", + pPool->name, atomic_load_64(&tsCurrentAvailMemorySize), size, pPool->cfg.reserveSize); + pPool->cfg.cb.reachFp(pJob->job.jobId, pJob->job.clientId, code); + mpSchedTrim(NULL); + (void)atomic_sub_fetch_64(&pJob->job.allocMemSize, size); + MP_RET(code); + } + + (void)atomic_add_fetch_64(&pPool->allocMemSize, size); + +/* + int64_t pAllocSize = atomic_add_fetch_64(&pPool->allocMemSize, size); + if (pAllocSize >= atomic_load_32(pPool->cfg.upperLimitSize) * 1048576UL) { + code = TSDB_CODE_QRY_QUERY_MEM_EXHAUSTED; + uWarn("%s pool allocSize %" PRId64 " reaches the upperLimit %" PRId64, pPool->name, pAllocSize, atomic_load_32(pPool->cfg.upperLimitSize) * 1048576UL); + pPool->cfg.cb.retireJobFp(&pJob->job, code); + (void)atomic_sub_fetch_64(&pJob->job.allocMemSize, size); + (void)atomic_sub_fetch_64(&pPool->allocMemSize, size); + MP_RET(code); + } +*/ + + return TSDB_CODE_SUCCESS; +} + +int64_t mpGetMemorySizeImpl(SMemPool* pPool, SMPSession* pSession, void *ptr) { + return (*gMPFps[gMPMgmt.strategy].getSizeFp)(pPool, pSession, ptr); +} + +int32_t mpMalloc(SMemPool* pPool, SMPSession* pSession, int64_t* size, uint32_t alignment, void** ppRes) { + MP_RET((*gMPFps[gMPMgmt.strategy].allocFp)(pPool, pSession, size, alignment, ppRes)); +} + +int32_t mpCalloc(SMemPool* pPool, SMPSession* pSession, int64_t* size, void** ppRes) { + int32_t code = TSDB_CODE_SUCCESS; + void *res = NULL; + + MP_ERR_RET(mpMalloc(pPool, pSession, size, 0, &res)); + + if (NULL != res) { + TAOS_MEMSET(res, 0, *size); + } + +_return: + + *ppRes = res; + + return code; +} + + +void mpFree(SMemPool* pPool, SMPSession* pSession, void *ptr, int64_t* origSize) { + if (NULL == ptr) { + if (origSize) { + *origSize = 0; + } + return; } - index = (int32_t)((pMem - pool_p->pool) / pool_p->blockSize); - if (index < 0 || index >= pool_p->numOfBlock) { - uError("mempool: error, invalid address:%p", pMem); + (*gMPFps[gMPMgmt.strategy].freeFp)(pPool, pSession, ptr, origSize); +} + +int32_t mpRealloc(SMemPool* pPool, SMPSession* pSession, void **pPtr, int64_t* size, int64_t* origSize) { + int32_t code = TSDB_CODE_SUCCESS; + + if (NULL == *pPtr) { + *origSize = 0; + MP_RET(mpMalloc(pPool, pSession, size, 0, pPtr)); + } + + if (0 == *size) { + mpFree(pPool, pSession, *pPtr, origSize); + *pPtr = NULL; + return TSDB_CODE_SUCCESS; + } + + *origSize = mpGetMemorySizeImpl(pPool, pSession, *pPtr); + + MP_RET((*gMPFps[gMPMgmt.strategy].reallocFp)(pPool, pSession, pPtr, size, origSize)); +} + +int32_t mpTrim(SMemPool* pPool, SMPSession* pSession, int32_t size, bool* trimed) { + int32_t code = TSDB_CODE_SUCCESS; + + if (gMPFps[gMPMgmt.strategy].trimFp) { + MP_RET((*gMPFps[gMPMgmt.strategy].trimFp)(pPool, pSession, size, trimed)); + } + + return code; +} + + +void mpPrintStatDetail(SMPCtrlInfo* pCtrl, SMPStatDetail* pDetail, char* detailName, int64_t maxAllocSize) { + if (!MP_GET_FLAG(pCtrl->funcFlags, MP_CTRL_FLAG_PRINT_STAT)) { return; } - (void)memset(pMem, 0, (size_t)pool_p->blockSize); + uInfo("MemPool [%s] stat detail:", detailName); - (void)taosThreadMutexLock(&pool_p->mutex); - - pool_p->freeList[(pool_p->first + pool_p->numOfFree) % pool_p->numOfBlock] = index; - pool_p->numOfFree++; - - (void)taosThreadMutexUnlock(&pool_p->mutex); + uInfo("Max Used Memory Size: %" PRId64, maxAllocSize); + + uInfo("[times]:"); + switch (gMPMgmt.strategy) { + case E_MP_STRATEGY_DIRECT: + uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Malloc", pDetail->times.memMalloc)); + uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Calloc", pDetail->times.memCalloc)); + uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Realloc", pDetail->times.memRealloc)); + uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Strdup", pDetail->times.memStrdup)); + uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Strndup", pDetail->times.memStrndup)); + uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Free", pDetail->times.memFree)); + uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Trim", pDetail->times.memTrim)); + break; + case E_MP_STRATEGY_CHUNK: + uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("chunkMalloc", pDetail->times.chunkMalloc)); + uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("chunkRecycle", pDetail->times.chunkRecycle)); + uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("chunkReUse", pDetail->times.chunkReUse)); + uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("chunkFree", pDetail->times.chunkFree)); + break; + default: + break; + } + + uInfo("[bytes]:"); + switch (gMPMgmt.strategy) { + case E_MP_STRATEGY_DIRECT: + uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Malloc", pDetail->bytes.memMalloc)); + uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Calloc", pDetail->bytes.memCalloc)); + uInfo(MP_STAT_ORIG_FORMAT, MP_STAT_ORIG_VALUE("Realloc", pDetail->bytes.memRealloc)); + uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Strdup", pDetail->bytes.memStrdup)); + uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Strndup", pDetail->bytes.memStrndup)); + uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Free", pDetail->bytes.memFree)); + uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Trim", pDetail->bytes.memTrim)); + break; + case E_MP_STRATEGY_CHUNK: + uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("chunkMalloc", pDetail->bytes.chunkMalloc)); + uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("chunkRecycle", pDetail->bytes.chunkRecycle)); + uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("chunkReUse", pDetail->bytes.chunkReUse)); + uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("chunkFree", pDetail->bytes.chunkFree)); + break; + default: + break; + } } -void taosMemPoolCleanUp(mpool_h handle) { - pool_t *pool_p = (pool_t *)handle; +int32_t mpAddToRemainAllocHash(SHashObj* pHash, SMPFileLine* pFileLine) { + int32_t code = TSDB_CODE_SUCCESS; + SMPAllocStat stat = {0}, *pStat = NULL; + + while (true) { + pStat = (SMPAllocStat*)taosHashGet(pHash, &pFileLine->fl, sizeof(pFileLine->fl)); + if (NULL == pStat) { + code = taosHashPut(pHash, &pFileLine->fl, sizeof(pFileLine->fl), &stat, sizeof(stat)); + if (TSDB_CODE_SUCCESS != code) { + if (TSDB_CODE_DUP_KEY == code) { + continue; + } + + uError("taosHashPut to remain alloc hash failed, error:%s", tstrerror(code)); + return code; + } - (void)taosThreadMutexDestroy(&pool_p->mutex); - if (pool_p->pool) taosMemoryFree(pool_p->pool); - if (pool_p->freeList) taosMemoryFree(pool_p->freeList); - (void)memset(pool_p, 0, sizeof(*pool_p)); - taosMemoryFree(pool_p); + continue; + } + + atomic_add_fetch_64(&pStat->allocBytes, pFileLine->size); + atomic_add_fetch_64(&pStat->allocTimes, 1); + break; + } + + return TSDB_CODE_SUCCESS; } + +void mpPrintPosRemainStat(SMPStatPos* pStat) { + int32_t code = TSDB_CODE_SUCCESS; + int32_t remainNum = taosHashGetSize(pStat->remainHash); + if (remainNum <= 0) { + uInfo("no alloc remaining memory"); + return; + } + + SHashObj* pAllocHash = taosHashInit(remainNum / 10, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); + if (NULL == pAllocHash) { + uError("taosHashInit pAllocHash failed, error:%s, remainNum:%d", tstrerror(terrno), remainNum); + return; + } + + SMPFileLine* pFileLine = NULL; + void* pIter = taosHashIterate(pStat->remainHash, NULL); + while (pIter) { + pFileLine = (SMPFileLine*)pIter; + + MP_ERR_JRET(mpAddToRemainAllocHash(pAllocHash, pFileLine)); + + pIter = taosHashIterate(pStat->remainHash, pIter); + } + + SMPAllocStat* pAlloc = NULL; + pIter = taosHashIterate(pAllocHash, NULL); + while (pIter) { + pAlloc = (SMPAllocStat*)pIter; + SMPFileLineId* pId = (SMPFileLineId*)taosHashGetKey(pIter, NULL); + SMPAllocStat* pAlloc = (SMPAllocStat*)taosHashGet(pStat->allocHash, pId, sizeof(*pId)); + char* pFileName = (char*)taosHashGet(pStat->fileHash, &pId->fileId, sizeof(pId->fileId)); + if (NULL == pAlloc || NULL == pFileName) { + uError("fail to get pId in allocHash or fileHash, pAlloc:%p, pFileName:%p", pAlloc, pFileName); + goto _return; + } + + uInfo("REMAINING: %" PRId64 " bytes alloced by %s:%d in %" PRId64 " times", pAlloc->allocBytes, pFileName, pId->line, pAlloc->allocTimes); + + pIter = taosHashIterate(pAllocHash, pIter); + } + +_return: + + taosHashCleanup(pAllocHash); +} + +void mpPrintPosAllocStat(SMPStatPos* pStat) { + +} + +void mpPrintPosFreeStat(SMPStatPos* pStat) { + +} + +void mpPrintPosStat(SMPCtrlInfo* pCtrl, SMPStatPos* pStat, char* detailName) { + if (!MP_GET_FLAG(pCtrl->funcFlags, MP_CTRL_FLAG_PRINT_STAT)) { + return; + } + + uInfo("MemPool [%s] Pos Stat:", detailName); + uInfo("error times: %" PRId64, pStat->logErrTimes); + + mpPrintPosRemainStat(pStat); + + mpPrintPosAllocStat(pStat); + + mpPrintPosFreeStat(pStat); +} + +void mpPrintNodeStat(SMPCtrlInfo* pCtrl, SHashObj* pHash, char* detailName) { + //TODO +} + +void mpPrintSessionStat(SMPCtrlInfo* pCtrl, SMPStatSession* pSessStat, char* detailName) { + if (!MP_GET_FLAG(pCtrl->funcFlags, MP_CTRL_FLAG_PRINT_STAT)) { + return; + } + + uInfo("MemPool [%s] session stat:", detailName); + uInfo("init session succeed num: %" PRId64, pSessStat->initSucc); + uInfo("init session failed num: %" PRId64, pSessStat->initFail); + uInfo("session destroyed num: %" PRId64, pSessStat->destroyNum); +} + + + +void mpLogDetailStat(SMPStatDetail* pDetail, EMPStatLogItem item, SMPStatInput* pInput) { + switch (item) { + case E_MP_STAT_LOG_MEM_MALLOC: { + if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_EXEC)) { + atomic_add_fetch_64(&pDetail->times.memMalloc.exec, 1); + atomic_add_fetch_64(&pDetail->bytes.memMalloc.exec, pInput->size); + } + if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_SUCC)) { + atomic_add_fetch_64(&pDetail->times.memMalloc.succ, 1); + atomic_add_fetch_64(&pDetail->bytes.memMalloc.succ, pInput->size); + } + if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_FAIL)) { + atomic_add_fetch_64(&pDetail->times.memMalloc.fail, 1); + atomic_add_fetch_64(&pDetail->bytes.memMalloc.fail, pInput->size); + } + break; + } + case E_MP_STAT_LOG_MEM_CALLOC:{ + if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_EXEC)) { + atomic_add_fetch_64(&pDetail->times.memCalloc.exec, 1); + atomic_add_fetch_64(&pDetail->bytes.memCalloc.exec, pInput->size); + } + if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_SUCC)) { + atomic_add_fetch_64(&pDetail->times.memCalloc.succ, 1); + atomic_add_fetch_64(&pDetail->bytes.memCalloc.succ, pInput->size); + } + if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_FAIL)) { + atomic_add_fetch_64(&pDetail->times.memCalloc.fail, 1); + atomic_add_fetch_64(&pDetail->bytes.memCalloc.fail, pInput->size); + } + break; + } + case E_MP_STAT_LOG_MEM_REALLOC:{ + if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_EXEC)) { + atomic_add_fetch_64(&pDetail->times.memRealloc.exec, 1); + atomic_add_fetch_64(&pDetail->bytes.memRealloc.exec, pInput->size); + atomic_add_fetch_64(&pDetail->bytes.memRealloc.origExec, pInput->origSize); + } + if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_SUCC)) { + atomic_add_fetch_64(&pDetail->times.memRealloc.succ, 1); + atomic_add_fetch_64(&pDetail->bytes.memRealloc.succ, pInput->size); + atomic_add_fetch_64(&pDetail->bytes.memRealloc.origSucc, pInput->origSize); + } + if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_FAIL)) { + atomic_add_fetch_64(&pDetail->times.memRealloc.fail, 1); + atomic_add_fetch_64(&pDetail->bytes.memRealloc.fail, pInput->size); + atomic_add_fetch_64(&pDetail->bytes.memRealloc.origFail, pInput->origSize); + } + break; + } + case E_MP_STAT_LOG_MEM_FREE:{ + if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_EXEC)) { + atomic_add_fetch_64(&pDetail->times.memFree.exec, 1); + atomic_add_fetch_64(&pDetail->bytes.memFree.exec, pInput->size); + } + if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_SUCC)) { + atomic_add_fetch_64(&pDetail->times.memFree.succ, 1); + atomic_add_fetch_64(&pDetail->bytes.memFree.succ, pInput->size); + } + if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_FAIL)) { + atomic_add_fetch_64(&pDetail->times.memFree.fail, 1); + atomic_add_fetch_64(&pDetail->bytes.memFree.fail, pInput->size); + } + break; + } + case E_MP_STAT_LOG_MEM_STRDUP: { + if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_EXEC)) { + atomic_add_fetch_64(&pDetail->times.memStrdup.exec, 1); + atomic_add_fetch_64(&pDetail->bytes.memStrdup.exec, pInput->size); + } + if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_SUCC)) { + atomic_add_fetch_64(&pDetail->times.memStrdup.succ, 1); + atomic_add_fetch_64(&pDetail->bytes.memStrdup.succ, pInput->size); + } + if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_FAIL)) { + atomic_add_fetch_64(&pDetail->times.memStrdup.fail, 1); + atomic_add_fetch_64(&pDetail->bytes.memStrdup.fail, pInput->size); + } + break; + } + case E_MP_STAT_LOG_MEM_STRNDUP: { + if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_EXEC)) { + atomic_add_fetch_64(&pDetail->times.memStrndup.exec, 1); + atomic_add_fetch_64(&pDetail->bytes.memStrndup.exec, pInput->size); + } + if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_SUCC)) { + atomic_add_fetch_64(&pDetail->times.memStrndup.succ, 1); + atomic_add_fetch_64(&pDetail->bytes.memStrndup.succ, pInput->size); + } + if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_FAIL)) { + atomic_add_fetch_64(&pDetail->times.memStrndup.fail, 1); + atomic_add_fetch_64(&pDetail->bytes.memStrndup.fail, pInput->size); + } + break; + } + case E_MP_STAT_LOG_MEM_TRIM: { + if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_EXEC)) { + atomic_add_fetch_64(&pDetail->times.memTrim.exec, 1); + } + if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_SUCC)) { + atomic_add_fetch_64(&pDetail->times.memTrim.succ, 1); + atomic_add_fetch_64(&pDetail->bytes.memTrim.succ, pInput->size); + } + if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_FAIL)) { + atomic_add_fetch_64(&pDetail->times.memTrim.fail, 1); + } + break; + } + case E_MP_STAT_LOG_CHUNK_MALLOC: + case E_MP_STAT_LOG_CHUNK_RECYCLE: + case E_MP_STAT_LOG_CHUNK_REUSE: + case E_MP_STAT_LOG_CHUNK_FREE: { + + } + default: + uError("Invalid stat item: %d", item); + break; + } +} + +int32_t mpGetAllocFreeStat(SHashObj* pHash, void* pKey, int32_t keyLen, void* pNew, int32_t newSize, void** ppRes) { + void* pStat = NULL; + int32_t code = TSDB_CODE_SUCCESS; + + while (true) { + pStat = taosHashGet(pHash, pKey, keyLen); + if (NULL != pStat) { + *ppRes = pStat; + break; + } + + code = taosHashPut(pHash, pKey, keyLen, pNew, newSize); + if (code) { + if (TSDB_CODE_DUP_KEY == code) { + continue; + } + + return code; + } + } + + return TSDB_CODE_SUCCESS; +} + +int32_t mpGetPosStatFileId(SMPStatPos* pStat, char* fileName, uint32_t* pId, bool sessionStat) { + uint32_t hashVal = MurmurHash3_32(fileName, strlen(fileName)); + int32_t code = taosHashPut(pStat->fileHash, &hashVal, sizeof(hashVal), fileName, strlen(fileName) + 1); + if (code && TSDB_CODE_DUP_KEY != code) { + return code; + } + + *pId = hashVal; + + return TSDB_CODE_SUCCESS; +} + +void mpLogPosStat(SMPStatPos* pStat, EMPStatLogItem item, SMPStatInput* pInput, bool sessionStat) { + if (!MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_SUCC)) { + return; + } + + int32_t code = TSDB_CODE_SUCCESS; + + switch (item) { + case E_MP_STAT_LOG_MEM_MALLOC: + case E_MP_STAT_LOG_MEM_CALLOC: + case E_MP_STAT_LOG_MEM_STRDUP: + case E_MP_STAT_LOG_MEM_STRNDUP: { + SMPAllocStat allocStat = {0}, *pAlloc = NULL; + SMPFileLine fileLine = {.fl.line = pInput->line, .size = pInput->size}; + code = mpGetPosStatFileId(pStat, pInput->file, &fileLine.fl.fileId, sessionStat); + if (TSDB_CODE_SUCCESS != code) { + uError("add pMem:%p %s:%d to fileHash failed, error:%s, sessionStat:%d", + pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat); + MP_ERR_JRET(code); + } + code = taosHashPut(pStat->remainHash, &pInput->pMem, POINTER_BYTES, &fileLine, sizeof(fileLine)); + if (TSDB_CODE_SUCCESS != code) { + if (TSDB_CODE_DUP_KEY == code) { + SMPFileLine* pFileLine = (SMPFileLine*)taosHashAcquire(pStat->remainHash, &pInput->pMem, POINTER_BYTES); + if (pFileLine) { + char* pFileName = (char*)taosHashGet(pStat->fileHash, &pFileLine->fl.fileId, sizeof(pFileLine->fl.fileId)); + if (NULL == pFileName) { + uError("fail to get fileId %u in fileHash", pFileLine->fl.fileId); + } else { + uError("add pMem:%p %s:%d to remainHash failed, error:%s, sessionStat:%d, origAllocAt %s:%d", + pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat, pFileName, pFileLine->fl.line); + MP_ERR_JRET(code); + } + } + } + + uError("add pMem:%p %s:%d to remainHash failed, error:%s, sessionStat:%d", + pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat); + + MP_ERR_JRET(code); + } + code = mpGetAllocFreeStat(pStat->allocHash, &fileLine.fl, sizeof(fileLine.fl), (void*)&allocStat, sizeof(allocStat), (void**)&pAlloc); + if (TSDB_CODE_SUCCESS != code) { + uError("add pMem:%p %s:%d to allocHash failed, error:%s, sessionStat:%d", + pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat); + MP_ERR_JRET(code); + } + + atomic_add_fetch_64(&pAlloc->allocTimes, 1); + atomic_add_fetch_64(&pAlloc->allocBytes, pInput->size); + break; + } + case E_MP_STAT_LOG_MEM_REALLOC: { + SMPAllocStat allocStat = {0}, *pAlloc = NULL; + SMPFreeStat freeStat = {0}, *pFree = NULL; + SMPFileLine fileLine = {.fl.line = pInput->line, .size = pInput->size}; + code = mpGetPosStatFileId(pStat, pInput->file, &fileLine.fl.fileId, sessionStat); + if (TSDB_CODE_SUCCESS != code) { + uError("realloc: add pMem:%p %s:%d to fileHash failed, error:%s, sessionStat:%d", + pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat); + MP_ERR_JRET(code); + } + + ASSERT((pInput->pOrigMem && pInput->origSize > 0) || (NULL == pInput->pOrigMem && pInput->origSize == 0)); + + if (pInput->pOrigMem && pInput->origSize > 0) { + code = taosHashRemove(pStat->remainHash, &pInput->pOrigMem, POINTER_BYTES); + if (TSDB_CODE_SUCCESS != code) { + uError("realloc: rm pOrigMem:%p %s:%d from remainHash failed, error:%s, sessionStat:%d", + pInput->pOrigMem, pInput->file, pInput->line, tstrerror(code), sessionStat); + MP_ERR_JRET(code); + } + code = mpGetAllocFreeStat(pStat->freeHash, &fileLine.fl, sizeof(fileLine.fl), (void*)&freeStat, sizeof(freeStat), (void**)&pFree); + if (TSDB_CODE_SUCCESS != code) { + uError("realloc: add pOrigMem:%p %s:%d to freeHash failed, error:%s, sessionStat:%d", + pInput->pOrigMem, pInput->file, pInput->line, tstrerror(code), sessionStat); + MP_ERR_JRET(code); + } + + atomic_add_fetch_64(&pFree->freeTimes, 1); + atomic_add_fetch_64(&pFree->freeBytes, pInput->origSize); + } + + code = taosHashPut(pStat->remainHash, &pInput->pMem, POINTER_BYTES, &fileLine, sizeof(fileLine)); + if (TSDB_CODE_SUCCESS != code) { + if (TSDB_CODE_DUP_KEY == code) { + SMPFileLine* pFileLine = (SMPFileLine*)taosHashAcquire(pStat->remainHash, &pInput->pMem, POINTER_BYTES); + if (pFileLine) { + char* pFileName = (char*)taosHashGet(pStat->fileHash, &pFileLine->fl.fileId, sizeof(pFileLine->fl.fileId)); + if (NULL == pFileName) { + uError("realloc: fail to get fileId %u in fileHash", pFileLine->fl.fileId); + } else { + uError("realloc: add pMem:%p %s:%d to remainHash failed, error:%s, sessionStat:%d, origAllocAt %s:%d", + pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat, pFileName, pFileLine->fl.line); + MP_ERR_JRET(code); + } + } + } + + uError("realloc: add pMem:%p %s:%d to remainHash failed, error:%s, sessionStat:%d", + pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat); + MP_ERR_JRET(code); + } + + code = mpGetAllocFreeStat(pStat->allocHash, &fileLine.fl, sizeof(fileLine.fl), (void*)&allocStat, sizeof(allocStat), (void**)&pAlloc); + if (TSDB_CODE_SUCCESS != code) { + uError("realloc: add pMem:%p %s:%d to allocHash failed, error:%s, sessionStat:%d", + pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat); + MP_ERR_JRET(code); + } + + atomic_add_fetch_64(&pAlloc->allocTimes, 1); + atomic_add_fetch_64(&pAlloc->allocBytes, pInput->size); + break; + } + case E_MP_STAT_LOG_MEM_FREE: { + SMPAllocStat allocStat = {0}, *pAlloc = NULL; + SMPFreeStat freeStat = {0}, *pFree = NULL; + SMPFileLineId fl = {.line = pInput->line}; + code = mpGetPosStatFileId(pStat, pInput->file, &fl.fileId, sessionStat); + if (TSDB_CODE_SUCCESS != code) { + uError("free: add pMem:%p %s:%d to fileHash failed, error:%s, sessionStat:%d", + pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat); + MP_ERR_JRET(code); + } + + code = taosHashRemove(pStat->remainHash, &pInput->pMem, POINTER_BYTES); + if (TSDB_CODE_SUCCESS != code) { + uDebug("free: rm pMem:%p %s:%d to remainHash failed, error:%s, sessionStat:%d", + pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat); + } + + code = mpGetAllocFreeStat(pStat->freeHash, &fl, sizeof(fl), (void*)&freeStat, sizeof(freeStat), (void**)&pFree); + if (TSDB_CODE_SUCCESS != code) { + uError("free: add pMem:%p %s:%d to freeHash failed, error:%s, sessionStat:%d", + pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat); + MP_ERR_JRET(code); + } + + atomic_add_fetch_64(&pFree->freeTimes, 1); + atomic_add_fetch_64(&pFree->freeBytes, pInput->size); + break; + } + case E_MP_STAT_LOG_MEM_TRIM: + break; + case E_MP_STAT_LOG_CHUNK_MALLOC: + case E_MP_STAT_LOG_CHUNK_RECYCLE: + case E_MP_STAT_LOG_CHUNK_REUSE: + case E_MP_STAT_LOG_CHUNK_FREE: { + break; + } + default: + uError("Invalid stat item: %d", item); + break; + } + + return; + +_return: + + atomic_add_fetch_64(&pStat->logErrTimes, 1); +} + + +void mpLogStat(SMemPool* pPool, SMPSession* pSession, EMPStatLogItem item, SMPStatInput* pInput) { + bool enablePool = false, randErr = false; + + switch (item) { + case E_MP_STAT_LOG_MEM_MALLOC: + case E_MP_STAT_LOG_MEM_CALLOC: + case E_MP_STAT_LOG_MEM_REALLOC: + case E_MP_STAT_LOG_MEM_FREE: + case E_MP_STAT_LOG_MEM_STRDUP: + case E_MP_STAT_LOG_MEM_STRNDUP: + case E_MP_STAT_LOG_MEM_TRIM: { + if (pSession && MP_GET_FLAG(pSession->ctrl.statFlags, MP_LOG_FLAG_ALL_MEM)) { + mpLogDetailStat(&pSession->stat.statDetail, item, pInput); + } + if (MP_GET_FLAG(gMPMgmt.ctrl.statFlags, MP_LOG_FLAG_ALL_MEM)) { + mpLogDetailStat(&pPool->stat.statDetail, item, pInput); + } + if (pSession && MP_GET_FLAG(pSession->ctrl.statFlags, MP_LOG_FLAG_ALL_POS)) { + taosSaveDisableMemPoolUsage(enablePool, randErr); + mpLogPosStat(&pSession->stat.posStat, item, pInput, true); + taosRestoreEnableMemPoolUsage(enablePool, randErr); + } + if (MP_GET_FLAG(gMPMgmt.ctrl.statFlags, MP_LOG_FLAG_ALL_POS)) { + taosSaveDisableMemPoolUsage(enablePool, randErr); + mpLogPosStat(&pPool->stat.posStat, item, pInput, false); + taosRestoreEnableMemPoolUsage(enablePool, randErr); + } + break; + } + case E_MP_STAT_LOG_CHUNK_MALLOC: + case E_MP_STAT_LOG_CHUNK_RECYCLE: + case E_MP_STAT_LOG_CHUNK_REUSE: + case E_MP_STAT_LOG_CHUNK_FREE: { + break; + } + default: + uError("Invalid stat item: %d", item); + break; + } +} + +void mpCheckStatDetail(void* poolHandle, void* session, char* detailName) { + if (0 == tsMemPoolFullFunc) { + return; + } + + SMemPool* pPool = (SMemPool*)poolHandle; + SMPSession* pSession = (SMPSession*)session; + SMPCtrlInfo* pCtrl = NULL; + SMPStatDetail* pDetail = NULL; + + if (NULL != session) { + pCtrl = &pSession->ctrl; + pDetail = &pSession->stat.statDetail; + if (MP_GET_FLAG(pCtrl->funcFlags, MP_CTRL_FLAG_CHECK_STAT)) { + int64_t allocSize = MEMPOOL_GET_ALLOC_SIZE(pDetail); + int64_t freeSize = MEMPOOL_GET_FREE_SIZE(pDetail); + + if (allocSize != freeSize) { + uError("%s Session in JOB:0x%" PRIx64 " stat check failed, allocSize:%" PRId64 ", freeSize:%" PRId64, + detailName, pSession->pJob->job.jobId, allocSize, freeSize); + + taosMemPoolPrintStat(NULL, pSession, detailName); + } else { + uDebug("%s Session in JOB:0x%" PRIx64 " stat check succeed, allocSize:%" PRId64 ", freeSize:%" PRId64, + detailName, pSession->pJob->job.jobId, allocSize, freeSize); + } + } + } + + if (NULL != poolHandle) { + pCtrl = &gMPMgmt.ctrl; + pDetail = &pPool->stat.statDetail; + int64_t sessInit = atomic_load_64(&pPool->stat.statSession.initFail) + atomic_load_64(&pPool->stat.statSession.initSucc); + if (MP_GET_FLAG(pCtrl->funcFlags, MP_CTRL_FLAG_CHECK_STAT) && sessInit == atomic_load_64(&pPool->stat.statSession.destroyNum)) { + int64_t allocSize = pDetail->bytes.memMalloc.succ + pDetail->bytes.memCalloc.succ + pDetail->bytes.memRealloc.succ + pDetail->bytes.memStrdup.succ + pDetail->bytes.memStrndup.succ; + int64_t freeSize = pDetail->bytes.memRealloc.origSucc + pDetail->bytes.memFree.succ; + + if (allocSize != freeSize) { + uError("%s MemPool %s stat check failed, allocSize:%" PRId64 ", freeSize:%" PRId64, detailName, pPool->name, allocSize, freeSize); + + taosMemPoolPrintStat(poolHandle, NULL, detailName); + } else { + uDebug("%s MemPool %s stat check succeed, allocSize:%" PRId64 ", freeSize:%" PRId64, detailName, pPool->name, allocSize, freeSize); + } + } + } +} + + +void mpCheckUpateCfg(void) { +/* + taosRLockLatch(&gMPMgmt.poolLock); + int32_t poolNum = taosArrayGetSize(gMPMgmt.poolList); + for (int32_t i = 0; i < poolNum; ++i) { + SMemPool* pPool = (SMemPool*)taosArrayGetP(gMPMgmt.poolList, i); + if (pPool->cfg.cb.cfgUpdateFp) { + (*pPool->cfg.cb.cfgUpdateFp)((void*)pPool, &pPool->cfg); + } + } + taosRUnLockLatch(&gMPMgmt.poolLock); +*/ +} + +void mpUpdateSystemAvailableMemorySize() { + static int64_t errorTimes = 0; + int64_t sysAvailSize = 0; + + int32_t code = taosGetSysAvailMemory(&sysAvailSize); + if (TSDB_CODE_SUCCESS != code) { + errorTimes++; + if (0 == errorTimes % 1000) { + uError("get system available memory size failed, error: %s, errorTimes:%" PRId64, tstrerror(code), errorTimes); + } + + return; + } + + atomic_store_64(&tsCurrentAvailMemorySize, sysAvailSize); + + uDebug("system available memory size: %" PRId64, sysAvailSize); +} + +void mpSchedTrim(int64_t* loopTimes) { + static int64_t trimTimes = 0; + + atomic_store_8(&tsNeedTrim, 1); + if (loopTimes) { + *loopTimes = 0; + } + + uDebug("%" PRId64 "th memory trim scheduled", ++trimTimes); +} + +void* mpMgmtThreadFunc(void* param) { + int32_t timeout = 0; + int64_t retireSize = 0, loopTimes = 0; + SMemPool* pPool = (SMemPool*)atomic_load_ptr(&gMemPoolHandle); + + while (0 == atomic_load_8(&gMPMgmt.modExit)) { + mpUpdateSystemAvailableMemorySize(); + + retireSize = pPool->cfg.reserveSize - atomic_load_64(&tsCurrentAvailMemorySize); + if (retireSize > 0) { + (*pPool->cfg.cb.failFp)(retireSize, TSDB_CODE_QRY_QUERY_MEM_EXHAUSTED); + + mpSchedTrim(&loopTimes); + } + + if (0 == (++loopTimes) % 500) { + mpSchedTrim(&loopTimes); + } + + taosMsleep(MP_DEFAULT_MEM_CHK_INTERVAL_MS); +/* + timeout = tsem2_timewait(&gMPMgmt.threadSem, gMPMgmt.waitMs); + if (0 != timeout) { + mpUpdateSystemAvailableMemorySize(); + continue; + } + + if (atomic_load_8(&gMPMgmt.msgQueue.midLevelRetire)) { + (*gMPMgmt.msgQueue.pPool->cfg.cb.retireJobsFp)(gMPMgmt.msgQueue.pPool, atomic_load_64(&gMPMgmt.msgQueue.pPool->cfg.retireUnitSize), false, TSDB_CODE_QRY_QUERY_MEM_EXHAUSTED); + } else if (atomic_load_8(&gMPMgmt.msgQueue.lowLevelRetire)) { + (*gMPMgmt.msgQueue.pPool->cfg.cb.retireJobsFp)(gMPMgmt.msgQueue.pPool, atomic_load_64(&gMPMgmt.msgQueue.pPool->cfg.retireUnitSize), true, TSDB_CODE_QRY_QUERY_MEM_EXHAUSTED); + } +*/ + } + + taosMemPoolModDestroy(); + + return NULL; +} + +int32_t mpCreateMgmtThread() { + int32_t code = TSDB_CODE_SUCCESS; + TdThreadAttr thAttr; + MP_ERR_RET(taosThreadAttrInit(&thAttr)); + MP_ERR_JRET(taosThreadAttrSetDetachState(&thAttr, PTHREAD_CREATE_JOINABLE)); + code = taosThreadCreate(&gMPMgmt.poolMgmtThread, &thAttr, mpMgmtThreadFunc, NULL); + if (code != 0) { + uError("failed to create memPool mgmt thread, error: 0x%x", code); + (void)taosThreadAttrDestroy(&thAttr); + MP_ERR_JRET(code); + } + +_return: + + MP_ERR_RET(taosThreadAttrDestroy(&thAttr)); + + return code; +} + +void mpModInit(void) { + int32_t code = TSDB_CODE_SUCCESS; + + gMPMgmt.modExit = 0; + + taosInitRWLatch(&gMPMgmt.poolLock); + + gMPMgmt.poolList = taosArrayInit(10, POINTER_BYTES); + if (NULL == gMPMgmt.poolList) { + MP_ERR_JRET(terrno); + } + + gMPMgmt.strategy = E_MP_STRATEGY_DIRECT; + + gMPMgmt.ctrl.statFlags = MP_STAT_FLAG_LOG_ALL & (~MP_LOG_FLAG_ALL_POS); + gMPMgmt.ctrl.funcFlags = MP_CTRL_FLAG_PRINT_STAT | MP_CTRL_FLAG_CHECK_STAT | MP_CTRL_FLAG_LOG_MAXSIZE; + + //gMPMgmt.code = tsem2_init(&gMPMgmt.threadSem, 0, 0); + //if (TSDB_CODE_SUCCESS != gMPMgmt.code) { + // uError("failed to init sem2, error: 0x%x", gMPMgmt.code); + // return; + //} + + gMPMgmt.waitMs = MP_DEFAULT_MEM_CHK_INTERVAL_MS; + +_return: + + gMPMgmt.code = code; +} + + +void mpFreePool(void* p) { + SMemPool* pPool = *(void**)p; + taosMemoryFree(pPool); +} + + +void taosMemPoolPrintStat(void* poolHandle, void* session, char* procName) { + SMemPool* pPool = (SMemPool*)poolHandle; + SMPSession* pSession = (SMPSession*)session; + char detailName[128]; + + if (NULL != pSession && MP_GET_FLAG(pSession->ctrl.funcFlags, MP_CTRL_FLAG_PRINT_STAT)) { + snprintf(detailName, sizeof(detailName) - 1, "%s - %s", procName, "Session"); + detailName[sizeof(detailName) - 1] = 0; + mpPrintStatDetail(&pSession->ctrl, &pSession->stat.statDetail, detailName, pSession->maxAllocMemSize); + + snprintf(detailName, sizeof(detailName) - 1, "%s - %s", procName, "SessionPos"); + detailName[sizeof(detailName) - 1] = 0; + mpPrintPosStat(&pSession->ctrl, &pSession->stat.posStat, detailName); + } + + if (NULL != pPool && MP_GET_FLAG(gMPMgmt.ctrl.funcFlags, MP_CTRL_FLAG_PRINT_STAT)) { + snprintf(detailName, sizeof(detailName) - 1, "%s - %s", procName, pPool->name); + detailName[sizeof(detailName) - 1] = 0; + mpPrintSessionStat(&gMPMgmt.ctrl, &pPool->stat.statSession, detailName); + mpPrintStatDetail(&gMPMgmt.ctrl, &pPool->stat.statDetail, detailName, pPool->maxAllocMemSize); + + //snprintf(detailName, sizeof(detailName) - 1, "%s - %s", procName, "MemPoolNode"); + //detailName[sizeof(detailName) - 1] = 0; + //mpPrintNodeStat(&gMPMgmt.ctrl, pPool->stat.nodeStat, detailName); + + snprintf(detailName, sizeof(detailName) - 1, "%s - %s", procName, "MemPoolPos"); + detailName[sizeof(detailName) - 1] = 0; + mpPrintPosStat(&gMPMgmt.ctrl, &pPool->stat.posStat, detailName); + } +} + + +int32_t taosMemPoolOpen(char* poolName, SMemPoolCfg* cfg, void** poolHandle) { + int32_t code = TSDB_CODE_SUCCESS; + SMemPool* pPool = NULL; + + //MP_ERR_JRET(taosThreadOnce(&gMPoolInit, mpModInit)); + mpModInit(); + + if (TSDB_CODE_SUCCESS != gMPMgmt.code) { + uError("init memory pool failed, code: 0x%x", gMPMgmt.code); + MP_ERR_JRET(gMPMgmt.code); + } + + pPool = (SMemPool*)taosMemoryCalloc(1, sizeof(SMemPool)); + if (NULL == pPool) { + uError("calloc memory pool failed, code: 0x%x", terrno); + MP_ERR_JRET(terrno); + } + + MP_ERR_JRET(mpInit(pPool, poolName, cfg)); + + taosWLockLatch(&gMPMgmt.poolLock); + + if (NULL == taosArrayPush(gMPMgmt.poolList, &pPool)) { + taosWUnLockLatch(&gMPMgmt.poolLock); + MP_ERR_JRET(terrno); + } + + pPool->slotId = taosArrayGetSize(gMPMgmt.poolList) - 1; + + taosWUnLockLatch(&gMPMgmt.poolLock); + + uInfo("mempool %s opened", poolName); + +_return: + + if (TSDB_CODE_SUCCESS != code) { + taosMemPoolClose(pPool); + pPool = NULL; + } + + *poolHandle = pPool; + + return code; +} + +void taosMemPoolCfgUpdate(void* poolHandle, SMemPoolCfg* pCfg) { + SMemPool* pPool = (SMemPool*)poolHandle; + + (void)mpUpdateCfg(pPool); +} + +void taosMemPoolDestroySession(void* poolHandle, void* session) { + SMemPool* pPool = (SMemPool*)poolHandle; + SMPSession* pSession = (SMPSession*)session; + if (NULL == poolHandle || NULL == pSession) { + uWarn("null pointer of poolHandle %p or session %p", poolHandle, session); + return; + } + + if (tsMemPoolFullFunc) { + (void)atomic_add_fetch_64(&pPool->stat.statSession.destroyNum, 1); + mpCheckStatDetail(pPool, pSession, "DestroySession"); + mpDestroyPosStat(&pSession->stat.posStat); + } + + taosMemFreeClear(pSession->sessionId); + + TAOS_MEMSET(pSession, 0, sizeof(*pSession)); + + mpPushIdleNode(pPool, &pPool->sessionCache, (SMPListNode*)pSession); +} + +int32_t taosMemPoolInitSession(void* poolHandle, void** ppSession, void* pJob, char* sessionId) { + int32_t code = TSDB_CODE_SUCCESS; + SMemPool* pPool = (SMemPool*)poolHandle; + SMPSession* pSession = NULL; + + MP_ERR_JRET(mpPopIdleNode(pPool, &pPool->sessionCache, (void**)&pSession)); + + pSession->sessionId = taosStrdup(sessionId); + if (NULL == pSession->sessionId) { + uError("strdup sessionId failed, error:%s", tstrerror(terrno)); + MP_ERR_JRET(terrno); + } + + TAOS_MEMCPY(&pSession->ctrl, &gMPMgmt.ctrl, sizeof(pSession->ctrl)); + + if (gMPFps[gMPMgmt.strategy].initSessionFp) { + MP_ERR_JRET((*gMPFps[gMPMgmt.strategy].initSessionFp)(pPool, pSession)); + } + + if (tsMemPoolFullFunc) { + MP_ERR_JRET(mpInitPosStat(&pSession->stat.posStat, true)); + } + + pSession->pJob = (SMPJob*)pJob; + +_return: + + if (TSDB_CODE_SUCCESS != code) { + taosMemPoolDestroySession(poolHandle, pSession); + pSession = NULL; + (void)atomic_add_fetch_64(&pPool->stat.statSession.initFail, 1); + } else { + (void)atomic_add_fetch_64(&pPool->stat.statSession.initSucc, 1); + } + + *ppSession = pSession; + + return code; +} + + +void *taosMemPoolMalloc(void* poolHandle, void* session, int64_t size, char* fileName, int32_t lineNo) { + if (0 == tsMemPoolFullFunc) { + return mpDirectAlloc(poolHandle, ((SMPSession*)session)->pJob, size); + } + + int32_t code = TSDB_CODE_SUCCESS; + SMPStatInput input = {.size = size, .file = fileName, .line = lineNo, .procFlags = MP_STAT_PROC_FLAG_EXEC, .pMem = NULL}; + + if (NULL == poolHandle || NULL == fileName || size < 0) { + uError("%s invalid input param, handle:%p, session:%p, fileName:%p, size:%" PRId64, __FUNCTION__, poolHandle, session, fileName, size); + MP_ERR_JRET(TSDB_CODE_INVALID_PARA); + } + + SMemPool* pPool = (SMemPool*)poolHandle; + SMPSession* pSession = (SMPSession*)session; + + code = mpMalloc(pPool, pSession, &input.size, 0, &input.pMem); + + MP_SET_FLAG(input.procFlags, (NULL != input.pMem ? MP_STAT_PROC_FLAG_RES_SUCC : MP_STAT_PROC_FLAG_RES_FAIL)); + mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_MALLOC, &input); + +_return: + + if (TSDB_CODE_SUCCESS != code) { + terrno = code; + } + + return input.pMem; +} + +void *taosMemPoolCalloc(void* poolHandle, void* session, int64_t num, int64_t size, char* fileName, int32_t lineNo) { + if (0 == tsMemPoolFullFunc) { + return mpDirectCalloc(poolHandle, ((SMPSession*)session)->pJob, num, size); + } + + int32_t code = TSDB_CODE_SUCCESS; + int64_t totalSize = num * size; + SMPStatInput input = {.size = totalSize, .file = fileName, .line = lineNo, .procFlags = MP_STAT_PROC_FLAG_EXEC, .pMem = NULL}; + + if (NULL == poolHandle || NULL == fileName || num < 0 || size < 0) { + uError("%s invalid input param, handle:%p, session:%p, fileName:%p, num:%" PRId64 ", size:%" PRId64, + __FUNCTION__, poolHandle, session, fileName, num, size); + MP_ERR_JRET(TSDB_CODE_INVALID_PARA); + } + + SMemPool* pPool = (SMemPool*)poolHandle; + SMPSession* pSession = (SMPSession*)session; + + code = mpCalloc(pPool, pSession, &input.size, &input.pMem); + + MP_SET_FLAG(input.procFlags, (NULL != input.pMem ? MP_STAT_PROC_FLAG_RES_SUCC : MP_STAT_PROC_FLAG_RES_FAIL)); + mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_CALLOC, &input); + +_return: + + if (TSDB_CODE_SUCCESS != code) { + terrno = code; + } + + return input.pMem; +} + +void *taosMemPoolRealloc(void* poolHandle, void* session, void *ptr, int64_t size, char* fileName, int32_t lineNo) { + if (0 == tsMemPoolFullFunc) { + return mpDirectRealloc(poolHandle, ((SMPSession*)session)->pJob, ptr, size); + } + + int32_t code = TSDB_CODE_SUCCESS; + SMPStatInput input = {.size = size, .file = fileName, .line = lineNo, .procFlags = MP_STAT_PROC_FLAG_EXEC, .origSize = 0, .pMem = ptr, .pOrigMem = ptr}; + + if (NULL == poolHandle || NULL == fileName || size < 0) { + uError("%s invalid input param, handle:%p, session:%p, fileName:%p, size:%" PRId64, + __FUNCTION__, poolHandle, session, fileName, size); + MP_ERR_JRET(TSDB_CODE_INVALID_PARA); + } + + SMemPool* pPool = (SMemPool*)poolHandle; + SMPSession* pSession = (SMPSession*)session; + + code = mpRealloc(pPool, pSession, &input.pMem, &input.size, &input.origSize); + + if (NULL != input.pMem) { + MP_SET_FLAG(input.procFlags, MP_STAT_PROC_FLAG_RES_SUCC); + mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_REALLOC, &input); + } else if (0 == size){ + input.pMem = input.pOrigMem; + input.pOrigMem = NULL; + input.size = input.origSize; + MP_SET_FLAG(input.procFlags, MP_STAT_PROC_FLAG_RES_SUCC); + mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_FREE, &input); + input.pMem = NULL; + } else { + MP_SET_FLAG(input.procFlags, MP_STAT_PROC_FLAG_RES_FAIL); + mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_REALLOC, &input); + + input.pMem = input.pOrigMem; + input.pOrigMem = NULL; + input.size = input.origSize; + input.procFlags = MP_STAT_PROC_FLAG_EXEC; + MP_SET_FLAG(input.procFlags, MP_STAT_PROC_FLAG_RES_SUCC); + mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_FREE, &input); + input.pMem = NULL; + } + +_return: + + if (TSDB_CODE_SUCCESS != code) { + terrno = code; + } + + return input.pMem; +} + +char *taosMemPoolStrdup(void* poolHandle, void* session, const char *ptr, char* fileName, int32_t lineNo) { + if (0 == tsMemPoolFullFunc) { + return mpDirectStrdup(poolHandle, ((SMPSession*)session)->pJob, ptr); + } + + int32_t code = TSDB_CODE_SUCCESS; + int64_t size = (ptr ? strlen(ptr) : 0) + 1; + SMPStatInput input = {.size = size, .file = fileName, .line = lineNo, .procFlags = MP_STAT_PROC_FLAG_EXEC, .pMem = NULL}; + + if (NULL == poolHandle || NULL == fileName || NULL == ptr) { + uError("%s invalid input param, handle:%p, session:%p, fileName:%p, ptr:%p", + __FUNCTION__, poolHandle, session, fileName, ptr); + MP_ERR_JRET(TSDB_CODE_INVALID_PARA); + } + + SMemPool* pPool = (SMemPool*)poolHandle; + SMPSession* pSession = (SMPSession*)session; + + code = mpMalloc(pPool, pSession, &input.size, 0, &input.pMem); + if (NULL != input.pMem) { + TAOS_STRCPY(input.pMem, ptr); + *((char*)input.pMem + size - 1) = 0; + } + + MP_SET_FLAG(input.procFlags, (NULL != input.pMem ? MP_STAT_PROC_FLAG_RES_SUCC : MP_STAT_PROC_FLAG_RES_FAIL)); + mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_STRDUP, &input); + +_return: + + if (TSDB_CODE_SUCCESS != code) { + terrno = code; + } + + return input.pMem; +} + +char *taosMemPoolStrndup(void* poolHandle, void* session, const char *ptr, int64_t size, char* fileName, int32_t lineNo) { + if (0 == tsMemPoolFullFunc) { + return mpDirectStrndup(poolHandle, ((SMPSession*)session)->pJob, ptr, size); + } + + int32_t code = TSDB_CODE_SUCCESS; + int64_t origSize = ptr ? strlen(ptr) : 0; + size = TMIN(size, origSize) + 1; + SMPStatInput input = {.size = size, .file = fileName, .line = lineNo, .procFlags = MP_STAT_PROC_FLAG_EXEC, .pMem = NULL}; + + if (NULL == poolHandle || NULL == fileName || NULL == ptr || size < 0) { + uError("%s invalid input param, handle:%p, session:%p, fileName:%p, ptr:%p, size:%" PRId64, + __FUNCTION__, poolHandle, session, fileName, ptr, size); + MP_ERR_JRET(TSDB_CODE_INVALID_PARA); + } + + SMemPool* pPool = (SMemPool*)poolHandle; + SMPSession* pSession = (SMPSession*)session; + + code = mpMalloc(pPool, pSession, &input.size, 0, &input.pMem); + if (NULL != input.pMem) { + TAOS_MEMCPY(input.pMem, ptr, size - 1); + *((char*)input.pMem + size - 1) = 0; + } + + MP_SET_FLAG(input.procFlags, (NULL != input.pMem ? MP_STAT_PROC_FLAG_RES_SUCC : MP_STAT_PROC_FLAG_RES_FAIL)); + mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_STRNDUP, &input); + +_return: + + if (TSDB_CODE_SUCCESS != code) { + terrno = code; + } + + return input.pMem; +} + + +void taosMemPoolFree(void* poolHandle, void* session, void *ptr, char* fileName, int32_t lineNo) { + if (0 == tsMemPoolFullFunc) { + mpDirectFree(poolHandle, ((SMPSession*)session)->pJob, ptr); + return; + } + + if (NULL == ptr) { + return; + } + + int32_t code = TSDB_CODE_SUCCESS; + if (NULL == poolHandle || NULL == fileName) { + uError("%s invalid input param, handle:%p, session:%p, fileName:%p", + __FUNCTION__, poolHandle, session, fileName); + } + + SMemPool* pPool = (SMemPool*)poolHandle; + SMPSession* pSession = (SMPSession*)session; + SMPStatInput input = {.file = fileName, .line = lineNo, .procFlags = MP_STAT_PROC_FLAG_EXEC, .pMem = ptr}; + + mpFree(pPool, pSession, ptr, &input.size); + + MP_SET_FLAG(input.procFlags, MP_STAT_PROC_FLAG_RES_SUCC); + mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_FREE, &input); +} + +int64_t taosMemPoolGetMemorySize(void* poolHandle, void* session, void *ptr, char* fileName, int32_t lineNo) { + if (0 == tsMemPoolFullFunc) { + return taosMemSize(ptr); + } + + int64_t code = 0; + if (NULL == poolHandle || NULL == fileName) { + uError("%s invalid input param, handle:%p, session:%p, fileName:%p", + __FUNCTION__, poolHandle, session, fileName); + MP_ERR_RET(TSDB_CODE_INVALID_PARA); + } + + if (NULL == ptr) { + return 0; + } + + SMemPool* pPool = (SMemPool*)poolHandle; + SMPSession* pSession = (SMPSession*)session; + + return mpGetMemorySizeImpl(pPool, pSession, ptr); +} + +void* taosMemPoolMallocAlign(void* poolHandle, void* session, uint32_t alignment, int64_t size, char* fileName, int32_t lineNo) { + if (0 == tsMemPoolFullFunc) { + return mpDirectAlignAlloc(poolHandle, ((SMPSession*)session)->pJob, alignment, size); + } + + int32_t code = TSDB_CODE_SUCCESS; + SMPStatInput input = {.size = size, .file = fileName, .line = lineNo, .procFlags = MP_STAT_PROC_FLAG_EXEC, .pMem = NULL}; + + if (NULL == poolHandle || NULL == fileName || size < 0 || alignment < POINTER_BYTES || alignment % POINTER_BYTES) { + uError("%s invalid input param, handle:%p, session:%p, fileName:%p, alignment:%u, size:%" PRId64, + __FUNCTION__, poolHandle, session, fileName, alignment, size); + MP_ERR_JRET(TSDB_CODE_INVALID_PARA); + } + + SMemPool* pPool = (SMemPool*)poolHandle; + SMPSession* pSession = (SMPSession*)session; + + code = mpMalloc(pPool, pSession, &input.size, alignment, &input.pMem); + + MP_SET_FLAG(input.procFlags, (NULL != input.pMem ? MP_STAT_PROC_FLAG_RES_SUCC : MP_STAT_PROC_FLAG_RES_FAIL)); + mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_MALLOC, &input); + +_return: + + if (TSDB_CODE_SUCCESS != code) { + terrno = code; + } + + return input.pMem; +} + +void taosMemPoolClose(void* poolHandle) { + if (NULL == poolHandle) { + return; + } + + SMemPool* pPool = (SMemPool*)poolHandle; + + if (tsMemPoolFullFunc) { + mpCheckStatDetail(pPool, NULL, "PoolClose"); + mpDestroyPosStat(&pPool->stat.posStat); + } + + taosMemoryFree(pPool->name); + mpDestroyCacheGroup(&pPool->sessionCache); + + atomic_store_8(&gMPMgmt.modExit, 1); + + (void)taosThreadJoin(gMPMgmt.poolMgmtThread, NULL); +} + + +void taosMemPoolModDestroy(void) { + gMemPoolHandle = NULL; + + taosArrayDestroyEx(gMPMgmt.poolList, mpFreePool); + gMPMgmt.poolList = NULL; +} + + +int32_t taosMemPoolTrim(void* poolHandle, void* session, int32_t size, char* fileName, int32_t lineNo, bool* trimed) { + if (0 == tsMemPoolFullFunc) { + return taosMemTrim(size, trimed); + } + + int32_t code = TSDB_CODE_SUCCESS; + + if (NULL == poolHandle || NULL == fileName || size < 0) { + uError("%s invalid input param, handle:%p, session:%p, fileName:%p, size:%d", + __FUNCTION__, poolHandle, session, fileName, size); + MP_ERR_RET(TSDB_CODE_INVALID_PARA); + } + + SMemPool* pPool = (SMemPool*)poolHandle; + SMPSession* pSession = (SMPSession*)session; + SMPStatInput input = {.size = 0, .file = fileName, .line = lineNo, .procFlags = MP_STAT_PROC_FLAG_EXEC}; + + code = mpTrim(pPool, pSession, size, trimed); + + input.size = (trimed) ? (*trimed) : 0; + + MP_SET_FLAG(input.procFlags, ((0 == code) ? MP_STAT_PROC_FLAG_RES_SUCC : MP_STAT_PROC_FLAG_RES_FAIL)); + mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_TRIM, &input); + + return code; +} + +int32_t taosMemPoolCallocJob(uint64_t jobId, uint64_t cId, void** ppJob) { + int32_t code = TSDB_CODE_SUCCESS; + *ppJob = taosMemoryCalloc(1, sizeof(SMPJob)); + if (NULL == *ppJob) { + uError("calloc mp job failed, code: 0x%x", terrno); + MP_ERR_RET(terrno); + } + + SMPJob* pJob = (SMPJob*)*ppJob; + pJob->job.jobId = jobId; + pJob->job.clientId = cId; + + return code; +} + +int32_t taosMemPoolTryLockPool(void* poolHandle, bool readLock) { + if (NULL == poolHandle) { + return TSDB_CODE_INVALID_PARA; + } + + int32_t code = 0; + SMemPool* pPool = (SMemPool*)poolHandle; + if (readLock) { + MP_TRY_LOCK(MP_READ, &pPool->cfgLock, code); + } else { + MP_TRY_LOCK(MP_WRITE, &pPool->cfgLock, code); + } + + return code; +} + +void taosMemPoolUnLockPool(void* poolHandle, bool readLock) { + if (NULL == poolHandle) { + return; + } + + SMemPool* pPool = (SMemPool*)poolHandle; + if (readLock) { + MP_UNLOCK(MP_READ, &pPool->cfgLock); + } else { + MP_UNLOCK(MP_WRITE, &pPool->cfgLock); + } +} + +void taosMemPoolGetUsedSizeBegin(void* poolHandle, int64_t* usedSize, bool* needEnd) { + if (NULL == poolHandle) { + *usedSize = 0; + *needEnd = false; + return; + } + + SMemPool* pPool = (SMemPool*)poolHandle; + + *needEnd = true; + *usedSize = atomic_load_64(&pPool->allocMemSize); +} + +void taosMemPoolGetUsedSizeEnd(void* poolHandle) { + SMemPool* pPool = (SMemPool*)poolHandle; + if (NULL == pPool) { + return; + } + + MP_UNLOCK(MP_WRITE, &pPool->cfgLock); +} + +int32_t taosMemPoolGetSessionStat(void* session, SMPStatDetail** ppStat, int64_t* allocSize, int64_t* maxAllocSize) { + int32_t code = TSDB_CODE_SUCCESS; + if (NULL == session || (NULL == ppStat && NULL == allocSize && NULL == maxAllocSize)) { + uError("%s invalid input param, session:%p, ppStat:%p, allocSize:%p, maxAllocSize:%p", __FUNCTION__, session, ppStat, allocSize, maxAllocSize); + MP_ERR_RET(TSDB_CODE_INVALID_PARA); + } + + SMPSession* pSession = (SMPSession*)session; + + if (ppStat) { + *ppStat = &pSession->stat.statDetail; + } + if (allocSize) { + *allocSize = atomic_load_64(&pSession->allocMemSize); + } + if (maxAllocSize) { + *maxAllocSize = atomic_load_64(&pSession->maxAllocMemSize); + } + + return code; +} + +void taosMemPoolSchedTrim(void) { + mpSchedTrim(NULL); +} + +int32_t taosMemoryPoolInit(mpReserveFailFp failFp, mpReserveReachFp reachFp) { + int32_t code = TSDB_CODE_SUCCESS; + +#ifdef LINUX + if (!tsQueryUseMemoryPool) { +#endif + uInfo("memory pool disabled cause of configured disabled"); + return code; +#ifdef LINUX + } +#endif + + code = taosGetTotalMemory(&tsTotalMemoryKB); + if (TSDB_CODE_SUCCESS != code) { + uInfo("fail to system total memory, error: %s", tstrerror(code)); + return code; + } + + if (tsTotalMemoryKB <= 0) { + uInfo("memory pool disabled since no enough system total memory, size: %" PRId64 "KB", tsTotalMemoryKB); + return code; + } + + uInfo("total memory size: %" PRId64 "KB", tsTotalMemoryKB); + + if (0 == tsMinReservedMemorySize) { + tsMinReservedMemorySize = TMAX(MIN_RESERVE_MEM_SIZE, tsTotalMemoryKB / 1024 * MP_DEFAULT_RESERVE_MEM_PERCENT / 100); + } + + SMemPoolCfg cfg = {0}; + int64_t sysAvailSize = 0; + + code = taosGetSysAvailMemory(&sysAvailSize); + if (code || sysAvailSize < MP_MIN_MEM_POOL_SIZE) { + uInfo("memory pool disabled since no enough system available memory, size: %" PRId64, sysAvailSize); + code = TSDB_CODE_SUCCESS; + return code; + } + + cfg.reserveSize = tsMinReservedMemorySize * 1048576UL; + + int64_t freeSizeAfterRes = sysAvailSize - tsMinReservedMemorySize * 1048576UL; + if (freeSizeAfterRes < MP_MIN_FREE_SIZE_AFTER_RESERVE) { + uInfo("memory pool disabled since no enough system available memory after reservied, size: %" PRId64, freeSizeAfterRes); + return code; + } + + atomic_store_64(&tsCurrentAvailMemorySize, sysAvailSize); + + cfg.evicPolicy = E_EVICT_AUTO; //TODO + cfg.chunkSize = 1048576; + cfg.jobQuota = &tsSingleQueryMaxMemorySize; + cfg.cb.failFp = failFp; + cfg.cb.reachFp = reachFp; + + code = taosMemPoolOpen("taosd", &cfg, &gMemPoolHandle); + if (TSDB_CODE_SUCCESS != code) { + return code; + } + + code = mpCreateMgmtThread(); + if (TSDB_CODE_SUCCESS != code) { + return code; + } + + uInfo("memory pool initialized, reservedSize:%dMB, freeAfterReserved:%" PRId64 "MB, jobQuota:%dMB", tsMinReservedMemorySize, freeSizeAfterRes/1048576UL, tsSingleQueryMaxMemorySize); + + return code; +} + + +void taosAutoMemoryFree(void *ptr) { + if (NULL != gMemPoolHandle && threadPoolEnabled && threadPoolSession) { + taosMemPoolFree(gMemPoolHandle, threadPoolSession, ptr, __FILE__, __LINE__); + } else { + taosMemFree(ptr); + } +} + + diff --git a/source/util/src/tpagedbuf.c b/source/util/src/tpagedbuf.c index fb8e597163..003150bde1 100644 --- a/source/util/src/tpagedbuf.c +++ b/source/util/src/tpagedbuf.c @@ -347,11 +347,13 @@ static SPageInfo* getPageInfoFromPayload(void* page) { return ppi; } -int32_t createDiskbasedBuf(SDiskbasedBuf** pBuf, int32_t pagesize, int32_t inMemBufSize, const char* id, +int32_t createDiskbasedBuf(SDiskbasedBuf** pBuf, int32_t pagesize, int64_t inMemBufSize, const char* id, const char* dir) { + int32_t code = 0; *pBuf = NULL; SDiskbasedBuf* pPBuf = taosMemoryCalloc(1, sizeof(SDiskbasedBuf)); if (pPBuf == NULL) { + code = terrno; goto _error; } @@ -362,12 +364,14 @@ int32_t createDiskbasedBuf(SDiskbasedBuf** pBuf, int32_t pagesize, int32_t inMem pPBuf->pFile = NULL; pPBuf->id = taosStrdup(id); if (id != NULL && pPBuf->id == NULL) { + code = terrno; goto _error; } pPBuf->fileSize = 0; pPBuf->pFree = taosArrayInit(4, sizeof(SFreeListItem)); pPBuf->freePgList = tdListNew(POINTER_BYTES); if (pPBuf->pFree == NULL || pPBuf->freePgList == NULL) { + code = terrno; goto _error; } @@ -379,6 +383,7 @@ int32_t createDiskbasedBuf(SDiskbasedBuf** pBuf, int32_t pagesize, int32_t inMem pPBuf->inMemPages = inMemBufSize / pagesize; // maximum allowed pages, it is a soft limit. pPBuf->lruList = tdListNew(POINTER_BYTES); if (pPBuf->lruList == NULL) { + code = terrno; goto _error; } @@ -386,17 +391,20 @@ int32_t createDiskbasedBuf(SDiskbasedBuf** pBuf, int32_t pagesize, int32_t inMem _hash_fn_t fn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT); pPBuf->pIdList = taosArrayInit(4, POINTER_BYTES); if (pPBuf->pIdList == NULL) { + code = terrno; goto _error; } pPBuf->all = tSimpleHashInit(64, fn); if (pPBuf->all == NULL) { + code = terrno; goto _error; } pPBuf->prefix = (char*)dir; pPBuf->emptyDummyIdList = taosArrayInit(1, sizeof(int32_t)); if (pPBuf->emptyDummyIdList == NULL) { + code = terrno; goto _error; } @@ -409,7 +417,7 @@ int32_t createDiskbasedBuf(SDiskbasedBuf** pBuf, int32_t pagesize, int32_t inMem _error: destroyDiskbasedBuf(pPBuf); *pBuf = NULL; - return TSDB_CODE_OUT_OF_MEMORY; + return code; } static char* doExtractPage(SDiskbasedBuf* pBuf) { diff --git a/source/util/src/ttimer.c b/source/util/src/ttimer.c index b11f65da8f..e8ed86b4bf 100644 --- a/source/util/src/ttimer.c +++ b/source/util/src/ttimer.c @@ -472,6 +472,20 @@ bool taosTmrStopA(tmr_h* timerId) { return ret; } +bool taosTmrIsStopped(tmr_h* timerId) { + uintptr_t id = (uintptr_t)*timerId; + + tmr_obj_t* timer = findTimer(id); + if (timer == NULL) { + tmrDebug("timer[id=%" PRIuPTR "] does not exist", id); + return true; + } + + uint8_t state = atomic_load_8(&timer->state); + + return (state == TIMER_STATE_CANCELED) || (state == TIMER_STATE_STOPPED); +} + bool taosTmrReset(TAOS_TMR_CALLBACK fp, int32_t mseconds, void* param, void* handle, tmr_h* pTmrId) { tmr_ctrl_t* ctrl = (tmr_ctrl_t*)handle; if (ctrl == NULL || ctrl->label[0] == 0) { diff --git a/source/util/src/tutil.c b/source/util/src/tutil.c index bf1f150262..cdcef4b807 100644 --- a/source/util/src/tutil.c +++ b/source/util/src/tutil.c @@ -585,4 +585,4 @@ bool taosIsSpecialChar(char c) { default: return false; } -} \ No newline at end of file +} diff --git a/source/util/test/CMakeLists.txt b/source/util/test/CMakeLists.txt index 55da8c0929..655557b180 100644 --- a/source/util/test/CMakeLists.txt +++ b/source/util/test/CMakeLists.txt @@ -159,4 +159,13 @@ if(${TD_LINUX}) add_custom_command(TARGET terrorTest POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ERR_TBL_FILE} $ ) + + # memPoolTest + add_executable(memPoolTest "memPoolTest.cpp") + target_link_libraries(memPoolTest os util common gtest_main) + add_test( + NAME memPoolTest + COMMAND memPoolTest + ) + endif() diff --git a/source/util/test/arrayTest.cpp b/source/util/test/arrayTest.cpp index 307719b984..95468eecaa 100644 --- a/source/util/test/arrayTest.cpp +++ b/source/util/test/arrayTest.cpp @@ -182,8 +182,8 @@ TEST(arrayTest, check_duplicate_needfree) { ASSERT_STREQ(v, value); } - taosArrayClearP(pa, taosMemoryFree); - taosArrayDestroyP(pa, taosMemoryFree); + taosArrayClearP(pa, NULL); + taosArrayDestroyP(pa, NULL); } // over all diff --git a/source/util/test/memPoolTest.cpp b/source/util/test/memPoolTest.cpp new file mode 100644 index 0000000000..d0c08b1318 --- /dev/null +++ b/source/util/test/memPoolTest.cpp @@ -0,0 +1,2075 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wwrite-strings" +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wformat" +#include + + +#ifdef WINDOWS +#define TD_USE_WINSOCK +#endif + +#include "os.h" + +#include "thash.h" +#include "theap.h" +#include "taos.h" +#include "tdef.h" +#include "tvariant.h" +#include "stub.h" +#include "../inc/tmempoolInt.h" +#include "tglobal.h" + +namespace { + +#define MPT_PRINTF(param, ...) (void)printf("[%" PRId64 ",%" PRId64 "] " param, mptCaseLoop, mptExecLoop, __VA_ARGS__) +#define MPT_EPRINTF(param, ...) (void)printf(param, __VA_ARGS__) + +#define MPT_MAX_MEM_ACT_TIMES 300 +#define MPT_MAX_SESSION_NUM 100 +#define MPT_MAX_JOB_NUM 100 +#define MPT_MAX_THREAD_NUM 100 +#define MPT_MAX_JOB_LOOP_TIMES 100 + +#define MPT_DEFAULT_RESERVE_MEM_PERCENT 20 +#define MPT_MIN_RESERVE_MEM_SIZE (512 * 1048576UL) +#define MPT_MIN_MEM_POOL_SIZE (1048576UL) +#define MPT_MAX_RETIRE_JOB_NUM 10000 +#define MPT_DEFAULT_TASK_RUN_TIMES 10 +#define MPT_NON_POOL_ALLOC_UNIT (1048576UL) +#define MPT_NON_POOL_KEEP_ALLOC_UNIT (10485760UL * 8) +#define MPT_MAX_NON_POOL_ALLOC_TIMES 30000 + +enum { + MPT_READ = 1, + MPT_WRITE, +}; + +#define TD_RWLATCH_WRITE_FLAG_COPY 0x40000000 + + + +threadlocal void* mptThreadPoolHandle = NULL; +threadlocal void* mptThreadPoolSession = NULL; +threadlocal int32_t mptJobNum = 0; +threadlocal int32_t mptExecNum = 0; +threadlocal int32_t mptExecLoop = 0; +threadlocal int64_t mptCaseLoop = 0; + + + + + +#define MPT_SET_TEID(id, tId, eId) \ + do { \ + *(uint64_t *)(id) = (tId); \ + *(uint32_t *)((char *)(id) + sizeof(tId)) = (eId); \ + } while (0) + +#define MPT_SET_QCID(id, qId, cId) \ + do { \ + *(uint64_t *)(id) = (qId); \ + *(uint64_t *)((char *)(id) + sizeof(qId)) = (cId); \ + } while (0) + + +#define mptEnableMemoryPoolUsage(_pool, _session) do { mptThreadPoolHandle = _pool; mptThreadPoolSession = _session; } while (0) +#define mptDisableMemoryPoolUsage() (mptThreadPoolHandle = NULL, mptThreadPoolSession = NULL) +#define mptSaveDisableMemoryPoolUsage(_handle) do { (_handle) = mptThreadPoolHandle; mptThreadPoolHandle = NULL; } while (0) +#define mptRestoreEnableMemoryPoolUsage(_handle) (mptThreadPoolHandle = (_handle)) + +#define mptMemoryMalloc(_size) ((NULL != mptThreadPoolHandle) ? (taosMemPoolMalloc(mptThreadPoolHandle, mptThreadPoolSession, _size, __FILE__, __LINE__)) : (taosMemMalloc(_size))) +#define mptMemoryCalloc(_num, _size) ((NULL != mptThreadPoolHandle) ? (taosMemPoolCalloc(mptThreadPoolHandle, mptThreadPoolSession, _num, _size, __FILE__, __LINE__)) : (taosMemCalloc(_num, _size))) +#define mptMemoryRealloc(_ptr, _size) ((NULL != mptThreadPoolHandle) ? (taosMemPoolRealloc(mptThreadPoolHandle, mptThreadPoolSession, _ptr, _size, __FILE__, __LINE__)) : (taosMemRealloc(_ptr, _size))) +#define mptStrdup(_ptr) ((NULL != mptThreadPoolHandle) ? (taosMemPoolStrdup(mptThreadPoolHandle, mptThreadPoolSession, _ptr, __FILE__, __LINE__)) : (taosStrdupi(_ptr))) +#define mptStrndup(_ptr, _size) ((NULL != mptThreadPoolHandle) ? (taosMemPoolStrndup(mptThreadPoolHandle, mptThreadPoolSession, _ptr, _size, (char*)__FILE__, __LINE__)) : (taosStrndupi(_ptr, _size))) +#define mptMemoryFree(_ptr) ((NULL != mptThreadPoolHandle) ? (taosMemPoolFree(mptThreadPoolHandle, mptThreadPoolSession, _ptr, __FILE__, __LINE__)) : (taosMemFree(_ptr))) +#define mptMemorySize(_ptr) ((NULL != mptThreadPoolHandle) ? (taosMemPoolGetMemorySize(mptThreadPoolHandle, mptThreadPoolSession, _ptr, __FILE__, __LINE__)) : (taosMemSize(_ptr))) +#define mptMemoryTrim(_size, _trimed) ((NULL != mptThreadPoolHandle) ? (taosMemPoolTrim(mptThreadPoolHandle, mptThreadPoolSession, _size, __FILE__, __LINE__, _trimed)) : (taosMemTrim(_size, _trimed))) +#define mptMemoryMallocAlign(_alignment, _size) ((NULL != mptThreadPoolHandle) ? (taosMemPoolMallocAlign(mptThreadPoolHandle, mptThreadPoolSession, _alignment, _size, __FILE__, __LINE__)) : (taosMemMallocAlign(_alignment, _size))) + +enum { + MPT_SMALL_MSIZE = 0, + MPT_BIG_MSIZE, +}; + +typedef struct { + int32_t jobNum; + int32_t sessionNum; + bool memSize[2]; + bool jobQuotaRetire; + bool poolRetire; +} SMPTCaseParam; + +typedef struct SMPTJobInfo { + int8_t retired; + int32_t errCode; + SMemPoolJob* memInfo; + void* pCtx; + + SRWLatch lock; + int8_t destroyed; + SHashObj* pSessions; + int8_t initDone; +} SMPTJobInfo; + + +typedef struct { + int32_t taskActTimes; + int32_t caseLoopTimes; + int32_t jobExecTimes; + int32_t jobNum; + int32_t jobTaskNum; + int64_t maxSingleAllocSize; + bool printExecDetail; + bool printInputRow; + + bool lockDbg; +} SMPTestCtrl; + +typedef struct { + void* p; + int64_t size; +} SMPTestMemInfo; + +typedef struct { + uint64_t taskId; + SRWLatch taskExecLock; + bool destoryed; + + int64_t poolMaxUsedSize; + int64_t poolTotalUsedSize; + + SMPStatDetail stat; + + int32_t memIdx; + SMPTestMemInfo* pMemList; + + bool taskFreed; + int32_t lastAct; +} SMPTestTaskCtx; + +typedef struct { + SRWLatch jobExecLock; + + int32_t jobIdx; + int64_t jobId; + int32_t initTimes; + void* pSessions[MPT_MAX_SESSION_NUM]; + int32_t taskNum; + SMPTestTaskCtx taskCtxs[MPT_MAX_SESSION_NUM]; + + int32_t taskRunningNum; + SMPTJobInfo* pJob; + int32_t jobStatus; +} SMPTestJobCtx; + +typedef struct { + int32_t jobQuota; + bool enableMemPool; + bool reserveMode; + int64_t upperLimitSize; + int32_t reserveSize; //MB + int32_t threadNum; + int32_t randTask; +} SMPTestParam; + +typedef struct { + int64_t initNum; + int64_t retireNum; + int64_t destoryNum; +} SMPTestJobStat; + +typedef struct { + int32_t idx; + TdThread threadFp; + bool allJobs; + bool autoJob; +} SMPTestThread; + +typedef struct SMPTestCtx { + int64_t qId; + int64_t tId; + SHashObj* pJobs; + BoundedQueue* pJobQueue; + SMPTestThread threadCtxs[MPT_MAX_THREAD_NUM]; + TdThread dropThreadFp; + TdThread nPoolThreadFp; + int32_t jobNum; + int64_t totalTaskNum; + SMPTestJobCtx* jobCtxs; + SMPTestParam param; + SMPTestJobStat runStat; + + SRWLatch stringLock; + char* pSrcString; + + bool initDone; + int8_t testDone; + int64_t jobLoop; + + int32_t npIdx; + SMPTestMemInfo* npMemList; +} SMPTestCtx; + +SMPTestCtx mptCtx = {0}; +SMPTestCtrl mptCtrl = {0}; + +static int32_t MPT_TRY_LOCK(int32_t type, SRWLatch *_lock) { + int32_t code = -1; + + if (MPT_READ == (type)) { + if (mptCtrl.lockDbg) { + if (atomic_load_32((_lock)) < 0) { + uError("invalid lock value before try read lock"); + return -1; + } + uDebug("MPT TRY RLOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); + } + code = taosRTryLockLatch(_lock); + if (mptCtrl.lockDbg) { + uDebug("MPT TRY RLOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); + if (atomic_load_32((_lock)) <= 0) { + uError("invalid lock value after try read lock"); + return -1; + } + } + } else { + if (mptCtrl.lockDbg) { + if (atomic_load_32((_lock)) < 0) { + uError("invalid lock value before try write lock"); + return -1; + } + uDebug("MPT TRY WLOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); + } + code = taosWTryLockLatch(_lock); + if (mptCtrl.lockDbg) { + uDebug("MPT TRY WLOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); + if (atomic_load_32((_lock)) != TD_RWLATCH_WRITE_FLAG_COPY) { + uError("invalid lock value after try write lock"); + return -1; + } + } + } + + return code; +} + +#define MPT_LOCK(type, _lock) \ + do { \ + if (MPT_READ == (type)) { \ + if (mptCtrl.lockDbg) { \ + if (atomic_load_32((_lock)) < 0) { \ + uError("invalid lock value before read lock"); \ + break; \ + } \ + uDebug("MPT RLOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + } \ + taosRLockLatch(_lock); \ + if (mptCtrl.lockDbg) { \ + uDebug("MPT RLOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + if (atomic_load_32((_lock)) <= 0) { \ + uError("invalid lock value after read lock"); \ + break; \ + } \ + } \ + } else { \ + if (mptCtrl.lockDbg) { \ + if (atomic_load_32((_lock)) < 0) { \ + uError("invalid lock value before write lock"); \ + break; \ + } \ + uDebug("MPT WLOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + } \ + taosWLockLatch(_lock); \ + if (mptCtrl.lockDbg) { \ + uDebug("MPT WLOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + if (atomic_load_32((_lock)) != TD_RWLATCH_WRITE_FLAG_COPY) { \ + uError("invalid lock value after write lock"); \ + break; \ + } \ + } \ + } \ + } while (0) + +#define MPT_UNLOCK(type, _lock) \ + do { \ + if (MPT_READ == (type)) { \ + if (mptCtrl.lockDbg) { \ + if (atomic_load_32((_lock)) <= 0) { \ + uError("invalid lock value before read unlock"); \ + break; \ + } \ + uDebug("MPT RULOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + } \ + taosRUnLockLatch(_lock); \ + if (mptCtrl.lockDbg) { \ + uDebug("MPT RULOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + if (atomic_load_32((_lock)) < 0) { \ + uError("invalid lock value after read unlock"); \ + break; \ + } \ + } \ + } else { \ + if (mptCtrl.lockDbg) { \ + if (atomic_load_32((_lock)) != TD_RWLATCH_WRITE_FLAG_COPY) { \ + uError("invalid lock value before write unlock"); \ + break; \ + } \ + uDebug("MPT WULOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + } \ + taosWUnLockLatch(_lock); \ + if (mptCtrl.lockDbg) { \ + uDebug("MPT WULOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + if (atomic_load_32((_lock)) < 0) { \ + uError("invalid lock value after write unlock"); \ + break; \ + } \ + } \ + } \ + } while (0) + + + + +#if 0 +void joinTestReplaceRetrieveFp() { + static Stub stub; + stub.set(getNextBlockFromDownstreamRemain, getDummyInputBlock); + { +#ifdef WINDOWS + AddrAny any; + std::map result; + any.get_func_addr("getNextBlockFromDownstreamRemain", result); + for (const auto &f : result) { + stub.set(f.second, getDummyInputBlock); + } +#endif +#ifdef LINUX + AddrAny any("libexecutor.so"); + std::map result; + any.get_global_func_addr_dynsym("^getNextBlockFromDownstreamRemain$", result); + for (const auto &f : result) { + stub.set(f.second, getDummyInputBlock); + } +#endif + } +} +#endif + +void mptInitLogFile() { + const char *defaultLogFileNamePrefix = "mplog"; + const int32_t maxLogFileNum = 10; + + tsAsyncLog = 0; + qDebugFlag = 159; + uDebugFlag = 159; + tsNumOfLogLines = INT32_MAX; + tsLogKeepDays = 10; + TAOS_STRCPY(tsLogDir, TD_LOG_DIR_PATH); + + if (taosInitLog(defaultLogFileNamePrefix, maxLogFileNum, false) < 0) { + MPT_PRINTF("failed to open log file in directory:%s\n", tsLogDir); + } + taosSetNoNewFile(); +} + +static bool mptJobMemSizeCompFn(void* l, void* r, void* param) { + SMPTJobInfo* left = (SMPTJobInfo*)l; + SMPTJobInfo* right = (SMPTJobInfo*)r; + if (atomic_load_8(&right->retired)) { + return true; + } + + return atomic_load_64(&right->memInfo->allocMemSize) < atomic_load_64(&left->memInfo->allocMemSize); +} + +void mptDeleteJobQueueData(void* pData) { + SMPTJobInfo* pJob = (SMPTJobInfo*)pData; + taosHashRelease(mptCtx.pJobs, pJob); +} + + +void mptDestroyJobInfo(void* job) { + SMPTJobInfo* pJob = (SMPTJobInfo*)job; + + taosMemFree(pJob->memInfo); + taosHashCleanup(pJob->pSessions); +} + + +void mptWriteMem(void* pStart, int64_t size) { + char* pEnd = (char*)pStart + size - 1; + char* p = (char*)pStart; + while (p <= pEnd) { + *p = 'a' + taosRand() % 26; + p += 4096; + } +} + + +void mptInit() { + osDefaultInit(); + mptInitLogFile(); + + mptCtrl.caseLoopTimes = 100000; + mptCtrl.taskActTimes = 0; + mptCtrl.maxSingleAllocSize = 104857600 * 5; + mptCtrl.jobNum = 100; + mptCtrl.jobExecTimes = 10; + mptCtrl.jobTaskNum = 0; + + mptCtx.pJobs = taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_ENTRY_LOCK); + ASSERT_TRUE(NULL != mptCtx.pJobs); + + taosHashSetFreeFp(mptCtx.pJobs, mptDestroyJobInfo); + + mptCtx.pJobQueue = createBoundedQueue(10000, mptJobMemSizeCompFn, mptDeleteJobQueueData, NULL); + ASSERT_TRUE(NULL != mptCtx.pJobQueue); + mptCtx.jobCtxs = (SMPTestJobCtx*)taosMemoryCalloc(MPT_MAX_JOB_NUM, sizeof(*mptCtx.jobCtxs)); + ASSERT_TRUE(NULL != mptCtx.jobCtxs); + + mptCtx.pSrcString = (char*)taosMemoryMalloc(mptCtrl.maxSingleAllocSize); + ASSERT_TRUE(NULL != mptCtx.pSrcString); + memset(mptCtx.pSrcString, 'P', mptCtrl.maxSingleAllocSize - 1); + mptCtx.pSrcString[mptCtrl.maxSingleAllocSize - 1] = 0; + +} + +void mptDestroySession(uint64_t qId, int64_t tId, int32_t eId, int32_t taskIdx, SMPTestJobCtx* pJobCtx, void* session) { + SMPTJobInfo *pJobInfo = pJobCtx->pJob; + char id[sizeof(tId) + sizeof(eId) + 1] = {0}; + MPT_SET_TEID(id, tId, eId); + int32_t remainSessions = atomic_sub_fetch_32(&pJobInfo->memInfo->remainSession, 1); + + (void)taosHashRemove(pJobInfo->pSessions, id, sizeof(id)); + + taosMemPoolDestroySession(gMemPoolHandle, session); + + if (0 == remainSessions) { + if (0 == taosHashGetSize(pJobInfo->pSessions)) { + atomic_store_8(&pJobInfo->destroyed, 1); + + uDebug("JOB:0x%x idx:%d destroyed, code:0x%x", pJobCtx->jobId, pJobCtx->jobIdx, pJobInfo->errCode); + + atomic_add_fetch_64(&mptCtx.runStat.destoryNum, 1); + + (void)taosHashRemove(mptCtx.pJobs, &qId, sizeof(qId)); + + pJobCtx->pJob = NULL; + uInfo("the whole query job removed"); + } + } +} + + +void mptDestroyTaskCtx(SMPTestJobCtx* pJobCtx, int32_t taskIdx) { + assert(gMemPoolHandle); + + SMPTestTaskCtx* pTask = &pJobCtx->taskCtxs[taskIdx]; + + if (mptCtx.param.enableMemPool) { + mptEnableMemoryPoolUsage(gMemPoolHandle, pJobCtx->pSessions[taskIdx]); + } + + for (int32_t i = 0; i < pTask->memIdx; ++i) { + pTask->stat.times.memFree.exec++; + pTask->stat.bytes.memFree.exec+=mptMemorySize(pTask->pMemList[i].p); + pTask->stat.bytes.memFree.succ+=mptMemorySize(pTask->pMemList[i].p); + mptMemoryFree(pTask->pMemList[i].p); + pTask->pMemList[i].p = NULL; + } + + if (mptCtx.param.enableMemPool) { + mptDisableMemoryPoolUsage(); + } + + mptDestroySession(pJobCtx->jobId, pJobCtx->taskCtxs[taskIdx].taskId, 0, taskIdx, pJobCtx, pJobCtx->pSessions[taskIdx]); + pJobCtx->pSessions[taskIdx] = NULL; + + taosMemFreeClear(pTask->pMemList); + + pTask->destoryed = true; +} + + +int32_t mptInitJobInfo(uint64_t qId, SMPTJobInfo* pJob) { + pJob->pSessions= taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK); + if (NULL == pJob->pSessions) { + uError("fail to init session hash, code: 0x%x", terrno); + return terrno; + } + + int32_t code = taosMemPoolCallocJob(qId, 0, (void**)&pJob->memInfo); + if (TSDB_CODE_SUCCESS != code) { + taosHashCleanup(pJob->pSessions); + pJob->pSessions = NULL; + return code; + } + + return code; +} + + +int32_t mptInitSession(uint64_t qId, uint64_t tId, int32_t eId, SMPTestJobCtx* pJobCtx, void** ppSession) { + int32_t code = TSDB_CODE_SUCCESS; + SMPTJobInfo* pJob = NULL; + + while (true) { + pJob = (SMPTJobInfo*)taosHashAcquire(mptCtx.pJobs, &qId, sizeof(qId)); + if (NULL == pJob) { + SMPTJobInfo jobInfo = {0}; + code = mptInitJobInfo(qId, &jobInfo); + if (TSDB_CODE_SUCCESS != code) { + return code; + } + + code = taosHashPut(mptCtx.pJobs, &qId, sizeof(qId), &jobInfo, sizeof(jobInfo)); + if (TSDB_CODE_SUCCESS != code) { + mptDestroyJobInfo(&jobInfo); + if (TSDB_CODE_DUP_KEY == code) { + code = TSDB_CODE_SUCCESS; + continue; + } + + return code; + } + + pJob = (SMPTJobInfo*)taosHashAcquire(mptCtx.pJobs, &qId, sizeof(qId)); + if (NULL == pJob) { + uError("QID:0x%" PRIx64 " not in joj hash, may be dropped", qId); + return TSDB_CODE_QRY_JOB_NOT_EXIST; + } + } + + break; + } + + atomic_store_ptr(&pJobCtx->pJob, pJob); + pJob->pCtx = pJobCtx; + + char id[sizeof(tId) + sizeof(eId) + 1] = {0}; + MPT_SET_TEID(id, tId, eId); + + assert(0 == taosMemPoolInitSession(gMemPoolHandle, ppSession, pJob->memInfo, id)); + + atomic_add_fetch_32(&pJob->memInfo->remainSession, 1); + + assert(0 == taosHashPut(pJob->pSessions, id, sizeof(id), ppSession, POINTER_BYTES)); + + atomic_store_8(&pJob->initDone, 1); + +_return: + + if (NULL != pJob) { + taosHashRelease(mptCtx.pJobs, pJob); + } + + return code; +} + + + +void mptInitTask(int32_t idx, int32_t eId, SMPTestJobCtx* pJob) { + pJob->taskCtxs[idx].taskId = atomic_add_fetch_64(&mptCtx.tId, 1); + + ASSERT_TRUE(0 == mptInitSession(pJob->jobId, pJob->taskCtxs[idx].taskId, eId, pJob, &pJob->pSessions[idx])); + + pJob->taskCtxs[idx].pMemList = (SMPTestMemInfo*)taosMemoryCalloc(MPT_MAX_MEM_ACT_TIMES, sizeof(*pJob->taskCtxs[idx].pMemList)); + ASSERT_TRUE(NULL != pJob->taskCtxs[idx].pMemList); + + pJob->taskCtxs[idx].destoryed = false; + + uDebug("JOB:0x%x TASK:0x%x idx:%d initialized", pJob->jobId, pJob->taskCtxs[idx].taskId, idx); +} + +void mptInitJob(int32_t idx) { + SMPTestJobCtx* pJobCtx = &mptCtx.jobCtxs[idx]; + + pJobCtx->jobIdx = idx; + pJobCtx->jobId = atomic_add_fetch_64(&mptCtx.qId, 1); + pJobCtx->taskNum = (mptCtrl.jobTaskNum) ? mptCtrl.jobTaskNum : ((taosRand() % 10) ? (taosRand() % (MPT_MAX_SESSION_NUM/10)) : (taosRand() % MPT_MAX_SESSION_NUM)) + 1; + pJobCtx->initTimes++; + + if (!mptCtx.initDone) { + atomic_add_fetch_64(&mptCtx.totalTaskNum, pJobCtx->taskNum); + } + + for (int32_t i = 0; i < pJobCtx->taskNum; ++i) { + mptInitTask(i, 0, pJobCtx); + assert(pJobCtx->pJob); + } + + atomic_add_fetch_64(&mptCtx.runStat.initNum, 1); + + uDebug("JOB:0x%x idx:%d initialized, total times:%d, taskNum:%d", pJobCtx->jobId, idx, pJobCtx->initTimes, pJobCtx->taskNum); +} + + +void mptDestroyTask(SMPTestJobCtx* pJobCtx, int32_t taskIdx) { + if (mptCtx.param.enableMemPool && tsMemPoolFullFunc) { + SMPStatDetail* pStat = NULL; + int64_t allocSize = 0; + taosMemPoolGetSessionStat(pJobCtx->pSessions[taskIdx], &pStat, &allocSize, NULL); + int64_t usedSize = MEMPOOL_GET_USED_SIZE(pStat); + + assert(allocSize == usedSize); + assert(0 == memcmp(pStat, &pJobCtx->taskCtxs[taskIdx].stat, sizeof(*pStat))); + } + + mptDestroyTaskCtx(pJobCtx, taskIdx); +} + +int32_t mptDestroyJob(SMPTestJobCtx* pJobCtx, bool reset) { + uint64_t jobId = pJobCtx->jobId; + for (int32_t i = 0; i < pJobCtx->taskNum; ++i) { + if (!pJobCtx->taskCtxs[i].destoryed) { + mptDestroyTask(pJobCtx, i); + } + } + + //mptDestroyJobInfo(pJobCtx->pJob); + //(void)taosHashRemove(mptCtx.pJobs, &pJobCtx->jobId, sizeof(pJobCtx->jobId)); + + if (reset) { + int32_t jobIdx = pJobCtx->jobIdx; + memset((char*)pJobCtx + sizeof(pJobCtx->jobExecLock), 0, sizeof(SMPTestJobCtx) - sizeof(pJobCtx->jobExecLock)); + mptInitJob(jobIdx); + } + + MPT_PRINTF(" JOB:0x%x retired\n", jobId); + + return 0; +} + +void mptCheckCompareJobInfo(SMPTestJobCtx* pJobCtx) { + +} + +int32_t mptResetJob(SMPTestJobCtx* pJobCtx) { + if (MPT_TRY_LOCK(MPT_WRITE, &pJobCtx->jobExecLock)) { + return -1; + } + + if (NULL == atomic_load_ptr(&pJobCtx->pJob)) { + int32_t jobIdx = pJobCtx->jobIdx; + memset((char*)pJobCtx + sizeof(pJobCtx->jobExecLock), 0, sizeof(SMPTestJobCtx) - sizeof(pJobCtx->jobExecLock)); + mptInitJob(jobIdx); + + MPT_UNLOCK(MPT_WRITE, &pJobCtx->jobExecLock); + return 0; + } + + int32_t code = 0; + if (atomic_load_8(&pJobCtx->pJob->retired)) { + int32_t taskRunning = atomic_load_32(&pJobCtx->taskRunningNum); + if (0 == taskRunning) { + code = mptDestroyJob(pJobCtx, true); + } else { + uDebug("JOB:0x%x retired but will not destroy cause of task running, num:%d", pJobCtx->jobId, taskRunning); + code = -1; + } + } + + MPT_UNLOCK(MPT_WRITE, &pJobCtx->jobExecLock); + + return 0; +} + +bool mptRetireJob(SMPTJobInfo* pJob) { + SMPTestJobCtx* pCtx = (SMPTestJobCtx*)pJob->pCtx; + + if (MPT_TRY_LOCK(MPT_WRITE, &pCtx->jobExecLock)) { + return false; + } + + bool retired = false; + int32_t taskRunning = atomic_load_32(&pCtx->taskRunningNum); + if (0 == taskRunning) { + mptDestroyJob(pCtx, false); + retired = true; + } else { + uDebug("JOB:0x%x retired but will not destroy cause of task running, num:%d", pCtx->jobId, taskRunning); + } + + MPT_UNLOCK(MPT_WRITE, &pCtx->jobExecLock); + + return retired; +} + +int32_t mptGetMemPoolMaxMemSize(void* pHandle, int64_t* maxSize) { + int64_t freeSize = 0; + int64_t usedSize = 0; + bool needEnd = false; + + taosMemPoolGetUsedSizeBegin(pHandle, &usedSize, &needEnd); + int32_t code = taosGetSysAvailMemory(&freeSize); + if (needEnd) { + taosMemPoolGetUsedSizeEnd(pHandle); + } + + if (TSDB_CODE_SUCCESS != code) { + uError("get system avaiable memory size failed, error: 0x%x", code); + return code; + } + + int64_t totalSize = freeSize + usedSize; + int64_t reserveSize = TMAX(totalSize * MPT_DEFAULT_RESERVE_MEM_PERCENT / 100 / 1048576UL * 1048576UL, MPT_MIN_RESERVE_MEM_SIZE); + int64_t availSize = (totalSize - reserveSize) / 1048576UL * 1048576UL; + if (availSize < MPT_MIN_MEM_POOL_SIZE) { + uError("too little available query memory, totalAvailable: %" PRId64 ", reserveSize: %" PRId64, totalSize, reserveSize); + //return TSDB_CODE_QRY_TOO_FEW_AVAILBLE_MEM; + } + + uDebug("new pool maxSize:%" PRId64 ", usedSize:%" PRId64 ", freeSize:%" PRId64, availSize, usedSize, freeSize); + + *maxSize = availSize; + + return TSDB_CODE_SUCCESS; +} + +void mptRetireJobsCb(int64_t retireSize, int32_t errCode) { + SMPTJobInfo* pJob = (SMPTJobInfo*)taosHashIterate(mptCtx.pJobs, NULL); + int32_t jobNum = 0; + uint64_t jobId = 0; + int64_t retiredSize = 0; + while (retiredSize < retireSize && NULL != pJob) { + if (atomic_load_8(&pJob->retired) || 0 == atomic_load_8(&pJob->initDone)) { + pJob = (SMPTJobInfo*)taosHashIterate(mptCtx.pJobs, pJob); + continue; + } + + if (0 == atomic_val_compare_exchange_32(&pJob->errCode, 0, errCode) && 0 == atomic_val_compare_exchange_8(&pJob->retired, 0, 1)) { + int64_t aSize = atomic_load_64(&pJob->memInfo->allocMemSize); + jobId = pJob->memInfo->jobId; + + atomic_add_fetch_64(&mptCtx.runStat.retireNum, 1); + + bool retired = mptRetireJob(pJob); + if (retired) { + retiredSize += aSize; + } + + jobNum++; + + uDebug("QID:0x%" PRIx64 " job mark retired cause of limit reached, retired:%d, usedSize:%" PRId64 ", retireSize:%" PRId64 ", retiredSize:%" PRId64, + jobId, retired, aSize, retireSize, retiredSize); + } + + pJob = (SMPTJobInfo*)taosHashIterate(mptCtx.pJobs, pJob); + } + + taosHashCancelIterate(mptCtx.pJobs, pJob); + + uDebug("total %d jobs mark retired, retiredSize:%" PRId64 " targetRetireSize:%" PRId64, jobNum, retiredSize, retireSize); +} + + +void mptRetireJobCb(uint64_t jobId, uint64_t clientId, int32_t errCode) { + SMPTJobInfo* pJob = (SMPTJobInfo*)taosHashGet(mptCtx.pJobs, &jobId, sizeof(jobId)); + if (NULL == pJob) { + uError("QID:0x%" PRIx64 " fail to get job from job hash", jobId); + return; + } + + if (0 == atomic_val_compare_exchange_32(&pJob->errCode, 0, errCode) && 0 == atomic_val_compare_exchange_8(&pJob->retired, 0, 1)) { + uInfo("QID:0x%" PRIx64 " mark retired, errCode: 0x%x, allocSize:%" PRId64, jobId, errCode, atomic_load_64(&pJob->memInfo->allocMemSize)); + atomic_add_fetch_64(&mptCtx.runStat.retireNum, 1); + } else { + uDebug("QID:0x%" PRIx64 " already retired, retired: %d, errCode: 0x%x, allocSize:%" PRId64, jobId, atomic_load_8(&pJob->retired), atomic_load_32(&pJob->errCode), atomic_load_64(&pJob->memInfo->allocMemSize)); + } +} + +void mptInitPool(void) { + assert(0 == taosMemoryPoolInit(mptRetireJobsCb, mptRetireJobCb)); +} + + +void mptSimulateAction(SMPTestJobCtx* pJobCtx, SMPTestTaskCtx* pTask) { + int32_t actId = 0; + bool actDone = false; + int32_t size = 0; + int32_t osize = 0, nsize = 0; + + while (!actDone) { + actId = taosRand() % 10; + size = (taosRand() % 8) ? (taosRand() % (mptCtrl.maxSingleAllocSize / 100)) : (taosRand() % mptCtrl.maxSingleAllocSize); + + switch (actId) { + case 0: { // malloc + if (pTask->memIdx >= MPT_MAX_MEM_ACT_TIMES) { + break; + } + + pTask->pMemList[pTask->memIdx].p = mptMemoryMalloc(size); + if (NULL == pTask->pMemList[pTask->memIdx].p) { + pTask->stat.times.memMalloc.exec++; + pTask->stat.bytes.memMalloc.exec+=size; + pTask->stat.times.memMalloc.fail++; + pTask->stat.bytes.memMalloc.fail+=size; + uError("JOB:0x%x TASK:0x%x mpMalloc %d failed, error:%s", pJobCtx->jobId, pTask->taskId, size, tstrerror(terrno)); + return; + } + + nsize = mptMemorySize(pTask->pMemList[pTask->memIdx].p); + pTask->stat.times.memMalloc.exec++; + pTask->stat.bytes.memMalloc.exec+=nsize; + pTask->stat.bytes.memMalloc.succ+=nsize; + pTask->stat.times.memMalloc.succ++; + + mptWriteMem(pTask->pMemList[pTask->memIdx].p, size); + + pTask->memIdx++; + pTask->lastAct = actId; + actDone = true; + break; + } + case 1: { // calloc + if (pTask->memIdx >= MPT_MAX_MEM_ACT_TIMES) { + break; + } + + pTask->pMemList[pTask->memIdx].p = mptMemoryCalloc(1, size); + if (NULL == pTask->pMemList[pTask->memIdx].p) { + pTask->stat.times.memCalloc.exec++; + pTask->stat.bytes.memCalloc.exec+=size; + pTask->stat.times.memCalloc.fail++; + pTask->stat.bytes.memCalloc.fail+=size; + uError("JOB:0x%x TASK:0x%x mpCalloc %d failed, error:%s", pJobCtx->jobId, pTask->taskId, size, tstrerror(terrno)); + return; + } + + nsize = mptMemorySize(pTask->pMemList[pTask->memIdx].p); + + pTask->stat.times.memCalloc.exec++; + pTask->stat.bytes.memCalloc.exec+=nsize; + pTask->stat.times.memCalloc.succ++; + pTask->stat.bytes.memCalloc.succ+=nsize; + + mptWriteMem(pTask->pMemList[pTask->memIdx].p, size); + + pTask->memIdx++; + pTask->lastAct = actId; + actDone = true; + break; + } + case 2:{ // new realloc + break; + if (pTask->memIdx >= MPT_MAX_MEM_ACT_TIMES) { + break; + } + + pTask->pMemList[pTask->memIdx].p = mptMemoryRealloc(NULL, size); + if (NULL == pTask->pMemList[pTask->memIdx].p) { + pTask->stat.times.memRealloc.exec++; + pTask->stat.bytes.memRealloc.exec+=size; + pTask->stat.times.memRealloc.fail++; + pTask->stat.bytes.memRealloc.fail+=size; + uError("JOB:0x%x TASK:0x%x new mpRealloc %d failed, error:%s", pJobCtx->jobId, pTask->taskId, size, tstrerror(terrno)); + return; + } + + nsize = mptMemorySize(pTask->pMemList[pTask->memIdx].p); + + pTask->stat.times.memRealloc.exec++; + pTask->stat.bytes.memRealloc.exec+=nsize; + pTask->stat.bytes.memRealloc.succ+=nsize; + pTask->stat.times.memRealloc.succ++; + + mptWriteMem(pTask->pMemList[pTask->memIdx].p, size); + + pTask->memIdx++; + pTask->lastAct = actId; + actDone = true; + break; + } + case 3:{ // real realloc + break; + if (pTask->memIdx <= 0) { + break; + } + + assert(pTask->pMemList[pTask->memIdx - 1].p); + osize = mptMemorySize(pTask->pMemList[pTask->memIdx - 1].p); + size++; + pTask->pMemList[pTask->memIdx - 1].p = mptMemoryRealloc(pTask->pMemList[pTask->memIdx - 1].p, size); + if (NULL == pTask->pMemList[pTask->memIdx - 1].p) { + pTask->stat.times.memRealloc.exec++; + pTask->stat.bytes.memRealloc.exec+=size; + pTask->stat.bytes.memRealloc.origExec+=osize; + pTask->stat.times.memRealloc.fail++; + pTask->stat.bytes.memRealloc.fail+=size; + + pTask->stat.times.memFree.exec++; + pTask->stat.bytes.memFree.exec+=osize; + pTask->stat.times.memFree.succ++; + pTask->stat.bytes.memFree.succ+=osize; + uError("JOB:0x%x TASK:0x%x real mpRealloc %d failed, error:%s", pJobCtx->jobId, pTask->taskId, size, tstrerror(terrno)); + pTask->memIdx--; + return; + } + + nsize = mptMemorySize(pTask->pMemList[pTask->memIdx - 1].p); + pTask->stat.times.memRealloc.exec++; + pTask->stat.bytes.memRealloc.exec+=nsize; + pTask->stat.bytes.memRealloc.origExec+=osize; + pTask->stat.bytes.memRealloc.origSucc+=osize; + pTask->stat.times.memRealloc.succ++; + pTask->stat.bytes.memRealloc.succ+=nsize; + + mptWriteMem(pTask->pMemList[pTask->memIdx - 1].p, size); + + pTask->lastAct = actId; + actDone = true; + break; + } + case 4:{ // realloc free + if (pTask->memIdx <= 0) { + break; + } + + assert(pTask->pMemList[pTask->memIdx - 1].p); + osize = mptMemorySize(pTask->pMemList[pTask->memIdx - 1].p); + + pTask->pMemList[pTask->memIdx - 1].p = mptMemoryRealloc(pTask->pMemList[pTask->memIdx - 1].p, 0); + pTask->stat.times.memFree.exec++; + pTask->stat.bytes.memFree.exec+=osize; + assert(NULL == pTask->pMemList[pTask->memIdx - 1].p); + + pTask->stat.times.memFree.succ++; + pTask->stat.bytes.memFree.succ+=osize; + + pTask->memIdx--; + pTask->lastAct = actId; + actDone = true; + break; + } + case 5:{ // strdup + if (pTask->memIdx >= MPT_MAX_MEM_ACT_TIMES) { + break; + } + + size /= 10; + MPT_LOCK(MPT_WRITE, &mptCtx.stringLock); + mptCtx.pSrcString[size] = 0; + pTask->pMemList[pTask->memIdx].p = mptStrdup(mptCtx.pSrcString); + mptCtx.pSrcString[size] = 'W'; + MPT_UNLOCK(MPT_WRITE, &mptCtx.stringLock); + + if (NULL == pTask->pMemList[pTask->memIdx].p) { + pTask->stat.times.memStrdup.exec++; + pTask->stat.bytes.memStrdup.exec+=size + 1; + pTask->stat.times.memStrdup.fail++; + pTask->stat.bytes.memStrdup.fail+=size + 1; + uError("JOB:0x%x TASK:0x%x mpStrdup %d failed, error:%s", pJobCtx->jobId, pTask->taskId, size, tstrerror(terrno)); + return; + } + + nsize = mptMemorySize(pTask->pMemList[pTask->memIdx].p); + pTask->stat.times.memStrdup.exec++; + pTask->stat.bytes.memStrdup.exec+= nsize; + + pTask->stat.times.memStrdup.succ++; + pTask->stat.bytes.memStrdup.succ+=nsize; + + mptWriteMem(pTask->pMemList[pTask->memIdx].p, size); + + pTask->memIdx++; + pTask->lastAct = actId; + actDone = true; + break; + } + case 6:{ // strndup + if (pTask->memIdx >= MPT_MAX_MEM_ACT_TIMES) { + break; + } + + size /= 10; + + MPT_LOCK(MPT_WRITE, &mptCtx.stringLock); + assert(strlen(mptCtx.pSrcString) > size); + pTask->pMemList[pTask->memIdx].p = mptStrndup(mptCtx.pSrcString, size); + MPT_UNLOCK(MPT_WRITE, &mptCtx.stringLock); + + if (NULL == pTask->pMemList[pTask->memIdx].p) { + pTask->stat.times.memStrndup.exec++; + pTask->stat.bytes.memStrndup.exec+=size + 1; + pTask->stat.times.memStrndup.fail++; + pTask->stat.bytes.memStrndup.fail+=size + 1; + uError("JOB:0x%x TASK:0x%x mpStrndup %d failed, error:%s", pJobCtx->jobId, pTask->taskId, size, tstrerror(terrno)); + return; + } + + assert(strlen((char*)pTask->pMemList[pTask->memIdx].p) == size); + nsize = mptMemorySize(pTask->pMemList[pTask->memIdx].p); + + pTask->stat.times.memStrndup.exec++; + pTask->stat.bytes.memStrndup.exec+=nsize; + pTask->stat.times.memStrndup.succ++; + pTask->stat.bytes.memStrndup.succ+=nsize; + + mptWriteMem(pTask->pMemList[pTask->memIdx].p, size); + + pTask->memIdx++; + pTask->lastAct = actId; + actDone = true; + break; + } + case 7:{ // free + if (pTask->memIdx <= 0) { + break; + } + + assert(pTask->pMemList[pTask->memIdx - 1].p); + osize = mptMemorySize(pTask->pMemList[pTask->memIdx - 1].p); + mptMemoryFree(pTask->pMemList[pTask->memIdx - 1].p); + pTask->stat.times.memFree.exec++; + pTask->stat.times.memFree.succ++; + pTask->stat.bytes.memFree.exec+=osize; + pTask->stat.bytes.memFree.succ+=osize; + pTask->pMemList[pTask->memIdx - 1].p = NULL; + + pTask->memIdx--; + pTask->lastAct = actId; + actDone = true; + break; + } + case 8:{ // trim + bool trimed = false; + int32_t code = mptMemoryTrim(0, &trimed); + pTask->stat.times.memTrim.exec++; + if (code) { + pTask->stat.times.memTrim.fail++; + } else { + pTask->stat.times.memTrim.succ++; + if (trimed) { + pTask->stat.bytes.memTrim.succ++; + } + } + pTask->lastAct = actId; + actDone = true; + break; + } + case 9: { // malloc_align + if (pTask->memIdx >= MPT_MAX_MEM_ACT_TIMES) { + break; + } + + pTask->pMemList[pTask->memIdx].p = mptMemoryMallocAlign(8, size); + if (NULL == pTask->pMemList[pTask->memIdx].p) { + pTask->stat.times.memMalloc.exec++; + pTask->stat.bytes.memMalloc.exec+=size; + pTask->stat.times.memMalloc.fail++; + pTask->stat.bytes.memMalloc.fail+=size; + uError("JOB:0x%x TASK:0x%x mpMallocAlign %d failed, error:%s", pJobCtx->jobId, pTask->taskId, size, tstrerror(terrno)); + return; + } + + nsize = mptMemorySize(pTask->pMemList[pTask->memIdx].p); + + mptWriteMem(pTask->pMemList[pTask->memIdx].p, size); + + pTask->stat.times.memMalloc.exec++; + pTask->stat.bytes.memMalloc.exec+=nsize; + + pTask->stat.times.memMalloc.succ++; + pTask->stat.bytes.memMalloc.succ+=nsize; + pTask->memIdx++; + pTask->lastAct = actId; + actDone = true; + break; + } + default: + assert(0); + break; + } + } +} + +void mptSimulateTask(SMPTestJobCtx* pJobCtx, SMPTestTaskCtx* pTask, int32_t actTimes) { + uDebug("JOB:0x%x TASK:0x%x will start total %d actions", pJobCtx->jobId, pTask->taskId, actTimes); + + for (int32_t i = 0; i < actTimes; ++i) { + if (atomic_load_8(&pJobCtx->pJob->retired)) { + uDebug("JOB:0x%x TASK:0x%x stop running cause of job already retired", pJobCtx->jobId, pTask->taskId); + return; + } + + //MPT_PRINTF("\tTASK:0x%x will start %d:%d actions\n", pTask->taskId, i, actTimes); + + mptSimulateAction(pJobCtx, pTask); + } +} + +void mptSimulateOutTask(int64_t targetSize) { + SMPTestMemInfo* pCtx = &mptCtx.npMemList[mptCtx.npIdx]; + pCtx->size = targetSize; + pCtx->p = taosMemMalloc(pCtx->size); + if (NULL == pCtx->p) { + uError("non-pool sim malloc %" PRId64 " failed", pCtx->size); + pCtx->size = 0; + return; + } + + mptWriteMem(pCtx->p, pCtx->size); + + mptCtx.npIdx++; +} + + +void mptTaskRun(SMPTestJobCtx* pJobCtx, SMPTestTaskCtx* pCtx, int32_t idx, int32_t actTimes) { + uDebug("JOB:0x%x TASK:0x%x start running", pJobCtx->jobId, pCtx->taskId); + + if (atomic_load_8(&pJobCtx->pJob->retired)) { + uDebug("JOB:0x%x TASK:0x%x stop running cause of job already retired", pJobCtx->jobId, pCtx->taskId); + return; + } + + if (taosWTryLockLatch(&pCtx->taskExecLock)) { + uDebug("JOB:0x%x TASK:0x%x stop running cause of task already running", pJobCtx->jobId, pCtx->taskId); + return; + } + + atomic_add_fetch_32(&pJobCtx->taskRunningNum, 1); + + if (mptCtx.param.enableMemPool) { + mptEnableMemoryPoolUsage(gMemPoolHandle, pJobCtx->pSessions[idx]); + } + + mptSimulateTask(pJobCtx, pCtx, actTimes); + + if (mptCtx.param.enableMemPool) { + mptDisableMemoryPoolUsage(); + } + + //mptSimulateOutTask(pJobCtx, pCtx); + + taosWUnLockLatch(&pCtx->taskExecLock); + + atomic_sub_fetch_32(&pJobCtx->taskRunningNum, 1); + + uDebug("JOB:0x%x TASK:0x%x end running", pJobCtx->jobId, pCtx->taskId); +} + + +void mptInitJobs() { + int32_t jobNum = mptCtrl.jobNum ? mptCtrl.jobNum : MPT_MAX_JOB_NUM; + + memset(mptCtx.jobCtxs, 0, sizeof(*mptCtx.jobCtxs) * jobNum); + mptCtx.totalTaskNum = 0; + + for (int32_t i = 0; i < jobNum; ++i) { + mptInitJob(i); + } +} + +void mptCheckPoolUsedSize(int32_t jobNum) { + int64_t usedSize = 0; + bool needEnd = false; + int64_t poolUsedSize = 0; + int32_t sleepTimes = 0; + + while (true) { + if (taosMemPoolTryLockPool(gMemPoolHandle, false)) { + taosUsleep(1); + continue; + } + + taosMemPoolGetUsedSizeBegin(gMemPoolHandle, &usedSize, &needEnd); + + poolUsedSize = 0; + + for (int32_t i = 0; i < jobNum; ++i) { + SMPTestJobCtx* pJobCtx = &mptCtx.jobCtxs[i]; + + sleepTimes = 0; + while (MPT_TRY_LOCK(MPT_READ, &pJobCtx->jobExecLock)) { + taosUsleep(1); + sleepTimes++; + if (sleepTimes > 100) { + break; + } + } + + if (sleepTimes > 100) { + break; + } + + if (NULL == pJobCtx->pJob) { + MPT_UNLOCK(MPT_READ, &pJobCtx->jobExecLock); + continue; + } + + int64_t jobUsedSize = 0; + for (int32_t m = 0; m < pJobCtx->taskNum; ++m) { + if (!pJobCtx->taskCtxs[m].destoryed) { + SMPStatDetail* pStat = NULL; + int64_t allocSize = 0; + taosMemPoolGetSessionStat(pJobCtx->pSessions[m], &pStat, &allocSize, NULL); + int64_t usedSize = MEMPOOL_GET_USED_SIZE(pStat); + + assert(allocSize == usedSize); + assert(0 == memcmp(pStat, &pJobCtx->taskCtxs[m].stat, sizeof(*pStat))); + + jobUsedSize += allocSize; + } + } + + assert(pJobCtx->pJob->memInfo->allocMemSize == jobUsedSize); + + MPT_UNLOCK(MPT_READ, &pJobCtx->jobExecLock); + + poolUsedSize += jobUsedSize; + } + + taosMemPoolGetUsedSizeEnd(gMemPoolHandle); + + if (sleepTimes > 100) { + continue; + } + + assert(poolUsedSize <= usedSize); + break; + } +} + +void mptLaunchSingleTask(SMPTestThread* pThread, SMPTestJobCtx* pJobCtx, int32_t taskIdx, int32_t actTimes) { + if (atomic_load_8(&pJobCtx->pJob->retired) || pJobCtx->taskCtxs[taskIdx].destoryed) { + return; + } + + MPT_PRINTF("Thread %d start to run %d:%d task\n", pThread->idx, taskIdx, pJobCtx->taskNum); + mptTaskRun(pJobCtx, &pJobCtx->taskCtxs[taskIdx], taskIdx, actTimes); + MPT_PRINTF("Thread %d end %d:%d task\n", pThread->idx, taskIdx, pJobCtx->taskNum); + +} + +void mptRunRandTasks(SMPTestThread* pThread) { + int64_t runTaskTimes = mptCtx.totalTaskNum * MPT_DEFAULT_TASK_RUN_TIMES, taskExecIdx = 0; + int32_t jobNum = mptCtrl.jobNum ? mptCtrl.jobNum : MPT_MAX_JOB_NUM; + int32_t jobIdx = 0, taskIdx = 0, code = 0; + SMPTestJobCtx* pJobCtx = NULL; + + MPT_PRINTF("Thread %d start the %d:%d exection - runTaskTimes:%" PRId64 "\n", pThread->idx, mptExecLoop, mptExecNum, runTaskTimes); + + while (runTaskTimes > 0) { + int32_t actTimes = mptCtrl.taskActTimes ? mptCtrl.taskActTimes : ((taosRand() % 10) ? (taosRand() % (MPT_MAX_MEM_ACT_TIMES/10)) : (taosRand() % MPT_MAX_MEM_ACT_TIMES)); + jobIdx = taosRand() % jobNum; + + pJobCtx = &mptCtx.jobCtxs[jobIdx]; + + if (mptResetJob(pJobCtx)) { + continue; + } + + if (MPT_TRY_LOCK(MPT_READ, &pJobCtx->jobExecLock)) { + continue; + } + + taskIdx = taosRand() % pJobCtx->taskNum; + + if (atomic_load_8(&pJobCtx->pJob->retired) || pJobCtx->taskCtxs[taskIdx].destoryed) { + MPT_UNLOCK(MPT_READ, &pJobCtx->jobExecLock); + continue; + } + + MPT_PRINTF("Thread %d start to run %d:%d task\n", pThread->idx, taskExecIdx, runTaskTimes); + mptTaskRun(pJobCtx, &pJobCtx->taskCtxs[taskIdx], taskIdx, actTimes); + MPT_PRINTF("Thread %d end %d:%d task\n", pThread->idx, taskExecIdx, runTaskTimes); + + MPT_UNLOCK(MPT_READ, &pJobCtx->jobExecLock); + + runTaskTimes--; + taskExecIdx++; + } + +} + +void mptRunLoopJobs(SMPTestThread* pThread) { + mptJobNum = (mptCtrl.jobNum) ? mptCtrl.jobNum : (taosRand() % MPT_MAX_JOB_NUM + 1); + + MPT_PRINTF("Thread %d start the %d:%d exection - jobNum:%d\n", pThread->idx, mptExecLoop, mptExecNum, mptJobNum); + + for (int32_t i = 0; i < mptJobNum; ++i) { + SMPTestJobCtx* pJobCtx = &mptCtx.jobCtxs[i]; + + if (mptResetJob(pJobCtx)) { + continue; + } + + if (MPT_TRY_LOCK(MPT_READ, &pJobCtx->jobExecLock)) { + continue; + } + + MPT_PRINTF(" Thread %d start to run %d:%d job[%d:0x%" PRIx64 "]\n", pThread->idx, i, mptJobNum, pJobCtx->jobIdx, pJobCtx->jobId); + + for (int32_t m = 0; m < pJobCtx->taskNum; ++m) { + if (atomic_load_8(&pJobCtx->pJob->retired)) { + break; + } + + int32_t actTimes = mptCtrl.taskActTimes ? mptCtrl.taskActTimes : ((taosRand() % 10) ? (taosRand() % (MPT_MAX_MEM_ACT_TIMES/10)) : (taosRand() % MPT_MAX_MEM_ACT_TIMES)); + mptLaunchSingleTask(pThread, pJobCtx, m, actTimes); + } + + MPT_UNLOCK(MPT_READ, &pJobCtx->jobExecLock); + + MPT_PRINTF(" Thread %d end %dth JOB 0x%x exec, retired:%d\n", pThread->idx, pJobCtx->jobIdx, pJobCtx->jobId, pJobCtx->pJob->retired); + } +} + +void* mptRunThreadFunc(void* param) { + SMPTestThread* pThread = (SMPTestThread*)param; + mptExecNum = (mptCtrl.jobExecTimes) ? mptCtrl.jobExecTimes : taosRand() % MPT_MAX_JOB_LOOP_TIMES + 1; + + for (int32_t n = 0; n < mptExecNum; ++n) { + mptExecLoop = n; + + if (mptCtx.param.randTask) { + mptRunRandTasks(pThread); + } else { + mptRunLoopJobs(pThread); + } + + MPT_PRINTF("Thread %d finish the %dth exection\n", pThread->idx, n); + + if (mptCtx.param.threadNum <= 1 && mptCtx.param.enableMemPool && tsMemPoolFullFunc) { + mptCheckPoolUsedSize(mptJobNum); + } + } + + return NULL; +} + +void* mptNonPoolThreadFunc(void* param) { + int64_t targetSize = MPT_NON_POOL_ALLOC_UNIT; + int64_t allocSize = 0; + + while (!atomic_load_8(&mptCtx.testDone)) { + mptSimulateOutTask(targetSize); + allocSize += targetSize; + + MPT_EPRINTF("%d:Non-pool malloc and write %" PRId64 " bytes, keep size:%" PRId64 "\n", mptCtx.npIdx - 1, targetSize, allocSize); + taosUsleep(1); + + if ((mptCtx.npIdx * targetSize) >= (tsMinReservedMemorySize * 1048576UL * 10)) { + for (int32_t i = 0; i < mptCtx.npIdx; ++i) { + taosMemFreeClear(mptCtx.npMemList[i].p); + } + + mptCtx.npIdx = 0; + targetSize += MPT_NON_POOL_ALLOC_UNIT; + allocSize = 0; + taosMsleep(100); + } + } + + return NULL; +} + + +void* mptDropThreadFunc(void* param) { + int32_t jobIdx = 0, taskIdx = 0, code = 0; + uint64_t taskId = 0; + int32_t jobNum = mptCtrl.jobNum ? mptCtrl.jobNum : MPT_MAX_JOB_NUM; + + while (!atomic_load_8(&mptCtx.testDone)) { + taosMsleep(400); + + MPT_EPRINTF("%" PRId64 " - initJobs:%" PRId64 " retireJobs:%" PRId64 " destoryJobs:%" PRId64 " remainJobs:%" PRId64 "\n", taosGetTimestampMs(), + mptCtx.runStat.initNum, mptCtx.runStat.retireNum, mptCtx.runStat.destoryNum, mptCtx.runStat.initNum - mptCtx.runStat.destoryNum); + + if (taosMemPoolTryLockPool(gMemPoolHandle, true)) { + continue; + } + + jobIdx = taosRand() % jobNum; + SMPTestJobCtx* pJobCtx = &mptCtx.jobCtxs[jobIdx]; + MPT_LOCK(MPT_WRITE, &pJobCtx->jobExecLock); + if (NULL == pJobCtx->pJob || pJobCtx->pJob->destroyed) { + MPT_UNLOCK(MPT_WRITE, &pJobCtx->jobExecLock); + taosMemPoolUnLockPool(gMemPoolHandle, true); + continue; + } + + if (taosRand() % 20) { + taskIdx = taosRand() % pJobCtx->taskNum; + if (pJobCtx->taskCtxs[taskIdx].destoryed) { + MPT_UNLOCK(MPT_WRITE, &pJobCtx->jobExecLock); + taosMemPoolUnLockPool(gMemPoolHandle, true); + continue; + } + + taskId = pJobCtx->taskCtxs[taskIdx].taskId; + mptDestroyTask(pJobCtx, taskIdx); + MPT_EPRINTF("Drop Thread destroy task %d:0x%" PRIx64 " in job %d:%" PRIx64 "\n", taskIdx, taskId, jobIdx, pJobCtx->jobId); + + MPT_UNLOCK(MPT_WRITE, &pJobCtx->jobExecLock); + } else { + code = mptDestroyJob(pJobCtx, false); + if (0 == code) { + MPT_EPRINTF("Drop Thread destroy job %d:%" PRIx64 "\n", jobIdx, pJobCtx->jobId); + } + MPT_UNLOCK(MPT_WRITE, &pJobCtx->jobExecLock); + } + + taosMemPoolUnLockPool(gMemPoolHandle, true); + } + + return NULL; +} + + +void mptStartRunThread(int32_t threadIdx) { + TdThreadAttr thattr; + ASSERT_EQ(0, taosThreadAttrInit(&thattr)); + ASSERT_EQ(0, taosThreadAttrSetDetachState(&thattr, PTHREAD_CREATE_JOINABLE)); + mptCtx.threadCtxs[threadIdx].idx = threadIdx; + ASSERT_EQ(0, taosThreadCreate(&mptCtx.threadCtxs[threadIdx].threadFp, &thattr, mptRunThreadFunc, &mptCtx.threadCtxs[threadIdx])); + ASSERT_EQ(0, taosThreadAttrDestroy(&thattr)); +} + +void mptStartDropThread() { + TdThreadAttr thattr; + ASSERT_EQ(0, taosThreadAttrInit(&thattr)); + ASSERT_EQ(0, taosThreadAttrSetDetachState(&thattr, PTHREAD_CREATE_JOINABLE)); + ASSERT_EQ(0, taosThreadCreate(&mptCtx.dropThreadFp, &thattr, mptDropThreadFunc, NULL)); + ASSERT_EQ(0, taosThreadAttrDestroy(&thattr)); +} + +void mptStartNonPoolThread() { + TdThreadAttr thattr; + ASSERT_EQ(0, taosThreadAttrInit(&thattr)); + ASSERT_EQ(0, taosThreadAttrSetDetachState(&thattr, PTHREAD_CREATE_JOINABLE)); + ASSERT_EQ(0, taosThreadCreate(&mptCtx.nPoolThreadFp, &thattr, mptNonPoolThreadFunc, NULL)); + ASSERT_EQ(0, taosThreadAttrDestroy(&thattr)); +} + + + + + + +void mptDestroyJobs() { + int32_t jobNum = mptCtrl.jobNum ? mptCtrl.jobNum : MPT_MAX_JOB_NUM; + + for (int32_t i = 0; i < jobNum; ++i) { + mptDestroyJob(&mptCtx.jobCtxs[i], false); + } + + +} + +void mptDestroyNonPoolCtx() { + for (int32_t i = 0; i < mptCtx.npIdx; ++i) { + taosMemFreeClear(mptCtx.npMemList[i].p); + } + taosMemFreeClear(mptCtx.npMemList); +} + +void mptInitNonPoolCtx() { + mptCtx.npMemList = (SMPTestMemInfo*)taosMemoryCalloc(MPT_MAX_NON_POOL_ALLOC_TIMES, sizeof(*mptCtx.npMemList)); + ASSERT_TRUE(NULL != mptCtx.npMemList); +} + +void mptRunCase(SMPTestParam* param, int32_t times) { + MPT_PRINTF("\t case start the %dth running\n", times); + + mptCaseLoop = times; + memcpy(&mptCtx.param, param, sizeof(SMPTestParam)); + tsSingleQueryMaxMemorySize = param->jobQuota; + + atomic_store_8(&mptCtx.testDone, 0); + mptCtx.initDone = false; + + mptInitPool(); + + mptInitJobs(); + + mptInitNonPoolCtx(); + + mptCtx.initDone = true; + + for (int32_t i = 0; i < mptCtx.param.threadNum; ++i) { + mptStartRunThread(i); + } + + mptStartDropThread(); + mptStartNonPoolThread(); + + for (int32_t i = 0; i < mptCtx.param.threadNum; ++i) { + (void)taosThreadJoin(mptCtx.threadCtxs[i].threadFp, NULL); + } + + atomic_store_8(&mptCtx.testDone, 1); + + (void)taosThreadJoin(mptCtx.dropThreadFp, NULL); + (void)taosThreadJoin(mptCtx.nPoolThreadFp, NULL); + + mptDestroyJobs(); + mptDestroyNonPoolCtx(); + + taosMemPoolClose(gMemPoolHandle); + + while (gMemPoolHandle) { + taosMsleep(10); + } + + MPT_PRINTF("\t case end the %dth running\n", times); +} + +void mptPrintTestBeginInfo(char* caseName, SMPTestParam* param) { + MPT_PRINTF("Case [%s] begins:\n", caseName); + MPT_PRINTF("\t case loop times: %d\n", mptCtrl.caseLoopTimes); + MPT_PRINTF("\t task max act times: %d\n", mptCtrl.taskActTimes ? mptCtrl.taskActTimes : MPT_MAX_MEM_ACT_TIMES); + MPT_PRINTF("\t max single alloc size: %" PRId64 "\n", mptCtrl.maxSingleAllocSize); + MPT_PRINTF("\t job quota size: %dMB\n", param->jobQuota); + MPT_PRINTF("\t reserve mode: %d\n", param->reserveMode); + MPT_PRINTF("\t reserve size: %dMB\n", param->reserveSize); + MPT_PRINTF("\t test thread num: %d\n", param->threadNum); + MPT_PRINTF("\t random exec task: %d\n", param->randTask); +} + +void mptFreeAddrList(void** pList, int32_t num) { + for (int32_t i = 0; i < num; ++i) { + assert(pList[i]); + taosMemFree(pList[i]); + } +} + +} // namespace + +#if 1 + +#if 0 +TEST(PerfTest, GetSysAvail) { + char* caseName = "PerfTest:GetSysAvail"; + int32_t code = 0; + + int64_t msize = 1048576UL*10240; + char* p = (char*)taosMemMalloc(msize); + int64_t st = taosGetTimestampUs(); + memset(p, 0, msize); + int64_t totalUs = taosGetTimestampUs() - st; + printf("memset %" PRId64 " used time:%" PRId64 "us, speed:%dMB/ms\n", msize, totalUs, msize/1048576UL/(totalUs/1000UL)); + + int64_t freeSize = 0; + int32_t loopTimes = 1000000; + st = taosGetTimestampUs(); + int64_t lt = st; + for (int32_t i = 0; i < loopTimes; ++i) { + code = taosGetSysAvailMemory(&freeSize); + assert(0 == code); + //taosMsleep(1); + } + totalUs = taosGetTimestampUs() - st; + + printf("%d times getSysMemory total time:%" PRId64 "us, avg:%dus\n", loopTimes, totalUs, totalUs/loopTimes); +} +#endif + +#if 0 +TEST(MiscTest, monSysAvailSize) { + char* caseName = "MiscTest:monSysAvailSize"; + int32_t code = 0; + + int64_t freeSize = 0; + int32_t loopTimes = 1000000000; + for (int32_t i = 0; i < loopTimes; ++i) { + code = taosGetSysAvailMemory(&freeSize); + assert(0 == code); + printf(" %" PRId64, freeSize); + if (i && 0 == (i % 10)) { + struct tm Tm, *ptm; + struct timeval timeSecs; + + TAOS_UNUSED(taosGetTimeOfDay(&timeSecs)); + time_t curTime = timeSecs.tv_sec; + ptm = taosLocalTime(&curTime, &Tm, NULL, 0); + + printf("- %02d/%02d %02d:%02d:%02d.%06d \n", ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, (int32_t)timeSecs.tv_usec); + } + taosMsleep(1); + } +} +#endif + + +#if 0 +TEST(MiscTest, simNonPoolAct) { + char* caseName = "MiscTest:simNonPoolAct"; + int64_t msize = 1048576UL*1024, asize = 0; + int32_t loopTimes = 1000000; + + for (int32_t i = 0; i < loopTimes; ++i) { + asize = taosRand() % msize; + void* p = taosMemMalloc(asize); + mptWriteMem(p, asize); + + taosMsleep(100); + taosMemFree(p); + + printf("sim %dth alloc/free %" PRId64 " bytes\n", i, asize); + } +} +#endif + + +#if 0 +TEST(PerfTest, allocLatency) { + char* caseName = "PerfTest:allocLatency"; + int32_t code = 0; + + int64_t msize = 10; + void* pSession = NULL; + void* pJob = NULL; + + mptInitPool(); + + memset(mptCtx.jobCtxs, 0, sizeof(*mptCtx.jobCtxs)); + + assert(0 == taosMemPoolCallocJob(0, 0, (void**)&pJob)); + assert(0 == taosMemPoolInitSession(gMemPoolHandle, &pSession, pJob, "id")); + + int32_t loopTimes = 10000000; + int64_t st = 0; + void **addrList = (void**)taosMemCalloc(loopTimes, POINTER_BYTES); + + + // MALLOC + + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + addrList[i] = (char*)mptMemoryMalloc(msize); + } + int64_t totalUs3 = taosGetTimestampUs() - st; + mptFreeAddrList(addrList, loopTimes); + + + + + tsMemPoolFullFunc = 0; + mptEnableMemoryPoolUsage(gMemPoolHandle, pSession); + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + addrList[i] = (char*)mptMemoryMalloc(msize); + } + int64_t totalUs1 = taosGetTimestampUs() - st; + mptDisableMemoryPoolUsage(); + mptFreeAddrList(addrList, loopTimes); + + + tsMemPoolFullFunc = 1; + mptEnableMemoryPoolUsage(gMemPoolHandle, pSession); + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + addrList[i] = (char*)mptMemoryMalloc(msize); + } + int64_t totalUs2 = taosGetTimestampUs() - st; + mptDisableMemoryPoolUsage(); + mptFreeAddrList(addrList, loopTimes); + + + + + // CALLOC + + tsMemPoolFullFunc = 0; + mptEnableMemoryPoolUsage(gMemPoolHandle, pSession); + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + addrList[i] = (char*)mptMemoryCalloc(1, msize); + } + int64_t totalUs11 = taosGetTimestampUs() - st; + mptDisableMemoryPoolUsage(); + mptFreeAddrList(addrList, loopTimes); + + + tsMemPoolFullFunc = 1; + mptEnableMemoryPoolUsage(gMemPoolHandle, pSession); + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + addrList[i] = (char*)mptMemoryCalloc(1, msize); + } + int64_t totalUs12 = taosGetTimestampUs() - st; + mptDisableMemoryPoolUsage(); + mptFreeAddrList(addrList, loopTimes); + + + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + addrList[i] = (char*)mptMemoryCalloc(1, msize); + } + int64_t totalUs13 = taosGetTimestampUs() - st; + //mptFreeAddrList(addrList, loopTimes); NO FREE FOR REALLOC + + // REALLOC + + tsMemPoolFullFunc = 0; + mptEnableMemoryPoolUsage(gMemPoolHandle, pSession); + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + addrList[i] = (char*)mptMemoryRealloc(addrList[i], msize); + } + int64_t totalUs21 = taosGetTimestampUs() - st; + mptDisableMemoryPoolUsage(); + + + tsMemPoolFullFunc = 1; + mptEnableMemoryPoolUsage(gMemPoolHandle, pSession); + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + addrList[i] = (char*)mptMemoryRealloc(addrList[i], msize); + } + int64_t totalUs22 = taosGetTimestampUs() - st; + mptDisableMemoryPoolUsage(); + + + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + addrList[i] = (char*)mptMemoryRealloc(addrList[i], msize); + } + int64_t totalUs23 = taosGetTimestampUs() - st; + mptFreeAddrList(addrList, loopTimes); + + + // STRDUP + + tsMemPoolFullFunc = 0; + mptEnableMemoryPoolUsage(gMemPoolHandle, pSession); + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + addrList[i] = (char*)mptStrdup("abc"); + } + int64_t totalUs31 = taosGetTimestampUs() - st; + mptDisableMemoryPoolUsage(); + mptFreeAddrList(addrList, loopTimes); + + + tsMemPoolFullFunc = 1; + mptEnableMemoryPoolUsage(gMemPoolHandle, pSession); + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + addrList[i] = (char*)mptStrdup("abc"); + } + int64_t totalUs32 = taosGetTimestampUs() - st; + mptDisableMemoryPoolUsage(); + mptFreeAddrList(addrList, loopTimes); + + + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + addrList[i] = (char*)mptStrdup("abc"); + } + int64_t totalUs33 = taosGetTimestampUs() - st; + mptFreeAddrList(addrList, loopTimes); + + // STRNDUP + + tsMemPoolFullFunc = 0; + mptEnableMemoryPoolUsage(gMemPoolHandle, pSession); + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + addrList[i] = (char*)mptStrndup("abc", 3); + } + int64_t totalUs41 = taosGetTimestampUs() - st; + mptDisableMemoryPoolUsage(); + mptFreeAddrList(addrList, loopTimes); + + + tsMemPoolFullFunc = 1; + mptEnableMemoryPoolUsage(gMemPoolHandle, pSession); + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + addrList[i] = (char*)mptStrndup("abc", 3); + } + int64_t totalUs42 = taosGetTimestampUs() - st; + mptDisableMemoryPoolUsage(); + mptFreeAddrList(addrList, loopTimes); + + + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + addrList[i] = (char*)mptStrndup("abc", 3); + } + int64_t totalUs43 = taosGetTimestampUs() - st; + mptFreeAddrList(addrList, loopTimes); + + // ALIGNALLOC + + tsMemPoolFullFunc = 0; + mptEnableMemoryPoolUsage(gMemPoolHandle, pSession); + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + addrList[i] = (char*)mptMemoryMallocAlign(8, msize); + } + int64_t totalUs51 = taosGetTimestampUs() - st; + mptDisableMemoryPoolUsage(); + mptFreeAddrList(addrList, loopTimes); + + + tsMemPoolFullFunc = 1; + mptEnableMemoryPoolUsage(gMemPoolHandle, pSession); + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + addrList[i] = (char*)mptMemoryMallocAlign(8, msize); + } + int64_t totalUs52 = taosGetTimestampUs() - st; + mptDisableMemoryPoolUsage(); + mptFreeAddrList(addrList, loopTimes); + + + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + addrList[i] = (char*)mptMemoryMallocAlign(8, msize); + } + int64_t totalUs53 = taosGetTimestampUs() - st; + //mptFreeAddrList(addrList, loopTimes); NO FREE FOR GETSIZE + + + // GETSIZE + + tsMemPoolFullFunc = 0; + mptEnableMemoryPoolUsage(gMemPoolHandle, pSession); + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + mptMemorySize(addrList[i]); + } + int64_t totalUs61 = taosGetTimestampUs() - st; + mptDisableMemoryPoolUsage(); + + + tsMemPoolFullFunc = 1; + mptEnableMemoryPoolUsage(gMemPoolHandle, pSession); + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + mptMemorySize(addrList[i]); + } + int64_t totalUs62 = taosGetTimestampUs() - st; + mptDisableMemoryPoolUsage(); + + + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + mptMemorySize(addrList[i]); + } + int64_t totalUs63 = taosGetTimestampUs() - st; + + // FREE + + tsMemPoolFullFunc = 0; + mptEnableMemoryPoolUsage(gMemPoolHandle, pSession); + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + mptMemoryFree(addrList[i]); + } + int64_t totalUs71 = taosGetTimestampUs() - st; + mptDisableMemoryPoolUsage(); + + + for (int32_t i = 0; i < loopTimes; ++i) { + addrList[i] = (char*)mptMemoryMalloc(msize); + } + tsMemPoolFullFunc = 1; + mptEnableMemoryPoolUsage(gMemPoolHandle, pSession); + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + mptMemoryFree(addrList[i]); + } + int64_t totalUs72 = taosGetTimestampUs() - st; + mptDisableMemoryPoolUsage(); + + + for (int32_t i = 0; i < loopTimes; ++i) { + addrList[i] = (char*)mptMemoryMalloc(msize); + } + st = taosGetTimestampUs(); + for (int32_t i = 0; i < loopTimes; ++i) { + mptMemoryFree(addrList[i]); + } + int64_t totalUs73 = taosGetTimestampUs() - st; + + + printf("%d times each %" PRId64 " bytes, time consumed:\n" + "\tnon-fpool malloc total time:%" PRId64 "us, avg:%fus\n" + "\tfull-pool malloc total time:%" PRId64 "us, avg:%fus\n" + "\tdirect malloc total time:%" PRId64 "us, avg:%fus\n" + "\tnon-fpool calloc total time:%" PRId64 "us, avg:%fus\n" + "\tfull-pool calloc total time:%" PRId64 "us, avg:%fus\n" + "\tdirect calloc total time:%" PRId64 "us, avg:%fus\n" + "\tnon-fpool realloc total time:%" PRId64 "us, avg:%fus\n" + "\tfull-pool realloc total time:%" PRId64 "us, avg:%fus\n" + "\tdirect realloc total time:%" PRId64 "us, avg:%fus\n" + "\tnon-fpool strdup total time:%" PRId64 "us, avg:%fus\n" + "\tfull-pool strdup total time:%" PRId64 "us, avg:%fus\n" + "\tdirect strdup total time:%" PRId64 "us, avg:%fus\n" + "\tnon-fpool strndup total time:%" PRId64 "us, avg:%fus\n" + "\tfull-pool strndup total time:%" PRId64 "us, avg:%fus\n" + "\tdirect strndup total time:%" PRId64 "us, avg:%fus\n" + "\tnon-fpool alignal total time:%" PRId64 "us, avg:%fus\n" + "\tfull-pool alignal total time:%" PRId64 "us, avg:%fus\n" + "\tdirect alignal total time:%" PRId64 "us, avg:%fus\n" + "\tnon-fpool getsize total time:%" PRId64 "us, avg:%fus\n" + "\tfull-pool getsize total time:%" PRId64 "us, avg:%fus\n" + "\tdirect getsize total time:%" PRId64 "us, avg:%fus\n" + "\tnon-fpool free total time:%" PRId64 "us, avg:%fus\n" + "\tfull-pool free total time:%" PRId64 "us, avg:%fus\n" + "\tdirect free total time:%" PRId64 "us, avg:%fus\n", + loopTimes, msize, + totalUs1, ((double)totalUs1)/loopTimes, totalUs2, ((double)totalUs2)/loopTimes, totalUs3, ((double)totalUs3)/loopTimes, + totalUs11, ((double)totalUs11)/loopTimes, totalUs12, ((double)totalUs12)/loopTimes, totalUs13, ((double)totalUs13)/loopTimes, + totalUs21, ((double)totalUs21)/loopTimes, totalUs22, ((double)totalUs22)/loopTimes, totalUs23, ((double)totalUs23)/loopTimes, + totalUs31, ((double)totalUs31)/loopTimes, totalUs32, ((double)totalUs32)/loopTimes, totalUs33, ((double)totalUs33)/loopTimes, + totalUs41, ((double)totalUs41)/loopTimes, totalUs42, ((double)totalUs42)/loopTimes, totalUs43, ((double)totalUs43)/loopTimes, + totalUs51, ((double)totalUs51)/loopTimes, totalUs52, ((double)totalUs52)/loopTimes, totalUs53, ((double)totalUs53)/loopTimes, + totalUs61, ((double)totalUs61)/loopTimes, totalUs62, ((double)totalUs62)/loopTimes, totalUs63, ((double)totalUs63)/loopTimes, + totalUs71, ((double)totalUs71)/loopTimes, totalUs72, ((double)totalUs72)/loopTimes, totalUs73, ((double)totalUs73)/loopTimes); +} +#endif + + +#if 0 +TEST(poolFuncTest, SingleThreadTest) { + char* caseName = "poolFuncTest:SingleThreadTest"; + SMPTestParam param = {0}; + param.reserveMode = true; + param.threadNum = 1; + param.jobQuota = 1024; + param.enableMemPool = true; + + tsMemPoolFullFunc = 0; + + mptPrintTestBeginInfo(caseName, ¶m); + + for (int32_t i = 0; i < mptCtrl.caseLoopTimes; ++i) { + mptRunCase(¶m, i); + } + +} +#endif +#if 0 +TEST(poolFuncTest, MultiThreadTest) { + char* caseName = "poolFuncTest:MultiThreadTest"; + SMPTestParam param = {0}; + param.reserveMode = true; + param.threadNum = 6; + param.jobQuota = 1024; + param.randTask = true; + param.enableMemPool = true; + + tsMemPoolFullFunc = 0; + + mptPrintTestBeginInfo(caseName, ¶m); + + for (int32_t i = 0; i < mptCtrl.caseLoopTimes; ++i) { + mptRunCase(¶m, i); + } + +} +#endif + +#if 0 +TEST(poolFullFuncTest, SingleThreadTest) { + char* caseName = "poolFullFuncTest:SingleThreadTest"; + SMPTestParam param = {0}; + param.reserveMode = true; + param.threadNum = 1; + param.jobQuota = 1024; + param.enableMemPool = true; + + tsMemPoolFullFunc = 1; + + mptPrintTestBeginInfo(caseName, ¶m); + + for (int32_t i = 0; i < mptCtrl.caseLoopTimes; ++i) { + mptRunCase(¶m, i); + } + +} +#endif +#if 0 +TEST(poolFullFuncTest, MultiThreadTest) { + char* caseName = "poolFullFuncTest:MultiThreadTest"; + SMPTestParam param = {0}; + param.reserveMode = true; + param.threadNum = 6; + param.jobQuota = 1024; + param.randTask = true; + param.enableMemPool = true; + + tsMemPoolFullFunc = 1; + + mptPrintTestBeginInfo(caseName, ¶m); + + for (int32_t i = 0; i < mptCtrl.caseLoopTimes; ++i) { + mptRunCase(¶m, i); + } + +} +#endif + + +#if 0 +TEST(DisablePoolFuncTest, MultiThreadTest) { + char* caseName = "FuncTest:MultiThreadTest"; + SMPTestParam param = {0}; + param.reserveMode = true; + param.threadNum = 6; + param.jobQuota = 1024; + param.randTask = true; + param.enableMemPool = false; + + mptPrintTestBeginInfo(caseName, ¶m); + + for (int32_t i = 0; i < mptCtrl.caseLoopTimes; ++i) { + mptRunCase(¶m, i); + } + +} +#endif + + + + +#endif + + + + + + + + + + + +int main(int argc, char** argv) { + taosSeedRand(taosGetTimestampSec()); + mptInit(); + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + + + +#pragma GCC diagnosti diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task index f70bfc804d..c5461aee00 100644 --- a/tests/parallel_test/cases.task +++ b/tests/parallel_test/cases.task @@ -398,6 +398,7 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/subscribe_stream_privilege.py ,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/empty_identifier.py ,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/persisit_config.py +,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/qmemCtrl.py ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/composite_primary_key_create.py diff --git a/tests/pytest/util/dnodes.py b/tests/pytest/util/dnodes.py index 8d048825d0..2c2e11cfcc 100644 --- a/tests/pytest/util/dnodes.py +++ b/tests/pytest/util/dnodes.py @@ -48,7 +48,8 @@ class TDSimClient: "telemetryReporting": "0", "tqDebugflag": "135", "stDebugflag":"135", - "safetyCheckLevel":"2" + "safetyCheckLevel":"2", + "minReservedMemorySize":"1024" } def getLogDir(self): @@ -889,4 +890,4 @@ class TDDnodes: def getAsan(self): return self.asan -tdDnodes = TDDnodes() \ No newline at end of file +tdDnodes = TDDnodes() diff --git a/tests/script/api/asyncQuery.c b/tests/script/api/asyncQuery.c new file mode 100644 index 0000000000..d53cd23b4b --- /dev/null +++ b/tests/script/api/asyncQuery.c @@ -0,0 +1,131 @@ +// sample code to verify multiple queries with the same reqid +// to compile: gcc -o sameReqdiTest sameReqidTest.c -ltaos + +#include +#include +#include +#include +#include "taos.h" + +#define CONST_REQ_ID 12345 +#define TEST_DB "db1" + +#define CHECK_CONDITION(condition, prompt, errstr) \ + do { \ + if (!(condition)) { \ + printf("\033[31m[%s:%d] failed to " prompt ", reason: %s\033[0m\n", __func__, __LINE__, errstr); \ + exit(EXIT_FAILURE); \ + } \ + } while (0) + +#define CHECK_RES(res, prompt) CHECK_CONDITION(taos_errno(res) == 0, prompt, taos_errstr(res)) +#define CHECK_CODE(code, prompt) CHECK_CONDITION(code == 0, prompt, taos_errstr(NULL)) + +int64_t errTimes = 0, finQueries = 0; + +static TAOS* getNewConnection() { + const char* host = "127.0.0.1"; + const char* user = "root"; + const char* passwd = "taosdata"; + TAOS* taos = NULL; + + taos_options(TSDB_OPTION_TIMEZONE, "GMT-8"); + taos = taos_connect(host, user, passwd, "", 0); + CHECK_CONDITION(taos != NULL, "connect to db", taos_errstr(NULL)); + return taos; +} + +static int32_t printResult(TAOS_RES* res, int32_t nlimit) { + TAOS_ROW row = NULL; + TAOS_FIELD* fields = NULL; + int32_t numFields = 0; + int32_t nRows = 0; + + numFields = taos_num_fields(res); + fields = taos_fetch_fields(res); + while ((nlimit-- > 0) && (row = taos_fetch_row(res))) { + nRows++; + } + return nRows; +} + +void retrieveCallback(void* param, TAOS_RES* res, int32_t nrows) { + if (nrows < 0) { + taos_free_result(res); + atomic_add_fetch_64(&finQueries, 1); + atomic_add_fetch_64(&errTimes, 1); + } else if (nrows == 0) { + taos_free_result(res); + atomic_add_fetch_64(&finQueries, 1); + } else { + printResult(res, nrows); + taos_fetch_rows_a(res, retrieveCallback, param); + } +} + +void selectCallback(void* param, TAOS_RES* res, int32_t code) { + if (code) { + atomic_add_fetch_64(&errTimes, 1); + taos_free_result(res); + atomic_add_fetch_64(&finQueries, 1); + return; + } + taos_fetch_rows_a(res, retrieveCallback, param); +} + + +#if 0 +static void verifyQueryAsync(TAOS* taos) { + taos_query_a(taos, "select * from (select cast(count(*) as binary(100)) a, rand() b from tbx where ts >= '2023-01-01' and ts <= '2024-12-01' interval(1s) fill(value, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')) t1 group by t1.a, t1.b;;", selectCallback, NULL); + taos_query_a(taos, "select * from (select cast(count(*) as binary(100)) a, rand() b from tbx where ts >= '2023-01-01' and ts <= '2024-12-01' interval(1s) fill(value, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')) t1 group by t1.a, t1.b;;", selectCallback, NULL); + taos_query_a(taos, "select * from (select cast(count(*) as binary(100)) a, rand() b from tbx where ts >= '2023-01-01' and ts <= '2024-12-01' interval(1s) fill(value, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')) t1 group by t1.a, t1.b;;", selectCallback, NULL); + taos_query_a(taos, "select * from (select cast(count(*) as binary(100)) a, rand() b from tbx where ts >= '2023-01-01' and ts <= '2024-12-01' interval(1s) fill(value, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')) t1 group by t1.a, t1.b;;", selectCallback, NULL); + taos_query_a(taos, "select * from (select cast(count(*) as binary(100)) a, rand() b from tbx where ts >= '2023-01-01' and ts <= '2024-12-01' interval(1s) fill(value, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')) t1 group by t1.a, t1.b;;", selectCallback, NULL); + taos_query_a(taos, "select * from (select cast(count(*) as binary(100)) a, rand() b from tbx where ts >= '2023-01-01' and ts <= '2024-12-01' interval(1s) fill(value, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')) t1 group by t1.a, t1.b;;", selectCallback, NULL); + taos_query_a(taos, "select * from (select cast(count(*) as binary(100)) a, rand() b from tbx where ts >= '2023-01-01' and ts <= '2024-12-01' interval(1s) fill(value, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')) t1 group by t1.a, t1.b;;", selectCallback, NULL); + taos_query_a(taos, "select * from (select cast(count(*) as binary(100)) a, rand() b from tbx where ts >= '2023-01-01' and ts <= '2024-12-01' interval(1s) fill(value, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')) t1 group by t1.a, t1.b;;", selectCallback, NULL); + taos_query_a(taos, "select * from (select cast(count(*) as binary(100)) a, rand() b from tbx where ts >= '2023-01-01' and ts <= '2024-12-01' interval(1s) fill(value, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')) t1 group by t1.a, t1.b;;", selectCallback, NULL); + taos_query_a(taos, "select twa(c1) from stb interval(10s);", selectCallback, NULL); +} +#else +static void verifyQueryAsync(TAOS* taos) { + taos_query_a(taos, "select * from (select cast(count(*) as binary(100)) a, rand() b from tbx where ts >= '2024-11-01' and ts <= '2024-12-01' interval(1m) fill(value, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')) t1 group by t1.a, t1.b;", selectCallback, NULL); + taos_query_a(taos, "select * from (select cast(count(*) as binary(100)) a, rand() b from tbx where ts >= '2024-11-01' and ts <= '2024-12-01' interval(1m) fill(value, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')) t1 group by t1.a, t1.b;", selectCallback, NULL); + taos_query_a(taos, "select * from (select cast(count(*) as binary(100)) a, rand() b from tbx where ts >= '2024-11-01' and ts <= '2024-12-01' interval(1m) fill(value, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')) t1 group by t1.a, t1.b;", selectCallback, NULL); + taos_query_a(taos, "select * from (select cast(count(*) as binary(100)) a, rand() b from tbx where ts >= '2024-11-01' and ts <= '2024-12-01' interval(1m) fill(value, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')) t1 group by t1.a, t1.b;", selectCallback, NULL); + taos_query_a(taos, "select * from (select cast(count(*) as binary(100)) a, rand() b from tbx where ts >= '2024-11-01' and ts <= '2024-12-01' interval(1m) fill(value, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')) t1 group by t1.a, t1.b;", selectCallback, NULL); + taos_query_a(taos, "select * from (select cast(count(*) as binary(100)) a, rand() b from tbx where ts >= '2024-11-01' and ts <= '2024-12-01' interval(1m) fill(value, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')) t1 group by t1.a, t1.b;", selectCallback, NULL); + taos_query_a(taos, "select * from (select cast(count(*) as binary(100)) a, rand() b from tbx where ts >= '2024-11-01' and ts <= '2024-12-01' interval(1m) fill(value, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')) t1 group by t1.a, t1.b;", selectCallback, NULL); + taos_query_a(taos, "select * from (select cast(count(*) as binary(100)) a, rand() b from tbx where ts >= '2024-11-01' and ts <= '2024-12-01' interval(1m) fill(value, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')) t1 group by t1.a, t1.b;", selectCallback, NULL); + taos_query_a(taos, "select * from (select cast(count(*) as binary(100)) a, rand() b from tbx where ts >= '2024-11-01' and ts <= '2024-12-01' interval(1m) fill(value, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')) t1 group by t1.a, t1.b;", selectCallback, NULL); + taos_query_a(taos, "select twa(c1) from tbx interval(10s);", selectCallback, NULL); +} +#endif + +int main(int argc, char* argv[]) { + TAOS* taos = NULL; + int32_t code = 0; + + taos = getNewConnection(); + taos_select_db(taos, TEST_DB); + CHECK_CODE(code, "switch to database"); + + printf("************ prepare data *************\n"); + + //create table tbx (ts timestamp, f1 int); insert into tbx values('2024-11-11 00:00:00', 1); + + for (int64_t i = 0; i < 1000000000; ++i) { + verifyQueryAsync(taos); + printf("%llu queries launched, errTimes:%lld \n", i * 10, errTimes); + while ((i * 10 - atomic_load_64(&finQueries)) > 100) { + printf("left queries:%llu\n", (i * 10 - atomic_load_64(&finQueries))); + taosMsleep(2000); + } + printf("\n"); + } + + taos_close(taos); + taos_cleanup(); + + return 0; +} diff --git a/tests/script/api/makefile b/tests/script/api/makefile index ce5980b37a..b871c5f3ff 100644 --- a/tests/script/api/makefile +++ b/tests/script/api/makefile @@ -22,6 +22,7 @@ exe: gcc $(CFLAGS) ./insert_stb.c -o $(ROOT)insert_stb $(LFLAGS) gcc $(CFLAGS) ./tmqViewTest.c -o $(ROOT)tmqViewTest $(LFLAGS) gcc $(CFLAGS) ./stmtQuery.c -o $(ROOT)stmtQuery $(LFLAGS) + gcc $(CFLAGS) ./asyncQuery.c -o $(ROOT)asyncQuery $(LFLAGS) # gcc $(CFLAGS) ./stmt.c -o $(ROOT)stmt $(LFLAGS) # gcc $(CFLAGS) ./stmt2.c -o $(ROOT)stmt2 $(LFLAGS) # gcc $(CFLAGS) ./stmt2-example.c -o $(ROOT)stmt2-example $(LFLAGS) diff --git a/tests/script/api/stmt2-performance.c b/tests/script/api/stmt2-performance.c new file mode 100644 index 0000000000..a0ab7f5e0d --- /dev/null +++ b/tests/script/api/stmt2-performance.c @@ -0,0 +1,171 @@ +#include +#include +#include +#include +#include +#include "taos.h" + +int CTB_NUMS = 10; +int ROW_NUMS = 2; + +void do_query(TAOS* taos, const char* sql) { + TAOS_RES* result = taos_query(taos, sql); + int code = taos_errno(result); + if (code) { + printf("failed to query: %s, reason:%s\n", sql, taos_errstr(result)); + taos_free_result(result); + return; + } + taos_free_result(result); +} + +void do_stmt(TAOS* taos, const char* sql) { + do_query(taos, "drop database if exists db"); + do_query(taos, "create database db"); + do_query(taos, "create table db.stb (ts timestamp, b binary(10)) tags(t1 int, t2 binary(10))"); + + TAOS_STMT2_OPTION option = {0, true, true, NULL, NULL}; + + TAOS_STMT2* stmt = taos_stmt2_init(taos, &option); + int code = taos_stmt2_prepare(stmt, sql, 0); + if (code != 0) { + printf("failed to execute taos_stmt2_prepare. error:%s\n", taos_stmt2_error(stmt)); + taos_stmt2_close(stmt); + return; + } + int fieldNum = 0; + TAOS_FIELD_STB* pFields = NULL; + code = taos_stmt2_get_stb_fields(stmt, &fieldNum, &pFields); + if (code != 0) { + printf("failed get col,ErrCode: 0x%x, ErrMessage: %s.\n", code, taos_stmt2_error(stmt)); + } else { + printf("col nums:%d\n", fieldNum); + for (int i = 0; i < fieldNum; i++) { + printf("field[%d]: %s, data_type:%d, field_type:%d\n", i, pFields[i].name, pFields[i].type, + pFields[i].field_type); + } + } + + // tbname + char** tbs = (char**)malloc(CTB_NUMS * sizeof(char*)); + for (int i = 0; i < CTB_NUMS; i++) { + tbs[i] = (char*)malloc(sizeof(char) * 20); + sprintf(tbs[i], "ctb_%d", i); + // char* tmp=(char*)malloc(sizeof(char) * 100); + // sprintf(tmp, "create table db.%s using db.stb tags(0, 'abc')", tbs[i]); + // do_query(taos, tmp); + } + // col params + int64_t** ts = (int64_t**)malloc(CTB_NUMS * sizeof(int64_t*)); + char** b = (char**)malloc(CTB_NUMS * sizeof(char*)); + int* ts_len = (int*)malloc(ROW_NUMS * sizeof(int)); + int* b_len = (int*)malloc(ROW_NUMS * sizeof(int)); + for (int i = 0; i < ROW_NUMS; i++) { + ts_len[i] = sizeof(int64_t); + b_len[i] = 1; + } + for (int i = 0; i < CTB_NUMS; i++) { + ts[i] = (int64_t*)malloc(ROW_NUMS * sizeof(int64_t)); + b[i] = (char*)malloc(ROW_NUMS * sizeof(char)); + for (int j = 0; j < ROW_NUMS; j++) { + ts[i][j] = 1591060628000 + j; + b[i][j] = 'a' + j; + } + } + // tag params + int t1 = 0; + int t1len = sizeof(int); + int t2len = 3; + // TAOS_STMT2_BIND* tagv[2] = {&tags[0][0], &tags[1][0]}; + + clock_t start, end; + double cpu_time_used; + + // bind params + TAOS_STMT2_BIND** paramv = (TAOS_STMT2_BIND**)malloc(CTB_NUMS * sizeof(TAOS_STMT2_BIND*)); + TAOS_STMT2_BIND** tags = (TAOS_STMT2_BIND**)malloc(CTB_NUMS * sizeof(TAOS_STMT2_BIND*)); + for (int i = 0; i < CTB_NUMS; i++) { + // create tags + tags[i] = (TAOS_STMT2_BIND*)malloc(2 * sizeof(TAOS_STMT2_BIND)); + tags[i][0] = (TAOS_STMT2_BIND){TSDB_DATA_TYPE_INT, &t1, &t1len, NULL, 0}; + tags[i][1] = (TAOS_STMT2_BIND){TSDB_DATA_TYPE_BINARY, "after", &t2len, NULL, 0}; + + // create col params + paramv[i] = (TAOS_STMT2_BIND*)malloc(2 * sizeof(TAOS_STMT2_BIND)); + paramv[i][0] = (TAOS_STMT2_BIND){TSDB_DATA_TYPE_TIMESTAMP, &ts[i][0], &ts_len[0], NULL, ROW_NUMS}; + paramv[i][1] = (TAOS_STMT2_BIND){TSDB_DATA_TYPE_BINARY, &b[i][0], &b_len[0], NULL, ROW_NUMS}; + } + // bind + start = clock(); + TAOS_STMT2_BINDV bindv = {CTB_NUMS, tbs, tags, paramv}; + if (taos_stmt2_bind_param(stmt, &bindv, -1)) { + printf("failed to execute taos_stmt2_bind_param statement.error:%s\n", taos_stmt2_error(stmt)); + taos_stmt2_close(stmt); + return; + } + end = clock(); + cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC; + printf("stmt2-bind [%s] insert Time used: %f seconds\n", sql, cpu_time_used); + start = clock(); + // exec + if (taos_stmt2_exec(stmt, NULL)) { + printf("failed to execute taos_stmt2_exec statement.error:%s\n", taos_stmt2_error(stmt)); + taos_stmt2_close(stmt); + return; + } + end = clock(); + cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC; + printf("stmt2-exec [%s] insert Time used: %f seconds\n", sql, cpu_time_used); + + taos_stmt2_free_fields(stmt, pFields); + taos_stmt2_close(stmt); +} + +void do_taosc(TAOS* taos) { + do_query(taos, "drop database if exists testdb"); + do_query(taos, "create database testdb"); + do_query(taos, "create table testdb.stb (ts timestamp, b binary(10)) tags(t1 int, t2 binary(10))"); + int64_t* ts = (int64_t*)malloc(CTB_NUMS * sizeof(int64_t)); + char** tbs = (char**)malloc(CTB_NUMS * sizeof(char*)); + for (int i = 0; i < CTB_NUMS; i++) { + tbs[i] = (char*)malloc(sizeof(char) * 10); + } + clock_t start, end; + double cpu_time_used; + char* tsc_sql = malloc(sizeof(char) * 1000000); + sprintf(tsc_sql, "insert into testdb.stb(tbname,ts,b,t1,t2) values"); + + for (int j = 0; j < ROW_NUMS; j++) { + for (int i = 0; i < CTB_NUMS; i++) { + ts[i] = 1591060628000 + i + j * CTB_NUMS; + snprintf(tbs[i], sizeof(tbs[i]), "ctb_%d", i + j * CTB_NUMS); + if (i == CTB_NUMS - 1 && j == ROW_NUMS - 1) { + sprintf(tsc_sql + strlen(tsc_sql), "('%s',%lld,'abc',0,'after')", tbs[i], ts[i]); + } else { + sprintf(tsc_sql + strlen(tsc_sql), "('%s',%lld,'abc'0,'after'),", tbs[i], ts[i]); + } + } + } + + start = clock(); + // printf("%s", tsc_sql); + taos_query(taos, tsc_sql); + end = clock(); + cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC; + printf("taosc insert Time used: %f seconds\n", cpu_time_used); +} + +int main() { + TAOS* taos = taos_connect("localhost", "root", "taosdata", "", 0); + if (!taos) { + printf("failed to connect to db, reason:%s\n", taos_errstr(taos)); + exit(1); + } + + // sleep(3); + do_stmt(taos, "insert into db.stb(tbname,ts,b,t1,t2) values(?,?,?,?,?)"); + do_stmt(taos, "insert into db.? using db.stb tags(?,?)values(?,?)"); + // do_taosc(taos); + taos_close(taos); + taos_cleanup(); +} diff --git a/tests/script/test.sh b/tests/script/test.sh index b10865dd65..26c01a6c09 100755 --- a/tests/script/test.sh +++ b/tests/script/test.sh @@ -111,6 +111,7 @@ echo "wal 0" >> $TAOS_CFG echo "asyncLog 0" >> $TAOS_CFG echo "locale en_US.UTF-8" >> $TAOS_CFG echo "enableCoreFile 1" >> $TAOS_CFG +echo "minReservedMemorySize 1024" >> $TAOS_CFG echo " " >> $TAOS_CFG ulimit -n 600000 diff --git a/tests/system-test/0-others/qmemCtrl.py b/tests/system-test/0-others/qmemCtrl.py new file mode 100644 index 0000000000..2aacc2c6ed --- /dev/null +++ b/tests/system-test/0-others/qmemCtrl.py @@ -0,0 +1,134 @@ +################################################################### +# Copyright (c) 2016 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- + +import re +from util.log import * +from util.cases import * +from util.sql import * +from util.common import * +from util.sqlset import * + +class TDTestCase: + updatecfgDict = {'queryUseMemoryPool':'true','minReservedMemorySize':1025, 'singleQueryMaxMemorySize': 0} + def init(self, conn, logSql, replicaVar=1): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor()) + self.setsql = TDSetSql() + self.perf_param_list = ['apps','connections','consumers','queries','trans'] + self.dbname = "db" + self.vgroups = 4 + self.stbname = f'`{tdCom.getLongName(5)}`' + self.tbname = f'`{tdCom.getLongName(3)}`' + self.db_param = { + "database":f"{self.dbname}", + "buffer":100, + "vgroups":self.vgroups, + "stt_trigger":1, + "tsdb_pagesize":16 + } + + def update_cfg(self, use_mpool = 1, min_rsize = 0, single_msize = 0): + updatecfgDict = {'queryUseMemoryPool':f'{use_mpool}','minReservedMemorySize': min_rsize, 'singleQueryMaxMemorySize': single_msize} + tdDnodes.stop(1) + tdDnodes.deploy(1, updatecfgDict) + tdDnodes.starttaosd(1) + + def alter_cfg(self, use_mpool = 1, min_rsize = 0, single_msize = 0): + tdSql.error(f"alter dnode 1 'queryUseMemoryPool' '{use_mpool}'") + tdSql.error(f"alter dnode 1 'minReservedMemorySize' '{min_rsize}'") + tdSql.error(f"alter dnode 1 'singleQueryMaxMemorySize' '{single_msize}'") + + def variables_check(self, err_case = 0, use_mpool = 1, min_rsize = 0, single_msize = 0): + if err_case == 1: + tdSql.error("show dnode 1 variables like 'queryUseMemoryPool'") + else: + tdSql.query("show dnode 1 variables like 'queryUseMemoryPool'") + tdSql.checkRows(1) + tdSql.checkData(0, 0, 1) + tdSql.checkData(0, 1, 'queryUseMemoryPool') + tdSql.checkData(0, 2, use_mpool) + + if err_case == 1: + tdSql.error("show dnode 1 variables like 'minReservedMemorySize'") + else: + tdSql.query("show dnode 1 variables like 'minReservedMemorySize'") + tdSql.checkRows(1) + tdSql.checkData(0, 0, 1) + tdSql.checkData(0, 1, 'minReservedMemorySize') + tdSql.checkData(0, 2, min_rsize) + + if err_case == 1: + tdSql.error("show dnode 1 variables like 'singleQueryMaxMemorySize'") + else: + tdSql.query("show dnode 1 variables like 'singleQueryMaxMemorySize'") + tdSql.checkRows(1) + tdSql.checkData(0, 0, 1) + tdSql.checkData(0, 1, 'singleQueryMaxMemorySize') + tdSql.checkData(0, 2, single_msize) + + + def cfg_check(self): + tdLog.info(f'[disable pool] start') + self.update_cfg(0, 1024, 0) + self.variables_check(0, 0, 1024, 0) + + tdLog.info(f'[enable pool + up limit] start') + self.update_cfg(1, 1024, 1000000000) + self.variables_check(0, 1, 1024, 1000000000) + + tdLog.info(f'[enable pool + reserve limit] start') + self.update_cfg(1, 1000000000, 3000) + self.variables_check(0, 1, 1000000000, 3000) + + tdLog.info(f'[enable pool + out of reserve] start') + self.update_cfg(1, 1000000001) + self.variables_check(1) + + tdLog.info(f'[enable pool + out of single] start') + self.update_cfg(1, 1000, 1000000001) + self.variables_check(1) + + tdLog.info(f'[out of pool] start') + self.update_cfg(2) + self.variables_check(1) + + def alter_check(self): + tdLog.info(f'[alter] start') + self.update_cfg(1, 1024, 0) + self.alter_cfg(1, 1024, 0); + + def single_up_check(self): + tdLog.info(f'[low single] start') + self.update_cfg(1, 1024, 1) + tdSql.error("select *, repeat('aaaaaaaaaa',1000) from information_schema.ins_tables") + + tdLog.info(f'[normal single] start') + self.update_cfg(1, 1024, 100) + tdSql.query("select *, repeat('aaaaaaaaaa',1000) from information_schema.ins_tables") + + def too_big_reserve(self): + tdLog.info(f'[too big reserve] start') + self.update_cfg(1, 1024000) + + def run(self): + self.cfg_check() + self.alter_check() + self.single_up_check() + self.too_big_reserve() + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase())