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

taosdata / TDengine / #4935

22 Jan 2026 06:38AM UTC coverage: 66.708% (+0.02%) from 66.691%
#4935

push

travis-ci

web-flow
merge: from main to 3.0 #34371

121 of 271 new or added lines in 17 files covered. (44.65%)

9066 existing lines in 149 files now uncovered.

203884 of 305637 relevant lines covered (66.71%)

125811266.68 hits per line

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

72.79
/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) {
588,589✔
23
  int32_t code = 0;
588,589✔
24

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

34
  // Read encrypted flag (optional, defaults to false for backward compatibility)
35
  int32_t encrypted = 0;
588,589✔
36
  tjsonGetInt32ValueFromDouble(pJson, "encrypted", encrypted, code);
588,589✔
37
  pOption->encrypted = (encrypted != 0);
588,589✔
38
  // Reset code to 0 if encrypted field not found (backward compatibility)
39
  code = 0;
588,589✔
40

41
  SJson *replicas = tjsonGetObjectItem(pJson, "replicas");
588,589✔
42
  if (replicas == NULL) return 0;
588,589✔
43
  pOption->numOfTotalReplicas = tjsonGetArraySize(replicas);
27,266✔
44

45
  pOption->numOfReplicas = 0;
27,266✔
46

47
  for (int32_t i = 0; i < pOption->numOfTotalReplicas; ++i) {
95,166✔
48
    SJson *replica = tjsonGetArrayItem(replicas, i);
67,900✔
49
    if (replica == NULL) return TSDB_CODE_INVALID_JSON_FORMAT;
67,900✔
50

51
    SReplica *pReplica = pOption->replicas + i;
67,900✔
52
    tjsonGetInt32ValueFromDouble(replica, "id", pReplica->id, code);
67,900✔
53
    if (code < 0) return code;
67,900✔
54
    code = tjsonGetStringValue(replica, "fqdn", pReplica->fqdn);
67,900✔
55
    if (code < 0) return code;
67,900✔
56
    tjsonGetUInt16ValueFromDouble(replica, "port", pReplica->port, code);
67,900✔
57
    if (code < 0) return code;
67,900✔
58
    tjsonGetInt32ValueFromDouble(replica, "role", pOption->nodeRoles[i], code);
67,900✔
59
    if (code < 0) return code;
67,900✔
60
    if (pOption->nodeRoles[i] == TAOS_SYNC_ROLE_VOTER) {
67,900✔
61
      pOption->numOfReplicas++;
54,267✔
62
    }
63
  }
64

65
  for (int32_t i = 0; i < pOption->numOfTotalReplicas; ++i) {
95,166✔
66
  }
67

68
  return 0;
27,266✔
69
}
70

71
int32_t mmReadFile(const char *path, SMnodeOpt *pOption) {
1,329,146✔
72
  int32_t   code = -1;
1,329,146✔
73
  char     *pData = NULL;
1,329,146✔
74
  int32_t   dataLen = 0;
1,329,146✔
75
  SJson    *pJson = NULL;
1,329,146✔
76
  char      file[PATH_MAX] = {0};
1,329,146✔
77

78
  int32_t nBytes = snprintf(file, sizeof(file), "%s%smnode.json", path, TD_DIRSEP);
1,329,146✔
79
  if (nBytes <= 0 || nBytes >= sizeof(file)) {
1,329,146✔
80
    code = TSDB_CODE_OUT_OF_BUFFER;
×
81
    goto _OVER;
×
82
  }
83

84
  if (taosStatFile(file, NULL, NULL, NULL) < 0) {
1,329,146✔
85
    dInfo("mnode file:%s not exist, reason:%s", file, tstrerror(terrno));
740,557✔
86
    return 0;
740,557✔
87
  }
88

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

97
  pJson = tjsonParse(pData);
588,589✔
98
  if (pJson == NULL) {
588,589✔
99
    code = TSDB_CODE_INVALID_JSON_FORMAT;
×
100
    goto _OVER;
×
101
  }
102

103
  if ((code = mmDecodeOption(pJson, pOption)) < 0) {
588,589✔
104
    goto _OVER;
×
105
  }
106

107
  code = 0;
588,589✔
108
  dInfo("succeed to read mnode file %s, sdb.data encrypted flag:%d", file, pOption->encrypted);
588,589✔
109

110
_OVER:
587,191✔
111
  if (pData != NULL) taosMemoryFree(pData);
588,589✔
112
  if (pJson != NULL) cJSON_Delete(pJson);
588,589✔
113

114
  if (code != 0) {
588,589✔
115
    dError("failed to read mnode file:%s since %s", file, tstrerror(code));
×
116
  }
117
  return code;
588,589✔
118
}
119

120
static int32_t mmEncodeOption(SJson *pJson, const SMnodeOpt *pOption) {
643,745✔
121
  int32_t code = 0;
643,745✔
122
  if (pOption->deploy && pOption->numOfTotalReplicas > 0) {
643,745✔
123
    if ((code = tjsonAddDoubleToObject(pJson, "selfIndex", pOption->selfIndex)) < 0) return code;
27,266✔
124

125
    SJson *replicas = tjsonCreateArray();
27,266✔
126
    if (replicas == NULL) {
27,266✔
127
      return terrno;
×
128
    }
129
    if ((code = tjsonAddItemToObject(pJson, "replicas", replicas)) < 0) return code;
27,266✔
130

131
    for (int32_t i = 0; i < pOption->numOfTotalReplicas; ++i) {
95,166✔
132
      SJson *replica = tjsonCreateObject();
67,900✔
133
      if (replica == NULL) {
67,900✔
134
        return terrno;
×
135
      }
136

137
      const SReplica *pReplica = pOption->replicas + i;
67,900✔
138
      if ((code = tjsonAddDoubleToObject(replica, "id", pReplica->id)) < 0) return code;
67,900✔
139
      if ((code = tjsonAddStringToObject(replica, "fqdn", pReplica->fqdn)) < 0) return code;
67,900✔
140
      if ((code = tjsonAddDoubleToObject(replica, "port", pReplica->port)) < 0) return code;
67,900✔
141
      if ((code = tjsonAddDoubleToObject(replica, "role", pOption->nodeRoles[i])) < 0) return code;
67,900✔
142
      if ((code = tjsonAddItemToArray(replicas, replica)) < 0) return code;
67,900✔
143
    }
144
  }
145

146
  if ((code = tjsonAddDoubleToObject(pJson, "lastIndex", pOption->lastIndex)) < 0) return code;
643,745✔
147

148
  if ((code = tjsonAddDoubleToObject(pJson, "deployed", pOption->deploy)) < 0) return code;
643,745✔
149

150
  if ((code = tjsonAddDoubleToObject(pJson, "version", pOption->version)) < 0) return code;
643,745✔
151

152
  // Add encrypted flag
153
  if ((code = tjsonAddDoubleToObject(pJson, "encrypted", pOption->encrypted ? 1 : 0)) < 0) return code;
643,745✔
154

155
  return code;
643,745✔
156
}
157

158
int32_t mmWriteFile(const char *path, const SMnodeOpt *pOption) {
643,745✔
159
  int32_t   code = -1;
643,745✔
160
  char     *buffer = NULL;
643,745✔
161
  SJson    *pJson = NULL;
643,745✔
162
  char      realfile[PATH_MAX] = {0};
643,745✔
163

164
  int32_t nBytes = snprintf(realfile, sizeof(realfile), "%s%smnode.json", path, TD_DIRSEP);
643,745✔
165
  if (nBytes <= 0 || nBytes >= sizeof(realfile)) {
643,745✔
166
    code = TSDB_CODE_OUT_OF_BUFFER;
×
167
    goto _OVER;
×
168
  }
169

170
  // terrno = TSDB_CODE_OUT_OF_MEMORY;
171
  pJson = tjsonCreateObject();
643,745✔
172
  if (pJson == NULL) {
643,745✔
173
    code = terrno;
×
174
    goto _OVER;
×
175
  }
176

177
  TAOS_CHECK_GOTO(mmEncodeOption(pJson, pOption), NULL, _OVER);
643,745✔
178

179
  buffer = tjsonToString(pJson);
643,745✔
180
  if (buffer == NULL) {
643,745✔
181
    code = TSDB_CODE_INVALID_JSON_FORMAT;
×
182
    goto _OVER;
×
183
  }
184

185
  int32_t len = strlen(buffer);
643,745✔
186

187
  // mnode.json itself is not encrypted, just write as plain JSON
188
  // The encrypted flag indicates whether sdb.data is encrypted
189
  code = taosWriteCfgFile(realfile, buffer, len);
643,745✔
190
  if (code != 0) {
643,745✔
191
    goto _OVER;
×
192
  }
193

194
  dInfo("succeed to write mnode file:%s, deployed:%d, sdb.data encrypted:%d", realfile, pOption->deploy,
643,745✔
195
        pOption->encrypted);
196

197
_OVER:
641,127✔
198
  if (pJson != NULL) tjsonDelete(pJson);
643,745✔
199
  if (buffer != NULL) taosMemoryFree(buffer);
643,745✔
200

201
  if (code != 0) {
643,745✔
202
    dError("failed to write mnode file:%s since %s, deloyed:%d", realfile, tstrerror(code), pOption->deploy);
×
203
  }
204
  return code;
643,745✔
205
}
206

207
// Update and persist encrypted flag (exposed via mnode.h for sdb module)
NEW
208
int32_t mndSetEncryptedFlag(SSdb *pSdb) {
×
NEW
209
  int32_t   code = 0;
×
NEW
210
  SMnodeOpt option = {0};
×
211

NEW
212
  if (pSdb == NULL || pSdb->mnodePath[0] == '\0') {
×
NEW
213
    dError("invalid parameters, pSdb:%p", pSdb);
×
NEW
214
    return TSDB_CODE_INVALID_PARA;
×
215
  }
216

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

224
  // Update encrypted flag
NEW
225
  option.encrypted = true;
×
NEW
226
  pSdb->encrypted = true;
×
227

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

NEW
237
  dInfo("successfully set and persisted encrypted flag in mnode.json");
×
NEW
238
  return 0;
×
239
}
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