• 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

47.76
/source/dnode/mgmt/mgmt_mnode/src/mmFile.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 "mmInt.h"
18
#include "sdb.h"
19
#include "tencrypt.h"
20
#include "tjson.h"
21

22
static int32_t mmDecodeOption(SJson *pJson, SMnodeOpt *pOption) {
26✔
23
  int32_t code = 0;
26✔
24

25
  tjsonGetInt32ValueFromDouble(pJson, "deployed", pOption->deploy, code);
26✔
26
  if (code < 0) return code;
26✔
27
  tjsonGetInt32ValueFromDouble(pJson, "version", pOption->version, code);
26✔
28
  if (code < 0) return code;
26✔
29
  tjsonGetInt32ValueFromDouble(pJson, "selfIndex", pOption->selfIndex, code);
26✔
30
  if (code < 0) return code;
26✔
31
  tjsonGetInt32ValueFromDouble(pJson, "lastIndex", pOption->lastIndex, code);
26✔
32
  if (code < 0) return code;
26✔
33

34
  tjsonGetInt32ValueFromDouble(pJson, "encrypted", pOption->encrypted, code);
26✔
35
  if (code < 0) return code;
26✔
36

37
  SJson *replicas = tjsonGetObjectItem(pJson, "replicas");
26✔
38
  if (replicas == NULL) return 0;
26✔
39
  pOption->numOfTotalReplicas = tjsonGetArraySize(replicas);
×
40

41
  pOption->numOfReplicas = 0;
×
42

43
  for (int32_t i = 0; i < pOption->numOfTotalReplicas; ++i) {
×
44
    SJson *replica = tjsonGetArrayItem(replicas, i);
×
45
    if (replica == NULL) return TSDB_CODE_INVALID_JSON_FORMAT;
×
46

47
    SReplica *pReplica = pOption->replicas + i;
×
48
    tjsonGetInt32ValueFromDouble(replica, "id", pReplica->id, code);
×
49
    if (code < 0) return code;
×
50
    code = tjsonGetStringValue(replica, "fqdn", pReplica->fqdn);
×
51
    if (code < 0) return code;
×
52
    tjsonGetUInt16ValueFromDouble(replica, "port", pReplica->port, code);
×
53
    if (code < 0) return code;
×
54
    tjsonGetInt32ValueFromDouble(replica, "role", pOption->nodeRoles[i], code);
×
55
    if (code < 0) return code;
×
56
    if (pOption->nodeRoles[i] == TAOS_SYNC_ROLE_VOTER) {
×
57
      pOption->numOfReplicas++;
×
58
    }
59
  }
60

61
  for (int32_t i = 0; i < pOption->numOfTotalReplicas; ++i) {
×
62
  }
63

64
  return 0;
×
65
}
66

67
int32_t mmReadFile(const char *path, SMnodeOpt *pOption) {
58✔
68
  int32_t   code = -1;
58✔
69
  char     *pData = NULL;
58✔
70
  int32_t   dataLen = 0;
58✔
71
  SJson    *pJson = NULL;
58✔
72
  char      file[PATH_MAX] = {0};
58✔
73

74
  int32_t nBytes = snprintf(file, sizeof(file), "%s%smnode.json", path, TD_DIRSEP);
58✔
75
  if (nBytes <= 0 || nBytes >= sizeof(file)) {
58✔
76
    code = TSDB_CODE_OUT_OF_BUFFER;
×
77
    goto _OVER;
×
78
  }
79

80
  if (taosStatFile(file, NULL, NULL, NULL) < 0) {
58✔
81
    dInfo("mnode file:%s not exist, reason:%s", file, tstrerror(terrno));
32✔
82
    return 0;
32✔
83
  }
84

85
  // Read file with potential decryption
86
  // First try to read with taosReadCfgFile (supports encrypted files)
87
  code = taosReadCfgFile(file, &pData, &dataLen);
26✔
88
  if (code != 0) {
26✔
89
    dError("failed to read mnode file:%s since %s", file, tstrerror(code));
×
90
    goto _OVER;
×
91
  }
92

93
  pJson = tjsonParse(pData);
26✔
94
  if (pJson == NULL) {
26✔
95
    code = TSDB_CODE_INVALID_JSON_FORMAT;
×
96
    goto _OVER;
×
97
  }
98

99
  if ((code = mmDecodeOption(pJson, pOption)) < 0) {
26✔
100
    goto _OVER;
×
101
  }
102

103
  code = 0;
26✔
104
  dInfo("succeed to read mnode file %s, sdb.data encrypted flag:%d", file, pOption->encrypted);
26✔
105

106
_OVER:
×
107
  if (pData != NULL) taosMemoryFree(pData);
26✔
108
  if (pJson != NULL) cJSON_Delete(pJson);
26✔
109

110
  if (code != 0) {
26✔
111
    dError("failed to read mnode file:%s since %s", file, tstrerror(code));
×
112
  }
113
  return code;
26✔
114
}
115

116
static int32_t mmEncodeOption(SJson *pJson, const SMnodeOpt *pOption) {
46✔
117
  int32_t code = 0;
46✔
118
  if (pOption->deploy && pOption->numOfTotalReplicas > 0) {
46✔
119
    if ((code = tjsonAddDoubleToObject(pJson, "selfIndex", pOption->selfIndex)) < 0) return code;
×
120

121
    SJson *replicas = tjsonCreateArray();
×
122
    if (replicas == NULL) {
×
123
      return terrno;
×
124
    }
125
    if ((code = tjsonAddItemToObject(pJson, "replicas", replicas)) < 0) return code;
×
126

127
    for (int32_t i = 0; i < pOption->numOfTotalReplicas; ++i) {
×
128
      SJson *replica = tjsonCreateObject();
×
129
      if (replica == NULL) {
×
130
        return terrno;
×
131
      }
132

133
      const SReplica *pReplica = pOption->replicas + i;
×
134
      if ((code = tjsonAddDoubleToObject(replica, "id", pReplica->id)) < 0) return code;
×
135
      if ((code = tjsonAddStringToObject(replica, "fqdn", pReplica->fqdn)) < 0) return code;
×
136
      if ((code = tjsonAddDoubleToObject(replica, "port", pReplica->port)) < 0) return code;
×
137
      if ((code = tjsonAddDoubleToObject(replica, "role", pOption->nodeRoles[i])) < 0) return code;
×
138
      if ((code = tjsonAddItemToArray(replicas, replica)) < 0) return code;
×
139
    }
140
  }
141

142
  if ((code = tjsonAddDoubleToObject(pJson, "lastIndex", pOption->lastIndex)) < 0) return code;
46✔
143

144
  if ((code = tjsonAddDoubleToObject(pJson, "deployed", pOption->deploy)) < 0) return code;
46✔
145

146
  if ((code = tjsonAddDoubleToObject(pJson, "version", pOption->version)) < 0) return code;
46✔
147

148
  // Add encrypted flag
149
  if ((code = tjsonAddDoubleToObject(pJson, "encrypted", pOption->encrypted ? 1 : 0)) < 0) return code;
46✔
150

151
  return code;
46✔
152
}
153

154
int32_t mmWriteFile(const char *path, const SMnodeOpt *pOption) {
46✔
155
  int32_t   code = -1;
46✔
156
  char     *buffer = NULL;
46✔
157
  SJson    *pJson = NULL;
46✔
158
  char      realfile[PATH_MAX] = {0};
46✔
159

160
  int32_t nBytes = snprintf(realfile, sizeof(realfile), "%s%smnode.json", path, TD_DIRSEP);
46✔
161
  if (nBytes <= 0 || nBytes >= sizeof(realfile)) {
46✔
162
    code = TSDB_CODE_OUT_OF_BUFFER;
×
163
    goto _OVER;
×
164
  }
165

166
  // terrno = TSDB_CODE_OUT_OF_MEMORY;
167
  pJson = tjsonCreateObject();
46✔
168
  if (pJson == NULL) {
46✔
169
    code = terrno;
×
170
    goto _OVER;
×
171
  }
172

173
  TAOS_CHECK_GOTO(mmEncodeOption(pJson, pOption), NULL, _OVER);
46✔
174

175
  buffer = tjsonToString(pJson);
46✔
176
  if (buffer == NULL) {
46✔
177
    code = TSDB_CODE_INVALID_JSON_FORMAT;
×
178
    goto _OVER;
×
179
  }
180

181
  int32_t len = strlen(buffer);
46✔
182

183
  // mnode.json itself is not encrypted, just write as plain JSON
184
  // The encrypted flag indicates whether sdb.data is encrypted
185
  code = taosWriteCfgFile(realfile, buffer, len);
46✔
186
  if (code != 0) {
46✔
187
    goto _OVER;
×
188
  }
189

190
  dInfo("succeed to write mnode file:%s, deployed:%d, sdb.data encrypted:%d", realfile, pOption->deploy,
46✔
191
        pOption->encrypted);
192

193
_OVER:
×
194
  if (pJson != NULL) tjsonDelete(pJson);
46✔
195
  if (buffer != NULL) taosMemoryFree(buffer);
46✔
196

197
  if (code != 0) {
46✔
198
    dError("failed to write mnode file:%s since %s, deloyed:%d", realfile, tstrerror(code), pOption->deploy);
×
199
  }
200
  return code;
46✔
201
}
202

203
// Update and persist encrypted flag (exposed via mnode.h for sdb module)
204
int32_t mndSetEncryptedFlag(SSdb *pSdb) {
×
205
  int32_t   code = 0;
×
206
  SMnodeOpt option = {0};
×
207

208
  if (pSdb == NULL || pSdb->mnodePath[0] == '\0') {
×
209
    dError("invalid parameters, pSdb:%p", pSdb);
×
210
    return TSDB_CODE_INVALID_PARA;
×
211
  }
212

213
  // Read current mnode.json
214
  code = mmReadFile(pSdb->mnodePath, &option);
×
215
  if (code != 0) {
×
216
    dError("failed to read mnode.json for setting encrypted flag since %s", tstrerror(code));
×
217
    return code;
×
218
  }
219

220
  // Update encrypted flag
221
  option.encrypted = true;
×
222
  pSdb->encrypted = true;
×
223

224
  // Write back to mnode.json
225
  code = mmWriteFile(pSdb->mnodePath, &option);
×
226
  if (code != 0) {
×
227
    dError("failed to persist encrypted flag to mnode.json since %s", tstrerror(code));
×
228
    // Rollback in-memory flag
229
    pSdb->encrypted = false;
×
230
    return code;
×
231
  }
232

233
  dInfo("successfully set and persisted encrypted flag in mnode.json");
×
234
  return 0;
×
235
}
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