From edc2b20d8a2c358c40122003f53935ccb640fd51 Mon Sep 17 00:00:00 2001 From: chen dongming Date: Tue, 12 May 2026 16:22:39 +0800 Subject: [PATCH 01/12] feat: [6984169049] improve-long-snapshot --- source/dnode/vnode/src/inc/tsdb.h | 1 - source/dnode/vnode/src/inc/vnodeInt.h | 2 +- source/dnode/vnode/src/tsdb/tsdbFS2.c | 46 +++++++++++++++++++ source/dnode/vnode/src/tsdb/tsdbFS2.h | 1 + source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c | 17 ++++--- source/dnode/vnode/src/vnd/vnodeSnapshot.c | 10 ++-- 6 files changed, 65 insertions(+), 12 deletions(-) diff --git a/source/dnode/vnode/src/inc/tsdb.h b/source/dnode/vnode/src/inc/tsdb.h index 296c0ad63cdc..b59c2c9be11a 100644 --- a/source/dnode/vnode/src/inc/tsdb.h +++ b/source/dnode/vnode/src/inc/tsdb.h @@ -717,7 +717,6 @@ int32_t tsdbFSetPartListToRangeDiff(STsdbFSetPartList *pList, TFileSe typedef enum ETsdbRepFmt { TSDB_SNAP_REP_FMT_DEFAULT = 0, TSDB_SNAP_REP_FMT_RAW, - TSDB_SNAP_REP_FMT_HYBRID, } ETsdbRepFmt; typedef struct STsdbRepOpts { diff --git a/source/dnode/vnode/src/inc/vnodeInt.h b/source/dnode/vnode/src/inc/vnodeInt.h index 457c15bd7e87..89e55cfd3ffb 100644 --- a/source/dnode/vnode/src/inc/vnodeInt.h +++ b/source/dnode/vnode/src/inc/vnodeInt.h @@ -342,7 +342,7 @@ int32_t tsdbSnapWrite(STsdbSnapWriter* pWriter, SSnapDataHdr* pHdr); int32_t tsdbSnapWriterPrepareClose(STsdbSnapWriter* pWriter, bool rollback); int32_t tsdbSnapWriterClose(STsdbSnapWriter** ppWriter, int8_t rollback); // STsdbSnapRAWReader ======================================== -int32_t tsdbSnapRAWReaderOpen(STsdb* pTsdb, int64_t ever, int8_t type, STsdbSnapRAWReader** ppReader); +int32_t tsdbSnapRAWReaderOpen(STsdb* pTsdb, int64_t ever, int8_t type, void* pRanges, STsdbSnapRAWReader** ppReader); void tsdbSnapRAWReaderClose(STsdbSnapRAWReader** ppReader); int32_t tsdbSnapRAWRead(STsdbSnapRAWReader* pReader, uint8_t** ppData); // STsdbSnapRAWWriter ======================================== diff --git a/source/dnode/vnode/src/tsdb/tsdbFS2.c b/source/dnode/vnode/src/tsdb/tsdbFS2.c index a9dee797bd95..7d66a5ebfbe1 100644 --- a/source/dnode/vnode/src/tsdb/tsdbFS2.c +++ b/source/dnode/vnode/src/tsdb/tsdbFS2.c @@ -1086,6 +1086,52 @@ static SHashObj *tsdbFSetRangeArrayToHash(TFileSetRangeArray *pRanges) { return pHash; } +int32_t tsdbFSCreateRefSnapshotWithRanges(STFileSystem *fs, TFileSetRangeArray *pRanges, TFileSetArray **fsetArr) { + int32_t code = 0; + STFileSet *fset, *fset1; + SHashObj *pHash = NULL; + + fsetArr[0] = taosMemoryCalloc(1, sizeof(*fsetArr[0])); + if (fsetArr[0] == NULL) return terrno; + + pHash = tsdbFSetRangeArrayToHash(pRanges); + if (pHash == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _out; + } + + (void)taosThreadMutexLock(&fs->tsdb->mutex); + TARRAY2_FOREACH(fs->fSetArr, fset) { + int32_t fid = fset->fid; + if (taosHashGet(pHash, &fid, sizeof(fid)) == NULL) { + tsdbDebug("skip fid:%d, not in ranges", fid); + continue; + } + + code = tsdbTFileSetInitRef(fs->tsdb, fset, &fset1); + if (code) break; + + code = TARRAY2_APPEND(fsetArr[0], fset1); + if (code) { + tsdbTFileSetClear(&fset1); + break; + } + } + (void)taosThreadMutexUnlock(&fs->tsdb->mutex); + + if (code) { + TARRAY2_DESTROY(fsetArr[0], tsdbTFileSetClear); + taosMemoryFree(fsetArr[0]); + fsetArr[0] = NULL; + } + +_out: + if (pHash) { + taosHashCleanup(pHash); + } + return code; +} + int32_t tsdbFSCreateCopyRangedSnapshot(STFileSystem *fs, TFileSetRangeArray *pRanges, TFileSetArray **fsetArr, TFileOpArray *fopArr) { int32_t code = 0; diff --git a/source/dnode/vnode/src/tsdb/tsdbFS2.h b/source/dnode/vnode/src/tsdb/tsdbFS2.h index 9694edcdd918..ccf3c7b3f64f 100644 --- a/source/dnode/vnode/src/tsdb/tsdbFS2.h +++ b/source/dnode/vnode/src/tsdb/tsdbFS2.h @@ -45,6 +45,7 @@ int32_t tsdbFSCreateCopySnapshot(STFileSystem *fs, TFileSetArray **fsetArr); void tsdbFSDestroyCopySnapshot(TFileSetArray **fsetArr); int32_t tsdbFSCreateRefSnapshot(STFileSystem *fs, TFileSetArray **fsetArr); int32_t tsdbFSCreateRefSnapshotWithoutLock(STFileSystem *fs, TFileSetArray **fsetArr); +int32_t tsdbFSCreateRefSnapshotWithRanges(STFileSystem *fs, TFileSetRangeArray *pRanges, TFileSetArray **fsetArr); void tsdbFSDestroyRefSnapshot(TFileSetArray **fsetArr); int32_t tsdbFSCreateCopyRangedSnapshot(STFileSystem *fs, TFileSetRangeArray *pExclude, TFileSetArray **fsetArr, diff --git a/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c b/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c index 254a9c5a2e1a..ca6c04fa2c32 100644 --- a/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c +++ b/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c @@ -47,7 +47,7 @@ typedef struct STsdbSnapRAWReader { SDataFileRAWReaderIter dataIter[1]; } STsdbSnapRAWReader; -int32_t tsdbSnapRAWReaderOpen(STsdb* tsdb, int64_t ever, int8_t type, STsdbSnapRAWReader** reader) { +int32_t tsdbSnapRAWReaderOpen(STsdb* tsdb, int64_t ever, int8_t type, void* pRanges, STsdbSnapRAWReader** reader) { int32_t code = 0; int32_t lino = 0; @@ -58,19 +58,24 @@ int32_t tsdbSnapRAWReaderOpen(STsdb* tsdb, int64_t ever, int8_t type, STsdbSnapR reader[0]->ever = ever; reader[0]->type = type; - code = tsdbFSCreateRefSnapshot(tsdb->pFS, &reader[0]->fsetArr); + TFileSetRangeArray* pTypedRanges = (TFileSetRangeArray*)pRanges; + if (pTypedRanges != NULL && TARRAY2_SIZE(pTypedRanges) > 0) { + code = tsdbFSCreateRefSnapshotWithRanges(tsdb->pFS, pTypedRanges, &reader[0]->fsetArr); + } else { + code = tsdbFSCreateRefSnapshot(tsdb->pFS, &reader[0]->fsetArr); + } TSDB_CHECK_CODE(code, lino, _exit); _exit: if (code) { - tsdbError("vgId:%d %s failed at line %d since %s, sver:0, ever:%" PRId64 " type:%d", TD_VID(tsdb->pVnode), __func__, - lino, tstrerror(code), ever, type); + tsdbError("vgId:%d %s failed at line %d since %s, ever:%" PRId64 " type:%d", TD_VID(tsdb->pVnode), __func__, lino, + tstrerror(code), ever, type); tsdbFSDestroyRefSnapshot(&reader[0]->fsetArr); taosMemoryFree(reader[0]); reader[0] = NULL; } else { - tsdbInfo("vgId:%d, tsdb snapshot raw reader opened. sver:0, ever:%" PRId64 " type:%d", TD_VID(tsdb->pVnode), ever, - type); + tsdbInfo("vgId:%d, tsdb snapshot raw reader opened. ever:%" PRId64 " type:%d ranged:%d", TD_VID(tsdb->pVnode), ever, + type, (pTypedRanges != NULL && TARRAY2_SIZE(pTypedRanges) > 0)); } return code; } diff --git a/source/dnode/vnode/src/vnd/vnodeSnapshot.c b/source/dnode/vnode/src/vnd/vnodeSnapshot.c index feec2404b9c6..a70117d469ad 100644 --- a/source/dnode/vnode/src/vnd/vnodeSnapshot.c +++ b/source/dnode/vnode/src/vnd/vnodeSnapshot.c @@ -143,8 +143,9 @@ static int32_t vnodeSnapReaderDealWithSnapInfo(SVSnapReader *pReader, SSnapshotP } // toggle snap replication mode - vInfo("vgId:%d, vnode snap reader supported tsdb rep of format:%d", TD_VID(pVnode), tsdbOpts.format); - if (pReader->sver == 0 && tsdbOpts.format == TSDB_SNAP_REP_FMT_RAW) { + vInfo("vgId:%d, vnode snap reader supported tsdb rep of format:%d, sver:%" PRId64, TD_VID(pVnode), tsdbOpts.format, + pReader->sver); + if (tsdbOpts.format == TSDB_SNAP_REP_FMT_RAW) { pReader->tsdbDone = true; } else { pReader->tsdbRAWDone = true; @@ -179,7 +180,7 @@ int32_t vnodeSnapReaderOpen(SVnode *pVnode, SSnapshotParam *pParam, SVSnapReader // open tsdb snapshot raw reader if (!pReader->tsdbRAWDone) { - code = tsdbSnapRAWReaderOpen(pVnode->pTsdb, ever, SNAP_DATA_RAW, &pReader->pTsdbRAWReader); + code = tsdbSnapRAWReaderOpen(pVnode->pTsdb, ever, SNAP_DATA_RAW, pReader->pRanges, &pReader->pTsdbRAWReader); if (code) goto _exit; } @@ -349,7 +350,8 @@ int32_t vnodeSnapRead(SVSnapReader *pReader, uint8_t **ppData, uint32_t *nData) if (!pReader->tsdbRAWDone) { // open if not if (pReader->pTsdbRAWReader == NULL) { - code = tsdbSnapRAWReaderOpen(pReader->pVnode->pTsdb, pReader->ever, SNAP_DATA_RAW, &pReader->pTsdbRAWReader); + code = tsdbSnapRAWReaderOpen(pReader->pVnode->pTsdb, pReader->ever, SNAP_DATA_RAW, pReader->pRanges, + &pReader->pTsdbRAWReader); TSDB_CHECK_CODE(code, lino, _exit); } From e1ec7a1b4486ab359ae60af39cadb399011c8a10 Mon Sep 17 00:00:00 2001 From: chen dongming Date: Wed, 13 May 2026 11:10:27 +0800 Subject: [PATCH 02/12] feat: long snapshot filter file --- source/dnode/vnode/src/inc/tsdb.h | 5 + source/dnode/vnode/src/inc/vnodeInt.h | 6 +- source/dnode/vnode/src/sma/smaSnapshot.c | 2 +- source/dnode/vnode/src/tsdb/tsdbFS2.c | 22 +- source/dnode/vnode/src/tsdb/tsdbFS2.h | 2 +- source/dnode/vnode/src/tsdb/tsdbSnapInfo.c | 284 +++++++++++++++++- source/dnode/vnode/src/tsdb/tsdbSnapshot.c | 50 ++- source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c | 73 ++++- source/dnode/vnode/src/vnd/vnodeSnapshot.c | 52 +++- 9 files changed, 474 insertions(+), 22 deletions(-) diff --git a/source/dnode/vnode/src/inc/tsdb.h b/source/dnode/vnode/src/inc/tsdb.h index b59c2c9be11a..6ab17fddfaa9 100644 --- a/source/dnode/vnode/src/inc/tsdb.h +++ b/source/dnode/vnode/src/inc/tsdb.h @@ -726,6 +726,11 @@ typedef struct STsdbRepOpts { int32_t tSerializeTsdbRepOpts(void *buf, int32_t bufLen, STsdbRepOpts *pInfo); int32_t tDeserializeTsdbRepOpts(void *buf, int32_t bufLen, STsdbRepOpts *pInfo); +int32_t tMissingFileListDataLenCalc(const char **fnames, int32_t fileCount); +int32_t tSerializeMissingFileList(void *buf, int32_t bufLen, const char **fnames, int32_t fileCount); +int32_t tDeserializeMissingFileList(void *buf, int32_t bufLen, SHashObj **ppHash); +int32_t tsdbExtractMissingFids(STsdb *pTsdb, SHashObj *missingFileHash, int32_t **ppFids, int32_t *pFidCount); + // snap read struct STsdbReadSnap { SMemTable *pMem; diff --git a/source/dnode/vnode/src/inc/vnodeInt.h b/source/dnode/vnode/src/inc/vnodeInt.h index 89e55cfd3ffb..76d4d9dd209f 100644 --- a/source/dnode/vnode/src/inc/vnodeInt.h +++ b/source/dnode/vnode/src/inc/vnodeInt.h @@ -333,7 +333,7 @@ int32_t metaSnapWrite(SMetaSnapWriter* pWriter, uint8_t* pData, uint32_t nData); int32_t metaSnapWriterClose(SMetaSnapWriter** ppWriter, int8_t rollback); // STsdbSnapReader ======================================== int32_t tsdbSnapReaderOpen(STsdb* pTsdb, int64_t sver, int64_t ever, int8_t type, void* pRanges, - STsdbSnapReader** ppReader); + const int32_t* missingFids, int32_t missingFidCount, STsdbSnapReader** ppReader); void tsdbSnapReaderClose(STsdbSnapReader** ppReader); int32_t tsdbSnapRead(STsdbSnapReader* pReader, uint8_t** ppData); // STsdbSnapWriter ======================================== @@ -342,7 +342,8 @@ int32_t tsdbSnapWrite(STsdbSnapWriter* pWriter, SSnapDataHdr* pHdr); int32_t tsdbSnapWriterPrepareClose(STsdbSnapWriter* pWriter, bool rollback); int32_t tsdbSnapWriterClose(STsdbSnapWriter** ppWriter, int8_t rollback); // STsdbSnapRAWReader ======================================== -int32_t tsdbSnapRAWReaderOpen(STsdb* pTsdb, int64_t ever, int8_t type, void* pRanges, STsdbSnapRAWReader** ppReader); +int32_t tsdbSnapRAWReaderOpen(STsdb* pTsdb, int64_t ever, int8_t type, void* pRanges, SHashObj* missingFileHash, + const int32_t* missingFids, int32_t missingFidCount, STsdbSnapRAWReader** ppReader); void tsdbSnapRAWReaderClose(STsdbSnapRAWReader** ppReader); int32_t tsdbSnapRAWRead(STsdbSnapRAWReader* pReader, uint8_t** ppData); // STsdbSnapRAWWriter ======================================== @@ -585,6 +586,7 @@ enum { SNAP_DATA_STREAM_STATE_BACKEND = 12, SNAP_DATA_TQ_CHECKINFO = 13, SNAP_DATA_RAW = 14, + SNAP_DATA_MISSING_FIDS = 16, }; struct SSnapDataHdr { diff --git a/source/dnode/vnode/src/sma/smaSnapshot.c b/source/dnode/vnode/src/sma/smaSnapshot.c index 5836b69b5fd6..e21816453548 100644 --- a/source/dnode/vnode/src/sma/smaSnapshot.c +++ b/source/dnode/vnode/src/sma/smaSnapshot.c @@ -48,7 +48,7 @@ int32_t rsmaSnapReaderOpen(SSma* pSma, int64_t sver, int64_t ever, SRSmaSnapRead for (int32_t i = 0; i < TSDB_RETENTION_L2; ++i) { if (pSma->pRSmaTsdb[i]) { code = tsdbSnapReaderOpen(pSma->pRSmaTsdb[i], sver, ever, (i == 0 ? SNAP_DATA_RSMA1 : SNAP_DATA_RSMA2), NULL, - &pReader->pDataReader[i]); + NULL, 0, &pReader->pDataReader[i]); TAOS_CHECK_GOTO(code, &lino, _exit); } } diff --git a/source/dnode/vnode/src/tsdb/tsdbFS2.c b/source/dnode/vnode/src/tsdb/tsdbFS2.c index 7d66a5ebfbe1..ff1da0bb61eb 100644 --- a/source/dnode/vnode/src/tsdb/tsdbFS2.c +++ b/source/dnode/vnode/src/tsdb/tsdbFS2.c @@ -1185,7 +1185,21 @@ int32_t tsdbFSCreateCopyRangedSnapshot(STFileSystem *fs, TFileSetRangeArray *pRa void tsdbFSDestroyCopyRangedSnapshot(TFileSetArray **fsetArr) { tsdbFSDestroyCopySnapshot(fsetArr); } +static bool tsdbFSFidInMissingSet(int32_t fid, const int32_t *missingFids, int32_t missingFidCount) { + int32_t lo = 0, hi = missingFidCount - 1; + while (lo <= hi) { + int32_t mid = lo + (hi - lo) / 2; + if (missingFids[mid] == fid) return true; + if (missingFids[mid] < fid) + lo = mid + 1; + else + hi = mid - 1; + } + return false; +} + int32_t tsdbFSCreateRefRangedSnapshot(STFileSystem *fs, int64_t sver, int64_t ever, TFileSetRangeArray *pRanges, + const int32_t *missingFids, int32_t missingFidCount, TFileSetRangeArray **fsrArr) { int32_t code = 0; STFileSet *fset; @@ -1212,6 +1226,12 @@ int32_t tsdbFSCreateRefRangedSnapshot(STFileSystem *fs, int64_t sver, int64_t ev int64_t sver1 = sver; int64_t ever1 = ever; + // skip fids not in missing-fid filter + if (missingFids != NULL && !tsdbFSFidInMissingSet(fset->fid, missingFids, missingFidCount)) { + tsdbDebug("vgId:%d, skip fid:%d not in missing-fid set", TD_VID(fs->tsdb->pVnode), fset->fid); + continue; + } + if (pHash) { int32_t fid = fset->fid; STFileSetRange *u = taosHashGet(pHash, &fid, sizeof(fid)); @@ -1226,7 +1246,7 @@ int32_t tsdbFSCreateRefRangedSnapshot(STFileSystem *fs, int64_t sver, int64_t ev continue; } - tsdbDebug("fsrArr:%p, fid:%d, sver:%" PRId64 ", ever:%" PRId64, fsrArr, fset->fid, sver1, ever1); + tsdbInfo("fsrArr:%p, fid:%d, sver:%" PRId64 ", ever:%" PRId64, fsrArr, fset->fid, sver1, ever1); code = tsdbTFileSetRangeInitRef(fs->tsdb, fset, sver1, ever1, &fsr1); if (code) break; diff --git a/source/dnode/vnode/src/tsdb/tsdbFS2.h b/source/dnode/vnode/src/tsdb/tsdbFS2.h index ccf3c7b3f64f..cb46a76baa95 100644 --- a/source/dnode/vnode/src/tsdb/tsdbFS2.h +++ b/source/dnode/vnode/src/tsdb/tsdbFS2.h @@ -52,7 +52,7 @@ int32_t tsdbFSCreateCopyRangedSnapshot(STFileSystem *fs, TFileSetRangeArray *pEx TFileOpArray *fopArr); void tsdbFSDestroyCopyRangedSnapshot(TFileSetArray **fsetArr); int32_t tsdbFSCreateRefRangedSnapshot(STFileSystem *fs, int64_t sver, int64_t ever, TFileSetRangeArray *pRanges, - TFileSetRangeArray **fsrArr); + const int32_t *missingFids, int32_t missingFidCount, TFileSetRangeArray **fsrArr); void tsdbFSDestroyRefRangedSnapshot(TFileSetRangeArray **fsrArr); // txn int64_t tsdbFSAllocEid(STFileSystem *fs); diff --git a/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c b/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c index 53bace994156..efe518cf77e0 100644 --- a/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c +++ b/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c @@ -529,6 +529,257 @@ int32_t tDeserializeTsdbRepOpts(void* buf, int32_t bufLen, STsdbRepOpts* pOpts) return code; } +int32_t tMissingFileListDataLenCalc(const char** fnames, int32_t fileCount) { + int32_t hdrLen = sizeof(int32_t); + int32_t datLen = 0; + + int8_t msgVer = 0; + hdrLen += sizeof(msgVer); + datLen += hdrLen; + datLen += sizeof(int32_t); // fileCount + for (int32_t i = 0; i < fileCount; ++i) { + datLen += sizeof(int32_t) + (int32_t)strlen(fnames[i]) + 1; // tEncodeCStr overhead + } + return datLen; +} + +int32_t tSerializeMissingFileList(void* buf, int32_t bufLen, const char** fnames, int32_t fileCount) { + int32_t code = 0; + SEncoder encoder = {0}; + int8_t msgVer = TSDB_SNAP_MSG_VER; + + tEncoderInit(&encoder, buf, bufLen); + + if ((code = tStartEncode(&encoder))) goto _err; + if ((code = tEncodeI8(&encoder, msgVer))) goto _err; + if ((code = tEncodeI32(&encoder, fileCount))) goto _err; + for (int32_t i = 0; i < fileCount; ++i) { + if ((code = tEncodeCStr(&encoder, fnames[i]))) goto _err; + } + + tEndEncode(&encoder); + int32_t tlen = encoder.pos; + tEncoderClear(&encoder); + return tlen; + +_err: + tEncoderClear(&encoder); + return code; +} + +int32_t tDeserializeMissingFileList(void* buf, int32_t bufLen, SHashObj** ppHash) { + int32_t code = 0; + SDecoder decoder = {0}; + int8_t msgVer = 0; + int32_t fileCount = 0; + SHashObj* pHash = NULL; + + tDecoderInit(&decoder, buf, bufLen); + + if ((code = tStartDecode(&decoder))) goto _err; + if ((code = tDecodeI8(&decoder, &msgVer))) goto _err; + if (msgVer != TSDB_SNAP_MSG_VER) { + code = TSDB_CODE_INVALID_MSG; + goto _err; + } + if ((code = tDecodeI32(&decoder, &fileCount))) goto _err; + if (fileCount < 0) { + code = TSDB_CODE_INVALID_MSG; + goto _err; + } + if (fileCount > 0) { + pHash = taosHashInit(fileCount * 2, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK); + if (pHash == NULL) { + code = terrno; + goto _err; + } + for (int32_t i = 0; i < fileCount; ++i) { + char* fname = NULL; + if ((code = tDecodeCStr(&decoder, &fname))) goto _err; + char dummy = 0; + tsdbDebug("Missing File fname:%s", fname); + if (taosHashPut(pHash, fname, strlen(fname), &dummy, sizeof(dummy)) != 0) { + code = terrno; + goto _err; + } + } + } + + tEndDecode(&decoder); + tDecoderClear(&decoder); + + *ppHash = pHash; + return 0; + +_err: + if (pHash) taosHashCleanup(pHash); + tDecoderClear(&decoder); + return code; +} + +int32_t tsdbExtractMissingFids(STsdb* pTsdb, SHashObj* missingFileHash, int32_t** ppFids, int32_t* pFidCount) { + int32_t code = 0; + int32_t fidCap = 0; + int32_t fidCount = 0; + int32_t* fids = NULL; + + (void)taosThreadMutexLock(&pTsdb->mutex); + + STFileSet* fset; + TARRAY2_FOREACH(pTsdb->pFS->fSetArr, fset) { + bool hasMissing = false; + + // check farr + for (int32_t ftype = 0; ftype < TSDB_FTYPE_MAX; ++ftype) { + if (fset->farr[ftype] != NULL) { + const char* base = strrchr(fset->farr[ftype]->fname, TD_DIRSEP_CHAR); + base = (base != NULL) ? base + 1 : fset->farr[ftype]->fname; + if (taosHashGet(missingFileHash, base, strlen(base)) != NULL) { + hasMissing = true; + break; + } + } + } + + // check stt + if (!hasMissing) { + SSttLvl* lvl; + TARRAY2_FOREACH(fset->lvlArr, lvl) { + STFileObj* fobj; + TARRAY2_FOREACH(lvl->fobjArr, fobj) { + const char* base = strrchr(fobj->fname, TD_DIRSEP_CHAR); + base = (base != NULL) ? base + 1 : fobj->fname; + if (taosHashGet(missingFileHash, base, strlen(base)) != NULL) { + hasMissing = true; + break; + } + } + if (hasMissing) break; + } + } + + if (hasMissing) { + if (fidCount >= fidCap) { + int32_t newCap = fidCap == 0 ? 16 : fidCap * 2; + int32_t* tmp = taosMemoryRealloc(fids, newCap * sizeof(int32_t)); + if (tmp == NULL) { + code = terrno; + (void)taosThreadMutexUnlock(&pTsdb->mutex); + taosMemoryFree(fids); + return code; + } + fids = tmp; + fidCap = newCap; + } + fids[fidCount++] = fset->fid; + } + } + + (void)taosThreadMutexUnlock(&pTsdb->mutex); + + *ppFids = fids; + *pFidCount = fidCount; + return 0; +} + +static int32_t tsdbDetectMissingFiles(SVnode* pVnode, char*** ppFnames, int32_t* pFnameCount) { + int32_t code = 0; + char** fnames = NULL; + int32_t fnameCount = 0; + int32_t fnameCap = 0; + STsdb* pTsdb = pVnode->pTsdb; + + *ppFnames = NULL; + *pFnameCount = 0; + + (void)taosThreadMutexLock(&pTsdb->mutex); + + STFileSet* fset; + TARRAY2_FOREACH(pTsdb->pFS->fSetArr, fset) { + // check farr entries (HEAD, DATA, SMA, TOMB) + for (int32_t ftype = TSDB_FTYPE_MIN; ftype < TSDB_FTYPE_MAX; ++ftype) { + if (fset->farr[ftype] != NULL) { + if (!taosCheckExistFile(fset->farr[ftype]->fname)) { + if (fnameCount >= fnameCap) { + int32_t newCap = fnameCap == 0 ? 16 : fnameCap * 2; + char** tmp = taosMemoryRealloc(fnames, newCap * sizeof(char*)); + if (tmp == NULL) { + code = terrno; + goto _unlock; + } + fnames = tmp; + fnameCap = newCap; + } + const char* base = strrchr(fset->farr[ftype]->fname, TD_DIRSEP_CHAR); + base = (base != NULL) ? base + 1 : fset->farr[ftype]->fname; + fnames[fnameCount] = taosStrdup(base); + if (fnames[fnameCount] == NULL) { + code = terrno; + goto _unlock; + } + fnameCount++; + } + } + } + + // check STT files in lvlArr + SSttLvl* lvl; + TARRAY2_FOREACH(fset->lvlArr, lvl) { + STFileObj* fobj; + TARRAY2_FOREACH(lvl->fobjArr, fobj) { + if (!taosCheckExistFile(fobj->fname)) { + if (fnameCount >= fnameCap) { + int32_t newCap = fnameCap == 0 ? 16 : fnameCap * 2; + char** tmp = taosMemoryRealloc(fnames, newCap * sizeof(char*)); + if (tmp == NULL) { + code = terrno; + goto _unlock; + } + fnames = tmp; + fnameCap = newCap; + } + const char* base = strrchr(fobj->fname, TD_DIRSEP_CHAR); + base = (base != NULL) ? base + 1 : fobj->fname; + fnames[fnameCount] = taosStrdup(base); + if (fnames[fnameCount] == NULL) { + code = terrno; + goto _unlock; + } + fnameCount++; + } + } + } + } + +_unlock: + (void)taosThreadMutexUnlock(&pTsdb->mutex); + + if (code != 0) { + for (int32_t i = 0; i < fnameCount; ++i) { + taosMemoryFree(fnames[i]); + } + taosMemoryFree(fnames); + return code; + } + + *ppFnames = fnames; + *pFnameCount = fnameCount; + return 0; +} + +static int32_t tsdbMissingFilesEstSize(const char** fnames, int32_t fileCount) { + return sizeof(SSyncTLV) + tMissingFileListDataLenCalc(fnames, fileCount); +} + +static int32_t tsdbMissingFilesSerialize(const char** fnames, int32_t fileCount, void* buf, int32_t bufLen) { + SSyncTLV* pSubHead = buf; + int32_t tlen = tSerializeMissingFileList(pSubHead->val, bufLen - sizeof(*pSubHead), fnames, fileCount); + if (tlen < 0) return tlen; + pSubHead->typ = SNAP_DATA_MISSING_FIDS; + pSubHead->len = tlen; + return sizeof(*pSubHead) + tlen; +} + static int32_t tsdbRepOptsEstSize(STsdbRepOpts* pOpts) { int32_t dataLen = 0; dataLen += sizeof(SSyncTLV); @@ -578,9 +829,8 @@ static int32_t tsdbSnapPrepDealWithSnapInfo(SVnode* pVnode, SSnapshot* pSnap, ST } } break; default: - code = TSDB_CODE_INVALID_MSG; - tsdbError("vgId:%d, unexpected subfield type of snap info. typ:%d", TD_VID(pVnode), pField->typ); - return code; + tsdbWarn("vgId:%d, unknown subfield type in snap info, skipping. typ:%d", TD_VID(pVnode), pField->typ); + break; } } @@ -599,6 +849,8 @@ int32_t tsdbSnapPrepDescription(SVnode* pVnode, SSnapshot* pSnap) { // deal with snap info for reply STsdbRepOpts opts = {.format = TSDB_SNAP_REP_FMT_RAW}; + char** missingFiles = NULL; + int32_t missingFileCount = 0; if (pSnap->type == TDMT_SYNC_PREP_SNAPSHOT_REPLY) { STsdbRepOpts leaderOpts = {0}; if ((code = tsdbSnapPrepDealWithSnapInfo(pVnode, pSnap, &leaderOpts)) < 0) { @@ -606,6 +858,15 @@ int32_t tsdbSnapPrepDescription(SVnode* pVnode, SSnapshot* pSnap) { goto _out; } opts.format = TMIN(opts.format, leaderOpts.format); + + int32_t detectCode = tsdbDetectMissingFiles(pVnode, &missingFiles, &missingFileCount); + if (detectCode != 0) { + tsdbWarn("vgId:%d, failed to detect missing files since %s, continuing without", TD_VID(pVnode), + tstrerror(detectCode)); + missingFileCount = 0; + } else if (missingFileCount > 0) { + tsdbInfo("vgId:%d, detected %d missing files for snapshot", TD_VID(pVnode), missingFileCount); + } } // info data realloc @@ -613,6 +874,9 @@ int32_t tsdbSnapPrepDescription(SVnode* pVnode, SSnapshot* pSnap) { int32_t bufLen = headLen; bufLen += tsdbPartitionInfoEstSize(pInfo); bufLen += tsdbRepOptsEstSize(&opts); + if (missingFileCount > 0) { + bufLen += tsdbMissingFilesEstSize((const char**)missingFiles, missingFileCount); + } if ((code = syncSnapInfoDataRealloc(pSnap, bufLen)) != 0) { tsdbError("vgId:%d, failed to realloc memory for data of snap info. bytes:%d", TD_VID(pVnode), bufLen); goto _out; @@ -637,6 +901,16 @@ int32_t tsdbSnapPrepDescription(SVnode* pVnode, SSnapshot* pSnap) { } offset += tlen; + if (missingFileCount > 0) { + if ((tlen = tsdbMissingFilesSerialize((const char**)missingFiles, missingFileCount, buf + offset, + bufLen - offset)) < 0) { + code = tlen; + tsdbError("vgId:%d, failed to serialize missing files since %s", TD_VID(pVnode), terrstr()); + goto _out; + } + offset += tlen; + } + // set header of info data SSyncTLV* pHead = pSnap->data; pHead->typ = pSnap->type; @@ -646,6 +920,10 @@ int32_t tsdbSnapPrepDescription(SVnode* pVnode, SSnapshot* pSnap) { pHead->len); _out: + for (int32_t i = 0; i < missingFileCount; ++i) { + taosMemoryFree(missingFiles[i]); + } + taosMemoryFree(missingFiles); tsdbPartitionInfoClear(pInfo); return code; } diff --git a/source/dnode/vnode/src/tsdb/tsdbSnapshot.c b/source/dnode/vnode/src/tsdb/tsdbSnapshot.c index b356beee453b..654203e1294e 100644 --- a/source/dnode/vnode/src/tsdb/tsdbSnapshot.c +++ b/source/dnode/vnode/src/tsdb/tsdbSnapshot.c @@ -52,6 +52,10 @@ struct STsdbSnapReader { TTsdbIterArray tombIterArr[1]; SIterMerger* tombIterMerger; + // missing fid filter (NULL = send all, non-NULL = only send listed fids) + int32_t* missingFids; + int32_t missingFidCount; + // data SBlockData blockData[1]; STombBlock tombBlock[1]; @@ -198,12 +202,35 @@ static void tsdbSnapReadFileSetCloseIter(STsdbSnapReader* reader) { return; } +static bool tsdbSnapFidInMissingSet(int32_t fid, const int32_t* missingFids, int32_t missingFidCount) { + int32_t lo = 0, hi = missingFidCount - 1; + while (lo <= hi) { + int32_t mid = lo + (hi - lo) / 2; + if (missingFids[mid] == fid) return true; + if (missingFids[mid] < fid) + lo = mid + 1; + else + hi = mid - 1; + } + return false; +} + static int32_t tsdbSnapReadRangeBegin(STsdbSnapReader* reader) { int32_t code = 0; int32_t lino = 0; - if (reader->ctx->fsrArrIdx < TARRAY2_SIZE(reader->fsrArr)) { + while (reader->ctx->fsrArrIdx < TARRAY2_SIZE(reader->fsrArr)) { reader->ctx->fsr = TARRAY2_GET(reader->fsrArr, reader->ctx->fsrArrIdx++); + + // skip fids not in missing-fid filter + if (reader->missingFids != NULL && + !tsdbSnapFidInMissingSet(reader->ctx->fsr->fset->fid, reader->missingFids, reader->missingFidCount)) { + tsdbDebug("vgId:%d, snap reader skip fid:%d not in missing-fid set", TD_VID(reader->tsdb->pVnode), + reader->ctx->fsr->fset->fid); + reader->ctx->fsr = NULL; + continue; + } + reader->ctx->isDataDone = false; reader->ctx->isTombDone = false; @@ -212,6 +239,8 @@ static int32_t tsdbSnapReadRangeBegin(STsdbSnapReader* reader) { code = tsdbSnapReadFileSetOpenIter(reader); TSDB_CHECK_CODE(code, lino, _exit); + + return code; } _exit: @@ -441,7 +470,7 @@ static int32_t tsdbSnapReadTombData(STsdbSnapReader* reader, uint8_t** data) { } int32_t tsdbSnapReaderOpen(STsdb* tsdb, int64_t sver, int64_t ever, int8_t type, void* pRanges, - STsdbSnapReader** reader) { + const int32_t* missingFids, int32_t missingFidCount, STsdbSnapReader** reader) { int32_t code = 0; int32_t lino = 0; @@ -453,7 +482,20 @@ int32_t tsdbSnapReaderOpen(STsdb* tsdb, int64_t sver, int64_t ever, int8_t type, reader[0]->ever = ever; reader[0]->type = type; - code = tsdbFSCreateRefRangedSnapshot(tsdb->pFS, sver, ever, (TFileSetRangeArray*)pRanges, &reader[0]->fsrArr); + // copy missing fid filter + if (missingFids != NULL && missingFidCount > 0) { + reader[0]->missingFids = taosMemoryMalloc(missingFidCount * sizeof(int32_t)); + if (reader[0]->missingFids == NULL) { + code = terrno; + TSDB_CHECK_CODE(code, lino, _exit); + } + memcpy(reader[0]->missingFids, missingFids, missingFidCount * sizeof(int32_t)); + reader[0]->missingFidCount = missingFidCount; + tsdbInfo("vgId:%d, snap reader opened with %d missing-fid filter", TD_VID(tsdb->pVnode), missingFidCount); + } + + code = tsdbFSCreateRefRangedSnapshot(tsdb->pFS, sver, ever, (TFileSetRangeArray*)pRanges, reader[0]->missingFids, + reader[0]->missingFidCount, &reader[0]->fsrArr); TSDB_CHECK_CODE(code, lino, _exit); _exit: @@ -461,6 +503,7 @@ int32_t tsdbSnapReaderOpen(STsdb* tsdb, int64_t sver, int64_t ever, int8_t type, tsdbError("vgId:%d %s failed at %s:%d since %s, sver:%" PRId64 " ever:%" PRId64 " type:%d", TD_VID(tsdb->pVnode), __func__, __FILE__, lino, tstrerror(code), sver, ever, type); tsdbTFileSetRangeArrayDestroy(&reader[0]->fsrArr); + taosMemoryFree(reader[0]->missingFids); taosMemoryFree(reader[0]); reader[0] = NULL; } else { @@ -496,6 +539,7 @@ void tsdbSnapReaderClose(STsdbSnapReader** reader) { tBufferDestroy(reader[0]->buffers + i); } + taosMemoryFree(reader[0]->missingFids); taosMemoryFree(reader[0]); reader[0] = NULL; diff --git a/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c b/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c index ca6c04fa2c32..0bb32a83bafb 100644 --- a/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c +++ b/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c @@ -45,9 +45,28 @@ typedef struct STsdbSnapRAWReader { // iter SDataFileRAWReaderIter dataIter[1]; + + // missing file filter + SHashObj* missingFileHash; // key=fname — per-file filtering (not owned, do not free) + int32_t* missingFids; // FID set for FID-level pre-filtering (owned, copy) + int32_t missingFidCount; } STsdbSnapRAWReader; -int32_t tsdbSnapRAWReaderOpen(STsdb* tsdb, int64_t ever, int8_t type, void* pRanges, STsdbSnapRAWReader** reader) { +static bool tsdbFidInMissingSet(int32_t fid, const int32_t* missingFids, int32_t missingFidCount) { + int32_t lo = 0, hi = missingFidCount - 1; + while (lo <= hi) { + int32_t mid = lo + (hi - lo) / 2; + if (missingFids[mid] == fid) return true; + if (missingFids[mid] < fid) + lo = mid + 1; + else + hi = mid - 1; + } + return false; +} + +int32_t tsdbSnapRAWReaderOpen(STsdb* tsdb, int64_t ever, int8_t type, void* pRanges, SHashObj* missingFileHash, + const int32_t* missingFids, int32_t missingFidCount, STsdbSnapRAWReader** reader) { int32_t code = 0; int32_t lino = 0; @@ -58,6 +77,21 @@ int32_t tsdbSnapRAWReaderOpen(STsdb* tsdb, int64_t ever, int8_t type, void* pRan reader[0]->ever = ever; reader[0]->type = type; + // set missing file filter (hash is borrowed, not owned) + reader[0]->missingFileHash = missingFileHash; + + // copy missing fid filter + if (missingFids != NULL && missingFidCount > 0) { + reader[0]->missingFids = taosMemoryMalloc(missingFidCount * sizeof(int32_t)); + if (reader[0]->missingFids == NULL) { + code = terrno; + TSDB_CHECK_CODE(code, lino, _exit); + } + memcpy(reader[0]->missingFids, missingFids, missingFidCount * sizeof(int32_t)); + reader[0]->missingFidCount = missingFidCount; + tsdbInfo("vgId:%d, RAW reader opened with %d missing-fid filter", TD_VID(tsdb->pVnode), missingFidCount); + } + TFileSetRangeArray* pTypedRanges = (TFileSetRangeArray*)pRanges; if (pTypedRanges != NULL && TARRAY2_SIZE(pTypedRanges) > 0) { code = tsdbFSCreateRefSnapshotWithRanges(tsdb->pFS, pTypedRanges, &reader[0]->fsetArr); @@ -71,6 +105,7 @@ int32_t tsdbSnapRAWReaderOpen(STsdb* tsdb, int64_t ever, int8_t type, void* pRan tsdbError("vgId:%d %s failed at line %d since %s, ever:%" PRId64 " type:%d", TD_VID(tsdb->pVnode), __func__, lino, tstrerror(code), ever, type); tsdbFSDestroyRefSnapshot(&reader[0]->fsetArr); + taosMemoryFree(reader[0]->missingFids); taosMemoryFree(reader[0]); reader[0] = NULL; } else { @@ -90,6 +125,8 @@ void tsdbSnapRAWReaderClose(STsdbSnapRAWReader** reader) { TARRAY2_DESTROY(reader[0]->dataReaderArr, tsdbDataFileRAWReaderClose); tsdbFSDestroyRefSnapshot(&reader[0]->fsetArr); + // missingFileHash is borrowed, not freed here + taosMemoryFree(reader[0]->missingFids); taosMemoryFree(reader[0]); reader[0] = NULL; return; @@ -105,6 +142,16 @@ static int32_t tsdbSnapRAWReadFileSetOpenReader(STsdbSnapRAWReader* reader) { continue; } STFileObj* fobj = reader->ctx->fset->farr[ftype]; + // per-file filter: skip files not in missing set (use basename only) + if (reader->missingFileHash != NULL) { + const char* base = strrchr(fobj->fname, TD_DIRSEP_CHAR); + base = (base != NULL) ? base + 1 : fobj->fname; + if (taosHashGet(reader->missingFileHash, base, strlen(base)) == NULL) { + tsdbDebug("vgId:%d, RAW skip file:%s not in missing set", TD_VID(reader->tsdb->pVnode), fobj->fname); + continue; + } + tsdbInfo("vgId:%d, RAW include file:%s in missing set", TD_VID(reader->tsdb->pVnode), base); + } SDataFileRAWReader* dataReader; SDataFileRAWReaderConfig config = { .tsdb = reader->tsdb, @@ -123,6 +170,16 @@ static int32_t tsdbSnapRAWReadFileSetOpenReader(STsdbSnapRAWReader* reader) { TARRAY2_FOREACH(reader->ctx->fset->lvlArr, lvl) { STFileObj* fobj; TARRAY2_FOREACH(lvl->fobjArr, fobj) { + // per-file filter: skip stt files not in missing set (use basename only) + if (reader->missingFileHash != NULL) { + const char* base = strrchr(fobj->fname, TD_DIRSEP_CHAR); + base = (base != NULL) ? base + 1 : fobj->fname; + if (taosHashGet(reader->missingFileHash, base, strlen(base)) == NULL) { + tsdbDebug("vgId:%d, RAW skip stt file:%s not in missing set", TD_VID(reader->tsdb->pVnode), fobj->fname); + continue; + } + tsdbInfo("vgId:%d, RAW include stt file:%s in missing set", TD_VID(reader->tsdb->pVnode), base); + } SDataFileRAWReader* dataReader; SDataFileRAWReaderConfig config = { .tsdb = reader->tsdb, @@ -238,8 +295,18 @@ static int32_t tsdbSnapRAWReadBegin(STsdbSnapRAWReader* reader) { int32_t code = 0; int32_t lino = 0; - if (reader->ctx->fsetArrIdx < TARRAY2_SIZE(reader->fsetArr)) { + while (reader->ctx->fsetArrIdx < TARRAY2_SIZE(reader->fsetArr)) { reader->ctx->fset = TARRAY2_GET(reader->fsetArr, reader->ctx->fsetArrIdx++); + + // skip fids not in missing-fid filter + if (reader->missingFids != NULL && + !tsdbFidInMissingSet(reader->ctx->fset->fid, reader->missingFids, reader->missingFidCount)) { + tsdbDebug("vgId:%d, skip fid:%d not in missing-fid set", TD_VID(reader->tsdb->pVnode), reader->ctx->fset->fid); + reader->ctx->fset = NULL; + continue; + } + tsdbInfo("vgId:%d, RAW include fid:%d in missing-fid set", TD_VID(reader->tsdb->pVnode), reader->ctx->fset->fid); + reader->ctx->isDataDone = false; code = tsdbSnapRAWReadFileSetOpenReader(reader); @@ -247,6 +314,8 @@ static int32_t tsdbSnapRAWReadBegin(STsdbSnapRAWReader* reader) { code = tsdbSnapRAWReadFileSetOpenIter(reader); TSDB_CHECK_CODE(code, lino, _exit); + + return code; } _exit: diff --git a/source/dnode/vnode/src/vnd/vnodeSnapshot.c b/source/dnode/vnode/src/vnd/vnodeSnapshot.c index a70117d469ad..3c36dab2f752 100644 --- a/source/dnode/vnode/src/vnd/vnodeSnapshot.c +++ b/source/dnode/vnode/src/vnd/vnodeSnapshot.c @@ -53,6 +53,10 @@ struct SVSnapReader { // tsdb raw int8_t tsdbRAWDone; STsdbSnapRAWReader *pTsdbRAWReader; + // missing file filter + SHashObj *missingFileHash; // key=fname, val=dummy — for RAW mode per-file filtering + int32_t *missingFids; // FID set extracted from file names — for Normal mode FID filtering + int32_t missingFidCount; // tq int8_t tqHandleDone; @@ -89,6 +93,11 @@ static TFileSetRangeArray **vnodeSnapReaderGetTsdbRanges(SVSnapReader *pReader, } } +static int32_t vnodeExtractMissingFids(SVSnapReader *pReader) { + return tsdbExtractMissingFids(pReader->pVnode->pTsdb, pReader->missingFileHash, &pReader->missingFids, + &pReader->missingFidCount); +} + static int32_t vnodeSnapReaderDealWithSnapInfo(SVSnapReader *pReader, SSnapshotParam *pParam) { int32_t code = 0; SVnode *pVnode = pReader->pVnode; @@ -135,10 +144,27 @@ static int32_t vnodeSnapReaderDealWithSnapInfo(SVSnapReader *pReader, SSnapshotP goto _out; } } break; + case SNAP_DATA_MISSING_FIDS: { + code = tDeserializeMissingFileList(buf, bufLen, &pReader->missingFileHash); + if (code) { + vError("vgId:%d, failed to deserialize missing file list since %s", TD_VID(pVnode), tstrerror(code)); + goto _out; + } + int32_t fileCount = pReader->missingFileHash ? (int32_t)taosHashGetSize(pReader->missingFileHash) : 0; + vInfo("vgId:%d, received %d missing files from follower", TD_VID(pVnode), fileCount); + } break; default: - vError("vgId:%d, unexpected subfield type of snap info. typ:%d", TD_VID(pVnode), subField->typ); - code = TSDB_CODE_INVALID_DATA_FMT; - goto _out; + vWarn("vgId:%d, unknown subfield type in snap info, skipping. typ:%d", TD_VID(pVnode), subField->typ); + break; + } + } + + // extract FID set from missing file hash for normal mode filtering + if (pReader->missingFileHash && taosHashGetSize(pReader->missingFileHash) > 0) { + code = vnodeExtractMissingFids(pReader); + if (code) { + vError("vgId:%d, failed to extract missing fids from file hash since %s", TD_VID(pVnode), tstrerror(code)); + goto _out; } } @@ -180,7 +206,8 @@ int32_t vnodeSnapReaderOpen(SVnode *pVnode, SSnapshotParam *pParam, SVSnapReader // open tsdb snapshot raw reader if (!pReader->tsdbRAWDone) { - code = tsdbSnapRAWReaderOpen(pVnode->pTsdb, ever, SNAP_DATA_RAW, pReader->pRanges, &pReader->pTsdbRAWReader); + code = tsdbSnapRAWReaderOpen(pVnode->pTsdb, ever, SNAP_DATA_RAW, pReader->pRanges, pReader->missingFileHash, pReader->missingFids, + pReader->missingFidCount, &pReader->pTsdbRAWReader); if (code) goto _exit; } @@ -248,6 +275,10 @@ void vnodeSnapReaderClose(SVSnapReader *pReader) { tqSnapReaderClose(&pReader->pTqCheckInfoReader); } #endif + if (pReader->missingFileHash) { + taosHashCleanup(pReader->missingFileHash); + } + taosMemoryFree(pReader->missingFids); taosMemoryFree(pReader); } @@ -333,7 +364,7 @@ int32_t vnodeSnapRead(SVSnapReader *pReader, uint8_t **ppData, uint32_t *nData) // open if not if (pReader->pTsdbReader == NULL) { code = tsdbSnapReaderOpen(pReader->pVnode->pTsdb, pReader->sver, pReader->ever, SNAP_DATA_TSDB, pReader->pRanges, - &pReader->pTsdbReader); + pReader->missingFids, pReader->missingFidCount, &pReader->pTsdbReader); TSDB_CHECK_CODE(code, lino, _exit); } @@ -351,7 +382,8 @@ int32_t vnodeSnapRead(SVSnapReader *pReader, uint8_t **ppData, uint32_t *nData) // open if not if (pReader->pTsdbRAWReader == NULL) { code = tsdbSnapRAWReaderOpen(pReader->pVnode->pTsdb, pReader->ever, SNAP_DATA_RAW, pReader->pRanges, - &pReader->pTsdbRAWReader); + pReader->missingFileHash, + pReader->missingFids, pReader->missingFidCount, &pReader->pTsdbRAWReader); TSDB_CHECK_CODE(code, lino, _exit); } @@ -580,10 +612,12 @@ static int32_t vnodeSnapWriterDealWithSnapInfo(SVSnapWriter *pWriter, SSnapshotP code = tDeserializeTsdbRepOpts(buf, bufLen, &tsdbOpts); TSDB_CHECK_CODE(code, lino, _exit); } break; + case SNAP_DATA_MISSING_FIDS: { + vInfo("vgId:%d, snap writer received missing fids subfield, skipping (handled by reader)", TD_VID(pVnode)); + } break; default: - vError("vgId:%d, unexpected subfield type of snap info. typ:%d", TD_VID(pVnode), subField->typ); - TSDB_CHECK_CODE(code = TSDB_CODE_INVALID_DATA_FMT, lino, _exit); - goto _exit; + vWarn("vgId:%d, unknown subfield type in snap info, skipping. typ:%d", TD_VID(pVnode), subField->typ); + break; } } From 90f66e23d2cea82da632d5907e4ffd0dd5a4754e Mon Sep 17 00:00:00 2001 From: chen dongming Date: Wed, 13 May 2026 15:00:26 +0800 Subject: [PATCH 03/12] feat: snapshot filter by fid+type --- source/dnode/vnode/src/inc/tsdb.h | 5 +- source/dnode/vnode/src/tsdb/tsdbSnapInfo.c | 214 +++++++++--------- source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c | 26 ++- 3 files changed, 118 insertions(+), 127 deletions(-) diff --git a/source/dnode/vnode/src/inc/tsdb.h b/source/dnode/vnode/src/inc/tsdb.h index 6ab17fddfaa9..4179b29d2803 100644 --- a/source/dnode/vnode/src/inc/tsdb.h +++ b/source/dnode/vnode/src/inc/tsdb.h @@ -726,11 +726,12 @@ typedef struct STsdbRepOpts { int32_t tSerializeTsdbRepOpts(void *buf, int32_t bufLen, STsdbRepOpts *pInfo); int32_t tDeserializeTsdbRepOpts(void *buf, int32_t bufLen, STsdbRepOpts *pInfo); -int32_t tMissingFileListDataLenCalc(const char **fnames, int32_t fileCount); -int32_t tSerializeMissingFileList(void *buf, int32_t bufLen, const char **fnames, int32_t fileCount); +int32_t tMissingFileListDataLenCalc(int32_t fileCount); int32_t tDeserializeMissingFileList(void *buf, int32_t bufLen, SHashObj **ppHash); int32_t tsdbExtractMissingFids(STsdb *pTsdb, SHashObj *missingFileHash, int32_t **ppFids, int32_t *pFidCount); +static inline int64_t tsdbMissingFileKey(int32_t fid, int32_t ftype) { return ((int64_t)fid << 32) | (uint32_t)ftype; } + // snap read struct STsdbReadSnap { SMemTable *pMem; diff --git a/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c b/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c index efe518cf77e0..42e61dbb4678 100644 --- a/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c +++ b/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c @@ -18,6 +18,12 @@ #define TSDB_SNAP_MSG_VER 1 +// missing file identifier: (fid, ftype) pair +typedef struct { + int32_t fid; + int32_t ftype; // tsdb_ftype_t +} STsdbMissingFile; + // fset partition static int32_t tsdbFSetPartCmprFn(STsdbFSetPartition* x, STsdbFSetPartition* y) { if (x->fid < y->fid) return -1; @@ -529,7 +535,7 @@ int32_t tDeserializeTsdbRepOpts(void* buf, int32_t bufLen, STsdbRepOpts* pOpts) return code; } -int32_t tMissingFileListDataLenCalc(const char** fnames, int32_t fileCount) { +int32_t tMissingFileListDataLenCalc(int32_t fileCount) { int32_t hdrLen = sizeof(int32_t); int32_t datLen = 0; @@ -537,13 +543,11 @@ int32_t tMissingFileListDataLenCalc(const char** fnames, int32_t fileCount) { hdrLen += sizeof(msgVer); datLen += hdrLen; datLen += sizeof(int32_t); // fileCount - for (int32_t i = 0; i < fileCount; ++i) { - datLen += sizeof(int32_t) + (int32_t)strlen(fnames[i]) + 1; // tEncodeCStr overhead - } + datLen += fileCount * (sizeof(int32_t) + sizeof(int32_t)); // fid + ftype per entry return datLen; } -int32_t tSerializeMissingFileList(void* buf, int32_t bufLen, const char** fnames, int32_t fileCount) { +int32_t tSerializeMissingFileList(void* buf, int32_t bufLen, const STsdbMissingFile* files, int32_t fileCount) { int32_t code = 0; SEncoder encoder = {0}; int8_t msgVer = TSDB_SNAP_MSG_VER; @@ -554,7 +558,8 @@ int32_t tSerializeMissingFileList(void* buf, int32_t bufLen, const char** fnames if ((code = tEncodeI8(&encoder, msgVer))) goto _err; if ((code = tEncodeI32(&encoder, fileCount))) goto _err; for (int32_t i = 0; i < fileCount; ++i) { - if ((code = tEncodeCStr(&encoder, fnames[i]))) goto _err; + if ((code = tEncodeI32(&encoder, files[i].fid))) goto _err; + if ((code = tEncodeI32(&encoder, files[i].ftype))) goto _err; } tEndEncode(&encoder); @@ -588,17 +593,20 @@ int32_t tDeserializeMissingFileList(void* buf, int32_t bufLen, SHashObj** ppHash goto _err; } if (fileCount > 0) { - pHash = taosHashInit(fileCount * 2, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK); + pHash = taosHashInit(fileCount * 2, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_ENTRY_LOCK); if (pHash == NULL) { code = terrno; goto _err; } for (int32_t i = 0; i < fileCount; ++i) { - char* fname = NULL; - if ((code = tDecodeCStr(&decoder, &fname))) goto _err; - char dummy = 0; - tsdbDebug("Missing File fname:%s", fname); - if (taosHashPut(pHash, fname, strlen(fname), &dummy, sizeof(dummy)) != 0) { + int32_t fid = 0; + int32_t ftype = 0; + if ((code = tDecodeI32(&decoder, &fid))) goto _err; + if ((code = tDecodeI32(&decoder, &ftype))) goto _err; + char dummy = 0; + int64_t key = tsdbMissingFileKey(fid, ftype); + tsdbDebug("Missing File fid:%d ftype:%d", fid, ftype); + if (taosHashPut(pHash, &key, sizeof(key), &dummy, sizeof(dummy)) != 0) { code = terrno; goto _err; } @@ -623,74 +631,65 @@ int32_t tsdbExtractMissingFids(STsdb* pTsdb, SHashObj* missingFileHash, int32_t* int32_t fidCount = 0; int32_t* fids = NULL; - (void)taosThreadMutexLock(&pTsdb->mutex); - - STFileSet* fset; - TARRAY2_FOREACH(pTsdb->pFS->fSetArr, fset) { - bool hasMissing = false; - - // check farr - for (int32_t ftype = 0; ftype < TSDB_FTYPE_MAX; ++ftype) { - if (fset->farr[ftype] != NULL) { - const char* base = strrchr(fset->farr[ftype]->fname, TD_DIRSEP_CHAR); - base = (base != NULL) ? base + 1 : fset->farr[ftype]->fname; - if (taosHashGet(missingFileHash, base, strlen(base)) != NULL) { - hasMissing = true; - break; - } + // extract unique fids from hash keys (key = (fid << 32) | ftype) + void* pIter = NULL; + while ((pIter = taosHashIterate(missingFileHash, pIter)) != NULL) { + size_t keyLen = 0; + int64_t* pKey = taosHashGetKey(pIter, &keyLen); + int32_t fid = (int32_t)(*pKey >> 32); + + // check if fid already exists + bool exists = false; + for (int32_t i = 0; i < fidCount; ++i) { + if (fids[i] == fid) { + exists = true; + break; } } + if (exists) continue; - // check stt - if (!hasMissing) { - SSttLvl* lvl; - TARRAY2_FOREACH(fset->lvlArr, lvl) { - STFileObj* fobj; - TARRAY2_FOREACH(lvl->fobjArr, fobj) { - const char* base = strrchr(fobj->fname, TD_DIRSEP_CHAR); - base = (base != NULL) ? base + 1 : fobj->fname; - if (taosHashGet(missingFileHash, base, strlen(base)) != NULL) { - hasMissing = true; - break; - } - } - if (hasMissing) break; + if (fidCount >= fidCap) { + int32_t newCap = fidCap == 0 ? 16 : fidCap * 2; + int32_t* tmp = taosMemoryRealloc(fids, newCap * sizeof(int32_t)); + if (tmp == NULL) { + code = terrno; + taosHashCancelIterate(missingFileHash, pIter); + taosMemoryFree(fids); + return code; } + fids = tmp; + fidCap = newCap; } + fids[fidCount++] = fid; + } - if (hasMissing) { - if (fidCount >= fidCap) { - int32_t newCap = fidCap == 0 ? 16 : fidCap * 2; - int32_t* tmp = taosMemoryRealloc(fids, newCap * sizeof(int32_t)); - if (tmp == NULL) { - code = terrno; - (void)taosThreadMutexUnlock(&pTsdb->mutex); - taosMemoryFree(fids); - return code; + // sort fids for binary search + if (fidCount > 1) { + for (int32_t i = 0; i < fidCount - 1; ++i) { + for (int32_t j = i + 1; j < fidCount; ++j) { + if (fids[i] > fids[j]) { + int32_t tmp = fids[i]; + fids[i] = fids[j]; + fids[j] = tmp; } - fids = tmp; - fidCap = newCap; } - fids[fidCount++] = fset->fid; } } - (void)taosThreadMutexUnlock(&pTsdb->mutex); - *ppFids = fids; *pFidCount = fidCount; return 0; } -static int32_t tsdbDetectMissingFiles(SVnode* pVnode, char*** ppFnames, int32_t* pFnameCount) { - int32_t code = 0; - char** fnames = NULL; - int32_t fnameCount = 0; - int32_t fnameCap = 0; - STsdb* pTsdb = pVnode->pTsdb; +static int32_t tsdbDetectMissingFiles(SVnode* pVnode, STsdbMissingFile** ppFiles, int32_t* pFileCount) { + int32_t code = 0; + STsdbMissingFile* files = NULL; + int32_t fileCount = 0; + int32_t fileCap = 0; + STsdb* pTsdb = pVnode->pTsdb; - *ppFnames = NULL; - *pFnameCount = 0; + *ppFiles = NULL; + *pFileCount = 0; (void)taosThreadMutexLock(&pTsdb->mutex); @@ -700,54 +699,50 @@ static int32_t tsdbDetectMissingFiles(SVnode* pVnode, char*** ppFnames, int32_t* for (int32_t ftype = TSDB_FTYPE_MIN; ftype < TSDB_FTYPE_MAX; ++ftype) { if (fset->farr[ftype] != NULL) { if (!taosCheckExistFile(fset->farr[ftype]->fname)) { - if (fnameCount >= fnameCap) { - int32_t newCap = fnameCap == 0 ? 16 : fnameCap * 2; - char** tmp = taosMemoryRealloc(fnames, newCap * sizeof(char*)); + if (fileCount >= fileCap) { + int32_t newCap = fileCap == 0 ? 16 : fileCap * 2; + STsdbMissingFile* tmp = taosMemoryRealloc(files, newCap * sizeof(STsdbMissingFile)); if (tmp == NULL) { code = terrno; goto _unlock; } - fnames = tmp; - fnameCap = newCap; - } - const char* base = strrchr(fset->farr[ftype]->fname, TD_DIRSEP_CHAR); - base = (base != NULL) ? base + 1 : fset->farr[ftype]->fname; - fnames[fnameCount] = taosStrdup(base); - if (fnames[fnameCount] == NULL) { - code = terrno; - goto _unlock; + files = tmp; + fileCap = newCap; } - fnameCount++; + files[fileCount].fid = fset->fid; + files[fileCount].ftype = ftype; + fileCount++; } } } // check STT files in lvlArr SSttLvl* lvl; + bool sttMissing = false; TARRAY2_FOREACH(fset->lvlArr, lvl) { STFileObj* fobj; TARRAY2_FOREACH(lvl->fobjArr, fobj) { if (!taosCheckExistFile(fobj->fname)) { - if (fnameCount >= fnameCap) { - int32_t newCap = fnameCap == 0 ? 16 : fnameCap * 2; - char** tmp = taosMemoryRealloc(fnames, newCap * sizeof(char*)); - if (tmp == NULL) { - code = terrno; - goto _unlock; - } - fnames = tmp; - fnameCap = newCap; - } - const char* base = strrchr(fobj->fname, TD_DIRSEP_CHAR); - base = (base != NULL) ? base + 1 : fobj->fname; - fnames[fnameCount] = taosStrdup(base); - if (fnames[fnameCount] == NULL) { - code = terrno; - goto _unlock; - } - fnameCount++; + sttMissing = true; + break; } } + if (sttMissing) break; + } + if (sttMissing) { + if (fileCount >= fileCap) { + int32_t newCap = fileCap == 0 ? 16 : fileCap * 2; + STsdbMissingFile* tmp = taosMemoryRealloc(files, newCap * sizeof(STsdbMissingFile)); + if (tmp == NULL) { + code = terrno; + goto _unlock; + } + files = tmp; + fileCap = newCap; + } + files[fileCount].fid = fset->fid; + files[fileCount].ftype = TSDB_FTYPE_STT; + fileCount++; } } @@ -755,25 +750,22 @@ static int32_t tsdbDetectMissingFiles(SVnode* pVnode, char*** ppFnames, int32_t* (void)taosThreadMutexUnlock(&pTsdb->mutex); if (code != 0) { - for (int32_t i = 0; i < fnameCount; ++i) { - taosMemoryFree(fnames[i]); - } - taosMemoryFree(fnames); + taosMemoryFree(files); return code; } - *ppFnames = fnames; - *pFnameCount = fnameCount; + *ppFiles = files; + *pFileCount = fileCount; return 0; } -static int32_t tsdbMissingFilesEstSize(const char** fnames, int32_t fileCount) { - return sizeof(SSyncTLV) + tMissingFileListDataLenCalc(fnames, fileCount); +static int32_t tsdbMissingFilesEstSize(int32_t fileCount) { + return sizeof(SSyncTLV) + tMissingFileListDataLenCalc(fileCount); } -static int32_t tsdbMissingFilesSerialize(const char** fnames, int32_t fileCount, void* buf, int32_t bufLen) { +static int32_t tsdbMissingFilesSerialize(const STsdbMissingFile* files, int32_t fileCount, void* buf, int32_t bufLen) { SSyncTLV* pSubHead = buf; - int32_t tlen = tSerializeMissingFileList(pSubHead->val, bufLen - sizeof(*pSubHead), fnames, fileCount); + int32_t tlen = tSerializeMissingFileList(pSubHead->val, bufLen - sizeof(*pSubHead), files, fileCount); if (tlen < 0) return tlen; pSubHead->typ = SNAP_DATA_MISSING_FIDS; pSubHead->len = tlen; @@ -848,9 +840,9 @@ int32_t tsdbSnapPrepDescription(SVnode* pVnode, SSnapshot* pSnap) { } // deal with snap info for reply - STsdbRepOpts opts = {.format = TSDB_SNAP_REP_FMT_RAW}; - char** missingFiles = NULL; - int32_t missingFileCount = 0; + STsdbRepOpts opts = {.format = TSDB_SNAP_REP_FMT_RAW}; + STsdbMissingFile* missingFiles = NULL; + int32_t missingFileCount = 0; if (pSnap->type == TDMT_SYNC_PREP_SNAPSHOT_REPLY) { STsdbRepOpts leaderOpts = {0}; if ((code = tsdbSnapPrepDealWithSnapInfo(pVnode, pSnap, &leaderOpts)) < 0) { @@ -875,7 +867,7 @@ int32_t tsdbSnapPrepDescription(SVnode* pVnode, SSnapshot* pSnap) { bufLen += tsdbPartitionInfoEstSize(pInfo); bufLen += tsdbRepOptsEstSize(&opts); if (missingFileCount > 0) { - bufLen += tsdbMissingFilesEstSize((const char**)missingFiles, missingFileCount); + bufLen += tsdbMissingFilesEstSize(missingFileCount); } if ((code = syncSnapInfoDataRealloc(pSnap, bufLen)) != 0) { tsdbError("vgId:%d, failed to realloc memory for data of snap info. bytes:%d", TD_VID(pVnode), bufLen); @@ -902,8 +894,7 @@ int32_t tsdbSnapPrepDescription(SVnode* pVnode, SSnapshot* pSnap) { offset += tlen; if (missingFileCount > 0) { - if ((tlen = tsdbMissingFilesSerialize((const char**)missingFiles, missingFileCount, buf + offset, - bufLen - offset)) < 0) { + if ((tlen = tsdbMissingFilesSerialize(missingFiles, missingFileCount, buf + offset, bufLen - offset)) < 0) { code = tlen; tsdbError("vgId:%d, failed to serialize missing files since %s", TD_VID(pVnode), terrstr()); goto _out; @@ -920,9 +911,6 @@ int32_t tsdbSnapPrepDescription(SVnode* pVnode, SSnapshot* pSnap) { pHead->len); _out: - for (int32_t i = 0; i < missingFileCount; ++i) { - taosMemoryFree(missingFiles[i]); - } taosMemoryFree(missingFiles); tsdbPartitionInfoClear(pInfo); return code; diff --git a/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c b/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c index 0bb32a83bafb..766838e4ca94 100644 --- a/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c +++ b/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c @@ -142,15 +142,16 @@ static int32_t tsdbSnapRAWReadFileSetOpenReader(STsdbSnapRAWReader* reader) { continue; } STFileObj* fobj = reader->ctx->fset->farr[ftype]; - // per-file filter: skip files not in missing set (use basename only) + // per-file filter: skip files not in missing set (use fid + ftype) if (reader->missingFileHash != NULL) { - const char* base = strrchr(fobj->fname, TD_DIRSEP_CHAR); - base = (base != NULL) ? base + 1 : fobj->fname; - if (taosHashGet(reader->missingFileHash, base, strlen(base)) == NULL) { - tsdbDebug("vgId:%d, RAW skip file:%s not in missing set", TD_VID(reader->tsdb->pVnode), fobj->fname); + int64_t mfKey = tsdbMissingFileKey(reader->ctx->fset->fid, ftype); + if (taosHashGet(reader->missingFileHash, &mfKey, sizeof(mfKey)) == NULL) { + tsdbDebug("vgId:%d, RAW skip file fid:%d ftype:%d not in missing set", TD_VID(reader->tsdb->pVnode), + reader->ctx->fset->fid, ftype); continue; } - tsdbInfo("vgId:%d, RAW include file:%s in missing set", TD_VID(reader->tsdb->pVnode), base); + tsdbInfo("vgId:%d, RAW include file fid:%d ftype:%d in missing set", TD_VID(reader->tsdb->pVnode), + reader->ctx->fset->fid, ftype); } SDataFileRAWReader* dataReader; SDataFileRAWReaderConfig config = { @@ -170,15 +171,16 @@ static int32_t tsdbSnapRAWReadFileSetOpenReader(STsdbSnapRAWReader* reader) { TARRAY2_FOREACH(reader->ctx->fset->lvlArr, lvl) { STFileObj* fobj; TARRAY2_FOREACH(lvl->fobjArr, fobj) { - // per-file filter: skip stt files not in missing set (use basename only) + // per-file filter: skip stt files not in missing set (use fid + ftype) if (reader->missingFileHash != NULL) { - const char* base = strrchr(fobj->fname, TD_DIRSEP_CHAR); - base = (base != NULL) ? base + 1 : fobj->fname; - if (taosHashGet(reader->missingFileHash, base, strlen(base)) == NULL) { - tsdbDebug("vgId:%d, RAW skip stt file:%s not in missing set", TD_VID(reader->tsdb->pVnode), fobj->fname); + int64_t mfKey = tsdbMissingFileKey(reader->ctx->fset->fid, TSDB_FTYPE_STT); + if (taosHashGet(reader->missingFileHash, &mfKey, sizeof(mfKey)) == NULL) { + tsdbDebug("vgId:%d, RAW skip stt file fid:%d not in missing set", TD_VID(reader->tsdb->pVnode), + reader->ctx->fset->fid); continue; } - tsdbInfo("vgId:%d, RAW include stt file:%s in missing set", TD_VID(reader->tsdb->pVnode), base); + tsdbInfo("vgId:%d, RAW include stt file fid:%d in missing set", TD_VID(reader->tsdb->pVnode), + reader->ctx->fset->fid); } SDataFileRAWReader* dataReader; SDataFileRAWReaderConfig config = { From 5d0be2d3035cb17099bbbcf21ea9f20840502e1d Mon Sep 17 00:00:00 2001 From: chen dongming Date: Wed, 13 May 2026 18:48:31 +0800 Subject: [PATCH 04/12] feat: long snapshot filter with cid --- source/dnode/vnode/src/inc/tsdb.h | 7 +- source/dnode/vnode/src/inc/vnodeInt.h | 3 +- source/dnode/vnode/src/tsdb/tsdbSnapInfo.c | 165 ++++++++++++++---- source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c | 37 ++-- source/dnode/vnode/src/vnd/vnodeSnapshot.c | 32 +++- 5 files changed, 190 insertions(+), 54 deletions(-) diff --git a/source/dnode/vnode/src/inc/tsdb.h b/source/dnode/vnode/src/inc/tsdb.h index 4179b29d2803..8e0fe3f35808 100644 --- a/source/dnode/vnode/src/inc/tsdb.h +++ b/source/dnode/vnode/src/inc/tsdb.h @@ -717,6 +717,7 @@ int32_t tsdbFSetPartListToRangeDiff(STsdbFSetPartList *pList, TFileSe typedef enum ETsdbRepFmt { TSDB_SNAP_REP_FMT_DEFAULT = 0, TSDB_SNAP_REP_FMT_RAW, + TSDB_SNAP_REP_FMT_HYBRID, } ETsdbRepFmt; typedef struct STsdbRepOpts { @@ -727,8 +728,12 @@ int32_t tSerializeTsdbRepOpts(void *buf, int32_t bufLen, STsdbRepOpts *pInfo); int32_t tDeserializeTsdbRepOpts(void *buf, int32_t bufLen, STsdbRepOpts *pInfo); int32_t tMissingFileListDataLenCalc(int32_t fileCount); -int32_t tDeserializeMissingFileList(void *buf, int32_t bufLen, SHashObj **ppHash); +int32_t tDeserializeMissingFileList(void *buf, int32_t bufLen, void **ppFiles, int32_t *pFileCount, SHashObj **ppHash); int32_t tsdbExtractMissingFids(STsdb *pTsdb, SHashObj *missingFileHash, int32_t **ppFids, int32_t *pFidCount); +int32_t tsdbDetermineFidSyncMode(STsdb *pTsdb, const void *files, int32_t fileCount, SHashObj **ppFidModeHash); + +#define TSDB_SNAP_SYNC_FILE_LEVEL 0 +#define TSDB_SNAP_SYNC_FSET_LEVEL 1 static inline int64_t tsdbMissingFileKey(int32_t fid, int32_t ftype) { return ((int64_t)fid << 32) | (uint32_t)ftype; } diff --git a/source/dnode/vnode/src/inc/vnodeInt.h b/source/dnode/vnode/src/inc/vnodeInt.h index 76d4d9dd209f..1ebf76ac73a6 100644 --- a/source/dnode/vnode/src/inc/vnodeInt.h +++ b/source/dnode/vnode/src/inc/vnodeInt.h @@ -343,7 +343,8 @@ int32_t tsdbSnapWriterPrepareClose(STsdbSnapWriter* pWriter, bool rollback); int32_t tsdbSnapWriterClose(STsdbSnapWriter** ppWriter, int8_t rollback); // STsdbSnapRAWReader ======================================== int32_t tsdbSnapRAWReaderOpen(STsdb* pTsdb, int64_t ever, int8_t type, void* pRanges, SHashObj* missingFileHash, - const int32_t* missingFids, int32_t missingFidCount, STsdbSnapRAWReader** ppReader); + SHashObj* fidModeHash, const int32_t* missingFids, int32_t missingFidCount, + STsdbSnapRAWReader** ppReader); void tsdbSnapRAWReaderClose(STsdbSnapRAWReader** ppReader); int32_t tsdbSnapRAWRead(STsdbSnapRAWReader* pReader, uint8_t** ppData); // STsdbSnapRAWWriter ======================================== diff --git a/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c b/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c index 42e61dbb4678..e82f158a46f9 100644 --- a/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c +++ b/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c @@ -18,10 +18,12 @@ #define TSDB_SNAP_MSG_VER 1 -// missing file identifier: (fid, ftype) pair +// missing file identifier: (fid, ftype, cid, size) typedef struct { int32_t fid; int32_t ftype; // tsdb_ftype_t + int64_t cid; // commit id + int64_t size; // file size } STsdbMissingFile; // fset partition @@ -543,7 +545,8 @@ int32_t tMissingFileListDataLenCalc(int32_t fileCount) { hdrLen += sizeof(msgVer); datLen += hdrLen; datLen += sizeof(int32_t); // fileCount - datLen += fileCount * (sizeof(int32_t) + sizeof(int32_t)); // fid + ftype per entry + datLen += + fileCount * (sizeof(int32_t) + sizeof(int32_t) + sizeof(int64_t) + sizeof(int64_t)); // fid + ftype + cid + size return datLen; } @@ -560,6 +563,8 @@ int32_t tSerializeMissingFileList(void* buf, int32_t bufLen, const STsdbMissingF for (int32_t i = 0; i < fileCount; ++i) { if ((code = tEncodeI32(&encoder, files[i].fid))) goto _err; if ((code = tEncodeI32(&encoder, files[i].ftype))) goto _err; + if ((code = tEncodeI64(&encoder, files[i].cid))) goto _err; + if ((code = tEncodeI64(&encoder, files[i].size))) goto _err; } tEndEncode(&encoder); @@ -572,12 +577,13 @@ int32_t tSerializeMissingFileList(void* buf, int32_t bufLen, const STsdbMissingF return code; } -int32_t tDeserializeMissingFileList(void* buf, int32_t bufLen, SHashObj** ppHash) { - int32_t code = 0; - SDecoder decoder = {0}; - int8_t msgVer = 0; - int32_t fileCount = 0; - SHashObj* pHash = NULL; +int32_t tDeserializeMissingFileList(void* buf, int32_t bufLen, void** ppFiles, int32_t* pFileCount, SHashObj** ppHash) { + int32_t code = 0; + SDecoder decoder = {0}; + int8_t msgVer = 0; + int32_t fileCount = 0; + SHashObj* pHash = NULL; + STsdbMissingFile* files = NULL; tDecoderInit(&decoder, buf, bufLen); @@ -598,14 +604,20 @@ int32_t tDeserializeMissingFileList(void* buf, int32_t bufLen, SHashObj** ppHash code = terrno; goto _err; } + files = taosMemoryMalloc(fileCount * sizeof(STsdbMissingFile)); + if (files == NULL) { + code = terrno; + goto _err; + } for (int32_t i = 0; i < fileCount; ++i) { - int32_t fid = 0; - int32_t ftype = 0; - if ((code = tDecodeI32(&decoder, &fid))) goto _err; - if ((code = tDecodeI32(&decoder, &ftype))) goto _err; + if ((code = tDecodeI32(&decoder, &files[i].fid))) goto _err; + if ((code = tDecodeI32(&decoder, &files[i].ftype))) goto _err; + if ((code = tDecodeI64(&decoder, &files[i].cid))) goto _err; + if ((code = tDecodeI64(&decoder, &files[i].size))) goto _err; char dummy = 0; - int64_t key = tsdbMissingFileKey(fid, ftype); - tsdbDebug("Missing File fid:%d ftype:%d", fid, ftype); + int64_t key = tsdbMissingFileKey(files[i].fid, files[i].ftype); + tsdbDebug("Missing File fid:%d ftype:%d cid:%" PRId64 " size:%" PRId64, files[i].fid, files[i].ftype, + files[i].cid, files[i].size); if (taosHashPut(pHash, &key, sizeof(key), &dummy, sizeof(dummy)) != 0) { code = terrno; goto _err; @@ -617,10 +629,13 @@ int32_t tDeserializeMissingFileList(void* buf, int32_t bufLen, SHashObj** ppHash tDecoderClear(&decoder); *ppHash = pHash; + *ppFiles = (void*)files; + *pFileCount = fileCount; return 0; _err: if (pHash) taosHashCleanup(pHash); + taosMemoryFree(files); tDecoderClear(&decoder); return code; } @@ -681,6 +696,90 @@ int32_t tsdbExtractMissingFids(STsdb* pTsdb, SHashObj* missingFileHash, int32_t* return 0; } +int32_t tsdbDetermineFidSyncMode(STsdb* pTsdb, const void* pFileArr, int32_t fileCount, SHashObj** ppFidModeHash) { + int32_t code = 0; + SHashObj* pFidModeHash = NULL; + const STsdbMissingFile* files = (const STsdbMissingFile*)pFileArr; + + if (fileCount <= 0 || files == NULL) { + *ppFidModeHash = NULL; + return 0; + } + + pFidModeHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_ENTRY_LOCK); + if (pFidModeHash == NULL) { + return terrno; + } + + (void)taosThreadMutexLock(&pTsdb->mutex); + + for (int32_t i = 0; i < fileCount; ++i) { + int32_t fid = files[i].fid; + int32_t ftype = files[i].ftype; + int64_t followerCid = files[i].cid; + int64_t followerSize = files[i].size; + + // check if already marked as FSET_LEVEL — skip further checks for this fid + uint8_t* pExistMode = taosHashGet(pFidModeHash, &fid, sizeof(fid)); + if (pExistMode != NULL && *pExistMode == TSDB_SNAP_SYNC_FSET_LEVEL) { + continue; + } + + // find leader's corresponding file + bool found = false; + int64_t leaderCid = 0; + int64_t leaderSize = 0; + + STFileSet* fset; + TARRAY2_FOREACH(pTsdb->pFS->fSetArr, fset) { + if (fset->fid != fid) continue; + + if (ftype == TSDB_FTYPE_STT) { + // search STT files + SSttLvl* lvl; + TARRAY2_FOREACH(fset->lvlArr, lvl) { + STFileObj* fobj; + TARRAY2_FOREACH(lvl->fobjArr, fobj) { + if (fobj->f->cid == followerCid) { + found = true; + leaderCid = fobj->f->cid; + leaderSize = fobj->f->size; + break; + } + } + if (found) break; + } + } else if (ftype >= 0 && ftype < TSDB_FTYPE_MAX) { + if (fset->farr[ftype] != NULL) { + found = true; + leaderCid = fset->farr[ftype]->f->cid; + leaderSize = fset->farr[ftype]->f->size; + } + } + break; // found the fid + } + + // determine mode + uint8_t mode = TSDB_SNAP_SYNC_FILE_LEVEL; + if (found && (leaderCid != followerCid || leaderSize != followerSize)) { + mode = TSDB_SNAP_SYNC_FSET_LEVEL; + } + // if leader doesn't have the file (found==false), keep FILE_LEVEL (leader can't send it anyway) + + if (taosHashPut(pFidModeHash, &fid, sizeof(fid), &mode, sizeof(mode)) != 0) { + code = terrno; + (void)taosThreadMutexUnlock(&pTsdb->mutex); + taosHashCleanup(pFidModeHash); + return code; + } + } + + (void)taosThreadMutexUnlock(&pTsdb->mutex); + + *ppFidModeHash = pFidModeHash; + return 0; +} + static int32_t tsdbDetectMissingFiles(SVnode* pVnode, STsdbMissingFile** ppFiles, int32_t* pFileCount) { int32_t code = 0; STsdbMissingFile* files = NULL; @@ -711,38 +810,36 @@ static int32_t tsdbDetectMissingFiles(SVnode* pVnode, STsdbMissingFile** ppFiles } files[fileCount].fid = fset->fid; files[fileCount].ftype = ftype; + files[fileCount].cid = fset->farr[ftype]->f->cid; + files[fileCount].size = fset->farr[ftype]->f->size; fileCount++; } } } - // check STT files in lvlArr + // check STT files in lvlArr — record each missing STT file individually SSttLvl* lvl; - bool sttMissing = false; TARRAY2_FOREACH(fset->lvlArr, lvl) { STFileObj* fobj; TARRAY2_FOREACH(lvl->fobjArr, fobj) { if (!taosCheckExistFile(fobj->fname)) { - sttMissing = true; - break; - } - } - if (sttMissing) break; - } - if (sttMissing) { - if (fileCount >= fileCap) { - int32_t newCap = fileCap == 0 ? 16 : fileCap * 2; - STsdbMissingFile* tmp = taosMemoryRealloc(files, newCap * sizeof(STsdbMissingFile)); - if (tmp == NULL) { - code = terrno; - goto _unlock; + if (fileCount >= fileCap) { + int32_t newCap = fileCap == 0 ? 16 : fileCap * 2; + STsdbMissingFile* tmp = taosMemoryRealloc(files, newCap * sizeof(STsdbMissingFile)); + if (tmp == NULL) { + code = terrno; + goto _unlock; + } + files = tmp; + fileCap = newCap; + } + files[fileCount].fid = fset->fid; + files[fileCount].ftype = TSDB_FTYPE_STT; + files[fileCount].cid = fobj->f->cid; + files[fileCount].size = fobj->f->size; + fileCount++; } - files = tmp; - fileCap = newCap; } - files[fileCount].fid = fset->fid; - files[fileCount].ftype = TSDB_FTYPE_STT; - fileCount++; } } diff --git a/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c b/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c index 766838e4ca94..ce9b691eb7de 100644 --- a/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c +++ b/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c @@ -47,7 +47,8 @@ typedef struct STsdbSnapRAWReader { SDataFileRAWReaderIter dataIter[1]; // missing file filter - SHashObj* missingFileHash; // key=fname — per-file filtering (not owned, do not free) + SHashObj* missingFileHash; // key=(fid,ftype) — per-file filtering (not owned, do not free) + SHashObj* fidModeHash; // key=fid, val=uint8_t mode (not owned, do not free) int32_t* missingFids; // FID set for FID-level pre-filtering (owned, copy) int32_t missingFidCount; } STsdbSnapRAWReader; @@ -66,7 +67,8 @@ static bool tsdbFidInMissingSet(int32_t fid, const int32_t* missingFids, int32_t } int32_t tsdbSnapRAWReaderOpen(STsdb* tsdb, int64_t ever, int8_t type, void* pRanges, SHashObj* missingFileHash, - const int32_t* missingFids, int32_t missingFidCount, STsdbSnapRAWReader** reader) { + SHashObj* fidModeHash, const int32_t* missingFids, int32_t missingFidCount, + STsdbSnapRAWReader** reader) { int32_t code = 0; int32_t lino = 0; @@ -79,6 +81,7 @@ int32_t tsdbSnapRAWReaderOpen(STsdb* tsdb, int64_t ever, int8_t type, void* pRan // set missing file filter (hash is borrowed, not owned) reader[0]->missingFileHash = missingFileHash; + reader[0]->fidModeHash = fidModeHash; // copy missing fid filter if (missingFids != NULL && missingFidCount > 0) { @@ -136,22 +139,34 @@ static int32_t tsdbSnapRAWReadFileSetOpenReader(STsdbSnapRAWReader* reader) { int32_t code = 0; int32_t lino = 0; + // determine sync mode for this fid + int32_t curFid = reader->ctx->fset->fid; + bool fsetLevel = false; + if (reader->fidModeHash != NULL) { + uint8_t* pMode = taosHashGet(reader->fidModeHash, &curFid, sizeof(curFid)); + if (pMode != NULL && *pMode == TSDB_SNAP_SYNC_FSET_LEVEL) { + fsetLevel = true; + tsdbInfo("vgId:%d, RAW fid:%d using FSET_LEVEL sync (send all files)", TD_VID(reader->tsdb->pVnode), curFid); + } else { + tsdbInfo("vgId:%d, RAW fid:%d using FILE_LEVEL sync (send only missing files)", TD_VID(reader->tsdb->pVnode), + curFid); + } + } + // data for (int32_t ftype = 0; ftype < TSDB_FTYPE_MAX; ftype++) { if (reader->ctx->fset->farr[ftype] == NULL) { continue; } STFileObj* fobj = reader->ctx->fset->farr[ftype]; - // per-file filter: skip files not in missing set (use fid + ftype) - if (reader->missingFileHash != NULL) { + // per-file filter: skip files not in missing set (only when FILE_LEVEL mode) + if (!fsetLevel && reader->missingFileHash != NULL) { int64_t mfKey = tsdbMissingFileKey(reader->ctx->fset->fid, ftype); if (taosHashGet(reader->missingFileHash, &mfKey, sizeof(mfKey)) == NULL) { tsdbDebug("vgId:%d, RAW skip file fid:%d ftype:%d not in missing set", TD_VID(reader->tsdb->pVnode), reader->ctx->fset->fid, ftype); continue; } - tsdbInfo("vgId:%d, RAW include file fid:%d ftype:%d in missing set", TD_VID(reader->tsdb->pVnode), - reader->ctx->fset->fid, ftype); } SDataFileRAWReader* dataReader; SDataFileRAWReaderConfig config = { @@ -163,6 +178,8 @@ static int32_t tsdbSnapRAWReadFileSetOpenReader(STsdbSnapRAWReader* reader) { TSDB_CHECK_CODE(code, lino, _exit); code = TARRAY2_APPEND(reader->dataReaderArr, dataReader); + tsdbInfo("vgId:%d, RAW include file fid:%d ftype:%d in missing set", TD_VID(reader->tsdb->pVnode), + reader->ctx->fset->fid, ftype); TSDB_CHECK_CODE(code, lino, _exit); } @@ -171,16 +188,14 @@ static int32_t tsdbSnapRAWReadFileSetOpenReader(STsdbSnapRAWReader* reader) { TARRAY2_FOREACH(reader->ctx->fset->lvlArr, lvl) { STFileObj* fobj; TARRAY2_FOREACH(lvl->fobjArr, fobj) { - // per-file filter: skip stt files not in missing set (use fid + ftype) - if (reader->missingFileHash != NULL) { + // per-file filter: skip stt files not in missing set (only when FILE_LEVEL mode) + if (!fsetLevel && reader->missingFileHash != NULL) { int64_t mfKey = tsdbMissingFileKey(reader->ctx->fset->fid, TSDB_FTYPE_STT); if (taosHashGet(reader->missingFileHash, &mfKey, sizeof(mfKey)) == NULL) { tsdbDebug("vgId:%d, RAW skip stt file fid:%d not in missing set", TD_VID(reader->tsdb->pVnode), reader->ctx->fset->fid); continue; } - tsdbInfo("vgId:%d, RAW include stt file fid:%d in missing set", TD_VID(reader->tsdb->pVnode), - reader->ctx->fset->fid); } SDataFileRAWReader* dataReader; SDataFileRAWReaderConfig config = { @@ -192,6 +207,8 @@ static int32_t tsdbSnapRAWReadFileSetOpenReader(STsdbSnapRAWReader* reader) { TSDB_CHECK_CODE(code, lino, _exit); code = TARRAY2_APPEND(reader->dataReaderArr, dataReader); + tsdbInfo("vgId:%d, RAW include stt file fid:%d in missing set", TD_VID(reader->tsdb->pVnode), + reader->ctx->fset->fid); TSDB_CHECK_CODE(code, lino, _exit); } } diff --git a/source/dnode/vnode/src/vnd/vnodeSnapshot.c b/source/dnode/vnode/src/vnd/vnodeSnapshot.c index 3c36dab2f752..8c3358a9a966 100644 --- a/source/dnode/vnode/src/vnd/vnodeSnapshot.c +++ b/source/dnode/vnode/src/vnd/vnodeSnapshot.c @@ -54,7 +54,8 @@ struct SVSnapReader { int8_t tsdbRAWDone; STsdbSnapRAWReader *pTsdbRAWReader; // missing file filter - SHashObj *missingFileHash; // key=fname, val=dummy — for RAW mode per-file filtering + SHashObj *missingFileHash; // key=(fid,ftype), val=dummy — for RAW mode per-file filtering + SHashObj *fidModeHash; // key=fid, val=uint8_t mode (FILE_LEVEL or FSET_LEVEL) int32_t *missingFids; // FID set extracted from file names — for Normal mode FID filtering int32_t missingFidCount; @@ -145,13 +146,24 @@ static int32_t vnodeSnapReaderDealWithSnapInfo(SVSnapReader *pReader, SSnapshotP } } break; case SNAP_DATA_MISSING_FIDS: { - code = tDeserializeMissingFileList(buf, bufLen, &pReader->missingFileHash); + void *missingFiles = NULL; + int32_t missingFileCount = 0; + code = tDeserializeMissingFileList(buf, bufLen, &missingFiles, &missingFileCount, &pReader->missingFileHash); if (code) { vError("vgId:%d, failed to deserialize missing file list since %s", TD_VID(pVnode), tstrerror(code)); goto _out; } - int32_t fileCount = pReader->missingFileHash ? (int32_t)taosHashGetSize(pReader->missingFileHash) : 0; - vInfo("vgId:%d, received %d missing files from follower", TD_VID(pVnode), fileCount); + vInfo("vgId:%d, received %d missing files from follower", TD_VID(pVnode), missingFileCount); + // determine sync mode per fid + if (missingFiles && missingFileCount > 0) { + code = tsdbDetermineFidSyncMode(pVnode->pTsdb, missingFiles, missingFileCount, &pReader->fidModeHash); + if (code) { + taosMemoryFree(missingFiles); + vError("vgId:%d, failed to determine fid sync mode since %s", TD_VID(pVnode), tstrerror(code)); + goto _out; + } + } + taosMemoryFree(missingFiles); } break; default: vWarn("vgId:%d, unknown subfield type in snap info, skipping. typ:%d", TD_VID(pVnode), subField->typ); @@ -206,8 +218,9 @@ int32_t vnodeSnapReaderOpen(SVnode *pVnode, SSnapshotParam *pParam, SVSnapReader // open tsdb snapshot raw reader if (!pReader->tsdbRAWDone) { - code = tsdbSnapRAWReaderOpen(pVnode->pTsdb, ever, SNAP_DATA_RAW, pReader->pRanges, pReader->missingFileHash, pReader->missingFids, - pReader->missingFidCount, &pReader->pTsdbRAWReader); + code = tsdbSnapRAWReaderOpen(pVnode->pTsdb, ever, SNAP_DATA_RAW, pReader->pRanges, pReader->missingFileHash, + pReader->fidModeHash, pReader->missingFids, pReader->missingFidCount, + &pReader->pTsdbRAWReader); if (code) goto _exit; } @@ -278,6 +291,9 @@ void vnodeSnapReaderClose(SVSnapReader *pReader) { if (pReader->missingFileHash) { taosHashCleanup(pReader->missingFileHash); } + if (pReader->fidModeHash) { + taosHashCleanup(pReader->fidModeHash); + } taosMemoryFree(pReader->missingFids); taosMemoryFree(pReader); } @@ -382,8 +398,8 @@ int32_t vnodeSnapRead(SVSnapReader *pReader, uint8_t **ppData, uint32_t *nData) // open if not if (pReader->pTsdbRAWReader == NULL) { code = tsdbSnapRAWReaderOpen(pReader->pVnode->pTsdb, pReader->ever, SNAP_DATA_RAW, pReader->pRanges, - pReader->missingFileHash, - pReader->missingFids, pReader->missingFidCount, &pReader->pTsdbRAWReader); + pReader->missingFileHash, pReader->fidModeHash, pReader->missingFids, + pReader->missingFidCount, &pReader->pTsdbRAWReader); TSDB_CHECK_CODE(code, lino, _exit); } From 5ee9728c16cc56f0eb0ccf33e6a237946bcea0dc Mon Sep 17 00:00:00 2001 From: chen dongming Date: Fri, 15 May 2026 15:22:57 +0800 Subject: [PATCH 05/12] feat: enhance snapshot handling with STT file support and improved data structures --- source/dnode/vnode/src/inc/tsdb.h | 10 +- source/dnode/vnode/src/inc/vnodeInt.h | 4 +- source/dnode/vnode/src/tsdb/tsdbSnapInfo.c | 268 ++++++++++++------ source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c | 18 +- source/dnode/vnode/src/vnd/vnodeSnapshot.c | 18 +- 5 files changed, 219 insertions(+), 99 deletions(-) diff --git a/source/dnode/vnode/src/inc/tsdb.h b/source/dnode/vnode/src/inc/tsdb.h index 8e0fe3f35808..41e8d405a4f5 100644 --- a/source/dnode/vnode/src/inc/tsdb.h +++ b/source/dnode/vnode/src/inc/tsdb.h @@ -728,7 +728,8 @@ int32_t tSerializeTsdbRepOpts(void *buf, int32_t bufLen, STsdbRepOpts *pInfo); int32_t tDeserializeTsdbRepOpts(void *buf, int32_t bufLen, STsdbRepOpts *pInfo); int32_t tMissingFileListDataLenCalc(int32_t fileCount); -int32_t tDeserializeMissingFileList(void *buf, int32_t bufLen, void **ppFiles, int32_t *pFileCount, SHashObj **ppHash); +int32_t tDeserializeMissingFileList(void *buf, int32_t bufLen, void **ppFiles, int32_t *pFileCount, SHashObj **ppHash, + SHashObj **ppSttHash); int32_t tsdbExtractMissingFids(STsdb *pTsdb, SHashObj *missingFileHash, int32_t **ppFids, int32_t *pFidCount); int32_t tsdbDetermineFidSyncMode(STsdb *pTsdb, const void *files, int32_t fileCount, SHashObj **ppFidModeHash); @@ -737,6 +738,13 @@ int32_t tsdbDetermineFidSyncMode(STsdb *pTsdb, const void *files, int32_t fileCo static inline int64_t tsdbMissingFileKey(int32_t fid, int32_t ftype) { return ((int64_t)fid << 32) | (uint32_t)ftype; } +// stt hash key: (fid, cid) composite key to avoid collision across different file sets +#define TSDB_STT_HASH_KEY_LEN (sizeof(int32_t) + sizeof(int64_t)) +static inline void tsdbSttHashKey(int32_t fid, int64_t cid, char key[TSDB_STT_HASH_KEY_LEN]) { + memcpy(key, &fid, sizeof(fid)); + memcpy(key + sizeof(fid), &cid, sizeof(cid)); +} + // snap read struct STsdbReadSnap { SMemTable *pMem; diff --git a/source/dnode/vnode/src/inc/vnodeInt.h b/source/dnode/vnode/src/inc/vnodeInt.h index 1ebf76ac73a6..76958dc6f0aa 100644 --- a/source/dnode/vnode/src/inc/vnodeInt.h +++ b/source/dnode/vnode/src/inc/vnodeInt.h @@ -343,8 +343,8 @@ int32_t tsdbSnapWriterPrepareClose(STsdbSnapWriter* pWriter, bool rollback); int32_t tsdbSnapWriterClose(STsdbSnapWriter** ppWriter, int8_t rollback); // STsdbSnapRAWReader ======================================== int32_t tsdbSnapRAWReaderOpen(STsdb* pTsdb, int64_t ever, int8_t type, void* pRanges, SHashObj* missingFileHash, - SHashObj* fidModeHash, const int32_t* missingFids, int32_t missingFidCount, - STsdbSnapRAWReader** ppReader); + SHashObj* fidModeHash, SHashObj* missingSttHash, const int32_t* missingFids, + int32_t missingFidCount, STsdbSnapRAWReader** ppReader); void tsdbSnapRAWReaderClose(STsdbSnapRAWReader** ppReader); int32_t tsdbSnapRAWRead(STsdbSnapRAWReader* pReader, uint8_t** ppData); // STsdbSnapRAWWriter ======================================== diff --git a/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c b/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c index e82f158a46f9..4e6518e3b6de 100644 --- a/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c +++ b/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c @@ -16,15 +16,17 @@ #include "tsdb.h" #include "tsdbFS2.h" -#define TSDB_SNAP_MSG_VER 1 +#define TSDB_SNAP_MSG_VER 2 -// missing file identifier: (fid, ftype, cid, size) +// file info for snapshot sync: (fid, ftype, level, cid, size, isMissing) typedef struct { int32_t fid; - int32_t ftype; // tsdb_ftype_t - int64_t cid; // commit id - int64_t size; // file size -} STsdbMissingFile; + int32_t ftype; // tsdb_ftype_t + int32_t level; // STT level (0/1/2), farr files use 0 + int64_t cid; // commit id + int64_t size; // file size + int8_t isMissing; // 1=missing, 0=present +} STsdbSnapFileInfo; // fset partition static int32_t tsdbFSetPartCmprFn(STsdbFSetPartition* x, STsdbFSetPartition* y) { @@ -545,12 +547,13 @@ int32_t tMissingFileListDataLenCalc(int32_t fileCount) { hdrLen += sizeof(msgVer); datLen += hdrLen; datLen += sizeof(int32_t); // fileCount - datLen += - fileCount * (sizeof(int32_t) + sizeof(int32_t) + sizeof(int64_t) + sizeof(int64_t)); // fid + ftype + cid + size + // fid + ftype + level + cid + size + isMissing = 4+4+4+8+8+1 = 29 bytes per record + datLen += fileCount * + (sizeof(int32_t) + sizeof(int32_t) + sizeof(int32_t) + sizeof(int64_t) + sizeof(int64_t) + sizeof(int8_t)); return datLen; } -int32_t tSerializeMissingFileList(void* buf, int32_t bufLen, const STsdbMissingFile* files, int32_t fileCount) { +int32_t tSerializeMissingFileList(void* buf, int32_t bufLen, const STsdbSnapFileInfo* files, int32_t fileCount) { int32_t code = 0; SEncoder encoder = {0}; int8_t msgVer = TSDB_SNAP_MSG_VER; @@ -563,8 +566,10 @@ int32_t tSerializeMissingFileList(void* buf, int32_t bufLen, const STsdbMissingF for (int32_t i = 0; i < fileCount; ++i) { if ((code = tEncodeI32(&encoder, files[i].fid))) goto _err; if ((code = tEncodeI32(&encoder, files[i].ftype))) goto _err; + if ((code = tEncodeI32(&encoder, files[i].level))) goto _err; if ((code = tEncodeI64(&encoder, files[i].cid))) goto _err; if ((code = tEncodeI64(&encoder, files[i].size))) goto _err; + if ((code = tEncodeI8(&encoder, files[i].isMissing))) goto _err; } tEndEncode(&encoder); @@ -577,13 +582,15 @@ int32_t tSerializeMissingFileList(void* buf, int32_t bufLen, const STsdbMissingF return code; } -int32_t tDeserializeMissingFileList(void* buf, int32_t bufLen, void** ppFiles, int32_t* pFileCount, SHashObj** ppHash) { - int32_t code = 0; - SDecoder decoder = {0}; - int8_t msgVer = 0; - int32_t fileCount = 0; - SHashObj* pHash = NULL; - STsdbMissingFile* files = NULL; +int32_t tDeserializeMissingFileList(void* buf, int32_t bufLen, void** ppFiles, int32_t* pFileCount, SHashObj** ppHash, + SHashObj** ppSttHash) { + int32_t code = 0; + SDecoder decoder = {0}; + int8_t msgVer = 0; + int32_t fileCount = 0; + SHashObj* pHash = NULL; + SHashObj* pSttHash = NULL; + STsdbSnapFileInfo* files = NULL; tDecoderInit(&decoder, buf, bufLen); @@ -604,7 +611,12 @@ int32_t tDeserializeMissingFileList(void* buf, int32_t bufLen, void** ppFiles, i code = terrno; goto _err; } - files = taosMemoryMalloc(fileCount * sizeof(STsdbMissingFile)); + pSttHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK); + if (pSttHash == NULL) { + code = terrno; + goto _err; + } + files = taosMemoryMalloc(fileCount * sizeof(STsdbSnapFileInfo)); if (files == NULL) { code = terrno; goto _err; @@ -612,15 +624,30 @@ int32_t tDeserializeMissingFileList(void* buf, int32_t bufLen, void** ppFiles, i for (int32_t i = 0; i < fileCount; ++i) { if ((code = tDecodeI32(&decoder, &files[i].fid))) goto _err; if ((code = tDecodeI32(&decoder, &files[i].ftype))) goto _err; + if ((code = tDecodeI32(&decoder, &files[i].level))) goto _err; if ((code = tDecodeI64(&decoder, &files[i].cid))) goto _err; if ((code = tDecodeI64(&decoder, &files[i].size))) goto _err; - char dummy = 0; - int64_t key = tsdbMissingFileKey(files[i].fid, files[i].ftype); - tsdbDebug("Missing File fid:%d ftype:%d cid:%" PRId64 " size:%" PRId64, files[i].fid, files[i].ftype, - files[i].cid, files[i].size); - if (taosHashPut(pHash, &key, sizeof(key), &dummy, sizeof(dummy)) != 0) { - code = terrno; - goto _err; + if ((code = tDecodeI8(&decoder, &files[i].isMissing))) goto _err; + + tsdbDebug("FileInfo fid:%d ftype:%d level:%d cid:%" PRId64 " size:%" PRId64 " isMissing:%d", files[i].fid, + files[i].ftype, files[i].level, files[i].cid, files[i].size, files[i].isMissing); + + if (files[i].isMissing) { + char dummy = 0; + int64_t key = tsdbMissingFileKey(files[i].fid, files[i].ftype); + if (taosHashPut(pHash, &key, sizeof(key), &dummy, sizeof(dummy)) != 0) { + code = terrno; + goto _err; + } + // for STT files, also put into missingSttHash keyed by (fid, cid) + if (files[i].ftype == TSDB_FTYPE_STT) { + char sttKey[TSDB_STT_HASH_KEY_LEN]; + tsdbSttHashKey(files[i].fid, files[i].cid, sttKey); + if (taosHashPut(pSttHash, sttKey, sizeof(sttKey), &dummy, sizeof(dummy)) != 0) { + code = terrno; + goto _err; + } + } } } } @@ -629,12 +656,14 @@ int32_t tDeserializeMissingFileList(void* buf, int32_t bufLen, void** ppFiles, i tDecoderClear(&decoder); *ppHash = pHash; + *ppSttHash = pSttHash; *ppFiles = (void*)files; *pFileCount = fileCount; return 0; _err: if (pHash) taosHashCleanup(pHash); + if (pSttHash) taosHashCleanup(pSttHash); taosMemoryFree(files); tDecoderClear(&decoder); return code; @@ -697,9 +726,9 @@ int32_t tsdbExtractMissingFids(STsdb* pTsdb, SHashObj* missingFileHash, int32_t* } int32_t tsdbDetermineFidSyncMode(STsdb* pTsdb, const void* pFileArr, int32_t fileCount, SHashObj** ppFidModeHash) { - int32_t code = 0; - SHashObj* pFidModeHash = NULL; - const STsdbMissingFile* files = (const STsdbMissingFile*)pFileArr; + int32_t code = 0; + SHashObj* pFidModeHash = NULL; + const STsdbSnapFileInfo* files = (const STsdbSnapFileInfo*)pFileArr; if (fileCount <= 0 || files == NULL) { *ppFidModeHash = NULL; @@ -715,9 +744,6 @@ int32_t tsdbDetermineFidSyncMode(STsdb* pTsdb, const void* pFileArr, int32_t fil for (int32_t i = 0; i < fileCount; ++i) { int32_t fid = files[i].fid; - int32_t ftype = files[i].ftype; - int64_t followerCid = files[i].cid; - int64_t followerSize = files[i].size; // check if already marked as FSET_LEVEL — skip further checks for this fid uint8_t* pExistMode = taosHashGet(pFidModeHash, &fid, sizeof(fid)); @@ -725,6 +751,13 @@ int32_t tsdbDetermineFidSyncMode(STsdb* pTsdb, const void* pFileArr, int32_t fil continue; } + // only process present files (isMissing=0) for content comparison + if (files[i].isMissing) continue; + + int32_t ftype = files[i].ftype; + int64_t followerCid = files[i].cid; + int64_t followerSize = files[i].size; + // find leader's corresponding file bool found = false; int64_t leaderCid = 0; @@ -735,7 +768,7 @@ int32_t tsdbDetermineFidSyncMode(STsdb* pTsdb, const void* pFileArr, int32_t fil if (fset->fid != fid) continue; if (ftype == TSDB_FTYPE_STT) { - // search STT files + // search STT files by cid SSttLvl* lvl; TARRAY2_FOREACH(fset->lvlArr, lvl) { STFileObj* fobj; @@ -761,17 +794,86 @@ int32_t tsdbDetermineFidSyncMode(STsdb* pTsdb, const void* pFileArr, int32_t fil // determine mode uint8_t mode = TSDB_SNAP_SYNC_FILE_LEVEL; - if (found && (leaderCid != followerCid || leaderSize != followerSize)) { + if (!found) { + // follower has a file that leader doesn't — content mismatcah + tsdbInfo("leader doesn't have file fid:%d, ftype:%d", files[i].fid, files[i].ftype); + mode = TSDB_SNAP_SYNC_FSET_LEVEL; + } else if (leaderCid != followerCid || leaderSize != followerSize) { + tsdbInfo("leader doesn't have different file fid:%d, ftype:%d, l-cid:%" PRId64 ", l-size:%" PRId64 + ", f-cid:%" PRId64 ", f-size:%" PRId64, + files[i].fid, files[i].ftype, leaderCid, leaderSize, followerCid, followerSize); mode = TSDB_SNAP_SYNC_FSET_LEVEL; } - // if leader doesn't have the file (found==false), keep FILE_LEVEL (leader can't send it anyway) - if (taosHashPut(pFidModeHash, &fid, sizeof(fid), &mode, sizeof(mode)) != 0) { - code = terrno; - (void)taosThreadMutexUnlock(&pTsdb->mutex); - taosHashCleanup(pFidModeHash); - return code; + if (mode == TSDB_SNAP_SYNC_FSET_LEVEL) { + if (taosHashPut(pFidModeHash, &fid, sizeof(fid), &mode, sizeof(mode)) != 0) { + code = terrno; + (void)taosThreadMutexUnlock(&pTsdb->mutex); + taosHashCleanup(pFidModeHash); + return code; + } + continue; + } + + // ensure fid has an entry (FILE_LEVEL if not already set) + if (pExistMode == NULL) { + if (taosHashPut(pFidModeHash, &fid, sizeof(fid), &mode, sizeof(mode)) != 0) { + code = terrno; + (void)taosThreadMutexUnlock(&pTsdb->mutex); + taosHashCleanup(pFidModeHash); + return code; + } + } + } + + // second pass: check leader STT files that follower doesn't know about at all + STFileSet* fset; + TARRAY2_FOREACH(pTsdb->pFS->fSetArr, fset) { + int32_t fid = fset->fid; + + uint8_t* pExistMode = taosHashGet(pFidModeHash, &fid, sizeof(fid)); + if (pExistMode != NULL && *pExistMode == TSDB_SNAP_SYNC_FSET_LEVEL) { + continue; + } + + // check if this fid has any file info from follower + bool fidHasInfo = false; + for (int32_t i = 0; i < fileCount; ++i) { + if (files[i].fid == fid) { + fidHasInfo = true; + break; + } + } + if (!fidHasInfo) continue; + + // for each leader STT file, check if follower reported it (either present or missing) + SSttLvl* lvl; + TARRAY2_FOREACH(fset->lvlArr, lvl) { + STFileObj* fobj; + TARRAY2_FOREACH(lvl->fobjArr, fobj) { + int64_t leaderCid = fobj->f->cid; + bool followerKnows = false; + for (int32_t i = 0; i < fileCount; ++i) { + if (files[i].fid == fid && files[i].ftype == TSDB_FTYPE_STT && files[i].cid == leaderCid) { + followerKnows = true; + break; + } + } + if (!followerKnows) { + // leader has STT file that follower doesn't know about — need FSET_LEVEL + tsdbInfo("follower doesn't have stt file fid:%d, cid:%" PRId64, fid, leaderCid); + uint8_t mode = TSDB_SNAP_SYNC_FSET_LEVEL; + if (taosHashPut(pFidModeHash, &fid, sizeof(fid), &mode, sizeof(mode)) != 0) { + code = terrno; + (void)taosThreadMutexUnlock(&pTsdb->mutex); + taosHashCleanup(pFidModeHash); + return code; + } + goto _next_fset; + } + } } + _next_fset:; } (void)taosThreadMutexUnlock(&pTsdb->mutex); @@ -780,12 +882,12 @@ int32_t tsdbDetermineFidSyncMode(STsdb* pTsdb, const void* pFileArr, int32_t fil return 0; } -static int32_t tsdbDetectMissingFiles(SVnode* pVnode, STsdbMissingFile** ppFiles, int32_t* pFileCount) { - int32_t code = 0; - STsdbMissingFile* files = NULL; - int32_t fileCount = 0; - int32_t fileCap = 0; - STsdb* pTsdb = pVnode->pTsdb; +static int32_t tsdbCollectAllFileInfo(SVnode* pVnode, STsdbSnapFileInfo** ppFiles, int32_t* pFileCount) { + int32_t code = 0; + STsdbSnapFileInfo* files = NULL; + int32_t fileCount = 0; + int32_t fileCap = 0; + STsdb* pTsdb = pVnode->pTsdb; *ppFiles = NULL; *pFileCount = 0; @@ -794,51 +896,51 @@ static int32_t tsdbDetectMissingFiles(SVnode* pVnode, STsdbMissingFile** ppFiles STFileSet* fset; TARRAY2_FOREACH(pTsdb->pFS->fSetArr, fset) { - // check farr entries (HEAD, DATA, SMA, TOMB) + // collect farr entries (HEAD, DATA, SMA, TOMB) for (int32_t ftype = TSDB_FTYPE_MIN; ftype < TSDB_FTYPE_MAX; ++ftype) { if (fset->farr[ftype] != NULL) { - if (!taosCheckExistFile(fset->farr[ftype]->fname)) { - if (fileCount >= fileCap) { - int32_t newCap = fileCap == 0 ? 16 : fileCap * 2; - STsdbMissingFile* tmp = taosMemoryRealloc(files, newCap * sizeof(STsdbMissingFile)); - if (tmp == NULL) { - code = terrno; - goto _unlock; - } - files = tmp; - fileCap = newCap; + if (fileCount >= fileCap) { + int32_t newCap = fileCap == 0 ? 16 : fileCap * 2; + STsdbSnapFileInfo* tmp = taosMemoryRealloc(files, newCap * sizeof(STsdbSnapFileInfo)); + if (tmp == NULL) { + code = terrno; + goto _unlock; } - files[fileCount].fid = fset->fid; - files[fileCount].ftype = ftype; - files[fileCount].cid = fset->farr[ftype]->f->cid; - files[fileCount].size = fset->farr[ftype]->f->size; - fileCount++; + files = tmp; + fileCap = newCap; } + files[fileCount].fid = fset->fid; + files[fileCount].ftype = ftype; + files[fileCount].level = 0; + files[fileCount].cid = fset->farr[ftype]->f->cid; + files[fileCount].size = fset->farr[ftype]->f->size; + files[fileCount].isMissing = !taosCheckExistFile(fset->farr[ftype]->fname) ? 1 : 0; + fileCount++; } } - // check STT files in lvlArr — record each missing STT file individually + // collect STT files in lvlArr SSttLvl* lvl; TARRAY2_FOREACH(fset->lvlArr, lvl) { STFileObj* fobj; TARRAY2_FOREACH(lvl->fobjArr, fobj) { - if (!taosCheckExistFile(fobj->fname)) { - if (fileCount >= fileCap) { - int32_t newCap = fileCap == 0 ? 16 : fileCap * 2; - STsdbMissingFile* tmp = taosMemoryRealloc(files, newCap * sizeof(STsdbMissingFile)); - if (tmp == NULL) { - code = terrno; - goto _unlock; - } - files = tmp; - fileCap = newCap; + if (fileCount >= fileCap) { + int32_t newCap = fileCap == 0 ? 16 : fileCap * 2; + STsdbSnapFileInfo* tmp = taosMemoryRealloc(files, newCap * sizeof(STsdbSnapFileInfo)); + if (tmp == NULL) { + code = terrno; + goto _unlock; } - files[fileCount].fid = fset->fid; - files[fileCount].ftype = TSDB_FTYPE_STT; - files[fileCount].cid = fobj->f->cid; - files[fileCount].size = fobj->f->size; - fileCount++; + files = tmp; + fileCap = newCap; } + files[fileCount].fid = fset->fid; + files[fileCount].ftype = TSDB_FTYPE_STT; + files[fileCount].level = lvl->level; + files[fileCount].cid = fobj->f->cid; + files[fileCount].size = fobj->f->size; + files[fileCount].isMissing = !taosCheckExistFile(fobj->fname) ? 1 : 0; + fileCount++; } } } @@ -860,7 +962,7 @@ static int32_t tsdbMissingFilesEstSize(int32_t fileCount) { return sizeof(SSyncTLV) + tMissingFileListDataLenCalc(fileCount); } -static int32_t tsdbMissingFilesSerialize(const STsdbMissingFile* files, int32_t fileCount, void* buf, int32_t bufLen) { +static int32_t tsdbMissingFilesSerialize(const STsdbSnapFileInfo* files, int32_t fileCount, void* buf, int32_t bufLen) { SSyncTLV* pSubHead = buf; int32_t tlen = tSerializeMissingFileList(pSubHead->val, bufLen - sizeof(*pSubHead), files, fileCount); if (tlen < 0) return tlen; @@ -937,9 +1039,9 @@ int32_t tsdbSnapPrepDescription(SVnode* pVnode, SSnapshot* pSnap) { } // deal with snap info for reply - STsdbRepOpts opts = {.format = TSDB_SNAP_REP_FMT_RAW}; - STsdbMissingFile* missingFiles = NULL; - int32_t missingFileCount = 0; + STsdbRepOpts opts = {.format = TSDB_SNAP_REP_FMT_RAW}; + STsdbSnapFileInfo* missingFiles = NULL; + int32_t missingFileCount = 0; if (pSnap->type == TDMT_SYNC_PREP_SNAPSHOT_REPLY) { STsdbRepOpts leaderOpts = {0}; if ((code = tsdbSnapPrepDealWithSnapInfo(pVnode, pSnap, &leaderOpts)) < 0) { @@ -948,13 +1050,13 @@ int32_t tsdbSnapPrepDescription(SVnode* pVnode, SSnapshot* pSnap) { } opts.format = TMIN(opts.format, leaderOpts.format); - int32_t detectCode = tsdbDetectMissingFiles(pVnode, &missingFiles, &missingFileCount); + int32_t detectCode = tsdbCollectAllFileInfo(pVnode, &missingFiles, &missingFileCount); if (detectCode != 0) { - tsdbWarn("vgId:%d, failed to detect missing files since %s, continuing without", TD_VID(pVnode), + tsdbWarn("vgId:%d, failed to collect file info since %s, continuing without", TD_VID(pVnode), tstrerror(detectCode)); missingFileCount = 0; } else if (missingFileCount > 0) { - tsdbInfo("vgId:%d, detected %d missing files for snapshot", TD_VID(pVnode), missingFileCount); + tsdbInfo("vgId:%d, collected %d file info entries for snapshot", TD_VID(pVnode), missingFileCount); } } diff --git a/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c b/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c index ce9b691eb7de..7ffda6253ddc 100644 --- a/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c +++ b/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c @@ -49,6 +49,7 @@ typedef struct STsdbSnapRAWReader { // missing file filter SHashObj* missingFileHash; // key=(fid,ftype) — per-file filtering (not owned, do not free) SHashObj* fidModeHash; // key=fid, val=uint8_t mode (not owned, do not free) + SHashObj* missingSttHash; // key=(fid,cid) — per-STT filtering (not owned, do not free) int32_t* missingFids; // FID set for FID-level pre-filtering (owned, copy) int32_t missingFidCount; } STsdbSnapRAWReader; @@ -67,8 +68,8 @@ static bool tsdbFidInMissingSet(int32_t fid, const int32_t* missingFids, int32_t } int32_t tsdbSnapRAWReaderOpen(STsdb* tsdb, int64_t ever, int8_t type, void* pRanges, SHashObj* missingFileHash, - SHashObj* fidModeHash, const int32_t* missingFids, int32_t missingFidCount, - STsdbSnapRAWReader** reader) { + SHashObj* fidModeHash, SHashObj* missingSttHash, const int32_t* missingFids, + int32_t missingFidCount, STsdbSnapRAWReader** reader) { int32_t code = 0; int32_t lino = 0; @@ -82,6 +83,7 @@ int32_t tsdbSnapRAWReaderOpen(STsdb* tsdb, int64_t ever, int8_t type, void* pRan // set missing file filter (hash is borrowed, not owned) reader[0]->missingFileHash = missingFileHash; reader[0]->fidModeHash = fidModeHash; + reader[0]->missingSttHash = missingSttHash; // copy missing fid filter if (missingFids != NULL && missingFidCount > 0) { @@ -189,11 +191,13 @@ static int32_t tsdbSnapRAWReadFileSetOpenReader(STsdbSnapRAWReader* reader) { STFileObj* fobj; TARRAY2_FOREACH(lvl->fobjArr, fobj) { // per-file filter: skip stt files not in missing set (only when FILE_LEVEL mode) - if (!fsetLevel && reader->missingFileHash != NULL) { - int64_t mfKey = tsdbMissingFileKey(reader->ctx->fset->fid, TSDB_FTYPE_STT); - if (taosHashGet(reader->missingFileHash, &mfKey, sizeof(mfKey)) == NULL) { - tsdbDebug("vgId:%d, RAW skip stt file fid:%d not in missing set", TD_VID(reader->tsdb->pVnode), - reader->ctx->fset->fid); + if (!fsetLevel && reader->missingSttHash != NULL) { + int64_t sttCid = fobj->f->cid; + char sttKey[TSDB_STT_HASH_KEY_LEN]; + tsdbSttHashKey(reader->ctx->fset->fid, sttCid, sttKey); + if (taosHashGet(reader->missingSttHash, sttKey, sizeof(sttKey)) == NULL) { + tsdbDebug("vgId:%d, RAW skip stt file fid:%d cid:%" PRId64 " not in missing set", + TD_VID(reader->tsdb->pVnode), reader->ctx->fset->fid, sttCid); continue; } } diff --git a/source/dnode/vnode/src/vnd/vnodeSnapshot.c b/source/dnode/vnode/src/vnd/vnodeSnapshot.c index 8c3358a9a966..0c71904ac1fd 100644 --- a/source/dnode/vnode/src/vnd/vnodeSnapshot.c +++ b/source/dnode/vnode/src/vnd/vnodeSnapshot.c @@ -56,6 +56,7 @@ struct SVSnapReader { // missing file filter SHashObj *missingFileHash; // key=(fid,ftype), val=dummy — for RAW mode per-file filtering SHashObj *fidModeHash; // key=fid, val=uint8_t mode (FILE_LEVEL or FSET_LEVEL) + SHashObj *missingSttHash; // key=cid, val=dummy — for RAW mode per-STT filtering int32_t *missingFids; // FID set extracted from file names — for Normal mode FID filtering int32_t missingFidCount; @@ -148,12 +149,14 @@ static int32_t vnodeSnapReaderDealWithSnapInfo(SVSnapReader *pReader, SSnapshotP case SNAP_DATA_MISSING_FIDS: { void *missingFiles = NULL; int32_t missingFileCount = 0; - code = tDeserializeMissingFileList(buf, bufLen, &missingFiles, &missingFileCount, &pReader->missingFileHash); + code = tDeserializeMissingFileList(buf, bufLen, &missingFiles, &missingFileCount, &pReader->missingFileHash, + &pReader->missingSttHash); if (code) { vError("vgId:%d, failed to deserialize missing file list since %s", TD_VID(pVnode), tstrerror(code)); goto _out; } - vInfo("vgId:%d, received %d missing files from follower", TD_VID(pVnode), missingFileCount); + vInfo("vgId:%d, received %d file infos from follower, missing:%d", TD_VID(pVnode), missingFileCount, + (pReader->missingFileHash ? (int32_t)taosHashGetSize(pReader->missingFileHash) : 0)); // determine sync mode per fid if (missingFiles && missingFileCount > 0) { code = tsdbDetermineFidSyncMode(pVnode->pTsdb, missingFiles, missingFileCount, &pReader->fidModeHash); @@ -219,8 +222,8 @@ int32_t vnodeSnapReaderOpen(SVnode *pVnode, SSnapshotParam *pParam, SVSnapReader // open tsdb snapshot raw reader if (!pReader->tsdbRAWDone) { code = tsdbSnapRAWReaderOpen(pVnode->pTsdb, ever, SNAP_DATA_RAW, pReader->pRanges, pReader->missingFileHash, - pReader->fidModeHash, pReader->missingFids, pReader->missingFidCount, - &pReader->pTsdbRAWReader); + pReader->fidModeHash, pReader->missingSttHash, pReader->missingFids, + pReader->missingFidCount, &pReader->pTsdbRAWReader); if (code) goto _exit; } @@ -294,6 +297,9 @@ void vnodeSnapReaderClose(SVSnapReader *pReader) { if (pReader->fidModeHash) { taosHashCleanup(pReader->fidModeHash); } + if (pReader->missingSttHash) { + taosHashCleanup(pReader->missingSttHash); + } taosMemoryFree(pReader->missingFids); taosMemoryFree(pReader); } @@ -398,8 +404,8 @@ int32_t vnodeSnapRead(SVSnapReader *pReader, uint8_t **ppData, uint32_t *nData) // open if not if (pReader->pTsdbRAWReader == NULL) { code = tsdbSnapRAWReaderOpen(pReader->pVnode->pTsdb, pReader->ever, SNAP_DATA_RAW, pReader->pRanges, - pReader->missingFileHash, pReader->fidModeHash, pReader->missingFids, - pReader->missingFidCount, &pReader->pTsdbRAWReader); + pReader->missingFileHash, pReader->fidModeHash, pReader->missingSttHash, + pReader->missingFids, pReader->missingFidCount, &pReader->pTsdbRAWReader); TSDB_CHECK_CODE(code, lino, _exit); } From c1f0fb099493d1d073efd9cab7bb4d21b8b86c25 Mon Sep 17 00:00:00 2001 From: chen dongming Date: Wed, 20 May 2026 10:35:19 +0800 Subject: [PATCH 06/12] change key --- source/dnode/vnode/src/inc/tsdb.h | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/source/dnode/vnode/src/inc/tsdb.h b/source/dnode/vnode/src/inc/tsdb.h index 41e8d405a4f5..2c39b2152d41 100644 --- a/source/dnode/vnode/src/inc/tsdb.h +++ b/source/dnode/vnode/src/inc/tsdb.h @@ -736,13 +736,20 @@ int32_t tsdbDetermineFidSyncMode(STsdb *pTsdb, const void *files, int32_t fileCo #define TSDB_SNAP_SYNC_FILE_LEVEL 0 #define TSDB_SNAP_SYNC_FSET_LEVEL 1 -static inline int64_t tsdbMissingFileKey(int32_t fid, int32_t ftype) { return ((int64_t)fid << 32) | (uint32_t)ftype; } - -// stt hash key: (fid, cid) composite key to avoid collision across different file sets -#define TSDB_STT_HASH_KEY_LEN (sizeof(int32_t) + sizeof(int64_t)) -static inline void tsdbSttHashKey(int32_t fid, int64_t cid, char key[TSDB_STT_HASH_KEY_LEN]) { - memcpy(key, &fid, sizeof(fid)); - memcpy(key + sizeof(fid), &cid, sizeof(cid)); +// snap file 5-tuple key for version-range matching: (fid, ftype, level, minVer, maxVer) +#define TSDB_SNAP_FILE_KEY_LEN (sizeof(int32_t) + sizeof(int32_t) + sizeof(int32_t) + sizeof(int64_t) + sizeof(int64_t)) +static inline void tsdbSnapFileKeyMake(int32_t fid, int32_t ftype, int32_t level, int64_t minVer, int64_t maxVer, + char key[TSDB_SNAP_FILE_KEY_LEN]) { + int32_t offset = 0; + memcpy(key + offset, &fid, sizeof(fid)); + offset += sizeof(fid); + memcpy(key + offset, &ftype, sizeof(ftype)); + offset += sizeof(ftype); + memcpy(key + offset, &level, sizeof(level)); + offset += sizeof(level); + memcpy(key + offset, &minVer, sizeof(minVer)); + offset += sizeof(minVer); + memcpy(key + offset, &maxVer, sizeof(maxVer)); } // snap read From 221abe79fd2887d9388a23f0895d38f4fd789477 Mon Sep 17 00:00:00 2001 From: chen dongming Date: Wed, 20 May 2026 10:36:21 +0800 Subject: [PATCH 07/12] use 5 tuple key --- source/dnode/vnode/src/tsdb/tsdbSnapInfo.c | 299 ++++++++++++--------- 1 file changed, 177 insertions(+), 122 deletions(-) diff --git a/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c b/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c index 4e6518e3b6de..012d8058900f 100644 --- a/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c +++ b/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c @@ -18,11 +18,13 @@ #define TSDB_SNAP_MSG_VER 2 -// file info for snapshot sync: (fid, ftype, level, cid, size, isMissing) +// file info for snapshot sync: (fid, ftype, level, minVer, maxVer, cid, size, isMissing) typedef struct { int32_t fid; int32_t ftype; // tsdb_ftype_t int32_t level; // STT level (0/1/2), farr files use 0 + int64_t minVer; // min version in file + int64_t maxVer; // max version in file int64_t cid; // commit id int64_t size; // file size int8_t isMissing; // 1=missing, 0=present @@ -547,9 +549,9 @@ int32_t tMissingFileListDataLenCalc(int32_t fileCount) { hdrLen += sizeof(msgVer); datLen += hdrLen; datLen += sizeof(int32_t); // fileCount - // fid + ftype + level + cid + size + isMissing = 4+4+4+8+8+1 = 29 bytes per record - datLen += fileCount * - (sizeof(int32_t) + sizeof(int32_t) + sizeof(int32_t) + sizeof(int64_t) + sizeof(int64_t) + sizeof(int8_t)); + // fid + ftype + level + minVer + maxVer + cid + size + isMissing = 4+4+4+8+8+8+8+1 = 45 bytes per record + datLen += fileCount * (sizeof(int32_t) + sizeof(int32_t) + sizeof(int32_t) + sizeof(int64_t) + sizeof(int64_t) + + sizeof(int64_t) + sizeof(int64_t) + sizeof(int8_t)); return datLen; } @@ -567,6 +569,8 @@ int32_t tSerializeMissingFileList(void* buf, int32_t bufLen, const STsdbSnapFile if ((code = tEncodeI32(&encoder, files[i].fid))) goto _err; if ((code = tEncodeI32(&encoder, files[i].ftype))) goto _err; if ((code = tEncodeI32(&encoder, files[i].level))) goto _err; + if ((code = tEncodeI64(&encoder, files[i].minVer))) goto _err; + if ((code = tEncodeI64(&encoder, files[i].maxVer))) goto _err; if ((code = tEncodeI64(&encoder, files[i].cid))) goto _err; if ((code = tEncodeI64(&encoder, files[i].size))) goto _err; if ((code = tEncodeI8(&encoder, files[i].isMissing))) goto _err; @@ -606,7 +610,7 @@ int32_t tDeserializeMissingFileList(void* buf, int32_t bufLen, void** ppFiles, i goto _err; } if (fileCount > 0) { - pHash = taosHashInit(fileCount * 2, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_ENTRY_LOCK); + pHash = taosHashInit(fileCount * 2, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK); if (pHash == NULL) { code = terrno; goto _err; @@ -625,25 +629,29 @@ int32_t tDeserializeMissingFileList(void* buf, int32_t bufLen, void** ppFiles, i if ((code = tDecodeI32(&decoder, &files[i].fid))) goto _err; if ((code = tDecodeI32(&decoder, &files[i].ftype))) goto _err; if ((code = tDecodeI32(&decoder, &files[i].level))) goto _err; + if ((code = tDecodeI64(&decoder, &files[i].minVer))) goto _err; + if ((code = tDecodeI64(&decoder, &files[i].maxVer))) goto _err; if ((code = tDecodeI64(&decoder, &files[i].cid))) goto _err; if ((code = tDecodeI64(&decoder, &files[i].size))) goto _err; if ((code = tDecodeI8(&decoder, &files[i].isMissing))) goto _err; - tsdbDebug("FileInfo fid:%d ftype:%d level:%d cid:%" PRId64 " size:%" PRId64 " isMissing:%d", files[i].fid, - files[i].ftype, files[i].level, files[i].cid, files[i].size, files[i].isMissing); + tsdbDebug("FileInfo fid:%d ftype:%d level:%d minVer:%" PRId64 " maxVer:%" PRId64 " cid:%" PRId64 " size:%" PRId64 + " isMissing:%d", + files[i].fid, files[i].ftype, files[i].level, files[i].minVer, files[i].maxVer, files[i].cid, + files[i].size, files[i].isMissing); if (files[i].isMissing) { char dummy = 0; - int64_t key = tsdbMissingFileKey(files[i].fid, files[i].ftype); - if (taosHashPut(pHash, &key, sizeof(key), &dummy, sizeof(dummy)) != 0) { + char key[TSDB_SNAP_FILE_KEY_LEN]; + tsdbSnapFileKeyMake(files[i].fid, files[i].ftype, files[i].level, files[i].minVer, files[i].maxVer, key); + + if (taosHashPut(pHash, key, sizeof(key), &dummy, sizeof(dummy)) != 0) { code = terrno; goto _err; } - // for STT files, also put into missingSttHash keyed by (fid, cid) + // for STT files, also put into missingSttHash keyed by 5-tuple (fid, ftype, level, minVer, maxVer) if (files[i].ftype == TSDB_FTYPE_STT) { - char sttKey[TSDB_STT_HASH_KEY_LEN]; - tsdbSttHashKey(files[i].fid, files[i].cid, sttKey); - if (taosHashPut(pSttHash, sttKey, sizeof(sttKey), &dummy, sizeof(dummy)) != 0) { + if (taosHashPut(pSttHash, key, sizeof(key), &dummy, sizeof(dummy)) != 0) { code = terrno; goto _err; } @@ -675,12 +683,13 @@ int32_t tsdbExtractMissingFids(STsdb* pTsdb, SHashObj* missingFileHash, int32_t* int32_t fidCount = 0; int32_t* fids = NULL; - // extract unique fids from hash keys (key = (fid << 32) | ftype) + // extract unique fids from hash keys (key = 5-tuple binary: fid, ftype, level, minVer, maxVer) void* pIter = NULL; while ((pIter = taosHashIterate(missingFileHash, pIter)) != NULL) { - size_t keyLen = 0; - int64_t* pKey = taosHashGetKey(pIter, &keyLen); - int32_t fid = (int32_t)(*pKey >> 32); + size_t keyLen = 0; + char* pKey = taosHashGetKey(pIter, &keyLen); + int32_t fid; + memcpy(&fid, pKey, sizeof(fid)); // check if fid already exists bool exists = false; @@ -728,6 +737,9 @@ int32_t tsdbExtractMissingFids(STsdb* pTsdb, SHashObj* missingFileHash, int32_t* int32_t tsdbDetermineFidSyncMode(STsdb* pTsdb, const void* pFileArr, int32_t fileCount, SHashObj** ppFidModeHash) { int32_t code = 0; SHashObj* pFidModeHash = NULL; + SHashObj* pLeaderKeyHash = NULL; + SHashObj* pFollowerKeyHash = NULL; + SHashObj* pFollowerFidSet = NULL; const STsdbSnapFileInfo* files = (const STsdbSnapFileInfo*)pFileArr; if (fileCount <= 0 || files == NULL) { @@ -740,146 +752,185 @@ int32_t tsdbDetermineFidSyncMode(STsdb* pTsdb, const void* pFileArr, int32_t fil return terrno; } + // build leader file key hash: key=(fid,ftype,level,minVer,maxVer) -> (cid, size) + pLeaderKeyHash = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK); + if (pLeaderKeyHash == NULL) { + code = terrno; + goto _out; + } + + typedef struct { + int64_t cid; + int64_t size; + } SLeaderFileVal; + (void)taosThreadMutexLock(&pTsdb->mutex); + // populate leader key hash + { + STFileSet* fset; + TARRAY2_FOREACH(pTsdb->pFS->fSetArr, fset) { + for (int32_t ftype = TSDB_FTYPE_MIN; ftype < TSDB_FTYPE_MAX; ++ftype) { + if (fset->farr[ftype] != NULL) { + char key[TSDB_SNAP_FILE_KEY_LEN]; + tsdbSnapFileKeyMake(fset->fid, ftype, 0, fset->farr[ftype]->f->minVer, fset->farr[ftype]->f->maxVer, key); + SLeaderFileVal val = {.cid = fset->farr[ftype]->f->cid, .size = fset->farr[ftype]->f->size}; + if (taosHashPut(pLeaderKeyHash, key, TSDB_SNAP_FILE_KEY_LEN, &val, sizeof(val)) != 0) { + code = terrno; + goto _unlock; + } + } + } + SSttLvl* lvl; + TARRAY2_FOREACH(fset->lvlArr, lvl) { + STFileObj* fobj; + TARRAY2_FOREACH(lvl->fobjArr, fobj) { + char key[TSDB_SNAP_FILE_KEY_LEN]; + tsdbSnapFileKeyMake(fset->fid, TSDB_FTYPE_STT, lvl->level, fobj->f->minVer, fobj->f->maxVer, key); + SLeaderFileVal val = {.cid = fobj->f->cid, .size = fobj->f->size}; + if (taosHashPut(pLeaderKeyHash, key, TSDB_SNAP_FILE_KEY_LEN, &val, sizeof(val)) != 0) { + code = terrno; + goto _unlock; + } + } + } + } + } + + // first pass: check each follower present file against leader for (int32_t i = 0; i < fileCount; ++i) { + if (files[i].isMissing) continue; + int32_t fid = files[i].fid; - // check if already marked as FSET_LEVEL — skip further checks for this fid + // skip if already FSET_LEVEL uint8_t* pExistMode = taosHashGet(pFidModeHash, &fid, sizeof(fid)); if (pExistMode != NULL && *pExistMode == TSDB_SNAP_SYNC_FSET_LEVEL) { continue; } - // only process present files (isMissing=0) for content comparison - if (files[i].isMissing) continue; - - int32_t ftype = files[i].ftype; - int64_t followerCid = files[i].cid; - int64_t followerSize = files[i].size; + char key[TSDB_SNAP_FILE_KEY_LEN]; + tsdbSnapFileKeyMake(fid, files[i].ftype, files[i].level, files[i].minVer, files[i].maxVer, key); - // find leader's corresponding file - bool found = false; - int64_t leaderCid = 0; - int64_t leaderSize = 0; + SLeaderFileVal* pLeaderVal = taosHashGet(pLeaderKeyHash, key, TSDB_SNAP_FILE_KEY_LEN); - STFileSet* fset; - TARRAY2_FOREACH(pTsdb->pFS->fSetArr, fset) { - if (fset->fid != fid) continue; - - if (ftype == TSDB_FTYPE_STT) { - // search STT files by cid - SSttLvl* lvl; - TARRAY2_FOREACH(fset->lvlArr, lvl) { - STFileObj* fobj; - TARRAY2_FOREACH(lvl->fobjArr, fobj) { - if (fobj->f->cid == followerCid) { - found = true; - leaderCid = fobj->f->cid; - leaderSize = fobj->f->size; - break; - } - } - if (found) break; - } - } else if (ftype >= 0 && ftype < TSDB_FTYPE_MAX) { - if (fset->farr[ftype] != NULL) { - found = true; - leaderCid = fset->farr[ftype]->f->cid; - leaderSize = fset->farr[ftype]->f->size; - } - } - break; // found the fid - } - - // determine mode uint8_t mode = TSDB_SNAP_SYNC_FILE_LEVEL; - if (!found) { - // follower has a file that leader doesn't — content mismatcah - tsdbInfo("leader doesn't have file fid:%d, ftype:%d", files[i].fid, files[i].ftype); + if (pLeaderVal == NULL) { + tsdbInfo("vgId:%d, snap leader no match key fid:%d ftype:%d level:%d minVer:%" PRId64 " maxVer:%" PRId64, + TD_VID(pTsdb->pVnode), fid, files[i].ftype, files[i].level, files[i].minVer, files[i].maxVer); mode = TSDB_SNAP_SYNC_FSET_LEVEL; - } else if (leaderCid != followerCid || leaderSize != followerSize) { - tsdbInfo("leader doesn't have different file fid:%d, ftype:%d, l-cid:%" PRId64 ", l-size:%" PRId64 - ", f-cid:%" PRId64 ", f-size:%" PRId64, - files[i].fid, files[i].ftype, leaderCid, leaderSize, followerCid, followerSize); + } else if (pLeaderVal->size != files[i].size) { + tsdbInfo("vgId:%d, snap size mismatch fid:%d ftype:%d level:%d leader-size:%" PRId64 " follower-size:%" PRId64, + TD_VID(pTsdb->pVnode), fid, files[i].ftype, files[i].level, pLeaderVal->size, files[i].size); + mode = TSDB_SNAP_SYNC_FSET_LEVEL; + } else if (llabs(pLeaderVal->cid - files[i].cid) > 10) { + tsdbInfo("vgId:%d, snap cid diff>10 fid:%d ftype:%d level:%d leader-cid:%" PRId64 " follower-cid:%" PRId64, + TD_VID(pTsdb->pVnode), fid, files[i].ftype, files[i].level, pLeaderVal->cid, files[i].cid); mode = TSDB_SNAP_SYNC_FSET_LEVEL; } - if (mode == TSDB_SNAP_SYNC_FSET_LEVEL) { - if (taosHashPut(pFidModeHash, &fid, sizeof(fid), &mode, sizeof(mode)) != 0) { - code = terrno; - (void)taosThreadMutexUnlock(&pTsdb->mutex); - taosHashCleanup(pFidModeHash); - return code; - } - continue; + if (taosHashPut(pFidModeHash, &fid, sizeof(fid), &mode, sizeof(mode)) != 0) { + code = terrno; + goto _unlock; } + } - // ensure fid has an entry (FILE_LEVEL if not already set) - if (pExistMode == NULL) { - if (taosHashPut(pFidModeHash, &fid, sizeof(fid), &mode, sizeof(mode)) != 0) { - code = terrno; - (void)taosThreadMutexUnlock(&pTsdb->mutex); - taosHashCleanup(pFidModeHash); - return code; - } + // second pass: check leader files not known by follower (within reported fids) + pFollowerKeyHash = + taosHashInit(fileCount * 2, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK); + if (pFollowerKeyHash == NULL) { + code = terrno; + goto _unlock; + } + + for (int32_t i = 0; i < fileCount; ++i) { + char key[TSDB_SNAP_FILE_KEY_LEN]; + tsdbSnapFileKeyMake(files[i].fid, files[i].ftype, files[i].level, files[i].minVer, files[i].maxVer, key); + char dummy = 0; + if (taosHashPut(pFollowerKeyHash, key, TSDB_SNAP_FILE_KEY_LEN, &dummy, sizeof(dummy)) != 0) { + code = terrno; + goto _unlock; } } - // second pass: check leader STT files that follower doesn't know about at all - STFileSet* fset; - TARRAY2_FOREACH(pTsdb->pFS->fSetArr, fset) { - int32_t fid = fset->fid; + // collect fids that follower reported + pFollowerFidSet = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_ENTRY_LOCK); + if (pFollowerFidSet == NULL) { + code = terrno; + goto _unlock; + } + for (int32_t i = 0; i < fileCount; ++i) { + char dummy = 0; + (void)taosHashPut(pFollowerFidSet, &files[i].fid, sizeof(files[i].fid), &dummy, sizeof(dummy)); + } - uint8_t* pExistMode = taosHashGet(pFidModeHash, &fid, sizeof(fid)); - if (pExistMode != NULL && *pExistMode == TSDB_SNAP_SYNC_FSET_LEVEL) { - continue; - } + { + STFileSet* fset; + TARRAY2_FOREACH(pTsdb->pFS->fSetArr, fset) { + int32_t fid = fset->fid; - // check if this fid has any file info from follower - bool fidHasInfo = false; - for (int32_t i = 0; i < fileCount; ++i) { - if (files[i].fid == fid) { - fidHasInfo = true; - break; - } - } - if (!fidHasInfo) continue; + // skip fids not reported by follower + if (taosHashGet(pFollowerFidSet, &fid, sizeof(fid)) == NULL) continue; - // for each leader STT file, check if follower reported it (either present or missing) - SSttLvl* lvl; - TARRAY2_FOREACH(fset->lvlArr, lvl) { - STFileObj* fobj; - TARRAY2_FOREACH(lvl->fobjArr, fobj) { - int64_t leaderCid = fobj->f->cid; - bool followerKnows = false; - for (int32_t i = 0; i < fileCount; ++i) { - if (files[i].fid == fid && files[i].ftype == TSDB_FTYPE_STT && files[i].cid == leaderCid) { - followerKnows = true; - break; + // skip if already FSET_LEVEL + uint8_t* pExistMode = taosHashGet(pFidModeHash, &fid, sizeof(fid)); + if (pExistMode != NULL && *pExistMode == TSDB_SNAP_SYNC_FSET_LEVEL) continue; + + for (int32_t ftype = TSDB_FTYPE_MIN; ftype < TSDB_FTYPE_MAX; ++ftype) { + if (fset->farr[ftype] != NULL) { + char key[TSDB_SNAP_FILE_KEY_LEN]; + tsdbSnapFileKeyMake(fid, ftype, 0, fset->farr[ftype]->f->minVer, fset->farr[ftype]->f->maxVer, key); + if (taosHashGet(pFollowerKeyHash, key, TSDB_SNAP_FILE_KEY_LEN) == NULL) { + tsdbInfo("vgId:%d, snap follower missing leader file fid:%d ftype:%d minVer:%" PRId64 " maxVer:%" PRId64, + TD_VID(pTsdb->pVnode), fid, ftype, fset->farr[ftype]->f->minVer, fset->farr[ftype]->f->maxVer); + uint8_t mode = TSDB_SNAP_SYNC_FSET_LEVEL; + if (taosHashPut(pFidModeHash, &fid, sizeof(fid), &mode, sizeof(mode)) != 0) { + code = terrno; + goto _unlock; + } + goto _next_fset; } } - if (!followerKnows) { - // leader has STT file that follower doesn't know about — need FSET_LEVEL - tsdbInfo("follower doesn't have stt file fid:%d, cid:%" PRId64, fid, leaderCid); - uint8_t mode = TSDB_SNAP_SYNC_FSET_LEVEL; - if (taosHashPut(pFidModeHash, &fid, sizeof(fid), &mode, sizeof(mode)) != 0) { - code = terrno; - (void)taosThreadMutexUnlock(&pTsdb->mutex); - taosHashCleanup(pFidModeHash); - return code; + } + + SSttLvl* lvl; + TARRAY2_FOREACH(fset->lvlArr, lvl) { + STFileObj* fobj; + TARRAY2_FOREACH(lvl->fobjArr, fobj) { + char key[TSDB_SNAP_FILE_KEY_LEN]; + tsdbSnapFileKeyMake(fid, TSDB_FTYPE_STT, lvl->level, fobj->f->minVer, fobj->f->maxVer, key); + if (taosHashGet(pFollowerKeyHash, key, TSDB_SNAP_FILE_KEY_LEN) == NULL) { + tsdbInfo("vgId:%d, snap follower missing leader stt fid:%d level:%d minVer:%" PRId64 " maxVer:%" PRId64, + TD_VID(pTsdb->pVnode), fid, lvl->level, fobj->f->minVer, fobj->f->maxVer); + uint8_t mode = TSDB_SNAP_SYNC_FSET_LEVEL; + if (taosHashPut(pFidModeHash, &fid, sizeof(fid), &mode, sizeof(mode)) != 0) { + code = terrno; + goto _unlock; + } + goto _next_fset; } - goto _next_fset; } } + _next_fset:; } - _next_fset:; } +_unlock: (void)taosThreadMutexUnlock(&pTsdb->mutex); - *ppFidModeHash = pFidModeHash; - return 0; +_out: + if (pFollowerKeyHash) taosHashCleanup(pFollowerKeyHash); + if (pFollowerFidSet) taosHashCleanup(pFollowerFidSet); + if (pLeaderKeyHash) taosHashCleanup(pLeaderKeyHash); + + if (code != 0) { + taosHashCleanup(pFidModeHash); + *ppFidModeHash = NULL; + } else { + tsdbInfo("vgId:%d, Fid mode count %d", TD_VID(pTsdb->pVnode), taosHashGetSize(pFidModeHash)); + *ppFidModeHash = pFidModeHash; + } + return code; } static int32_t tsdbCollectAllFileInfo(SVnode* pVnode, STsdbSnapFileInfo** ppFiles, int32_t* pFileCount) { @@ -912,6 +963,8 @@ static int32_t tsdbCollectAllFileInfo(SVnode* pVnode, STsdbSnapFileInfo** ppFile files[fileCount].fid = fset->fid; files[fileCount].ftype = ftype; files[fileCount].level = 0; + files[fileCount].minVer = fset->farr[ftype]->f->minVer; + files[fileCount].maxVer = fset->farr[ftype]->f->maxVer; files[fileCount].cid = fset->farr[ftype]->f->cid; files[fileCount].size = fset->farr[ftype]->f->size; files[fileCount].isMissing = !taosCheckExistFile(fset->farr[ftype]->fname) ? 1 : 0; @@ -937,6 +990,8 @@ static int32_t tsdbCollectAllFileInfo(SVnode* pVnode, STsdbSnapFileInfo** ppFile files[fileCount].fid = fset->fid; files[fileCount].ftype = TSDB_FTYPE_STT; files[fileCount].level = lvl->level; + files[fileCount].minVer = fobj->f->minVer; + files[fileCount].maxVer = fobj->f->maxVer; files[fileCount].cid = fobj->f->cid; files[fileCount].size = fobj->f->size; files[fileCount].isMissing = !taosCheckExistFile(fobj->fname) ? 1 : 0; From cac2fa3531b5a4eda0c67670e2409ff71894358f Mon Sep 17 00:00:00 2001 From: chen dongming Date: Wed, 20 May 2026 10:37:20 +0800 Subject: [PATCH 08/12] feat: enhance missing file filtering with additional key parameters in RAW mode --- source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c | 22 ++++++++++--------- source/dnode/vnode/src/vnd/vnodeSnapshot.c | 7 +++--- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c b/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c index 7ffda6253ddc..09e4f48486ca 100644 --- a/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c +++ b/source/dnode/vnode/src/tsdb/tsdbSnapshotRAW.c @@ -47,7 +47,7 @@ typedef struct STsdbSnapRAWReader { SDataFileRAWReaderIter dataIter[1]; // missing file filter - SHashObj* missingFileHash; // key=(fid,ftype) — per-file filtering (not owned, do not free) + SHashObj* missingFileHash; // key=(fid,ftype,level,minVer,maxVer) — per-file filtering (not owned, do not free) SHashObj* fidModeHash; // key=fid, val=uint8_t mode (not owned, do not free) SHashObj* missingSttHash; // key=(fid,cid) — per-STT filtering (not owned, do not free) int32_t* missingFids; // FID set for FID-level pre-filtering (owned, copy) @@ -163,8 +163,9 @@ static int32_t tsdbSnapRAWReadFileSetOpenReader(STsdbSnapRAWReader* reader) { STFileObj* fobj = reader->ctx->fset->farr[ftype]; // per-file filter: skip files not in missing set (only when FILE_LEVEL mode) if (!fsetLevel && reader->missingFileHash != NULL) { - int64_t mfKey = tsdbMissingFileKey(reader->ctx->fset->fid, ftype); - if (taosHashGet(reader->missingFileHash, &mfKey, sizeof(mfKey)) == NULL) { + char key[TSDB_SNAP_FILE_KEY_LEN]; + tsdbSnapFileKeyMake(reader->ctx->fset->fid, ftype, 0, fobj->f->minVer, fobj->f->maxVer, key); + if (taosHashGet(reader->missingFileHash, key, sizeof(key)) == NULL) { tsdbDebug("vgId:%d, RAW skip file fid:%d ftype:%d not in missing set", TD_VID(reader->tsdb->pVnode), reader->ctx->fset->fid, ftype); continue; @@ -180,7 +181,7 @@ static int32_t tsdbSnapRAWReadFileSetOpenReader(STsdbSnapRAWReader* reader) { TSDB_CHECK_CODE(code, lino, _exit); code = TARRAY2_APPEND(reader->dataReaderArr, dataReader); - tsdbInfo("vgId:%d, RAW include file fid:%d ftype:%d in missing set", TD_VID(reader->tsdb->pVnode), + tsdbInfo("vgId:%d, RAW include file non-stt fid:%d ftype:%d in missing set", TD_VID(reader->tsdb->pVnode), reader->ctx->fset->fid, ftype); TSDB_CHECK_CODE(code, lino, _exit); } @@ -192,12 +193,12 @@ static int32_t tsdbSnapRAWReadFileSetOpenReader(STsdbSnapRAWReader* reader) { TARRAY2_FOREACH(lvl->fobjArr, fobj) { // per-file filter: skip stt files not in missing set (only when FILE_LEVEL mode) if (!fsetLevel && reader->missingSttHash != NULL) { - int64_t sttCid = fobj->f->cid; - char sttKey[TSDB_STT_HASH_KEY_LEN]; - tsdbSttHashKey(reader->ctx->fset->fid, sttCid, sttKey); + char sttKey[TSDB_SNAP_FILE_KEY_LEN]; + tsdbSnapFileKeyMake(reader->ctx->fset->fid, TSDB_FTYPE_STT, lvl->level, fobj->f->minVer, fobj->f->maxVer, + sttKey); if (taosHashGet(reader->missingSttHash, sttKey, sizeof(sttKey)) == NULL) { tsdbDebug("vgId:%d, RAW skip stt file fid:%d cid:%" PRId64 " not in missing set", - TD_VID(reader->tsdb->pVnode), reader->ctx->fset->fid, sttCid); + TD_VID(reader->tsdb->pVnode), reader->ctx->fset->fid, fobj->f->cid); continue; } } @@ -211,7 +212,7 @@ static int32_t tsdbSnapRAWReadFileSetOpenReader(STsdbSnapRAWReader* reader) { TSDB_CHECK_CODE(code, lino, _exit); code = TARRAY2_APPEND(reader->dataReaderArr, dataReader); - tsdbInfo("vgId:%d, RAW include stt file fid:%d in missing set", TD_VID(reader->tsdb->pVnode), + tsdbInfo("vgId:%d, RAW include file stt fid:%d in missing set", TD_VID(reader->tsdb->pVnode), reader->ctx->fset->fid); TSDB_CHECK_CODE(code, lino, _exit); } @@ -328,7 +329,8 @@ static int32_t tsdbSnapRAWReadBegin(STsdbSnapRAWReader* reader) { reader->ctx->fset = NULL; continue; } - tsdbInfo("vgId:%d, RAW include fid:%d in missing-fid set", TD_VID(reader->tsdb->pVnode), reader->ctx->fset->fid); + tsdbInfo("vgId:%d, RAW include fset fid:%d in missing-fid set", TD_VID(reader->tsdb->pVnode), + reader->ctx->fset->fid); reader->ctx->isDataDone = false; diff --git a/source/dnode/vnode/src/vnd/vnodeSnapshot.c b/source/dnode/vnode/src/vnd/vnodeSnapshot.c index 0c71904ac1fd..ebde4baaeba3 100644 --- a/source/dnode/vnode/src/vnd/vnodeSnapshot.c +++ b/source/dnode/vnode/src/vnd/vnodeSnapshot.c @@ -54,7 +54,7 @@ struct SVSnapReader { int8_t tsdbRAWDone; STsdbSnapRAWReader *pTsdbRAWReader; // missing file filter - SHashObj *missingFileHash; // key=(fid,ftype), val=dummy — for RAW mode per-file filtering + SHashObj *missingFileHash; // key=(fid,ftype,level,minVer,maxVer), val=dummy — for RAW mode per-file filtering SHashObj *fidModeHash; // key=fid, val=uint8_t mode (FILE_LEVEL or FSET_LEVEL) SHashObj *missingSttHash; // key=cid, val=dummy — for RAW mode per-STT filtering int32_t *missingFids; // FID set extracted from file names — for Normal mode FID filtering @@ -155,8 +155,9 @@ static int32_t vnodeSnapReaderDealWithSnapInfo(SVSnapReader *pReader, SSnapshotP vError("vgId:%d, failed to deserialize missing file list since %s", TD_VID(pVnode), tstrerror(code)); goto _out; } - vInfo("vgId:%d, received %d file infos from follower, missing:%d", TD_VID(pVnode), missingFileCount, - (pReader->missingFileHash ? (int32_t)taosHashGetSize(pReader->missingFileHash) : 0)); + vInfo("vgId:%d, received %d file infos from follower, missing file:%d, missing stt file:%d", TD_VID(pVnode), + missingFileCount, (pReader->missingFileHash ? (int32_t)taosHashGetSize(pReader->missingFileHash) : 0), + (pReader->missingSttHash ? (int32_t)taosHashGetSize(pReader->missingSttHash) : 0)); // determine sync mode per fid if (missingFiles && missingFileCount > 0) { code = tsdbDetermineFidSyncMode(pVnode->pTsdb, missingFiles, missingFileCount, &pReader->fidModeHash); From c84cadd4637ff5ad818138a0fe78a08de3d5eb95 Mon Sep 17 00:00:00 2001 From: chen dongming Date: Wed, 20 May 2026 17:43:01 +0800 Subject: [PATCH 09/12] feat: enhance logging in snapshot handling and file info collection --- source/dnode/vnode/src/inc/tsdb.h | 2 ++ source/dnode/vnode/src/tsdb/tsdbFS2.c | 8 ++++++++ source/dnode/vnode/src/tsdb/tsdbSnapInfo.c | 13 +++++++++---- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/source/dnode/vnode/src/inc/tsdb.h b/source/dnode/vnode/src/inc/tsdb.h index 2c39b2152d41..d2945797da22 100644 --- a/source/dnode/vnode/src/inc/tsdb.h +++ b/source/dnode/vnode/src/inc/tsdb.h @@ -34,6 +34,8 @@ extern "C" { #define tsdbInfo(...) do { if (tsdbDebugFlag & DEBUG_INFO) { taosPrintLog("TSD INFO ", DEBUG_INFO, 255, __VA_ARGS__); }} while(0) #define tsdbDebug(...) do { if (tsdbDebugFlag & DEBUG_DEBUG) { taosPrintLog("TSD DEBUG ", DEBUG_DEBUG, tsdbDebugFlag, __VA_ARGS__); }} while(0) #define tsdbTrace(...) do { if (tsdbDebugFlag & DEBUG_TRACE) { taosPrintLog("TSD TRACE ", DEBUG_TRACE, tsdbDebugFlag, __VA_ARGS__); }} while(0) + +#define tsdbInfoL(...) { if (tsdbDebugFlag & DEBUG_INFO) { taosPrintLongString("TSD INFO ", DEBUG_INFO, tsLogEmbedded ? 255 : tsdbDebugFlag, __VA_ARGS__); }} // clang-format on typedef struct TSDBROW TSDBROW; diff --git a/source/dnode/vnode/src/tsdb/tsdbFS2.c b/source/dnode/vnode/src/tsdb/tsdbFS2.c index ff1da0bb61eb..54174bdb0b2e 100644 --- a/source/dnode/vnode/src/tsdb/tsdbFS2.c +++ b/source/dnode/vnode/src/tsdb/tsdbFS2.c @@ -622,6 +622,14 @@ static int32_t open_fs(STFileSystem *fs, int8_t rollback) { current_fname(pTsdb, mCurrent, TSDB_FCURRENT_M); if (taosCheckExistFile(fCurrent)) { // current.json exists + { + char *pData = NULL; + int32_t dataLen = 0; + if (taosReadCfgFile(fCurrent, &pData, &dataLen) == 0 && pData != NULL) { + tsdbInfoL("vgId:%d, open_fs read %s content: %s", TD_VID(pTsdb->pVnode), fCurrent, pData); + taosMemoryFree(pData); + } + } code = load_fs(pTsdb, fCurrent, fs->fSetArr); TSDB_CHECK_CODE(code, lino, _exit); diff --git a/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c b/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c index 012d8058900f..53a9f7061bf3 100644 --- a/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c +++ b/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c @@ -635,10 +635,10 @@ int32_t tDeserializeMissingFileList(void* buf, int32_t bufLen, void** ppFiles, i if ((code = tDecodeI64(&decoder, &files[i].size))) goto _err; if ((code = tDecodeI8(&decoder, &files[i].isMissing))) goto _err; - tsdbDebug("FileInfo fid:%d ftype:%d level:%d minVer:%" PRId64 " maxVer:%" PRId64 " cid:%" PRId64 " size:%" PRId64 - " isMissing:%d", - files[i].fid, files[i].ftype, files[i].level, files[i].minVer, files[i].maxVer, files[i].cid, - files[i].size, files[i].isMissing); + tsdbInfo("FileInfo fid:%d ftype:%d level:%d minVer:%" PRId64 " maxVer:%" PRId64 " cid:%" PRId64 " size:%" PRId64 + " isMissing:%d", + files[i].fid, files[i].ftype, files[i].level, files[i].minVer, files[i].maxVer, files[i].cid, + files[i].size, files[i].isMissing); if (files[i].isMissing) { char dummy = 0; @@ -968,6 +968,11 @@ static int32_t tsdbCollectAllFileInfo(SVnode* pVnode, STsdbSnapFileInfo** ppFile files[fileCount].cid = fset->farr[ftype]->f->cid; files[fileCount].size = fset->farr[ftype]->f->size; files[fileCount].isMissing = !taosCheckExistFile(fset->farr[ftype]->fname) ? 1 : 0; + tsdbInfo("vgId:%d, collect all file info, fid:%d ftype:%d level:%d minVer:%" PRId64 " maxVer:%" PRId64 + " cid:%" PRId64 " size:%" PRId64 " isMissing:%d", + TD_VID(pVnode), files[fileCount].fid, files[fileCount].ftype, files[fileCount].level, + files[fileCount].minVer, files[fileCount].maxVer, files[fileCount].cid, files[fileCount].size, + files[fileCount].isMissing); fileCount++; } } From fca01fb54556f0a7fae81adf1c70f1324f3d3c1d Mon Sep 17 00:00:00 2001 From: chen dongming Date: Wed, 20 May 2026 17:56:04 +0800 Subject: [PATCH 10/12] feat: enhance file info collection logging in tsdbCollectAllFileInfo --- source/dnode/vnode/src/tsdb/tsdbSnapInfo.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c b/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c index 53a9f7061bf3..57f6a5d33fa4 100644 --- a/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c +++ b/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c @@ -1000,6 +1000,11 @@ static int32_t tsdbCollectAllFileInfo(SVnode* pVnode, STsdbSnapFileInfo** ppFile files[fileCount].cid = fobj->f->cid; files[fileCount].size = fobj->f->size; files[fileCount].isMissing = !taosCheckExistFile(fobj->fname) ? 1 : 0; + tsdbInfo("vgId:%d, collect all file info, fid:%d ftype:%d level:%d minVer:%" PRId64 " maxVer:%" PRId64 + " cid:%" PRId64 " size:%" PRId64 " isMissing:%d", + TD_VID(pVnode), files[fileCount].fid, files[fileCount].ftype, files[fileCount].level, + files[fileCount].minVer, files[fileCount].maxVer, files[fileCount].cid, files[fileCount].size, + files[fileCount].isMissing); fileCount++; } } From 70a5c34f6ce6010d6ef1cba91a8b0c311f4637a2 Mon Sep 17 00:00:00 2001 From: chen dongming Date: Wed, 20 May 2026 18:40:12 +0800 Subject: [PATCH 11/12] feat: add vgId parameter to missing file list deserialization functions --- source/dnode/vnode/src/inc/tsdb.h | 2 +- source/dnode/vnode/src/tsdb/tsdbSnapInfo.c | 16 ++++++++++++---- source/dnode/vnode/src/vnd/vnodeSnapshot.c | 2 +- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/source/dnode/vnode/src/inc/tsdb.h b/source/dnode/vnode/src/inc/tsdb.h index d2945797da22..6cb155a0ccfa 100644 --- a/source/dnode/vnode/src/inc/tsdb.h +++ b/source/dnode/vnode/src/inc/tsdb.h @@ -731,7 +731,7 @@ int32_t tDeserializeTsdbRepOpts(void *buf, int32_t bufLen, STsdbRepOpts *pInfo); int32_t tMissingFileListDataLenCalc(int32_t fileCount); int32_t tDeserializeMissingFileList(void *buf, int32_t bufLen, void **ppFiles, int32_t *pFileCount, SHashObj **ppHash, - SHashObj **ppSttHash); + SHashObj **ppSttHash, int32_t vgId); int32_t tsdbExtractMissingFids(STsdb *pTsdb, SHashObj *missingFileHash, int32_t **ppFids, int32_t *pFidCount); int32_t tsdbDetermineFidSyncMode(STsdb *pTsdb, const void *files, int32_t fileCount, SHashObj **ppFidModeHash); diff --git a/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c b/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c index 57f6a5d33fa4..dc495de330fb 100644 --- a/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c +++ b/source/dnode/vnode/src/tsdb/tsdbSnapInfo.c @@ -587,7 +587,7 @@ int32_t tSerializeMissingFileList(void* buf, int32_t bufLen, const STsdbSnapFile } int32_t tDeserializeMissingFileList(void* buf, int32_t bufLen, void** ppFiles, int32_t* pFileCount, SHashObj** ppHash, - SHashObj** ppSttHash) { + SHashObj** ppSttHash, int32_t vgId) { int32_t code = 0; SDecoder decoder = {0}; int8_t msgVer = 0; @@ -635,9 +635,9 @@ int32_t tDeserializeMissingFileList(void* buf, int32_t bufLen, void** ppFiles, i if ((code = tDecodeI64(&decoder, &files[i].size))) goto _err; if ((code = tDecodeI8(&decoder, &files[i].isMissing))) goto _err; - tsdbInfo("FileInfo fid:%d ftype:%d level:%d minVer:%" PRId64 " maxVer:%" PRId64 " cid:%" PRId64 " size:%" PRId64 - " isMissing:%d", - files[i].fid, files[i].ftype, files[i].level, files[i].minVer, files[i].maxVer, files[i].cid, + tsdbInfo("vgId:%d, FileInfo fid:%d ftype:%d level:%d minVer:%" PRId64 " maxVer:%" PRId64 " cid:%" PRId64 + " size:%" PRId64 " isMissing:%d", + vgId, files[i].fid, files[i].ftype, files[i].level, files[i].minVer, files[i].maxVer, files[i].cid, files[i].size, files[i].isMissing); if (files[i].isMissing) { @@ -775,6 +775,10 @@ int32_t tsdbDetermineFidSyncMode(STsdb* pTsdb, const void* pFileArr, int32_t fil char key[TSDB_SNAP_FILE_KEY_LEN]; tsdbSnapFileKeyMake(fset->fid, ftype, 0, fset->farr[ftype]->f->minVer, fset->farr[ftype]->f->maxVer, key); SLeaderFileVal val = {.cid = fset->farr[ftype]->f->cid, .size = fset->farr[ftype]->f->size}; + tsdbInfo("vgId:%d, leader FileInfo fid:%d ftype:%d level:%d minVer:%" PRId64 " maxVer:%" PRId64 + " cid:%" PRId64 " size:%" PRId64, + TD_VID(pTsdb->pVnode), fset->fid, ftype, 0, fset->farr[ftype]->f->minVer, + fset->farr[ftype]->f->maxVer, fset->farr[ftype]->f->cid, fset->farr[ftype]->f->size); if (taosHashPut(pLeaderKeyHash, key, TSDB_SNAP_FILE_KEY_LEN, &val, sizeof(val)) != 0) { code = terrno; goto _unlock; @@ -788,6 +792,10 @@ int32_t tsdbDetermineFidSyncMode(STsdb* pTsdb, const void* pFileArr, int32_t fil char key[TSDB_SNAP_FILE_KEY_LEN]; tsdbSnapFileKeyMake(fset->fid, TSDB_FTYPE_STT, lvl->level, fobj->f->minVer, fobj->f->maxVer, key); SLeaderFileVal val = {.cid = fobj->f->cid, .size = fobj->f->size}; + tsdbInfo("vgId:%d, leader FileInfo fid:%d ftype:%d level:%d minVer:%" PRId64 " maxVer:%" PRId64 + " cid:%" PRId64 " size:%" PRId64, + TD_VID(pTsdb->pVnode), fset->fid, TSDB_FTYPE_STT, lvl->level, fobj->f->minVer, fobj->f->maxVer, + fobj->f->cid, fobj->f->size); if (taosHashPut(pLeaderKeyHash, key, TSDB_SNAP_FILE_KEY_LEN, &val, sizeof(val)) != 0) { code = terrno; goto _unlock; diff --git a/source/dnode/vnode/src/vnd/vnodeSnapshot.c b/source/dnode/vnode/src/vnd/vnodeSnapshot.c index ebde4baaeba3..0d7646a1d380 100644 --- a/source/dnode/vnode/src/vnd/vnodeSnapshot.c +++ b/source/dnode/vnode/src/vnd/vnodeSnapshot.c @@ -150,7 +150,7 @@ static int32_t vnodeSnapReaderDealWithSnapInfo(SVSnapReader *pReader, SSnapshotP void *missingFiles = NULL; int32_t missingFileCount = 0; code = tDeserializeMissingFileList(buf, bufLen, &missingFiles, &missingFileCount, &pReader->missingFileHash, - &pReader->missingSttHash); + &pReader->missingSttHash, TD_VID(pVnode)); if (code) { vError("vgId:%d, failed to deserialize missing file list since %s", TD_VID(pVnode), tstrerror(code)); goto _out; From e5a596bcae62911eca434311fc569fd142615beb Mon Sep 17 00:00:00 2001 From: chen dongming Date: Wed, 20 May 2026 18:52:39 +0800 Subject: [PATCH 12/12] feat: enhance logging in load_fs and open_fs functions --- source/dnode/vnode/src/tsdb/tsdbFS2.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/source/dnode/vnode/src/tsdb/tsdbFS2.c b/source/dnode/vnode/src/tsdb/tsdbFS2.c index 54174bdb0b2e..35726be9ab2c 100644 --- a/source/dnode/vnode/src/tsdb/tsdbFS2.c +++ b/source/dnode/vnode/src/tsdb/tsdbFS2.c @@ -205,6 +205,12 @@ static int32_t load_fs(STsdb *pTsdb, const char *fname, TFileSetArray *arr) { code = load_json(fname, &json); TSDB_CHECK_CODE(code, lino, _exit); + char *jsonStr = cJSON_Print(json); + if (jsonStr != NULL) { + tsdbInfoL("vgId:%d, load_fs file:%s content:%s", TD_VID(pTsdb->pVnode), fname, jsonStr); + taosMemoryFree(jsonStr); + } + // parse json const cJSON *item1; @@ -622,14 +628,6 @@ static int32_t open_fs(STFileSystem *fs, int8_t rollback) { current_fname(pTsdb, mCurrent, TSDB_FCURRENT_M); if (taosCheckExistFile(fCurrent)) { // current.json exists - { - char *pData = NULL; - int32_t dataLen = 0; - if (taosReadCfgFile(fCurrent, &pData, &dataLen) == 0 && pData != NULL) { - tsdbInfoL("vgId:%d, open_fs read %s content: %s", TD_VID(pTsdb->pVnode), fCurrent, pData); - taosMemoryFree(pData); - } - } code = load_fs(pTsdb, fCurrent, fs->fSetArr); TSDB_CHECK_CODE(code, lino, _exit);