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

taosdata / TDengine / #5071

17 May 2026 01:15AM UTC coverage: 63.054% (-10.3%) from 73.326%
#5071

push

travis-ci

web-flow
feat (TDgpt): Dynamic Model Synchronization Enhancements (#35344)

* refactor: do some internal refactor.

* fix: fix multiprocess sync issue.

* feat: add dynamic anomaly detection and forecasting services

* fix: log error message for undeploying model in exception handling

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix: handle undeploy when model exists only on disk

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/286aafa0-c3ce-4c27-b803-2707571e9dc1

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* fix: guard dynamic registry concurrent access

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/5e4db858-6458-40f4-ac28-d1b1b7f97c18

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* fix: tighten service list locking scope

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/5e4db858-6458-40f4-ac28-d1b1b7f97c18

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* fix: restore prophet support and update tests per review feedback

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/92298ae1-7da6-4d07-b20e-101c7cd0b26b

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* fix: improve test name and move copy inside lock scope

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/92298ae1-7da6-4d07-b20e-101c7cd0b26b

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* Potential fix for pull request finding

Co-au... (continued)

238317 of 377957 relevant lines covered (63.05%)

130539817.12 hits per line

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

47.45
/source/dnode/mgmt/mgmt_vnode/src/vmFile.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 "tencrypt.h"
18
#include "tjson.h"
19
#include "vmInt.h"
20

21
#define MAX_CONTENT_LEN 2 * 1024 * 1024
22

23
int32_t vmGetAllVnodeListFromHash(SVnodeMgmt *pMgmt, int32_t *numOfVnodes, SVnodeObj ***ppVnodes) {
6,426,345✔
24
  int32_t num = 0;
6,426,345✔
25
  int32_t size = taosHashGetSize(pMgmt->runngingHash);
6,426,345✔
26
  int32_t closedSize = taosHashGetSize(pMgmt->closedHash);
6,426,345✔
27
  size += closedSize;
6,426,345✔
28
  SVnodeObj **pVnodes = taosMemoryCalloc(size, sizeof(SVnodeObj *));
6,426,345✔
29
  if (pVnodes == NULL) {
6,426,345✔
30
    return terrno;
×
31
  }
32

33
  void *pIter = taosHashIterate(pMgmt->runngingHash, NULL);
6,426,345✔
34
  while (pIter) {
33,663,530✔
35
    SVnodeObj **ppVnode = pIter;
27,237,185✔
36
    SVnodeObj  *pVnode = *ppVnode;
27,237,185✔
37
    if (pVnode && num < size) {
54,474,370✔
38
      int32_t refCount = atomic_add_fetch_32(&pVnode->refCount, 1);
27,237,185✔
39
      dTrace("vgId:%d,acquire vnode, vnode:%p, ref:%d", pVnode->vgId, pVnode, refCount);
27,237,185✔
40
      pVnodes[num++] = (*ppVnode);
27,237,185✔
41
      pIter = taosHashIterate(pMgmt->runngingHash, pIter);
27,237,185✔
42
    } else {
43
      taosHashCancelIterate(pMgmt->runngingHash, pIter);
×
44
    }
45
  }
46

47
  pIter = taosHashIterate(pMgmt->closedHash, NULL);
6,426,345✔
48
  while (pIter) {
6,426,345✔
49
    SVnodeObj **ppVnode = pIter;
×
50
    SVnodeObj  *pVnode = *ppVnode;
×
51
    if (pVnode && num < size) {
×
52
      int32_t refCount = atomic_add_fetch_32(&pVnode->refCount, 1);
×
53
      dTrace("vgId:%d, acquire vnode, vnode:%p, ref:%d", pVnode->vgId, pVnode, refCount);
×
54
      pVnodes[num++] = (*ppVnode);
×
55
      pIter = taosHashIterate(pMgmt->closedHash, pIter);
×
56
    } else {
57
      taosHashCancelIterate(pMgmt->closedHash, pIter);
×
58
    }
59
  }
60

61
  *numOfVnodes = num;
6,426,345✔
62
  *ppVnodes = pVnodes;
6,426,345✔
63

64
  return 0;
6,426,345✔
65
}
66

67
int32_t vmGetAllVnodeListFromHashWithCreating(SVnodeMgmt *pMgmt, int32_t *numOfVnodes, SVnodeObj ***ppVnodes) {
3,009,013✔
68
  (void)taosThreadRwlockRdlock(&pMgmt->hashLock);
3,009,013✔
69

70
  int32_t num = 0;
3,009,013✔
71
  int32_t size = taosHashGetSize(pMgmt->runngingHash);
3,009,013✔
72
  int32_t creatingSize = taosHashGetSize(pMgmt->creatingHash);
3,009,013✔
73
  size += creatingSize;
3,009,013✔
74
  SVnodeObj **pVnodes = taosMemoryCalloc(size, sizeof(SVnodeObj *));
3,009,013✔
75
  if (pVnodes == NULL) {
3,009,013✔
76
    (void)taosThreadRwlockUnlock(&pMgmt->hashLock);
×
77
    return terrno;
×
78
  }
79

80
  void *pIter = taosHashIterate(pMgmt->runngingHash, NULL);
3,009,013✔
81
  while (pIter) {
10,295,442✔
82
    SVnodeObj **ppVnode = pIter;
7,286,429✔
83
    SVnodeObj  *pVnode = *ppVnode;
7,286,429✔
84
    if (pVnode && num < size) {
14,572,858✔
85
      int32_t refCount = atomic_add_fetch_32(&pVnode->refCount, 1);
7,286,429✔
86
      dTrace("vgId:%d,acquire vnode, vnode:%p, ref:%d", pVnode->vgId, pVnode, refCount);
7,286,429✔
87
      pVnodes[num++] = (*ppVnode);
7,286,429✔
88
      pIter = taosHashIterate(pMgmt->runngingHash, pIter);
7,286,429✔
89
    } else {
90
      taosHashCancelIterate(pMgmt->runngingHash, pIter);
×
91
    }
92
  }
93

94
  pIter = taosHashIterate(pMgmt->creatingHash, NULL);
3,009,013✔
95
  while (pIter) {
5,458,907✔
96
    SVnodeObj **ppVnode = pIter;
2,449,894✔
97
    SVnodeObj  *pVnode = *ppVnode;
2,449,894✔
98
    if (pVnode && num < size) {
4,899,788✔
99
      int32_t refCount = atomic_add_fetch_32(&pVnode->refCount, 1);
2,449,894✔
100
      dTrace("vgId:%d, acquire vnode, vnode:%p, ref:%d", pVnode->vgId, pVnode, refCount);
2,449,894✔
101
      pVnodes[num++] = (*ppVnode);
2,449,894✔
102
      pIter = taosHashIterate(pMgmt->creatingHash, pIter);
2,449,894✔
103
    } else {
104
      taosHashCancelIterate(pMgmt->creatingHash, pIter);
×
105
    }
106
  }
107
  (void)taosThreadRwlockUnlock(&pMgmt->hashLock);
3,009,013✔
108

109
  *numOfVnodes = num;
3,009,013✔
110
  *ppVnodes = pVnodes;
3,009,013✔
111

112
  return 0;
3,009,013✔
113
}
114

115
int32_t vmGetVnodeListFromHash(SVnodeMgmt *pMgmt, int32_t *numOfVnodes, SVnodeObj ***ppVnodes) {
2,177,586✔
116
  (void)taosThreadRwlockRdlock(&pMgmt->hashLock);
2,177,586✔
117

118
  int32_t     num = 0;
2,177,586✔
119
  int32_t     size = taosHashGetSize(pMgmt->runngingHash);
2,177,586✔
120
  SVnodeObj **pVnodes = taosMemoryCalloc(size, sizeof(SVnodeObj *));
2,177,586✔
121
  if (pVnodes == NULL) {
2,177,586✔
122
    (void)taosThreadRwlockUnlock(&pMgmt->hashLock);
×
123
    return terrno;
×
124
  }
125

126
  void *pIter = taosHashIterate(pMgmt->runngingHash, NULL);
2,177,586✔
127
  while (pIter) {
7,770,220✔
128
    SVnodeObj **ppVnode = pIter;
5,592,634✔
129
    SVnodeObj  *pVnode = *ppVnode;
5,592,634✔
130
    if (pVnode && num < size) {
11,185,268✔
131
      int32_t refCount = atomic_add_fetch_32(&pVnode->refCount, 1);
5,592,634✔
132
      dTrace("vgId:%d, acquire vnode, vnode:%p, ref:%d", pVnode->vgId, pVnode, refCount);
5,592,634✔
133
      pVnodes[num++] = (*ppVnode);
5,592,634✔
134
      pIter = taosHashIterate(pMgmt->runngingHash, pIter);
5,592,634✔
135
    } else {
136
      taosHashCancelIterate(pMgmt->runngingHash, pIter);
×
137
    }
138
  }
139

140
  (void)taosThreadRwlockUnlock(&pMgmt->hashLock);
2,177,586✔
141
  *numOfVnodes = num;
2,177,586✔
142
  *ppVnodes = pVnodes;
2,177,586✔
143

144
  return 0;
2,177,586✔
145
}
146

147
static int32_t vmDecodeVnodeList(SJson *pJson, SVnodeMgmt *pMgmt, SWrapperCfg **ppCfgs, int32_t *numOfVnodes) {
102,032✔
148
  int32_t      code = -1;
102,032✔
149
  SWrapperCfg *pCfgs = NULL;
102,032✔
150
  *ppCfgs = NULL;
102,032✔
151

152
  SJson *vnodes = tjsonGetObjectItem(pJson, "vnodes");
102,032✔
153
  if (vnodes == NULL) return TSDB_CODE_INVALID_JSON_FORMAT;
102,032✔
154

155
  int32_t vnodesNum = cJSON_GetArraySize(vnodes);
102,032✔
156
  if (vnodesNum > 0) {
102,032✔
157
    pCfgs = taosMemoryCalloc(vnodesNum, sizeof(SWrapperCfg));
98,441✔
158
    if (pCfgs == NULL) return terrno;
98,441✔
159
  }
160

161
  for (int32_t i = 0; i < vnodesNum; ++i) {
383,685✔
162
    SJson *vnode = tjsonGetArrayItem(vnodes, i);
281,653✔
163
    if (vnode == NULL) {
281,653✔
164
      code = TSDB_CODE_INVALID_JSON_FORMAT;
×
165
      goto _OVER;
×
166
    }
167

168
    SWrapperCfg *pCfg = &pCfgs[i];
281,653✔
169
    tjsonGetInt32ValueFromDouble(vnode, "vgId", pCfg->vgId, code);
281,653✔
170
    if (code != 0) goto _OVER;
281,653✔
171
    tjsonGetInt32ValueFromDouble(vnode, "dropped", pCfg->dropped, code);
281,653✔
172
    if (code != 0) goto _OVER;
281,653✔
173
    tjsonGetInt32ValueFromDouble(vnode, "vgVersion", pCfg->vgVersion, code);
281,653✔
174
    if (code != 0) goto _OVER;
281,653✔
175
    tjsonGetInt32ValueFromDouble(vnode, "diskPrimary", pCfg->diskPrimary, code);
281,653✔
176
    if (code != 0) goto _OVER;
281,653✔
177
    tjsonGetInt32ValueFromDouble(vnode, "toVgId", pCfg->toVgId, code);
281,653✔
178
    if (code != 0) goto _OVER;
281,653✔
179
    if ((code = tjsonGetBigIntValue(vnode, "mountId", &pCfg->mountId)) != 0) goto _OVER;
281,653✔
180

181
    snprintf(pCfg->path, sizeof(pCfg->path), "%s%svnode%d", pMgmt->path, TD_DIRSEP, pCfg->vgId);
281,653✔
182
  }
183

184
  code = 0;
102,032✔
185
  *ppCfgs = pCfgs;
102,032✔
186
  *numOfVnodes = vnodesNum;
102,032✔
187

188
_OVER:
102,032✔
189
  if (*ppCfgs == NULL) taosMemoryFree(pCfgs);
102,032✔
190
  return code;
102,032✔
191
}
192

193
int32_t vmGetVnodeListFromFile(SVnodeMgmt *pMgmt, SWrapperCfg **ppCfgs, int32_t *numOfVnodes) {
535,586✔
194
  int32_t      code = -1;
535,586✔
195
  char        *pData = NULL;
535,586✔
196
  int32_t      dataLen = 0;
535,586✔
197
  SJson       *pJson = NULL;
535,586✔
198
  char         file[PATH_MAX] = {0};
535,586✔
199
  SWrapperCfg *pCfgs = NULL;
535,586✔
200
  snprintf(file, sizeof(file), "%s%svnodes.json", pMgmt->path, TD_DIRSEP);
535,586✔
201

202
  if (taosStatFile(file, NULL, NULL, NULL) < 0) {
535,586✔
203
    code = terrno;
433,554✔
204
    dInfo("vnode file:%s not exist, reason:%s", file, tstrerror(code));
433,554✔
205
    code = 0;
433,554✔
206
    return code;
433,554✔
207
  }
208

209
  // Use taosReadCfgFile for automatic decryption support (returns null-terminated string)
210
  code = taosReadCfgFile(file, &pData, &dataLen);
102,032✔
211
  if (code != 0) {
102,032✔
212
    dError("failed to read vnode file:%s since %s", file, tstrerror(code));
×
213
    goto _OVER;
×
214
  }
215

216
  pJson = tjsonParse(pData);
102,032✔
217
  if (pJson == NULL) {
102,032✔
218
    code = TSDB_CODE_INVALID_JSON_FORMAT;
×
219
    goto _OVER;
×
220
  }
221

222
  if (vmDecodeVnodeList(pJson, pMgmt, ppCfgs, numOfVnodes) < 0) {
102,032✔
223
    code = TSDB_CODE_INVALID_JSON_FORMAT;
×
224
    goto _OVER;
×
225
  }
226

227
  code = 0;
102,032✔
228
  dInfo("succceed to read vnode file %s", file);
102,032✔
229

230
_OVER:
102,032✔
231
  if (pData != NULL) taosMemoryFree(pData);
102,032✔
232
  if (pJson != NULL) cJSON_Delete(pJson);
102,032✔
233

234
  if (code != 0) {
102,032✔
235
    dError("failed to read vnode file:%s since %s", file, tstrerror(code));
×
236
  }
237
  return code;
102,032✔
238
}
239

240
static int32_t vmEncodeVnodeList(SJson *pJson, SVnodeObj **ppVnodes, int32_t numOfVnodes) {
6,426,345✔
241
  int32_t code = 0;
6,426,345✔
242
  SJson  *vnodes = tjsonCreateArray();
6,426,345✔
243
  if (vnodes == NULL) {
6,426,345✔
244
    return terrno;
×
245
  }
246
  if ((code = tjsonAddItemToObject(pJson, "vnodes", vnodes)) < 0) {
6,426,345✔
247
    tjsonDelete(vnodes);
×
248
    return code;
×
249
  };
250

251
  for (int32_t i = 0; i < numOfVnodes; ++i) {
33,663,530✔
252
    SVnodeObj *pVnode = ppVnodes[i];
27,237,185✔
253
    if (pVnode == NULL) continue;
27,237,185✔
254

255
    SJson *vnode = tjsonCreateObject();
27,237,185✔
256
    if (vnode == NULL) return terrno;
27,237,185✔
257
    if ((code = tjsonAddDoubleToObject(vnode, "vgId", pVnode->vgId)) < 0) return code;
27,237,185✔
258
    if ((code = tjsonAddDoubleToObject(vnode, "dropped", pVnode->dropped)) < 0) return code;
27,237,185✔
259
    if ((code = tjsonAddDoubleToObject(vnode, "vgVersion", pVnode->vgVersion)) < 0) return code;
27,237,185✔
260
    if ((code = tjsonAddDoubleToObject(vnode, "diskPrimary", pVnode->diskPrimary)) < 0) return code;
27,237,185✔
261
    if (pVnode->toVgId) {
27,237,185✔
262
      if ((code = tjsonAddDoubleToObject(vnode, "toVgId", pVnode->toVgId)) < 0) return code;
21,159✔
263
    }
264
    if (pVnode->mountId) {
27,237,185✔
265
      if ((code = tjsonAddIntegerToObject(vnode, "mountId", pVnode->mountId)) < 0) return code;
×
266
    }
267
    if ((code = tjsonAddItemToArray(vnodes, vnode)) < 0) return code;
27,237,185✔
268
  }
269

270
  return 0;
6,426,345✔
271
}
272

273
int32_t vmWriteVnodeListToFile(SVnodeMgmt *pMgmt) {
6,426,345✔
274
  int32_t     code = -1;
6,426,345✔
275
  char       *buffer = NULL;
6,426,345✔
276
  SJson      *pJson = NULL;
6,426,345✔
277
  SVnodeObj **ppVnodes = NULL;
6,426,345✔
278
  char        realfile[PATH_MAX] = {0};
6,426,345✔
279
  int32_t     lino = 0;
6,426,345✔
280

281
  int32_t nBytes = snprintf(realfile, sizeof(realfile), "%s%svnodes.json", pMgmt->path, TD_DIRSEP);
6,426,345✔
282
  if (nBytes <= 0 || nBytes >= sizeof(realfile)) {
6,426,345✔
283
    return TSDB_CODE_OUT_OF_RANGE;
×
284
  }
285

286
  int32_t numOfVnodes = 0;
6,426,345✔
287
  (void)taosThreadRwlockWrlock(&pMgmt->hashLock);
6,426,345✔
288
  TAOS_CHECK_GOTO(vmGetAllVnodeListFromHash(pMgmt, &numOfVnodes, &ppVnodes), &lino, _OVER);
6,426,345✔
289

290
  // terrno = TSDB_CODE_OUT_OF_MEMORY;
291
  pJson = tjsonCreateObject();
6,426,345✔
292
  if (pJson == NULL) {
6,426,345✔
293
    code = terrno;
×
294
    goto _OVER;
×
295
  }
296
  TAOS_CHECK_GOTO(vmEncodeVnodeList(pJson, ppVnodes, numOfVnodes), &lino, _OVER);
6,426,345✔
297

298
  buffer = tjsonToString(pJson);
6,426,345✔
299
  if (buffer == NULL) {
6,426,345✔
300
    code = TSDB_CODE_INVALID_JSON_FORMAT;
×
301
    lino = __LINE__;
×
302
    goto _OVER;
×
303
  }
304

305
  int32_t len = strlen(buffer);
6,426,345✔
306
  
307
  // Use encrypted write if tsCfgKey is enabled
308
  code = taosWriteCfgFile(realfile, buffer, len);
6,426,345✔
309
  if (code != 0) {
6,426,345✔
310
    lino = __LINE__;
×
311
    goto _OVER;
×
312
  }
313

314
  dInfo("succeed to write vnodes file:%s, vnodes:%d", realfile, numOfVnodes);
6,426,345✔
315

316
_OVER:
6,421,093✔
317
  (void)taosThreadRwlockUnlock(&pMgmt->hashLock);
6,426,345✔
318

319
  if (pJson != NULL) tjsonDelete(pJson);
6,426,345✔
320
  if (buffer != NULL) taosMemoryFree(buffer);
6,426,345✔
321
  if (ppVnodes != NULL) {
6,426,345✔
322
    for (int32_t i = 0; i < numOfVnodes; ++i) {
33,663,530✔
323
      SVnodeObj *pVnode = ppVnodes[i];
27,237,185✔
324
      if (pVnode != NULL) {
27,237,185✔
325
        vmReleaseVnode(pMgmt, pVnode);
27,237,185✔
326
      }
327
    }
328
    taosMemoryFree(ppVnodes);
6,426,345✔
329
  }
330

331
  if (code != 0) {
6,426,345✔
332
    dError("failed to write vnodes file:%s at line:%d since %s, vnodes:%d", realfile, lino, tstrerror(code),
×
333
           numOfVnodes);
334
  }
335
  return code;
6,426,345✔
336
}
337

338
#ifdef USE_MOUNT
339
static int32_t vmDecodeMountList(SJson *pJson, SVnodeMgmt *pMgmt, SMountCfg **ppCfgs, int32_t *numOfMounts) {
×
340
  int32_t    code = 0, lino = 0;
×
341
  int32_t    mountsNum = 0;
×
342
  SMountCfg *pCfgs = NULL;
×
343
  SJson     *mounts = NULL;
×
344

345
  if (!(mounts = tjsonGetObjectItem(pJson, "mounts"))) {
×
346
    goto _exit;
×
347
  }
348
  if ((mountsNum = cJSON_GetArraySize(mounts)) > 0) {
×
349
    TSDB_CHECK_NULL((pCfgs = taosMemoryMalloc(mountsNum * sizeof(SMountCfg))), code, lino, _exit, terrno);
×
350
  }
351

352
  for (int32_t i = 0; i < mountsNum; ++i) {
×
353
    SJson *mount = tjsonGetArrayItem(mounts, i);
×
354
    TSDB_CHECK_NULL(mount, code, lino, _exit, TSDB_CODE_INVALID_JSON_FORMAT);
×
355
    SMountCfg *pCfg = &pCfgs[i];
×
356
    TAOS_CHECK_EXIT(tjsonGetBigIntValue(mount, "mountId", &pCfg->mountId));
×
357
    TAOS_CHECK_EXIT(tjsonGetStringValue2(mount, "name", pCfg->name, sizeof(pCfg->name)));
×
358
    TAOS_CHECK_EXIT(tjsonGetStringValue2(mount, "path", pCfg->path, sizeof(pCfg->path)));
×
359
  }
360
_exit:
×
361
  if (code) {
×
362
    dError("failed to decode mount list at line %d since %s", lino, tstrerror(code));
×
363
    if (pCfgs) {
×
364
      taosMemoryFree(pCfgs);
×
365
      pCfgs = NULL;
×
366
    }
367
  }
368
  *numOfMounts = mountsNum;
×
369
  *ppCfgs = pCfgs;
×
370
  return code;
×
371
}
372

373
int32_t vmGetMountListFromFile(SVnodeMgmt *pMgmt, SMountCfg **ppCfgs, int32_t *numOfMounts) {
535,586✔
374
  int32_t    code = 0, lino = 0;
535,586✔
375
  int64_t    size = 0;
535,586✔
376
  TdFilePtr  pFile = NULL;
535,586✔
377
  char      *pData = NULL;
535,586✔
378
  SJson     *pJson = NULL;
535,586✔
379
  char       file[PATH_MAX] = {0};
535,586✔
380
  SMountCfg *pCfgs = NULL;
535,586✔
381
  snprintf(file, sizeof(file), "%s%smounts.json", pMgmt->path, TD_DIRSEP);
535,586✔
382

383
  if (!taosCheckExistFile(file)) goto _exit;
535,586✔
384
  TAOS_CHECK_EXIT(taosStatFile(file, &size, NULL, NULL));
×
385
  TSDB_CHECK_NULL((pFile = taosOpenFile(file, TD_FILE_READ)), code, lino, _exit, terrno);
×
386
  TSDB_CHECK_NULL((pData = taosMemoryMalloc(size + 1)), code, lino, _exit, terrno);
×
387
  if (taosReadFile(pFile, pData, size) != size) {
×
388
    TAOS_CHECK_EXIT(terrno);
×
389
  }
390
  pData[size] = '\0';
×
391
  TSDB_CHECK_NULL((pJson = tjsonParse(pData)), code, lino, _exit, TSDB_CODE_INVALID_JSON_FORMAT);
×
392
  TAOS_CHECK_EXIT(vmDecodeMountList(pJson, pMgmt, ppCfgs, numOfMounts));
×
393
  dInfo("succceed to read mounts file %s", file);
×
394
_exit:
534,778✔
395
  if (pData != NULL) taosMemoryFree(pData);
535,586✔
396
  if (pJson != NULL) cJSON_Delete(pJson);
535,586✔
397
  if (pFile != NULL) taosCloseFile(&pFile);
535,586✔
398
  if (code != 0) {
535,586✔
399
    dError("failed to read mounts file:%s since %s", file, tstrerror(code));
×
400
  }
401
  return code;
535,586✔
402
}
403

404
static int32_t vmEncodeMountList(SVnodeMgmt *pMgmt, SJson *pJson) {
×
405
  int32_t    code = 0, lino = 0;
×
406
  SHashObj  *pTfsHash = pMgmt->mountTfsHash;
×
407
  int32_t    numOfMounts = 0;
×
408
  SJson     *mounts = NULL;
×
409
  SJson     *mount = NULL;
×
410
  SMountTfs *pTfs = NULL;
×
411

412
  if ((numOfMounts = taosHashGetSize(pTfsHash)) < 0) {
×
413
    goto _exit;
×
414
  }
415
  TSDB_CHECK_NULL((mounts = tjsonCreateArray()), code, lino, _exit, terrno);
×
416
  if ((code = tjsonAddItemToObject(pJson, "mounts", mounts))) {
×
417
    tjsonDelete(mounts);
×
418
    TAOS_CHECK_EXIT(code);
×
419
  }
420
  size_t keyLen = sizeof(int64_t);
×
421
  while ((pTfs = taosHashIterate(pTfsHash, pTfs))) {
×
422
    TSDB_CHECK_NULL((mount = tjsonCreateObject()), code, lino, _exit, terrno);
×
423
    if (!mount) TAOS_CHECK_EXIT(terrno);
×
424
    int64_t mountId = *(int64_t *)taosHashGetKey(pTfs, NULL);
×
425
    TAOS_CHECK_EXIT(tjsonAddIntegerToObject(mount, "mountId", mountId));
×
426
    TAOS_CHECK_EXIT(tjsonAddStringToObject(mount, "name", (*(SMountTfs **)pTfs)->name));
×
427
    TAOS_CHECK_EXIT(tjsonAddStringToObject(mount, "path", (*(SMountTfs **)pTfs)->path));
×
428
    TAOS_CHECK_EXIT(tjsonAddItemToArray(mounts, mount));
×
429
    mount = NULL;
×
430
  }
431
_exit:
×
432
  if (code != 0) {
×
433
    if (mount) tjsonDelete(mount);
×
434
    if (pTfs) taosHashCancelIterate(pTfsHash, pTfs);
×
435
    dError("failed to encode mount list at line %d since %s", lino, tstrerror(code));
×
436
  }
437
  TAOS_RETURN(code);
×
438
}
439
#endif
440

441
int32_t vmWriteMountListToFile(SVnodeMgmt *pMgmt) {
×
442
  int32_t     code = 0, lino = 0, ret = 0;
×
443
#ifdef USE_MOUNT
444
  char       *buffer = NULL;
×
445
  SJson      *pJson = NULL;
×
446
  TdFilePtr   pFile = NULL;
×
447
  SVnodeObj **ppVnodes = NULL;
×
448
  char        file[PATH_MAX] = {0};
×
449
  char        realfile[PATH_MAX] = {0};
×
450
  bool        unlock = false;
×
451

452
  int32_t nBytes = snprintf(file, sizeof(file), "%s%smounts_tmp.json", pMgmt->path, TD_DIRSEP);
×
453
  if (nBytes <= 0 || nBytes >= sizeof(file)) {
×
454
    TAOS_CHECK_EXIT(TSDB_CODE_OUT_OF_RANGE);
×
455
  }
456
  nBytes = snprintf(realfile, sizeof(realfile), "%s%smounts.json", pMgmt->path, TD_DIRSEP);
×
457
  if (nBytes <= 0 || nBytes >= sizeof(realfile)) {
×
458
    TAOS_CHECK_EXIT(TSDB_CODE_OUT_OF_RANGE);
×
459
  }
460
  TSDB_CHECK_NULL((pJson = tjsonCreateObject()), code, lino, _exit, terrno);
×
461
  TAOS_CHECK_EXIT(vmEncodeMountList(pMgmt, pJson));
×
462
  TSDB_CHECK_NULL((buffer = tjsonToString(pJson)), code, lino, _exit, terrno);
×
463
  TAOS_CHECK_EXIT(taosThreadMutexLock(&pMgmt->mutex));
×
464
  unlock = true;
×
465
  TSDB_CHECK_NULL((pFile = taosOpenFile(file, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC | TD_FILE_WRITE_THROUGH)),
×
466
                  code, lino, _exit, terrno);
467

468
  int32_t len = strlen(buffer);
×
469
  if ((code = taosWriteFile(pFile, buffer, len)) <= 0) {
×
470
    TAOS_CHECK_EXIT(code);
×
471
  }
472
  TAOS_CHECK_EXIT(taosFsyncFile(pFile));
×
473
  TAOS_CHECK_EXIT(taosCloseFile(&pFile));
×
474
  TAOS_CHECK_EXIT(taosRenameFile(file, realfile));
×
475
  dInfo("succeed to write mounts file:%s", realfile);
×
476
_exit:
×
477
  if (unlock && (ret = taosThreadMutexUnlock(&pMgmt->mutex))) {
×
478
    dError("failed to unlock at line %d when write mounts file since %s", __LINE__, tstrerror(ret));
×
479
  }
480
  if (pJson) tjsonDelete(pJson);
×
481
  if (buffer) taosMemoryFree(buffer);
×
482
  if (pFile) taosCloseFile(&pFile);
×
483
  if (code != 0) {
×
484
    dError("failed to write mounts file:%s at line:%d since %s", realfile, lino, tstrerror(code));
×
485
  }
486
#endif
487
  TAOS_RETURN(code);
×
488
}
489
#ifdef USE_MOUNT
490
int32_t vmGetMountDisks(SVnodeMgmt *pMgmt, const char *mountPath, SArray **ppDisks) {
×
491
  int32_t   code = 0, lino = 0;
×
492
  SArray   *pDisks = NULL;
×
493
  TdFilePtr pFile = NULL;
×
494
  char     *content = NULL;
×
495
  SJson    *pJson = NULL;
×
496
  int64_t   size = 0;
×
497
  int64_t   clusterId = 0, dropped = 0, encryptScope = 0;
×
498
  char      file[TSDB_MOUNT_FPATH_LEN] = {0};
×
499

500
  (void)snprintf(file, sizeof(file), "%s%s%s%sconfig%s%s", mountPath, TD_DIRSEP, dmNodeName(DNODE), TD_DIRSEP,
×
501
                 TD_DIRSEP, "local.json");
502
  TAOS_CHECK_EXIT(taosStatFile(file, &size, NULL, NULL));
×
503
  TSDB_CHECK_NULL((pFile = taosOpenFile(file, TD_FILE_READ)), code, lino, _exit, terrno);
×
504
  TSDB_CHECK_NULL((content = taosMemoryMalloc(size + 1)), code, lino, _exit, terrno);
×
505
  if (taosReadFile(pFile, content, size) != size) {
×
506
    TAOS_CHECK_EXIT(terrno);
×
507
  }
508
  content[size] = '\0';
×
509
  pJson = tjsonParse(content);
×
510
  if (pJson == NULL) {
×
511
    TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
512
  }
513
  SJson *pConfigs = tjsonGetObjectItem(pJson, "configs");
×
514
  if (pConfigs == NULL) {
×
515
    TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
516
  }
517
  int32_t nDataDir = 0;
×
518
  SJson  *pDataDir = tjsonGetObjectItem(pConfigs, "dataDir");
×
519
  if (pDataDir) {
×
520
    nDataDir = tjsonGetArraySize(pDataDir);
×
521
  }
522
  if (!(pDisks = taosArrayInit_s(sizeof(SDiskCfg), nDataDir > 0 ? nDataDir : 1))) {
×
523
    TAOS_CHECK_EXIT(TSDB_CODE_OUT_OF_MEMORY);
×
524
  }
525
  for (int32_t i = 0; i < nDataDir; ++i) {
×
526
    char   dir[TSDB_MOUNT_PATH_LEN] = {0};
×
527
    SJson *pItem = tjsonGetArrayItem(pDataDir, i);
×
528
    if (pItem == NULL) {
×
529
      TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
530
    }
531
    code = tjsonGetStringValue1(pItem, "dir", dir, sizeof(dir));
×
532
    if (code < 0) {
×
533
      TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
534
    }
535
    int32_t j = strlen(dir) - 1;
×
536
    while (j > 0 && (dir[j] == '/' || dir[j] == '\\')) {
×
537
      dir[j--] = '\0';  // remove trailing slashes
×
538
    }
539
    SJson *pLevel = tjsonGetObjectItem(pItem, "level");
×
540
    if (!pLevel) {
×
541
      TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
542
    }
543
    int32_t level = (int32_t)cJSON_GetNumberValue(pLevel);
×
544
    if (level < 0 || level >= TFS_MAX_TIERS) {
×
545
      TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
546
    }
547
    SJson *pPrimary = tjsonGetObjectItem(pItem, "primary");
×
548
    if (!pPrimary) {
×
549
      TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
550
    }
551
    int32_t primary = (int32_t)cJSON_GetNumberValue(pPrimary);
×
552
    if ((primary < 0 || primary > 1) || (primary == 1 && level != 0)) {
×
553
      dError("mount:%s, invalid primary disk, primary:%d, level:%d", mountPath, primary, level);
×
554
      TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
555
    }
556
    int8_t    disable = (int8_t)cJSON_GetNumberValue(pLevel);
×
557
    SDiskCfg *pDisk = taosArrayGet(pDisks, i);
×
558
    pDisk->level = level;
×
559
    pDisk->primary = primary;
×
560
    pDisk->disable = disable;
×
561
    if (primary == 1 && level == 0) {
×
562
      (void)snprintf(pDisk->dir, sizeof(pDisk->dir), "%s", mountPath);
×
563
    } else {
564
      (void)snprintf(pDisk->dir, sizeof(pDisk->dir), "%s", dir);
×
565
    }
566
  }
567
  if (nDataDir <= 0) {
×
568
    SDiskCfg *pDisk = taosArrayGet(pDisks, 0);
×
569
    pDisk->level = 0;
×
570
    pDisk->primary = 1;
×
571
    pDisk->disable = 0;
×
572
    (void)snprintf(pDisk->dir, sizeof(pDisk->dir), "%s", mountPath);
×
573
  }
574
_exit:
×
575
  if (content != NULL) taosMemoryFreeClear(content);
×
576
  if (pJson != NULL) cJSON_Delete(pJson);
×
577
  if (pFile != NULL) taosCloseFile(&pFile);
×
578
  if (code != 0) {
×
579
    dError("failed to get mount disks at line %d since %s, path:%s", lino, tstrerror(code), mountPath);
×
580
    taosArrayDestroy(pDisks);
×
581
    pDisks = NULL;
×
582
  }
583
  *ppDisks = pDisks;
×
584
  TAOS_RETURN(code);
×
585
}
586

587
#endif
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