TDengine/source/libs/stream/src/streamMeta.c

1643 lines
51 KiB
C
Raw Normal View History

2022-08-02 14:23:33 +00:00
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "executor.h"
#include "streamBackendRocksdb.h"
2023-07-05 07:55:55 +00:00
#include "streamInt.h"
2023-08-26 08:13:17 +00:00
#include "tmisce.h"
2023-05-05 08:32:33 +00:00
#include "tref.h"
2023-11-08 06:14:01 +00:00
#include "tsched.h"
#include "tstream.h"
#include "ttimer.h"
2023-10-02 18:37:52 +00:00
#include "wal.h"
static TdThreadOnce streamMetaModuleInit = PTHREAD_ONCE_INIT;
2023-08-26 09:37:09 +00:00
int32_t streamBackendId = 0;
int32_t streamBackendCfWrapperId = 0;
int32_t streamMetaId = 0;
2023-10-11 12:26:19 +00:00
int32_t taskDbWrapperId = 0;
2023-06-16 02:00:16 +00:00
2023-08-28 08:13:27 +00:00
static void metaHbToMnode(void* param, void* tmrId);
static int32_t streamMetaBegin(SStreamMeta* pMeta);
static void streamMetaCloseImpl(void* arg);
2023-08-26 13:54:36 +00:00
typedef struct {
TdThreadMutex mutex;
SHashObj* pTable;
2023-08-28 08:13:27 +00:00
} SMetaRefMgt;
2023-09-15 01:25:22 +00:00
struct SMetaHbInfo {
tmr_h hbTmr;
int32_t stopFlag;
int32_t tickCounter;
int32_t hbCount;
int64_t hbStart;
2023-09-15 01:25:22 +00:00
};
2024-01-15 03:28:36 +00:00
typedef struct STaskInitTs {
int64_t start;
int64_t end;
bool success;
} STaskInitTs;
2023-08-28 08:13:27 +00:00
SMetaRefMgt gMetaRefMgt;
void metaRefMgtInit();
void metaRefMgtCleanup();
int32_t metaRefMgtAdd(int64_t vgId, int64_t* rid);
2023-08-26 13:54:36 +00:00
2023-06-16 02:00:16 +00:00
static void streamMetaEnvInit() {
2023-06-15 13:29:52 +00:00
streamBackendId = taosOpenRef(64, streamBackendCleanup);
2023-06-16 01:32:38 +00:00
streamBackendCfWrapperId = taosOpenRef(64, streamBackendHandleCleanup);
taskDbWrapperId = taosOpenRef(64, taskDbDestroy2);
2023-08-26 09:37:09 +00:00
streamMetaId = taosOpenRef(64, streamMetaCloseImpl);
2023-08-26 13:54:36 +00:00
2023-08-28 08:13:27 +00:00
metaRefMgtInit();
2024-01-09 01:13:53 +00:00
streamTimerInit();
2023-06-15 13:29:52 +00:00
}
2023-05-11 06:37:57 +00:00
void streamMetaInit() { taosThreadOnce(&streamMetaModuleInit, streamMetaEnvInit);}
2023-06-15 13:29:52 +00:00
void streamMetaCleanup() {
taosCloseRef(streamBackendId);
2023-06-16 01:32:38 +00:00
taosCloseRef(streamBackendCfWrapperId);
2023-08-26 09:37:09 +00:00
taosCloseRef(streamMetaId);
2023-08-26 13:54:36 +00:00
2023-08-28 08:13:27 +00:00
metaRefMgtCleanup();
2024-01-09 01:13:53 +00:00
streamTimerCleanUp();
2023-08-28 08:13:27 +00:00
}
2023-08-26 13:54:36 +00:00
2023-08-29 01:52:03 +00:00
void metaRefMgtInit() {
taosThreadMutexInit(&(gMetaRefMgt.mutex), NULL);
gMetaRefMgt.pTable = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_ENTRY_LOCK);
}
2023-08-28 08:13:27 +00:00
void metaRefMgtCleanup() {
void* pIter = taosHashIterate(gMetaRefMgt.pTable, NULL);
2023-08-26 13:54:36 +00:00
while (pIter) {
SArray* list = *(SArray**)pIter;
for (int i = 0; i < taosArrayGetSize(list); i++) {
void* rid = taosArrayGetP(list, i);
taosMemoryFree(rid);
}
taosArrayDestroy(list);
2023-08-28 08:13:27 +00:00
pIter = taosHashIterate(gMetaRefMgt.pTable, pIter);
2023-08-26 13:54:36 +00:00
}
2023-08-28 08:13:27 +00:00
taosHashCleanup(gMetaRefMgt.pTable);
taosThreadMutexDestroy(&gMetaRefMgt.mutex);
2023-08-26 13:54:36 +00:00
}
2023-08-28 08:13:27 +00:00
int32_t metaRefMgtAdd(int64_t vgId, int64_t* rid) {
taosThreadMutexLock(&gMetaRefMgt.mutex);
void* p = taosHashGet(gMetaRefMgt.pTable, &vgId, sizeof(vgId));
2023-08-26 13:54:36 +00:00
if (p == NULL) {
SArray* list = taosArrayInit(8, sizeof(void*));
taosArrayPush(list, &rid);
2023-08-28 08:13:27 +00:00
taosHashPut(gMetaRefMgt.pTable, &vgId, sizeof(vgId), &list, sizeof(void*));
2023-08-26 13:54:36 +00:00
} else {
SArray* list = *(SArray**)p;
taosArrayPush(list, &rid);
}
2023-08-28 08:13:27 +00:00
taosThreadMutexUnlock(&gMetaRefMgt.mutex);
2023-08-26 13:54:36 +00:00
return 0;
2023-06-15 13:29:52 +00:00
}
2023-05-11 06:37:57 +00:00
2023-09-20 12:53:58 +00:00
typedef struct {
int64_t chkpId;
char* path;
char* taskId;
SArray* pChkpSave;
SArray* pChkpInUse;
int8_t chkpCap;
void* backend;
} StreamMetaTaskState;
int32_t streamMetaOpenTdb(SStreamMeta* pMeta) {
if (tdbOpen(pMeta->path, 16 * 1024, 1, &pMeta->db, 0) < 0) {
return -1;
// goto _err;
}
if (tdbTbOpen("task.db", STREAM_TASK_KEY_LEN, -1, NULL, pMeta->db, &pMeta->pTaskDb, 0) < 0) {
return -1;
}
if (tdbTbOpen("checkpoint.db", sizeof(int32_t), -1, NULL, pMeta->db, &pMeta->pCheckpointDb, 0) < 0) {
return -1;
}
return 0;
}
//
// impl later
//
enum STREAM_STATE_VER {
STREAM_STATA_NO_COMPATIBLE,
STREAM_STATA_COMPATIBLE,
STREAM_STATA_NEED_CONVERT,
};
2023-09-22 12:51:29 +00:00
int32_t streamMetaCheckBackendCompatible(SStreamMeta* pMeta) {
2023-09-21 09:41:30 +00:00
int8_t ret = STREAM_STATA_COMPATIBLE;
TBC* pCur = NULL;
2023-09-20 12:53:58 +00:00
if (tdbTbcOpen(pMeta->pTaskDb, &pCur, NULL) < 0) {
// no task info, no stream
2023-09-21 09:41:30 +00:00
return ret;
2023-09-20 12:53:58 +00:00
}
2023-09-21 09:41:30 +00:00
void* pKey = NULL;
int32_t kLen = 0;
void* pVal = NULL;
int32_t vLen = 0;
2023-09-20 12:53:58 +00:00
tdbTbcMoveToFirst(pCur);
while (tdbTbcNext(pCur, &pKey, &kLen, &pVal, &vLen) == 0) {
if (pVal == NULL || vLen == 0) {
break;
}
2023-09-21 09:41:30 +00:00
SDecoder decoder;
2023-09-20 12:53:58 +00:00
SCheckpointInfo info;
tDecoderInit(&decoder, (uint8_t*)pVal, vLen);
if (tDecodeStreamTaskChkInfo(&decoder, &info) < 0) {
continue;
}
2023-09-21 09:41:30 +00:00
if (info.msgVer <= SSTREAM_TASK_INCOMPATIBLE_VER) {
ret = STREAM_STATA_NO_COMPATIBLE;
} else if (info.msgVer == SSTREAM_TASK_NEED_CONVERT_VER) {
ret = STREAM_STATA_NEED_CONVERT;
} else if (info.msgVer == SSTREAM_TASK_VER) {
ret = STREAM_STATA_COMPATIBLE;
}
2023-09-20 12:53:58 +00:00
tDecoderClear(&decoder);
2023-09-21 09:41:30 +00:00
break;
2023-09-20 12:53:58 +00:00
}
tdbFree(pKey);
tdbFree(pVal);
tdbTbcClose(pCur);
2023-09-21 09:41:30 +00:00
return ret;
2023-09-20 12:53:58 +00:00
}
2023-10-12 12:16:41 +00:00
int32_t streamMetaCvtDbFormat(SStreamMeta* pMeta) {
2023-11-16 06:41:04 +00:00
int32_t code = 0;
int64_t chkpId = streamMetaGetLatestCheckpointId(pMeta);
bool exist = streamBackendDataIsExist(pMeta->path, chkpId, pMeta->vgId);
if (exist == false) {
return code;
}
SBackendWrapper* pBackend = streamBackendInit(pMeta->path, chkpId, pMeta->vgId);
2023-09-21 09:41:30 +00:00
void* pIter = taosHashIterate(pBackend->cfInst, NULL);
while (pIter) {
2023-09-22 08:26:03 +00:00
void* key = taosHashGetKey(pIter, NULL);
2023-10-12 12:16:41 +00:00
code = streamStateCvtDataFormat(pMeta->path, key, *(void**)pIter);
2023-09-22 08:26:03 +00:00
if (code != 0) {
2024-01-08 08:38:16 +00:00
stError("failed to cvt data");
2023-09-22 08:38:41 +00:00
goto _EXIT;
2023-09-22 08:26:03 +00:00
}
2023-09-21 09:41:30 +00:00
pIter = taosHashIterate(pBackend->cfInst, pIter);
}
2023-09-22 08:38:41 +00:00
_EXIT:
streamBackendCleanup((void*)pBackend);
2023-11-16 06:41:04 +00:00
if (code == 0) {
char* state = taosMemoryCalloc(1, strlen(pMeta->path) + 32);
sprintf(state, "%s%s%s", pMeta->path, TD_DIRSEP, "state");
taosRemoveDir(state);
taosMemoryFree(state);
}
2023-09-22 08:38:41 +00:00
return code;
2023-09-21 09:41:30 +00:00
}
2023-10-12 07:24:50 +00:00
int32_t streamMetaMayCvtDbFormat(SStreamMeta* pMeta) {
2023-09-22 12:51:29 +00:00
int8_t compatible = streamMetaCheckBackendCompatible(pMeta);
2023-09-21 09:41:30 +00:00
if (compatible == STREAM_STATA_COMPATIBLE) {
return 0;
2023-09-22 08:26:03 +00:00
} else if (compatible == STREAM_STATA_NEED_CONVERT) {
2024-01-08 08:38:16 +00:00
stInfo("stream state need covert backend format");
2023-09-22 08:26:03 +00:00
2023-10-12 12:16:41 +00:00
return streamMetaCvtDbFormat(pMeta);
2023-09-21 09:41:30 +00:00
} else if (compatible == STREAM_STATA_NO_COMPATIBLE) {
2024-01-08 08:38:16 +00:00
stError(
2023-09-21 09:41:30 +00:00
"stream read incompatible data, rm %s/vnode/vnode*/tq/stream if taosd cannot start, and rebuild stream "
"manually",
tsDataDir);
2023-09-22 08:26:03 +00:00
2023-09-21 09:41:30 +00:00
return -1;
}
return 0;
}
2023-09-22 08:26:03 +00:00
2023-11-08 06:14:01 +00:00
int32_t streamTaskSetDb(SStreamMeta* pMeta, void* arg, char* key) {
2023-10-17 10:19:52 +00:00
SStreamTask* pTask = arg;
2023-11-17 08:14:51 +00:00
int64_t chkpId = pTask->chkInfo.checkpointId;
2023-10-17 10:19:52 +00:00
2023-09-27 06:44:09 +00:00
taosThreadMutexLock(&pMeta->backendMutex);
2023-10-12 12:16:41 +00:00
void** ppBackend = taosHashGet(pMeta->pTaskDbUnique, key, strlen(key));
2023-09-22 09:08:42 +00:00
if (ppBackend != NULL && *ppBackend != NULL) {
2023-10-11 12:12:07 +00:00
taskDbAddRef(*ppBackend);
2023-10-17 10:19:52 +00:00
STaskDbWrapper* pBackend = *ppBackend;
2023-12-16 07:05:27 +00:00
pBackend->pMeta = pMeta;
2023-10-17 10:19:52 +00:00
pTask->backendRefId = pBackend->refId;
pTask->pBackend = pBackend;
2023-12-16 07:05:27 +00:00
2023-09-27 06:44:09 +00:00
taosThreadMutexUnlock(&pMeta->backendMutex);
2023-11-29 11:57:30 +00:00
stDebug("s-task:0x%x set backend %p", pTask->id.taskId, pBackend);
2023-10-17 10:19:52 +00:00
return 0;
2023-09-22 09:08:42 +00:00
}
2023-10-07 04:17:55 +00:00
2023-10-17 10:19:52 +00:00
STaskDbWrapper* pBackend = taskDbOpen(pMeta->path, key, chkpId);
2023-12-18 03:19:15 +00:00
while (1) {
if (pBackend == NULL) {
taosThreadMutexUnlock(&pMeta->backendMutex);
taosMsleep(1000);
stDebug("backend held by other task, restart later, path:%s, key:%s", pMeta->path, key);
2023-12-18 03:19:15 +00:00
} else {
taosThreadMutexUnlock(&pMeta->backendMutex);
break;
}
2023-12-18 03:19:15 +00:00
taosThreadMutexLock(&pMeta->backendMutex);
pBackend = taskDbOpen(pMeta->path, key, chkpId);
2023-09-28 09:07:19 +00:00
}
2023-10-17 10:19:52 +00:00
2023-10-17 03:23:39 +00:00
int64_t tref = taosAddRef(taskDbWrapperId, pBackend);
2023-10-17 10:19:52 +00:00
pTask->backendRefId = tref;
pTask->pBackend = pBackend;
pBackend->refId = tref;
pBackend->pTask = pTask;
2023-12-16 07:05:27 +00:00
pBackend->pMeta = pMeta;
2023-09-28 07:46:12 +00:00
2023-10-12 12:16:41 +00:00
taosHashPut(pMeta->pTaskDbUnique, key, strlen(key), &pBackend, sizeof(void*));
2023-10-07 09:17:30 +00:00
taosThreadMutexUnlock(&pMeta->backendMutex);
2023-11-29 11:57:30 +00:00
stDebug("s-task:0x%x set backend %p", pTask->id.taskId, pBackend);
2023-10-17 10:19:52 +00:00
return 0;
2023-09-22 09:08:42 +00:00
}
2023-12-16 07:05:27 +00:00
void streamMetaRemoveDB(void* arg, char* key) {
if (arg == NULL || key == NULL) return;
SStreamMeta* pMeta = arg;
taosThreadMutexLock(&pMeta->backendMutex);
taosHashRemove(pMeta->pTaskDbUnique, key, strlen(key));
taosThreadMutexUnlock(&pMeta->backendMutex);
}
SStreamMeta* streamMetaOpen(const char* path, void* ahandle, FTaskExpand expandFunc, int32_t vgId, int64_t stage,
startComplete_fn_t fn) {
2023-03-15 12:01:16 +00:00
int32_t code = -1;
2022-08-02 14:23:33 +00:00
SStreamMeta* pMeta = taosMemoryCalloc(1, sizeof(SStreamMeta));
if (pMeta == NULL) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
2023-09-20 10:18:31 +00:00
stError("vgId:%d failed to prepare stream meta, alloc size:%" PRIzu ", out of memory", vgId, sizeof(SStreamMeta));
2022-08-02 14:23:33 +00:00
return NULL;
}
2023-04-08 17:39:09 +00:00
2023-08-30 08:00:14 +00:00
int32_t len = strlen(path) + 64;
2023-08-30 09:12:37 +00:00
char* tpath = taosMemoryCalloc(1, len);
2023-08-30 08:00:14 +00:00
2023-08-03 08:24:50 +00:00
sprintf(tpath, "%s%s%s", path, TD_DIRSEP, "stream");
pMeta->path = tpath;
2022-08-02 14:23:33 +00:00
2023-09-20 12:53:58 +00:00
if (streamMetaOpenTdb(pMeta) < 0) {
2022-08-02 14:23:33 +00:00
goto _err;
}
2023-10-12 07:24:50 +00:00
if (streamMetaMayCvtDbFormat(pMeta) < 0) {
2022-08-02 14:23:33 +00:00
goto _err;
}
if (streamMetaBegin(pMeta) < 0) {
goto _err;
}
_hash_fn_t fp = taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR);
2023-09-15 01:25:22 +00:00
pMeta->pTasksMap = taosHashInit(64, fp, true, HASH_NO_LOCK);
if (pMeta->pTasksMap == NULL) {
goto _err;
}
pMeta->updateInfo.pTasks = taosHashInit(64, fp, false, HASH_NO_LOCK);
if (pMeta->updateInfo.pTasks == NULL) {
2022-08-08 05:48:09 +00:00
goto _err;
}
pMeta->startInfo.pReadyTaskSet = taosHashInit(64, fp, false, HASH_NO_LOCK);
if (pMeta->startInfo.pReadyTaskSet == NULL) {
goto _err;
}
pMeta->startInfo.pFailedTaskSet = taosHashInit(4, fp, false, HASH_NO_LOCK);
if (pMeta->startInfo.pFailedTaskSet == NULL) {
goto _err;
}
2023-09-15 01:25:22 +00:00
pMeta->pHbInfo = taosMemoryCalloc(1, sizeof(SMetaHbInfo));
if (pMeta->pHbInfo == NULL) {
2022-08-08 05:48:09 +00:00
goto _err;
}
// task list
pMeta->pTaskList = taosArrayInit(4, sizeof(SStreamTaskId));
if (pMeta->pTaskList == NULL) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
goto _err;
}
pMeta->scanInfo.scanCounter = 0;
pMeta->vgId = vgId;
2022-08-02 14:23:33 +00:00
pMeta->ahandle = ahandle;
pMeta->expandFunc = expandFunc;
pMeta->stage = stage;
2023-11-10 06:14:22 +00:00
pMeta->role = (vgId == SNODE_HANDLE) ? NODE_ROLE_LEADER : NODE_ROLE_UNINIT;
2023-04-27 14:38:33 +00:00
pMeta->startInfo.completeFn = fn;
2023-10-12 12:16:41 +00:00
pMeta->pTaskDbUnique = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK);
2023-09-22 09:08:42 +00:00
2023-09-16 17:19:59 +00:00
pMeta->numOfPausedTasks = 0;
pMeta->numOfStreamTasks = 0;
2023-09-20 10:18:31 +00:00
stInfo("vgId:%d open stream meta successfully, latest checkpoint:%" PRId64 ", stage:%" PRId64, vgId, pMeta->chkpId,
2023-10-07 09:48:24 +00:00
stage);
pMeta->rid = taosAddRef(streamMetaId, pMeta);
2023-12-22 16:58:52 +00:00
2023-12-25 04:47:16 +00:00
// set the attribute when running on Linux OS
2023-12-22 16:58:52 +00:00
TdThreadRwlockAttr attr;
taosThreadRwlockAttrInit(&attr);
#ifdef LINUX
2023-12-22 16:58:52 +00:00
pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
#endif
2023-12-25 04:47:16 +00:00
taosThreadRwlockInit(&pMeta->lock, &attr);
2023-12-22 16:58:52 +00:00
taosThreadRwlockAttrDestroy(&attr);
int64_t* pRid = taosMemoryMalloc(sizeof(int64_t));
memcpy(pRid, &pMeta->rid, sizeof(pMeta->rid));
metaRefMgtAdd(pMeta->vgId, pRid);
pMeta->pHbInfo->hbTmr = taosTmrStart(metaHbToMnode, META_HB_CHECK_INTERVAL, pRid, streamTimer);
pMeta->pHbInfo->tickCounter = 0;
pMeta->pHbInfo->stopFlag = 0;
2023-11-08 06:14:01 +00:00
pMeta->qHandle = taosInitScheduler(32, 1, "stream-chkp", NULL);
2023-04-27 14:38:33 +00:00
2023-11-09 12:15:08 +00:00
pMeta->bkdChkptMgt = bkdMgtCreate(tpath);
2023-12-20 08:56:12 +00:00
taosThreadMutexInit(&pMeta->backendMutex, NULL);
2023-11-09 12:15:08 +00:00
return pMeta;
2022-08-09 02:35:39 +00:00
2023-11-08 06:14:01 +00:00
_err:
2022-10-14 06:43:22 +00:00
taosMemoryFree(pMeta->path);
2023-09-15 01:25:22 +00:00
if (pMeta->pTasksMap) taosHashCleanup(pMeta->pTasksMap);
if (pMeta->pTaskList) taosArrayDestroy(pMeta->pTaskList);
2022-08-09 02:35:39 +00:00
if (pMeta->pTaskDb) tdbTbClose(pMeta->pTaskDb);
if (pMeta->pCheckpointDb) tdbTbClose(pMeta->pCheckpointDb);
2022-08-09 02:35:39 +00:00
if (pMeta->db) tdbClose(pMeta->db);
2023-09-15 01:25:22 +00:00
if (pMeta->pHbInfo) taosMemoryFreeClear(pMeta->pHbInfo);
if (pMeta->updateInfo.pTasks) taosHashCleanup(pMeta->updateInfo.pTasks);
2023-09-25 08:01:17 +00:00
if (pMeta->startInfo.pReadyTaskSet) taosHashCleanup(pMeta->startInfo.pReadyTaskSet);
if (pMeta->startInfo.pFailedTaskSet) taosHashCleanup(pMeta->startInfo.pFailedTaskSet);
2022-08-09 02:35:39 +00:00
taosMemoryFree(pMeta);
2023-06-30 11:48:46 +00:00
2023-09-20 10:18:31 +00:00
stError("failed to open stream meta");
2022-08-02 14:23:33 +00:00
return NULL;
}
2023-11-13 10:20:30 +00:00
// todo refactor: the lock shoud be restricted in one function
#ifdef BUILD_NO_CALL
2023-11-13 10:20:30 +00:00
void streamMetaInitBackend(SStreamMeta* pMeta) {
pMeta->streamBackend = streamBackendInit(pMeta->path, pMeta->chkpId, pMeta->vgId);
if (pMeta->streamBackend == NULL) {
streamMetaWUnLock(pMeta);
while (1) {
streamMetaWLock(pMeta);
pMeta->streamBackend = streamBackendInit(pMeta->path, pMeta->chkpId, pMeta->vgId);
if (pMeta->streamBackend != NULL) {
break;
}
streamMetaWUnLock(pMeta);
stInfo("vgId:%d failed to init stream backend, retry in 100ms", pMeta->vgId);
taosMsleep(100);
}
2023-08-07 11:39:32 +00:00
}
2023-09-26 04:15:12 +00:00
2023-08-07 08:51:01 +00:00
pMeta->streamBackendRid = taosAddRef(streamBackendId, pMeta->streamBackend);
2023-08-23 13:43:10 +00:00
streamBackendLoadCheckpointInfo(pMeta);
}
#endif
2023-08-07 08:51:01 +00:00
void streamMetaClear(SStreamMeta* pMeta) {
// remove all existed tasks in this vnode
void* pIter = NULL;
2023-09-15 01:25:22 +00:00
while ((pIter = taosHashIterate(pMeta->pTasksMap, pIter)) != NULL) {
SStreamTask* p = *(SStreamTask**)pIter;
// release the ref by timer
2023-08-31 05:46:48 +00:00
if (p->info.triggerParam != 0 && p->info.fillHistory == 0) { // one more ref in timer
2023-09-20 10:18:31 +00:00
stDebug("s-task:%s stop schedTimer, and (before) desc ref:%d", p->id.idStr, p->refCnt);
taosTmrStop(p->schedInfo.pDelayTimer);
2023-08-31 05:46:48 +00:00
p->info.triggerParam = 0;
streamMetaReleaseTask(pMeta, p);
}
streamMetaReleaseTask(pMeta, p);
}
2023-08-07 08:51:01 +00:00
taosRemoveRef(streamBackendId, pMeta->streamBackendRid);
2023-08-07 08:51:01 +00:00
2023-09-15 01:25:22 +00:00
taosHashClear(pMeta->pTasksMap);
2023-08-07 08:51:01 +00:00
taosArrayClear(pMeta->pTaskList);
2023-08-10 01:49:26 +00:00
taosArrayClear(pMeta->chkpSaved);
taosArrayClear(pMeta->chkpInUse);
2023-09-18 16:52:35 +00:00
pMeta->numOfStreamTasks = 0;
pMeta->numOfPausedTasks = 0;
// the willrestart/starting flag can NOT be cleared
taosHashClear(pMeta->startInfo.pReadyTaskSet);
taosHashClear(pMeta->startInfo.pFailedTaskSet);
pMeta->startInfo.readyTs = 0;
2023-08-03 08:24:50 +00:00
}
2022-08-02 14:23:33 +00:00
void streamMetaClose(SStreamMeta* pMeta) {
2023-09-20 10:18:31 +00:00
stDebug("start to close stream meta");
2023-08-30 08:58:22 +00:00
if (pMeta == NULL) {
return;
}
2023-08-26 13:54:36 +00:00
// int64_t rid = *(int64_t*)pMeta->pRid;
// if (taosTmrStop(pMeta->hbInfo.hbTmr)) {
// taosMemoryFree(pMeta->pRid);
// } else {
// // do nothing, stop by timer thread
// }
2023-08-26 09:37:09 +00:00
taosRemoveRef(streamMetaId, pMeta->rid);
}
void streamMetaCloseImpl(void* arg) {
SStreamMeta* pMeta = arg;
2023-09-20 10:18:31 +00:00
stDebug("start to do-close stream meta");
if (pMeta == NULL) {
return;
}
streamMetaClear(pMeta);
tdbAbort(pMeta->db, pMeta->txn);
tdbTbClose(pMeta->pTaskDb);
tdbTbClose(pMeta->pCheckpointDb);
tdbClose(pMeta->db);
2022-08-08 05:48:09 +00:00
taosArrayDestroy(pMeta->pTaskList);
taosArrayDestroy(pMeta->chkpSaved);
taosArrayDestroy(pMeta->chkpInUse);
2023-09-15 01:25:22 +00:00
taosHashCleanup(pMeta->pTasksMap);
2023-10-12 12:16:41 +00:00
taosHashCleanup(pMeta->pTaskDbUnique);
2023-09-15 01:25:22 +00:00
taosHashCleanup(pMeta->pUpdateTaskSet);
2023-11-08 06:14:01 +00:00
// taosHashCleanup(pMeta->pTaskBackendUnique);
taosHashCleanup(pMeta->updateInfo.pTasks);
2023-09-25 08:01:17 +00:00
taosHashCleanup(pMeta->startInfo.pReadyTaskSet);
taosHashCleanup(pMeta->startInfo.pFailedTaskSet);
2023-06-30 11:48:46 +00:00
taosMemoryFree(pMeta->pHbInfo);
taosMemoryFree(pMeta->path);
taosThreadMutexDestroy(&pMeta->backendMutex);
2023-06-30 12:05:05 +00:00
2023-11-08 09:10:54 +00:00
taosCleanUpScheduler(pMeta->qHandle);
taosMemoryFree(pMeta->qHandle);
2023-11-09 12:37:08 +00:00
bkdMgtDestroy(pMeta->bkdChkptMgt);
2023-09-26 04:15:12 +00:00
pMeta->role = NODE_ROLE_UNINIT;
2022-08-08 05:48:09 +00:00
taosMemoryFree(pMeta);
2023-09-20 10:18:31 +00:00
stDebug("end to close stream meta");
2022-08-08 05:48:09 +00:00
}
2023-10-19 08:20:27 +00:00
// todo let's check the status for each task
2023-02-16 08:02:32 +00:00
int32_t streamMetaSaveTask(SStreamMeta* pMeta, SStreamTask* pTask) {
void* buf = NULL;
2022-08-02 14:23:33 +00:00
int32_t len;
int32_t code;
2023-08-04 05:52:20 +00:00
pTask->ver = SSTREAM_TASK_VER;
2023-04-11 07:42:24 +00:00
tEncodeSize(tEncodeStreamTask, pTask, len, code);
2022-08-02 14:23:33 +00:00
if (code < 0) {
return -1;
}
2022-10-25 16:36:25 +00:00
buf = taosMemoryCalloc(1, len);
2022-08-02 14:23:33 +00:00
if (buf == NULL) {
return -1;
}
SEncoder encoder = {0};
2022-08-02 14:23:33 +00:00
tEncoderInit(&encoder, buf, len);
2023-04-11 07:42:24 +00:00
tEncodeStreamTask(&encoder, pTask);
tEncoderClear(&encoder);
2022-08-02 14:23:33 +00:00
2023-09-16 13:37:30 +00:00
int64_t id[2] = {pTask->id.streamId, pTask->id.taskId};
if (tdbTbUpsert(pMeta->pTaskDb, id, STREAM_TASK_KEY_LEN, buf, len, pMeta->txn) < 0) {
2023-09-20 10:18:31 +00:00
stError("s-task:%s save to disk failed, code:%s", pTask->id.idStr, tstrerror(terrno));
2022-08-02 14:23:33 +00:00
return -1;
}
2022-10-25 16:36:25 +00:00
taosMemoryFree(buf);
2023-02-16 08:02:32 +00:00
return 0;
}
2023-09-16 13:37:30 +00:00
int32_t streamMetaRemoveTask(SStreamMeta* pMeta, STaskId* pTaskId) {
int64_t key[2] = {pTaskId->streamId, pTaskId->taskId};
int32_t code = tdbTbDelete(pMeta->pTaskDb, key, STREAM_TASK_KEY_LEN, pMeta->txn);
2023-07-25 09:31:54 +00:00
if (code != 0) {
2023-10-07 09:48:24 +00:00
stError("vgId:%d failed to remove task:0x%x from metastore, code:%s", pMeta->vgId, (int32_t)pTaskId->taskId,
tstrerror(terrno));
2023-07-25 09:31:54 +00:00
} else {
2023-10-07 09:48:24 +00:00
stDebug("vgId:%d remove task:0x%x from metastore", pMeta->vgId, (int32_t)pTaskId->taskId);
2023-07-25 09:31:54 +00:00
}
return code;
}
// add to the ready tasks hash map, not the restored tasks hash map
int32_t streamMetaRegisterTask(SStreamMeta* pMeta, int64_t ver, SStreamTask* pTask, bool* pAdded) {
*pAdded = false;
2024-01-15 03:28:36 +00:00
STaskId id = streamTaskGetTaskId(pTask);
void* p = taosHashGet(pMeta->pTasksMap, &id, sizeof(id));
if (p != NULL) {
return 0;
}
if (pTask->info.fillHistory == 1) {
stDebug("s-task:0x%x initial nextProcessVer is set to 1 for fill-history task", pTask->id.taskId);
ver = 1;
}
2023-07-26 06:37:04 +00:00
if (pMeta->expandFunc(pMeta->ahandle, pTask, ver) < 0) {
tFreeStreamTask(pTask);
return -1;
}
taosArrayPush(pMeta->pTaskList, &pTask->id);
2023-10-01 14:27:29 +00:00
if (streamMetaSaveTask(pMeta, pTask) < 0) {
tFreeStreamTask(pTask);
return -1;
}
if (streamMetaCommit(pMeta) < 0) {
tFreeStreamTask(pTask);
return -1;
}
2023-09-16 13:37:30 +00:00
taosHashPut(pMeta->pTasksMap, &id, sizeof(id), &pTask, POINTER_BYTES);
2023-09-16 17:19:59 +00:00
if (pTask->info.fillHistory == 0) {
atomic_add_fetch_32(&pMeta->numOfStreamTasks, 1);
}
*pAdded = true;
2022-08-02 14:23:33 +00:00
return 0;
}
int32_t streamMetaGetNumOfTasks(SStreamMeta* pMeta) {
2023-09-15 01:25:22 +00:00
size_t size = taosHashGetSize(pMeta->pTasksMap);
ASSERT(taosArrayGetSize(pMeta->pTaskList) == taosHashGetSize(pMeta->pTasksMap));
return (int32_t)size;
}
2022-08-02 14:23:33 +00:00
2023-12-22 06:51:04 +00:00
SStreamTask* streamMetaAcquireTaskNoLock(SStreamMeta* pMeta, int64_t streamId, int32_t taskId) {
2023-10-07 09:48:24 +00:00
STaskId id = {.streamId = streamId, .taskId = taskId};
2023-09-16 13:37:30 +00:00
SStreamTask** ppTask = (SStreamTask**)taosHashGet(pMeta->pTasksMap, &id, sizeof(id));
2023-12-22 06:51:04 +00:00
if (ppTask == NULL || streamTaskShouldStop(*ppTask)) {
return NULL;
2022-11-15 10:32:08 +00:00
}
2023-12-22 06:51:04 +00:00
int32_t ref = atomic_add_fetch_32(&(*ppTask)->refCnt, 1);
stTrace("s-task:%s acquire task, ref:%d", (*ppTask)->id.idStr, ref);
return *ppTask;
}
SStreamTask* streamMetaAcquireTask(SStreamMeta* pMeta, int64_t streamId, int32_t taskId) {
streamMetaRLock(pMeta);
SStreamTask* p = streamMetaAcquireTaskNoLock(pMeta, streamId, taskId);
2023-11-01 09:19:21 +00:00
streamMetaRUnLock(pMeta);
2023-12-22 06:51:04 +00:00
return p;
2022-11-15 10:32:08 +00:00
}
void streamMetaReleaseTask(SStreamMeta* UNUSED_PARAM(pMeta), SStreamTask* pTask) {
2023-07-11 11:29:52 +00:00
int32_t ref = atomic_sub_fetch_32(&pTask->refCnt, 1);
if (ref > 0) {
2023-09-20 10:18:31 +00:00
stTrace("s-task:%s release task, ref:%d", pTask->id.idStr, ref);
2023-07-11 11:29:52 +00:00
} else if (ref == 0) {
2023-09-20 10:18:31 +00:00
stTrace("s-task:%s all refs are gone, free it", pTask->id.idStr);
2023-04-08 17:39:09 +00:00
tFreeStreamTask(pTask);
2023-07-11 11:29:52 +00:00
} else if (ref < 0) {
2023-09-20 10:18:31 +00:00
stError("task ref is invalid, ref:%d, %s", ref, pTask->id.idStr);
2023-07-11 11:29:52 +00:00
}
}
static void doRemoveIdFromList(SStreamMeta* pMeta, int32_t num, SStreamTaskId* id) {
2023-07-11 11:29:52 +00:00
for (int32_t i = 0; i < num; ++i) {
SStreamTaskId* pTaskId = taosArrayGet(pMeta->pTaskList, i);
if (pTaskId->streamId == id->streamId && pTaskId->taskId == id->taskId) {
2023-07-11 11:29:52 +00:00
taosArrayRemove(pMeta->pTaskList, i);
break;
}
2022-11-15 10:32:08 +00:00
}
}
2023-08-09 08:04:48 +00:00
int32_t streamMetaUnregisterTask(SStreamMeta* pMeta, int64_t streamId, int32_t taskId) {
2023-06-25 11:41:44 +00:00
SStreamTask* pTask = NULL;
2023-04-28 16:00:25 +00:00
2023-06-25 11:41:44 +00:00
// pre-delete operation
2023-11-01 09:19:21 +00:00
streamMetaWLock(pMeta);
2023-08-09 08:04:48 +00:00
2023-10-07 09:48:24 +00:00
STaskId id = {.streamId = streamId, .taskId = taskId};
2023-09-16 13:37:30 +00:00
SStreamTask** ppTask = (SStreamTask**)taosHashGet(pMeta->pTasksMap, &id, sizeof(id));
2022-11-15 10:32:08 +00:00
if (ppTask) {
2023-06-25 11:41:44 +00:00
pTask = *ppTask;
// desc the paused task counter
if (streamTaskShouldPause(pTask)) {
2023-09-16 17:19:59 +00:00
int32_t num = atomic_sub_fetch_32(&pMeta->numOfPausedTasks, 1);
2023-09-20 10:18:31 +00:00
stInfo("vgId:%d s-task:%s drop stream task. pause task num:%d", pMeta->vgId, pTask->id.idStr, num);
}
// handle the dropping event
streamTaskHandleEvent(pTask->status.pSM, TASK_EVENT_DROPPING);
2023-06-25 11:41:44 +00:00
} else {
2023-09-20 10:18:31 +00:00
stDebug("vgId:%d failed to find the task:0x%x, it may be dropped already", pMeta->vgId, taskId);
2023-11-01 09:19:21 +00:00
streamMetaWUnLock(pMeta);
2023-07-25 09:31:54 +00:00
return 0;
2023-06-25 11:41:44 +00:00
}
2023-11-01 09:19:21 +00:00
streamMetaWUnLock(pMeta);
2023-06-25 11:41:44 +00:00
stDebug("s-task:0x%x set task status:dropping and start to unregister it", taskId);
2023-07-11 08:30:14 +00:00
while (1) {
2023-11-01 09:19:21 +00:00
streamMetaRLock(pMeta);
2023-06-25 11:41:44 +00:00
ppTask = (SStreamTask**)taosHashGet(pMeta->pTasksMap, &id, sizeof(id));
2023-06-25 11:41:44 +00:00
if (ppTask) {
if ((*ppTask)->status.timerActive == 0) {
2023-11-01 09:19:21 +00:00
streamMetaRUnLock(pMeta);
2023-06-25 11:41:44 +00:00
break;
}
2023-06-25 11:41:44 +00:00
taosMsleep(10);
2023-09-20 10:18:31 +00:00
stDebug("s-task:%s wait for quit from timer", (*ppTask)->id.idStr);
2023-11-01 09:19:21 +00:00
streamMetaRUnLock(pMeta);
2023-06-25 11:41:44 +00:00
} else {
2023-11-01 09:19:21 +00:00
streamMetaRUnLock(pMeta);
2023-06-25 11:41:44 +00:00
break;
}
}
// let's do delete of stream task
2023-11-01 09:19:21 +00:00
streamMetaWLock(pMeta);
2023-11-01 08:12:15 +00:00
2023-09-16 13:37:30 +00:00
ppTask = (SStreamTask**)taosHashGet(pMeta->pTasksMap, &id, sizeof(id));
2023-06-25 11:41:44 +00:00
if (ppTask) {
pTask = *ppTask;
2023-09-17 05:59:06 +00:00
// it is an fill-history task, remove the related stream task's id that points to it
if (pTask->info.fillHistory == 1) {
streamTaskClearHTaskAttr(pTask);
} else {
atomic_sub_fetch_32(&pMeta->numOfStreamTasks, 1);
2023-09-17 05:59:06 +00:00
}
2023-09-16 13:37:30 +00:00
taosHashRemove(pMeta->pTasksMap, &id, sizeof(id));
doRemoveIdFromList(pMeta, (int32_t)taosArrayGetSize(pMeta->pTaskList), &pTask->id);
2023-07-25 09:31:54 +00:00
2023-06-25 11:41:44 +00:00
ASSERT(pTask->status.timerActive == 0);
2023-07-11 11:29:52 +00:00
2023-09-04 15:13:57 +00:00
if (pTask->info.triggerParam != 0 && pTask->info.fillHistory == 0) {
2023-09-20 10:18:31 +00:00
stDebug("s-task:%s stop schedTimer, and (before) desc ref:%d", pTask->id.idStr, pTask->refCnt);
taosTmrStop(pTask->schedInfo.pDelayTimer);
pTask->info.triggerParam = 0;
streamMetaReleaseTask(pMeta, pTask);
}
2023-09-16 13:37:30 +00:00
streamMetaRemoveTask(pMeta, &id);
2022-11-15 10:32:08 +00:00
streamMetaReleaseTask(pMeta, pTask);
} else {
2023-09-20 10:18:31 +00:00
stDebug("vgId:%d failed to find the task:0x%x, it may have been dropped already", pMeta->vgId, taskId);
2022-11-15 10:32:08 +00:00
}
2023-04-28 16:00:25 +00:00
2023-11-01 09:19:21 +00:00
streamMetaWUnLock(pMeta);
2023-07-25 09:31:54 +00:00
return 0;
2022-11-15 10:32:08 +00:00
}
2022-08-02 14:23:33 +00:00
int32_t streamMetaBegin(SStreamMeta* pMeta) {
2023-11-01 09:19:21 +00:00
streamMetaWLock(pMeta);
2023-11-01 08:12:15 +00:00
int32_t code = tdbBegin(pMeta->db, &pMeta->txn, tdbDefaultMalloc, tdbDefaultFree, NULL,
TDB_TXN_WRITE | TDB_TXN_READ_UNCOMMITTED);
2023-11-01 09:19:21 +00:00
streamMetaWUnLock(pMeta);
2023-11-01 08:12:15 +00:00
return code;
2022-08-02 14:23:33 +00:00
}
2023-05-20 03:37:17 +00:00
// todo add error log
2022-08-02 14:23:33 +00:00
int32_t streamMetaCommit(SStreamMeta* pMeta) {
if (tdbCommit(pMeta->db, pMeta->txn) < 0) {
2023-09-20 10:18:31 +00:00
stError("vgId:%d failed to commit stream meta", pMeta->vgId);
2022-08-02 14:23:33 +00:00
return -1;
}
if (tdbPostCommit(pMeta->db, pMeta->txn) < 0) {
2023-09-20 10:18:31 +00:00
stError("vgId:%d failed to do post-commit stream meta", pMeta->vgId);
return -1;
}
if (tdbBegin(pMeta->db, &pMeta->txn, tdbDefaultMalloc, tdbDefaultFree, NULL,
TDB_TXN_WRITE | TDB_TXN_READ_UNCOMMITTED) < 0) {
2023-09-20 10:18:31 +00:00
stError("vgId:%d failed to begin trans", pMeta->vgId);
return -1;
}
2023-05-20 03:37:17 +00:00
2022-08-02 14:23:33 +00:00
return 0;
}
2023-11-07 11:59:05 +00:00
int64_t streamMetaGetLatestCheckpointId(SStreamMeta* pMeta) {
2023-07-14 10:06:24 +00:00
int64_t chkpId = 0;
TBC* pCur = NULL;
if (tdbTbcOpen(pMeta->pTaskDb, &pCur, NULL) < 0) {
return chkpId;
}
2023-07-14 10:06:24 +00:00
void* pKey = NULL;
int32_t kLen = 0;
void* pVal = NULL;
int32_t vLen = 0;
SDecoder decoder;
tdbTbcMoveToFirst(pCur);
while (tdbTbcNext(pCur, &pKey, &kLen, &pVal, &vLen) == 0) {
2023-08-18 13:42:35 +00:00
if (pVal == NULL || vLen == 0) {
2023-08-10 12:34:00 +00:00
break;
}
2023-07-18 04:01:20 +00:00
SCheckpointInfo info;
2023-07-14 10:06:24 +00:00
tDecoderInit(&decoder, (uint8_t*)pVal, vLen);
2023-07-18 04:01:20 +00:00
if (tDecodeStreamTaskChkInfo(&decoder, &info) < 0) {
continue;
}
2023-07-14 10:06:24 +00:00
tDecoderClear(&decoder);
2023-07-18 04:01:20 +00:00
chkpId = TMAX(chkpId, info.checkpointId);
2023-07-14 10:06:24 +00:00
}
2023-09-20 10:18:31 +00:00
stDebug("get max chkp id: %" PRId64 "", chkpId);
2023-07-14 10:06:24 +00:00
tdbFree(pKey);
tdbFree(pVal);
tdbTbcClose(pCur);
return chkpId;
}
static void doClear(void* pKey, void* pVal, TBC* pCur, SArray* pRecycleList) {
tdbFree(pKey);
tdbFree(pVal);
tdbTbcClose(pCur);
taosArrayDestroy(pRecycleList);
}
int32_t streamMetaLoadAllTasks(SStreamMeta* pMeta) {
2023-12-16 07:05:27 +00:00
TBC* pCur = NULL;
2023-12-14 01:33:51 +00:00
void* pKey = NULL;
int32_t kLen = 0;
void* pVal = NULL;
int32_t vLen = 0;
SDecoder decoder;
2023-09-18 15:51:08 +00:00
2023-12-14 01:33:51 +00:00
if (pMeta == NULL) {
return TSDB_CODE_SUCCESS;
}
SArray* pRecycleList = taosArrayInit(4, sizeof(STaskId));
int32_t vgId = pMeta->vgId;
2023-09-20 10:18:31 +00:00
stInfo("vgId:%d load stream tasks from meta files", vgId);
2023-07-25 09:31:54 +00:00
2022-08-02 14:23:33 +00:00
if (tdbTbcOpen(pMeta->pTaskDb, &pCur, NULL) < 0) {
2023-09-20 10:18:31 +00:00
stError("vgId:%d failed to open stream meta, code:%s", vgId, tstrerror(terrno));
2023-12-14 01:33:51 +00:00
taosArrayDestroy(pRecycleList);
2022-08-02 14:23:33 +00:00
return -1;
}
tdbTbcMoveToFirst(pCur);
while (tdbTbcNext(pCur, &pKey, &kLen, &pVal, &vLen) == 0) {
SStreamTask* pTask = taosMemoryCalloc(1, sizeof(SStreamTask));
if (pTask == NULL) {
2023-09-18 15:51:08 +00:00
terrno = TSDB_CODE_OUT_OF_MEMORY;
2023-09-20 10:18:31 +00:00
stError("vgId:%d failed to load stream task from meta-files, code:%s", vgId, tstrerror(terrno));
doClear(pKey, pVal, pCur, pRecycleList);
2022-08-02 14:23:33 +00:00
return -1;
}
2022-08-02 14:23:33 +00:00
tDecoderInit(&decoder, (uint8_t*)pVal, vLen);
2023-08-04 05:52:20 +00:00
if (tDecodeStreamTask(&decoder, pTask) < 0) {
tDecoderClear(&decoder);
doClear(pKey, pVal, pCur, pRecycleList);
2023-08-04 05:52:20 +00:00
tFreeStreamTask(pTask);
2023-09-20 10:18:31 +00:00
stError(
2023-10-07 09:48:24 +00:00
"vgId:%d stream read incompatible data, rm %s/vnode/vnode*/tq/stream if taosd cannot start, and rebuild "
"stream manually",
vgId, tsDataDir);
2023-08-04 05:52:20 +00:00
return -1;
}
2022-08-02 14:23:33 +00:00
tDecoderClear(&decoder);
2023-07-25 09:31:54 +00:00
if (pTask->status.taskStatus == TASK_STATUS__DROPPING) {
int32_t taskId = pTask->id.taskId;
tFreeStreamTask(pTask);
2024-01-15 03:28:36 +00:00
STaskId id = streamTaskGetTaskId(pTask);
2023-09-16 13:37:30 +00:00
taosArrayPush(pRecycleList, &id);
2023-07-25 09:31:54 +00:00
int32_t total = taosArrayGetSize(pRecycleList);
2023-09-20 10:18:31 +00:00
stDebug("s-task:0x%x is already dropped, add into recycle list, total:%d", taskId, total);
2023-07-25 09:31:54 +00:00
continue;
}
// do duplicate task check.
2023-09-16 13:37:30 +00:00
STaskId id = {.streamId = pTask->id.streamId, .taskId = pTask->id.taskId};
void* p = taosHashGet(pMeta->pTasksMap, &id, sizeof(id));
if (p == NULL) {
2023-10-01 14:27:29 +00:00
if (pMeta->expandFunc(pMeta->ahandle, pTask, pTask->chkInfo.checkpointVer + 1) < 0) {
doClear(pKey, pVal, pCur, pRecycleList);
2023-07-25 09:31:54 +00:00
tFreeStreamTask(pTask);
return -1;
}
2023-07-25 09:31:54 +00:00
taosArrayPush(pMeta->pTaskList, &pTask->id);
} else {
// todo this should replace the existed object put by replay creating stream task msg from mnode
stError("s-task:0x%x already added into table meta by replaying WAL, need check", pTask->id.taskId);
taosMemoryFree(pTask);
continue;
}
2023-09-16 13:37:30 +00:00
if (taosHashPut(pMeta->pTasksMap, &id, sizeof(id), &pTask, POINTER_BYTES) < 0) {
doClear(pKey, pVal, pCur, pRecycleList);
2023-07-25 09:31:54 +00:00
tFreeStreamTask(pTask);
return -1;
}
2023-09-16 17:19:59 +00:00
if (pTask->info.fillHistory == 0) {
atomic_add_fetch_32(&pMeta->numOfStreamTasks, 1);
}
if (streamTaskShouldPause(pTask)) {
2023-09-16 17:19:59 +00:00
atomic_add_fetch_32(&pMeta->numOfPausedTasks, 1);
}
ASSERT(pTask->status.downstreamReady == 0);
}
tdbFree(pKey);
tdbFree(pVal);
if (tdbTbcClose(pCur) < 0) {
2023-09-20 10:18:31 +00:00
stError("vgId:%d failed to close meta-file cursor", vgId);
2023-07-25 09:31:54 +00:00
taosArrayDestroy(pRecycleList);
return -1;
2022-08-02 14:23:33 +00:00
}
2023-07-25 09:31:54 +00:00
if (taosArrayGetSize(pRecycleList) > 0) {
2023-08-04 05:52:20 +00:00
for (int32_t i = 0; i < taosArrayGetSize(pRecycleList); ++i) {
2023-09-16 13:37:30 +00:00
STaskId* pId = taosArrayGet(pRecycleList, i);
streamMetaRemoveTask(pMeta, pId);
2023-07-25 09:31:54 +00:00
}
}
2023-08-10 06:07:29 +00:00
int32_t numOfTasks = taosArrayGetSize(pMeta->pTaskList);
ASSERT(pMeta->numOfStreamTasks <= numOfTasks && pMeta->numOfPausedTasks <= numOfTasks);
2023-09-20 10:18:31 +00:00
stDebug("vgId:%d load %d tasks into meta from disk completed, streamTask:%d, paused:%d", pMeta->vgId, numOfTasks,
2023-10-07 09:48:24 +00:00
pMeta->numOfStreamTasks, pMeta->numOfPausedTasks);
2023-07-25 09:31:54 +00:00
taosArrayDestroy(pRecycleList);
2022-08-02 14:23:33 +00:00
return 0;
}
int32_t tEncodeStreamHbMsg(SEncoder* pEncoder, const SStreamHbMsg* pReq) {
if (tStartEncode(pEncoder) < 0) return -1;
if (tEncodeI32(pEncoder, pReq->vgId) < 0) return -1;
if (tEncodeI32(pEncoder, pReq->numOfTasks) < 0) return -1;
for (int32_t i = 0; i < pReq->numOfTasks; ++i) {
STaskStatusEntry* ps = taosArrayGet(pReq->pTaskStatus, i);
2023-09-16 17:19:59 +00:00
if (tEncodeI64(pEncoder, ps->id.streamId) < 0) return -1;
if (tEncodeI32(pEncoder, ps->id.taskId) < 0) return -1;
if (tEncodeI32(pEncoder, ps->status) < 0) return -1;
2023-11-13 10:39:42 +00:00
if (tEncodeI64(pEncoder, ps->stage) < 0) return -1;
2023-09-20 02:35:01 +00:00
if (tEncodeI32(pEncoder, ps->nodeId) < 0) return -1;
2023-10-01 14:27:29 +00:00
if (tEncodeDouble(pEncoder, ps->inputQUsed) < 0) return -1;
2023-10-02 17:52:03 +00:00
if (tEncodeDouble(pEncoder, ps->inputRate) < 0) return -1;
if (tEncodeDouble(pEncoder, ps->sinkQuota) < 0) return -1;
if (tEncodeDouble(pEncoder, ps->sinkDataSize) < 0) return -1;
if (tEncodeI64(pEncoder, ps->processedVer) < 0) return -1;
2023-10-02 18:37:52 +00:00
if (tEncodeI64(pEncoder, ps->verStart) < 0) return -1;
if (tEncodeI64(pEncoder, ps->verEnd) < 0) return -1;
if (tEncodeI64(pEncoder, ps->activeCheckpointId) < 0) return -1;
if (tEncodeI8(pEncoder, ps->checkpointFailed) < 0) return -1;
if (tEncodeI32(pEncoder, ps->chkpointTransId) < 0) return -1;
}
int32_t numOfVgs = taosArrayGetSize(pReq->pUpdateNodes);
if (tEncodeI32(pEncoder, numOfVgs) < 0) return -1;
for (int j = 0; j < numOfVgs; ++j) {
int32_t* pVgId = taosArrayGet(pReq->pUpdateNodes, j);
if (tEncodeI32(pEncoder, *pVgId) < 0) return -1;
}
tEndEncode(pEncoder);
return pEncoder->pos;
}
2023-07-30 11:25:00 +00:00
int32_t tDecodeStreamHbMsg(SDecoder* pDecoder, SStreamHbMsg* pReq) {
if (tStartDecode(pDecoder) < 0) return -1;
2023-07-30 11:25:00 +00:00
if (tDecodeI32(pDecoder, &pReq->vgId) < 0) return -1;
if (tDecodeI32(pDecoder, &pReq->numOfTasks) < 0) return -1;
pReq->pTaskStatus = taosArrayInit(pReq->numOfTasks, sizeof(STaskStatusEntry));
for (int32_t i = 0; i < pReq->numOfTasks; ++i) {
2023-09-20 02:35:01 +00:00
int32_t taskId = 0;
STaskStatusEntry entry = {0};
2023-09-16 17:19:59 +00:00
2023-09-20 02:35:01 +00:00
if (tDecodeI64(pDecoder, &entry.id.streamId) < 0) return -1;
if (tDecodeI32(pDecoder, &taskId) < 0) return -1;
if (tDecodeI32(pDecoder, &entry.status) < 0) return -1;
2023-11-13 10:39:42 +00:00
if (tDecodeI64(pDecoder, &entry.stage) < 0) return -1;
2023-09-20 02:35:01 +00:00
if (tDecodeI32(pDecoder, &entry.nodeId) < 0) return -1;
2023-10-01 14:27:29 +00:00
if (tDecodeDouble(pDecoder, &entry.inputQUsed) < 0) return -1;
2023-10-02 17:52:03 +00:00
if (tDecodeDouble(pDecoder, &entry.inputRate) < 0) return -1;
if (tDecodeDouble(pDecoder, &entry.sinkQuota) < 0) return -1;
if (tDecodeDouble(pDecoder, &entry.sinkDataSize) < 0) return -1;
if (tDecodeI64(pDecoder, &entry.processedVer) < 0) return -1;
2023-10-02 18:37:52 +00:00
if (tDecodeI64(pDecoder, &entry.verStart) < 0) return -1;
if (tDecodeI64(pDecoder, &entry.verEnd) < 0) return -1;
if (tDecodeI64(pDecoder, &entry.activeCheckpointId) < 0) return -1;
if (tDecodeI8(pDecoder, (int8_t*)&entry.checkpointFailed) < 0) return -1;
if (tDecodeI32(pDecoder, &entry.chkpointTransId) < 0) return -1;
2023-09-20 02:35:01 +00:00
entry.id.taskId = taskId;
taosArrayPush(pReq->pTaskStatus, &entry);
}
int32_t numOfVgs = 0;
if (tDecodeI32(pDecoder, &numOfVgs) < 0) return -1;
pReq->pUpdateNodes = taosArrayInit(numOfVgs, sizeof(int32_t));
for (int j = 0; j < numOfVgs; ++j) {
int32_t vgId = 0;
if (tDecodeI32(pDecoder, &vgId) < 0) return -1;
taosArrayPush(pReq->pUpdateNodes, &vgId);
}
tEndDecode(pDecoder);
return 0;
}
static bool waitForEnoughDuration(SMetaHbInfo* pInfo) {
2023-10-07 09:48:24 +00:00
if ((++pInfo->tickCounter) >= META_HB_SEND_IDLE_COUNTER) { // reset the counter
pInfo->tickCounter = 0;
return true;
}
return false;
}
void streamMetaClearHbMsg(SStreamHbMsg* pMsg) {
if (pMsg == NULL) {
return;
}
if (pMsg->pUpdateNodes != NULL) {
taosArrayDestroy(pMsg->pUpdateNodes);
}
if (pMsg->pTaskStatus != NULL) {
taosArrayDestroy(pMsg->pTaskStatus);
}
2023-11-02 00:11:51 +00:00
}
2023-11-10 07:30:21 +00:00
static bool existInHbMsg(SStreamHbMsg* pMsg, SDownstreamTaskEpset* pTaskEpset) {
int32_t numOfExisted = taosArrayGetSize(pMsg->pUpdateNodes);
for (int k = 0; k < numOfExisted; ++k) {
if (pTaskEpset->nodeId == *(int32_t*)taosArrayGet(pMsg->pUpdateNodes, k)) {
return true;
}
}
return false;
}
static void addUpdateNodeIntoHbMsg(SStreamTask* pTask, SStreamHbMsg* pMsg) {
SStreamMeta* pMeta = pTask->pMeta;
taosThreadMutexLock(&pTask->lock);
int32_t num = taosArrayGetSize(pTask->outputInfo.pDownstreamUpdateList);
for (int j = 0; j < num; ++j) {
SDownstreamTaskEpset* pTaskEpset = taosArrayGet(pTask->outputInfo.pDownstreamUpdateList, j);
bool exist = existInHbMsg(pMsg, pTaskEpset);
if (!exist) {
taosArrayPush(pMsg->pUpdateNodes, &pTaskEpset->nodeId);
stDebug("vgId:%d nodeId:%d added into hb update list, total:%d", pMeta->vgId, pTaskEpset->nodeId,
(int32_t)taosArrayGetSize(pMsg->pUpdateNodes));
}
}
taosArrayClear(pTask->outputInfo.pDownstreamUpdateList);
taosThreadMutexUnlock(&pTask->lock);
}
static int32_t metaHeartbeatToMnodeImpl(SStreamMeta* pMeta) {
SStreamHbMsg hbMsg = {0};
2023-11-01 11:09:21 +00:00
SEpSet epset = {0};
bool hasMnodeEpset = false;
2023-12-23 08:37:21 +00:00
int32_t numOfTasks = streamMetaGetNumOfTasks(pMeta);
hbMsg.vgId = pMeta->vgId;
hbMsg.pTaskStatus = taosArrayInit(numOfTasks, sizeof(STaskStatusEntry));
hbMsg.pUpdateNodes = taosArrayInit(numOfTasks, sizeof(int32_t));
for (int32_t i = 0; i < numOfTasks; ++i) {
2023-12-23 08:37:21 +00:00
STaskId* pId = taosArrayGet(pMeta->pTaskList, i);
2023-11-01 11:09:21 +00:00
2023-09-16 13:37:30 +00:00
SStreamTask** pTask = taosHashGet(pMeta->pTasksMap, pId, sizeof(*pId));
2023-11-01 11:09:21 +00:00
if (pTask == NULL) {
continue;
}
2023-10-01 14:27:29 +00:00
// not report the status of fill-history task
if ((*pTask)->info.fillHistory == 1) {
continue;
}
2023-09-20 02:35:01 +00:00
STaskStatusEntry entry = {
2023-10-01 14:27:29 +00:00
.id = *pId,
2024-01-04 10:47:49 +00:00
.status = streamTaskGetStatus(*pTask)->state,
2023-11-01 11:09:21 +00:00
.nodeId = hbMsg.vgId,
2023-12-23 08:37:21 +00:00
.stage = pMeta->stage,
.inputQUsed = SIZE_IN_MiB(streamQueueGetItemSize((*pTask)->inputq.queue)),
2023-10-01 14:27:29 +00:00
};
2023-10-02 17:52:03 +00:00
2024-01-11 03:50:52 +00:00
entry.inputRate = entry.inputQUsed * 100.0 / (2*STREAM_TASK_QUEUE_CAPACITY_IN_SIZE);
if ((*pTask)->info.taskLevel == TASK_LEVEL__SINK) {
2023-10-07 11:16:55 +00:00
entry.sinkQuota = (*pTask)->outputInfo.pTokenBucket->quotaRate;
entry.sinkDataSize = SIZE_IN_MiB((*pTask)->execInfo.sink.dataSize);
}
if ((*pTask)->chkInfo.checkpointingId != 0) {
entry.checkpointFailed = ((*pTask)->chkInfo.failedId >= (*pTask)->chkInfo.checkpointingId);
entry.activeCheckpointId = (*pTask)->chkInfo.checkpointingId;
entry.chkpointTransId = (*pTask)->chkInfo.transId;
2023-12-24 15:30:00 +00:00
if (entry.checkpointFailed) {
stInfo("s-task:%s send kill checkpoint trans info, transId:%d", (*pTask)->id.idStr, (*pTask)->chkInfo.transId);
}
}
2023-10-02 18:39:57 +00:00
if ((*pTask)->exec.pWalReader != NULL) {
entry.processedVer = (*pTask)->chkInfo.nextProcessVer - 1;
2023-10-02 18:39:57 +00:00
walReaderValidVersionRange((*pTask)->exec.pWalReader, &entry.verStart, &entry.verEnd);
}
2023-10-01 14:27:29 +00:00
2023-11-10 07:30:21 +00:00
addUpdateNodeIntoHbMsg(*pTask, &hbMsg);
taosArrayPush(hbMsg.pTaskStatus, &entry);
if (!hasMnodeEpset) {
epsetAssign(&epset, &(*pTask)->info.mnodeEpset);
hasMnodeEpset = true;
}
}
hbMsg.numOfTasks = taosArrayGetSize(hbMsg.pTaskStatus);
if (hasMnodeEpset) {
2023-08-31 12:50:12 +00:00
int32_t code = 0;
int32_t tlen = 0;
2023-08-31 12:50:12 +00:00
tEncodeSize(tEncodeStreamHbMsg, &hbMsg, tlen, code);
if (code < 0) {
2023-09-20 10:18:31 +00:00
stError("vgId:%d encode stream hb msg failed, code:%s", pMeta->vgId, tstrerror(code));
2023-11-02 00:11:51 +00:00
goto _end;
2023-08-31 12:50:12 +00:00
}
2023-08-31 12:50:12 +00:00
void* buf = rpcMallocCont(tlen);
if (buf == NULL) {
2023-09-20 10:18:31 +00:00
stError("vgId:%d encode stream hb msg failed, code:%s", pMeta->vgId, tstrerror(TSDB_CODE_OUT_OF_MEMORY));
2023-11-02 00:11:51 +00:00
goto _end;
2023-08-31 12:50:12 +00:00
}
2023-07-28 06:23:53 +00:00
2023-08-31 12:50:12 +00:00
SEncoder encoder;
tEncoderInit(&encoder, buf, tlen);
if ((code = tEncodeStreamHbMsg(&encoder, &hbMsg)) < 0) {
rpcFreeCont(buf);
2023-09-20 10:18:31 +00:00
stError("vgId:%d encode stream hb msg failed, code:%s", pMeta->vgId, tstrerror(code));
2023-11-02 00:11:51 +00:00
goto _end;
2023-08-31 12:50:12 +00:00
}
tEncoderClear(&encoder);
2023-08-23 01:08:37 +00:00
SRpcMsg msg = {.info.noResp = 1};
2023-08-31 12:50:12 +00:00
initRpcMsg(&msg, TDMT_MND_STREAM_HEARTBEAT, buf, tlen);
2023-07-28 06:23:53 +00:00
pMeta->pHbInfo->hbCount += 1;
stDebug("vgId:%d build and send hb to mnode, numOfTasks:%d total:%d", pMeta->vgId, hbMsg.numOfTasks,
2023-10-07 09:48:24 +00:00
pMeta->pHbInfo->hbCount);
2023-08-31 12:50:12 +00:00
tmsgSendReq(&epset, &msg);
} else {
2023-09-20 10:18:31 +00:00
stDebug("vgId:%d no tasks and no mnd epset, not send stream hb to mnode", pMeta->vgId);
2023-08-31 12:50:12 +00:00
}
_end:
streamMetaClearHbMsg(&hbMsg);
return TSDB_CODE_SUCCESS;
}
void metaHbToMnode(void* param, void* tmrId) {
int64_t rid = *(int64_t*)param;
SStreamMeta* pMeta = taosAcquireRef(streamMetaId, rid);
if (pMeta == NULL) {
return;
}
// need to stop, stop now
if (pMeta->pHbInfo->stopFlag == STREAM_META_WILL_STOP) {
pMeta->pHbInfo->stopFlag = STREAM_META_OK_TO_STOP;
stDebug("vgId:%d jump out of meta timer", pMeta->vgId);
taosReleaseRef(streamMetaId, rid);
return;
}
// not leader not send msg
if (pMeta->role != NODE_ROLE_LEADER) {
stInfo("vgId:%d role:%d not leader not send hb to mnode", pMeta->vgId, pMeta->role);
taosReleaseRef(streamMetaId, rid);
pMeta->pHbInfo->hbStart = 0;
return;
}
// set the hb start time
if (pMeta->pHbInfo->hbStart == 0) {
pMeta->pHbInfo->hbStart = taosGetTimestampMs();
}
if (!waitForEnoughDuration(pMeta->pHbInfo)) {
taosTmrReset(metaHbToMnode, META_HB_CHECK_INTERVAL, param, streamTimer, &pMeta->pHbInfo->hbTmr);
taosReleaseRef(streamMetaId, rid);
return;
}
stDebug("vgId:%d build stream task hb, leader:%d", pMeta->vgId, (pMeta->role == NODE_ROLE_LEADER));
2023-12-23 08:37:21 +00:00
streamMetaRLock(pMeta);
metaHeartbeatToMnodeImpl(pMeta);
2023-12-23 08:37:21 +00:00
streamMetaRUnLock(pMeta);
taosTmrReset(metaHbToMnode, META_HB_CHECK_INTERVAL, param, streamTimer, &pMeta->pHbInfo->hbTmr);
2023-08-26 09:37:09 +00:00
taosReleaseRef(streamMetaId, rid);
2023-08-28 01:53:08 +00:00
}
bool streamMetaTaskInTimer(SStreamMeta* pMeta) {
2023-08-28 01:53:08 +00:00
bool inTimer = false;
2023-12-22 05:57:15 +00:00
streamMetaRLock(pMeta);
2023-08-28 01:53:08 +00:00
void* pIter = NULL;
while (1) {
2023-09-15 01:25:22 +00:00
pIter = taosHashIterate(pMeta->pTasksMap, pIter);
2023-08-28 01:53:08 +00:00
if (pIter == NULL) {
break;
}
SStreamTask* pTask = *(SStreamTask**)pIter;
if (pTask->status.timerActive >= 1) {
2023-12-20 10:07:53 +00:00
stDebug("s-task:%s in timer, blocking tasks in vgId:%d restart", pTask->id.idStr, pMeta->vgId);
2023-08-28 01:53:08 +00:00
inTimer = true;
}
}
2023-12-22 05:57:15 +00:00
streamMetaRUnLock(pMeta);
2023-08-28 01:53:08 +00:00
return inTimer;
}
void streamMetaNotifyClose(SStreamMeta* pMeta) {
int32_t vgId = pMeta->vgId;
stDebug("vgId:%d notify all stream tasks that the vnode is closing. isLeader:%d startHb:%" PRId64 ", totalHb:%d",
vgId, (pMeta->role == NODE_ROLE_LEADER), pMeta->pHbInfo->hbStart, pMeta->pHbInfo->hbCount);
2023-11-01 09:19:21 +00:00
streamMetaWLock(pMeta);
2023-08-28 01:53:08 +00:00
void* pIter = NULL;
while (1) {
2023-09-15 01:25:22 +00:00
pIter = taosHashIterate(pMeta->pTasksMap, pIter);
2023-08-28 01:53:08 +00:00
if (pIter == NULL) {
break;
}
SStreamTask* pTask = *(SStreamTask**)pIter;
2023-09-20 10:18:31 +00:00
stDebug("vgId:%d s-task:%s set closing flag", vgId, pTask->id.idStr);
2023-08-28 01:53:08 +00:00
streamTaskStop(pTask);
}
2023-11-01 09:19:21 +00:00
streamMetaWUnLock(pMeta);
2023-08-28 01:53:08 +00:00
// wait for the stream meta hb function stopping
2023-09-26 04:15:12 +00:00
if (pMeta->role == NODE_ROLE_LEADER) {
2024-01-09 01:13:53 +00:00
// pMeta->pHbInfo->stopFlag = STREAM_META_WILL_STOP;
// while (pMeta->pHbInfo->stopFlag != STREAM_META_OK_TO_STOP) {
// taosMsleep(100);
// stDebug("vgId:%d wait for meta to stop timer", pMeta->vgId);
// }
2023-08-28 01:53:08 +00:00
}
2023-09-20 10:18:31 +00:00
stDebug("vgId:%d start to check all tasks", vgId);
2023-08-28 01:53:08 +00:00
int64_t st = taosGetTimestampMs();
while (streamMetaTaskInTimer(pMeta)) {
2023-09-20 10:18:31 +00:00
stDebug("vgId:%d some tasks in timer, wait for 100ms and recheck", pMeta->vgId);
2023-08-28 01:53:08 +00:00
taosMsleep(100);
}
int64_t el = taosGetTimestampMs() - st;
2023-09-20 10:18:31 +00:00
stDebug("vgId:%d all stream tasks are not in timer, continue close, elapsed time:%" PRId64 " ms", pMeta->vgId, el);
2023-09-01 07:33:23 +00:00
}
2023-09-14 11:33:05 +00:00
void streamMetaStartHb(SStreamMeta* pMeta) {
int64_t* pRid = taosMemoryMalloc(sizeof(int64_t));
metaRefMgtAdd(pMeta->vgId, pRid);
*pRid = pMeta->rid;
metaHbToMnode(pRid, NULL);
2023-09-14 11:33:05 +00:00
}
2023-10-01 14:27:29 +00:00
void streamMetaResetStartInfo(STaskStartInfo* pStartInfo) {
taosHashClear(pStartInfo->pReadyTaskSet);
taosHashClear(pStartInfo->pFailedTaskSet);
pStartInfo->tasksWillRestart = 0;
pStartInfo->readyTs = 0;
// reset the sentinel flag value to be 0
pStartInfo->taskStarting = 0;
2023-11-01 09:19:21 +00:00
}
void streamMetaRLock(SStreamMeta* pMeta) {
2024-01-16 02:28:07 +00:00
// stTrace("vgId:%d meta-rlock", pMeta->vgId);
2023-12-22 08:14:49 +00:00
taosThreadRwlockRdlock(&pMeta->lock);
2023-11-01 09:19:21 +00:00
}
2023-12-19 08:21:11 +00:00
2023-11-01 09:19:21 +00:00
void streamMetaRUnLock(SStreamMeta* pMeta) {
2024-01-16 02:28:07 +00:00
// stTrace("vgId:%d meta-runlock", pMeta->vgId);
2023-12-22 16:09:55 +00:00
int32_t code = taosThreadRwlockUnlock(&pMeta->lock);
if (code != TSDB_CODE_SUCCESS) {
stError("vgId:%d meta-runlock failed, code:%d", pMeta->vgId, code);
} else {
2024-01-16 02:28:07 +00:00
// stDebug("vgId:%d meta-runlock completed", pMeta->vgId);
2023-12-22 16:09:55 +00:00
}
2023-11-01 09:19:21 +00:00
}
2023-12-19 08:21:11 +00:00
2023-11-01 09:19:21 +00:00
void streamMetaWLock(SStreamMeta* pMeta) {
2024-01-16 02:28:07 +00:00
// stTrace("vgId:%d meta-wlock", pMeta->vgId);
2023-12-22 08:14:49 +00:00
taosThreadRwlockWrlock(&pMeta->lock);
2024-01-16 02:28:07 +00:00
// stTrace("vgId:%d meta-wlock completed", pMeta->vgId);
2023-11-01 09:19:21 +00:00
}
2023-12-19 08:21:11 +00:00
2023-11-01 09:19:21 +00:00
void streamMetaWUnLock(SStreamMeta* pMeta) {
2024-01-16 02:28:07 +00:00
// stTrace("vgId:%d meta-wunlock", pMeta->vgId);
2023-12-22 08:14:49 +00:00
taosThreadRwlockUnlock(&pMeta->lock);
2023-11-01 09:19:21 +00:00
}
2023-12-19 08:21:11 +00:00
2023-11-08 09:10:54 +00:00
static void execHelper(struct SSchedMsg* pSchedMsg) {
__async_exec_fn_t execFn = (__async_exec_fn_t)pSchedMsg->ahandle;
int32_t code = execFn(pSchedMsg->thandle);
if (code != 0 && pSchedMsg->msg != NULL) {
*(int32_t*)pSchedMsg->msg = code;
}
}
int32_t streamMetaAsyncExec(SStreamMeta* pMeta, __stream_async_exec_fn_t fn, void* param, int32_t* code) {
SSchedMsg schedMsg = {0};
schedMsg.fp = execHelper;
schedMsg.ahandle = fn;
schedMsg.thandle = param;
schedMsg.msg = code;
return taosScheduleTask(pMeta->qHandle, &schedMsg);
}
SArray* streamMetaSendMsgBeforeCloseTasks(SStreamMeta* pMeta) {
2023-12-22 01:34:49 +00:00
SArray* pTaskList = taosArrayDup(pMeta->pTaskList, NULL);
2023-12-22 01:34:49 +00:00
bool sendMsg = pMeta->sendMsgBeforeClosing;
if (!sendMsg) {
stDebug("vgId:%d no need to send msg to mnode before closing tasks", pMeta->vgId);
return pTaskList;
}
stDebug("vgId:%d send msg to mnode before closing all tasks", pMeta->vgId);
// send hb msg to mnode before closing all tasks.
int32_t numOfTasks = taosArrayGetSize(pTaskList);
for (int32_t i = 0; i < numOfTasks; ++i) {
SStreamTaskId* pTaskId = taosArrayGet(pTaskList, i);
2023-12-23 07:33:50 +00:00
SStreamTask* pTask = streamMetaAcquireTaskNoLock(pMeta, pTaskId->streamId, pTaskId->taskId);
if (pTask == NULL) {
continue;
}
taosThreadMutexLock(&pTask->lock);
2024-01-04 10:47:49 +00:00
SStreamTaskState* pState = streamTaskGetStatus(pTask);
if (pState->state == TASK_STATUS__CK) {
streamTaskSetCheckpointFailedId(pTask);
stDebug("s-task:%s mark the checkpoint:%"PRId64" failed", pTask->id.idStr, pTask->chkInfo.checkpointingId);
} else {
2024-01-04 11:14:24 +00:00
stDebug("s-task:%s status:%s not reset the checkpoint", pTask->id.idStr, pState->name);
}
taosThreadMutexUnlock(&pTask->lock);
streamMetaReleaseTask(pMeta, pTask);
}
metaHeartbeatToMnodeImpl(pMeta);
pMeta->sendMsgBeforeClosing = false;
return pTaskList;
}
void streamMetaUpdateStageRole(SStreamMeta* pMeta, int64_t stage, bool isLeader) {
streamMetaWLock(pMeta);
int64_t prevStage = pMeta->stage;
pMeta->stage = stage;
// mark the sign to send msg before close all tasks
if ((!isLeader) && (pMeta->role == NODE_ROLE_LEADER)) {
pMeta->sendMsgBeforeClosing = true;
}
pMeta->role = (isLeader)? NODE_ROLE_LEADER:NODE_ROLE_FOLLOWER;
2023-12-22 16:58:52 +00:00
streamMetaWUnLock(pMeta);
if (isLeader) {
stInfo("vgId:%d update meta stage:%" PRId64 ", prev:%" PRId64 " leader:%d, start to send Hb", pMeta->vgId,
prevStage, stage, isLeader);
streamMetaStartHb(pMeta);
} else {
stInfo("vgId:%d update meta stage:%" PRId64 " prev:%" PRId64 " leader:%d sendMsg beforeClosing:%d", pMeta->vgId,
prevStage, stage, isLeader, pMeta->sendMsgBeforeClosing);
}
}
int32_t streamMetaStartAllTasks(SStreamMeta* pMeta) {
int32_t code = TSDB_CODE_SUCCESS;
int32_t vgId = pMeta->vgId;
int32_t numOfTasks = taosArrayGetSize(pMeta->pTaskList);
stInfo("vgId:%d start to check all %d stream task(s) downstream status", vgId, numOfTasks);
if (numOfTasks == 0) {
stInfo("vgId:%d start tasks completed", pMeta->vgId);
return TSDB_CODE_SUCCESS;
}
SArray* pTaskList = NULL;
streamMetaWLock(pMeta);
pTaskList = taosArrayDup(pMeta->pTaskList, NULL);
taosHashClear(pMeta->startInfo.pReadyTaskSet);
taosHashClear(pMeta->startInfo.pFailedTaskSet);
pMeta->startInfo.startTs = taosGetTimestampMs();
streamMetaWUnLock(pMeta);
// broadcast the check downstream tasks msg
int64_t now = taosGetTimestampMs();
for (int32_t i = 0; i < numOfTasks; ++i) {
SStreamTaskId* pTaskId = taosArrayGet(pTaskList, i);
SStreamTask* pTask = streamMetaAcquireTask(pMeta, pTaskId->streamId, pTaskId->taskId);
if (pTask == NULL) {
stError("vgId:%d failed to acquire task:0x%x during start tasks", pMeta->vgId, pTaskId->taskId);
2024-01-12 11:08:46 +00:00
streamMetaAddTaskLaunchResult(pMeta, pTaskId->streamId, pTaskId->taskId, 0, now, false);
continue;
}
// todo: may be we should find the related fill-history task and set it failed.
// fill-history task can only be launched by related stream tasks.
STaskExecStatisInfo* pInfo = &pTask->execInfo;
if (pTask->info.fillHistory == 1) {
stDebug("s-task:%s fill-history task wait related stream task start", pTask->id.idStr);
streamMetaReleaseTask(pMeta, pTask);
continue;
}
if (pTask->status.downstreamReady == 1) {
if (HAS_RELATED_FILLHISTORY_TASK(pTask)) {
stDebug("s-task:%s downstream ready, no need to check downstream, check only related fill-history task",
pTask->id.idStr);
streamLaunchFillHistoryTask(pTask);
}
2024-01-12 11:08:46 +00:00
streamMetaAddTaskLaunchResult(pMeta, pTaskId->streamId, pTaskId->taskId, pInfo->init, pInfo->start, true);
streamMetaReleaseTask(pMeta, pTask);
continue;
}
int32_t ret = streamTaskHandleEvent(pTask->status.pSM, TASK_EVENT_INIT);
if (ret != TSDB_CODE_SUCCESS) {
stError("vgId:%d failed to handle event:%d", pMeta->vgId, TASK_EVENT_INIT);
code = ret;
2024-01-12 11:08:46 +00:00
streamMetaAddTaskLaunchResult(pMeta, pTaskId->streamId, pTaskId->taskId, pInfo->init, pInfo->start, false);
if (HAS_RELATED_FILLHISTORY_TASK(pTask)) {
STaskId* pId = &pTask->hTaskInfo.id;
2024-01-12 11:08:46 +00:00
streamMetaAddTaskLaunchResult(pMeta, pId->streamId, pId->taskId, pInfo->init, pInfo->start, false);
}
}
streamMetaReleaseTask(pMeta, pTask);
}
stInfo("vgId:%d start tasks completed", pMeta->vgId);
taosArrayDestroy(pTaskList);
return code;
2024-01-05 09:55:39 +00:00
}
2024-01-15 03:28:36 +00:00
int32_t streamMetaStopAllTasks(SStreamMeta* pMeta) {
streamMetaRLock(pMeta);
int32_t num = taosArrayGetSize(pMeta->pTaskList);
stDebug("vgId:%d stop all %d stream task(s)", pMeta->vgId, num);
if (num == 0) {
streamMetaRUnLock(pMeta);
return TSDB_CODE_SUCCESS;
}
// send hb msg to mnode before closing all tasks.
SArray* pTaskList = streamMetaSendMsgBeforeCloseTasks(pMeta);
int32_t numOfTasks = taosArrayGetSize(pTaskList);
for (int32_t i = 0; i < numOfTasks; ++i) {
SStreamTaskId* pTaskId = taosArrayGet(pTaskList, i);
SStreamTask* pTask = streamMetaAcquireTaskNoLock(pMeta, pTaskId->streamId, pTaskId->taskId);
if (pTask == NULL) {
continue;
}
streamTaskStop(pTask);
streamMetaReleaseTask(pMeta, pTask);
}
taosArrayDestroy(pTaskList);
streamMetaRUnLock(pMeta);
return 0;
}
bool streamMetaAllTasksReady(const SStreamMeta* pMeta) {
int32_t num = taosArrayGetSize(pMeta->pTaskList);
for(int32_t i = 0; i < num; ++i) {
STaskId* pTaskId = taosArrayGet(pMeta->pTaskList, i);
SStreamTask** ppTask = taosHashGet(pMeta->pTasksMap, pTaskId, sizeof(*pTaskId));
if (ppTask == NULL) {
continue;
}
if ((*ppTask)->status.downstreamReady == 0) {
return false;
}
}
return true;
}
2024-01-05 09:55:39 +00:00
int32_t streamMetaStartOneTask(SStreamMeta* pMeta, int64_t streamId, int32_t taskId) {
int32_t vgId = pMeta->vgId;
stInfo("vgId:%d start to task:0x%x by checking downstream status", vgId, taskId);
SStreamTask* pTask = streamMetaAcquireTask(pMeta, streamId, taskId);
if (pTask == NULL) {
stError("vgId:%d failed to acquire task:0x%x during start tasks", pMeta->vgId, taskId);
2024-01-12 11:08:46 +00:00
streamMetaAddTaskLaunchResult(pMeta, streamId, taskId, 0, taosGetTimestampMs(), false);
2024-01-05 09:55:39 +00:00
return TSDB_CODE_STREAM_TASK_IVLD_STATUS;
}
// todo: may be we should find the related fill-history task and set it failed.
// fill-history task can only be launched by related stream tasks.
STaskExecStatisInfo* pInfo = &pTask->execInfo;
if (pTask->info.fillHistory == 1) {
streamMetaReleaseTask(pMeta, pTask);
return TSDB_CODE_SUCCESS;
}
ASSERT(pTask->status.downstreamReady == 0);
int32_t ret = streamTaskHandleEvent(pTask->status.pSM, TASK_EVENT_INIT);
if (ret != TSDB_CODE_SUCCESS) {
stError("vgId:%d failed to handle event:%d", pMeta->vgId, TASK_EVENT_INIT);
2024-01-12 11:08:46 +00:00
streamMetaAddTaskLaunchResult(pMeta, streamId, taskId, pInfo->init, pInfo->start, false);
2024-01-05 09:55:39 +00:00
if (HAS_RELATED_FILLHISTORY_TASK(pTask)) {
STaskId* pId = &pTask->hTaskInfo.id;
2024-01-12 11:08:46 +00:00
streamMetaAddTaskLaunchResult(pMeta, pId->streamId, pId->taskId, pInfo->init, pInfo->start, false);
2024-01-05 09:55:39 +00:00
}
}
streamMetaReleaseTask(pMeta, pTask);
2024-01-05 09:55:39 +00:00
return ret;
2024-01-15 03:28:36 +00:00
}
static void displayStatusInfo(SStreamMeta* pMeta, SHashObj* pTaskSet, bool succ) {
int32_t vgId = pMeta->vgId;
void* pIter = NULL;
size_t keyLen = 0;
stInfo("vgId:%d %d tasks check-downstream completed %s", vgId, taosHashGetSize(pTaskSet),
succ ? "success" : "failed");
while ((pIter = taosHashIterate(pTaskSet, pIter)) != NULL) {
STaskInitTs* pInfo = pIter;
void* key = taosHashGetKey(pIter, &keyLen);
SStreamTask** pTask1 = taosHashGet(pMeta->pTasksMap, key, sizeof(STaskId));
if (pTask1 == NULL) {
stInfo("s-task:0x%x is dropped already, %s", (int32_t)((STaskId*)key)->taskId, succ ? "success" : "failed");
} else {
stInfo("s-task:%s level:%d vgId:%d, init:%" PRId64 ", initEnd:%" PRId64 ", %s", (*pTask1)->id.idStr,
(*pTask1)->info.taskLevel, vgId, pInfo->start, pInfo->end, pInfo->success ? "success" : "failed");
}
}
}
int32_t streamMetaAddTaskLaunchResult(SStreamMeta* pMeta, int64_t streamId, int32_t taskId, int64_t startTs,
int64_t endTs, bool ready) {
STaskStartInfo* pStartInfo = &pMeta->startInfo;
STaskId id = {.streamId = streamId, .taskId = taskId};
streamMetaWLock(pMeta);
if (pStartInfo->taskStarting != 1) {
int64_t el = endTs - startTs;
qDebug("vgId:%d not start all task(s), not record status, s-task:0x%x launch succ:%d elapsed time:%" PRId64 "ms",
pMeta->vgId, taskId, ready, el);
streamMetaWUnLock(pMeta);
return 0;
}
SHashObj* pDst = ready ? pStartInfo->pReadyTaskSet : pStartInfo->pFailedTaskSet;
STaskInitTs initTs = {.start = startTs, .end = endTs, .success = ready};
taosHashPut(pDst, &id, sizeof(id), &initTs, sizeof(STaskInitTs));
int32_t numOfTotal = streamMetaGetNumOfTasks(pMeta);
int32_t numOfRecv = taosHashGetSize(pStartInfo->pReadyTaskSet) + taosHashGetSize(pStartInfo->pFailedTaskSet);
if (numOfRecv == numOfTotal) {
pStartInfo->readyTs = taosGetTimestampMs();
pStartInfo->elapsedTime = (pStartInfo->startTs != 0) ? pStartInfo->readyTs - pStartInfo->startTs : 0;
stDebug("vgId:%d all %d task(s) check downstream completed, last completed task:0x%x (succ:%d) startTs:%" PRId64
", readyTs:%" PRId64 " total elapsed time:%.2fs",
pMeta->vgId, numOfTotal, taskId, ready, pStartInfo->startTs, pStartInfo->readyTs,
pStartInfo->elapsedTime / 1000.0);
// print the initialization elapsed time and info
displayStatusInfo(pMeta, pStartInfo->pReadyTaskSet, true);
displayStatusInfo(pMeta, pStartInfo->pFailedTaskSet, false);
streamMetaResetStartInfo(pStartInfo);
streamMetaWUnLock(pMeta);
pStartInfo->completeFn(pMeta);
} else {
streamMetaWUnLock(pMeta);
stDebug("vgId:%d recv check downstream results, s-task:0x%x succ:%d, received:%d, total:%d", pMeta->vgId, taskId,
ready, numOfRecv, numOfTotal);
}
return TSDB_CODE_SUCCESS;
}