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

taosdata / TDengine / #4800

16 Oct 2025 09:19AM UTC coverage: 53.935% (-7.1%) from 61.083%
#4800

push

travis-ci

web-flow
Merge b32e3a393 into a190048d5

134724 of 323629 branches covered (41.63%)

Branch coverage included in aggregate %.

184803 of 268802 relevant lines covered (68.75%)

69058627.2 hits per line

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

39.02
/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 "tjson.h"
18
#include "vmInt.h"
19

20
#define MAX_CONTENT_LEN 2 * 1024 * 1024
21

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

32
  void *pIter = taosHashIterate(pMgmt->runngingHash, NULL);
2,122,704✔
33
  while (pIter) {
8,283,751✔
34
    SVnodeObj **ppVnode = pIter;
6,161,047✔
35
    SVnodeObj  *pVnode = *ppVnode;
6,161,047✔
36
    if (pVnode && num < size) {
12,322,094!
37
      int32_t refCount = atomic_add_fetch_32(&pVnode->refCount, 1);
6,161,047✔
38
      dTrace("vgId:%d,acquire vnode, vnode:%p, ref:%d", pVnode->vgId, pVnode, refCount);
6,161,047✔
39
      pVnodes[num++] = (*ppVnode);
6,161,047✔
40
      pIter = taosHashIterate(pMgmt->runngingHash, pIter);
6,161,047✔
41
    } else {
42
      taosHashCancelIterate(pMgmt->runngingHash, pIter);
×
43
    }
44
  }
45

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

60
  *numOfVnodes = num;
2,122,704✔
61
  *ppVnodes = pVnodes;
2,122,704✔
62

63
  return 0;
2,122,704✔
64
}
65

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

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

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

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

108
  *numOfVnodes = num;
951,188✔
109
  *ppVnodes = pVnodes;
951,188✔
110

111
  return 0;
951,188✔
112
}
113

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

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

125
  void *pIter = taosHashIterate(pMgmt->runngingHash, NULL);
813,296✔
126
  while (pIter) {
2,268,965✔
127
    SVnodeObj **ppVnode = pIter;
1,455,669✔
128
    SVnodeObj  *pVnode = *ppVnode;
1,455,669✔
129
    if (pVnode && num < size) {
2,911,338!
130
      int32_t refCount = atomic_add_fetch_32(&pVnode->refCount, 1);
1,455,669✔
131
      dTrace("vgId:%d, acquire vnode, vnode:%p, ref:%d", pVnode->vgId, pVnode, refCount);
1,455,669✔
132
      pVnodes[num++] = (*ppVnode);
1,455,669✔
133
      pIter = taosHashIterate(pMgmt->runngingHash, pIter);
1,455,669✔
134
    } else {
135
      taosHashCancelIterate(pMgmt->runngingHash, pIter);
×
136
    }
137
  }
138

139
  (void)taosThreadRwlockUnlock(&pMgmt->hashLock);
813,296✔
140
  *numOfVnodes = num;
813,296✔
141
  *ppVnodes = pVnodes;
813,296✔
142

143
  return 0;
813,296✔
144
}
145

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

151
  SJson *vnodes = tjsonGetObjectItem(pJson, "vnodes");
46,353✔
152
  if (vnodes == NULL) return TSDB_CODE_INVALID_JSON_FORMAT;
46,353!
153

154
  int32_t vnodesNum = cJSON_GetArraySize(vnodes);
46,353✔
155
  if (vnodesNum > 0) {
46,353✔
156
    pCfgs = taosMemoryCalloc(vnodesNum, sizeof(SWrapperCfg));
44,780!
157
    if (pCfgs == NULL) return terrno;
44,780!
158
  }
159

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

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

180
    snprintf(pCfg->path, sizeof(pCfg->path), "%s%svnode%d", pMgmt->path, TD_DIRSEP, pCfg->vgId);
115,553!
181
  }
182

183
  code = 0;
46,353✔
184
  *ppCfgs = pCfgs;
46,353✔
185
  *numOfVnodes = vnodesNum;
46,353✔
186

187
_OVER:
46,353✔
188
  if (*ppCfgs == NULL) taosMemoryFree(pCfgs);
46,353!
189
  return code;
46,353✔
190
}
191

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

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

208
  pFile = taosOpenFile(file, TD_FILE_READ);
46,353✔
209
  if (pFile == NULL) {
46,353!
210
    code = terrno;
×
211
    dError("failed to open vnode file:%s since %s", file, tstrerror(code));
×
212
    goto _OVER;
×
213
  }
214

215
  int64_t size = 0;
46,353✔
216
  code = taosFStatFile(pFile, &size, NULL);
46,353✔
217
  if (code != 0) {
46,353!
218
    dError("failed to fstat vnode file:%s since %s", file, tstrerror(code));
×
219
    goto _OVER;
×
220
  }
221

222
  pData = taosMemoryMalloc(size + 1);
46,353!
223
  if (pData == NULL) {
46,353!
224
    code = terrno;
×
225
    goto _OVER;
×
226
  }
227

228
  if (taosReadFile(pFile, pData, size) != size) {
46,353!
229
    code = terrno;
×
230
    dError("failed to read vnode file:%s since %s", file, tstrerror(code));
×
231
    goto _OVER;
×
232
  }
233

234
  pData[size] = '\0';
46,353✔
235

236
  pJson = tjsonParse(pData);
46,353✔
237
  if (pJson == NULL) {
46,353!
238
    code = TSDB_CODE_INVALID_JSON_FORMAT;
×
239
    goto _OVER;
×
240
  }
241

242
  if (vmDecodeVnodeList(pJson, pMgmt, ppCfgs, numOfVnodes) < 0) {
46,353!
243
    code = TSDB_CODE_INVALID_JSON_FORMAT;
×
244
    goto _OVER;
×
245
  }
246

247
  code = 0;
46,353✔
248
  dInfo("succceed to read vnode file %s", file);
46,353!
249

250
_OVER:
46,324✔
251
  if (pData != NULL) taosMemoryFree(pData);
46,353!
252
  if (pJson != NULL) cJSON_Delete(pJson);
46,353!
253
  if (pFile != NULL) taosCloseFile(&pFile);
46,353!
254

255
  if (code != 0) {
46,353!
256
    dError("failed to read vnode file:%s since %s", file, tstrerror(code));
×
257
  }
258
  return code;
46,353✔
259
}
260

261
static int32_t vmEncodeVnodeList(SJson *pJson, SVnodeObj **ppVnodes, int32_t numOfVnodes) {
2,122,704✔
262
  int32_t code = 0;
2,122,704✔
263
  SJson  *vnodes = tjsonCreateArray();
2,122,704✔
264
  if (vnodes == NULL) {
2,122,704!
265
    return terrno;
×
266
  }
267
  if ((code = tjsonAddItemToObject(pJson, "vnodes", vnodes)) < 0) {
2,122,704!
268
    tjsonDelete(vnodes);
×
269
    return code;
×
270
  };
271

272
  for (int32_t i = 0; i < numOfVnodes; ++i) {
8,283,806✔
273
    SVnodeObj *pVnode = ppVnodes[i];
6,161,102✔
274
    if (pVnode == NULL) continue;
6,161,102!
275

276
    SJson *vnode = tjsonCreateObject();
6,161,102✔
277
    if (vnode == NULL) return terrno;
6,161,102!
278
    if ((code = tjsonAddDoubleToObject(vnode, "vgId", pVnode->vgId)) < 0) return code;
6,161,102!
279
    if ((code = tjsonAddDoubleToObject(vnode, "dropped", pVnode->dropped)) < 0) return code;
6,161,102!
280
    if ((code = tjsonAddDoubleToObject(vnode, "vgVersion", pVnode->vgVersion)) < 0) return code;
6,161,102!
281
    if ((code = tjsonAddDoubleToObject(vnode, "diskPrimary", pVnode->diskPrimary)) < 0) return code;
6,161,102!
282
    if (pVnode->toVgId) {
6,161,102✔
283
      if ((code = tjsonAddDoubleToObject(vnode, "toVgId", pVnode->toVgId)) < 0) return code;
1,523!
284
    }
285
    if (pVnode->mountId) {
6,161,102!
286
      if ((code = tjsonAddIntegerToObject(vnode, "mountId", pVnode->mountId)) < 0) return code;
×
287
    }
288
    if ((code = tjsonAddItemToArray(vnodes, vnode)) < 0) return code;
6,161,102!
289
  }
290

291
  return 0;
2,122,704✔
292
}
293

294
int32_t vmWriteVnodeListToFile(SVnodeMgmt *pMgmt) {
2,122,704✔
295
  int32_t     code = -1;
2,122,704✔
296
  char       *buffer = NULL;
2,122,704✔
297
  SJson      *pJson = NULL;
2,122,704✔
298
  TdFilePtr   pFile = NULL;
2,122,704✔
299
  SVnodeObj **ppVnodes = NULL;
2,122,704✔
300
  char        file[PATH_MAX] = {0};
2,122,704✔
301
  char        realfile[PATH_MAX] = {0};
2,122,704✔
302
  int32_t     lino = 0;
2,122,704✔
303
  int32_t     ret = -1;
2,122,704✔
304

305
  int32_t nBytes = snprintf(file, sizeof(file), "%s%svnodes_tmp.json", pMgmt->path, TD_DIRSEP);
2,122,704✔
306
  if (nBytes <= 0 || nBytes >= sizeof(file)) {
2,122,704!
307
    return TSDB_CODE_OUT_OF_RANGE;
×
308
  }
309

310
  nBytes = snprintf(realfile, sizeof(realfile), "%s%svnodes.json", pMgmt->path, TD_DIRSEP);
2,122,704✔
311
  if (nBytes <= 0 || nBytes >= sizeof(realfile)) {
2,122,704!
312
    return TSDB_CODE_OUT_OF_RANGE;
×
313
  }
314

315
  int32_t numOfVnodes = 0;
2,122,704✔
316
  (void)taosThreadRwlockWrlock(&pMgmt->hashLock);
2,122,704✔
317
  TAOS_CHECK_GOTO(vmGetAllVnodeListFromHash(pMgmt, &numOfVnodes, &ppVnodes), &lino, _OVER);
2,122,704!
318

319
  // terrno = TSDB_CODE_OUT_OF_MEMORY;
320
  pJson = tjsonCreateObject();
2,122,704✔
321
  if (pJson == NULL) {
2,122,704!
322
    code = terrno;
×
323
    goto _OVER;
×
324
  }
325
  TAOS_CHECK_GOTO(vmEncodeVnodeList(pJson, ppVnodes, numOfVnodes), &lino, _OVER);
2,122,704!
326

327
  buffer = tjsonToString(pJson);
2,122,704✔
328
  if (buffer == NULL) {
2,122,704!
329
    code = TSDB_CODE_INVALID_JSON_FORMAT;
×
330
    lino = __LINE__;
×
331
    goto _OVER;
×
332
  }
333

334

335
  pFile = taosOpenFile(file, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC | TD_FILE_WRITE_THROUGH);
2,122,704✔
336
  if (pFile == NULL) {
2,122,704!
337
    code = terrno;
×
338
    lino = __LINE__;
×
339
    goto _OVER;
×
340
  }
341

342
  int32_t len = strlen(buffer);
2,122,704!
343
  if (taosWriteFile(pFile, buffer, len) <= 0) {
2,122,704!
344
    code = terrno;
×
345
    lino = __LINE__;
×
346
    goto _OVER;
×
347
  }
348
  if (taosFsyncFile(pFile) < 0) {
2,122,704!
349
    code = TAOS_SYSTEM_ERROR(ERRNO);
×
350
    lino = __LINE__;
×
351
    goto _OVER;
×
352
  }
353

354
  code = taosCloseFile(&pFile);
2,122,704✔
355
  if (code != 0) {
2,122,704!
356
    code = TAOS_SYSTEM_ERROR(ERRNO);
×
357
    lino = __LINE__;
×
358
    goto _OVER;
×
359
  }
360
  TAOS_CHECK_GOTO(taosRenameFile(file, realfile), &lino, _OVER);
2,122,704!
361

362
  dInfo("succeed to write vnodes file:%s, vnodes:%d", realfile, numOfVnodes);
2,122,704!
363

364
_OVER:
2,122,621✔
365
  (void)taosThreadRwlockUnlock(&pMgmt->hashLock);
2,122,704✔
366

367
  if (pJson != NULL) tjsonDelete(pJson);
2,122,704!
368
  if (buffer != NULL) taosMemoryFree(buffer);
2,122,704!
369
  if (pFile != NULL) taosCloseFile(&pFile);
2,122,704!
370
  if (ppVnodes != NULL) {
2,122,704!
371
    for (int32_t i = 0; i < numOfVnodes; ++i) {
8,283,806✔
372
      SVnodeObj *pVnode = ppVnodes[i];
6,161,102✔
373
      if (pVnode != NULL) {
6,161,102!
374
        vmReleaseVnode(pMgmt, pVnode);
6,161,102✔
375
      }
376
    }
377
    taosMemoryFree(ppVnodes);
2,122,704!
378
  }
379

380
  if (code != 0) {
2,122,704!
381
    dError("failed to write vnodes file:%s at line:%d since %s, vnodes:%d", realfile, lino, tstrerror(code),
×
382
           numOfVnodes);
383
  }
384
  return code;
2,122,704✔
385
}
386

387
#ifdef USE_MOUNT
388
static int32_t vmDecodeMountList(SJson *pJson, SVnodeMgmt *pMgmt, SMountCfg **ppCfgs, int32_t *numOfMounts) {
×
389
  int32_t    code = 0, lino = 0;
×
390
  int32_t    mountsNum = 0;
×
391
  SMountCfg *pCfgs = NULL;
×
392
  SJson     *mounts = NULL;
×
393

394
  if (!(mounts = tjsonGetObjectItem(pJson, "mounts"))) {
×
395
    goto _exit;
×
396
  }
397
  if ((mountsNum = cJSON_GetArraySize(mounts)) > 0) {
×
398
    TSDB_CHECK_NULL((pCfgs = taosMemoryMalloc(mountsNum * sizeof(SMountCfg))), code, lino, _exit, terrno);
×
399
  }
400

401
  for (int32_t i = 0; i < mountsNum; ++i) {
×
402
    SJson *mount = tjsonGetArrayItem(mounts, i);
×
403
    TSDB_CHECK_NULL(mount, code, lino, _exit, TSDB_CODE_INVALID_JSON_FORMAT);
×
404
    SMountCfg *pCfg = &pCfgs[i];
×
405
    TAOS_CHECK_EXIT(tjsonGetBigIntValue(mount, "mountId", &pCfg->mountId));
×
406
    TAOS_CHECK_EXIT(tjsonGetStringValue2(mount, "name", pCfg->name, sizeof(pCfg->name)));
×
407
    TAOS_CHECK_EXIT(tjsonGetStringValue2(mount, "path", pCfg->path, sizeof(pCfg->path)));
×
408
  }
409
_exit:
×
410
  if (code) {
×
411
    dError("failed to decode mount list at line %d since %s", lino, tstrerror(code));
×
412
    if (pCfgs) {
×
413
      taosMemoryFree(pCfgs);
×
414
      pCfgs = NULL;
×
415
    }
416
  }
417
  *numOfMounts = mountsNum;
×
418
  *ppCfgs = pCfgs;
×
419
  return code;
×
420
}
421

422
int32_t vmGetMountListFromFile(SVnodeMgmt *pMgmt, SMountCfg **ppCfgs, int32_t *numOfMounts) {
236,477✔
423
  int32_t    code = 0, lino = 0;
236,477✔
424
  int64_t    size = 0;
236,477✔
425
  TdFilePtr  pFile = NULL;
236,477✔
426
  char      *pData = NULL;
236,477✔
427
  SJson     *pJson = NULL;
236,477✔
428
  char       file[PATH_MAX] = {0};
236,477✔
429
  SMountCfg *pCfgs = NULL;
236,477✔
430
  snprintf(file, sizeof(file), "%s%smounts.json", pMgmt->path, TD_DIRSEP);
236,477✔
431

432
  if (!taosCheckExistFile(file)) goto _exit;
236,477!
433
  TAOS_CHECK_EXIT(taosStatFile(file, &size, NULL, NULL));
×
434
  TSDB_CHECK_NULL((pFile = taosOpenFile(file, TD_FILE_READ)), code, lino, _exit, terrno);
×
435
  TSDB_CHECK_NULL((pData = taosMemoryMalloc(size + 1)), code, lino, _exit, terrno);
×
436
  if (taosReadFile(pFile, pData, size) != size) {
×
437
    TAOS_CHECK_EXIT(terrno);
×
438
  }
439
  pData[size] = '\0';
×
440
  TSDB_CHECK_NULL((pJson = tjsonParse(pData)), code, lino, _exit, TSDB_CODE_INVALID_JSON_FORMAT);
×
441
  TAOS_CHECK_EXIT(vmDecodeMountList(pJson, pMgmt, ppCfgs, numOfMounts));
×
442
  dInfo("succceed to read mounts file %s", file);
×
443
_exit:
236,243✔
444
  if (pData != NULL) taosMemoryFree(pData);
236,477!
445
  if (pJson != NULL) cJSON_Delete(pJson);
236,477!
446
  if (pFile != NULL) taosCloseFile(&pFile);
236,477!
447
  if (code != 0) {
236,477!
448
    dError("failed to read mounts file:%s since %s", file, tstrerror(code));
×
449
  }
450
  return code;
236,477✔
451
}
452

453
static int32_t vmEncodeMountList(SVnodeMgmt *pMgmt, SJson *pJson) {
×
454
  int32_t    code = 0, lino = 0;
×
455
  SHashObj  *pTfsHash = pMgmt->mountTfsHash;
×
456
  int32_t    numOfMounts = 0;
×
457
  SJson     *mounts = NULL;
×
458
  SJson     *mount = NULL;
×
459
  SMountTfs *pTfs = NULL;
×
460

461
  if ((numOfMounts = taosHashGetSize(pTfsHash)) < 0) {
×
462
    goto _exit;
×
463
  }
464
  TSDB_CHECK_NULL((mounts = tjsonCreateArray()), code, lino, _exit, terrno);
×
465
  if ((code = tjsonAddItemToObject(pJson, "mounts", mounts))) {
×
466
    tjsonDelete(mounts);
×
467
    TAOS_CHECK_EXIT(code);
×
468
  }
469
  size_t keyLen = sizeof(int64_t);
×
470
  while ((pTfs = taosHashIterate(pTfsHash, pTfs))) {
×
471
    TSDB_CHECK_NULL((mount = tjsonCreateObject()), code, lino, _exit, terrno);
×
472
    if (!mount) TAOS_CHECK_EXIT(terrno);
×
473
    int64_t mountId = *(int64_t *)taosHashGetKey(pTfs, NULL);
×
474
    TAOS_CHECK_EXIT(tjsonAddIntegerToObject(mount, "mountId", mountId));
×
475
    TAOS_CHECK_EXIT(tjsonAddStringToObject(mount, "name", (*(SMountTfs **)pTfs)->name));
×
476
    TAOS_CHECK_EXIT(tjsonAddStringToObject(mount, "path", (*(SMountTfs **)pTfs)->path));
×
477
    TAOS_CHECK_EXIT(tjsonAddItemToArray(mounts, mount));
×
478
    mount = NULL;
×
479
  }
480
_exit:
×
481
  if (code != 0) {
×
482
    if (mount) tjsonDelete(mount);
×
483
    if (pTfs) taosHashCancelIterate(pTfsHash, pTfs);
×
484
    dError("failed to encode mount list at line %d since %s", lino, tstrerror(code));
×
485
  }
486
  TAOS_RETURN(code);
×
487
}
488
#endif
489

490
int32_t vmWriteMountListToFile(SVnodeMgmt *pMgmt) {
×
491
  int32_t     code = 0, lino = 0, ret = 0;
×
492
#ifdef USE_MOUNT
493
  char       *buffer = NULL;
×
494
  SJson      *pJson = NULL;
×
495
  TdFilePtr   pFile = NULL;
×
496
  SVnodeObj **ppVnodes = NULL;
×
497
  char        file[PATH_MAX] = {0};
×
498
  char        realfile[PATH_MAX] = {0};
×
499
  bool        unlock = false;
×
500

501
  int32_t nBytes = snprintf(file, sizeof(file), "%s%smounts_tmp.json", pMgmt->path, TD_DIRSEP);
×
502
  if (nBytes <= 0 || nBytes >= sizeof(file)) {
×
503
    TAOS_CHECK_EXIT(TSDB_CODE_OUT_OF_RANGE);
×
504
  }
505
  nBytes = snprintf(realfile, sizeof(realfile), "%s%smounts.json", pMgmt->path, TD_DIRSEP);
×
506
  if (nBytes <= 0 || nBytes >= sizeof(realfile)) {
×
507
    TAOS_CHECK_EXIT(TSDB_CODE_OUT_OF_RANGE);
×
508
  }
509
  TSDB_CHECK_NULL((pJson = tjsonCreateObject()), code, lino, _exit, terrno);
×
510
  TAOS_CHECK_EXIT(vmEncodeMountList(pMgmt, pJson));
×
511
  TSDB_CHECK_NULL((buffer = tjsonToString(pJson)), code, lino, _exit, terrno);
×
512
  TAOS_CHECK_EXIT(taosThreadMutexLock(&pMgmt->mutex));
×
513
  unlock = true;
×
514
  TSDB_CHECK_NULL((pFile = taosOpenFile(file, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC | TD_FILE_WRITE_THROUGH)),
×
515
                  code, lino, _exit, terrno);
516

517
  int32_t len = strlen(buffer);
×
518
  if ((code = taosWriteFile(pFile, buffer, len)) <= 0) {
×
519
    TAOS_CHECK_EXIT(code);
×
520
  }
521
  TAOS_CHECK_EXIT(taosFsyncFile(pFile));
×
522
  TAOS_CHECK_EXIT(taosCloseFile(&pFile));
×
523
  TAOS_CHECK_EXIT(taosRenameFile(file, realfile));
×
524
  dInfo("succeed to write mounts file:%s", realfile);
×
525
_exit:
×
526
  if (unlock && (ret = taosThreadMutexUnlock(&pMgmt->mutex))) {
×
527
    dError("failed to unlock at line %d when write mounts file since %s", __LINE__, tstrerror(ret));
×
528
  }
529
  if (pJson) tjsonDelete(pJson);
×
530
  if (buffer) taosMemoryFree(buffer);
×
531
  if (pFile) taosCloseFile(&pFile);
×
532
  if (code != 0) {
×
533
    dError("failed to write mounts file:%s at line:%d since %s", realfile, lino, tstrerror(code));
×
534
  }
535
#endif
536
  TAOS_RETURN(code);
×
537
}
538
#ifdef USE_MOUNT
539
int32_t vmGetMountDisks(SVnodeMgmt *pMgmt, const char *mountPath, SArray **ppDisks) {
×
540
  int32_t   code = 0, lino = 0;
×
541
  SArray   *pDisks = NULL;
×
542
  TdFilePtr pFile = NULL;
×
543
  char     *content = NULL;
×
544
  SJson    *pJson = NULL;
×
545
  int64_t   size = 0;
×
546
  int64_t   clusterId = 0, dropped = 0, encryptScope = 0;
×
547
  char      file[TSDB_MOUNT_FPATH_LEN] = {0};
×
548

549
  (void)snprintf(file, sizeof(file), "%s%s%s%sconfig%s%s", mountPath, TD_DIRSEP, dmNodeName(DNODE), TD_DIRSEP,
×
550
                 TD_DIRSEP, "local.json");
551
  TAOS_CHECK_EXIT(taosStatFile(file, &size, NULL, NULL));
×
552
  TSDB_CHECK_NULL((pFile = taosOpenFile(file, TD_FILE_READ)), code, lino, _exit, terrno);
×
553
  TSDB_CHECK_NULL((content = taosMemoryMalloc(size + 1)), code, lino, _exit, terrno);
×
554
  if (taosReadFile(pFile, content, size) != size) {
×
555
    TAOS_CHECK_EXIT(terrno);
×
556
  }
557
  content[size] = '\0';
×
558
  pJson = tjsonParse(content);
×
559
  if (pJson == NULL) {
×
560
    TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
561
  }
562
  SJson *pConfigs = tjsonGetObjectItem(pJson, "configs");
×
563
  if (pConfigs == NULL) {
×
564
    TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
565
  }
566
  int32_t nDataDir = 0;
×
567
  SJson  *pDataDir = tjsonGetObjectItem(pConfigs, "dataDir");
×
568
  if (pDataDir) {
×
569
    nDataDir = tjsonGetArraySize(pDataDir);
×
570
  }
571
  if (!(pDisks = taosArrayInit_s(sizeof(SDiskCfg), nDataDir > 0 ? nDataDir : 1))) {
×
572
    TAOS_CHECK_EXIT(TSDB_CODE_OUT_OF_MEMORY);
×
573
  }
574
  for (int32_t i = 0; i < nDataDir; ++i) {
×
575
    char   dir[TSDB_MOUNT_PATH_LEN] = {0};
×
576
    SJson *pItem = tjsonGetArrayItem(pDataDir, i);
×
577
    if (pItem == NULL) {
×
578
      TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
579
    }
580
    code = tjsonGetStringValue(pItem, "dir", dir);
×
581
    if (code < 0) {
×
582
      TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
583
    }
584
    int32_t j = strlen(dir) - 1;
×
585
    while (j > 0 && (dir[j] == '/' || dir[j] == '\\')) {
×
586
      dir[j--] = '\0';  // remove trailing slashes
×
587
    }
588
    SJson *pLevel = tjsonGetObjectItem(pItem, "level");
×
589
    if (!pLevel) {
×
590
      TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
591
    }
592
    int32_t level = (int32_t)cJSON_GetNumberValue(pLevel);
×
593
    if (level < 0 || level >= TFS_MAX_TIERS) {
×
594
      TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
595
    }
596
    SJson *pPrimary = tjsonGetObjectItem(pItem, "primary");
×
597
    if (!pPrimary) {
×
598
      TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
599
    }
600
    int32_t primary = (int32_t)cJSON_GetNumberValue(pPrimary);
×
601
    if ((primary < 0 || primary > 1) || (primary == 1 && level != 0)) {
×
602
      dError("mount:%s, invalid primary disk, primary:%d, level:%d", mountPath, primary, level);
×
603
      TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
604
    }
605
    int8_t    disable = (int8_t)cJSON_GetNumberValue(pLevel);
×
606
    SDiskCfg *pDisk = taosArrayGet(pDisks, i);
×
607
    pDisk->level = level;
×
608
    pDisk->primary = primary;
×
609
    pDisk->disable = disable;
×
610
    if (primary == 1 && level == 0) {
×
611
      (void)snprintf(pDisk->dir, sizeof(pDisk->dir), "%s", mountPath);
×
612
    } else {
613
      (void)snprintf(pDisk->dir, sizeof(pDisk->dir), "%s", dir);
×
614
    }
615
  }
616
  if (nDataDir <= 0) {
×
617
    SDiskCfg *pDisk = taosArrayGet(pDisks, 0);
×
618
    pDisk->level = 0;
×
619
    pDisk->primary = 1;
×
620
    pDisk->disable = 0;
×
621
    (void)snprintf(pDisk->dir, sizeof(pDisk->dir), "%s", mountPath);
×
622
  }
623
_exit:
×
624
  if (content != NULL) taosMemoryFreeClear(content);
×
625
  if (pJson != NULL) cJSON_Delete(pJson);
×
626
  if (pFile != NULL) taosCloseFile(&pFile);
×
627
  if (code != 0) {
×
628
    dError("failed to get mount disks at line %d since %s, path:%s", lino, tstrerror(code), mountPath);
×
629
    taosArrayDestroy(pDisks);
×
630
    pDisks = NULL;
×
631
  }
632
  *ppDisks = pDisks;
×
633
  TAOS_RETURN(code);
×
634
}
635

636
#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