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

taosdata / TDengine / #4914

06 Jan 2026 01:30AM UTC coverage: 64.876% (-0.008%) from 64.884%
#4914

push

travis-ci

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

180 of 319 new or added lines in 14 files covered. (56.43%)

3475 existing lines in 124 files now uncovered.

194993 of 300563 relevant lines covered (64.88%)

116239151.85 hits per line

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

83.33
/source/dnode/vnode/src/tsdb/tsdbFS2.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 "cos.h"
17
#include "tencrypt.h"
18
#include "tsdbFS2.h"
19
#include "tsdbUpgrade.h"
20
#include "vnd.h"
21

22
#define BLOCK_COMMIT_FACTOR 3
23

24
typedef struct STFileHashEntry {
25
  struct STFileHashEntry *next;
26
  char                    fname[TSDB_FILENAME_LEN];
27
} STFileHashEntry;
28

29
typedef struct {
30
  int32_t           numFile;
31
  int32_t           numBucket;
32
  STFileHashEntry **buckets;
33
} STFileHash;
34

35
static const char *gCurrentFname[] = {
36
    [TSDB_FCURRENT] = "current.json",
37
    [TSDB_FCURRENT_C] = "current.c.json",
38
    [TSDB_FCURRENT_M] = "current.m.json",
39
};
40

41
static int32_t create_fs(STsdb *pTsdb, STFileSystem **fs) {
3,722,823✔
42
  fs[0] = taosMemoryCalloc(1, sizeof(*fs[0]));
3,722,823✔
43
  if (fs[0] == NULL) {
3,734,122✔
44
    return terrno;
×
45
  }
46

47
  fs[0]->tsdb = pTsdb;
3,734,831✔
48
  int32_t code = tsem_init(&fs[0]->canEdit, 0, 1);
3,734,746✔
49
  if (code) {
3,732,973✔
50
    taosMemoryFree(fs[0]);
×
51
    return code;
×
52
  }
53

54
  fs[0]->fsstate = TSDB_FS_STATE_NORMAL;
3,732,973✔
55
  fs[0]->neid = 0;
3,732,837✔
56
  TARRAY2_INIT(fs[0]->fSetArr);
3,733,856✔
57
  TARRAY2_INIT(fs[0]->fSetArrTmp);
3,732,973✔
58

59
  return 0;
3,732,020✔
60
}
61

62
static void destroy_fs(STFileSystem **fs) {
3,735,037✔
63
  if (fs[0] == NULL) return;
3,735,037✔
64

65
  TARRAY2_DESTROY(fs[0]->fSetArr, NULL);
3,735,037✔
66
  TARRAY2_DESTROY(fs[0]->fSetArrTmp, NULL);
3,734,443✔
67
  if (tsem_destroy(&fs[0]->canEdit) != 0) {
3,735,037✔
68
    tsdbError("failed to destroy semaphore");
×
69
  }
70
  taosMemoryFree(fs[0]);
3,733,842✔
71
  fs[0] = NULL;
3,735,037✔
72
}
73

74
void current_fname(STsdb *pTsdb, char *fname, EFCurrentT ftype) {
23,861,763✔
75
  int32_t offset = 0;
23,861,763✔
76

77
  vnodeGetPrimaryPath(pTsdb->pVnode, false, fname, TSDB_FILENAME_LEN);
23,861,763✔
78
  offset = strlen(fname);
23,860,176✔
79
  snprintf(fname + offset, TSDB_FILENAME_LEN - offset - 1, "%s%s%s%s", TD_DIRSEP, pTsdb->name, TD_DIRSEP,
23,862,579✔
80
           gCurrentFname[ftype]);
23,857,865✔
81
}
23,862,626✔
82

83
static int32_t save_json(const cJSON *json, const char *fname) {
6,545,099✔
84
  int32_t   code = 0;
6,545,099✔
85
  int32_t   lino;
86
  char     *data = NULL;
6,545,099✔
87

88
  data = cJSON_PrintUnformatted(json);
6,545,099✔
89
  if (data == NULL) {
6,545,666✔
90
    TSDB_CHECK_CODE(code = TSDB_CODE_OUT_OF_MEMORY, lino, _exit);
×
91
  }
92

93
  int32_t len = strlen(data);
6,545,666✔
94
  
95
  // Use encrypted write if tsCfgKey is enabled
96
  code = taosWriteCfgFile(fname, data, len);
6,545,666✔
97
  if (code != 0) {
6,545,401✔
98
    TSDB_CHECK_CODE(code, lino, _exit);
×
99
  }
100

101
_exit:
6,545,401✔
102
  if (code) {
6,545,401✔
103
    tsdbError("%s failed at %s:%d since %s", __func__, fname, __LINE__, tstrerror(code));
×
104
  }
105
  taosMemoryFree(data);
6,545,064✔
106
  return code;
6,544,139✔
107
}
108

109
static int32_t load_json(const char *fname, cJSON **json) {
1,057,196✔
110
  int32_t code = 0;
1,057,196✔
111
  int32_t lino;
112
  char   *data = NULL;
1,057,196✔
113
  int32_t dataLen = 0;
1,057,196✔
114

115
  // Use taosReadCfgFile for automatic decryption support (returns null-terminated string)
116
  code = taosReadCfgFile(fname, &data, &dataLen);
1,057,196✔
117
  if (code != 0) {
1,056,444✔
118
    TSDB_CHECK_CODE(code, lino, _exit);
×
119
  }
120

121
  json[0] = cJSON_Parse(data);
1,056,444✔
122
  if (json[0] == NULL) {
1,057,196✔
123
    TSDB_CHECK_CODE(code = TSDB_CODE_FILE_CORRUPTED, lino, _exit);
×
124
  }
125

126
_exit:
1,057,196✔
127
  if (code) {
1,056,519✔
128
    tsdbError("%s failed at %s:%d since %s", __func__, fname, __LINE__, tstrerror(code));
×
129
    json[0] = NULL;
×
130
  }
131
  taosMemoryFree(data);
1,056,519✔
132
  return code;
1,057,196✔
133
}
134

135
int32_t save_fs(const TFileSetArray *arr, const char *fname) {
6,544,557✔
136
  int32_t code = 0;
6,544,557✔
137
  int32_t lino = 0;
6,544,557✔
138

139
  cJSON *json = cJSON_CreateObject();
6,544,557✔
140
  if (json == NULL) {
6,545,666✔
141
    TSDB_CHECK_CODE(code = TSDB_CODE_OUT_OF_MEMORY, lino, _exit);
×
142
  }
143

144
  // fmtv
145
  if (cJSON_AddNumberToObject(json, "fmtv", 1) == NULL) {
6,545,666✔
146
    TSDB_CHECK_CODE(code = TSDB_CODE_OUT_OF_MEMORY, lino, _exit);
×
147
  }
148

149
  // fset
150
  cJSON *ajson = cJSON_AddArrayToObject(json, "fset");
6,544,612✔
151
  if (!ajson) {
6,545,124✔
152
    TSDB_CHECK_CODE(code = TSDB_CODE_OUT_OF_MEMORY, lino, _exit);
×
153
  }
154
  const STFileSet *fset;
155
  TARRAY2_FOREACH(arr, fset) {
25,226,634✔
156
    cJSON *item = cJSON_CreateObject();
18,679,933✔
157
    if (!item) {
18,681,945✔
158
      TSDB_CHECK_CODE(code = TSDB_CODE_OUT_OF_MEMORY, lino, _exit);
×
159
    }
160
    (void)cJSON_AddItemToArray(ajson, item);
18,681,945✔
161

162
    code = tsdbTFileSetToJson(fset, item);
18,681,945✔
163
    TSDB_CHECK_CODE(code, lino, _exit);
18,681,510✔
164
  }
165

166
  code = save_json(json, fname);
6,543,826✔
167
  TSDB_CHECK_CODE(code, lino, _exit);
6,544,786✔
168

169
_exit:
6,544,786✔
170
  if (code) {
6,544,786✔
171
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
172
  }
173
  cJSON_Delete(json);
6,544,786✔
174
  return code;
6,545,126✔
175
}
176

177
static int32_t load_fs(STsdb *pTsdb, const char *fname, TFileSetArray *arr) {
1,057,036✔
178
  int32_t code = 0;
1,057,036✔
179
  int32_t lino = 0;
1,057,036✔
180

181
  TARRAY2_CLEAR(arr, tsdbTFileSetClear);
1,057,036✔
182

183
  // load json
184
  cJSON *json = NULL;
1,057,196✔
185
  code = load_json(fname, &json);
1,057,196✔
186
  TSDB_CHECK_CODE(code, lino, _exit);
1,057,196✔
187

188
  // parse json
189
  const cJSON *item1;
190

191
  /* fmtv */
192
  item1 = cJSON_GetObjectItem(json, "fmtv");
1,057,196✔
193
  if (cJSON_IsNumber(item1)) {
1,057,196✔
194
    if (item1->valuedouble != 1) {
1,057,196✔
195
      TSDB_CHECK_CODE(code = TSDB_CODE_FILE_CORRUPTED, lino, _exit);
×
196
    }
197
  } else {
198
    TSDB_CHECK_CODE(code = TSDB_CODE_FILE_CORRUPTED, lino, _exit);
×
199
  }
200

201
  /* fset */
202
  item1 = cJSON_GetObjectItem(json, "fset");
1,057,196✔
203
  if (cJSON_IsArray(item1)) {
1,056,519✔
204
    const cJSON *item2;
205
    cJSON_ArrayForEach(item2, item1) {
1,705,015✔
206
      STFileSet *fset;
648,569✔
207
      code = tsdbJsonToTFileSet(pTsdb, item2, &fset);
648,659✔
208
      TSDB_CHECK_CODE(code, lino, _exit);
648,659✔
209

210
      code = TARRAY2_APPEND(arr, fset);
648,659✔
211
      TSDB_CHECK_CODE(code, lino, _exit);
648,659✔
212
    }
213
    TARRAY2_SORT(arr, tsdbTFileSetCmprFn);
1,057,196✔
214
  } else {
215
    code = TSDB_CODE_FILE_CORRUPTED;
×
216
    TSDB_CHECK_CODE(code, lino, _exit);
×
217
  }
218

219
_exit:
1,057,120✔
220
  if (code) {
1,056,356✔
221
    tsdbError("%s failed at %s:%d since %s, fname:%s", __func__, __FILE__, lino, tstrerror(code), fname);
×
222
  }
223
  if (json) {
1,056,356✔
224
    cJSON_Delete(json);
1,056,356✔
225
  }
226
  return code;
1,057,196✔
227
}
228

229
static int32_t apply_commit(STFileSystem *fs) {
3,867,916✔
230
  int32_t        code = 0;
3,867,916✔
231
  int32_t        lino;
232
  TFileSetArray *fsetArray1 = fs->fSetArr;
3,867,916✔
233
  TFileSetArray *fsetArray2 = fs->fSetArrTmp;
3,867,916✔
234
  int32_t        i1 = 0, i2 = 0;
3,867,916✔
235

236
  while (i1 < TARRAY2_SIZE(fsetArray1) || i2 < TARRAY2_SIZE(fsetArray2)) {
22,624,429✔
237
    STFileSet *fset1 = i1 < TARRAY2_SIZE(fsetArray1) ? TARRAY2_GET(fsetArray1, i1) : NULL;
18,756,488✔
238
    STFileSet *fset2 = i2 < TARRAY2_SIZE(fsetArray2) ? TARRAY2_GET(fsetArray2, i2) : NULL;
18,757,174✔
239

240
    if (fset1 && fset2) {
18,757,174✔
241
      if (fset1->fid < fset2->fid) {
4,585,035✔
242
        // delete fset1
243
        tsdbTFileSetRemove(fset1);
72,367✔
244
        i1++;
72,367✔
245
      } else if (fset1->fid > fset2->fid) {
4,512,668✔
246
        // create new file set with fid of fset2->fid
247
        code = tsdbTFileSetInitCopy(fs->tsdb, fset2, &fset1);
8,481✔
248
        TSDB_CHECK_CODE(code, lino, _exit);
8,481✔
249
        code = TARRAY2_SORT_INSERT(fsetArray1, fset1, tsdbTFileSetCmprFn);
8,481✔
250
        TSDB_CHECK_CODE(code, lino, _exit);
8,481✔
251
        i1++;
8,481✔
252
        i2++;
8,481✔
253
      } else {
254
        // edit
255
        code = tsdbTFileSetApplyEdit(fs->tsdb, fset2, fset1);
4,504,187✔
256
        TSDB_CHECK_CODE(code, lino, _exit);
4,504,187✔
257
        i1++;
4,504,187✔
258
        i2++;
4,504,187✔
259
      }
260
    } else if (fset1) {
14,172,139✔
261
      // delete fset1
262
      tsdbTFileSetRemove(fset1);
2,964✔
263
      i1++;
2,964✔
264
    } else {
265
      // create new file set with fid of fset2->fid
266
      code = tsdbTFileSetInitCopy(fs->tsdb, fset2, &fset1);
14,169,175✔
267
      TSDB_CHECK_CODE(code, lino, _exit);
14,168,107✔
268
      code = TARRAY2_SORT_INSERT(fsetArray1, fset1, tsdbTFileSetCmprFn);
14,167,639✔
269
      TSDB_CHECK_CODE(code, lino, _exit);
14,167,639✔
270
      i1++;
14,167,639✔
271
      i2++;
14,167,639✔
272
    }
273
  }
274

275
_exit:
3,867,228✔
276
  if (code) {
3,867,035✔
277
    TSDB_ERROR_LOG(TD_VID(fs->tsdb->pVnode), lino, code);
×
278
  }
279
  return code;
3,867,113✔
280
}
281

282
static int32_t commit_edit(STFileSystem *fs) {
3,866,437✔
283
  char current[TSDB_FILENAME_LEN];
3,866,105✔
284
  char current_t[TSDB_FILENAME_LEN];
3,867,584✔
285

286
  current_fname(fs->tsdb, current, TSDB_FCURRENT);
3,867,916✔
287
  if (fs->etype == TSDB_FEDIT_COMMIT) {
3,867,916✔
288
    current_fname(fs->tsdb, current_t, TSDB_FCURRENT_C);
2,752,568✔
289
  } else {
290
    current_fname(fs->tsdb, current_t, TSDB_FCURRENT_M);
1,115,348✔
291
  }
292

293
  int32_t code;
294
  int32_t lino;
295
  TSDB_CHECK_CODE(taosRenameFile(current_t, current), lino, _exit);
3,867,916✔
296

297
  code = apply_commit(fs);
3,867,916✔
298
  TSDB_CHECK_CODE(code, lino, _exit);
3,866,637✔
299

300
_exit:
3,866,637✔
301
  if (code) {
3,867,041✔
302
    tsdbError("vgId:%d %s failed at %s:%d since %s", TD_VID(fs->tsdb->pVnode), __func__, __FILE__, lino,
×
303
              tstrerror(code));
304
  } else {
305
    tsdbInfo("vgId:%d %s success, etype:%d", TD_VID(fs->tsdb->pVnode), __func__, fs->etype);
3,867,041✔
306
  }
307
  return code;
3,867,916✔
308
}
309

310
// static int32_t
311
static int32_t tsdbFSDoSanAndFix(STFileSystem *fs);
312
static int32_t apply_abort(STFileSystem *fs) { return tsdbFSDoSanAndFix(fs); }
102✔
313

314
static int32_t abort_edit(STFileSystem *fs) {
102✔
315
  char fname[TSDB_FILENAME_LEN];
102✔
316

317
  if (fs->etype == TSDB_FEDIT_COMMIT) {
102✔
318
    current_fname(fs->tsdb, fname, TSDB_FCURRENT_C);
102✔
319
  } else {
320
    current_fname(fs->tsdb, fname, TSDB_FCURRENT_M);
×
321
  }
322

323
  int32_t code;
324
  int32_t lino;
325
  if ((code = taosRemoveFile(fname))) {
102✔
326
    code = TAOS_SYSTEM_ERROR(code);
×
327
    TSDB_CHECK_CODE(code, lino, _exit);
×
328
  }
329

330
  code = apply_abort(fs);
102✔
331
  TSDB_CHECK_CODE(code, lino, _exit);
102✔
332

333
_exit:
102✔
334
  if (code) {
102✔
335
    tsdbError("vgId:%d %s failed at %s:%d since %s", TD_VID(fs->tsdb->pVnode), __func__, __FILE__, lino,
×
336
              tstrerror(code));
337
  } else {
338
    tsdbInfo("vgId:%d %s success, etype:%d", TD_VID(fs->tsdb->pVnode), __func__, fs->etype);
102✔
339
  }
340
  return code;
102✔
341
}
342

343
static int32_t tsdbFSDoScanAndFixFile(STFileSystem *fs, const STFileObj *fobj) {
1,172,651✔
344
  int32_t code = 0;
1,172,651✔
345
  int32_t lino = 0;
1,172,651✔
346

347
  // check file existence
348
  if (!taosCheckExistFile(fobj->fname)) {
1,172,651✔
349
    bool found = false;
×
350

351
    if (tsSsEnabled && fobj->f->lcn > 1) {
×
352
      char fname1[TSDB_FILENAME_LEN];
×
353
      tsdbTFileLastChunkName(fs->tsdb, fobj->f, fname1);
×
354
      if (!taosCheckExistFile(fname1)) {
×
355
        code = TSDB_CODE_FILE_CORRUPTED;
×
356
        tsdbError("vgId:%d %s failed since file:%s does not exist", TD_VID(fs->tsdb->pVnode), __func__, fname1);
×
357
        return code;
×
358
      }
359

360
      found = true;
×
361
    }
362

363
    if (!found) {
×
364
      code = TSDB_CODE_FILE_CORRUPTED;
×
365
      tsdbError("vgId:%d %s failed since file:%s does not exist", TD_VID(fs->tsdb->pVnode), __func__, fobj->fname);
×
366
      return code;
×
367
    }
368
  }
369

370
  return 0;
1,172,651✔
371
}
372

373
static void tsdbFSDestroyFileObjHash(STFileHash *hash);
374

375
static int32_t tsdbFSAddEntryToFileObjHash(STFileHash *hash, const char *fname) {
2,227,917✔
376
  STFileHashEntry *entry = taosMemoryMalloc(sizeof(*entry));
2,227,917✔
377
  if (entry == NULL) return terrno;
2,227,917✔
378

379
  tstrncpy(entry->fname, fname, TSDB_FILENAME_LEN);
2,227,917✔
380

381
  uint32_t idx = MurmurHash3_32(fname, strlen(fname)) % hash->numBucket;
2,227,917✔
382

383
  entry->next = hash->buckets[idx];
2,227,917✔
384
  hash->buckets[idx] = entry;
2,227,917✔
385
  hash->numFile++;
2,227,917✔
386

387
  return 0;
2,227,917✔
388
}
389

390
static int32_t tsdbFSCreateFileObjHash(STFileSystem *fs, STFileHash *hash) {
1,055,266✔
391
  int32_t code = 0;
1,055,266✔
392
  int32_t lino;
393
  char    fname[TSDB_FILENAME_LEN];
1,055,190✔
394

395
  // init hash table
396
  hash->numFile = 0;
1,055,266✔
397
  hash->numBucket = 4096;
1,055,266✔
398
  hash->buckets = taosMemoryCalloc(hash->numBucket, sizeof(STFileHashEntry *));
1,055,266✔
399
  if (hash->buckets == NULL) {
1,055,266✔
400
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
401
  }
402

403
  // vnode.json
404
  current_fname(fs->tsdb, fname, TSDB_FCURRENT);
1,055,266✔
405
  code = tsdbFSAddEntryToFileObjHash(hash, fname);
1,055,266✔
406
  TSDB_CHECK_CODE(code, lino, _exit);
1,055,266✔
407

408
  // other
409
  STFileSet *fset = NULL;
1,055,266✔
410
  TARRAY2_FOREACH(fs->fSetArr, fset) {
1,703,011✔
411
    // data file
412
    for (int32_t i = 0; i < TSDB_FTYPE_MAX; i++) {
3,238,725✔
413
      if (fset->farr[i] != NULL) {
2,590,980✔
414
        code = tsdbFSAddEntryToFileObjHash(hash, fset->farr[i]->fname);
454,963✔
415
        TSDB_CHECK_CODE(code, lino, _exit);
454,963✔
416

417
        if (TSDB_FTYPE_DATA == i && fset->farr[i]->f->lcn > 0) {
454,963✔
418
          STFileObj *fobj = fset->farr[i];
×
419
          int32_t    lcn = fobj->f->lcn;
×
420
          char       lcn_name[TSDB_FILENAME_LEN];
×
421

422
          snprintf(lcn_name, TSDB_FQDN_LEN, "%s", fobj->fname);
×
423
          char *dot = strrchr(lcn_name, '.');
×
424
          if (dot) {
×
425
            snprintf(dot + 1, TSDB_FQDN_LEN - (dot + 1 - lcn_name), "%d.data", lcn);
×
426

427
            code = tsdbFSAddEntryToFileObjHash(hash, lcn_name);
×
428
            TSDB_CHECK_CODE(code, lino, _exit);
×
429
          }
430
        }
431
      }
432
    }
433

434
    // stt file
435
    SSttLvl *lvl = NULL;
647,745✔
436
    TARRAY2_FOREACH(fset->lvlArr, lvl) {
1,322,910✔
437
      STFileObj *fobj;
438
      TARRAY2_FOREACH(lvl->fobjArr, fobj) {
1,392,853✔
439
        code = tsdbFSAddEntryToFileObjHash(hash, fobj->fname);
717,688✔
440
        TSDB_CHECK_CODE(code, lino, _exit);
717,688✔
441
      }
442
    }
443
  }
444

445
_exit:
1,055,266✔
446
  if (code) {
1,055,266✔
447
    TSDB_ERROR_LOG(TD_VID(fs->tsdb->pVnode), lino, code);
×
448
    tsdbFSDestroyFileObjHash(hash);
×
449
  }
450
  return code;
1,055,266✔
451
}
452

453
static const STFileHashEntry *tsdbFSGetFileObjHashEntry(STFileHash *hash, const char *fname) {
2,228,223✔
454
  uint32_t idx = MurmurHash3_32(fname, strlen(fname)) % hash->numBucket;
2,228,223✔
455

456
  STFileHashEntry *entry = hash->buckets[idx];
2,228,223✔
457
  while (entry) {
2,228,898✔
458
    if (strcmp(entry->fname, fname) == 0) {
2,228,592✔
459
      return entry;
2,227,917✔
460
    }
461
    entry = entry->next;
675✔
462
  }
463

464
  return NULL;
306✔
465
}
466

467
static void tsdbFSDestroyFileObjHash(STFileHash *hash) {
1,055,266✔
468
  for (int32_t i = 0; i < hash->numBucket; i++) {
2,147,483,647✔
469
    STFileHashEntry *entry = hash->buckets[i];
2,147,483,647✔
470
    while (entry) {
2,147,483,647✔
471
      STFileHashEntry *next = entry->next;
2,227,917✔
472
      taosMemoryFree(entry);
2,227,917✔
473
      entry = next;
2,227,917✔
474
    }
475
  }
476
  taosMemoryFree(hash->buckets);
1,055,266✔
477
  memset(hash, 0, sizeof(*hash));
1,055,266✔
478
}
1,055,266✔
479

480
static int32_t tsdbFSDoSanAndFix(STFileSystem *fs) {
1,056,621✔
481
  int32_t code = 0;
1,056,621✔
482
  int32_t lino = 0;
1,056,621✔
483
  int32_t corrupt = false;
1,056,621✔
484

485
  if (fs->tsdb->pVnode->mounted) goto _exit;
1,056,621✔
486

487
  {  // scan each file
488
    STFileSet *fset = NULL;
1,055,266✔
489
    TARRAY2_FOREACH(fs->fSetArr, fset) {
1,703,011✔
490
      // data file
491
      for (int32_t ftype = 0; ftype < TSDB_FTYPE_MAX; ftype++) {
3,238,725✔
492
        if (fset->farr[ftype] == NULL) continue;
2,590,980✔
493
        STFileObj *fobj = fset->farr[ftype];
454,963✔
494
        code = tsdbFSDoScanAndFixFile(fs, fobj);
454,963✔
495
        if (code) {
454,963✔
496
          fset->maxVerValid = (fobj->f->minVer <= fobj->f->maxVer) ? TMIN(fset->maxVerValid, fobj->f->minVer - 1) : -1;
×
497
          corrupt = true;
×
498
        }
499
      }
500

501
      // stt file
502
      SSttLvl *lvl;
503
      TARRAY2_FOREACH(fset->lvlArr, lvl) {
1,322,910✔
504
        STFileObj *fobj;
505
        TARRAY2_FOREACH(lvl->fobjArr, fobj) {
1,392,853✔
506
          code = tsdbFSDoScanAndFixFile(fs, fobj);
717,688✔
507
          if (code) {
717,688✔
508
            fset->maxVerValid =
×
509
                (fobj->f->minVer <= fobj->f->maxVer) ? TMIN(fset->maxVerValid, fobj->f->minVer - 1) : -1;
×
510
            corrupt = true;
×
511
          }
512
        }
513
      }
514
    }
515
  }
516

517
  {  // clear unreferenced files
518
    STfsDir *dir = NULL;
1,054,589✔
519
    TAOS_CHECK_GOTO(tfsOpendir(fs->tsdb->pVnode->pTfs, fs->tsdb->path, &dir), &lino, _exit);
1,054,589✔
520

521
    STFileHash fobjHash = {0};
1,055,266✔
522
    code = tsdbFSCreateFileObjHash(fs, &fobjHash);
1,055,266✔
523
    if (code) goto _close_dir;
1,055,178✔
524

525
    for (const STfsFile *file = NULL; (file = tfsReaddir(dir)) != NULL;) {
4,338,667✔
526
      if (taosIsDir(file->aname)) continue;
3,283,489✔
527

528
      if (tsdbFSGetFileObjHashEntry(&fobjHash, file->aname) == NULL) {
2,228,223✔
529
        tsdbRemoveFile(file->aname);
306✔
530
      }
531
    }
532

533
    tsdbFSDestroyFileObjHash(&fobjHash);
1,055,103✔
534

535
  _close_dir:
1,055,266✔
536
    tfsClosedir(dir);
1,055,266✔
537
  }
538

539
_exit:
1,057,298✔
540
  if (corrupt) {
1,057,298✔
541
    tsdbError("vgId:%d, TSDB file system is corrupted", TD_VID(fs->tsdb->pVnode));
×
542
    fs->fsstate = TSDB_FS_STATE_INCOMPLETE;
×
543
    code = 0;
×
544
  }
545

546
  if (code) {
1,057,298✔
547
    TSDB_ERROR_LOG(TD_VID(fs->tsdb->pVnode), lino, code);
×
548
  }
549
  return code;
1,057,298✔
550
}
551

552
static int32_t tsdbFSScanAndFix(STFileSystem *fs) {
1,057,196✔
553
  fs->neid = 0;
1,057,196✔
554

555
  // get max commit id
556
  const STFileSet *fset;
557
  TARRAY2_FOREACH(fs->fSetArr, fset) { fs->neid = TMAX(fs->neid, tsdbTFileSetMaxCid(fset)); }
1,705,855✔
558

559
  // scan and fix
560
  int32_t code = 0;
1,056,519✔
561
  int32_t lino = 0;
1,056,519✔
562

563
  code = tsdbFSDoSanAndFix(fs);
1,056,519✔
564
  TSDB_CHECK_CODE(code, lino, _exit);
1,057,196✔
565

566
_exit:
1,057,196✔
567
  if (code) {
1,057,196✔
568
    TSDB_ERROR_LOG(TD_VID(fs->tsdb->pVnode), lino, code);
×
569
  }
570
  return code;
1,057,196✔
571
}
572

573
static int32_t tsdbFSDupState(STFileSystem *fs) {
4,923,188✔
574
  int32_t code;
575

576
  const TFileSetArray *src = fs->fSetArr;
4,923,188✔
577
  TFileSetArray       *dst = fs->fSetArrTmp;
4,924,423✔
578

579
  TARRAY2_CLEAR(dst, tsdbTFileSetClear);
9,448,813✔
580

581
  const STFileSet *fset1;
582
  TARRAY2_FOREACH(src, fset1) {
10,149,796✔
583
    STFileSet *fset2;
5,226,716✔
584
    code = tsdbTFileSetInitCopy(fs->tsdb, fset1, &fset2);
5,227,727✔
585
    if (code) return code;
5,228,279✔
586
    code = TARRAY2_APPEND(dst, fset2);
5,228,279✔
587
    if (code) return code;
5,227,598✔
588
  }
589

590
  return 0;
4,922,297✔
591
}
592

593
static int32_t open_fs(STFileSystem *fs, int8_t rollback) {
3,720,589✔
594
  int32_t code = 0;
3,720,589✔
595
  int32_t lino = 0;
3,720,589✔
596
  STsdb  *pTsdb = fs->tsdb;
3,720,589✔
597

598
  char fCurrent[TSDB_FILENAME_LEN];
3,734,418✔
599
  char cCurrent[TSDB_FILENAME_LEN];
3,734,418✔
600
  char mCurrent[TSDB_FILENAME_LEN];
3,734,418✔
601

602
  current_fname(pTsdb, fCurrent, TSDB_FCURRENT);
3,734,831✔
603
  current_fname(pTsdb, cCurrent, TSDB_FCURRENT_C);
3,734,124✔
604
  current_fname(pTsdb, mCurrent, TSDB_FCURRENT_M);
3,735,037✔
605

606
  if (taosCheckExistFile(fCurrent)) {  // current.json exists
3,735,037✔
607
    code = load_fs(pTsdb, fCurrent, fs->fSetArr);
1,057,196✔
608
    TSDB_CHECK_CODE(code, lino, _exit);
1,057,196✔
609

610
    if (taosCheckExistFile(cCurrent)) {
1,057,196✔
611
      // current.c.json exists
612

613
      fs->etype = TSDB_FEDIT_COMMIT;
×
614
      if (rollback) {
×
615
        code = abort_edit(fs);
×
616
        TSDB_CHECK_CODE(code, lino, _exit);
×
617
      } else {
618
        code = load_fs(pTsdb, cCurrent, fs->fSetArrTmp);
×
619
        TSDB_CHECK_CODE(code, lino, _exit);
×
620

621
        code = commit_edit(fs);
×
622
        TSDB_CHECK_CODE(code, lino, _exit);
×
623
      }
624
    } else if (taosCheckExistFile(mCurrent)) {
1,057,196✔
625
      // current.m.json exists
626
      fs->etype = TSDB_FEDIT_MERGE;
×
627
      code = abort_edit(fs);
×
628
      TSDB_CHECK_CODE(code, lino, _exit);
×
629
    }
630

631
    code = tsdbFSDupState(fs);
1,057,196✔
632
    TSDB_CHECK_CODE(code, lino, _exit);
1,057,196✔
633

634
    code = tsdbFSScanAndFix(fs);
1,057,196✔
635
    TSDB_CHECK_CODE(code, lino, _exit);
1,057,196✔
636
  } else {
637
    code = save_fs(fs->fSetArr, fCurrent);
2,677,635✔
638
    TSDB_CHECK_CODE(code, lino, _exit);
2,676,902✔
639
  }
640

641
_exit:
3,734,022✔
642
  if (code) {
3,734,566✔
643
    tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pTsdb->pVnode), __func__, lino, tstrerror(code));
×
644
  } else {
645
    tsdbInfo("vgId:%d %s success", TD_VID(pTsdb->pVnode), __func__);
3,734,566✔
646
  }
647
  return code;
3,736,048✔
648
}
649

650
static void close_file_system(STFileSystem *fs) {
3,735,037✔
651
  TARRAY2_CLEAR(fs->fSetArr, tsdbTFileSetClear);
18,559,414✔
652
  TARRAY2_CLEAR(fs->fSetArrTmp, tsdbTFileSetClear);
18,540,008✔
653
}
3,735,037✔
654

655
static int32_t fset_cmpr_fn(const struct STFileSet *pSet1, const struct STFileSet *pSet2) {
×
656
  if (pSet1->fid < pSet2->fid) {
×
657
    return -1;
×
658
  } else if (pSet1->fid > pSet2->fid) {
×
659
    return 1;
×
660
  }
661
  return 0;
×
662
}
663

664
static int32_t edit_fs(STFileSystem *fs, const TFileOpArray *opArray, EFEditT etype) {
3,867,464✔
665
  int32_t code = 0;
3,867,464✔
666
  int32_t lino = 0;
3,867,464✔
667

668
  code = tsdbFSDupState(fs);
3,867,464✔
669
  if (code) return code;
3,863,567✔
670

671
  TFileSetArray  *fsetArray = fs->fSetArrTmp;
3,863,567✔
672
  STFileSet      *fset = NULL;
3,864,248✔
673
  const STFileOp *op;
674
  int32_t         fid = INT32_MIN;
3,864,974✔
675
  TSKEY           now = taosGetTimestampMs();
3,866,479✔
676
  TARRAY2_FOREACH_PTR(opArray, op) {
25,985,061✔
677
    if (!fset || fset->fid != op->fid) {
22,118,603✔
678
      STFileSet tfset = {.fid = op->fid};
17,368,474✔
679
      fset = &tfset;
17,369,869✔
680
      STFileSet **fsetPtr = TARRAY2_SEARCH(fsetArray, &fset, tsdbTFileSetCmprFn, TD_EQ);
17,367,676✔
681
      fset = (fsetPtr == NULL) ? NULL : *fsetPtr;
17,367,676✔
682

683
      if (!fset) {
17,367,676✔
684
        code = tsdbTFileSetInit(op->fid, &fset);
14,175,284✔
685
        TSDB_CHECK_CODE(code, lino, _exit);
14,175,444✔
686

687
        code = TARRAY2_SORT_INSERT(fsetArray, fset, tsdbTFileSetCmprFn);
14,176,369✔
688
        TSDB_CHECK_CODE(code, lino, _exit);
14,176,369✔
689
      }
690
    }
691

692
    code = tsdbTFileSetEdit(fs->tsdb, fset, op);
22,119,990✔
693
    TSDB_CHECK_CODE(code, lino, _exit);
22,119,406✔
694

695
    if (fid != op->fid) {
22,119,406✔
696
      fid = op->fid;
17,370,008✔
697
      if (etype == TSDB_FEDIT_COMMIT) {
17,367,927✔
698
        fset->lastCommit = now;
16,252,579✔
699
      } else if (etype == TSDB_FEDIT_COMPACT) {
1,115,348✔
700
        fset->lastCompact = now;
86,863✔
701
      } else if (etype == TSDB_FEDIT_SSMIGRATE) {
1,028,485✔
702
        fset->lastMigrate = now;
×
703
      } else if (etype == TSDB_FEDIT_ROLLUP) {
1,028,485✔
704
        fset->lastRollupLevel = fs->rollupLevel;
16,813✔
705
        fset->lastRollup = now;
16,813✔
706
        fset->lastCompact = now;  // rollup implies compact
16,813✔
707
      }
708
    }
709
  }
710

711
  // remove empty empty stt level and empty file set
712
  int32_t i = 0;
3,865,616✔
713
  while (i < TARRAY2_SIZE(fsetArray)) {
22,618,574✔
714
    fset = TARRAY2_GET(fsetArray, i);
18,757,276✔
715

716
    SSttLvl *lvl;
717
    int32_t  j = 0;
18,755,022✔
718
    while (j < TARRAY2_SIZE(fset->lvlArr)) {
40,666,550✔
719
      lvl = TARRAY2_GET(fset->lvlArr, j);
21,916,883✔
720

721
      if (TARRAY2_SIZE(lvl->fobjArr) == 0) {
21,914,618✔
722
        TARRAY2_REMOVE(fset->lvlArr, j, tsdbSttLvlClear);
1,381,611✔
723
      } else {
724
        j++;
20,529,917✔
725
      }
726
    }
727

728
    if (tsdbTFileSetIsEmpty(fset)) {
18,753,014✔
729
      TARRAY2_REMOVE(fsetArray, i, tsdbTFileSetClear);
78,377✔
730
    } else {
731
      i++;
18,677,627✔
732
    }
733
  }
734

735
_exit:
3,862,662✔
736
  if (code) {
3,865,119✔
737
    TSDB_ERROR_LOG(TD_VID(fs->tsdb->pVnode), lino, code);
×
738
  }
739
  return code;
3,864,832✔
740
}
741

742
// return error code
743
int32_t tsdbOpenFS(STsdb *pTsdb, STFileSystem **fs, int8_t rollback) {
3,731,450✔
744
  int32_t code;
745
  int32_t lino;
746

747
  code = tsdbCheckAndUpgradeFileSystem(pTsdb, rollback);
3,731,450✔
748
  TSDB_CHECK_CODE(code, lino, _exit);
3,734,831✔
749

750
  code = create_fs(pTsdb, fs);
3,734,831✔
751
  TSDB_CHECK_CODE(code, lino, _exit);
3,732,020✔
752

753
  code = open_fs(fs[0], rollback);
3,732,020✔
754
  TSDB_CHECK_CODE(code, lino, _exit);
3,735,037✔
755

756
_exit:
3,735,037✔
757
  if (code) {
3,735,037✔
758
    tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pTsdb->pVnode), __func__, lino, tstrerror(code));
×
759
    destroy_fs(fs);
×
760
  } else {
761
    tsdbInfo("vgId:%d %s success", TD_VID(pTsdb->pVnode), __func__);
3,735,037✔
762
  }
763
  return code;
3,735,037✔
764
}
765

766
static void tsdbFSSetBlockCommit(STFileSet *fset, bool block);
767
extern void tsdbStopAllCompTask(STsdb *tsdb);
768
extern void tsdbStopAllRetentionTask(STsdb *tsdb);
769

770
int32_t tsdbDisableAndCancelAllBgTask(STsdb *pTsdb) {
3,764,381✔
771
  STFileSystem *fs = pTsdb->pFS;
3,764,381✔
772
  SArray       *asyncTasks = taosArrayInit(0, sizeof(SVATaskID));
3,764,114✔
773
  if (asyncTasks == NULL) {
3,764,215✔
774
    return terrno;
×
775
  }
776

777
  (void)taosThreadMutexLock(&pTsdb->mutex);
3,764,215✔
778

779
  // disable
780
  pTsdb->bgTaskDisabled = true;
3,764,381✔
781

782
  // collect channel
783
  STFileSet *fset;
784
  TARRAY2_FOREACH(fs->fSetArr, fset) {
18,592,160✔
785
    if (taosArrayPush(asyncTasks, &fset->mergeTask) == NULL       //
29,657,086✔
786
        || taosArrayPush(asyncTasks, &fset->compactTask) == NULL  //
29,657,252✔
787
        || taosArrayPush(asyncTasks, &fset->retentionTask) == NULL
29,657,252✔
788
        || taosArrayPush(asyncTasks, &fset->migrateTask) == NULL) {
29,657,252✔
UNCOV
789
      taosArrayDestroy(asyncTasks);
×
790
      (void)taosThreadMutexUnlock(&pTsdb->mutex);
×
791
      return terrno;
×
792
    }
793
    tsdbFSSetBlockCommit(fset, false);
14,828,626✔
794
  }
795

796
  (void)taosThreadMutexUnlock(&pTsdb->mutex);
3,764,215✔
797

798
  // destroy all channels
799
  for (int32_t k = 0; k < 2; k++) {
11,291,427✔
800
    for (int32_t i = 0; i < taosArrayGetSize(asyncTasks); i++) {
126,153,982✔
801
      SVATaskID *task = taosArrayGet(asyncTasks, i);
118,623,097✔
802
      if (k == 0) {
118,624,395✔
803
        (void)vnodeACancel(task);
59,312,957✔
804
      } else {
805
        vnodeAWait(task);
59,311,438✔
806
      }
807
    }
808
  }
809
  taosArrayDestroy(asyncTasks);
3,764,381✔
810

811
#ifdef TD_ENTERPRISE
812
  tsdbStopAllCompTask(pTsdb);
3,764,215✔
813
#endif
814
  tsdbStopAllRetentionTask(pTsdb);
3,764,215✔
815
  return 0;
3,764,381✔
816
}
817

818
void tsdbEnableBgTask(STsdb *pTsdb) {
29,344✔
819
  (void)taosThreadMutexLock(&pTsdb->mutex);
29,344✔
820
  pTsdb->bgTaskDisabled = false;
29,344✔
821
  (void)taosThreadMutexUnlock(&pTsdb->mutex);
29,344✔
822
}
29,344✔
823

824
void tsdbCloseFS(STFileSystem **fs) {
3,735,037✔
825
  if (fs[0] == NULL) return;
3,735,037✔
826

827
  int32_t code = tsdbDisableAndCancelAllBgTask((*fs)->tsdb);
3,735,037✔
828
  if (code) {
3,735,037✔
829
    tsdbError("vgId:%d %s failed at line %d since %s", TD_VID((*fs)->tsdb->pVnode), __func__, __LINE__,
×
830
              tstrerror(code));
831
  }
832
  close_file_system(fs[0]);
3,735,037✔
833
  destroy_fs(fs);
3,735,037✔
834
  return;
3,735,037✔
835
}
836

837
int64_t tsdbFSAllocEid(STFileSystem *fs) {
3,964,443✔
838
  (void)taosThreadMutexLock(&fs->tsdb->mutex);
3,964,443✔
839
  int64_t cid = ++fs->neid;
3,964,956✔
840
  (void)taosThreadMutexUnlock(&fs->tsdb->mutex);
3,964,956✔
841
  return cid;
3,963,891✔
842
}
843

844
void tsdbFSUpdateEid(STFileSystem *fs, int64_t cid) {
112,758✔
845
  (void)taosThreadMutexLock(&fs->tsdb->mutex);
112,758✔
846
  fs->neid = TMAX(fs->neid, cid);
112,758✔
847
  (void)taosThreadMutexUnlock(&fs->tsdb->mutex);
112,758✔
848
}
112,758✔
849

850
int32_t tsdbFSEditBegin(STFileSystem *fs, const TFileOpArray *opArray, EFEditT etype) {
3,866,240✔
851
  int32_t code = 0;
3,866,240✔
852
  int32_t lino;
853
  char    current_t[TSDB_FILENAME_LEN];
3,865,908✔
854

855
  if (etype == TSDB_FEDIT_COMMIT) {
3,866,240✔
856
    current_fname(fs->tsdb, current_t, TSDB_FCURRENT_C);
2,751,085✔
857
  } else {
858
    current_fname(fs->tsdb, current_t, TSDB_FCURRENT_M);
1,115,155✔
859
  }
860

861
  if (tsem_wait(&fs->canEdit) != 0) {
3,866,737✔
862
    tsdbError("vgId:%d failed to wait semaphore", TD_VID(fs->tsdb->pVnode));
×
863
  }
864
  fs->etype = etype;
3,865,818✔
865

866
  // edit
867
  code = edit_fs(fs, opArray, etype);
3,867,657✔
868
  TSDB_CHECK_CODE(code, lino, _exit);
3,866,684✔
869

870
  // save fs
871
  code = save_fs(fs->fSetArrTmp, current_t);
3,866,684✔
872
  TSDB_CHECK_CODE(code, lino, _exit);
3,867,825✔
873

874
_exit:
3,867,825✔
875
  if (code) {
3,867,825✔
876
    tsdbError("vgId:%d %s failed at line %d since %s, etype:%d", TD_VID(fs->tsdb->pVnode), __func__, lino,
×
877
              tstrerror(code), etype);
878
  } else {
879
    tsdbInfo("vgId:%d %s done, etype:%d", TD_VID(fs->tsdb->pVnode), __func__, etype);
3,867,825✔
880
  }
881
  return code;
3,868,184✔
882
}
883

884
static void tsdbFSSetBlockCommit(STFileSet *fset, bool block) {
29,782,521✔
885
  if (block) {
29,782,521✔
886
    fset->blockCommit = true;
3,358✔
887
  } else {
888
    fset->blockCommit = false;
29,779,163✔
889
    if (fset->numWaitCommit > 0) {
29,778,222✔
890
      (void)taosThreadCondSignal(&fset->canCommit);
18✔
891
    }
892
  }
893
}
29,781,407✔
894

895
void tsdbFSCheckCommit(STsdb *tsdb, int32_t fid) {
16,253,621✔
896
  (void)taosThreadMutexLock(&tsdb->mutex);
16,253,621✔
897
  STFileSet *fset;
16,251,806✔
898
  tsdbFSGetFSet(tsdb->pFS, fid, &fset);
16,253,885✔
899
  bool blockCommit = false;
16,243,000✔
900
  if (fset) {
16,243,000✔
901
    blockCommit = fset->blockCommit;
2,102,008✔
902
  }
903
  if (fset) {
16,243,000✔
904
    METRICS_TIMING_BLOCK(tsdb->pVnode->writeMetrics.block_commit_time, METRIC_LEVEL_HIGH, {
2,102,026✔
905
      while (fset->blockCommit) {
906
        fset->numWaitCommit++;
907
        (void)taosThreadCondWait(&fset->canCommit, &tsdb->mutex);
908
        fset->numWaitCommit--;
909
      }
910
    });
911
  }
912
  if (blockCommit) {
16,244,707✔
913
    METRICS_UPDATE(tsdb->pVnode->writeMetrics.blocked_commit_count, METRIC_LEVEL_HIGH, 1);
18✔
914
  }
915
  (void)taosThreadMutexUnlock(&tsdb->mutex);
16,244,707✔
916
  return;
16,248,197✔
917
}
918

919
// IMPORTANT: the caller must hold fs->tsdb->mutex
920
int32_t tsdbFSEditCommit(STFileSystem *fs) {
3,867,916✔
921
  int32_t code = 0;
3,867,916✔
922
  int32_t lino = 0;
3,867,916✔
923

924
  // commit
925
  code = commit_edit(fs);
3,867,916✔
926
  TSDB_CHECK_CODE(code, lino, _exit);
3,867,916✔
927

928
  // schedule merge
929
  int32_t sttTrigger = fs->tsdb->pVnode->config.sttTrigger;
3,867,916✔
930
  if (sttTrigger > 1 && !fs->tsdb->bgTaskDisabled) {
3,867,916✔
931
    STFileSet *fset;
932
    TARRAY2_FOREACH_REVERSE(fs->fSetArr, fset) {
18,633,470✔
933
      if (TARRAY2_SIZE(fset->lvlArr) == 0) {
14,953,895✔
934
        tsdbFSSetBlockCommit(fset, false);
431,663✔
935
        continue;
431,663✔
936
      }
937

938
      SSttLvl *lvl = TARRAY2_FIRST(fset->lvlArr);
14,522,232✔
939
      if (lvl->level != 0) {
14,522,232✔
940
        tsdbFSSetBlockCommit(fset, false);
866,931✔
941
        continue;
866,931✔
942
      }
943

944
      // bool    skipMerge = false;
945
      int32_t numFile = TARRAY2_SIZE(lvl->fobjArr);
13,655,301✔
946
      if (numFile >= sttTrigger && (!vnodeATaskValid(&fset->mergeTask))) {
13,655,301✔
947
        SMergeArg *arg = taosMemoryMalloc(sizeof(*arg));
1,002,706✔
948
        if (arg == NULL) {
1,002,706✔
949
          code = terrno;
×
950
          TSDB_CHECK_CODE(code, lino, _exit);
×
951
        }
952

953
        arg->tsdb = fs->tsdb;
1,002,706✔
954
        arg->fid = fset->fid;
1,002,706✔
955

956
        code = vnodeAsync(MERGE_TASK_ASYNC, EVA_PRIORITY_HIGH, tsdbMerge, taosAutoMemoryFree, arg, &fset->mergeTask);
1,002,706✔
957
        TSDB_CHECK_CODE(code, lino, _exit);
1,002,706✔
958
      }
959

960
      if (numFile >= sttTrigger * BLOCK_COMMIT_FACTOR) {
13,655,301✔
961
        tsdbFSSetBlockCommit(fset, true);
3,358✔
962
      } else {
963
        tsdbFSSetBlockCommit(fset, false);
13,651,943✔
964
      }
965
    }
966
  }
967

968
_exit:
3,867,916✔
969
  if (code) {
3,867,916✔
970
    tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(fs->tsdb->pVnode), __func__, lino, tstrerror(code));
×
971
  } else {
972
    tsdbInfo("vgId:%d %s done, etype:%d", TD_VID(fs->tsdb->pVnode), __func__, fs->etype);
3,867,916✔
973
  }
974
  if (tsem_post(&fs->canEdit) != 0) {
3,867,916✔
975
    tsdbError("vgId:%d failed to post semaphore", TD_VID(fs->tsdb->pVnode));
×
976
  }
977
  return code;
3,867,916✔
978
}
979

980
int32_t tsdbFSEditAbort(STFileSystem *fs) {
102✔
981
  int32_t code = abort_edit(fs);
102✔
982
  if (tsem_post(&fs->canEdit) != 0) {
102✔
983
    tsdbError("vgId:%d failed to post semaphore", TD_VID(fs->tsdb->pVnode));
×
984
  }
985
  return code;
102✔
986
}
987

988
void tsdbFSGetFSet(STFileSystem *fs, int32_t fid, STFileSet **fset) {
36,993,296✔
989
  STFileSet   tfset = {.fid = fid};
36,993,296✔
990
  STFileSet  *pset = &tfset;
36,996,850✔
991
  STFileSet **fsetPtr = TARRAY2_SEARCH(fs->fSetArr, &pset, tsdbTFileSetCmprFn, TD_EQ);
36,993,585✔
992
  fset[0] = (fsetPtr == NULL) ? NULL : fsetPtr[0];
36,992,727✔
993
}
36,989,844✔
994

995
int32_t tsdbFSCreateCopySnapshot(STFileSystem *fs, TFileSetArray **fsetArr) {
25,236✔
996
  int32_t    code = 0;
25,236✔
997
  STFileSet *fset;
998
  STFileSet *fset1;
25,236✔
999

1000
  fsetArr[0] = taosMemoryMalloc(sizeof(TFileSetArray));
25,236✔
1001
  if (fsetArr[0] == NULL) return terrno;
25,236✔
1002

1003
  TARRAY2_INIT(fsetArr[0]);
25,236✔
1004

1005
  (void)taosThreadMutexLock(&fs->tsdb->mutex);
25,236✔
1006
  TARRAY2_FOREACH(fs->fSetArr, fset) {
25,236✔
1007
    code = tsdbTFileSetInitCopy(fs->tsdb, fset, &fset1);
×
1008
    if (code) break;
×
1009

1010
    code = TARRAY2_APPEND(fsetArr[0], fset1);
×
1011
    if (code) break;
×
1012
  }
1013
  (void)taosThreadMutexUnlock(&fs->tsdb->mutex);
25,236✔
1014

1015
  if (code) {
25,236✔
1016
    TARRAY2_DESTROY(fsetArr[0], tsdbTFileSetClear);
×
1017
    taosMemoryFree(fsetArr[0]);
×
1018
    fsetArr[0] = NULL;
×
1019
  }
1020
  return code;
25,236✔
1021
}
1022

1023
void tsdbFSDestroyCopySnapshot(TFileSetArray **fsetArr) {
25,704✔
1024
  if (fsetArr[0]) {
25,704✔
1025
    TARRAY2_DESTROY(fsetArr[0], tsdbTFileSetClear);
27,492✔
1026
    taosMemoryFree(fsetArr[0]);
25,704✔
1027
    fsetArr[0] = NULL;
25,704✔
1028
  }
1029
}
25,704✔
1030

1031
int32_t tsdbFSCreateRefSnapshot(STFileSystem *fs, TFileSetArray **fsetArr) {
27,826✔
1032
  (void)taosThreadMutexLock(&fs->tsdb->mutex);
27,826✔
1033
  int32_t code = tsdbFSCreateRefSnapshotWithoutLock(fs, fsetArr);
27,826✔
1034
  (void)taosThreadMutexUnlock(&fs->tsdb->mutex);
27,826✔
1035
  return code;
27,826✔
1036
}
1037

1038
int32_t tsdbFSCreateRefSnapshotWithoutLock(STFileSystem *fs, TFileSetArray **fsetArr) {
244,816,032✔
1039
  int32_t    code = 0;
244,816,032✔
1040
  STFileSet *fset, *fset1;
244,812,675✔
1041

1042
  fsetArr[0] = taosMemoryCalloc(1, sizeof(*fsetArr[0]));
244,914,498✔
1043
  if (fsetArr[0] == NULL) return terrno;
244,781,206✔
1044

1045
  TARRAY2_FOREACH(fs->fSetArr, fset) {
551,779,706✔
1046
    code = tsdbTFileSetInitRef(fs->tsdb, fset, &fset1);
307,306,533✔
1047
    if (code) break;
307,287,099✔
1048

1049
    code = TARRAY2_APPEND(fsetArr[0], fset1);
307,287,099✔
1050
    if (code) {
307,282,959✔
1051
      tsdbTFileSetClear(&fset1);
×
1052
      break;
×
1053
    }
1054
  }
1055

1056
  if (code) {
244,829,700✔
1057
    TARRAY2_DESTROY(fsetArr[0], tsdbTFileSetClear);
×
1058
    taosMemoryFree(fsetArr[0]);
×
1059
    fsetArr[0] = NULL;
×
1060
  }
1061
  return code;
244,829,700✔
1062
}
1063

1064
void tsdbFSDestroyRefSnapshot(TFileSetArray **fsetArr) {
244,947,539✔
1065
  if (fsetArr[0]) {
244,947,539✔
1066
    TARRAY2_DESTROY(fsetArr[0], tsdbTFileSetClear);
552,365,807✔
1067
    taosMemoryFreeClear(fsetArr[0]);
245,043,828✔
1068
    fsetArr[0] = NULL;
244,854,049✔
1069
  }
1070
}
244,719,944✔
1071

1072
static SHashObj *tsdbFSetRangeArrayToHash(TFileSetRangeArray *pRanges) {
939✔
1073
  int32_t   capacity = TARRAY2_SIZE(pRanges) * 2;
939✔
1074
  SHashObj *pHash = taosHashInit(capacity, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_ENTRY_LOCK);
939✔
1075
  if (pHash == NULL) {
939✔
1076
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
1077
    return NULL;
×
1078
  }
1079

1080
  for (int32_t i = 0; i < TARRAY2_SIZE(pRanges); i++) {
4,518✔
1081
    STFileSetRange *u = TARRAY2_GET(pRanges, i);
3,579✔
1082
    int32_t         fid = u->fid;
3,579✔
1083
    int32_t         code = taosHashPut(pHash, &fid, sizeof(fid), u, sizeof(*u));
3,579✔
1084
    tsdbDebug("range diff hash fid:%d, sver:%" PRId64 ", ever:%" PRId64, u->fid, u->sver, u->ever);
3,579✔
1085
  }
1086
  return pHash;
939✔
1087
}
1088

1089
int32_t tsdbFSCreateCopyRangedSnapshot(STFileSystem *fs, TFileSetRangeArray *pRanges, TFileSetArray **fsetArr,
468✔
1090
                                       TFileOpArray *fopArr) {
1091
  int32_t    code = 0;
468✔
1092
  STFileSet *fset;
1093
  STFileSet *fset1;
468✔
1094
  SHashObj  *pHash = NULL;
468✔
1095

1096
  fsetArr[0] = taosMemoryMalloc(sizeof(TFileSetArray));
468✔
1097
  if (fsetArr == NULL) return terrno;
468✔
1098
  TARRAY2_INIT(fsetArr[0]);
468✔
1099

1100
  if (pRanges) {
468✔
1101
    pHash = tsdbFSetRangeArrayToHash(pRanges);
468✔
1102
    if (pHash == NULL) {
468✔
1103
      code = TSDB_CODE_OUT_OF_MEMORY;
×
1104
      goto _out;
×
1105
    }
1106
  }
1107

1108
  (void)taosThreadMutexLock(&fs->tsdb->mutex);
468✔
1109
  TARRAY2_FOREACH(fs->fSetArr, fset) {
2,256✔
1110
    int64_t ever = VERSION_MAX;
1,788✔
1111
    if (pHash) {
1,788✔
1112
      int32_t         fid = fset->fid;
1,788✔
1113
      STFileSetRange *u = taosHashGet(pHash, &fid, sizeof(fid));
1,788✔
1114
      if (u) {
1,788✔
1115
        ever = u->sver - 1;
1,788✔
1116
      }
1117
    }
1118

1119
    code = tsdbTFileSetFilteredInitDup(fs->tsdb, fset, ever, &fset1, fopArr);
1,788✔
1120
    if (code) break;
1,788✔
1121

1122
    code = TARRAY2_APPEND(fsetArr[0], fset1);
1,788✔
1123
    if (code) break;
1,788✔
1124
  }
1125
  (void)taosThreadMutexUnlock(&fs->tsdb->mutex);
468✔
1126

1127
_out:
468✔
1128
  if (code) {
468✔
1129
    TARRAY2_DESTROY(fsetArr[0], tsdbTFileSetClear);
×
1130
    taosMemoryFree(fsetArr[0]);
×
1131
    fsetArr[0] = NULL;
×
1132
  }
1133
  if (pHash) {
468✔
1134
    taosHashCleanup(pHash);
468✔
1135
    pHash = NULL;
468✔
1136
  }
1137
  return code;
468✔
1138
}
1139

1140
void tsdbFSDestroyCopyRangedSnapshot(TFileSetArray **fsetArr) { tsdbFSDestroyCopySnapshot(fsetArr); }
468✔
1141

1142
int32_t tsdbFSCreateRefRangedSnapshot(STFileSystem *fs, int64_t sver, int64_t ever, TFileSetRangeArray *pRanges,
471✔
1143
                                      TFileSetRangeArray **fsrArr) {
1144
  int32_t         code = 0;
471✔
1145
  STFileSet      *fset;
1146
  STFileSetRange *fsr1 = NULL;
471✔
1147
  SHashObj       *pHash = NULL;
471✔
1148

1149
  fsrArr[0] = taosMemoryCalloc(1, sizeof(*fsrArr[0]));
471✔
1150
  if (fsrArr[0] == NULL) {
471✔
1151
    code = terrno;
×
1152
    goto _out;
×
1153
  }
1154

1155
  tsdbInfo("pRanges size:%d", (pRanges == NULL ? 0 : TARRAY2_SIZE(pRanges)));
471✔
1156
  if (pRanges) {
471✔
1157
    pHash = tsdbFSetRangeArrayToHash(pRanges);
471✔
1158
    if (pHash == NULL) {
471✔
1159
      code = TSDB_CODE_OUT_OF_MEMORY;
×
1160
      goto _out;
×
1161
    }
1162
  }
1163

1164
  (void)taosThreadMutexLock(&fs->tsdb->mutex);
471✔
1165
  TARRAY2_FOREACH(fs->fSetArr, fset) {
2,262✔
1166
    int64_t sver1 = sver;
1,791✔
1167
    int64_t ever1 = ever;
1,791✔
1168

1169
    if (pHash) {
1,791✔
1170
      int32_t         fid = fset->fid;
1,791✔
1171
      STFileSetRange *u = taosHashGet(pHash, &fid, sizeof(fid));
1,791✔
1172
      if (u) {
1,791✔
1173
        sver1 = u->sver;
1,791✔
1174
        tsdbDebug("range hash get fid:%d, sver:%" PRId64 ", ever:%" PRId64, u->fid, u->sver, u->ever);
1,791✔
1175
      }
1176
    }
1177

1178
    if (sver1 > ever1) {
1,791✔
1179
      tsdbDebug("skip fid:%d, sver:%" PRId64 ", ever:%" PRId64, fset->fid, sver1, ever1);
×
1180
      continue;
×
1181
    }
1182

1183
    tsdbDebug("fsrArr:%p, fid:%d, sver:%" PRId64 ", ever:%" PRId64, fsrArr, fset->fid, sver1, ever1);
1,791✔
1184

1185
    code = tsdbTFileSetRangeInitRef(fs->tsdb, fset, sver1, ever1, &fsr1);
1,791✔
1186
    if (code) break;
1,791✔
1187

1188
    code = TARRAY2_APPEND(fsrArr[0], fsr1);
1,791✔
1189
    if (code) break;
1,791✔
1190

1191
    fsr1 = NULL;
1,791✔
1192
  }
1193
  (void)taosThreadMutexUnlock(&fs->tsdb->mutex);
471✔
1194

1195
  if (code) {
471✔
1196
    tsdbTFileSetRangeClear(&fsr1);
×
1197
    TARRAY2_DESTROY(fsrArr[0], tsdbTFileSetRangeClear);
×
1198
    fsrArr[0] = NULL;
×
1199
  }
1200

1201
_out:
471✔
1202
  if (pHash) {
471✔
1203
    taosHashCleanup(pHash);
471✔
1204
    pHash = NULL;
471✔
1205
  }
1206
  return code;
471✔
1207
}
1208

1209
void tsdbFSDestroyRefRangedSnapshot(TFileSetRangeArray **fsrArr) { tsdbTFileSetRangeArrayDestroy(fsrArr); }
471✔
1210

1211
void tsdbBeginTaskOnFileSet(STsdb *tsdb, int32_t fid, EVATaskT task, STFileSet **fset) {
17,450,405✔
1212
  // Here, sttTrigger is protected by tsdb->mutex, so it is safe to read it without lock
1213
  int16_t sttTrigger = tsdb->pVnode->config.sttTrigger;
17,450,405✔
1214

1215
  tsdbFSGetFSet(tsdb->pFS, fid, fset);
17,453,395✔
1216
  if (*fset == NULL) {
17,452,056✔
1217
    return;
14,159,348✔
1218
  }
1219

1220
  struct STFileSetCond *cond = NULL;
3,293,221✔
1221
  if (sttTrigger == 1 || task == EVA_TASK_COMMIT) {
3,293,221✔
1222
    cond = &(*fset)->conds[0];
2,169,370✔
1223
  } else {
1224
    cond = &(*fset)->conds[1];
1,123,851✔
1225
  }
1226

1227
  while (1) {
1228
    if (cond->running) {
3,293,221✔
1229
      cond->numWait++;
×
1230
      (void)taosThreadCondWait(&cond->cond, &tsdb->mutex);
×
1231
      cond->numWait--;
×
1232
    } else {
1233
      cond->running = true;
3,293,221✔
1234
      break;
3,293,221✔
1235
    }
1236
  }
1237

1238
  tsdbTrace("vgId:%d begin %s task on file set:%d", TD_VID(tsdb->pVnode), vnodeGetATaskName(task), fid);
3,293,221✔
1239
  return;
3,293,221✔
1240
}
1241

1242
void tsdbFinishTaskOnFileSet(STsdb *tsdb, int32_t fid, EVATaskT task) {
3,293,826✔
1243
  // Here, sttTrigger is protected by tsdb->mutex, so it is safe to read it without lock
1244
  int16_t sttTrigger = tsdb->pVnode->config.sttTrigger;
3,293,826✔
1245

1246
  STFileSet *fset = NULL;
3,293,826✔
1247
  tsdbFSGetFSet(tsdb->pFS, fid, &fset);
3,293,826✔
1248
  if (fset == NULL) {
3,293,826✔
1249
    return;
×
1250
  }
1251

1252
  struct STFileSetCond *cond = NULL;
3,293,826✔
1253
  if (sttTrigger == 1 || task == EVA_TASK_COMMIT) {
3,293,826✔
1254
    cond = &fset->conds[0];
2,169,370✔
1255
  } else {
1256
    cond = &fset->conds[1];
1,124,456✔
1257
  }
1258

1259
  cond->running = false;
3,293,826✔
1260
  if (cond->numWait > 0) {
3,293,826✔
1261
    (void)taosThreadCondSignal(&cond->cond);
×
1262
  }
1263

1264
  tsdbTrace("vgId:%d finish %s task on file set:%d", TD_VID(tsdb->pVnode), vnodeGetATaskName(task), fid);
3,293,826✔
1265
  return;
3,293,826✔
1266
}
1267

1268
struct SFileSetReader {
1269
  STsdb     *pTsdb;
1270
  STFileSet *pFileSet;
1271
  int32_t    fid;
1272
  int64_t    startTime;
1273
  int64_t    endTime;
1274
  int64_t    lastCompactTime;
1275
  int64_t    totalSize;
1276
};
1277

1278
int32_t tsdbFileSetReaderOpen(void *pVnode, struct SFileSetReader **ppReader) {
140✔
1279
  if (pVnode == NULL || ppReader == NULL) {
140✔
1280
    return TSDB_CODE_INVALID_PARA;
×
1281
  }
1282

1283
  STsdb *pTsdb = ((SVnode *)pVnode)->pTsdb;
140✔
1284

1285
  (*ppReader) = taosMemoryCalloc(1, sizeof(struct SFileSetReader));
140✔
1286
  if (*ppReader == NULL) {
140✔
1287
    tsdbError("vgId:%d %s failed at %s:%d since %s", TD_VID(pTsdb->pVnode), __func__, __FILE__, __LINE__,
×
1288
              tstrerror(terrno));
1289
    return terrno;
×
1290
  }
1291

1292
  (*ppReader)->pTsdb = pTsdb;
140✔
1293
  (*ppReader)->fid = INT32_MIN;
140✔
1294
  (*ppReader)->pFileSet = NULL;
140✔
1295

1296
  return TSDB_CODE_SUCCESS;
140✔
1297
}
1298

1299
static int32_t tsdbFileSetReaderNextNoLock(struct SFileSetReader *pReader) {
280✔
1300
  STsdb  *pTsdb = pReader->pTsdb;
280✔
1301
  int32_t code = TSDB_CODE_SUCCESS;
280✔
1302

1303
  tsdbTFileSetClear(&pReader->pFileSet);
280✔
1304

1305
  STFileSet *fset = &(STFileSet){
280✔
1306
      .fid = pReader->fid,
280✔
1307
  };
1308

1309
  STFileSet **fsetPtr = TARRAY2_SEARCH(pReader->pTsdb->pFS->fSetArr, &fset, tsdbTFileSetCmprFn, TD_GT);
280✔
1310
  if (fsetPtr == NULL) {
280✔
1311
    pReader->fid = INT32_MAX;
140✔
1312
    return TSDB_CODE_NOT_FOUND;
140✔
1313
  }
1314

1315
  // ref file set
1316
  code = tsdbTFileSetInitRef(pReader->pTsdb, *fsetPtr, &pReader->pFileSet);
140✔
1317
  if (code) return code;
140✔
1318

1319
  // get file set details
1320
  pReader->fid = pReader->pFileSet->fid;
140✔
1321
  tsdbFidKeyRange(pReader->fid, pTsdb->keepCfg.days, pTsdb->keepCfg.precision, &pReader->startTime, &pReader->endTime);
140✔
1322
  if (pTsdb->keepCfg.precision == TSDB_TIME_PRECISION_MICRO) {
140✔
1323
    pReader->startTime /= 1000;
×
1324
    pReader->endTime /= 1000;
×
1325
  } else if (pTsdb->keepCfg.precision == TSDB_TIME_PRECISION_NANO) {
140✔
1326
    pReader->startTime /= 1000000;
×
1327
    pReader->endTime /= 1000000;
×
1328
  }
1329
  pReader->lastCompactTime = pReader->pFileSet->lastCompact;
140✔
1330
  pReader->totalSize = 0;
140✔
1331
  for (int32_t i = 0; i < TSDB_FTYPE_MAX; i++) {
700✔
1332
    STFileObj *fobj = pReader->pFileSet->farr[i];
560✔
1333
    if (fobj) {
560✔
1334
      pReader->totalSize += fobj->f->size;
×
1335
    }
1336
  }
1337
  SSttLvl *lvl;
1338
  TARRAY2_FOREACH(pReader->pFileSet->lvlArr, lvl) {
280✔
1339
    STFileObj *fobj;
1340
    TARRAY2_FOREACH(lvl->fobjArr, fobj) { pReader->totalSize += fobj->f->size; }
280✔
1341
  }
1342

1343
  return code;
140✔
1344
}
1345

1346
int32_t tsdbFileSetReaderNext(struct SFileSetReader *pReader) {
280✔
1347
  int32_t code = TSDB_CODE_SUCCESS;
280✔
1348
  (void)taosThreadMutexLock(&pReader->pTsdb->mutex);
280✔
1349
  code = tsdbFileSetReaderNextNoLock(pReader);
280✔
1350
  (void)taosThreadMutexUnlock(&pReader->pTsdb->mutex);
280✔
1351
  return code;
280✔
1352
}
1353

1354
extern bool tsdbShouldCompact(STFileSet *fset, int32_t vgId, int32_t expLevel, ETsdbOpType type);
1355
int32_t tsdbFileSetGetEntryField(struct SFileSetReader *pReader, const char *field, void *value) {
840✔
1356
  const char *fieldName;
1357

1358
  if (pReader->fid == INT32_MIN || pReader->fid == INT32_MAX) {
840✔
1359
    return TSDB_CODE_INVALID_PARA;
×
1360
  }
1361

1362
  fieldName = "fileset_id";
840✔
1363
  if (strncmp(field, fieldName, strlen(fieldName) + 1) == 0) {
840✔
1364
    *(int32_t *)value = pReader->fid;
140✔
1365
    return TSDB_CODE_SUCCESS;
140✔
1366
  }
1367

1368
  fieldName = "start_time";
700✔
1369
  if (strncmp(field, fieldName, strlen(fieldName) + 1) == 0) {
700✔
1370
    *(int64_t *)value = pReader->startTime;
140✔
1371
    return TSDB_CODE_SUCCESS;
140✔
1372
  }
1373

1374
  fieldName = "end_time";
560✔
1375
  if (strncmp(field, fieldName, strlen(fieldName) + 1) == 0) {
560✔
1376
    *(int64_t *)value = pReader->endTime;
140✔
1377
    return TSDB_CODE_SUCCESS;
140✔
1378
  }
1379

1380
  fieldName = "total_size";
420✔
1381
  if (strncmp(field, fieldName, strlen(fieldName) + 1) == 0) {
420✔
1382
    *(int64_t *)value = pReader->totalSize;
140✔
1383
    return TSDB_CODE_SUCCESS;
140✔
1384
  }
1385

1386
  fieldName = "last_compact_time";
280✔
1387
  if (strncmp(field, fieldName, strlen(fieldName) + 1) == 0) {
280✔
1388
    *(int64_t *)value = pReader->lastCompactTime;
140✔
1389
    return TSDB_CODE_SUCCESS;
140✔
1390
  }
1391

1392
  fieldName = "should_compact";
140✔
1393
  if (strncmp(field, fieldName, strlen(fieldName) + 1) == 0) {
140✔
1394
    *(bool *)value = false;
140✔
1395
#ifdef TD_ENTERPRISE
1396
    *(bool *)value = tsdbShouldCompact(pReader->pFileSet, pReader->pTsdb->pVnode->config.vgId, 0, TSDB_OPTR_NORMAL);
140✔
1397
#endif
1398
    return TSDB_CODE_SUCCESS;
140✔
1399
  }
1400

1401
  fieldName = "details";
×
1402
  if (strncmp(field, fieldName, strlen(fieldName) + 1) == 0) {
×
1403
    // TODO
1404
    return TSDB_CODE_SUCCESS;
×
1405
  }
1406

1407
  return TSDB_CODE_INVALID_PARA;
×
1408
}
1409

1410
void tsdbFileSetReaderClose(struct SFileSetReader **ppReader) {
140✔
1411
  if (ppReader == NULL || *ppReader == NULL) {
140✔
1412
    return;
×
1413
  }
1414

1415
  tsdbTFileSetClear(&(*ppReader)->pFileSet);
140✔
1416
  taosMemoryFree(*ppReader);
140✔
1417

1418
  *ppReader = NULL;
140✔
1419
  return;
140✔
1420
}
1421

1422
static FORCE_INLINE void getLevelSize(const STFileObj *fObj, int64_t szArr[TFS_MAX_TIERS]) {
1423
  if (fObj == NULL) return;
12,172,498✔
1424

1425
  int64_t sz = fObj->f->size;
10,497,546✔
1426
  // level == 0, primary storage
1427
  // level == 1, second storage,
1428
  // level == 2, third storage
1429
  int32_t level = fObj->f->did.level;
10,497,546✔
1430
  if (level >= 0 && level < TFS_MAX_TIERS) {
10,497,546✔
1431
    szArr[level] += sz;
10,497,546✔
1432
  }
1433
}
1434

1435
static FORCE_INLINE int32_t tsdbGetFsSizeImpl(STsdb *tsdb, SDbSizeStatisInfo *pInfo) {
1436
  int32_t code = 0;
6,063,708✔
1437
  int64_t levelSize[TFS_MAX_TIERS] = {0};
6,063,708✔
1438
  int64_t ssSize = 0;
6,063,708✔
1439

1440
  const STFileSet *fset;
1441
  const SSttLvl   *stt = NULL;
6,063,708✔
1442
  const STFileObj *fObj = NULL;
6,063,708✔
1443

1444
  SVnodeCfg *pCfg = &tsdb->pVnode->config;
6,063,708✔
1445
  int64_t    chunksize = (int64_t)pCfg->tsdbPageSize * pCfg->ssChunkSize;
6,063,708✔
1446

1447
  TARRAY2_FOREACH(tsdb->pFS->fSetArr, fset) {
10,581,095✔
1448
    for (int32_t t = TSDB_FTYPE_MIN; t < TSDB_FTYPE_MAX; ++t) {
22,586,935✔
1449
      getLevelSize(fset->farr[t], levelSize);
18,069,548✔
1450
    }
1451

1452
    TARRAY2_FOREACH(fset->lvlArr, stt) {
6,723,550✔
1453
      TARRAY2_FOREACH(stt->fobjArr, fObj) { getLevelSize(fObj, levelSize); }
4,506,411✔
1454
    }
1455

1456
    fObj = fset->farr[TSDB_FTYPE_DATA];
4,517,387✔
1457
    if (fObj) {
4,517,387✔
1458
      int32_t lcn = fObj->f->lcn;
2,729,558✔
1459
      if (lcn > 1) {
2,729,558✔
1460
        ssSize += ((lcn - 1) * chunksize);
×
1461
      }
1462
    }
1463
  }
1464

1465
  pInfo->l1Size = levelSize[0];
6,063,708✔
1466
  pInfo->l2Size = levelSize[1];
6,063,708✔
1467
  pInfo->l3Size = levelSize[2];
6,063,708✔
1468
  pInfo->ssSize = ssSize;
6,063,708✔
1469
  return code;
6,063,708✔
1470
}
1471
int32_t tsdbGetFsSize(STsdb *tsdb, SDbSizeStatisInfo *pInfo) {
6,063,708✔
1472
  int32_t code = 0;
6,063,708✔
1473

1474
  (void)taosThreadMutexLock(&tsdb->mutex);
6,063,708✔
1475
  code = tsdbGetFsSizeImpl(tsdb, pInfo);
6,063,708✔
1476
  (void)taosThreadMutexUnlock(&tsdb->mutex);
6,063,708✔
1477
  return code;
6,063,708✔
1478
}
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