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

taosdata / TDengine / #4898

26 Dec 2025 09:58AM UTC coverage: 65.061% (-0.7%) from 65.717%
#4898

push

travis-ci

web-flow
feat: support encryption of configuration files, data files and metadata files (#33801)

350 of 1333 new or added lines in 31 files covered. (26.26%)

2796 existing lines in 159 files now uncovered.

184024 of 282850 relevant lines covered (65.06%)

113940470.33 hits per line

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

71.83
/source/dnode/mgmt/node_mgmt/src/dmMgmt.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 "dmMgmt.h"
18
#include "dmNodes.h"
19
#include "index.h"
20
#include "qworker.h"
21
#include "tcompression.h"
22
#include "tconv.h"
23
#include "tglobal.h"
24
#include "tgrant.h"
25
#include "tconv.h"
26
#include "stream.h"
27
#if defined(TD_ENTERPRISE) && defined(TD_HAS_TAOSK)
28
#include "taoskInt.h"
29
#endif
30

31
static bool dmRequireNode(SDnode *pDnode, SMgmtWrapper *pWrapper) {
3,469,266✔
32
  SMgmtInputOpt input = dmBuildMgmtInputOpt(pWrapper);
3,469,266✔
33
  input.dnodeId = pDnode->data.dnodeId;
3,469,266✔
34

35
  bool    required = false;
3,469,266✔
36
  int32_t code = (*pWrapper->func.requiredFp)(&input, &required);
3,469,266✔
37
  if (!required) {
3,469,266✔
38
    dDebug("node:%s, does not require startup", pWrapper->name);
1,924,746✔
39
  } else {
40
    dDebug("node:%s, required to startup", pWrapper->name);
1,544,520✔
41
  }
42

43
  return required;
3,469,266✔
44
}
45

46
int32_t dmInitDnode(SDnode *pDnode) {
578,211✔
47
  dDebug("start to create dnode");
578,211✔
48
  int32_t code = -1;
578,211✔
49
  char    path[PATH_MAX + 100] = {0};
578,211✔
50

51
  if ((code = dmInitVarsWrapper(pDnode)) != 0) {
578,211✔
52
    goto _OVER;
×
53
  }
54

55
  // compress module init
56
  tsCompressInit(tsLossyColumns, tsFPrecision, tsDPrecision, tsMaxRange, tsCurRange, (int)tsIfAdtFse, tsCompressor);
578,211✔
57

58
  pDnode->wrappers[DNODE].func = dmGetMgmtFunc();
578,211✔
59
  pDnode->wrappers[MNODE].func = mmGetMgmtFunc();
578,211✔
60
  pDnode->wrappers[VNODE].func = vmGetMgmtFunc();
578,211✔
61
  pDnode->wrappers[QNODE].func = qmGetMgmtFunc();
578,211✔
62
  pDnode->wrappers[SNODE].func = smGetMgmtFunc();
578,211✔
63
  pDnode->wrappers[BNODE].func = bmGetMgmtFunc();
578,211✔
64

65
  for (EDndNodeType ntype = DNODE; ntype < NODE_END; ++ntype) {
4,047,477✔
66
    SMgmtWrapper *pWrapper = &pDnode->wrappers[ntype];
3,469,266✔
67
    pWrapper->pDnode = pDnode;
3,469,266✔
68
    pWrapper->name = dmNodeName(ntype);
3,469,266✔
69
    pWrapper->ntype = ntype;
3,469,266✔
70
    (void)taosThreadRwlockInit(&pWrapper->lock, NULL);
3,469,266✔
71

72
    snprintf(path, sizeof(path), "%s%s%s", tsDataDir, TD_DIRSEP, pWrapper->name);
3,469,266✔
73
    pWrapper->path = taosStrdup(path);
3,469,266✔
74
    if (pWrapper->path == NULL) {
3,469,266✔
75
      code = terrno;
×
76
      goto _OVER;
×
77
    }
78

79
    pWrapper->required = dmRequireNode(pDnode, pWrapper);
3,469,266✔
80
  }
81

82
  code = dmCheckRunning(tsDataDir, &pDnode->lockfile);
578,211✔
83
  if (code != 0) {
578,211✔
84
    goto _OVER;
9,839✔
85
  }
86

87
  if ((code = dmInitModule(pDnode)) != 0) {
568,372✔
88
    goto _OVER;
30✔
89
  }
90

91
  indexInit(tsNumOfCommitThreads);
568,342✔
92

93
  if ((code = dmInitStatusClient(pDnode)) != 0) {
568,342✔
94
    goto _OVER;
×
95
  }
96
  if ((code = dmInitSyncClient(pDnode)) != 0) {
568,342✔
97
    goto _OVER;
×
98
  }
99

100
  dmReportStartup("dnode-transport", "initialized");
568,342✔
101
  dDebug("dnode is created, ptr:%p", pDnode);
568,342✔
102
  code = 0;
568,342✔
103

104
_OVER:
578,211✔
105
  if (code != 0 && pDnode != NULL) {
578,211✔
106
    dmClearVars(pDnode);
9,869✔
107
    pDnode = NULL;
9,869✔
108
    dError("failed to create dnode since %s", tstrerror(code));
9,869✔
109
  }
110

111
  return code;
578,211✔
112
}
113

114
void dmCleanupDnode(SDnode *pDnode) {
568,342✔
115
  if (pDnode == NULL) {
568,342✔
116
    return;
×
117
  }
118

119
  dmCleanupClient(pDnode);
568,342✔
120
  dmCleanupStatusClient(pDnode);
568,342✔
121
  dmCleanupSyncClient(pDnode);
568,342✔
122
  dmCleanupServer(pDnode);
568,342✔
123

124
  dmClearVars(pDnode);
568,342✔
125
  rpcCleanup();
568,342✔
126
  streamCleanup();
568,342✔
127
  indexCleanup();
568,342✔
128
  taosConvDestroy();
568,342✔
129

130
  // compress destroy
131
  tsCompressExit();
568,342✔
132

133
  dDebug("dnode is closed, ptr:%p", pDnode);
568,342✔
134
}
135

136
int32_t dmInitVarsWrapper(SDnode *pDnode) {
578,211✔
137
  int32_t code = dmInitVars(pDnode);
578,211✔
138
  if (code == -1) {
578,211✔
139
    return terrno;
×
140
  }
141
  return 0;
578,211✔
142
}
143
int32_t dmInitVars(SDnode *pDnode) {
578,211✔
144
  int32_t     code = 0;
578,211✔
145
  SDnodeData *pData = &pDnode->data;
578,211✔
146
  pData->dnodeId = 0;
578,211✔
147
  pData->clusterId = 0;
578,211✔
148
  pData->dnodeVer = 0;
578,211✔
149
  pData->engineVer = 0;
578,211✔
150
  pData->updateTime = 0;
578,211✔
151
  pData->rebootTime = taosGetTimestampMs();
578,211✔
152
  pData->dropped = 0;
578,211✔
153
  pData->stopped = 0;
578,211✔
154
  char *machineId = NULL;
578,211✔
155
  code = tGetMachineId(&machineId);
578,211✔
156
  if (machineId) {
578,211✔
157
    tstrncpy(pData->machineId, machineId, TSDB_MACHINE_ID_LEN + 1);
578,211✔
158
    taosMemoryFreeClear(machineId);
578,211✔
159
  } else {
160
#if defined(TD_ENTERPRISE) && !defined(GRANTS_CFG)
161
    code = TSDB_CODE_DNODE_NO_MACHINE_CODE;
×
162
    return terrno = code;
×
163
#endif
164
  }
165

166
  pData->dnodeHash = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
578,211✔
167
  if (pData->dnodeHash == NULL) {
578,211✔
168
    dError("failed to init dnode hash");
×
169
    return terrno;
×
170
  }
171

172
  if ((code = dmReadEps(pData)) != 0) {
578,211✔
173
    dError("failed to read file since %s", tstrerror(code));
×
174
    return code;
×
175
  }
176

177
#if defined(TD_ENTERPRISE) || defined(TD_ASTRA_TODO)
178
  tsiEncryptAlgorithm = pData->encryptAlgorigthm;
578,211✔
179
  tsiEncryptScope = pData->encryptScope;
578,211✔
180

181
#if defined(TD_HAS_TAOSK) || defined(TD_ASTRA_TODO)
182
  // Load local encryption keys and initialize key version
183
  {
184
    char masterKeyFile[PATH_MAX] = {0};
578,211✔
185
    char derivedKeyFile[PATH_MAX] = {0};
578,211✔
186
    snprintf(masterKeyFile, sizeof(masterKeyFile), "%s%sdnode%sconfig%smaster.bin", tsDataDir, TD_DIRSEP, TD_DIRSEP,
578,211✔
187
             TD_DIRSEP);
188
    snprintf(derivedKeyFile, sizeof(derivedKeyFile), "%s%sdnode%sconfig%sderived.bin", tsDataDir, TD_DIRSEP, TD_DIRSEP,
578,211✔
189
             TD_DIRSEP);
190

191
    char    svrKey[129] = {0};
578,211✔
192
    char    dbKey[129] = {0};
578,211✔
193
    char    cfgKey[129] = {0};
578,211✔
194
    char    metaKey[129] = {0};
578,211✔
195
    char    dataKey[129] = {0};
578,211✔
196
    int32_t algorithm = 0;
578,211✔
197
    int32_t cfgAlgorithm = 0;
578,211✔
198
    int32_t metaAlgorithm = 0;
578,211✔
199
    int32_t fileVersion = 0;
578,211✔
200
    int32_t keyVersion = 0;
578,211✔
201
    int64_t createTime = 0;
578,211✔
202
    int64_t svrKeyUpdateTime = 0;
578,211✔
203
    int64_t dbKeyUpdateTime = 0;
578,211✔
204

205
    code = taoskLoadEncryptKeys(masterKeyFile, derivedKeyFile, svrKey, dbKey, cfgKey, metaKey, dataKey, &algorithm,
578,211✔
206
                                &cfgAlgorithm, &metaAlgorithm, &fileVersion, &keyVersion, &createTime, 
207
                                &svrKeyUpdateTime, &dbKeyUpdateTime);
208
    if (code == 0) {
578,211✔
NEW
209
      tsLocalKeyVersion = keyVersion;
×
NEW
210
      dInfo("loaded local encryption keys, version:%d", tsLocalKeyVersion);
×
211
    } else {
212
      tsLocalKeyVersion = 0;
578,211✔
213
      dInfo("no local encryption keys found or failed to load, will sync from mnode");
578,211✔
214
    }
215
  }
216
#endif
217
#endif
218
  /*
219
  if(tsiEncryptAlgorithm != 0) {
220
    if(pData->machineId != NULL && strlen(pData->machineId) > 0){
221
      dInfo("get crypt key at startup, machineId:%s", pData->machineId);
222
      int32_t code = 0;
223

224
      //code = taosGetCryptKey(tsAuthCode, pData->machineId, tsCryptKey);
225
      code = 0;
226
      tstrncpy(tsEncryptKey, tsAuthCode, 16);
227

228
      if (code != 0) {
229
        if(code == -1){
230
          terrno = TSDB_CODE_DNODE_NO_ENCRYPT_KEY;
231
          dError("machine code changed, can't get crypt key");
232
        }
233
        if(code == -2){
234
          terrno = TSDB_CODE_DNODE_NO_ENCRYPT_KEY;
235
          dError("failed to get crypt key");
236
        }
237
        return -1;
238
      }
239

240
      if(strlen(tsEncryptKey) == 0){
241
        terrno = TSDB_CODE_DNODE_NO_ENCRYPT_KEY;
242
        dError("failed to get crypt key at startup since key is null, machineId:%s", pData->machineId);
243
        return -1;
244
      }
245
    }
246
    else{
247
      terrno = TSDB_CODE_DNODE_NO_MACHINE_CODE;
248
      dError("failed to get crypt key at startup, machineId:%s", pData->machineId);
249
      return -1;
250
    }
251
  }
252
  */
253

254
  if (pData->dropped) {
578,211✔
255
    dError("dnode will not start since its already dropped");
×
256
    return -1;
×
257
  }
258

259
  (void)taosThreadRwlockInit(&pData->lock, NULL);
578,211✔
260
  (void)taosThreadMutexInit(&pData->statusInfolock, NULL);
578,211✔
261
  (void)taosThreadMutexInit(&pDnode->mutex, NULL);
578,211✔
262
  return 0;
578,211✔
263
}
264

265
extern SMonVloadInfo tsVinfo;
266

267
void dmClearVars(SDnode *pDnode) {
578,211✔
268
  for (EDndNodeType ntype = DNODE; ntype < NODE_END; ++ntype) {
4,047,477✔
269
    SMgmtWrapper *pWrapper = &pDnode->wrappers[ntype];
3,469,266✔
270
    taosMemoryFreeClear(pWrapper->path);
3,469,266✔
271
    (void)taosThreadRwlockDestroy(&pWrapper->lock);
3,469,266✔
272
  }
273
  if (pDnode->lockfile != NULL) {
578,211✔
274
    if (taosUnLockFile(pDnode->lockfile) != 0) {
577,927✔
275
      dError("failed to unlock file");
×
276
    }
277

278
    (void)taosCloseFile(&pDnode->lockfile);
577,927✔
279
    pDnode->lockfile = NULL;
577,927✔
280
  }
281

282
  SDnodeData *pData = &pDnode->data;
578,211✔
283
  (void)taosThreadRwlockWrlock(&pData->lock);
578,211✔
284
  if (pData->oldDnodeEps != NULL) {
578,211✔
285
    if (dmWriteEps(pData) == 0) {
×
286
      dmRemoveDnodePairs(pData);
×
287
    }
288
    taosArrayDestroy(pData->oldDnodeEps);
×
289
    pData->oldDnodeEps = NULL;
×
290
  }
291
  if (pData->dnodeEps != NULL) {
578,211✔
292
    taosArrayDestroy(pData->dnodeEps);
578,211✔
293
    pData->dnodeEps = NULL;
578,211✔
294
  }
295
  if (pData->dnodeHash != NULL) {
578,211✔
296
    taosHashCleanup(pData->dnodeHash);
578,211✔
297
    pData->dnodeHash = NULL;
578,211✔
298
  }
299
  (void)taosThreadRwlockUnlock(&pData->lock);
578,211✔
300

301
  (void)taosThreadRwlockDestroy(&pData->lock);
578,211✔
302

303
  dDebug("begin to lock status info when thread exit");
578,211✔
304
  if (taosThreadMutexLock(&pData->statusInfolock) != 0) {
578,211✔
305
    dError("failed to lock status info lock");
×
306
    return;
×
307
  }
308
  if (tsVinfo.pVloads != NULL) {
578,211✔
309
    taosArrayDestroy(tsVinfo.pVloads);
154,721✔
310
    tsVinfo.pVloads = NULL;
154,721✔
311
  }
312
  if (taosThreadMutexUnlock(&pData->statusInfolock) != 0) {
578,211✔
313
    dError("failed to unlock status info lock");
×
314
    return;
×
315
  }
316
  if (taosThreadMutexDestroy(&pData->statusInfolock) != 0) {
578,211✔
317
    dError("failed to destroy status info lock");
×
318
  }
319
  memset(&pData->statusInfolock, 0, sizeof(pData->statusInfolock));
578,211✔
320

321
  (void)taosThreadMutexDestroy(&pDnode->mutex);
578,211✔
322
  memset(&pDnode->mutex, 0, sizeof(pDnode->mutex));
578,211✔
323
}
324

325
void dmSetStatus(SDnode *pDnode, EDndRunStatus status) {
1,136,684✔
326
  if (pDnode->status != status) {
1,136,684✔
327
    dDebug("dnode status set from %s to %s", dmStatStr(pDnode->status), dmStatStr(status));
1,136,684✔
328
    pDnode->status = status;
1,136,684✔
329
  }
330
}
1,136,684✔
331

332
SMgmtWrapper *dmAcquireWrapper(SDnode *pDnode, EDndNodeType ntype) {
421,264✔
333
  SMgmtWrapper *pWrapper = &pDnode->wrappers[ntype];
421,264✔
334
  SMgmtWrapper *pRetWrapper = pWrapper;
421,264✔
335

336
  (void)taosThreadRwlockRdlock(&pWrapper->lock);
421,264✔
337
  if (pWrapper->deployed) {
421,264✔
338
    int32_t refCount = atomic_add_fetch_32(&pWrapper->refCount, 1);
324,124✔
339
    // dTrace("node:%s, is acquired, ref:%d", pWrapper->name, refCount);
340
  } else {
341
    pRetWrapper = NULL;
97,140✔
342
  }
343
  (void)taosThreadRwlockUnlock(&pWrapper->lock);
421,264✔
344

345
  return pRetWrapper;
421,264✔
346
}
347

348
int32_t dmMarkWrapper(SMgmtWrapper *pWrapper) {
2,147,483,647✔
349
  int32_t code = 0;
2,147,483,647✔
350

351
  (void)taosThreadRwlockRdlock(&pWrapper->lock);
2,147,483,647✔
352
  if (pWrapper->deployed) {
2,147,483,647✔
353
    int32_t refCount = atomic_add_fetch_32(&pWrapper->refCount, 1);
2,147,483,647✔
354
    // dTrace("node:%s, is marked, ref:%d", pWrapper->name, refCount);
355
  } else {
356
    switch (pWrapper->ntype) {
57,175,061✔
357
      case MNODE:
16,489,811✔
358
        code = TSDB_CODE_MNODE_NOT_FOUND;
16,489,811✔
359
        break;
16,489,811✔
360
      case QNODE:
40,559,209✔
361
        code = TSDB_CODE_QNODE_NOT_FOUND;
40,559,209✔
362
        break;
40,559,209✔
363
      case SNODE:
82✔
364
        code = TSDB_CODE_SNODE_NOT_FOUND;
82✔
365
        break;
82✔
366
      case BNODE:
×
367
        code = TSDB_CODE_BNODE_NOT_FOUND;
×
368
        break;
×
369
      case VNODE:
125,765✔
370
        code = TSDB_CODE_VND_STOPPED;
125,765✔
371
        break;
125,765✔
372
      default:
×
373
        code = TSDB_CODE_APP_IS_STOPPING;
×
374
        break;
×
375
    }
376
  }
377
  (void)taosThreadRwlockUnlock(&pWrapper->lock);
2,147,483,647✔
378

379
  return code;
2,147,483,647✔
380
}
381

382
void dmReleaseWrapper(SMgmtWrapper *pWrapper) {
2,147,483,647✔
383
  if (pWrapper == NULL) return;
2,147,483,647✔
384

385
  (void)taosThreadRwlockRdlock(&pWrapper->lock);
2,147,483,647✔
386
  int32_t refCount = atomic_sub_fetch_32(&pWrapper->refCount, 1);
2,147,483,647✔
387
  (void)taosThreadRwlockUnlock(&pWrapper->lock);
2,147,483,647✔
388
  // dTrace("node:%s, is released, ref:%d", pWrapper->name, refCount);
389
}
390

391
static void dmGetServerStartupStatus(SDnode *pDnode, SServerStatusRsp *pStatus) {
×
392
  SDnodeMgmt *pMgmt = pDnode->wrappers[DNODE].pMgmt;
×
393
  pStatus->details[0] = 0;
×
394

395
  if (pDnode->status == DND_STAT_INIT) {
×
396
    pStatus->statusCode = TSDB_SRV_STATUS_NETWORK_OK;
×
397
    snprintf(pStatus->details, sizeof(pStatus->details), "%s: %s", pDnode->startup.name, pDnode->startup.desc);
×
398
  } else if (pDnode->status == DND_STAT_STOPPED) {
×
399
    pStatus->statusCode = TSDB_SRV_STATUS_EXTING;
×
400
  } else {
401
    pStatus->statusCode = TSDB_SRV_STATUS_SERVICE_OK;
×
402
  }
403
}
×
404

405
void dmProcessNetTestReq(SDnode *pDnode, SRpcMsg *pMsg) {
×
406
  dDebug("msg:%p, net test req will be processed", pMsg);
×
407

408
  SRpcMsg rsp = {.info = pMsg->info};
×
409
  rsp.pCont = rpcMallocCont(pMsg->contLen);
×
410
  if (rsp.pCont == NULL) {
×
411
    rsp.code = TSDB_CODE_OUT_OF_MEMORY;
×
412
  } else {
413
    rsp.contLen = pMsg->contLen;
×
414
  }
415

416
  if (rpcSendResponse(&rsp) != 0) {
×
417
    dError("failed to send response, msg:%p", &rsp);
×
418
  }
419
  rpcFreeCont(pMsg->pCont);
×
420
}
×
421

422
void dmProcessServerStartupStatus(SDnode *pDnode, SRpcMsg *pMsg) {
×
423
  dDebug("msg:%p, server startup status req will be processed", pMsg);
×
424

425
  SServerStatusRsp statusRsp = {0};
×
426
  dmGetServerStartupStatus(pDnode, &statusRsp);
×
427

428
  SRpcMsg rsp = {.info = pMsg->info};
×
429
  int32_t contLen = tSerializeSServerStatusRsp(NULL, 0, &statusRsp);
×
430
  if (contLen < 0) {
×
431
    rsp.code = TSDB_CODE_OUT_OF_MEMORY;
×
432
  } else {
433
    rsp.pCont = rpcMallocCont(contLen);
×
434
    if (rsp.pCont != NULL) {
×
435
      if (tSerializeSServerStatusRsp(rsp.pCont, contLen, &statusRsp) < 0) {
×
436
        rsp.code = TSDB_CODE_APP_ERROR;
×
437
      } else {
438
        rsp.contLen = contLen;
×
439
      }
440
    }
441
  }
442

443
  if (rpcSendResponse(&rsp) != 0) {
×
444
    dError("failed to send response, msg:%p", &rsp);
×
445
  }
446
  rpcFreeCont(pMsg->pCont);
×
447
}
×
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