TDengine/source/dnode/vnode/src/vnd/vnodeCommit.c

570 lines
17 KiB
C
Raw Normal View History

2021-09-27 02:49:36 +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 "meta.h"
#include "sync.h"
2022-04-26 11:04:26 +00:00
#include "vnd.h"
2022-12-04 07:14:04 +00:00
#include "vnodeInt.h"
2022-12-02 07:44:24 +00:00
2023-03-23 08:10:08 +00:00
extern int32_t tsdbPreCommit(STsdb *pTsdb);
extern int32_t tsdbCommitBegin(STsdb *pTsdb, SCommitInfo *pInfo);
2023-04-11 03:00:35 +00:00
extern int32_t tsdbCommitCommit(STsdb *pTsdb);
extern int32_t tsdbCommitAbort(STsdb *pTsdb);
2023-03-23 08:10:08 +00:00
2022-04-15 05:47:57 +00:00
#define VND_INFO_FNAME_TMP "vnode_tmp.json"
2022-12-02 07:44:24 +00:00
static int vnodeEncodeInfo(const SVnodeInfo *pInfo, char **ppData);
static int vnodeCommitImpl(SCommitInfo *pInfo);
2021-09-27 02:49:36 +00:00
2023-01-06 07:24:27 +00:00
#define WAIT_TIME_MILI_SEC 10 // miliseconds
2023-01-09 02:09:31 +00:00
static int32_t vnodeTryRecycleBufPool(SVnode *pVnode) {
int32_t code = 0;
2023-01-09 06:54:49 +00:00
2023-01-09 11:03:09 +00:00
if (pVnode->onRecycle == NULL) {
if (pVnode->recycleHead == NULL) {
2023-01-30 09:46:42 +00:00
vDebug("vgId:%d, no recyclable buffer pool", TD_VID(pVnode));
2023-01-09 11:03:09 +00:00
goto _exit;
2023-01-09 06:54:49 +00:00
} else {
2023-01-30 09:46:42 +00:00
vDebug("vgId:%d, buffer pool %p of id %d on recycle queue, try to recycle", TD_VID(pVnode), pVnode->recycleHead,
2023-01-09 11:03:09 +00:00
pVnode->recycleHead->id);
pVnode->onRecycle = pVnode->recycleHead;
if (pVnode->recycleHead == pVnode->recycleTail) {
pVnode->recycleHead = pVnode->recycleTail = NULL;
} else {
pVnode->recycleHead = pVnode->recycleHead->recycleNext;
pVnode->recycleHead->recyclePrev = NULL;
}
pVnode->onRecycle->recycleNext = pVnode->onRecycle->recyclePrev = NULL;
2023-01-09 06:54:49 +00:00
}
2023-01-09 11:03:09 +00:00
}
2023-01-09 08:06:07 +00:00
2023-01-10 03:01:41 +00:00
code = vnodeBufPoolRecycle(pVnode->onRecycle);
if (code) goto _exit;
2022-04-20 06:56:34 +00:00
2023-01-09 02:09:31 +00:00
_exit:
2023-01-09 11:03:09 +00:00
if (code) {
2023-01-30 09:46:42 +00:00
vError("vgId:%d, %s failed since %s", TD_VID(pVnode), __func__, tstrerror(code));
2022-04-20 06:56:34 +00:00
}
2023-01-09 02:09:31 +00:00
return code;
}
2023-01-10 01:53:38 +00:00
static int32_t vnodeGetBufPoolToUse(SVnode *pVnode) {
int32_t code = 0;
2023-01-10 01:56:38 +00:00
int32_t lino = 0;
2022-04-20 06:56:34 +00:00
2024-07-27 10:28:26 +00:00
(void)taosThreadMutexLock(&pVnode->mutex);
2022-04-20 06:56:34 +00:00
2023-01-06 07:24:27 +00:00
int32_t nTry = 0;
2023-01-10 01:53:38 +00:00
for (;;) {
++nTry;
2023-01-09 02:09:31 +00:00
if (pVnode->freeList) {
2023-01-30 09:46:42 +00:00
vDebug("vgId:%d, allocate free buffer pool on %d try, pPool:%p id:%d", TD_VID(pVnode), nTry, pVnode->freeList,
2023-01-09 06:54:49 +00:00
pVnode->freeList->id);
2022-04-20 06:56:34 +00:00
2023-01-09 02:09:31 +00:00
pVnode->inUse = pVnode->freeList;
pVnode->inUse->nRef = 1;
pVnode->freeList = pVnode->inUse->freeNext;
pVnode->inUse->freeNext = NULL;
break;
} else {
2023-01-30 09:46:42 +00:00
vDebug("vgId:%d, no free buffer pool on %d try, try to recycle...", TD_VID(pVnode), nTry);
2023-01-10 01:56:38 +00:00
code = vnodeTryRecycleBufPool(pVnode);
TSDB_CHECK_CODE(code, lino, _exit);
2023-01-09 02:09:31 +00:00
if (pVnode->freeList == NULL) {
2023-01-30 09:46:42 +00:00
vDebug("vgId:%d, no free buffer pool on %d try, wait %d ms...", TD_VID(pVnode), nTry, WAIT_TIME_MILI_SEC);
2023-01-09 02:09:31 +00:00
struct timeval tv;
struct timespec ts;
2024-07-29 05:54:50 +00:00
(void)taosGetTimeOfDay(&tv);
2023-01-09 02:09:31 +00:00
ts.tv_nsec = tv.tv_usec * 1000 + WAIT_TIME_MILI_SEC * 1000000;
2023-01-10 09:00:25 +00:00
if (ts.tv_nsec > 999999999l) {
ts.tv_sec = tv.tv_sec + 1;
ts.tv_nsec -= 1000000000l;
} else {
ts.tv_sec = tv.tv_sec;
}
2023-01-09 02:09:31 +00:00
int32_t rc = taosThreadCondTimedWait(&pVnode->poolNotEmpty, &pVnode->mutex, &ts);
if (rc && rc != ETIMEDOUT) {
2023-01-10 01:56:38 +00:00
code = TAOS_SYSTEM_ERROR(rc);
TSDB_CHECK_CODE(code, lino, _exit);
2023-01-09 02:09:31 +00:00
}
}
2023-01-06 07:24:27 +00:00
}
}
2022-04-20 06:56:34 +00:00
2023-01-10 01:53:38 +00:00
_exit:
2024-07-27 10:28:26 +00:00
(void)taosThreadMutexUnlock(&pVnode->mutex);
2023-01-10 01:56:38 +00:00
if (code) {
2023-01-30 09:46:42 +00:00
vError("vgId:%d, %s failed at line %d since %s", TD_VID(pVnode), __func__, lino, tstrerror(code));
2023-01-10 01:56:38 +00:00
}
2023-01-10 01:53:38 +00:00
return code;
}
int vnodeBegin(SVnode *pVnode) {
int32_t code = 0;
int32_t lino = 0;
2022-04-19 13:10:03 +00:00
2023-01-10 01:53:38 +00:00
// alloc buffer pool
code = vnodeGetBufPoolToUse(pVnode);
TSDB_CHECK_CODE(code, lino, _exit);
2022-04-19 13:10:03 +00:00
// begin meta
2024-07-22 11:40:07 +00:00
code = metaBegin(pVnode->pMeta, META_BEGIN_HEAP_BUFFERPOOL);
TSDB_CHECK_CODE(code, lino, _exit);
2022-04-19 13:10:03 +00:00
// begin tsdb
2024-07-22 11:40:07 +00:00
code = tsdbBegin(pVnode->pTsdb);
TSDB_CHECK_CODE(code, lino, _exit);
2022-05-01 16:30:47 +00:00
2022-07-02 07:17:41 +00:00
// begin sma
2024-07-22 11:40:07 +00:00
if (VND_IS_RSMA(pVnode)) {
code = smaBegin(pVnode->pSma);
2023-01-10 01:53:38 +00:00
TSDB_CHECK_CODE(code, lino, _exit);
2022-10-19 11:59:35 +00:00
}
2022-07-02 07:17:41 +00:00
2023-01-10 01:53:38 +00:00
_exit:
if (code) {
2023-01-10 09:00:25 +00:00
terrno = code;
2023-01-30 09:46:42 +00:00
vError("vgId:%d, %s failed at line %d since %s", TD_VID(pVnode), __func__, lino, tstrerror(code));
2023-01-10 01:53:38 +00:00
}
return code;
2022-04-19 13:10:03 +00:00
}
int vnodeShouldCommit(SVnode *pVnode, bool atExit) {
bool diskAvail = osDataSpaceAvailable();
bool needCommit = false;
2022-12-23 12:16:23 +00:00
2024-07-27 10:28:26 +00:00
(void)taosThreadMutexLock(&pVnode->mutex);
2023-03-24 01:05:06 +00:00
if (pVnode->inUse && diskAvail) {
needCommit = (pVnode->inUse->size > pVnode->inUse->node.size) ||
(atExit && (pVnode->inUse->size > 0 || pVnode->pMeta->changed ||
pVnode->state.applied - pVnode->state.committed > 4096));
2022-06-26 10:44:49 +00:00
}
2024-06-04 09:13:48 +00:00
vTrace("vgId:%d, should commit:%d, disk available:%d, buffer size:%" PRId64 ", node size:%" PRId64
", meta changed:%d"
", state:[%" PRId64 ",%" PRId64 "]",
TD_VID(pVnode), needCommit, diskAvail, pVnode->inUse ? pVnode->inUse->size : 0,
pVnode->inUse ? pVnode->inUse->node.size : 0, pVnode->pMeta->changed, pVnode->state.applied,
pVnode->state.committed);
2024-07-27 10:28:26 +00:00
(void)taosThreadMutexUnlock(&pVnode->mutex);
return needCommit;
2022-06-26 10:44:49 +00:00
}
2022-04-20 08:50:45 +00:00
2022-04-15 05:47:57 +00:00
int vnodeSaveInfo(const char *dir, const SVnodeInfo *pInfo) {
2024-07-22 11:40:07 +00:00
int32_t code = 0;
int32_t lino;
2022-04-15 05:47:57 +00:00
char fname[TSDB_FILENAME_LEN];
2024-07-22 11:40:07 +00:00
TdFilePtr pFile = NULL;
char *data = NULL;
2022-04-15 05:47:57 +00:00
snprintf(fname, TSDB_FILENAME_LEN, "%s%s%s", dir, TD_DIRSEP, VND_INFO_FNAME_TMP);
2024-07-22 11:40:07 +00:00
code = vnodeEncodeInfo(pInfo, &data);
TSDB_CHECK_CODE(code, lino, _exit);
2022-04-15 05:47:57 +00:00
// save info to a vnode_tmp.json
2023-11-21 08:31:31 +00:00
pFile = taosOpenFile(fname, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC | TD_FILE_WRITE_THROUGH);
2022-04-15 05:47:57 +00:00
if (pFile == NULL) {
2024-07-22 11:40:07 +00:00
TSDB_CHECK_CODE(code = TAOS_SYSTEM_ERROR(errno), lino, _exit);
2022-04-15 05:47:57 +00:00
}
2022-04-15 06:27:04 +00:00
if (taosWriteFile(pFile, data, strlen(data)) < 0) {
2024-07-22 11:40:07 +00:00
TSDB_CHECK_CODE(code = TAOS_SYSTEM_ERROR(errno), lino, _exit);
2022-04-15 05:47:57 +00:00
}
if (taosFsyncFile(pFile) < 0) {
2024-07-22 11:40:07 +00:00
TSDB_CHECK_CODE(code = TAOS_SYSTEM_ERROR(errno), lino, _exit);
2022-04-15 05:47:57 +00:00
}
2024-07-22 11:40:07 +00:00
_exit:
if (code) {
vError("vgId:%d %s failed at %s:%d since %s", pInfo->config.vgId, __func__, __FILE__, lino, tstrerror(code));
} else {
vInfo("vgId:%d, vnode info is saved, fname:%s replica:%d selfIndex:%d changeVersion:%d", pInfo->config.vgId, fname,
pInfo->config.syncCfg.replicaNum, pInfo->config.syncCfg.myIndex, pInfo->config.syncCfg.changeVersion);
}
2024-07-29 05:54:50 +00:00
(void)taosCloseFile(&pFile);
2022-04-15 05:47:57 +00:00
taosMemoryFree(data);
2024-07-22 11:40:07 +00:00
return code;
2022-04-15 05:47:57 +00:00
}
2023-02-10 08:24:29 +00:00
int vnodeCommitInfo(const char *dir) {
2022-04-15 05:47:57 +00:00
char fname[TSDB_FILENAME_LEN];
char tfname[TSDB_FILENAME_LEN];
snprintf(fname, TSDB_FILENAME_LEN, "%s%s%s", dir, TD_DIRSEP, VND_INFO_FNAME);
snprintf(tfname, TSDB_FILENAME_LEN, "%s%s%s", dir, TD_DIRSEP, VND_INFO_FNAME_TMP);
if (taosRenameFile(tfname, fname) < 0) {
2024-07-22 11:40:07 +00:00
return terrno = TAOS_SYSTEM_ERROR(errno);
2022-04-15 05:47:57 +00:00
}
2023-02-10 08:24:29 +00:00
vInfo("vnode info is committed, dir:%s", dir);
2022-04-15 05:47:57 +00:00
return 0;
}
2022-04-15 07:07:44 +00:00
int vnodeLoadInfo(const char *dir, SVnodeInfo *pInfo) {
2024-07-22 11:40:07 +00:00
int32_t code = 0;
int32_t lino;
2022-04-15 07:07:44 +00:00
char fname[TSDB_FILENAME_LEN];
TdFilePtr pFile = NULL;
char *pData = NULL;
int64_t size;
snprintf(fname, TSDB_FILENAME_LEN, "%s%s%s", dir, TD_DIRSEP, VND_INFO_FNAME);
// read info
pFile = taosOpenFile(fname, TD_FILE_READ);
if (pFile == NULL) {
2024-07-22 11:40:07 +00:00
TSDB_CHECK_CODE(code = TAOS_SYSTEM_ERROR(errno), lino, _exit);
2022-04-15 07:07:44 +00:00
}
if (taosFStatFile(pFile, &size, NULL) < 0) {
2024-07-22 11:40:07 +00:00
TSDB_CHECK_CODE(code = TAOS_SYSTEM_ERROR(errno), lino, _exit);
2022-04-15 07:07:44 +00:00
}
2022-04-16 07:16:10 +00:00
pData = taosMemoryMalloc(size + 1);
2022-04-15 07:07:44 +00:00
if (pData == NULL) {
2024-07-22 11:40:07 +00:00
TSDB_CHECK_CODE(code = TSDB_CODE_OUT_OF_MEMORY, lino, _exit);
2022-04-15 07:07:44 +00:00
}
if (taosReadFile(pFile, pData, size) < 0) {
2024-07-22 11:40:07 +00:00
TSDB_CHECK_CODE(code = TAOS_SYSTEM_ERROR(errno), lino, _exit);
2022-04-15 07:07:44 +00:00
}
2022-04-16 07:16:10 +00:00
pData[size] = '\0';
2022-04-15 07:07:44 +00:00
// decode info
2024-07-22 11:40:07 +00:00
code = vnodeDecodeInfo(pData, pInfo);
TSDB_CHECK_CODE(code, lino, _exit);
2022-04-15 07:07:44 +00:00
2024-07-22 11:40:07 +00:00
_exit:
if (code) {
2024-07-30 09:48:08 +00:00
if (pFile) {
vError("vgId:%d %s failed at %s:%d since %s", pInfo->config.vgId, __func__, __FILE__, lino, tstrerror(code));
}
2024-07-22 11:40:07 +00:00
}
2022-04-15 07:07:44 +00:00
taosMemoryFree(pData);
2024-07-29 05:54:50 +00:00
(void)taosCloseFile(&pFile);
2024-07-22 11:40:07 +00:00
return code;
2022-04-15 05:47:57 +00:00
}
2023-02-10 08:24:29 +00:00
static int32_t vnodePrepareCommit(SVnode *pVnode, SCommitInfo *pInfo) {
int32_t code = 0;
int32_t lino = 0;
char dir[TSDB_FILENAME_LEN] = {0};
int64_t lastCommitted = pInfo->info.state.committed;
2023-11-29 10:01:31 +00:00
// wait last commit task
2024-07-29 05:54:50 +00:00
(void)vnodeAWait(&pVnode->commitTask);
2022-12-01 12:26:56 +00:00
2024-07-22 11:40:07 +00:00
code = syncNodeGetConfig(pVnode->sync, &pVnode->config.syncCfg);
TSDB_CHECK_CODE(code, lino, _exit);
2023-08-16 02:20:48 +00:00
pVnode->state.commitTerm = pVnode->state.applyTerm;
pInfo->info.config = pVnode->config;
pInfo->info.state.committed = pVnode->state.applied;
pInfo->info.state.commitTerm = pVnode->state.applyTerm;
2023-02-10 08:24:29 +00:00
pInfo->info.state.commitID = ++pVnode->state.commitID;
pInfo->pVnode = pVnode;
pInfo->txn = metaGetTxn(pVnode->pMeta);
// save info
2024-07-29 05:54:50 +00:00
(void)vnodeGetPrimaryDir(pVnode->path, pVnode->diskPrimary, pVnode->pTfs, dir, TSDB_FILENAME_LEN);
vDebug("vgId:%d, save config while prepare commit", TD_VID(pVnode));
2024-07-22 11:40:07 +00:00
code = vnodeSaveInfo(dir, &pInfo->info);
TSDB_CHECK_CODE(code, lino, _exit);
2024-07-29 12:14:15 +00:00
(void)tsdbPreCommit(pVnode->pTsdb);
2022-12-04 12:26:58 +00:00
2024-07-22 11:40:07 +00:00
code = metaPrepareAsyncCommit(pVnode->pMeta);
TSDB_CHECK_CODE(code, lino, _exit);
code = smaPrepareAsyncCommit(pVnode->pSma);
2024-07-22 11:40:07 +00:00
TSDB_CHECK_CODE(code, lino, _exit);
2022-12-04 12:26:58 +00:00
2024-07-27 10:28:26 +00:00
(void)taosThreadMutexLock(&pVnode->mutex);
2023-01-28 09:00:53 +00:00
pVnode->onCommit = pVnode->inUse;
pVnode->inUse = NULL;
2024-07-27 10:28:26 +00:00
(void)taosThreadMutexUnlock(&pVnode->mutex);
2023-01-28 09:00:53 +00:00
_exit:
if (code) {
vError("vgId:%d, %s failed at line %d since %s, commit id:%" PRId64, TD_VID(pVnode), __func__, lino,
tstrerror(code), pVnode->state.commitID);
} else {
2023-02-10 10:01:22 +00:00
vDebug("vgId:%d, %s done, commit id:%" PRId64, TD_VID(pVnode), __func__, pInfo->info.state.commitID);
}
return code;
2022-12-01 12:26:56 +00:00
}
2023-01-10 03:01:41 +00:00
static void vnodeReturnBufPool(SVnode *pVnode) {
2024-07-27 10:28:26 +00:00
(void)taosThreadMutexLock(&pVnode->mutex);
2023-01-09 11:03:09 +00:00
SVBufPool *pPool = pVnode->onCommit;
int32_t nRef = atomic_sub_fetch_32(&pPool->nRef, 1);
2023-01-09 06:54:49 +00:00
pVnode->onCommit = NULL;
if (nRef == 0) {
2023-01-10 03:01:41 +00:00
vnodeBufPoolAddToFreeList(pPool);
2023-01-09 11:03:09 +00:00
} else if (nRef > 0) {
2023-01-30 09:46:42 +00:00
vDebug("vgId:%d, buffer pool %p of id %d is added to recycle queue", TD_VID(pVnode), pPool, pPool->id);
2023-01-09 06:54:49 +00:00
if (pVnode->recycleTail == NULL) {
pPool->recyclePrev = pPool->recycleNext = NULL;
pVnode->recycleHead = pVnode->recycleTail = pPool;
} else {
pPool->recyclePrev = pVnode->recycleTail;
pPool->recycleNext = NULL;
pVnode->recycleTail->recycleNext = pPool;
pVnode->recycleTail = pPool;
}
2023-01-09 11:03:09 +00:00
} else {
2024-08-20 02:43:28 +00:00
vError("vgId:%d, buffer pool %p of id %d nRef:%d", TD_VID(pVnode), pPool, pPool->id, nRef);
2023-01-09 06:54:49 +00:00
}
2024-07-27 10:28:26 +00:00
(void)taosThreadMutexUnlock(&pVnode->mutex);
2023-01-10 03:01:41 +00:00
}
2024-05-23 09:57:07 +00:00
static int32_t vnodeCommit(void *arg) {
2022-12-01 12:26:56 +00:00
int32_t code = 0;
2022-12-02 07:44:24 +00:00
SCommitInfo *pInfo = (SCommitInfo *)arg;
2023-01-10 03:01:41 +00:00
SVnode *pVnode = pInfo->pVnode;
2022-12-01 12:26:56 +00:00
2022-12-02 07:44:24 +00:00
// commit
2024-05-23 09:57:07 +00:00
if ((code = vnodeCommitImpl(pInfo))) {
vFatal("vgId:%d, failed to commit vnode since %s", TD_VID(pVnode), terrstr());
taosMsleep(100);
exit(EXIT_FAILURE);
goto _exit;
}
2022-12-01 12:26:56 +00:00
2023-01-10 03:01:41 +00:00
vnodeReturnBufPool(pVnode);
2023-01-09 06:54:49 +00:00
_exit:
2024-05-23 09:57:07 +00:00
taosMemoryFree(arg);
2022-12-01 12:26:56 +00:00
return code;
}
2022-12-23 12:16:23 +00:00
2024-05-23 09:57:07 +00:00
static void vnodeCommitCancel(void *arg) { taosMemoryFree(arg); }
2023-11-29 10:01:31 +00:00
2021-09-27 02:49:36 +00:00
int vnodeAsyncCommit(SVnode *pVnode) {
2022-12-01 12:26:56 +00:00
int32_t code = 0;
2024-05-23 09:57:07 +00:00
int32_t lino = 0;
2022-01-06 06:34:20 +00:00
2022-12-02 07:44:24 +00:00
SCommitInfo *pInfo = (SCommitInfo *)taosMemoryCalloc(1, sizeof(*pInfo));
2022-12-01 12:26:56 +00:00
if (NULL == pInfo) {
TSDB_CHECK_CODE(code = terrno, lino, _exit);
2022-12-01 12:26:56 +00:00
}
// prepare to commit
code = vnodePrepareCommit(pVnode, pInfo);
2024-05-23 09:57:07 +00:00
TSDB_CHECK_CODE(code, lino, _exit);
// schedule the task
2024-05-23 09:57:07 +00:00
code =
vnodeAsync(&pVnode->commitChannel, EVA_PRIORITY_HIGH, vnodeCommit, vnodeCommitCancel, pInfo, &pVnode->commitTask);
TSDB_CHECK_CODE(code, lino, _exit);
2022-04-14 06:16:43 +00:00
2022-12-01 12:26:56 +00:00
_exit:
if (code) {
2024-05-23 09:57:07 +00:00
taosMemoryFree(pInfo);
vError("vgId:%d %s failed at line %d since %s" PRId64, TD_VID(pVnode), __func__, lino, tstrerror(code));
2022-12-01 12:26:56 +00:00
} else {
vInfo("vgId:%d, vnode async commit done, commitId:%" PRId64 " term:%" PRId64 " applied:%" PRId64, TD_VID(pVnode),
pVnode->state.commitID, pVnode->state.applyTerm, pVnode->state.applied);
2022-12-01 12:26:56 +00:00
}
return code;
2021-12-14 06:32:07 +00:00
}
2021-09-27 02:49:36 +00:00
2022-01-06 06:34:20 +00:00
int vnodeSyncCommit(SVnode *pVnode) {
2024-07-29 05:54:50 +00:00
(void)vnodeAsyncCommit(pVnode);
(void)vnodeAWait(&pVnode->commitTask);
2022-01-06 06:34:20 +00:00
return 0;
}
2022-12-02 07:44:24 +00:00
static int vnodeCommitImpl(SCommitInfo *pInfo) {
int32_t code = 0;
int32_t lino = 0;
char dir[TSDB_FILENAME_LEN] = {0};
SVnode *pVnode = pInfo->pVnode;
2022-04-24 07:34:53 +00:00
vInfo("vgId:%d, start to commit, commitId:%" PRId64 " version:%" PRId64 " term: %" PRId64, TD_VID(pVnode),
2022-12-23 12:16:23 +00:00
pInfo->info.state.commitID, pInfo->info.state.committed, pInfo->info.state.commitTerm);
// persist wal before starting
2024-08-14 09:50:20 +00:00
if ((code = walPersist(pVnode->pWal)) < 0) {
vError("vgId:%d, failed to persist wal since %s", TD_VID(pVnode), tstrerror(code));
return code;
}
2024-07-29 05:54:50 +00:00
(void)vnodeGetPrimaryDir(pVnode->path, pVnode->diskPrimary, pVnode->pTfs, dir, TSDB_FILENAME_LEN);
2024-07-29 05:54:50 +00:00
(void)syncBeginSnapshot(pVnode->sync, pInfo->info.state.committed);
2022-04-24 07:34:53 +00:00
2023-03-23 08:10:08 +00:00
code = tsdbCommitBegin(pVnode->pTsdb, pInfo);
2022-10-19 11:52:09 +00:00
TSDB_CHECK_CODE(code, lino, _exit);
if (!TSDB_CACHE_NO(pVnode->config)) {
code = tsdbCacheCommit(pVnode->pTsdb);
TSDB_CHECK_CODE(code, lino, _exit);
}
2022-06-01 07:06:12 +00:00
if (VND_IS_RSMA(pVnode)) {
2022-12-04 07:14:04 +00:00
code = smaCommit(pVnode->pSma, pInfo);
2022-10-18 08:54:53 +00:00
TSDB_CHECK_CODE(code, lino, _exit);
2022-04-24 07:34:53 +00:00
}
2022-05-02 10:16:43 +00:00
2022-04-24 07:34:53 +00:00
// commit info
2024-07-22 11:40:07 +00:00
code = vnodeCommitInfo(dir);
TSDB_CHECK_CODE(code, lino, _exit);
2022-07-06 09:46:14 +00:00
2023-04-11 03:00:35 +00:00
code = tsdbCommitCommit(pVnode->pTsdb);
2022-10-19 11:52:09 +00:00
TSDB_CHECK_CODE(code, lino, _exit);
2022-10-19 09:18:41 +00:00
if (VND_IS_RSMA(pVnode)) {
code = smaFinishCommit(pVnode->pSma);
TSDB_CHECK_CODE(code, lino, _exit);
}
2022-10-18 08:54:53 +00:00
2024-07-22 11:40:07 +00:00
code = metaFinishCommit(pVnode->pMeta, pInfo->txn);
TSDB_CHECK_CODE(code, lino, _exit);
2022-12-02 07:44:24 +00:00
pVnode->state.committed = pInfo->info.state.committed;
2022-04-24 07:34:53 +00:00
if (smaPostCommit(pVnode->pSma) < 0) {
vError("vgId:%d, failed to post-commit sma since %s", TD_VID(pVnode), tstrerror(terrno));
2022-08-20 15:28:48 +00:00
return -1;
}
2022-04-24 07:34:53 +00:00
2024-07-29 05:54:50 +00:00
(void)syncEndSnapshot(pVnode->sync);
2022-04-24 07:34:53 +00:00
2022-10-18 08:54:53 +00:00
_exit:
if (code) {
2022-10-21 02:39:19 +00:00
vError("vgId:%d, %s failed at line %d since %s", TD_VID(pVnode), __func__, lino, tstrerror(code));
2022-10-18 08:54:53 +00:00
} else {
vInfo("vgId:%d, commit end", TD_VID(pVnode));
}
2024-07-22 11:40:07 +00:00
return code;
2022-04-24 07:34:53 +00:00
}
2022-10-18 05:38:26 +00:00
bool vnodeShouldRollback(SVnode *pVnode) {
2023-11-29 10:01:31 +00:00
char tFName[TSDB_FILENAME_LEN] = {0};
int32_t offset = 0;
2024-07-29 05:54:50 +00:00
(void)vnodeGetPrimaryDir(pVnode->path, pVnode->diskPrimary, pVnode->pTfs, tFName, TSDB_FILENAME_LEN);
offset = strlen(tFName);
snprintf(tFName + offset, TSDB_FILENAME_LEN - offset - 1, "%s%s", TD_DIRSEP, VND_INFO_FNAME_TMP);
2022-10-18 05:38:26 +00:00
return taosCheckExistFile(tFName);
}
void vnodeRollback(SVnode *pVnode) {
2023-11-29 10:01:31 +00:00
char tFName[TSDB_FILENAME_LEN] = {0};
int32_t offset = 0;
2024-07-29 05:54:50 +00:00
(void)vnodeGetPrimaryDir(pVnode->path, pVnode->diskPrimary, pVnode->pTfs, tFName, TSDB_FILENAME_LEN);
offset = strlen(tFName);
snprintf(tFName + offset, TSDB_FILENAME_LEN - offset - 1, "%s%s", TD_DIRSEP, VND_INFO_FNAME_TMP);
2022-10-18 05:38:26 +00:00
2024-07-22 11:40:07 +00:00
TAOS_UNUSED(taosRemoveFile(tFName));
2022-10-18 05:38:26 +00:00
}
2022-04-15 06:27:04 +00:00
static int vnodeEncodeState(const void *pObj, SJson *pJson) {
const SVState *pState = (SVState *)pObj;
2024-07-22 11:40:07 +00:00
TAOS_CHECK_RETURN(tjsonAddIntegerToObject(pJson, "commit version", pState->committed));
TAOS_CHECK_RETURN(tjsonAddIntegerToObject(pJson, "commit ID", pState->commitID));
TAOS_CHECK_RETURN(tjsonAddIntegerToObject(pJson, "commit term", pState->commitTerm));
2022-04-15 06:27:04 +00:00
return 0;
}
static int vnodeDecodeState(const SJson *pJson, void *pObj) {
SVState *pState = (SVState *)pObj;
int32_t code;
tjsonGetNumberValue(pJson, "commit version", pState->committed, code);
2024-07-22 11:40:07 +00:00
if (code) return code;
2022-06-23 03:08:19 +00:00
tjsonGetNumberValue(pJson, "commit ID", pState->commitID, code);
2024-07-22 11:40:07 +00:00
if (code) return code;
2022-07-06 09:46:14 +00:00
tjsonGetNumberValue(pJson, "commit term", pState->commitTerm, code);
2024-07-22 11:40:07 +00:00
if (code) return code;
2022-04-15 06:27:04 +00:00
return 0;
}
static int vnodeEncodeInfo(const SVnodeInfo *pInfo, char **ppData) {
2024-07-22 11:40:07 +00:00
int32_t code = 0;
int32_t lino;
SJson *pJson = NULL;
char *pData = NULL;
2022-04-15 06:27:04 +00:00
pJson = tjsonCreateObject();
if (pJson == NULL) {
2024-07-22 11:40:07 +00:00
TSDB_CHECK_CODE(code = terrno, lino, _exit);
2022-04-15 06:27:04 +00:00
}
2024-07-22 11:40:07 +00:00
code = tjsonAddObject(pJson, "config", vnodeEncodeConfig, (void *)&pInfo->config);
TSDB_CHECK_CODE(code, lino, _exit);
2022-04-15 06:27:04 +00:00
2024-07-22 11:40:07 +00:00
code = tjsonAddObject(pJson, "state", vnodeEncodeState, (void *)&pInfo->state);
TSDB_CHECK_CODE(code, lino, _exit);
2022-04-15 06:27:04 +00:00
pData = tjsonToString(pJson);
if (pData == NULL) {
2024-07-22 11:40:07 +00:00
TSDB_CHECK_CODE(code = terrno, lino, _exit);
2022-04-15 06:27:04 +00:00
}
tjsonDelete(pJson);
2024-07-22 11:40:07 +00:00
_exit:
if (code) {
tjsonDelete(pJson);
*ppData = NULL;
} else {
*ppData = pData;
}
return code;
2022-04-15 05:47:57 +00:00
}
2022-12-09 07:50:22 +00:00
int vnodeDecodeInfo(uint8_t *pData, SVnodeInfo *pInfo) {
2024-07-22 11:40:07 +00:00
int32_t code = 0;
int32_t lino;
SJson *pJson = NULL;
2022-04-15 06:27:04 +00:00
2022-04-16 07:26:11 +00:00
pJson = tjsonParse(pData);
2022-04-15 06:27:04 +00:00
if (pJson == NULL) {
2024-07-22 11:40:07 +00:00
TSDB_CHECK_CODE(code = TSDB_CODE_INVALID_DATA_FMT, lino, _exit);
2022-04-15 06:27:04 +00:00
}
2024-07-22 11:40:07 +00:00
code = tjsonToObject(pJson, "config", vnodeDecodeConfig, (void *)&pInfo->config);
TSDB_CHECK_CODE(code, lino, _exit);
2022-04-15 06:27:04 +00:00
2024-07-22 11:40:07 +00:00
code = tjsonToObject(pJson, "state", vnodeDecodeState, (void *)&pInfo->state);
TSDB_CHECK_CODE(code, lino, _exit);
2022-04-15 06:27:04 +00:00
2024-07-22 11:40:07 +00:00
_exit:
2022-04-15 06:27:04 +00:00
tjsonDelete(pJson);
2024-07-22 11:40:07 +00:00
return code;
2022-04-15 05:47:57 +00:00
}