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

taosdata / TDengine / #4986

15 Mar 2026 08:32AM UTC coverage: 37.305% (-31.3%) from 68.601%
#4986

push

travis-ci

tomchon
test: keep docs and unit test

125478 of 336361 relevant lines covered (37.3%)

1134847.06 hits per line

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

64.87
/source/dnode/mnode/sdb/src/sdbFile.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
#define _DEFAULT_SOURCE
17
#include "crypt.h"
18
#include "sdb.h"
19
#include "sync.h"
20
#include "tchecksum.h"
21
#include "tencrypt.h"
22
#include "tglobal.h"
23
#include "tjson.h"
24
#include "wal.h"
25

26
#define SDB_TABLE_SIZE   24
27
#define SDB_RESERVE_SIZE 512
28
#define SDB_FILE_VER     1
29

30
#define SDB_TABLE_SIZE_EXTRA   SDB_MAX
31
#define SDB_RESERVE_SIZE_EXTRA (512 - (SDB_TABLE_SIZE_EXTRA - SDB_TABLE_SIZE) * 2 * sizeof(int64_t))
32

33
// Forward declaration
34
static int32_t sdbWriteFileImp(SSdb *pSdb, int32_t skip_type);
35

36
static int32_t sdbDeployData(SSdb *pSdb) {
22✔
37
  int32_t code = 0;
22✔
38
  mInfo("start to deploy sdb");
22✔
39

40
  for (int32_t i = SDB_MAX - 1; i >= 0; --i) {
1,056✔
41
    SdbDeployFp fp = pSdb->deployFps[i];
1,034✔
42
    if (fp == NULL) continue;
1,034✔
43

44
    mInfo("start to deploy sdb:%s", sdbTableName(i));
118✔
45
    code = (*fp)(pSdb->pMnode);
118✔
46
    if (code != 0) {
118✔
47
      mError("failed to deploy sdb:%s since %s", sdbTableName(i), tstrerror(code));
×
48
      return -1;
×
49
    }
50
  }
51

52
  mInfo("sdb deploy success");
22✔
53
  return 0;
22✔
54
}
55

56
static int32_t sdbUpgradeData(SSdb *pSdb, int32_t version) {
16✔
57
  int32_t code = 0;
16✔
58
  mInfo("start to upgrade sdb");
16✔
59

60
  for (int32_t i = SDB_MAX - 1; i >= 0; --i) {
768✔
61
    SdbUpgradeFp fp = pSdb->upgradeFps[i];
752✔
62
    if (fp == NULL) continue;
752✔
63

64
    mInfo("start to upgrade sdb:%s", sdbTableName(i));
48✔
65
    code = (*fp)(pSdb->pMnode, version);
48✔
66
    if (code != 0) {
48✔
67
      mError("failed to upgrade sdb:%s since %s", sdbTableName(i), tstrerror(code));
×
68
      return -1;
×
69
    }
70
  }
71

72
  mInfo("sdb upgrade success");
16✔
73
  return 0;
16✔
74
}
75

76
static int32_t sdbAfterRestoredData(SSdb *pSdb) {
×
77
  int32_t code = 0;
×
78
  mInfo("start to prepare sdb");
×
79

80
  for (int32_t i = SDB_MAX - 1; i >= 0; --i) {
×
81
    SdbAfterRestoredFp fp = pSdb->afterRestoredFps[i];
×
82
    if (fp == NULL) continue;
×
83

84
    mInfo("start to prepare sdb:%s", sdbTableName(i));
×
85
    code = (*fp)(pSdb->pMnode);
×
86
    if (code != 0) {
×
87
      mError("failed to prepare sdb:%s since %s", sdbTableName(i), tstrerror(code));
×
88
      return -1;
×
89
    }
90
  }
91

92
  mInfo("sdb prepare success");
×
93
  return 0;
×
94
}
95

96
static void sdbResetData(SSdb *pSdb) {
10✔
97
  mInfo("start to reset sdb");
10✔
98

99
  for (ESdbType i = 0; i < SDB_MAX; ++i) {
480✔
100
    SHashObj *hash = pSdb->hashObjs[i];
470✔
101
    if (hash == NULL) continue;
470✔
102

103
    sdbWriteLock(pSdb, i);
18✔
104

105
    SSdbRow **ppRow = taosHashIterate(hash, NULL);
18✔
106
    while (ppRow != NULL) {
28✔
107
      SSdbRow *pRow = *ppRow;
10✔
108
      if (pRow == NULL) continue;
10✔
109

110
      sdbFreeRow(pSdb, pRow, true);
10✔
111
      ppRow = taosHashIterate(hash, ppRow);
10✔
112
    }
113

114
    taosHashClear(pSdb->hashObjs[i]);
18✔
115
    pSdb->tableVer[i] = 0;
18✔
116
    pSdb->maxId[i] = 0;
18✔
117

118
    sdbUnLock(pSdb, i);
18✔
119

120
    mInfo("sdb:%s is reset", sdbTableName(i));
18✔
121
  }
122

123
  pSdb->applyIndex = -1;
10✔
124
  pSdb->applyTerm = -1;
10✔
125
  pSdb->applyConfig = -1;
10✔
126
  pSdb->commitIndex = -1;
10✔
127
  pSdb->commitTerm = -1;
10✔
128
  pSdb->commitConfig = -1;
10✔
129
  mInfo("sdb reset success");
10✔
130
}
10✔
131

132
static int32_t sdbReadFileHead(SSdb *pSdb, TdFilePtr pFile) {
10✔
133
  int32_t code = 0;
10✔
134
  int64_t sver = 0;
10✔
135
  int32_t ret = taosReadFile(pFile, &sver, sizeof(int64_t));
10✔
136
  if (ret < 0) {
10✔
137
    return terrno;
×
138
  }
139
  if (ret != sizeof(int64_t)) {
10✔
140
    code = TSDB_CODE_FILE_CORRUPTED;
×
141
    TAOS_RETURN(code);
×
142
  }
143
  if (sver != SDB_FILE_VER) {
10✔
144
    code = TSDB_CODE_FILE_CORRUPTED;
×
145
    TAOS_RETURN(code);
×
146
  }
147

148
  ret = taosReadFile(pFile, &pSdb->applyIndex, sizeof(int64_t));
10✔
149
  if (ret < 0) {
10✔
150
    return terrno;
×
151
  }
152
  if (ret != sizeof(int64_t)) {
10✔
153
    code = TSDB_CODE_FILE_CORRUPTED;
×
154
    TAOS_RETURN(code);
×
155
  }
156

157
  ret = taosReadFile(pFile, &pSdb->applyTerm, sizeof(int64_t));
10✔
158
  if (ret < 0) {
10✔
159
    return terrno;
×
160
  }
161
  if (ret != sizeof(int64_t)) {
10✔
162
    code = TSDB_CODE_FILE_CORRUPTED;
×
163
    TAOS_RETURN(code);
×
164
  }
165

166
  ret = taosReadFile(pFile, &pSdb->applyConfig, sizeof(int64_t));
10✔
167
  if (ret < 0) {
10✔
168
    return terrno;
×
169
  }
170
  if (ret != sizeof(int64_t)) {
10✔
171
    code = TSDB_CODE_FILE_CORRUPTED;
×
172
    TAOS_RETURN(code);
×
173
  }
174

175
  for (int32_t i = 0; i < SDB_TABLE_SIZE; ++i) {
250✔
176
    int64_t maxId = 0;
240✔
177
    ret = taosReadFile(pFile, &maxId, sizeof(int64_t));
240✔
178
    if (ret < 0) {
240✔
179
      return terrno;
×
180
    }
181
    if (ret != sizeof(int64_t)) {
240✔
182
      code = TSDB_CODE_FILE_CORRUPTED;
×
183
      TAOS_RETURN(code);
×
184
    }
185
    if (i < SDB_MAX) {
240✔
186
      pSdb->maxId[i] = maxId;
240✔
187
    }
188
  }
189

190
  for (int32_t i = 0; i < SDB_TABLE_SIZE; ++i) {
250✔
191
    int64_t ver = 0;
240✔
192
    ret = taosReadFile(pFile, &ver, sizeof(int64_t));
240✔
193
    if (ret < 0) {
240✔
194
      return terrno;
×
195
    }
196
    if (ret != sizeof(int64_t)) {
240✔
197
      code = TSDB_CODE_FILE_CORRUPTED;
×
198
      TAOS_RETURN(code);
×
199
    }
200
    if (i < SDB_MAX) {
240✔
201
      pSdb->tableVer[i] = ver;
240✔
202
    }
203
  }
204

205
  // for sdb compatibility
206
  for (int32_t i = SDB_TABLE_SIZE; i < SDB_TABLE_SIZE_EXTRA; ++i) {
240✔
207
    int64_t maxId = 0;
230✔
208
    ret = taosReadFile(pFile, &maxId, sizeof(int64_t));
230✔
209
    if (ret < 0) {
230✔
210
      code = TAOS_SYSTEM_ERROR(ERRNO);
×
211
      TAOS_RETURN(code);
×
212
    }
213
    if (ret != sizeof(int64_t)) {
230✔
214
      code = TSDB_CODE_FILE_CORRUPTED;
×
215
      TAOS_RETURN(code);
×
216
    }
217
    if (i < SDB_MAX) {
230✔
218
      pSdb->maxId[i] = maxId;
230✔
219
    }
220

221
    int64_t ver = 0;
230✔
222
    ret = taosReadFile(pFile, &ver, sizeof(int64_t));
230✔
223
    if (ret < 0) {
230✔
224
      code = TAOS_SYSTEM_ERROR(ERRNO);
×
225
      TAOS_RETURN(code);
×
226
    }
227
    if (ret != sizeof(int64_t)) {
230✔
228
      code = TSDB_CODE_FILE_CORRUPTED;
×
229
      TAOS_RETURN(code);
×
230
    }
231
    if (i < SDB_MAX) {
230✔
232
      pSdb->tableVer[i] = ver;
230✔
233
    }
234
  }
235

236
  char reserve[SDB_RESERVE_SIZE_EXTRA] = {0};
10✔
237
  ret = taosReadFile(pFile, reserve, sizeof(reserve));
10✔
238
  if (ret < 0) {
10✔
239
    return terrno;
×
240
  }
241
  if (ret != sizeof(reserve)) {
10✔
242
    code = TSDB_CODE_FILE_CORRUPTED;
×
243
    TAOS_RETURN(code);
×
244
  }
245

246
  return 0;
10✔
247
}
248

249
static int32_t sdbWriteFileHead(SSdb *pSdb, TdFilePtr pFile) {
51✔
250
  int64_t sver = SDB_FILE_VER;
51✔
251
  if (taosWriteFile(pFile, &sver, sizeof(int64_t)) != sizeof(int64_t)) {
51✔
252
    return terrno;
×
253
  }
254

255
  mInfo("vgId:1, write sdb file with sdb applyIndex:%" PRId64 " term:%" PRId64 " config:%" PRId64, pSdb->applyIndex,
51✔
256
        pSdb->applyTerm, pSdb->applyConfig);
257
  if (taosWriteFile(pFile, &pSdb->applyIndex, sizeof(int64_t)) != sizeof(int64_t)) {
51✔
258
    return terrno;
×
259
  }
260

261
  if (taosWriteFile(pFile, &pSdb->applyTerm, sizeof(int64_t)) != sizeof(int64_t)) {
51✔
262
    return terrno;
×
263
  }
264

265
  if (taosWriteFile(pFile, &pSdb->applyConfig, sizeof(int64_t)) != sizeof(int64_t)) {
51✔
266
    return terrno;
×
267
  }
268

269
  for (int32_t i = 0; i < SDB_TABLE_SIZE; ++i) {
1,275✔
270
    int64_t maxId = 0;
1,224✔
271
    if (i < SDB_MAX) {
1,224✔
272
      maxId = pSdb->maxId[i];
1,224✔
273
    }
274
    if (taosWriteFile(pFile, &maxId, sizeof(int64_t)) != sizeof(int64_t)) {
1,224✔
275
      return terrno;
×
276
    }
277
  }
278

279
  for (int32_t i = 0; i < SDB_TABLE_SIZE; ++i) {
1,275✔
280
    int64_t ver = 0;
1,224✔
281
    if (i < SDB_MAX) {
1,224✔
282
      ver = pSdb->tableVer[i];
1,224✔
283
    }
284
    if (taosWriteFile(pFile, &ver, sizeof(int64_t)) != sizeof(int64_t)) {
1,224✔
285
      return terrno;
×
286
    }
287
  }
288

289
  // for sdb compatibility
290
  for (int32_t i = SDB_TABLE_SIZE; i < SDB_TABLE_SIZE_EXTRA; ++i) {
1,224✔
291
    int64_t maxId = 0;
1,173✔
292
    if (i < SDB_MAX) {
1,173✔
293
      maxId = pSdb->maxId[i];
1,173✔
294
    }
295
    if (taosWriteFile(pFile, &maxId, sizeof(int64_t)) != sizeof(int64_t)) {
1,173✔
296
      return terrno;
×
297
    }
298

299
    int64_t ver = 0;
1,173✔
300
    if (i < SDB_MAX) {
1,173✔
301
      ver = pSdb->tableVer[i];
1,173✔
302
    }
303
    if (taosWriteFile(pFile, &ver, sizeof(int64_t)) != sizeof(int64_t)) {
1,173✔
304
      return terrno;
×
305
    }
306
  }
307

308
  char reserve[SDB_RESERVE_SIZE_EXTRA] = {0};
51✔
309
  if (taosWriteFile(pFile, reserve, sizeof(reserve)) != sizeof(reserve)) {
51✔
310
    return terrno;
×
311
  }
312

313
  return 0;
51✔
314
}
315

316
// Read encrypted flag from mnode.json for defensive check
317
// This is more reliable than heuristics when receiving snapshots
318
static bool sdbReadEncryptedFlagFromMnodeJson(SSdb *pSdb) {
6✔
319
  if (pSdb->mnodePath[0] == '\0') {
6✔
320
    // No mnode path configured, use heuristic
321
    return (tsMetaKey[0] != '\0');
×
322
  }
323

324
  // Read the encrypted flag from mnode.json
325
  char file[PATH_MAX] = {0};
6✔
326
  snprintf(file, sizeof(file), "%s%smnode.json", pSdb->mnodePath, TD_DIRSEP);
6✔
327

328
  // Try to read mnode.json
329
  char   *pData = NULL;
6✔
330
  int32_t dataLen = 0;
6✔
331
  if (taosReadCfgFile(file, &pData, &dataLen) != 0) {
6✔
332
    // Cannot read, use heuristic
333
    return (tsMetaKey[0] != '\0');
2✔
334
  }
335

336
  SJson *pJson = tjsonParse(pData);
4✔
337
  taosMemoryFree(pData);
4✔
338

339
  if (pJson == NULL) {
4✔
340
    return (tsMetaKey[0] != '\0');
×
341
  }
342

343
  // Read encrypted field (default to false if not found)
344
  int32_t encrypted = 0;
4✔
345
  int32_t code = 0;
4✔
346
  tjsonGetInt32ValueFromDouble(pJson, "encrypted", encrypted, code);
4✔
347
  cJSON_Delete(pJson);
4✔
348

349
  return (encrypted != 0);
4✔
350
}
351

352
static int32_t sdbReadFileImp(SSdb *pSdb) {
10✔
353
  int64_t offset = 0;
10✔
354
  int32_t code = 0;
10✔
355
  int32_t readLen = 0;
10✔
356
  int64_t ret = 0;
10✔
357
  char    file[PATH_MAX] = {0};
10✔
358
  int32_t bufLen = TSDB_MAX_MSG_SIZE;
10✔
359
  bool    needMigration = false;
10✔
360

361
  snprintf(file, sizeof(file), "%s%ssdb.data", pSdb->currDir, TD_DIRSEP);
10✔
362

363
  // Wait for encryption keys to be loaded
364
  code = taosWaitCfgKeyLoaded();
10✔
365
  if (code != 0) {
10✔
366
    mError("failed to wait for encryption keys since %s", tstrerror(code));
×
367
    return code;
×
368
  }
369

370
  // Check if sdb.data needs encryption migration
371
  // This info is stored in mnode.json encrypted flag
372
  bool isEncrypted = pSdb->encrypted;
10✔
373
  if (!isEncrypted && tsMetaKey[0] != '\0') {
10✔
374
    mInfo("sdb.data not encrypted but tsMetaKey available, checking encrypted flag from mnode.json");
4✔
375
    isEncrypted = sdbReadEncryptedFlagFromMnodeJson(pSdb);  // Fix: don't redeclare, just assign
4✔
376
    if (isEncrypted) {
4✔
377
      mInfo("reload encrypted flag from mnode.json is true, will not migrate after reading");
×
378
      needMigration = false;
×
379
    } else {
380
      mInfo("reload encrypted flag from mnode.json is false, will migrate after reading");
4✔
381
      needMigration = true;
4✔
382
    }
383
  }
384

385
  pSdb->encrypted = isEncrypted;
10✔
386

387
  mInfo("start to read sdb file:%s, encrypted:%d, needMigration:%d", file, isEncrypted, needMigration);
10✔
388

389
  SSdbRaw *pRaw = taosMemoryMalloc(bufLen + 100);
10✔
390
  if (pRaw == NULL) {
10✔
391
    code = terrno;
×
392
    mError("failed read sdb file since %s", tstrerror(code));
×
393
    TAOS_RETURN(code);
×
394
  }
395

396
  TdFilePtr pFile = taosOpenFile(file, TD_FILE_READ);
10✔
397
  if (pFile == NULL) {
10✔
398
    taosMemoryFree(pRaw);
×
399
    code = terrno;
×
400
    mInfo("read sdb file:%s finished since %s", file, tstrerror(code));
×
401
    return 0;
×
402
  }
403

404
  code = sdbReadFileHead(pSdb, pFile);
10✔
405
  if (code != 0) {
10✔
406
    mError("failed to read sdb file:%s head since %s", file, tstrerror(code));
×
407
    taosMemoryFree(pRaw);
×
408
    int32_t ret = 0;
×
409
    if ((ret = taosCloseFile(&pFile)) != 0) {
×
410
      mError("failed to close sdb file:%s since %s", file, tstrerror(ret));
×
411
    }
412
    return code;
×
413
  }
414

415
  int64_t tableVer[SDB_MAX] = {0};
10✔
416
  memcpy(tableVer, pSdb->tableVer, sizeof(tableVer));
10✔
417

418
  while (1) {
30✔
419
    readLen = sizeof(SSdbRaw);
40✔
420
    ret = taosReadFile(pFile, pRaw, readLen);
40✔
421
    if (ret == 0) break;
40✔
422

423
    if (ret < 0) {
30✔
424
      code = terrno;
×
425
      mError("failed to read sdb file:%s since %s", file, tstrerror(code));
×
426
      goto _OVER;
×
427
    }
428

429
    if (ret != readLen) {
30✔
430
      code = TSDB_CODE_FILE_CORRUPTED;
×
431
      mError("failed to read sdb file:%s since %s, ret:%" PRId64 " != readLen:%d", file, tstrerror(code), ret, readLen);
×
432
      goto _OVER;
×
433
    }
434

435
    readLen = pRaw->dataLen + sizeof(int32_t);
30✔
436
    if (tsMetaKey[0] != '\0' && !needMigration) {
30✔
437
      readLen = ENCRYPTED_LEN(pRaw->dataLen) + sizeof(int32_t);
6✔
438
    }
439
    if (readLen >= bufLen) {
30✔
440
      bufLen = pRaw->dataLen * 2;
×
441
      SSdbRaw *pNewRaw = taosMemoryMalloc(bufLen + 100);
×
442
      if (pNewRaw == NULL) {
×
443
        code = terrno;
×
444
        mError("failed read sdb file since malloc new sdbRaw size:%d failed", bufLen);
×
445
        goto _OVER;
×
446
      }
447
      mInfo("malloc new sdb raw size:%d, type:%d", bufLen, pRaw->type);
×
448
      memcpy(pNewRaw, pRaw, sizeof(SSdbRaw));
×
449
      sdbFreeRaw(pRaw);
×
450
      pRaw = pNewRaw;
×
451
    }
452

453
    ret = taosReadFile(pFile, pRaw->pData, readLen);
30✔
454
    if (ret < 0) {
30✔
455
      code = terrno;
×
456
      mError("failed to read sdb file:%s since %s, ret:%" PRId64 " readLen:%d", file, tstrerror(code), ret, readLen);
×
457
      goto _OVER;
×
458
    }
459

460
    if (ret != readLen) {
30✔
461
      code = TSDB_CODE_FILE_CORRUPTED;
×
462
      mError("failed to read sdb file:%s since %s, ret:%" PRId64 " != readLen:%d", file, tstrerror(code), ret, readLen);
×
463
      goto _OVER;
×
464
    }
465

466
    if (taosWaitCfgKeyLoaded() != 0) {
30✔
467
      code = terrno;
×
468
      goto _OVER;
×
469
    }
470

471
    if (tsMetaKey[0] != '\0' && !needMigration) {
30✔
472
      int32_t count = 0;
6✔
473

474
      char *plantContent = taosMemoryMalloc(ENCRYPTED_LEN(pRaw->dataLen));
6✔
475
      if (plantContent == NULL) {
6✔
476
        code = terrno;
×
477
        goto _OVER;
×
478
      }
479

480
      SCryptOpts opts = {0};
6✔
481
      opts.len = ENCRYPTED_LEN(pRaw->dataLen);
6✔
482
      opts.source = pRaw->pData;
6✔
483
      opts.result = plantContent;
6✔
484
      opts.unitLen = 16;
6✔
485
      opts.pOsslAlgrName = taosGetEncryptAlgoName(tsEncryptAlgorithmType);
6✔
486
      tstrncpy(opts.key, tsMetaKey, ENCRYPT_KEY_LEN + 1);
6✔
487

488
      count = CBC_Decrypt(&opts);
6✔
489
      if (count <= 0) {
6✔
490
        code = terrno;
×
491
        goto _OVER;
×
492
      }
493

494
      // mDebug("read sdb, CBC Decrypt dataLen:%d, descrypted len:%d, %s", pRaw->dataLen, count, __FUNCTION__);
495

496
      memcpy(pRaw->pData, plantContent, pRaw->dataLen);
6✔
497
      taosMemoryFree(plantContent);
6✔
498
      memcpy(pRaw->pData + pRaw->dataLen, &pRaw->pData[ENCRYPTED_LEN(pRaw->dataLen)], sizeof(int32_t));
6✔
499
    }
500

501
    int32_t totalLen = sizeof(SSdbRaw) + pRaw->dataLen + sizeof(int32_t);
30✔
502
    if ((!taosCheckChecksumWhole((const uint8_t *)pRaw, totalLen)) != 0) {
60✔
503
      code = TSDB_CODE_CHECKSUM_ERROR;
×
504
      mError("failed to read sdb file:%s since %s, readLen:%d", file, tstrerror(code), readLen);
×
505
      goto _OVER;
×
506
    }
507

508
    if (pRaw->type >= SDB_MAX) {
30✔
509
      mInfo("skip sdb raw type:%d since it is not supported", pRaw->type);
×
510
      continue;
×
511
    }
512

513
    code = sdbWriteWithoutFree(pSdb, pRaw);
30✔
514
    if (code != 0) {
30✔
515
      mError("failed to exec sdbWrite while read sdb file:%s since %s", file, terrstr());
×
516
      goto _OVER;
×
517
    }
518
  }
519

520
  code = 0;
10✔
521
  pSdb->commitIndex = pSdb->applyIndex;
10✔
522
  pSdb->commitTerm = pSdb->applyTerm;
10✔
523
  pSdb->commitConfig = pSdb->applyConfig;
10✔
524
  memcpy(pSdb->tableVer, tableVer, sizeof(tableVer));
10✔
525
  mInfo("vgId:1, trans:0, read sdb file:%s success, commit index:%" PRId64 " term:%" PRId64 " config:%" PRId64, file,
10✔
526
        pSdb->commitIndex, pSdb->commitTerm, pSdb->commitConfig);
527

528
_OVER:
×
529
  if ((ret = taosCloseFile(&pFile)) != 0) {
10✔
530
    mError("failed to close sdb file:%s since %s", file, tstrerror(ret));
×
531
  }
532
  sdbFreeRaw(pRaw);
10✔
533

534
  TAOS_RETURN(code);
10✔
535
}
536

537
int32_t sdbReadFile(SSdb *pSdb) {
10✔
538
  (void)taosThreadMutexLock(&pSdb->filelock);
10✔
539

540
  sdbResetData(pSdb);
10✔
541
  int32_t code = sdbReadFileImp(pSdb);
10✔
542
  if (code != 0) {
10✔
543
    mError("failed to read sdb file since %s", tstrerror(code));
×
544
    sdbResetData(pSdb);
×
545
    return code;
×
546
  }
547

548
  // Check if sdb.data needs encryption migration
549
  bool isEncrypted = pSdb->encrypted;
10✔
550
  if (!isEncrypted && tsMetaKey[0] != '\0') {
10✔
551
    mInfo("sdb.data read successfully, now migrating to encrypted format");
4✔
552

553
    // Rewrite sdb.data with encryption (atomic operation)
554
    code = sdbWriteFileImp(pSdb, -1);
4✔
555
    if (code != 0) {
4✔
556
      mError("failed to migrate sdb.data to encrypted format since %s", tstrerror(code));
×
557
      // Don't fail the read, continue
558
      (void)taosThreadMutexUnlock(&pSdb->filelock);
×
559
      return code;
×
560
    }
561

562
    // Update encrypted flag and persist to mnode.json immediately (atomic operation)
563
    pSdb->encrypted = true;
4✔
564

565
    if (pSdb->persistEncryptedFlagFp != NULL && pSdb->pMnodeForCallback != NULL) {
4✔
566
      code = pSdb->persistEncryptedFlagFp(pSdb->pMnodeForCallback);
4✔
567
      if (code == 0) {
4✔
568
        mInfo("sdb.data migrated to encrypted format and persisted encrypted flag to mnode.json successfully");
4✔
569
      } else {
570
        mError("failed to persist encrypted flag to mnode.json since %s", tstrerror(code));
×
571
        // Rollback encrypted flag
572
        pSdb->encrypted = false;
×
573
      }
574
    } else {
575
      mWarn("sdb.data migrated to encrypted format but no callback to persist flag");
×
576
    }
577
  }
578

579
  (void)taosThreadMutexUnlock(&pSdb->filelock);
10✔
580
  return code;
10✔
581
}
582

583
int32_t sdbWriteFileImp(SSdb *pSdb, int32_t skip_type) {
51✔
584
  int32_t code = 0;
51✔
585

586
  char tmpfile[PATH_MAX] = {0};
51✔
587
  snprintf(tmpfile, sizeof(tmpfile), "%s%ssdb.data", pSdb->tmpDir, TD_DIRSEP);
51✔
588
  char curfile[PATH_MAX] = {0};
51✔
589
  snprintf(curfile, sizeof(curfile), "%s%ssdb.data", pSdb->currDir, TD_DIRSEP);
51✔
590

591
  mInfo("start to write sdb file, apply index:%" PRId64 " term:%" PRId64 " config:%" PRId64 ", commit index:%" PRId64
51✔
592
        " term:%" PRId64 " config:%" PRId64 ", file:%s",
593
        pSdb->applyIndex, pSdb->applyTerm, pSdb->applyConfig, pSdb->commitIndex, pSdb->commitTerm, pSdb->commitConfig,
594
        curfile);
595

596
  TdFilePtr pFile = taosOpenFile(tmpfile, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
51✔
597
  if (pFile == NULL) {
51✔
598
    code = terrno;
×
599
    mError("failed to open sdb file:%s for write since %s", tmpfile, tstrerror(code));
×
600
    TAOS_RETURN(code);
×
601
  }
602

603
  code = sdbWriteFileHead(pSdb, pFile);
51✔
604
  if (code != 0) {
51✔
605
    mError("failed to write sdb file:%s head since %s", tmpfile, tstrerror(code));
×
606
    int32_t ret = 0;
×
607
    if ((ret = taosCloseFile(&pFile)) != 0) {
×
608
      mError("failed to close sdb file:%s since %s", tmpfile, tstrerror(ret));
×
609
    }
610
    return code;
×
611
  }
612

613
  for (int32_t i = SDB_MAX - 1; i >= 0; --i) {
2,448✔
614
    if (i == skip_type) continue;
2,397✔
615
    SdbEncodeFp encodeFp = pSdb->encodeFps[i];
2,397✔
616
    if (encodeFp == NULL) continue;
2,397✔
617

618
    mInfo("write %s to sdb file, total %d rows", sdbTableName(i), sdbGetSize(pSdb, i));
1,654✔
619

620
    SHashObj *hash = pSdb->hashObjs[i];
1,654✔
621
    sdbWriteLock(pSdb, i);
1,654✔
622

623
    SSdbRow **ppRow = taosHashIterate(hash, NULL);
1,654✔
624
    while (ppRow != NULL) {
2,307✔
625
      SSdbRow *pRow = *ppRow;
653✔
626
      if (pRow == NULL) {
653✔
627
        ppRow = taosHashIterate(hash, ppRow);
×
628
        continue;
×
629
      }
630

631
      if (pRow->status != SDB_STATUS_READY && pRow->status != SDB_STATUS_DROPPING) {
653✔
632
        sdbPrintOper(pSdb, pRow, "not-write");
×
633
        ppRow = taosHashIterate(hash, ppRow);
×
634
        continue;
×
635
      }
636

637
      sdbPrintOper(pSdb, pRow, "write");
653✔
638

639
      SSdbRaw *pRaw = (*encodeFp)(pRow->pObj);
653✔
640
      if (pRaw != NULL) {
653✔
641
        pRaw->status = pRow->status;
653✔
642

643
        if (taosWriteFile(pFile, pRaw, sizeof(SSdbRaw)) != sizeof(SSdbRaw)) {
653✔
644
          code = terrno;
×
645
          taosHashCancelIterate(hash, ppRow);
×
646
          sdbFreeRaw(pRaw);
×
647
          break;
×
648
        }
649

650
        int32_t newDataLen = pRaw->dataLen;
653✔
651
        char   *newData = pRaw->pData;
653✔
652

653
        if (taosWaitCfgKeyLoaded() != 0) {
653✔
654
          code = terrno;
×
655
          taosHashCancelIterate(hash, ppRow);
×
656
          sdbFreeRaw(pRaw);
×
657
          break;
×
658
        }
659

660
        if (tsMetaKey[0] != '\0') {
653✔
661
          newDataLen = ENCRYPTED_LEN(pRaw->dataLen);
14✔
662
          newData = taosMemoryMalloc(newDataLen);
14✔
663
          if (newData == NULL) {
14✔
664
            code = terrno;
×
665
            taosHashCancelIterate(hash, ppRow);
×
666
            sdbFreeRaw(pRaw);
×
667
            break;
×
668
          }
669

670
          SCryptOpts opts = {0};
14✔
671
          opts.len = newDataLen;
14✔
672
          opts.source = pRaw->pData;
14✔
673
          opts.result = newData;
14✔
674
          opts.unitLen = 16;
14✔
675
          opts.pOsslAlgrName = taosGetEncryptAlgoName(tsEncryptAlgorithmType);
14✔
676
          tstrncpy(opts.key, tsMetaKey, ENCRYPT_KEY_LEN + 1);
14✔
677

678
          int32_t count = CBC_Encrypt(&opts);
14✔
679
          if (count <= 0) {
14✔
680
            code = terrno;
×
681
            taosHashCancelIterate(hash, ppRow);
×
682
            sdbFreeRaw(pRaw);
×
683
            break;
×
684
          }
685

686
          // mDebug("write sdb, CBC Encrypt encryptedDataLen:%d, dataLen:%d, %s",
687
          //       newDataLen, pRaw->dataLen, __FUNCTION__);
688
        }
689

690
        if (taosWriteFile(pFile, newData, newDataLen) != newDataLen) {
653✔
691
          code = terrno;
×
692
          taosHashCancelIterate(hash, ppRow);
×
693
          sdbFreeRaw(pRaw);
×
694
          break;
×
695
        }
696

697
        if (tsMetaKey[0] != '\0') {
653✔
698
          taosMemoryFree(newData);
14✔
699
        }
700

701
        int32_t cksum = taosCalcChecksum(0, (const uint8_t *)pRaw, sizeof(SSdbRaw) + pRaw->dataLen);
653✔
702
        if (taosWriteFile(pFile, &cksum, sizeof(int32_t)) != sizeof(int32_t)) {
653✔
703
          code = terrno;
×
704
          taosHashCancelIterate(hash, ppRow);
×
705
          sdbFreeRaw(pRaw);
×
706
          break;
×
707
        }
708
      } else {
709
        code = TSDB_CODE_APP_ERROR;
×
710
        taosHashCancelIterate(hash, ppRow);
×
711
        break;
×
712
      }
713

714
      sdbFreeRaw(pRaw);
653✔
715
      ppRow = taosHashIterate(hash, ppRow);
653✔
716
    }
717
    sdbUnLock(pSdb, i);
1,654✔
718
  }
719

720
  if (code == 0) {
51✔
721
    code = taosFsyncFile(pFile);
51✔
722
    if (code != 0) {
51✔
723
      code = TAOS_SYSTEM_ERROR(ERRNO);
×
724
      mError("failed to sync sdb file:%s since %s", tmpfile, tstrerror(code));
×
725
    }
726
  }
727

728
  if (taosCloseFile(&pFile) != 0) {
51✔
729
    code = taosRenameFile(tmpfile, curfile);
×
730
  }
731

732
  if (code == 0) {
51✔
733
    code = taosRenameFile(tmpfile, curfile);
51✔
734
    if (code != 0) {
51✔
735
      mError("failed to write sdb file:%s since %s", curfile, tstrerror(code));
×
736
    }
737
  }
738

739
  if (code != 0) {
51✔
740
    mError("failed to write sdb file:%s since %s", curfile, tstrerror(code));
×
741
  } else {
742
    pSdb->commitIndex = pSdb->applyIndex;
51✔
743
    pSdb->commitTerm = pSdb->applyTerm;
51✔
744
    pSdb->commitConfig = pSdb->applyConfig;
51✔
745
    mInfo("vgId:1, trans:0, write sdb file success, commit index:%" PRId64 " term:%" PRId64 " config:%" PRId64
51✔
746
          " file:%s",
747
          pSdb->commitIndex, pSdb->commitTerm, pSdb->commitConfig, curfile);
748

749
    if (tsMetaKey[0] != '\0') {
51✔
750
      if (pSdb->persistEncryptedFlagFp != NULL && pSdb->pMnodeForCallback != NULL) {
6✔
751
        code = pSdb->persistEncryptedFlagFp(pSdb->pMnodeForCallback);
6✔
752
        if (code == 0) {
6✔
753
          mInfo("sdb.data now is encrypted format and persisted encrypted flag to mnode.json successfully");
6✔
754
          pSdb->encrypted = true;
6✔
755
        } else {
756
          mError("failed to persist encrypted flag to mnode.json since %s", tstrerror(code));
×
757
          return code;
×
758
        }
759
      } else {
760
        mWarn("sdb.data written in encrypted format but no callback to persist flag");
×
761
        pSdb->encrypted = true;
×
762
      }
763
    }
764
  }
765

766
  terrno = code;
51✔
767
  return code;
51✔
768
}
769

770
int32_t sdbWriteFile(SSdb *pSdb, int32_t delta) {
754✔
771
  int32_t code = 0;
754✔
772
  if (pSdb->applyIndex == pSdb->commitIndex) {
754✔
773
    return 0;
47✔
774
  }
775

776
  if (pSdb->applyIndex - pSdb->commitIndex < delta) {
707✔
777
    return 0;
660✔
778
  }
779

780
  (void)taosThreadMutexLock(&pSdb->filelock);
47✔
781
  if (pSdb->pWal != NULL) {
47✔
782
    if (pSdb->sync > 0) {
39✔
783
      code = syncBeginSnapshot(pSdb->sync, pSdb->applyIndex);
39✔
784
    }
785
  }
786
  if (code == 0) {
47✔
787
    code = sdbWriteFileImp(pSdb, -1);
47✔
788
  }
789
  if (code == 0) {
47✔
790
    if (pSdb->pWal != NULL) {
47✔
791
      if (pSdb->sync > 0) {
39✔
792
        code = syncEndSnapshot(pSdb->sync, false);
39✔
793
      }
794
    }
795
  }
796
  if (code != 0) {
47✔
797
    mError("failed to write sdb file since %s", tstrerror(code));
×
798
  } else {
799
    mInfo("vgId:1, trans:0, write sdb file success, apply index:%" PRId64 ", term:%" PRId64 ", config:%" PRId64,
47✔
800
          pSdb->applyIndex, pSdb->applyTerm, pSdb->applyConfig);
801
  }
802
  (void)taosThreadMutexUnlock(&pSdb->filelock);
47✔
803

804
  return code;
47✔
805
}
806

807
int32_t sdbWriteFileForDump(SSdb *pSdb, int32_t skip_type) {
×
808
  int32_t code = 0;
×
809

810
  code = sdbWriteFileImp(pSdb, skip_type);
×
811

812
  return code;
×
813
}
814

815
int32_t sdbDeploy(SSdb *pSdb) {
22✔
816
  int32_t code = 0;
22✔
817
  code = sdbDeployData(pSdb);
22✔
818
  if (code != 0) {
22✔
819
    TAOS_RETURN(code);
×
820
  }
821

822
  code = sdbWriteFile(pSdb, 0);
22✔
823
  if (code != 0) {
22✔
824
    TAOS_RETURN(code);
×
825
  }
826

827
  return 0;
22✔
828
}
829

830
int32_t sdbUpgrade(SSdb *pSdb, int32_t version) {
16✔
831
  int32_t code = 0;
16✔
832
  code = sdbUpgradeData(pSdb, version);
16✔
833
  if (code != 0) {
16✔
834
    TAOS_RETURN(code);
×
835
  }
836

837
  code = sdbWriteFile(pSdb, 0);
16✔
838
  if (code != 0) {
16✔
839
    TAOS_RETURN(code);
×
840
  }
841

842
  return 0;
16✔
843
}
844

845
int32_t sdbAfterRestored(SSdb *pSdb) {
×
846
  int32_t code = 0;
×
847
  code = sdbAfterRestoredData(pSdb);
×
848
  if (code != 0) {
×
849
    TAOS_RETURN(code);
×
850
  }
851
  return 0;
×
852
}
853

854
static SSdbIter *sdbCreateIter(SSdb *pSdb) {
4✔
855
  SSdbIter *pIter = taosMemoryCalloc(1, sizeof(SSdbIter));
4✔
856
  if (pIter == NULL) {
4✔
857
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
858
    return NULL;
×
859
  }
860

861
  char name[PATH_MAX + 100] = {0};
4✔
862
  snprintf(name, sizeof(name), "%s%ssdb.data.%" PRIu64, pSdb->tmpDir, TD_DIRSEP, (uint64_t)pIter);
4✔
863
  pIter->name = taosStrdup(name);
4✔
864
  if (pIter->name == NULL) {
4✔
865
    taosMemoryFree(pIter);
×
866
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
867
    return NULL;
×
868
  }
869

870
  return pIter;
4✔
871
}
872

873
static void sdbCloseIter(SSdbIter *pIter) {
4✔
874
  if (pIter == NULL) return;
4✔
875

876
  if (pIter->file != NULL) {
4✔
877
    int32_t ret = 0;
2✔
878
    if ((ret = taosCloseFile(&pIter->file)) != 0) {
2✔
879
      mError("failed to close sdb file since %s", tstrerror(ret));
×
880
    }
881
    pIter->file = NULL;
2✔
882
  }
883

884
  if (pIter->name != NULL) {
4✔
885
    int32_t ret = 0;
4✔
886
    if ((ret = taosRemoveFile(pIter->name)) != 0) {
4✔
887
      mError("failed to remove sdb file:%s since %s", pIter->name, tstrerror(ret));
2✔
888
    }
889
    taosMemoryFree(pIter->name);
4✔
890
    pIter->name = NULL;
4✔
891
  }
892

893
  mInfo("sdbiter:%p, is closed, total:%" PRId64, pIter, pIter->total);
4✔
894
  taosMemoryFree(pIter);
4✔
895
}
896

897
int32_t sdbStartRead(SSdb *pSdb, SSdbIter **ppIter, int64_t *index, int64_t *term, int64_t *config) {
2✔
898
  int32_t   code = 0;
2✔
899
  SSdbIter *pIter = sdbCreateIter(pSdb);
2✔
900
  if (pIter == NULL) return -1;
2✔
901

902
  char datafile[PATH_MAX] = {0};
2✔
903
  snprintf(datafile, sizeof(datafile), "%s%ssdb.data", pSdb->currDir, TD_DIRSEP);
2✔
904

905
  (void)taosThreadMutexLock(&pSdb->filelock);
2✔
906
  int64_t commitIndex = pSdb->commitIndex;
2✔
907
  int64_t commitTerm = pSdb->commitTerm;
2✔
908
  int64_t commitConfig = pSdb->commitConfig;
2✔
909
  if (taosCopyFile(datafile, pIter->name) < 0) {
2✔
910
    code = terrno;
×
911
    (void)taosThreadMutexUnlock(&pSdb->filelock);
×
912
    mError("failed to copy sdb file %s to %s since %s", datafile, pIter->name, tstrerror(code));
×
913
    sdbCloseIter(pIter);
×
914
    TAOS_RETURN(code);
×
915
  }
916
  (void)taosThreadMutexUnlock(&pSdb->filelock);
2✔
917

918
  pIter->file = taosOpenFile(pIter->name, TD_FILE_READ);
2✔
919
  if (pIter->file == NULL) {
2✔
920
    code = terrno;
×
921
    mError("failed to open sdb file:%s since %s", pIter->name, tstrerror(code));
×
922
    sdbCloseIter(pIter);
×
923
    TAOS_RETURN(code);
×
924
  }
925

926
  *ppIter = pIter;
2✔
927
  if (index != NULL) *index = commitIndex;
2✔
928
  if (term != NULL) *term = commitTerm;
2✔
929
  if (config != NULL) *config = commitConfig;
2✔
930

931
  mInfo("sdbiter:%p, is created to read snapshot, commit index:%" PRId64 " term:%" PRId64 " config:%" PRId64 " file:%s",
2✔
932
        pIter, commitIndex, commitTerm, commitConfig, pIter->name);
933
  return 0;
2✔
934
}
935

936
void sdbStopRead(SSdb *pSdb, SSdbIter *pIter) { sdbCloseIter(pIter); }
2✔
937

938
int32_t sdbDoRead(SSdb *pSdb, SSdbIter *pIter, void **ppBuf, int32_t *len) {
4✔
939
  int32_t code = 0;
4✔
940
  int32_t maxlen = 4096;
4✔
941
  void   *pBuf = taosMemoryCalloc(1, maxlen);
4✔
942
  if (pBuf == NULL) {
4✔
943
    code = terrno;
×
944
    TAOS_RETURN(code);
×
945
  }
946

947
  int32_t readlen = taosReadFile(pIter->file, pBuf, maxlen);
4✔
948
  if (readlen < 0 || readlen > maxlen) {
4✔
949
    code = terrno;
×
950
    mError("sdbiter:%p, failed to read snapshot since %s, total:%" PRId64, pIter, tstrerror(code), pIter->total);
×
951
    *ppBuf = NULL;
×
952
    *len = 0;
×
953
    taosMemoryFree(pBuf);
×
954
    TAOS_RETURN(code);
×
955
  } else if (readlen == 0) {
4✔
956
    mInfo("sdbiter:%p, read snapshot to the end, total:%" PRId64, pIter, pIter->total);
2✔
957
    *ppBuf = NULL;
2✔
958
    *len = 0;
2✔
959
    taosMemoryFree(pBuf);
2✔
960
    return 0;
2✔
961
  } else {  // (readlen <= maxlen)
962
    pIter->total += readlen;
2✔
963
    mInfo("sdbiter:%p, read:%d bytes from snapshot, total:%" PRId64, pIter, readlen, pIter->total);
2✔
964
    *ppBuf = pBuf;
2✔
965
    *len = readlen;
2✔
966
    return 0;
2✔
967
  }
968
}
969

970
int32_t sdbStartWrite(SSdb *pSdb, SSdbIter **ppIter) {
2✔
971
  int32_t   code = 0;
2✔
972
  SSdbIter *pIter = sdbCreateIter(pSdb);
2✔
973
  if (pIter == NULL) {
2✔
974
    code = terrno;
×
975
    TAOS_RETURN(code);
×
976
  }
977

978
  pIter->file = taosOpenFile(pIter->name, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
2✔
979
  if (pIter->file == NULL) {
2✔
980
    code = terrno;
×
981
    mError("failed to open %s since %s", pIter->name, tstrerror(code));
×
982
    sdbCloseIter(pIter);
×
983
    TAOS_RETURN(code);
×
984
  }
985

986
  *ppIter = pIter;
2✔
987
  mInfo("sdbiter:%p, is created to write snapshot, file:%s", pIter, pIter->name);
2✔
988
  return 0;
2✔
989
}
990

991
int32_t sdbStopWrite(SSdb *pSdb, SSdbIter *pIter, bool isApply, int64_t index, int64_t term, int64_t config) {
2✔
992
  int32_t code = -1;
2✔
993

994
  if (!isApply) {
2✔
995
    mInfo("sdbiter:%p, not apply to sdb", pIter);
×
996
    code = 0;
×
997
    goto _OVER;
×
998
  }
999

1000
  if (taosFsyncFile(pIter->file) != 0) {
2✔
1001
    code = TAOS_SYSTEM_ERROR(ERRNO);
×
1002
    mError("sdbiter:%p, failed to fasync file %s since %s", pIter, pIter->name, tstrerror(code));
×
1003
    goto _OVER;
×
1004
  }
1005

1006
  if (taosCloseFile(&pIter->file) != 0) {
2✔
1007
    code = TAOS_SYSTEM_ERROR(ERRNO);
×
1008
    goto _OVER;
×
1009
  }
1010
  pIter->file = NULL;
2✔
1011

1012
  char datafile[PATH_MAX] = {0};
2✔
1013
  snprintf(datafile, sizeof(datafile), "%s%ssdb.data", pSdb->currDir, TD_DIRSEP);
2✔
1014
  code = taosRenameFile(pIter->name, datafile);
2✔
1015
  if (code != 0) {
2✔
1016
    mError("sdbiter:%p, failed to rename file %s to %s since %s", pIter, pIter->name, datafile, tstrerror(code));
×
1017
    goto _OVER;
×
1018
  }
1019

1020
  // Defensive check: re-read encrypted flag from mnode.json to ensure consistency
1021
  // This handles edge cases like CREATE MNODE where flag might not have been passed correctly
1022
  bool mnodeJsonEncrypted = sdbReadEncryptedFlagFromMnodeJson(pSdb);
2✔
1023
  if (mnodeJsonEncrypted != pSdb->encrypted) {
2✔
1024
    mInfo("sdbiter:%p, sdb encrypted flag mismatch: memory=%d, mnode.json=%d, correcting to %d", pIter, pSdb->encrypted,
×
1025
          mnodeJsonEncrypted, mnodeJsonEncrypted);
1026
    pSdb->encrypted = mnodeJsonEncrypted;
×
1027
  }
1028

1029
  code = sdbReadFile(pSdb);
2✔
1030
  if (code != 0) {
2✔
1031
    mError("sdbiter:%p, failed to read from %s since %s", pIter, datafile, tstrerror(code));
×
1032
    goto _OVER;
×
1033
  }
1034

1035
  if (config > 0) {
2✔
1036
    pSdb->commitConfig = config;
×
1037
  }
1038
  if (term > 0) {
2✔
1039
    pSdb->commitTerm = term;
×
1040
  }
1041
  if (index > 0) {
2✔
1042
    pSdb->commitIndex = index;
×
1043
  }
1044

1045
  mInfo("sdbiter:%p, success applyed to sdb", pIter);
2✔
1046
  code = 0;
2✔
1047

1048
_OVER:
2✔
1049
  sdbCloseIter(pIter);
2✔
1050
  return code;
2✔
1051
}
1052

1053
int32_t sdbDoWrite(SSdb *pSdb, SSdbIter *pIter, void *pBuf, int32_t len) {
2✔
1054
  int32_t code = 0;
2✔
1055
  int32_t writelen = taosWriteFile(pIter->file, pBuf, len);
2✔
1056
  if (writelen != len) {
2✔
1057
    code = terrno;
×
1058
    mError("failed to write len:%d since %s, total:%" PRId64, len, tstrerror(code), pIter->total);
×
1059
    TAOS_RETURN(code);
×
1060
  }
1061

1062
  pIter->total += writelen;
2✔
1063
  mInfo("sdbiter:%p, write:%d bytes to snapshot, total:%" PRId64, pIter, writelen, pIter->total);
2✔
1064
  return 0;
2✔
1065
}
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