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

taosdata / TDengine / #4881

14 Dec 2025 03:48AM UTC coverage: 60.617% (+0.5%) from 60.092%
#4881

push

travis-ci

web-flow
test: update coverage workflow time (#33918)

156854 of 258761 relevant lines covered (60.62%)

75258957.81 hits per line

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

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

32
  void *pIter = taosHashIterate(pMgmt->runngingHash, NULL);
3,504,248✔
33
  while (pIter) {
17,355,048✔
34
    SVnodeObj **ppVnode = pIter;
13,850,800✔
35
    SVnodeObj  *pVnode = *ppVnode;
13,850,800✔
36
    if (pVnode && num < size) {
27,701,600✔
37
      int32_t refCount = atomic_add_fetch_32(&pVnode->refCount, 1);
13,850,800✔
38
      dTrace("vgId:%d,acquire vnode, vnode:%p, ref:%d", pVnode->vgId, pVnode, refCount);
13,850,800✔
39
      pVnodes[num++] = (*ppVnode);
13,850,800✔
40
      pIter = taosHashIterate(pMgmt->runngingHash, pIter);
13,850,800✔
41
    } else {
42
      taosHashCancelIterate(pMgmt->runngingHash, pIter);
×
43
    }
44
  }
45

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

60
  *numOfVnodes = num;
3,504,248✔
61
  *ppVnodes = pVnodes;
3,504,248✔
62

63
  return 0;
3,504,248✔
64
}
65

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

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

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

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

108
  *numOfVnodes = num;
1,543,785✔
109
  *ppVnodes = pVnodes;
1,543,785✔
110

111
  return 0;
1,543,785✔
112
}
113

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

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

125
  void *pIter = taosHashIterate(pMgmt->runngingHash, NULL);
1,149,380✔
126
  while (pIter) {
3,322,892✔
127
    SVnodeObj **ppVnode = pIter;
2,173,512✔
128
    SVnodeObj  *pVnode = *ppVnode;
2,173,512✔
129
    if (pVnode && num < size) {
4,347,024✔
130
      int32_t refCount = atomic_add_fetch_32(&pVnode->refCount, 1);
2,173,512✔
131
      dTrace("vgId:%d, acquire vnode, vnode:%p, ref:%d", pVnode->vgId, pVnode, refCount);
2,173,512✔
132
      pVnodes[num++] = (*ppVnode);
2,173,512✔
133
      pIter = taosHashIterate(pMgmt->runngingHash, pIter);
2,173,512✔
134
    } else {
135
      taosHashCancelIterate(pMgmt->runngingHash, pIter);
×
136
    }
137
  }
138

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

143
  return 0;
1,149,380✔
144
}
145

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

151
  SJson *vnodes = tjsonGetObjectItem(pJson, "vnodes");
58,749✔
152
  if (vnodes == NULL) return TSDB_CODE_INVALID_JSON_FORMAT;
58,749✔
153

154
  int32_t vnodesNum = cJSON_GetArraySize(vnodes);
58,749✔
155
  if (vnodesNum > 0) {
58,749✔
156
    pCfgs = taosMemoryCalloc(vnodesNum, sizeof(SWrapperCfg));
56,421✔
157
    if (pCfgs == NULL) return terrno;
56,421✔
158
  }
159

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

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

180
    snprintf(pCfg->path, sizeof(pCfg->path), "%s%svnode%d", pMgmt->path, TD_DIRSEP, pCfg->vgId);
152,518✔
181
  }
182

183
  code = 0;
58,749✔
184
  *ppCfgs = pCfgs;
58,749✔
185
  *numOfVnodes = vnodesNum;
58,749✔
186

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

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

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

208
  pFile = taosOpenFile(file, TD_FILE_READ);
58,749✔
209
  if (pFile == NULL) {
58,749✔
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;
58,749✔
216
  code = taosFStatFile(pFile, &size, NULL);
58,749✔
217
  if (code != 0) {
58,749✔
218
    dError("failed to fstat vnode file:%s since %s", file, tstrerror(code));
×
219
    goto _OVER;
×
220
  }
221

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

228
  if (taosReadFile(pFile, pData, size) != size) {
58,749✔
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';
58,749✔
235

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

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

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

250
_OVER:
58,744✔
251
  if (pData != NULL) taosMemoryFree(pData);
58,749✔
252
  if (pJson != NULL) cJSON_Delete(pJson);
58,749✔
253
  if (pFile != NULL) taosCloseFile(&pFile);
58,749✔
254

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

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

272
  for (int32_t i = 0; i < numOfVnodes; ++i) {
17,374,543✔
273
    SVnodeObj *pVnode = ppVnodes[i];
13,870,295✔
274
    if (pVnode == NULL) continue;
13,870,295✔
275

276
    SJson *vnode = tjsonCreateObject();
13,870,295✔
277
    if (vnode == NULL) return terrno;
13,870,295✔
278
    if ((code = tjsonAddDoubleToObject(vnode, "vgId", pVnode->vgId)) < 0) return code;
13,870,295✔
279
    if ((code = tjsonAddDoubleToObject(vnode, "dropped", pVnode->dropped)) < 0) return code;
13,870,295✔
280
    if ((code = tjsonAddDoubleToObject(vnode, "vgVersion", pVnode->vgVersion)) < 0) return code;
13,870,295✔
281
    if ((code = tjsonAddDoubleToObject(vnode, "diskPrimary", pVnode->diskPrimary)) < 0) return code;
13,870,295✔
282
    if (pVnode->toVgId) {
13,870,295✔
283
      if ((code = tjsonAddDoubleToObject(vnode, "toVgId", pVnode->toVgId)) < 0) return code;
13,043✔
284
    }
285
    if (pVnode->mountId) {
13,870,295✔
286
      if ((code = tjsonAddIntegerToObject(vnode, "mountId", pVnode->mountId)) < 0) return code;
9,226✔
287
    }
288
    if ((code = tjsonAddItemToArray(vnodes, vnode)) < 0) return code;
13,870,295✔
289
  }
290

291
  return 0;
3,504,248✔
292
}
293

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

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

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

315
  int32_t numOfVnodes = 0;
3,504,248✔
316
  (void)taosThreadRwlockWrlock(&pMgmt->hashLock);
3,504,248✔
317
  TAOS_CHECK_GOTO(vmGetAllVnodeListFromHash(pMgmt, &numOfVnodes, &ppVnodes), &lino, _OVER);
3,504,248✔
318

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

327
  buffer = tjsonToString(pJson);
3,504,248✔
328
  if (buffer == NULL) {
3,504,248✔
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);
3,504,248✔
336
  if (pFile == NULL) {
3,504,248✔
337
    code = terrno;
×
338
    lino = __LINE__;
×
339
    goto _OVER;
×
340
  }
341

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

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

362
  dInfo("succeed to write vnodes file:%s, vnodes:%d", realfile, numOfVnodes);
3,504,248✔
363

364
_OVER:
3,503,682✔
365
  (void)taosThreadRwlockUnlock(&pMgmt->hashLock);
3,504,248✔
366

367
  if (pJson != NULL) tjsonDelete(pJson);
3,504,248✔
368
  if (buffer != NULL) taosMemoryFree(buffer);
3,504,248✔
369
  if (pFile != NULL) taosCloseFile(&pFile);
3,504,248✔
370
  if (ppVnodes != NULL) {
3,504,248✔
371
    for (int32_t i = 0; i < numOfVnodes; ++i) {
17,374,543✔
372
      SVnodeObj *pVnode = ppVnodes[i];
13,870,295✔
373
      if (pVnode != NULL) {
13,870,295✔
374
        vmReleaseVnode(pMgmt, pVnode);
13,870,295✔
375
      }
376
    }
377
    taosMemoryFree(ppVnodes);
3,504,248✔
378
  }
379

380
  if (code != 0) {
3,504,248✔
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;
3,504,248✔
385
}
386

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

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

401
  for (int32_t i = 0; i < mountsNum; ++i) {
815✔
402
    SJson *mount = tjsonGetArrayItem(mounts, i);
327✔
403
    TSDB_CHECK_NULL(mount, code, lino, _exit, TSDB_CODE_INVALID_JSON_FORMAT);
327✔
404
    SMountCfg *pCfg = &pCfgs[i];
327✔
405
    TAOS_CHECK_EXIT(tjsonGetBigIntValue(mount, "mountId", &pCfg->mountId));
327✔
406
    TAOS_CHECK_EXIT(tjsonGetStringValue2(mount, "name", pCfg->name, sizeof(pCfg->name)));
327✔
407
    TAOS_CHECK_EXIT(tjsonGetStringValue2(mount, "path", pCfg->path, sizeof(pCfg->path)));
327✔
408
  }
409
_exit:
488✔
410
  if (code) {
488✔
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;
488✔
418
  *ppCfgs = pCfgs;
488✔
419
  return code;
488✔
420
}
421

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

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

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

461
  if ((numOfMounts = taosHashGetSize(pTfsHash)) < 0) {
1,655✔
462
    goto _exit;
×
463
  }
464
  TSDB_CHECK_NULL((mounts = tjsonCreateArray()), code, lino, _exit, terrno);
1,655✔
465
  if ((code = tjsonAddItemToObject(pJson, "mounts", mounts))) {
1,655✔
466
    tjsonDelete(mounts);
×
467
    TAOS_CHECK_EXIT(code);
×
468
  }
469
  size_t keyLen = sizeof(int64_t);
1,655✔
470
  while ((pTfs = taosHashIterate(pTfsHash, pTfs))) {
2,983✔
471
    TSDB_CHECK_NULL((mount = tjsonCreateObject()), code, lino, _exit, terrno);
1,328✔
472
    if (!mount) TAOS_CHECK_EXIT(terrno);
1,328✔
473
    int64_t mountId = *(int64_t *)taosHashGetKey(pTfs, NULL);
1,328✔
474
    TAOS_CHECK_EXIT(tjsonAddIntegerToObject(mount, "mountId", mountId));
1,328✔
475
    TAOS_CHECK_EXIT(tjsonAddStringToObject(mount, "name", (*(SMountTfs **)pTfs)->name));
1,328✔
476
    TAOS_CHECK_EXIT(tjsonAddStringToObject(mount, "path", (*(SMountTfs **)pTfs)->path));
1,328✔
477
    TAOS_CHECK_EXIT(tjsonAddItemToArray(mounts, mount));
1,328✔
478
    mount = NULL;
1,328✔
479
  }
480
_exit:
1,655✔
481
  if (code != 0) {
1,655✔
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);
1,655✔
487
}
488
#endif
489

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

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

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

549
  (void)snprintf(file, sizeof(file), "%s%s%s%sconfig%s%s", mountPath, TD_DIRSEP, dmNodeName(DNODE), TD_DIRSEP,
1,162✔
550
                 TD_DIRSEP, "local.json");
551
  TAOS_CHECK_EXIT(taosStatFile(file, &size, NULL, NULL));
1,162✔
552
  TSDB_CHECK_NULL((pFile = taosOpenFile(file, TD_FILE_READ)), code, lino, _exit, terrno);
1,162✔
553
  TSDB_CHECK_NULL((content = taosMemoryMalloc(size + 1)), code, lino, _exit, terrno);
1,162✔
554
  if (taosReadFile(pFile, content, size) != size) {
1,162✔
555
    TAOS_CHECK_EXIT(terrno);
×
556
  }
557
  content[size] = '\0';
1,162✔
558
  pJson = tjsonParse(content);
1,162✔
559
  if (pJson == NULL) {
1,162✔
560
    TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
561
  }
562
  SJson *pConfigs = tjsonGetObjectItem(pJson, "configs");
1,162✔
563
  if (pConfigs == NULL) {
1,162✔
564
    TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
565
  }
566
  int32_t nDataDir = 0;
1,162✔
567
  SJson  *pDataDir = tjsonGetObjectItem(pConfigs, "dataDir");
1,162✔
568
  if (pDataDir) {
1,162✔
569
    nDataDir = tjsonGetArraySize(pDataDir);
1,162✔
570
  }
571
  if (!(pDisks = taosArrayInit_s(sizeof(SDiskCfg), nDataDir > 0 ? nDataDir : 1))) {
1,162✔
572
    TAOS_CHECK_EXIT(TSDB_CODE_OUT_OF_MEMORY);
×
573
  }
574
  for (int32_t i = 0; i < nDataDir; ++i) {
8,134✔
575
    char   dir[TSDB_MOUNT_PATH_LEN] = {0};
6,972✔
576
    SJson *pItem = tjsonGetArrayItem(pDataDir, i);
6,972✔
577
    if (pItem == NULL) {
6,972✔
578
      TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
579
    }
580
    code = tjsonGetStringValue(pItem, "dir", dir);
6,972✔
581
    if (code < 0) {
6,972✔
582
      TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
583
    }
584
    int32_t j = strlen(dir) - 1;
6,972✔
585
    while (j > 0 && (dir[j] == '/' || dir[j] == '\\')) {
6,972✔
586
      dir[j--] = '\0';  // remove trailing slashes
×
587
    }
588
    SJson *pLevel = tjsonGetObjectItem(pItem, "level");
6,972✔
589
    if (!pLevel) {
6,972✔
590
      TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
591
    }
592
    int32_t level = (int32_t)cJSON_GetNumberValue(pLevel);
6,972✔
593
    if (level < 0 || level >= TFS_MAX_TIERS) {
6,972✔
594
      TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
595
    }
596
    SJson *pPrimary = tjsonGetObjectItem(pItem, "primary");
6,972✔
597
    if (!pPrimary) {
6,972✔
598
      TAOS_CHECK_EXIT(TSDB_CODE_INVALID_JSON_FORMAT);
×
599
    }
600
    int32_t primary = (int32_t)cJSON_GetNumberValue(pPrimary);
6,972✔
601
    if ((primary < 0 || primary > 1) || (primary == 1 && level != 0)) {
6,972✔
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);
6,972✔
606
    SDiskCfg *pDisk = taosArrayGet(pDisks, i);
6,972✔
607
    pDisk->level = level;
6,972✔
608
    pDisk->primary = primary;
6,972✔
609
    pDisk->disable = disable;
6,972✔
610
    if (primary == 1 && level == 0) {
6,972✔
611
      (void)snprintf(pDisk->dir, sizeof(pDisk->dir), "%s", mountPath);
1,162✔
612
    } else {
613
      (void)snprintf(pDisk->dir, sizeof(pDisk->dir), "%s", dir);
5,810✔
614
    }
615
  }
616
  if (nDataDir <= 0) {
1,162✔
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:
1,162✔
624
  if (content != NULL) taosMemoryFreeClear(content);
1,162✔
625
  if (pJson != NULL) cJSON_Delete(pJson);
1,162✔
626
  if (pFile != NULL) taosCloseFile(&pFile);
1,162✔
627
  if (code != 0) {
1,162✔
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;
1,162✔
633
  TAOS_RETURN(code);
1,162✔
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