• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

taosdata / TDengine / #4975

05 Mar 2026 08:43AM UTC coverage: 68.37% (+0.7%) from 67.664%
#4975

push

travis-ci

web-flow
merge: from main to 3.0 branch #34682

250 of 345 new or added lines in 28 files covered. (72.46%)

446 existing lines in 120 files now uncovered.

210600 of 308032 relevant lines covered (68.37%)

130326818.69 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.97
/source/dnode/vnode/src/meta/metaSnapshot.c
1
/*
2
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
3
 *
4
 * This program is free software: you can use, redistribute, and/or modify
5
 * it under the terms of the GNU Affero General Public License, version 3
6
 * or later ("AGPL"), as published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
 * FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * You should have received a copy of the GNU Affero General Public License
13
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14
 */
15

16
#include "meta.h"
17

18
// SMetaSnapReader ========================================
19
struct SMetaSnapReader {
20
  SMeta*  pMeta;
21
  int64_t sver;
22
  int64_t ever;
23
  TBC*    pTbc;
24
  int32_t iLoop;
25
};
26

27
int32_t metaSnapReaderOpen(SMeta* pMeta, int64_t sver, int64_t ever, SMetaSnapReader** ppReader) {
30,541✔
28
  int32_t          code = 0;
30,541✔
29
  int32_t          lino;
30
  int32_t          c = 0;
30,541✔
31
  SMetaSnapReader* pReader = NULL;
30,541✔
32

33
  // alloc
34
  pReader = (SMetaSnapReader*)taosMemoryCalloc(1, sizeof(*pReader));
30,541✔
35
  if (pReader == NULL) {
30,541✔
36
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
37
  }
38
  pReader->pMeta = pMeta;
30,541✔
39
  pReader->sver = sver;
30,541✔
40
  pReader->ever = ever;
30,541✔
41

42
  // impl
43
  code = tdbTbcOpen(pMeta->pTbDb, &pReader->pTbc, NULL);
30,541✔
44
  TSDB_CHECK_CODE(code, lino, _exit);
30,541✔
45

46
  code = tdbTbcMoveTo(pReader->pTbc, &(STbDbKey){.version = sver, .uid = INT64_MIN}, sizeof(STbDbKey), &c);
30,541✔
47
  TSDB_CHECK_CODE(code, lino, _exit);
30,541✔
48

49
_exit:
30,541✔
50
  if (code) {
30,541✔
51
    metaError("vgId:%d, %s failed at %s:%d since %s", TD_VID(pMeta->pVnode), __func__, __FILE__, lino, tstrerror(code));
×
52
    metaSnapReaderClose(&pReader);
×
53
    *ppReader = NULL;
×
54
  } else {
55
    metaInfo("vgId:%d, %s success", TD_VID(pMeta->pVnode), __func__);
30,541✔
56
    *ppReader = pReader;
30,541✔
57
  }
58
  return code;
30,541✔
59
}
60

61
void metaSnapReaderClose(SMetaSnapReader** ppReader) {
30,541✔
62
  if (ppReader && *ppReader) {
30,541✔
63
    tdbTbcClose((*ppReader)->pTbc);
30,541✔
64
    taosMemoryFree(*ppReader);
30,541✔
65
    *ppReader = NULL;
30,541✔
66
  }
67
}
30,541✔
68

69
extern int metaDecodeEntryImpl(SDecoder* pCoder, SMetaEntry* pME, bool headerOnly);
70

71
static int32_t metaDecodeEntryHeader(void* data, int32_t size, SMetaEntry* entry) {
377,648✔
72
  SDecoder decoder = {0};
377,648✔
73
  tDecoderInit(&decoder, (uint8_t*)data, size);
377,648✔
74

75
  int32_t code = metaDecodeEntryImpl(&decoder, entry, true);
377,648✔
76
  if (code) {
377,648✔
77
    tDecoderClear(&decoder);
×
78
    return code;
×
79
  }
80

81
  tDecoderClear(&decoder);
377,648✔
82
  return 0;
377,648✔
83
}
84

85
int32_t metaSnapRead(SMetaSnapReader* pReader, uint8_t** ppData) {
218,375✔
86
  int32_t     code = 0;
218,375✔
87
  const void* pKey = NULL;
218,375✔
88
  const void* pData = NULL;
218,375✔
89
  int32_t     nKey = 0;
218,375✔
90
  int32_t     nData = 0;
218,375✔
91
  STbDbKey    key;
92
  int32_t     c;
218,375✔
93

94
  *ppData = NULL;
218,375✔
95
  while (pReader->iLoop < 2) {
469,271✔
96
    if (tdbTbcGet(pReader->pTbc, &pKey, &nKey, &pData, &nData) != 0 || ((STbDbKey*)pKey)->version > pReader->ever) {
438,730✔
97
      pReader->iLoop++;
61,082✔
98

99
      // Reopen the cursor to read from the beginning
100
      tdbTbcClose(pReader->pTbc);
61,082✔
101
      pReader->pTbc = NULL;
61,082✔
102
      code = tdbTbcOpen(pReader->pMeta->pTbDb, &pReader->pTbc, NULL);
61,082✔
103
      if (code) {
61,082✔
104
        metaError("vgId:%d, %s failed at %s:%d since %s", TD_VID(pReader->pMeta->pVnode), __func__, __FILE__, __LINE__,
×
105
                  tstrerror(code));
106
        goto _exit;
×
107
      }
108

109
      code = tdbTbcMoveTo(pReader->pTbc, &(STbDbKey){.version = pReader->sver, .uid = INT64_MIN}, sizeof(STbDbKey), &c);
61,082✔
110
      if (code) {
61,082✔
111
        metaError("vgId:%d, %s failed at %s:%d since %s", TD_VID(pReader->pMeta->pVnode), __func__, __FILE__, __LINE__,
×
112
                  tstrerror(code));
113
        goto _exit;
×
114
      }
115

116
      continue;
61,082✔
117
    }
118

119
    // Decode meta entry
120
    SMetaEntry entry = {0};
377,648✔
121
    code = metaDecodeEntryHeader((void*)pData, nData, &entry);
377,648✔
122
    if (code) {
377,648✔
123
      metaError("vgId:%d, %s failed at %s:%d since %s", TD_VID(pReader->pMeta->pVnode), __func__, __FILE__, __LINE__,
×
124
                tstrerror(code));
125
      goto _exit;
×
126
    }
127

128
    key = ((STbDbKey*)pKey)[0];
377,648✔
129
    if (key.version < pReader->sver                                       //
377,648✔
130
        || (pReader->iLoop == 0 && TABS(entry.type) != TSDB_SUPER_TABLE)  // First loop send super table entry
375,668✔
131
        || (pReader->iLoop == 1 && TABS(entry.type) == TSDB_SUPER_TABLE)  // Second loop send non-super table entry
214,281✔
132
    ) {
133
      if (tdbTbcMoveToNext(pReader->pTbc) != 0) {
189,814✔
134
        metaTrace("vgId:%d, vnode snapshot meta read data done", TD_VID(pReader->pMeta->pVnode));
×
135
      }
136
      continue;
189,814✔
137
    }
138

139
    if (!pData || !nData) {
187,834✔
140
      metaError("meta/snap: invalide nData: %" PRId32 " meta snap read failed.", nData);
×
141
      goto _exit;
×
142
    }
143

144
    *ppData = taosMemoryMalloc(sizeof(SSnapDataHdr) + nData);
187,834✔
145
    if (*ppData == NULL) {
187,834✔
146
      code = terrno;
×
147
      goto _exit;
×
148
    }
149

150
    SSnapDataHdr* pHdr = (SSnapDataHdr*)(*ppData);
187,834✔
151
    pHdr->type = SNAP_DATA_META;
187,834✔
152
    pHdr->size = nData;
187,834✔
153
    memcpy(pHdr->data, pData, nData);
187,834✔
154

155
    metaDebug("vgId:%d, vnode snapshot meta read data, version:%" PRId64 " uid:%" PRId64 " blockLen:%d",
187,834✔
156
              TD_VID(pReader->pMeta->pVnode), key.version, key.uid, nData);
157

158
    if (tdbTbcMoveToNext(pReader->pTbc) != 0) {
187,834✔
159
      metaTrace("vgId:%d, vnode snapshot meta read data done", TD_VID(pReader->pMeta->pVnode));
×
160
    }
161
    break;
187,834✔
162
  }
163

164
_exit:
218,375✔
165
  if (code) {
218,375✔
166
    metaError("vgId:%d, vnode snapshot meta read data failed since %s", TD_VID(pReader->pMeta->pVnode),
×
167
              tstrerror(code));
168
  }
169
  return code;
218,375✔
170
}
171

172
// SMetaSnapWriter ========================================
173
struct SMetaSnapWriter {
174
  SMeta*  pMeta;
175
  int64_t sver;
176
  int64_t ever;
177
};
178

179
int32_t metaSnapWriterOpen(SMeta* pMeta, int64_t sver, int64_t ever, SMetaSnapWriter** ppWriter) {
26,363✔
180
  int32_t          code = 0;
26,363✔
181
  int32_t          lino;
182
  SMetaSnapWriter* pWriter;
183

184
  // alloc
185
  pWriter = (SMetaSnapWriter*)taosMemoryCalloc(1, sizeof(*pWriter));
26,363✔
186
  if (pWriter == NULL) {
26,363✔
187
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
188
  }
189
  pWriter->pMeta = pMeta;
26,363✔
190
  pWriter->sver = sver;
26,363✔
191
  pWriter->ever = ever;
26,363✔
192

193
  code = metaBegin(pMeta, META_BEGIN_HEAP_NIL);
26,363✔
194
  TSDB_CHECK_CODE(code, lino, _exit);
26,363✔
195

196
_exit:
26,363✔
197
  if (code) {
26,363✔
198
    metaError("vgId:%d, %s failed at %s:%d since %s", TD_VID(pMeta->pVnode), __func__, __FILE__, lino, tstrerror(code));
×
199
    taosMemoryFree(pWriter);
×
200
    *ppWriter = NULL;
×
201
  } else {
202
    metaDebug("vgId:%d, %s success", TD_VID(pMeta->pVnode), __func__);
26,363✔
203
    *ppWriter = pWriter;
26,363✔
204
  }
205
  return code;
26,363✔
206
}
207

208
int32_t metaSnapWriterClose(SMetaSnapWriter** ppWriter, int8_t rollback) {
26,363✔
209
  int32_t          code = 0;
26,363✔
210
  SMetaSnapWriter* pWriter = *ppWriter;
26,363✔
211

212
  if (rollback) {
26,363✔
UNCOV
213
    metaInfo("vgId:%d, meta snapshot writer close and rollback start ", TD_VID(pWriter->pMeta->pVnode));
×
UNCOV
214
    code = metaAbort(pWriter->pMeta);
×
UNCOV
215
    metaInfo("vgId:%d, meta snapshot writer close and rollback finished, code:0x%x", TD_VID(pWriter->pMeta->pVnode),
×
216
             code);
UNCOV
217
    if (code) goto _err;
×
218
  } else {
219
    code = metaCommit(pWriter->pMeta, pWriter->pMeta->txn);
26,363✔
220
    if (code) goto _err;
26,363✔
221
    code = metaFinishCommit(pWriter->pMeta, pWriter->pMeta->txn);
26,363✔
222
    if (code) goto _err;
26,363✔
223
  }
224
  taosMemoryFree(pWriter);
26,363✔
225
  *ppWriter = NULL;
26,363✔
226

227
  return code;
26,363✔
228

229
_err:
×
230
  metaError("vgId:%d, meta snapshot writer close failed since %s", TD_VID(pWriter->pMeta->pVnode), tstrerror(code));
×
231
  return code;
×
232
}
233

234
int32_t metaSnapWrite(SMetaSnapWriter* pWriter, uint8_t* pData, uint32_t nData) {
187,708✔
235
  int32_t    code = 0;
187,708✔
236
  int32_t    lino = 0;
187,708✔
237
  SMeta*     pMeta = pWriter->pMeta;
187,708✔
238
  SMetaEntry metaEntry = {0};
187,708✔
239
  SDecoder*  pDecoder = &(SDecoder){0};
187,708✔
240

241
  tDecoderInit(pDecoder, pData + sizeof(SSnapDataHdr), nData - sizeof(SSnapDataHdr));
187,708✔
242
  code = metaDecodeEntry(pDecoder, &metaEntry);
187,708✔
243
  TSDB_CHECK_CODE(code, lino, _exit);
187,708✔
244

245
  metaHandleSyncEntry(pMeta, &metaEntry);
187,708✔
246

247
_exit:
187,708✔
248
  if (code) {
187,708✔
249
    metaError("vgId:%d, %s failed at %s:%d since %s", TD_VID(pMeta->pVnode), __func__, __FILE__, lino, tstrerror(code));
×
250
  }
251
  tDecoderClear(pDecoder);
187,708✔
252
  return code;
187,708✔
253
}
254

255
typedef struct STableInfoForChildTable {
256
  char*           tableName;
257
  SSchemaWrapper* schemaRow;
258
  SSchemaWrapper* tagRow;
259
  SExtSchema*     pExtSchemas;
260
} STableInfoForChildTable;
261

262
static void destroySTableInfoForChildTable(void* data) {
181,046✔
263
  STableInfoForChildTable* pData = (STableInfoForChildTable*)data;
181,046✔
264
  taosMemoryFree(pData->tableName);
181,046✔
265
  tDeleteSchemaWrapper(pData->schemaRow);
181,046✔
266
  tDeleteSchemaWrapper(pData->tagRow);
181,046✔
267
  taosMemoryFreeClear(pData->pExtSchemas);
180,694✔
268
}
180,694✔
269

270
static int32_t MoveToSnapShotVersion(SSnapContext* ctx) {
125,808✔
271
  int32_t code = 0;
125,808✔
272
  tdbTbcClose((TBC*)ctx->pCur);
125,808✔
273
  code = tdbTbcOpen(ctx->pMeta->pTbDb, (TBC**)&ctx->pCur, NULL);
125,808✔
274
  if (code != 0) {
125,808✔
275
    return TAOS_GET_TERRNO(code);
×
276
  }
277
  STbDbKey key = {.version = ctx->snapVersion, .uid = INT64_MAX};
125,808✔
278
  int      c = 0;
125,808✔
279
  code = tdbTbcMoveTo((TBC*)ctx->pCur, &key, sizeof(key), &c);
125,808✔
280
  if (code != 0) {
125,808✔
281
    return TAOS_GET_TERRNO(code);
×
282
  }
283
  if (c < 0) {
125,808✔
284
    if (tdbTbcMoveToPrev((TBC*)ctx->pCur) != 0) {
4,091✔
285
      metaTrace("vgId:%d, vnode snapshot move to prev failed", TD_VID(ctx->pMeta->pVnode));
×
286
    }
287
  }
288
  return 0;
125,808✔
289
}
290

291
static int32_t MoveToPosition(SSnapContext* ctx, int64_t ver, int64_t uid) {
1,631,198✔
292
  tdbTbcClose((TBC*)ctx->pCur);
1,631,198✔
293
  int32_t code = tdbTbcOpen(ctx->pMeta->pTbDb, (TBC**)&ctx->pCur, NULL);
1,630,882✔
294
  if (code != 0) {
1,630,562✔
295
    return TAOS_GET_TERRNO(code);
×
296
  }
297
  STbDbKey key = {.version = ver, .uid = uid};
1,630,562✔
298
  int      c = 0;
1,630,882✔
299
  code = tdbTbcMoveTo((TBC*)ctx->pCur, &key, sizeof(key), &c);
1,630,882✔
300
  if (code != 0) {
1,630,882✔
301
    return TAOS_GET_TERRNO(code);
×
302
  }
303
  return c;
1,630,882✔
304
}
305

306
static int32_t MoveToFirst(SSnapContext* ctx) {
125,808✔
307
  tdbTbcClose((TBC*)ctx->pCur);
125,808✔
308
  int32_t code = tdbTbcOpen(ctx->pMeta->pTbDb, (TBC**)&ctx->pCur, NULL);
125,808✔
309
  if (code != 0) {
125,808✔
310
    return TAOS_GET_TERRNO(code);
×
311
  }
312
  code = tdbTbcMoveToFirst((TBC*)ctx->pCur);
125,808✔
313
  if (code != 0) {
125,808✔
314
    return TAOS_GET_TERRNO(code);
×
315
  }
316
  return 0;
125,808✔
317
}
318

319
static int32_t saveSuperTableInfoForChildTable(SMetaEntry* me, SHashObj* suidInfo) {
181,046✔
320
  STableInfoForChildTable* data = (STableInfoForChildTable*)taosHashGet(suidInfo, &me->uid, sizeof(tb_uid_t));
181,046✔
321
  if (data) {
181,046✔
322
    return 0;
×
323
  }
324
  int32_t                 code = 0;
181,046✔
325
  STableInfoForChildTable dataTmp = {0};
181,046✔
326
  dataTmp.tableName = taosStrdup(me->name);
181,046✔
327
  if (dataTmp.tableName == NULL) {
181,046✔
328
    code = terrno;
×
329
    goto END;
×
330
  }
331
  dataTmp.schemaRow = tCloneSSchemaWrapper(&me->stbEntry.schemaRow);
181,046✔
332
  if (dataTmp.schemaRow == NULL) {
181,046✔
333
    code = TSDB_CODE_OUT_OF_MEMORY;
×
334
    goto END;
×
335
  }
336
  dataTmp.tagRow = tCloneSSchemaWrapper(&me->stbEntry.schemaTag);
181,046✔
337
  if (dataTmp.tagRow == NULL) {
181,046✔
338
    code = TSDB_CODE_OUT_OF_MEMORY;
×
339
    goto END;
×
340
  }
341
  if (me->pExtSchemas != NULL) {
181,046✔
342
    dataTmp.pExtSchemas = taosMemoryMalloc(sizeof(SExtSchema) * me->stbEntry.schemaRow.nCols);
8,090✔
343
    if (dataTmp.pExtSchemas == NULL) {
8,090✔
344
      code = TSDB_CODE_OUT_OF_MEMORY;
×
345
      goto END;
×
346
    }
347
    memcpy(dataTmp.pExtSchemas, me->pExtSchemas, sizeof(SExtSchema) * me->stbEntry.schemaRow.nCols);
8,090✔
348
  }
349
  
350
  code = taosHashPut(suidInfo, &me->uid, sizeof(tb_uid_t), &dataTmp, sizeof(STableInfoForChildTable));
181,046✔
351
  if (code != 0) {
181,046✔
352
    goto END;
×
353
  }
354
  return 0;
181,046✔
355

356
END:
×
357
  destroySTableInfoForChildTable(&dataTmp);
×
358
  return TAOS_GET_TERRNO(code);
×
359
}
360

361
int32_t buildSnapContext(SVnode* pVnode, int64_t snapVersion, int64_t suid, int8_t subType, int8_t withMeta,
125,808✔
362
                         SSnapContext** ctxRet) {
363
  int32_t code = 0;
125,808✔
364
  int32_t lino = 0;
125,808✔
365
  SDecoder   dc = {0};
125,808✔
366
  void* pKey = NULL;
125,808✔
367
  void* pVal = NULL;
125,808✔
368
  int   vLen = 0, kLen = 0;
125,808✔
369

370
  metaRLock(pVnode->pMeta);
125,808✔
371
  SSnapContext* ctx = taosMemoryCalloc(1, sizeof(SSnapContext));
125,808✔
372
  TSDB_CHECK_NULL(ctx, code, lino, END, terrno);
125,808✔
373
  *ctxRet = ctx;
125,808✔
374
  ctx->pMeta = pVnode->pMeta;
125,808✔
375
  ctx->snapVersion = snapVersion;
125,808✔
376
  ctx->suid = suid;
125,808✔
377
  ctx->subType = subType;
125,808✔
378
  ctx->queryMeta = withMeta;
125,808✔
379
  ctx->withMeta = withMeta;
125,808✔
380
  ctx->idVersion = taosHashInit(100, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK);
125,808✔
381
  TSDB_CHECK_NULL(ctx->idVersion, code, lino, END, terrno);
125,808✔
382
  ctx->suidInfo = taosHashInit(100, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK);
125,808✔
383
  TSDB_CHECK_NULL(ctx->suidInfo, code, lino, END, terrno);
125,808✔
384
  taosHashSetFreeFp(ctx->suidInfo, destroySTableInfoForChildTable);
125,808✔
385

386
  ctx->index = 0;
125,808✔
387
  ctx->idList = taosArrayInit(100, sizeof(int64_t));
125,808✔
388
  TSDB_CHECK_NULL(ctx->idList, code, lino, END, terrno);
125,808✔
389

390
  metaDebug("tmqsnap init snapVersion:%" PRIi64, ctx->snapVersion);
125,808✔
391
  code = MoveToFirst(ctx);
125,808✔
392
  TSDB_CHECK_CODE(code, lino, END);
125,808✔
393
  while (1) {
12,349,107✔
394
    int32_t ret = tdbTbcNext((TBC*)ctx->pCur, &pKey, &kLen, &pVal, &vLen);
12,474,915✔
395
    if (ret < 0) break;
12,469,731✔
396
    STbDbKey* tmp = (STbDbKey*)pKey;
12,348,661✔
397
    if (tmp->version > ctx->snapVersion) break;
12,348,661✔
398

399
    SIdInfo* idData = (SIdInfo*)taosHashGet(ctx->idVersion, &tmp->uid, sizeof(tb_uid_t));
12,351,007✔
400
    if (idData) {
12,350,369✔
401
      continue;
87,741✔
402
    }
403

404
    // check if table exist for now, need optimize later
405
    if (tdbTbGet(ctx->pMeta->pUidIdx, &tmp->uid, sizeof(tb_uid_t), NULL, NULL) < 0) {
12,262,628✔
406
      continue;
93,650✔
407
    }
408

409
    SMetaEntry me = {0};
12,168,968✔
410
    tDecoderInit(&dc, pVal, vLen);
12,169,296✔
411
    code = metaDecodeEntry(&dc, &me);
12,170,876✔
412
    TSDB_CHECK_CODE(code, lino, END);
12,167,418✔
413
    if (ctx->subType == TOPIC_SUB_TYPE__TABLE) {
12,167,418✔
414
      if (!((me.uid == ctx->suid && me.type == TSDB_SUPER_TABLE) ||
203,874✔
415
          (me.ctbEntry.suid == ctx->suid && (me.type == TSDB_CHILD_TABLE)))) {
181,761✔
416
        tDecoderClear(&dc);
2,842✔
417
        continue;
2,842✔
418
      }
419
    } else if (ctx->subType == TOPIC_SUB_TYPE__DB) {
11,961,944✔
420
      if (me.type == TSDB_VIRTUAL_NORMAL_TABLE ||
11,964,154✔
421
          me.type == TSDB_VIRTUAL_CHILD_TABLE ||
11,962,204✔
422
          TABLE_IS_VIRTUAL(me.flags)) {
11,963,824✔
423
        tDecoderClear(&dc);
330✔
424
        continue;
×
425
      }
426
    }
427

428
    TSDB_CHECK_NULL(taosArrayPush(ctx->idList, &tmp->uid), code, lino, END, terrno);
24,326,876✔
429
    metaDebug("tmqsnap init idlist name:%s, uid:%" PRIi64, me.name, tmp->uid);
12,162,342✔
430
    tDecoderClear(&dc);
12,164,226✔
431

432
    SIdInfo info = {0};
12,167,724✔
433
    code = taosHashPut(ctx->idVersion, &tmp->uid, sizeof(tb_uid_t), &info, sizeof(SIdInfo));
12,167,724✔
434
    TSDB_CHECK_CODE(code, lino, END);
12,166,146✔
435
  }
436
  taosHashClear(ctx->idVersion);
125,808✔
437

438
  code = MoveToSnapShotVersion(ctx);
125,808✔
439
  TSDB_CHECK_CODE(code, lino, END);
125,808✔
440

441
  while (1) {
12,352,687✔
442
    int32_t ret = tdbTbcPrev((TBC*)ctx->pCur, &pKey, &kLen, &pVal, &vLen);
12,478,495✔
443
    if (ret < 0) break;
12,475,853✔
444

445
    STbDbKey* tmp = (STbDbKey*)pKey;
12,350,045✔
446
    SIdInfo*  idData = (SIdInfo*)taosHashGet(ctx->idVersion, &tmp->uid, sizeof(tb_uid_t));
12,350,045✔
447
    if (idData) {
12,349,143✔
448
      continue;
149,225✔
449
    }
450
    SIdInfo info = {.version = tmp->version, .index = 0};
12,199,918✔
451
    code = taosHashPut(ctx->idVersion, &tmp->uid, sizeof(tb_uid_t), &info, sizeof(SIdInfo));
12,199,918✔
452
    TSDB_CHECK_CODE(code, lino, END);
12,200,564✔
453

454
    SMetaEntry me = {0};
12,200,564✔
455
    tDecoderInit(&dc, pVal, vLen);
12,200,564✔
456
    code = metaDecodeEntry(&dc, &me);
12,202,160✔
457
    TSDB_CHECK_CODE(code, lino, END);
12,200,574✔
458

459
    if (ctx->subType == TOPIC_SUB_TYPE__TABLE) {
12,200,574✔
460
      if ((me.uid != ctx->suid && me.type == TSDB_SUPER_TABLE) ||
203,874✔
461
          (me.ctbEntry.suid != ctx->suid && me.type == TSDB_CHILD_TABLE)) {
203,600✔
462
        tDecoderClear(&dc);
1,096✔
463
        continue;
1,096✔
464
      }
465
    } else if (ctx->subType == TOPIC_SUB_TYPE__DB) {
11,997,940✔
466
      if (me.type == TSDB_VIRTUAL_NORMAL_TABLE ||
11,997,940✔
467
          me.type == TSDB_VIRTUAL_CHILD_TABLE ||
11,997,940✔
468
          TABLE_IS_VIRTUAL(me.flags)) {
11,997,940✔
UNCOV
469
        tDecoderClear(&dc);
×
470
        continue;
×
471
      }
472
    }
473

474
    if ((ctx->subType == TOPIC_SUB_TYPE__DB && me.type == TSDB_SUPER_TABLE) ||
12,200,718✔
475
        (ctx->subType == TOPIC_SUB_TYPE__TABLE && me.uid == ctx->suid)) {
12,041,457✔
476
      code = saveSuperTableInfoForChildTable(&me, ctx->suidInfo);
181,046✔
477
      TSDB_CHECK_CODE(code, lino, END);
181,046✔
478
    }
479
    tDecoderClear(&dc);
12,200,718✔
480

481
  }
482

483
  for (int i = 0; i < taosArrayGetSize(ctx->idList); i++) {
12,296,410✔
484
    int64_t* uid = taosArrayGet(ctx->idList, i);
12,170,602✔
485
    TSDB_CHECK_NULL(uid, code, lino, END, terrno);
12,169,568✔
486
    SIdInfo* idData = (SIdInfo*)taosHashGet(ctx->idVersion, uid, sizeof(int64_t));
12,169,568✔
487
    TSDB_CHECK_NULL(idData, code, lino, END, terrno);
12,169,958✔
488

489
    idData->index = i;
12,169,958✔
490
    metaDebug("tmqsnap init idVersion uid:%" PRIi64 " version:%" PRIi64 " index:%d", *uid, idData->version, idData->index);
12,169,958✔
491
  }
492

493
END:
125,168✔
494
  tdbFree(pKey);
125,808✔
495
  tdbFree(pVal);
125,808✔
496
  tDecoderClear(&dc);
125,808✔
497

498
  if (ctx != NULL) {
125,808✔
499
    tdbTbcClose((TBC*)ctx->pCur);
125,808✔
500
    ctx->pCur = NULL;
125,808✔
501
  }
502
  metaULock(pVnode->pMeta);
125,808✔
503

504
  if(code != 0) {
125,808✔
505
    destroySnapContext(ctx);
×
506
    *ctxRet = NULL;
×
507
    metaError("tmqsnap build snap context failed line:%d since %s", lino, tstrerror(code));
×
508
  }
509
  return code;
125,808✔
510
}
511

512
void destroySnapContext(SSnapContext* ctx) {
587,039✔
513
  if (ctx == NULL) {
587,039✔
514
    return;
462,472✔
515
  }
516
  taosArrayDestroy(ctx->idList);
124,567✔
517
  taosHashCleanup(ctx->idVersion);
125,808✔
518
  taosHashCleanup(ctx->suidInfo);
125,808✔
519
  taosMemoryFree(ctx);
125,808✔
520
}
521

522
static int32_t buildNormalChildTableInfo(SVCreateTbReq* req, void** pBuf, int32_t* contLen) {
25,558✔
523
  int32_t            ret = 0;
25,558✔
524
  SVCreateTbBatchReq reqs = {0};
25,558✔
525

526
  reqs.pArray = taosArrayInit(1, sizeof(struct SVCreateTbReq));
25,558✔
527
  if (NULL == reqs.pArray) {
25,558✔
528
    ret = TAOS_GET_TERRNO(TSDB_CODE_OUT_OF_MEMORY);
×
529
    goto end;
×
530
  }
531
  if (taosArrayPush(reqs.pArray, req) == NULL) {
51,116✔
532
    ret = TAOS_GET_TERRNO(TSDB_CODE_OUT_OF_MEMORY);
×
533
    goto end;
×
534
  }
535
  reqs.nReqs = 1;
25,558✔
536

537
  tEncodeSize(tEncodeSVCreateTbBatchReq, &reqs, *contLen, ret);
25,558✔
538
  if (ret < 0) {
25,558✔
539
    ret = TAOS_GET_TERRNO(ret);
×
540
    goto end;
×
541
  }
542
  *contLen += sizeof(SMsgHead);
25,558✔
543
  *pBuf = taosMemoryMalloc(*contLen);
25,558✔
544
  if (NULL == *pBuf) {
25,558✔
545
    ret = TAOS_GET_TERRNO(TSDB_CODE_OUT_OF_MEMORY);
×
546
    goto end;
×
547
  }
548
  SEncoder coder = {0};
25,558✔
549
  tEncoderInit(&coder, POINTER_SHIFT(*pBuf, sizeof(SMsgHead)), *contLen);
25,558✔
550
  ret = tEncodeSVCreateTbBatchReq(&coder, &reqs);
25,558✔
551
  tEncoderClear(&coder);
25,558✔
552

553
  if (ret < 0) {
25,558✔
554
    taosMemoryFreeClear(*pBuf);
×
555
    ret = TAOS_GET_TERRNO(ret);
×
556
    goto end;
×
557
  }
558

559
end:
25,558✔
560
  taosArrayDestroy(reqs.pArray);
25,558✔
561
  return ret;
25,558✔
562
}
563

564
static int32_t buildSuperTableInfo(SVCreateStbReq* req, void** pBuf, int32_t* contLen) {
10,830✔
565
  int32_t ret = 0;
10,830✔
566
  tEncodeSize(tEncodeSVCreateStbReq, req, *contLen, ret);
10,830✔
567
  if (ret < 0) {
10,830✔
568
    return TAOS_GET_TERRNO(ret);
×
569
  }
570

571
  *contLen += sizeof(SMsgHead);
10,830✔
572
  *pBuf = taosMemoryMalloc(*contLen);
10,830✔
573
  if (NULL == *pBuf) {
10,830✔
574
    return TAOS_GET_TERRNO(TSDB_CODE_OUT_OF_MEMORY);
×
575
  }
576

577
  SEncoder encoder = {0};
10,830✔
578
  tEncoderInit(&encoder, POINTER_SHIFT(*pBuf, sizeof(SMsgHead)), *contLen);
10,830✔
579
  ret = tEncodeSVCreateStbReq(&encoder, req);
10,830✔
580
  tEncoderClear(&encoder);
10,830✔
581
  if (ret < 0) {
10,830✔
582
    taosMemoryFreeClear(*pBuf);
×
583
    return TAOS_GET_TERRNO(ret);
×
584
  }
585
  return 0;
10,830✔
586
}
587

588
int32_t setForSnapShot(SSnapContext* ctx, int64_t uid) {
799,161✔
589
  if (uid == 0) {
799,161✔
590
    ctx->index = 0;
16,073✔
591
    return 0;
16,073✔
592
  }
593

594
  SIdInfo* idInfo = (SIdInfo*)taosHashGet(ctx->idVersion, &uid, sizeof(tb_uid_t));
783,088✔
595
  if (idInfo == NULL) {
783,088✔
596
    return terrno;
×
597
  }
598

599
  ctx->index = idInfo->index;
783,088✔
600

601
  return 0;
783,088✔
602
}
603

604
void taosXSetTablePrimaryKey(SSnapContext* ctx, int64_t uid) {
792,699✔
605
  bool            ret = false;
792,699✔
606
  SSchemaWrapper* schema = metaGetTableSchema(ctx->pMeta, uid, -1, 1, NULL, 0);
792,699✔
607
  if (schema && schema->nCols >= 2 && schema->pSchema[1].flags & COL_IS_KEY) {
791,751✔
608
    ret = true;
1,359✔
609
  }
610
  tDeleteSchemaWrapper(schema);
611
  ctx->hasPrimaryKey = ret;
791,115✔
612
}
793,015✔
613

614
bool taosXGetTablePrimaryKey(SSnapContext* ctx) { return ctx->hasPrimaryKey; }
1,579,928✔
615

616
int32_t getTableInfoFromSnapshot(SSnapContext* ctx, void** pBuf, int32_t* contLen, int16_t* type, int64_t* uid) {
41,348✔
617
  int32_t ret = 0;
41,348✔
618
  int32_t lino = 0;
41,348✔
619
  void*   pKey = NULL;
41,348✔
620
  void*   pVal = NULL;
41,348✔
621
  int     vLen = 0, kLen = 0;
41,348✔
622
  SDecoder   dc = {0};
41,348✔
623
  SArray* tagName = NULL;
41,348✔
624
  SArray* pTagVals = NULL;
41,348✔
625

626
  metaRLock(ctx->pMeta);
41,348✔
627
  while (1) {
×
628
    if (ctx->index >= taosArrayGetSize(ctx->idList)) {
41,348✔
629
      metaDebug("tmqsnap get meta end");
4,960✔
630
      ctx->index = 0;
4,960✔
631
      ctx->queryMeta = 0;  // change to get data
4,960✔
632
      goto END;
4,960✔
633
    }
634

635
    int64_t* uidTmp = taosArrayGet(ctx->idList, ctx->index);
36,388✔
636
    TSDB_CHECK_NULL(uidTmp, ret, lino, END, terrno);
36,388✔
637
    ctx->index++;
36,388✔
638
    SIdInfo* idInfo = (SIdInfo*)taosHashGet(ctx->idVersion, uidTmp, sizeof(tb_uid_t));
36,388✔
639
    TSDB_CHECK_NULL(idInfo, ret, lino, END, terrno);
36,388✔
640

641
    *uid = *uidTmp;
36,388✔
642
    ret = MoveToPosition(ctx, idInfo->version, *uidTmp);
36,388✔
643
    if (ret == 0) {
36,388✔
644
      break;
36,388✔
645
    }
646
    metaDebug("tmqsnap get meta not exist uid:%" PRIi64 " version:%" PRIi64, *uid, idInfo->version);
×
647
  }
648

649
  ret = tdbTbcGet((TBC*)ctx->pCur, (const void**)&pKey, &kLen, (const void**)&pVal, &vLen);
36,388✔
650
  TSDB_CHECK_CONDITION(ret >= 0, ret, lino, END, TAOS_GET_TERRNO(ret));
36,388✔
651
  SMetaEntry me = {0};
36,388✔
652
  tDecoderInit(&dc, pVal, vLen);
36,388✔
653
  ret = metaDecodeEntry(&dc, &me);
36,388✔
654
  TSDB_CHECK_CONDITION(ret >= 0, ret, lino, END, TAOS_GET_TERRNO(ret));
36,388✔
655
  metaDebug("tmqsnap get meta uid:%" PRIi64 " name:%s index:%d", *uid, me.name, ctx->index - 1);
36,388✔
656

657
  if ((ctx->subType == TOPIC_SUB_TYPE__DB && me.type == TSDB_SUPER_TABLE) ||
36,388✔
658
      (ctx->subType == TOPIC_SUB_TYPE__TABLE && me.uid == ctx->suid)) {
36,388✔
659
    SVCreateStbReq req = {0};
10,830✔
660
    req.name = me.name;
10,830✔
661
    req.suid = me.uid;
10,830✔
662
    req.schemaRow = me.stbEntry.schemaRow;
10,830✔
663
    req.schemaTag = me.stbEntry.schemaTag;
10,830✔
664
    req.schemaRow.version = 1;
10,830✔
665
    req.schemaTag.version = 1;
10,830✔
666
    req.colCmpr = me.colCmpr;
10,830✔
667
    req.pExtSchemas = me.pExtSchemas;
10,830✔
668

669
    ret = buildSuperTableInfo(&req, pBuf, contLen);
10,830✔
670
    *type = TDMT_VND_CREATE_STB;
10,830✔
671
  } else if ((ctx->subType == TOPIC_SUB_TYPE__DB && me.type == TSDB_CHILD_TABLE) ||
25,558✔
672
             (ctx->subType == TOPIC_SUB_TYPE__TABLE && me.type == TSDB_CHILD_TABLE && me.ctbEntry.suid == ctx->suid)) {
25,558✔
673
    STableInfoForChildTable* data =
674
        (STableInfoForChildTable*)taosHashGet(ctx->suidInfo, &me.ctbEntry.suid, sizeof(tb_uid_t));
22,112✔
675
    TSDB_CHECK_NULL(data, ret, lino, END, terrno);
22,112✔
676

677
    SVCreateTbReq req = {0};
22,112✔
678

679
    req.type = TSDB_CHILD_TABLE;
22,112✔
680
    req.name = me.name;
22,112✔
681
    req.uid = me.uid;
22,112✔
682
    req.commentLen = -1;
22,112✔
683
    req.ctb.suid = me.ctbEntry.suid;
22,112✔
684
    req.ctb.tagNum = data->tagRow->nCols;
22,112✔
685
    req.ctb.stbName = data->tableName;
22,112✔
686

687
    tagName = taosArrayInit(req.ctb.tagNum, TSDB_COL_NAME_LEN);
22,112✔
688
    TSDB_CHECK_NULL(tagName, ret, lino, END, terrno);
22,112✔
689
    STag* p = (STag*)me.ctbEntry.pTags;
22,112✔
690
    if (tTagIsJson(p)) {
22,112✔
691
      if (p->nTag != 0) {
3,288✔
692
        SSchema* schema = &data->tagRow->pSchema[0];
1,644✔
693
        TSDB_CHECK_NULL(taosArrayPush(tagName, schema->name), ret, lino, END, terrno);
3,288✔
694
      }
695
    } else {
696
      ret = tTagToValArray((const STag*)p, &pTagVals);
18,824✔
697
      TSDB_CHECK_CODE(ret, lino, END);
18,824✔
698
      int16_t nCols = taosArrayGetSize(pTagVals);
18,824✔
699
      for (int j = 0; j < nCols; ++j) {
65,048✔
700
        STagVal* pTagVal = (STagVal*)taosArrayGet(pTagVals, j);
46,224✔
701
        for (int i = 0; pTagVal && i < data->tagRow->nCols; i++) {
187,526✔
702
          SSchema* schema = &data->tagRow->pSchema[i];
141,302✔
703
          if (schema->colId == pTagVal->cid) {
141,302✔
704
            TSDB_CHECK_NULL(taosArrayPush(tagName, schema->name), ret, lino, END, terrno);
92,448✔
705
          }
706
        }
707
      }
708
    }
709
    req.ctb.pTag = me.ctbEntry.pTags;
22,112✔
710
    req.ctb.tagName = tagName;
22,112✔
711
    ret = buildNormalChildTableInfo(&req, pBuf, contLen);
22,112✔
712
    *type = TDMT_VND_CREATE_TABLE;
22,112✔
713
  } else if (ctx->subType == TOPIC_SUB_TYPE__DB && me.type == TSDB_NORMAL_TABLE) {
6,892✔
714
    SVCreateTbReq req = {0};
3,446✔
715
    req.type = TSDB_NORMAL_TABLE;
3,446✔
716
    req.name = me.name;
3,446✔
717
    req.uid = me.uid;
3,446✔
718
    req.commentLen = -1;
3,446✔
719
    req.ntb.schemaRow = me.ntbEntry.schemaRow;
3,446✔
720
    req.colCmpr = me.colCmpr;
3,446✔
721
    req.pExtSchemas = me.pExtSchemas;
3,446✔
722
    ret = buildNormalChildTableInfo(&req, pBuf, contLen);
3,446✔
723
    *type = TDMT_VND_CREATE_TABLE;
3,446✔
724
  } else {
725
    metaError("meta/snap: invalid topic sub type: %" PRId8 " get meta from snap failed.", ctx->subType);
×
726
    ret = TSDB_CODE_SDB_INVALID_TABLE_TYPE;
×
727
  }
728

729
END:
41,348✔
730
  tdbTbcClose((TBC*)ctx->pCur);
41,348✔
731
  ctx->pCur = NULL;
41,348✔
732
  taosArrayDestroy(pTagVals);
41,348✔
733
  taosArrayDestroy(tagName);
41,348✔
734
  tDecoderClear(&dc);
41,348✔
735
  metaULock(ctx->pMeta);
41,348✔
736

737
  if(ret != 0) {
41,348✔
738
    metaError("tmqsnap get table info from snapshot failed line:%d since %s", lino, tstrerror(ret));
×
739
  }
740
  return ret;
41,348✔
741
}
742

743
int32_t getMetaTableInfoFromSnapshot(SSnapContext* ctx, SMetaTableInfo* result) {
1,586,453✔
744
  void* pKey = NULL;
1,586,453✔
745
  void* pVal = NULL;
1,586,453✔
746
  int   vLen = 0;
1,586,769✔
747
  int   kLen = 0;
1,586,769✔
748
  int32_t code = 0;
1,586,769✔
749
  int32_t lino = 0;
1,586,769✔
750
  SDecoder   dc = {0};
1,586,769✔
751

752
  metaRLock(ctx->pMeta);
1,586,769✔
753
  while (1) {
19,007✔
754
    if (ctx->index >= taosArrayGetSize(ctx->idList)) {
1,605,776✔
755
      metaDebug("tmqsnap get uid info end");
10,650✔
756
      goto END;
10,650✔
757
    }
758
    int64_t* uidTmp = taosArrayGet(ctx->idList, ctx->index);
1,595,126✔
759
    TSDB_CHECK_NULL(uidTmp, code, lino, END, terrno);
1,595,126✔
760
    ctx->index++;
1,595,126✔
761
    SIdInfo* idInfo = (SIdInfo*)taosHashGet(ctx->idVersion, uidTmp, sizeof(tb_uid_t));
1,595,126✔
762
    TSDB_CHECK_NULL(idInfo, code, lino, END, terrno);
1,594,810✔
763

764
    if (MoveToPosition(ctx, idInfo->version, *uidTmp) != 0) {
1,594,810✔
765
      metaDebug("tmqsnap getMetaTableInfoFromSnapshot not exist uid:%" PRIi64 " version:%" PRIi64, *uidTmp,
×
766
                idInfo->version);
767
      continue;
×
768
    }
769
    code = tdbTbcGet((TBC*)ctx->pCur, (const void**)&pKey, &kLen, (const void**)&pVal, &vLen);
1,594,810✔
770
    TSDB_CHECK_CODE(code, lino, END);
1,594,810✔
771
    SMetaEntry me = {0};
1,594,810✔
772
    tDecoderInit(&dc, pVal, vLen);
1,594,810✔
773
    code = metaDecodeEntry(&dc, &me);
1,594,810✔
774
    TSDB_CHECK_CODE(code, lino, END);
1,591,926✔
775
    metaDebug("tmqsnap get uid info uid:%" PRIi64 " name:%s index:%d", me.uid, me.name, ctx->index - 1);
1,591,926✔
776

777
    if ((ctx->subType == TOPIC_SUB_TYPE__DB && me.type == TSDB_CHILD_TABLE) ||
1,591,926✔
778
        (ctx->subType == TOPIC_SUB_TYPE__TABLE && me.type == TSDB_CHILD_TABLE && me.ctbEntry.suid == ctx->suid)) {
1,593,579✔
779
      STableInfoForChildTable* data =
780
          (STableInfoForChildTable*)taosHashGet(ctx->suidInfo, &me.ctbEntry.suid, sizeof(tb_uid_t));
307,237✔
781
      TSDB_CHECK_NULL(data, code, lino, END, terrno);
309,485✔
782
      result->suid = me.ctbEntry.suid;
309,485✔
783
      result->schema = tCloneSSchemaWrapper(data->schemaRow);
619,290✔
784
      if (data->pExtSchemas != NULL) {
309,485✔
785
        result->pExtSchemas = taosMemoryMalloc(sizeof(SExtSchema) * data->schemaRow->nCols);
8,542✔
786
        TSDB_CHECK_NULL(result->pExtSchemas, code, lino, END, terrno);
8,542✔
787
        memcpy(result->pExtSchemas, data->pExtSchemas, sizeof(SExtSchema) * data->schemaRow->nCols);
8,542✔
788
      }
789
    } else if (ctx->subType == TOPIC_SUB_TYPE__DB && me.type == TSDB_NORMAL_TABLE) {
1,284,689✔
790
      result->suid = 0;
1,265,050✔
791
      result->schema = tCloneSSchemaWrapper(&me.ntbEntry.schemaRow);
1,265,050✔
792
      if (me.pExtSchemas != NULL) {
1,263,786✔
793
        result->pExtSchemas = taosMemoryMalloc(sizeof(SExtSchema) * me.ntbEntry.schemaRow.nCols);
×
794
        TSDB_CHECK_NULL(result->pExtSchemas, code, lino, END, terrno);
×
795
        memcpy(result->pExtSchemas, me.pExtSchemas, sizeof(SExtSchema) * me.ntbEntry.schemaRow.nCols);
×
796
      }
797
    } else {
798
      metaDebug("tmqsnap get uid continue");
18,691✔
799
      tDecoderClear(&dc);
18,691✔
800
      continue;
19,007✔
801
    }
802
    result->uid = me.uid;
1,573,271✔
803
    tstrncpy(result->tbName, me.name, TSDB_TABLE_NAME_LEN);
1,574,219✔
804
    TSDB_CHECK_NULL(result->schema, code, lino, END, TAOS_GET_TERRNO(TSDB_CODE_OUT_OF_MEMORY));
1,572,955✔
805
    break;
1,571,647✔
806
  }
807

808
END:
1,585,501✔
809
  tDecoderClear(&dc);
1,586,137✔
810
  tdbTbcClose((TBC*)ctx->pCur);
1,585,817✔
811
  ctx->pCur = NULL;
1,585,821✔
812
  metaULock(ctx->pMeta);
1,585,821✔
813

814
  if (code != 0) {
1,582,973✔
815
    metaError("tmqsnap get meta table info from snapshot failed line:%d since %s", lino, tstrerror(code));
×
816
  }
817
  return code;
1,582,973✔
818
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc