• 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

34.31
/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) {
104✔
24
  int32_t num = 0;
104✔
25
  int32_t size = taosHashGetSize(pMgmt->runngingHash);
104✔
26
  int32_t closedSize = taosHashGetSize(pMgmt->closedHash);
104✔
27
  size += closedSize;
104✔
28
  SVnodeObj **pVnodes = taosMemoryCalloc(size, sizeof(SVnodeObj *));
104✔
29
  if (pVnodes == NULL) {
104✔
30
    return terrno;
×
31
  }
32

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

47
  pIter = taosHashIterate(pMgmt->closedHash, NULL);
104✔
48
  while (pIter) {
104✔
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;
104✔
62
  *ppVnodes = pVnodes;
104✔
63

64
  return 0;
104✔
65
}
66

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

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

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

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

109
  *numOfVnodes = num;
40✔
110
  *ppVnodes = pVnodes;
40✔
111

112
  return 0;
40✔
113
}
114

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

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

126
  void *pIter = taosHashIterate(pMgmt->runngingHash, NULL);
32✔
127
  while (pIter) {
40✔
128
    SVnodeObj **ppVnode = pIter;
8✔
129
    SVnodeObj  *pVnode = *ppVnode;
8✔
130
    if (pVnode && num < size) {
16✔
131
      int32_t refCount = atomic_add_fetch_32(&pVnode->refCount, 1);
8✔
132
      dTrace("vgId:%d, acquire vnode, vnode:%p, ref:%d", pVnode->vgId, pVnode, refCount);
8✔
133
      pVnodes[num++] = (*ppVnode);
8✔
134
      pIter = taosHashIterate(pMgmt->runngingHash, pIter);
8✔
135
    } else {
136
      taosHashCancelIterate(pMgmt->runngingHash, pIter);
×
137
    }
138
  }
139

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

144
  return 0;
32✔
145
}
146

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

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

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

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

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

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

184
  code = 0;
×
185
  *ppCfgs = pCfgs;
×
186
  *numOfVnodes = vnodesNum;
×
187

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

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

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

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

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

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

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

230
_OVER:
×
231
  if (pData != NULL) taosMemoryFree(pData);
×
232
  if (pJson != NULL) cJSON_Delete(pJson);
×
233

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

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

251
  for (int32_t i = 0; i < numOfVnodes; ++i) {
232✔
252
    SVnodeObj *pVnode = ppVnodes[i];
128✔
253
    if (pVnode == NULL) continue;
128✔
254

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

270
  return 0;
104✔
271
}
272

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

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

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

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

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

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

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

316
_OVER:
×
317
  (void)taosThreadRwlockUnlock(&pMgmt->hashLock);
104✔
318

319
  if (pJson != NULL) tjsonDelete(pJson);
104✔
320
  if (buffer != NULL) taosMemoryFree(buffer);
104✔
321
  if (ppVnodes != NULL) {
104✔
322
    for (int32_t i = 0; i < numOfVnodes; ++i) {
232✔
323
      SVnodeObj *pVnode = ppVnodes[i];
128✔
324
      if (pVnode != NULL) {
128✔
325
        vmReleaseVnode(pMgmt, pVnode);
128✔
326
      }
327
    }
328
    taosMemoryFree(ppVnodes);
104✔
329
  }
330

331
  if (code != 0) {
104✔
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;
104✔
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) {
16✔
374
  int32_t    code = 0, lino = 0;
16✔
375
  int64_t    size = 0;
16✔
376
  TdFilePtr  pFile = NULL;
16✔
377
  char      *pData = NULL;
16✔
378
  SJson     *pJson = NULL;
16✔
379
  char       file[PATH_MAX] = {0};
16✔
380
  SMountCfg *pCfgs = NULL;
16✔
381
  snprintf(file, sizeof(file), "%s%smounts.json", pMgmt->path, TD_DIRSEP);
16✔
382

383
  if (!taosCheckExistFile(file)) goto _exit;
16✔
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:
×
395
  if (pData != NULL) taosMemoryFree(pData);
16✔
396
  if (pJson != NULL) cJSON_Delete(pJson);
16✔
397
  if (pFile != NULL) taosCloseFile(&pFile);
16✔
398
  if (code != 0) {
16✔
399
    dError("failed to read mounts file:%s since %s", file, tstrerror(code));
×
400
  }
401
  return code;
16✔
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 = tjsonGetStringValue(pItem, "dir", 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