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

taosdata / TDengine / #3653

14 Mar 2025 08:10AM UTC coverage: 22.565% (-41.0%) from 63.596%
#3653

push

travis-ci

web-flow
feat(keep): support keep on super table level. (#30097)

* Feat: support use keep while create super table.

* Test(keep): add test for create super table with keep option.

* Feat(keep): Add tmsg for create keep.

* Feat(keep): support alter table option keep.

* Fix(keep): Add baisc test for alter table option.

* Fix(keep): memory leek.

* Feat(keep): add keep to metaEntry&metaCache and fix earliestTs with stn keep.

* Test(keep): add some cases for select with stb keep.

* Fix: fix ci core while alter stb.

* Feat(keep): delete expired data in super table level.

* Feat: remove get stb keep while query.

* Fix : build error.

* Revert "Fix : build error."

This reverts commit 0ed66e4e8.

* Revert "Feat(keep): delete expired data in super table level."

This reverts commit 36330f6b4.

* Fix : build errors.

* Feat : support restart taosd.

* Fix : alter table comment problems.

* Test : add tests for super table keep.

* Fix: change sdb stb reserve size.

* Test: add more tests.

* Feat: Disable normal tables and sub tables from setting the keep parameter

* Fix: add more checks to avoid unknown address.

* Docs: Add docs for stable keep.

* Fix: some review changes.

* Fix: review errors.

49248 of 302527 branches covered (16.28%)

Branch coverage included in aggregate %.

53 of 99 new or added lines in 12 files covered. (53.54%)

155872 existing lines in 443 files now uncovered.

87359 of 302857 relevant lines covered (28.84%)

570004.22 hits per line

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

28.55
/source/dnode/vnode/src/meta/metaOpen.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
#include "vnd.h"
18

19
#ifndef NO_UNALIGNED_ACCESS
20
#define TDB_KEY_ALIGN(k1, k2, kType)
21
#else
22
#define TDB_KEY_ALIGN(k1, k2, kType)   \
23
  kType _k1, _k2;                      \
24
  if (((uintptr_t)(k1) & 7)) {         \
25
    memcpy(&_k1, (k1), sizeof(kType)); \
26
    (k1) = &_k1;                       \
27
  }                                    \
28
  if (((uintptr_t)(k2) & 7)) {         \
29
    memcpy(&_k2, (k2), sizeof(kType)); \
30
    (k2) = &_k2;                       \
31
  }
32
#endif
33

34
static int tbDbKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2);
35
static int skmDbKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2);
36
static int ctbIdxKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2);
37
int        tagIdxKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2);
38
static int uidIdxKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2);
39
static int smaIdxKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2);
40
static int taskIdxKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2);
41

42
static int btimeIdxCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2);
43
static int ncolIdxCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2);
44

45
static void metaInitLock(SMeta *pMeta) {
20✔
46
  TdThreadRwlockAttr attr;
47
  (void)taosThreadRwlockAttrInit(&attr);
20✔
48
  (void)taosThreadRwlockAttrSetKindNP(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
20✔
49
  (void)taosThreadRwlockInit(&pMeta->lock, &attr);
20✔
50
  (void)taosThreadRwlockAttrDestroy(&attr);
20✔
51
  return;
20✔
52
}
53
static void metaDestroyLock(SMeta *pMeta) { (void)taosThreadRwlockDestroy(&pMeta->lock); }
20✔
54

55
static void metaCleanup(SMeta **ppMeta);
56

57
static void doScan(SMeta *pMeta) {
×
58
  TBC    *cursor = NULL;
×
59
  int32_t code;
60

61
  // open file to write
UNCOV
62
  char path[TSDB_FILENAME_LEN] = {0};
×
UNCOV
63
  snprintf(path, TSDB_FILENAME_LEN - 1, "%s%s", pMeta->path, TD_DIRSEP "scan.txt");
×
64
  TdFilePtr fp = taosOpenFile(path, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
×
65
  if (fp == NULL) {
×
66
    metaError("failed to open file:%s, reason:%s", path, tstrerror(terrno));
×
67
    return;
×
68
  }
69

70
  code = tdbTbcOpen(pMeta->pTbDb, &cursor, NULL);
×
71
  if (code) {
×
UNCOV
72
    if (taosCloseFile(&fp) != 0) {
×
UNCOV
73
      metaError("failed to close file:%s, reason:%s", path, tstrerror(terrno));
×
74
    }
UNCOV
75
    metaError("failed to open table.db cursor, reason:%s", tstrerror(terrno));
×
UNCOV
76
    return;
×
77
  }
78

79
  code = tdbTbcMoveToFirst(cursor);
×
80
  if (code) {
×
UNCOV
81
    if (taosCloseFile(&fp) != 0) {
×
UNCOV
82
      metaError("failed to close file:%s, reason:%s", path, tstrerror(terrno));
×
83
    }
84
    tdbTbcClose(cursor);
×
85
    metaError("failed to move to first, reason:%s", tstrerror(terrno));
×
UNCOV
86
    return;
×
87
  }
88

89
  for (;;) {
×
90
    const void *pKey;
91
    int         kLen;
92
    const void *pVal;
93
    int         vLen;
UNCOV
94
    if (tdbTbcGet(cursor, &pKey, &kLen, &pVal, &vLen) < 0) {
×
95
      break;
×
96
    }
97

98
    // decode entry
99
    SDecoder   dc = {0};
×
UNCOV
100
    SMetaEntry me = {0};
×
101

102
    tDecoderInit(&dc, (uint8_t *)pVal, vLen);
×
103

UNCOV
104
    if (metaDecodeEntry(&dc, &me) < 0) {
×
UNCOV
105
      tDecoderClear(&dc);
×
UNCOV
106
      break;
×
107
    }
108

109
    // skip deleted entry
UNCOV
110
    if (tdbTbGet(pMeta->pUidIdx, &me.uid, sizeof(me.uid), NULL, NULL) == 0) {
×
111
      // print entry
112
      char buf[1024] = {0};
×
113
      if (me.type == TSDB_SUPER_TABLE) {
×
114
        snprintf(buf, sizeof(buf) - 1, "type: super table, version:%" PRId64 " uid: %" PRId64 " name: %s\n", me.version,
×
115
                 me.uid, me.name);
116

UNCOV
117
      } else if (me.type == TSDB_CHILD_TABLE) {
×
118
        snprintf(buf, sizeof(buf) - 1,
×
119
                 "type: child table, version:%" PRId64 " uid: %" PRId64 " name: %s suid:%" PRId64 "\n", me.version,
120
                 me.uid, me.name, me.ctbEntry.suid);
121
      } else {
UNCOV
122
        snprintf(buf, sizeof(buf) - 1, "type: normal table, version:%" PRId64 " uid: %" PRId64 " name: %s\n",
×
123
                 me.version, me.uid, me.name);
124
      }
125

UNCOV
126
      if (taosWriteFile(fp, buf, strlen(buf)) < 0) {
×
UNCOV
127
        metaError("failed to write file:%s, reason:%s", path, tstrerror(terrno));
×
128
        tDecoderClear(&dc);
×
129
        break;
×
130
      }
131
    }
132

UNCOV
133
    tDecoderClear(&dc);
×
134

UNCOV
135
    if (tdbTbcMoveToNext(cursor) < 0) {
×
UNCOV
136
      break;
×
137
    }
138
  }
139

UNCOV
140
  tdbTbcClose(cursor);
×
141

142
  // close file
UNCOV
143
  if (taosFsyncFile(fp) < 0) {
×
UNCOV
144
    metaError("failed to fsync file:%s, reason:%s", path, tstrerror(terrno));
×
145
  }
UNCOV
146
  if (taosCloseFile(&fp) < 0) {
×
UNCOV
147
    metaError("failed to close file:%s, reason:%s", path, tstrerror(terrno));
×
148
  }
149
}
150

151
int32_t metaOpenImpl(SVnode *pVnode, SMeta **ppMeta, const char *metaDir, int8_t rollback) {
20✔
152
  SMeta  *pMeta = NULL;
20✔
153
  int32_t code = 0;
20✔
154
  int32_t lino;
155
  int32_t offset;
156
  int32_t pathLen = 0;
20✔
157
  char    path[TSDB_FILENAME_LEN] = {0};
20✔
158
  char    indexFullPath[128] = {0};
20✔
159

160
  // create handle
161
  vnodeGetPrimaryDir(pVnode->path, pVnode->diskPrimary, pVnode->pTfs, path, TSDB_FILENAME_LEN);
20✔
162
  offset = strlen(path);
20✔
163
  snprintf(path + offset, TSDB_FILENAME_LEN - offset - 1, "%s%s", TD_DIRSEP, metaDir);
20✔
164

165
  if (strncmp(metaDir, VNODE_META_TMP_DIR, strlen(VNODE_META_TMP_DIR)) == 0) {
20!
UNCOV
166
    taosRemoveDir(path);
×
167
  }
168

169
  pathLen = strlen(path) + 1;
20✔
170
  if ((pMeta = taosMemoryCalloc(1, sizeof(*pMeta) + pathLen)) == NULL) {
20!
UNCOV
171
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
172
  }
173

174
  metaInitLock(pMeta);
20✔
175

176
  pMeta->path = (char *)&pMeta[1];
20✔
177
  tstrncpy(pMeta->path, path, pathLen);
20✔
178
  int32_t ret = taosRealPath(pMeta->path, NULL, strlen(path) + 1);
20✔
179

180
  pMeta->pVnode = pVnode;
20✔
181

182
  // create path if not created yet
183
  code = taosMkDir(pMeta->path);
20✔
184
  TSDB_CHECK_CODE(code, lino, _exit);
20!
185

186
  // open env
187
  code = tdbOpen(pMeta->path, pVnode->config.szPage, pVnode->config.szCache, &pMeta->pEnv, rollback,
20✔
188
                 pVnode->config.tdbEncryptAlgorithm, pVnode->config.tdbEncryptKey);
20✔
189
  TSDB_CHECK_CODE(code, lino, _exit);
20!
190

191
  // open pTbDb
192
  code = tdbTbOpen("table.db", sizeof(STbDbKey), -1, tbDbKeyCmpr, pMeta->pEnv, &pMeta->pTbDb, 0);
20✔
193
  TSDB_CHECK_CODE(code, lino, _exit);
20!
194

195
  // open pSkmDb
196
  code = tdbTbOpen("schema.db", sizeof(SSkmDbKey), -1, skmDbKeyCmpr, pMeta->pEnv, &pMeta->pSkmDb, 0);
20✔
197
  TSDB_CHECK_CODE(code, lino, _exit);
20!
198

199
  // open pUidIdx
200
  code = tdbTbOpen("uid.idx", sizeof(tb_uid_t), sizeof(SUidIdxVal), uidIdxKeyCmpr, pMeta->pEnv, &pMeta->pUidIdx, 0);
20✔
201
  TSDB_CHECK_CODE(code, lino, _exit);
20!
202

203
  // open pNameIdx
204
  code = tdbTbOpen("name.idx", -1, sizeof(tb_uid_t), NULL, pMeta->pEnv, &pMeta->pNameIdx, 0);
20✔
205
  TSDB_CHECK_CODE(code, lino, _exit);
20!
206

207
  // open pCtbIdx
208
  code = tdbTbOpen("ctb.idx", sizeof(SCtbIdxKey), -1, ctbIdxKeyCmpr, pMeta->pEnv, &pMeta->pCtbIdx, 0);
20✔
209
  TSDB_CHECK_CODE(code, lino, _exit);
20!
210

211
  // open pSuidIdx
212
  code = tdbTbOpen("suid.idx", sizeof(tb_uid_t), 0, uidIdxKeyCmpr, pMeta->pEnv, &pMeta->pSuidIdx, 0);
20✔
213
  TSDB_CHECK_CODE(code, lino, _exit);
20!
214

215
  (void)tsnprintf(indexFullPath, sizeof(indexFullPath), "%s/%s", pMeta->path, "invert");
20✔
216
  ret = taosMkDir(indexFullPath);
20✔
217

218
  SIndexOpts opts = {.cacheSize = 8 * 1024 * 1024};
20✔
219
  code = indexOpen(&opts, indexFullPath, (SIndex **)&pMeta->pTagIvtIdx);
20✔
220
  TSDB_CHECK_CODE(code, lino, _exit);
20!
221

222
  code = tdbTbOpen("tag.idx", -1, 0, tagIdxKeyCmpr, pMeta->pEnv, &pMeta->pTagIdx, 0);
20✔
223
  TSDB_CHECK_CODE(code, lino, _exit);
20!
224

225
  // open pTtlMgr ("ttlv1.idx")
226
  char logPrefix[128] = {0};
20✔
227
  (void)tsnprintf(logPrefix, sizeof(logPrefix), "vgId:%d", TD_VID(pVnode));
20✔
228
  code = ttlMgrOpen(&pMeta->pTtlMgr, pMeta->pEnv, 0, logPrefix, tsTtlFlushThreshold);
20✔
229
  TSDB_CHECK_CODE(code, lino, _exit);
20!
230

231
  // open pSmaIdx
232
  code = tdbTbOpen("sma.idx", sizeof(SSmaIdxKey), 0, smaIdxKeyCmpr, pMeta->pEnv, &pMeta->pSmaIdx, 0);
20✔
233
  TSDB_CHECK_CODE(code, lino, _exit);
20!
234

235
  // idx table create time
236
  code = tdbTbOpen("ctime.idx", sizeof(SBtimeIdxKey), 0, btimeIdxCmpr, pMeta->pEnv, &pMeta->pBtimeIdx, 0);
20✔
237
  TSDB_CHECK_CODE(code, lino, _exit);
20!
238

239
  // idx num of col, normal table only
240
  code = tdbTbOpen("ncol.idx", sizeof(SNcolIdxKey), 0, ncolIdxCmpr, pMeta->pEnv, &pMeta->pNcolIdx, 0);
20✔
241
  TSDB_CHECK_CODE(code, lino, _exit);
20!
242

243
  code = tdbTbOpen("stream.task.db", sizeof(int64_t), -1, taskIdxKeyCmpr, pMeta->pEnv, &pMeta->pStreamDb, 0);
20✔
244
  TSDB_CHECK_CODE(code, lino, _exit);
20!
245

246
  code = metaCacheOpen(pMeta);
20✔
247
  TSDB_CHECK_CODE(code, lino, _exit);
20!
248

249
  code = metaInitTbFilterCache(pMeta);
20✔
250
  TSDB_CHECK_CODE(code, lino, _exit);
20!
251

252
#if 0
253
  // Do NOT remove this code, it is used to do debug stuff
254
  doScan(pMeta);
255
#endif
256

257
_exit:
20✔
258
  if (code) {
20!
UNCOV
259
    metaError("vgId:%d %s failed at %s:%d since %s", TD_VID(pVnode), __func__, __FILE__, __LINE__, tstrerror(code));
×
UNCOV
260
    metaCleanup(&pMeta);
×
UNCOV
261
    *ppMeta = NULL;
×
262
  } else {
263
    metaDebug("vgId:%d %s success", TD_VID(pVnode), __func__);
20!
264
    *ppMeta = pMeta;
20✔
265
  }
266
  TAOS_RETURN(code);
20✔
267
}
268

269
void vnodeGetMetaPath(SVnode *pVnode, const char *metaDir, char *fname) {
60✔
270
  vnodeGetPrimaryDir(pVnode->path, pVnode->diskPrimary, pVnode->pTfs, fname, TSDB_FILENAME_LEN);
60✔
271
  int32_t offset = strlen(fname);
60✔
272
  snprintf(fname + offset, TSDB_FILENAME_LEN - offset - 1, "%s%s", TD_DIRSEP, metaDir);
60✔
273
}
60✔
274

275
bool generateNewMeta = false;
276

277
static int32_t metaGenerateNewMeta(SMeta **ppMeta) {
×
UNCOV
278
  SMeta  *pNewMeta = NULL;
×
UNCOV
279
  SMeta  *pMeta = *ppMeta;
×
UNCOV
280
  SVnode *pVnode = pMeta->pVnode;
×
281

282
  metaInfo("vgId:%d start to generate new meta", TD_VID(pMeta->pVnode));
×
283

284
  // Open a new meta for organization
UNCOV
285
  int32_t code = metaOpenImpl(pMeta->pVnode, &pNewMeta, VNODE_META_TMP_DIR, false);
×
286
  if (code) {
×
287
    return code;
×
288
  }
289

UNCOV
290
  code = metaBegin(pNewMeta, META_BEGIN_HEAP_NIL);
×
UNCOV
291
  if (code) {
×
292
    return code;
×
293
  }
294

295
  // i == 0, scan super table
296
  // i == 1, scan normal table and child table
UNCOV
297
  for (int i = 0; i < 2; i++) {
×
UNCOV
298
    TBC    *uidCursor = NULL;
×
299
    int32_t counter = 0;
×
300

UNCOV
301
    code = tdbTbcOpen(pMeta->pUidIdx, &uidCursor, NULL);
×
UNCOV
302
    if (code) {
×
UNCOV
303
      metaError("vgId:%d failed to open uid index cursor, reason:%s", TD_VID(pVnode), tstrerror(code));
×
UNCOV
304
      return code;
×
305
    }
306

UNCOV
307
    code = tdbTbcMoveToFirst(uidCursor);
×
UNCOV
308
    if (code) {
×
309
      metaError("vgId:%d failed to move to first, reason:%s", TD_VID(pVnode), tstrerror(code));
×
310
      tdbTbcClose(uidCursor);
×
311
      return code;
×
312
    }
313

314
    for (;;) {
×
315
      const void *pKey;
316
      int         kLen;
317
      const void *pVal;
318
      int         vLen;
319

UNCOV
320
      if (tdbTbcGet(uidCursor, &pKey, &kLen, &pVal, &vLen) < 0) {
×
UNCOV
321
        break;
×
322
      }
323

324
      tb_uid_t    uid = *(tb_uid_t *)pKey;
×
325
      SUidIdxVal *pUidIdxVal = (SUidIdxVal *)pVal;
×
326
      if ((i == 0 && (pUidIdxVal->suid && pUidIdxVal->suid == uid))          // super table
×
327
          || (i == 1 && (pUidIdxVal->suid == 0 || pUidIdxVal->suid != uid))  // normal table and child table
×
328
      ) {
UNCOV
329
        counter++;
×
UNCOV
330
        if (i == 0) {
×
331
          metaInfo("vgId:%d counter:%d new meta handle %s table uid:%" PRId64, TD_VID(pVnode), counter, "super", uid);
×
332
        } else {
333
          metaInfo("vgId:%d counter:%d new meta handle %s table uid:%" PRId64, TD_VID(pVnode), counter,
×
334
                   pUidIdxVal->suid == 0 ? "normal" : "child", uid);
335
        }
336

337
        // fetch table entry
UNCOV
338
        void *value = NULL;
×
339
        int   valueSize = 0;
×
340
        if (tdbTbGet(pMeta->pTbDb,
×
UNCOV
341
                     &(STbDbKey){
×
UNCOV
342
                         .version = pUidIdxVal->version,
×
343
                         .uid = uid,
344
                     },
345
                     sizeof(uid), &value, &valueSize) == 0) {
UNCOV
346
          SDecoder   dc = {0};
×
UNCOV
347
          SMetaEntry me = {0};
×
348
          tDecoderInit(&dc, value, valueSize);
×
349
          if (metaDecodeEntry(&dc, &me) == 0) {
×
350
            if (me.type == TSDB_CHILD_TABLE &&
×
351
                tdbTbGet(pMeta->pUidIdx, &me.ctbEntry.suid, sizeof(me.ctbEntry.suid), NULL, NULL) != 0) {
×
UNCOV
352
              metaError("vgId:%d failed to get super table uid:%" PRId64 " for child table uid:%" PRId64,
×
353
                        TD_VID(pVnode), me.ctbEntry.suid, uid);
UNCOV
354
            } else if (metaHandleEntry2(pNewMeta, &me) != 0) {
×
355
              metaError("vgId:%d failed to handle entry, uid:%" PRId64, TD_VID(pVnode), uid);
×
356
            }
357
          }
358
          tDecoderClear(&dc);
×
359
        }
360
        tdbFree(value);
×
361
      }
362

UNCOV
363
      code = tdbTbcMoveToNext(uidCursor);
×
364
      if (code) {
×
365
        metaError("vgId:%d failed to move to next, reason:%s", TD_VID(pVnode), tstrerror(code));
×
366
        return code;
×
367
      }
368
    }
369

370
    tdbTbcClose(uidCursor);
×
371
  }
372

373
  code = metaCommit(pNewMeta, pNewMeta->txn);
×
374
  if (code) {
×
UNCOV
375
    metaError("vgId:%d failed to commit, reason:%s", TD_VID(pVnode), tstrerror(code));
×
UNCOV
376
    return code;
×
377
  }
378

379
  code = metaFinishCommit(pNewMeta, pNewMeta->txn);
×
UNCOV
380
  if (code) {
×
381
    metaError("vgId:%d failed to finish commit, reason:%s", TD_VID(pVnode), tstrerror(code));
×
382
    return code;
×
383
  }
384

385
  if ((code = metaBegin(pNewMeta, META_BEGIN_HEAP_NIL)) != 0) {
×
386
    metaError("vgId:%d failed to begin new meta, reason:%s", TD_VID(pVnode), tstrerror(code));
×
387
  }
388
  metaClose(&pNewMeta);
×
UNCOV
389
  metaInfo("vgId:%d finish to generate new meta", TD_VID(pVnode));
×
390

391
  // Commit the new metadata
392
  char metaDir[TSDB_FILENAME_LEN] = {0};
×
393
  char metaTempDir[TSDB_FILENAME_LEN] = {0};
×
394
  char metaBackupDir[TSDB_FILENAME_LEN] = {0};
×
395

UNCOV
396
  vnodeGetMetaPath(pVnode, metaDir, VNODE_META_DIR);
×
397
  vnodeGetMetaPath(pVnode, metaTempDir, VNODE_META_TMP_DIR);
×
398
  vnodeGetMetaPath(pVnode, metaBackupDir, VNODE_META_BACKUP_DIR);
×
399

400
  metaClose(ppMeta);
×
UNCOV
401
  if (taosRenameFile(metaDir, metaBackupDir) != 0) {
×
UNCOV
402
    metaError("vgId:%d failed to rename old meta to backup, reason:%s", TD_VID(pVnode), tstrerror(terrno));
×
403
    return terrno;
×
404
  }
405

406
  // rename the new meta to old meta
UNCOV
407
  if (taosRenameFile(metaTempDir, metaDir) != 0) {
×
UNCOV
408
    metaError("vgId:%d failed to rename new meta to old meta, reason:%s", TD_VID(pVnode), tstrerror(terrno));
×
UNCOV
409
    return terrno;
×
410
  }
411

UNCOV
412
  code = metaOpenImpl(pVnode, ppMeta, VNODE_META_DIR, false);
×
UNCOV
413
  if (code) {
×
UNCOV
414
    metaError("vgId:%d failed to open new meta, reason:%s", TD_VID(pVnode), tstrerror(code));
×
UNCOV
415
    return code;
×
416
  }
417

UNCOV
418
  metaInfo("vgId:%d successfully opened new meta", TD_VID(pVnode));
×
419

UNCOV
420
  return 0;
×
421
}
422

423
int32_t metaOpen(SVnode *pVnode, SMeta **ppMeta, int8_t rollback) {
20✔
424
  int32_t code = TSDB_CODE_SUCCESS;
20✔
425
  char    metaDir[TSDB_FILENAME_LEN] = {0};
20✔
426
  char    metaBackupDir[TSDB_FILENAME_LEN] = {0};
20✔
427
  char    metaTempDir[TSDB_FILENAME_LEN] = {0};
20✔
428

429
  vnodeGetMetaPath(pVnode, VNODE_META_DIR, metaDir);
20✔
430
  vnodeGetMetaPath(pVnode, VNODE_META_BACKUP_DIR, metaBackupDir);
20✔
431
  vnodeGetMetaPath(pVnode, VNODE_META_TMP_DIR, metaTempDir);
20✔
432

433
  bool metaExists = taosCheckExistFile(metaDir);
20✔
434
  bool metaBackupExists = taosCheckExistFile(metaBackupDir);
20✔
435
  bool metaTempExists = taosCheckExistFile(metaTempDir);
20✔
436

437
  if ((!metaBackupExists && !metaExists && metaTempExists)     //
20!
438
      || (metaBackupExists && !metaExists && !metaTempExists)  //
20!
439
      || (metaBackupExists && metaExists && metaTempExists)    //
20!
440
  ) {
UNCOV
441
    metaError("vgId:%d, invalid meta state, please check!", TD_VID(pVnode));
×
UNCOV
442
    TAOS_RETURN(TSDB_CODE_FAILED);
×
443
  } else if (!metaBackupExists && metaExists && metaTempExists) {
20!
444
    taosRemoveDir(metaTempDir);
×
445
  } else if (metaBackupExists && !metaExists && metaTempExists) {
20!
UNCOV
446
    code = taosRenameFile(metaTempDir, metaDir);
×
UNCOV
447
    if (code) {
×
UNCOV
448
      metaError("vgId:%d, %s failed at %s:%d since %s", TD_VID(pVnode), __func__, __FILE__, __LINE__, tstrerror(code));
×
449
      TAOS_RETURN(code);
×
450
    }
451
    taosRemoveDir(metaBackupDir);
×
452
  } else if (metaBackupExists && metaExists && !metaTempExists) {
20!
UNCOV
453
    taosRemoveDir(metaBackupDir);
×
454
  }
455

456
  // Do open meta
457
  code = metaOpenImpl(pVnode, ppMeta, VNODE_META_DIR, rollback);
20✔
458
  if (code) {
20!
UNCOV
459
    metaError("vgId:%d, %s failed at %s:%d since %s", TD_VID(pVnode), __func__, __FILE__, __LINE__, tstrerror(code));
×
UNCOV
460
    TAOS_RETURN(code);
×
461
  }
462

463
  if (generateNewMeta) {
20!
UNCOV
464
    code = metaGenerateNewMeta(ppMeta);
×
465
    if (code) {
×
466
      metaError("vgId:%d, %s failed at %s:%d since %s", TD_VID(pVnode), __func__, __FILE__, __LINE__, tstrerror(code));
×
UNCOV
467
      TAOS_RETURN(code);
×
468
    }
469
  }
470

471
  return TSDB_CODE_SUCCESS;
20✔
472
}
473

474
int32_t metaUpgrade(SVnode *pVnode, SMeta **ppMeta) {
20✔
475
  int32_t code = TSDB_CODE_SUCCESS;
20✔
476
  int32_t lino;
477
  SMeta  *pMeta = *ppMeta;
20✔
478

479
  if (ttlMgrNeedUpgrade(pMeta->pEnv)) {
20!
UNCOV
480
    code = metaBegin(pMeta, META_BEGIN_HEAP_OS);
×
UNCOV
481
    TSDB_CHECK_CODE(code, lino, _exit);
×
482

UNCOV
483
    code = ttlMgrUpgrade(pMeta->pTtlMgr, pMeta);
×
UNCOV
484
    TSDB_CHECK_CODE(code, lino, _exit);
×
485

UNCOV
486
    code = metaCommit(pMeta, pMeta->txn);
×
UNCOV
487
    TSDB_CHECK_CODE(code, lino, _exit);
×
488
  }
489

490
_exit:
20✔
491
  if (code) {
20!
492
    metaError("vgId:%d %s failed at %s:%d since %s", TD_VID(pVnode), __func__, __FILE__, __LINE__, tstrerror(code));
×
UNCOV
493
    metaCleanup(ppMeta);
×
494
  }
495
  return code;
20✔
496
}
497

498
void metaClose(SMeta **ppMeta) {
20✔
499
  metaCleanup(ppMeta);
20✔
500
  return;
20✔
501
}
502

503
int metaAlterCache(SMeta *pMeta, int32_t nPage) {
×
UNCOV
504
  int32_t code = 0;
×
UNCOV
505
  metaWLock(pMeta);
×
UNCOV
506
  code = tdbAlter(pMeta->pEnv, nPage);
×
UNCOV
507
  metaULock(pMeta);
×
508

UNCOV
509
  if (code) {
×
510
    metaError("vgId:%d %s failed since %s", TD_VID(pMeta->pVnode), __func__, tstrerror(code));
×
511
  }
UNCOV
512
  return code;
×
513
}
514

515
void metaRLock(SMeta *pMeta) {
93✔
516
  metaTrace("meta rlock %p", &pMeta->lock);
93!
517
  if (taosThreadRwlockRdlock(&pMeta->lock) != 0) {
93!
UNCOV
518
    metaError("vgId:%d failed to lock %p", TD_VID(pMeta->pVnode), &pMeta->lock);
×
519
  }
520
}
93✔
521

522
void metaWLock(SMeta *pMeta) {
48✔
523
  metaTrace("meta wlock %p", &pMeta->lock);
48!
524
  if (taosThreadRwlockWrlock(&pMeta->lock) != 0) {
48!
UNCOV
525
    metaError("vgId:%d failed to lock %p", TD_VID(pMeta->pVnode), &pMeta->lock);
×
526
  }
527
}
48✔
528

529
void metaULock(SMeta *pMeta) {
141✔
530
  metaTrace("meta ulock %p", &pMeta->lock);
141!
531
  if (taosThreadRwlockUnlock(&pMeta->lock) != 0) {
141!
UNCOV
532
    metaError("vgId:%d failed to unlock %p", TD_VID(pMeta->pVnode), &pMeta->lock);
×
533
  }
534
}
141✔
535

536
static void metaCleanup(SMeta **ppMeta) {
20✔
537
  SMeta *pMeta = *ppMeta;
20✔
538
  if (pMeta) {
20!
539
    metaInfo("vgId:%d meta clean up, path:%s", TD_VID(pMeta->pVnode), pMeta->path);
20!
540
    if (pMeta->pEnv) metaAbort(pMeta);
20!
541
    if (pMeta->pCache) metaCacheClose(pMeta);
20!
542
#ifdef BUILD_NO_CALL
543
    if (pMeta->pIdx) metaCloseIdx(pMeta);
544
#endif
545
    if (pMeta->pStreamDb) tdbTbClose(pMeta->pStreamDb);
20!
546
    if (pMeta->pNcolIdx) tdbTbClose(pMeta->pNcolIdx);
20!
547
    if (pMeta->pBtimeIdx) tdbTbClose(pMeta->pBtimeIdx);
20!
548
    if (pMeta->pSmaIdx) tdbTbClose(pMeta->pSmaIdx);
20!
549
    if (pMeta->pTtlMgr) ttlMgrClose(pMeta->pTtlMgr);
20!
550
    if (pMeta->pTagIvtIdx) indexClose(pMeta->pTagIvtIdx);
20!
551
    if (pMeta->pTagIdx) tdbTbClose(pMeta->pTagIdx);
20!
552
    if (pMeta->pCtbIdx) tdbTbClose(pMeta->pCtbIdx);
20!
553
    if (pMeta->pSuidIdx) tdbTbClose(pMeta->pSuidIdx);
20!
554
    if (pMeta->pNameIdx) tdbTbClose(pMeta->pNameIdx);
20!
555
    if (pMeta->pUidIdx) tdbTbClose(pMeta->pUidIdx);
20!
556
    if (pMeta->pSkmDb) tdbTbClose(pMeta->pSkmDb);
20!
557
    if (pMeta->pTbDb) tdbTbClose(pMeta->pTbDb);
20!
558
    if (pMeta->pEnv) tdbClose(pMeta->pEnv);
20!
559
    metaDestroyLock(pMeta);
20✔
560

561
    taosMemoryFreeClear(*ppMeta);
20!
562
  }
563
}
20✔
564

565
static int tbDbKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2) {
112✔
566
  STbDbKey *pTbDbKey1 = (STbDbKey *)pKey1;
112✔
567
  STbDbKey *pTbDbKey2 = (STbDbKey *)pKey2;
112✔
568

569
  TDB_KEY_ALIGN(pTbDbKey1, pTbDbKey2, STbDbKey);
570

571
  if (pTbDbKey1->version > pTbDbKey2->version) {
112✔
572
    return 1;
60✔
573
  } else if (pTbDbKey1->version < pTbDbKey2->version) {
52!
UNCOV
574
    return -1;
×
575
  }
576

577
  if (pTbDbKey1->uid > pTbDbKey2->uid) {
52!
UNCOV
578
    return 1;
×
579
  } else if (pTbDbKey1->uid < pTbDbKey2->uid) {
52!
UNCOV
580
    return -1;
×
581
  }
582

583
  return 0;
52✔
584
}
585

586
static int skmDbKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2) {
24✔
587
  SSkmDbKey *pSkmDbKey1 = (SSkmDbKey *)pKey1;
24✔
588
  SSkmDbKey *pSkmDbKey2 = (SSkmDbKey *)pKey2;
24✔
589

590
  TDB_KEY_ALIGN(pSkmDbKey1, pSkmDbKey2, SSkmDbKey);
591

592
  if (pSkmDbKey1->uid > pSkmDbKey2->uid) {
24!
UNCOV
593
    return 1;
×
594
  } else if (pSkmDbKey1->uid < pSkmDbKey2->uid) {
24!
UNCOV
595
    return -1;
×
596
  }
597

598
  if (pSkmDbKey1->sver > pSkmDbKey2->sver) {
24✔
599
    return 1;
20✔
600
  } else if (pSkmDbKey1->sver < pSkmDbKey2->sver) {
4!
UNCOV
601
    return -1;
×
602
  }
603

604
  return 0;
4✔
605
}
606

607
static int uidIdxKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2) {
85✔
608
  tb_uid_t uid1 = taosGetInt64Aligned((int64_t*)pKey1);
85✔
609
  tb_uid_t uid2 = taosGetInt64Aligned((int64_t*)pKey2);
85✔
610

611
  if (uid1 > uid2) {
85!
UNCOV
612
    return 1;
×
613
  } else if (uid1 < uid2) {
85✔
614
    return -1;
9✔
615
  }
616

617
  return 0;
76✔
618
}
619

UNCOV
620
static int ctbIdxKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2) {
×
UNCOV
621
  SCtbIdxKey *pCtbIdxKey1 = (SCtbIdxKey *)pKey1;
×
UNCOV
622
  SCtbIdxKey *pCtbIdxKey2 = (SCtbIdxKey *)pKey2;
×
623

624
  TDB_KEY_ALIGN(pCtbIdxKey1, pCtbIdxKey2, SCtbIdxKey);
625

UNCOV
626
  if (pCtbIdxKey1->suid > pCtbIdxKey2->suid) {
×
UNCOV
627
    return 1;
×
UNCOV
628
  } else if (pCtbIdxKey1->suid < pCtbIdxKey2->suid) {
×
UNCOV
629
    return -1;
×
630
  }
631

UNCOV
632
  if (pCtbIdxKey1->uid > pCtbIdxKey2->uid) {
×
UNCOV
633
    return 1;
×
UNCOV
634
  } else if (pCtbIdxKey1->uid < pCtbIdxKey2->uid) {
×
UNCOV
635
    return -1;
×
636
  }
637

UNCOV
638
  return 0;
×
639
}
640

641
int tagIdxKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2) {
×
642
  STagIdxKey *pTagIdxKey1 = (STagIdxKey *)pKey1;
×
UNCOV
643
  STagIdxKey *pTagIdxKey2 = (STagIdxKey *)pKey2;
×
UNCOV
644
  tb_uid_t    uid1 = 0, uid2 = 0;
×
645
  int         c;
646

647
  TDB_KEY_ALIGN(pTagIdxKey1, pTagIdxKey2, STagIdxKey);
648

649
  // compare suid
UNCOV
650
  if (pTagIdxKey1->suid > pTagIdxKey2->suid) {
×
UNCOV
651
    return 1;
×
UNCOV
652
  } else if (pTagIdxKey1->suid < pTagIdxKey2->suid) {
×
UNCOV
653
    return -1;
×
654
  }
655

656
  // compare column id
UNCOV
657
  if (pTagIdxKey1->cid > pTagIdxKey2->cid) {
×
UNCOV
658
    return 1;
×
UNCOV
659
  } else if (pTagIdxKey1->cid < pTagIdxKey2->cid) {
×
UNCOV
660
    return -1;
×
661
  }
662

UNCOV
663
  if (pTagIdxKey1->type != pTagIdxKey2->type) {
×
UNCOV
664
    metaError("meta/open: incorrect tag idx type.");
×
UNCOV
665
    return TSDB_CODE_FAILED;
×
666
  }
667

668
  // check NULL, NULL is always the smallest
UNCOV
669
  if (pTagIdxKey1->isNull && !pTagIdxKey2->isNull) {
×
UNCOV
670
    return -1;
×
UNCOV
671
  } else if (!pTagIdxKey1->isNull && pTagIdxKey2->isNull) {
×
UNCOV
672
    return 1;
×
UNCOV
673
  } else if (!pTagIdxKey1->isNull && !pTagIdxKey2->isNull) {
×
674
    // all not NULL, compr tag vals
UNCOV
675
    __compar_fn_t func = getComparFunc(pTagIdxKey1->type, 0);
×
UNCOV
676
    if (func == NULL) {
×
UNCOV
677
      metaError("meta/open: %s", terrstr());
×
UNCOV
678
      return TSDB_CODE_FAILED;
×
679
    }
UNCOV
680
    c = func(pTagIdxKey1->data, pTagIdxKey2->data);
×
UNCOV
681
    if (c) return c;
×
682
  }
683

684
  // both null or tag values are equal, then continue to compare uids
UNCOV
685
  if (IS_VAR_DATA_TYPE(pTagIdxKey1->type)) {
×
UNCOV
686
    uid1 = *(tb_uid_t *)(pTagIdxKey1->data + varDataTLen(pTagIdxKey1->data));
×
UNCOV
687
    uid2 = *(tb_uid_t *)(pTagIdxKey2->data + varDataTLen(pTagIdxKey2->data));
×
688
  } else {
UNCOV
689
    uid1 = *(tb_uid_t *)(pTagIdxKey1->data + tDataTypes[pTagIdxKey1->type].bytes);
×
UNCOV
690
    uid2 = *(tb_uid_t *)(pTagIdxKey2->data + tDataTypes[pTagIdxKey2->type].bytes);
×
691
  }
692

693
  // compare uid
UNCOV
694
  if (uid1 < uid2) {
×
UNCOV
695
    return -1;
×
UNCOV
696
  } else if (uid1 > uid2) {
×
UNCOV
697
    return 1;
×
698
  } else {
UNCOV
699
    return 0;
×
700
  }
701

702
  return 0;
703
}
704

705
static int btimeIdxCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2) {
×
706
  SBtimeIdxKey *pBtimeIdxKey1 = (SBtimeIdxKey *)pKey1;
×
707
  SBtimeIdxKey *pBtimeIdxKey2 = (SBtimeIdxKey *)pKey2;
×
708

709
  TDB_KEY_ALIGN(pBtimeIdxKey1, pBtimeIdxKey2, SBtimeIdxKey);
710

711
  if (pBtimeIdxKey1->btime > pBtimeIdxKey2->btime) {
×
712
    return 1;
×
713
  } else if (pBtimeIdxKey1->btime < pBtimeIdxKey2->btime) {
×
UNCOV
714
    return -1;
×
715
  }
716

UNCOV
717
  if (pBtimeIdxKey1->uid > pBtimeIdxKey2->uid) {
×
UNCOV
718
    return 1;
×
719
  } else if (pBtimeIdxKey1->uid < pBtimeIdxKey2->uid) {
×
720
    return -1;
×
721
  }
722

723
  return 0;
×
724
}
725

726
static int ncolIdxCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2) {
×
UNCOV
727
  SNcolIdxKey *pNcolIdxKey1 = (SNcolIdxKey *)pKey1;
×
UNCOV
728
  SNcolIdxKey *pNcolIdxKey2 = (SNcolIdxKey *)pKey2;
×
729

730
  TDB_KEY_ALIGN(pNcolIdxKey1, pNcolIdxKey2, SNcolIdxKey);
731

732
  if (pNcolIdxKey1->ncol > pNcolIdxKey2->ncol) {
×
UNCOV
733
    return 1;
×
UNCOV
734
  } else if (pNcolIdxKey1->ncol < pNcolIdxKey2->ncol) {
×
735
    return -1;
×
736
  }
737

738
  if (pNcolIdxKey1->uid > pNcolIdxKey2->uid) {
×
739
    return 1;
×
740
  } else if (pNcolIdxKey1->uid < pNcolIdxKey2->uid) {
×
UNCOV
741
    return -1;
×
742
  }
743

744
  return 0;
×
745
}
746

UNCOV
747
static int smaIdxKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2) {
×
748
  SSmaIdxKey *pSmaIdxKey1 = (SSmaIdxKey *)pKey1;
×
UNCOV
749
  SSmaIdxKey *pSmaIdxKey2 = (SSmaIdxKey *)pKey2;
×
750

751
  TDB_KEY_ALIGN(pSmaIdxKey1, pSmaIdxKey2, SSmaIdxKey);
752

UNCOV
753
  if (pSmaIdxKey1->uid > pSmaIdxKey2->uid) {
×
UNCOV
754
    return 1;
×
UNCOV
755
  } else if (pSmaIdxKey1->uid < pSmaIdxKey2->uid) {
×
UNCOV
756
    return -1;
×
757
  }
758

UNCOV
759
  if (pSmaIdxKey1->smaUid > pSmaIdxKey2->smaUid) {
×
UNCOV
760
    return 1;
×
UNCOV
761
  } else if (pSmaIdxKey1->smaUid < pSmaIdxKey2->smaUid) {
×
UNCOV
762
    return -1;
×
763
  }
764

UNCOV
765
  return 0;
×
766
}
767

UNCOV
768
static int taskIdxKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2) {
×
UNCOV
769
  int32_t uid1 = *(int32_t *)pKey1;
×
UNCOV
770
  int32_t uid2 = *(int32_t *)pKey2;
×
771

UNCOV
772
  if (uid1 > uid2) {
×
UNCOV
773
    return 1;
×
UNCOV
774
  } else if (uid1 < uid2) {
×
UNCOV
775
    return -1;
×
776
  }
777

UNCOV
778
  return 0;
×
779
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc