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

taosdata / TDengine / #4192

30 May 2025 03:55AM UTC coverage: 63.023% (-0.2%) from 63.267%
#4192

push

travis-ci

web-flow
fix:defined col bind in interlace mode (#31246)

157832 of 318864 branches covered (49.5%)

Branch coverage included in aggregate %.

1 of 3 new or added lines in 1 file covered. (33.33%)

2934 existing lines in 172 files now uncovered.

243367 of 317732 relevant lines covered (76.6%)

17346426.62 hits per line

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

59.51
/source/dnode/mnode/impl/src/mndVgroup.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 "audit.h"
18
#include "mndArbGroup.h"
19
#include "mndDb.h"
20
#include "mndDnode.h"
21
#include "mndMnode.h"
22
#include "mndPrivilege.h"
23
#include "mndShow.h"
24
#include "mndStb.h"
25
#include "mndStream.h"
26
#include "mndTopic.h"
27
#include "mndTrans.h"
28
#include "mndUser.h"
29
#include "mndVgroup.h"
30
#include "tmisce.h"
31

32
#define VGROUP_VER_NUMBER   1
33
#define VGROUP_RESERVE_SIZE 64
34

35
static int32_t mndVgroupActionInsert(SSdb *pSdb, SVgObj *pVgroup);
36
static int32_t mndVgroupActionDelete(SSdb *pSdb, SVgObj *pVgroup);
37
static int32_t mndVgroupActionUpdate(SSdb *pSdb, SVgObj *pOld, SVgObj *pNew);
38
static int32_t mndNewVgActionValidate(SMnode *pMnode, STrans *pTrans, SSdbRaw *pRaw);
39

40
static int32_t mndRetrieveVgroups(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows);
41
static void    mndCancelGetNextVgroup(SMnode *pMnode, void *pIter);
42
static int32_t mndRetrieveVnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows);
43
static void    mndCancelGetNextVnode(SMnode *pMnode, void *pIter);
44

45
static int32_t mndProcessRedistributeVgroupMsg(SRpcMsg *pReq);
46
static int32_t mndProcessSplitVgroupMsg(SRpcMsg *pReq);
47
static int32_t mndProcessBalanceVgroupMsg(SRpcMsg *pReq);
48
static int32_t mndProcessVgroupBalanceLeaderMsg(SRpcMsg *pReq);
49

50
int32_t mndInitVgroup(SMnode *pMnode) {
2,189✔
51
  SSdbTable table = {
2,189✔
52
      .sdbType = SDB_VGROUP,
53
      .keyType = SDB_KEY_INT32,
54
      .encodeFp = (SdbEncodeFp)mndVgroupActionEncode,
55
      .decodeFp = (SdbDecodeFp)mndVgroupActionDecode,
56
      .insertFp = (SdbInsertFp)mndVgroupActionInsert,
57
      .updateFp = (SdbUpdateFp)mndVgroupActionUpdate,
58
      .deleteFp = (SdbDeleteFp)mndVgroupActionDelete,
59
      .validateFp = (SdbValidateFp)mndNewVgActionValidate,
60
  };
61

62
  mndSetMsgHandle(pMnode, TDMT_DND_CREATE_VNODE_RSP, mndTransProcessRsp);
2,189✔
63
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_REPLICA_RSP, mndTransProcessRsp);
2,189✔
64
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_CONFIG_RSP, mndTransProcessRsp);
2,189✔
65
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_CONFIRM_RSP, mndTransProcessRsp);
2,189✔
66
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_HASHRANGE_RSP, mndTransProcessRsp);
2,189✔
67
  mndSetMsgHandle(pMnode, TDMT_DND_DROP_VNODE_RSP, mndTransProcessRsp);
2,189✔
68
  mndSetMsgHandle(pMnode, TDMT_VND_COMPACT_RSP, mndTransProcessRsp);
2,189✔
69
  mndSetMsgHandle(pMnode, TDMT_VND_DISABLE_WRITE_RSP, mndTransProcessRsp);
2,189✔
70
  mndSetMsgHandle(pMnode, TDMT_SYNC_FORCE_FOLLOWER_RSP, mndTransProcessRsp);
2,189✔
71
  mndSetMsgHandle(pMnode, TDMT_DND_ALTER_VNODE_TYPE_RSP, mndTransProcessRsp);
2,189✔
72
  mndSetMsgHandle(pMnode, TDMT_DND_CHECK_VNODE_LEARNER_CATCHUP_RSP, mndTransProcessRsp);
2,189✔
73
  mndSetMsgHandle(pMnode, TDMT_SYNC_CONFIG_CHANGE_RSP, mndTransProcessRsp);
2,189✔
74

75
  mndSetMsgHandle(pMnode, TDMT_MND_REDISTRIBUTE_VGROUP, mndProcessRedistributeVgroupMsg);
2,189✔
76
  mndSetMsgHandle(pMnode, TDMT_MND_SPLIT_VGROUP, mndProcessSplitVgroupMsg);
2,189✔
77
  // mndSetMsgHandle(pMnode, TDMT_MND_BALANCE_VGROUP, mndProcessVgroupBalanceLeaderMsg);
78
  mndSetMsgHandle(pMnode, TDMT_MND_BALANCE_VGROUP, mndProcessBalanceVgroupMsg);
2,189✔
79
  mndSetMsgHandle(pMnode, TDMT_MND_BALANCE_VGROUP_LEADER, mndProcessVgroupBalanceLeaderMsg);
2,189✔
80

81
  mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_VGROUP, mndRetrieveVgroups);
2,189✔
82
  mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_VGROUP, mndCancelGetNextVgroup);
2,189✔
83
  mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_VNODES, mndRetrieveVnodes);
2,189✔
84
  mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_VNODES, mndCancelGetNextVnode);
2,189✔
85

86
  return sdbSetTable(pMnode->pSdb, table);
2,189✔
87
}
88

89
void mndCleanupVgroup(SMnode *pMnode) {}
2,188✔
90

91
SSdbRaw *mndVgroupActionEncode(SVgObj *pVgroup) {
47,523✔
92
  int32_t code = 0;
47,523✔
93
  int32_t lino = 0;
47,523✔
94
  terrno = TSDB_CODE_OUT_OF_MEMORY;
47,523✔
95

96
  SSdbRaw *pRaw = sdbAllocRaw(SDB_VGROUP, VGROUP_VER_NUMBER, sizeof(SVgObj) + VGROUP_RESERVE_SIZE);
47,523✔
97
  if (pRaw == NULL) goto _OVER;
47,523!
98

99
  int32_t dataPos = 0;
47,523✔
100
  SDB_SET_INT32(pRaw, dataPos, pVgroup->vgId, _OVER)
47,523!
101
  SDB_SET_INT64(pRaw, dataPos, pVgroup->createdTime, _OVER)
47,523!
102
  SDB_SET_INT64(pRaw, dataPos, pVgroup->updateTime, _OVER)
47,523!
103
  SDB_SET_INT32(pRaw, dataPos, pVgroup->version, _OVER)
47,523!
104
  SDB_SET_INT32(pRaw, dataPos, pVgroup->hashBegin, _OVER)
47,523!
105
  SDB_SET_INT32(pRaw, dataPos, pVgroup->hashEnd, _OVER)
47,523!
106
  SDB_SET_BINARY(pRaw, dataPos, pVgroup->dbName, TSDB_DB_FNAME_LEN, _OVER)
47,523!
107
  SDB_SET_INT64(pRaw, dataPos, pVgroup->dbUid, _OVER)
47,523!
108
  SDB_SET_INT8(pRaw, dataPos, pVgroup->isTsma, _OVER)
47,523!
109
  SDB_SET_INT8(pRaw, dataPos, pVgroup->replica, _OVER)
47,523!
110
  for (int8_t i = 0; i < pVgroup->replica; ++i) {
100,456✔
111
    SVnodeGid *pVgid = &pVgroup->vnodeGid[i];
52,933✔
112
    SDB_SET_INT32(pRaw, dataPos, pVgid->dnodeId, _OVER)
52,933!
113
  }
114
  SDB_SET_INT32(pRaw, dataPos, pVgroup->syncConfChangeVer, _OVER)
47,523!
115
  SDB_SET_RESERVE(pRaw, dataPos, VGROUP_RESERVE_SIZE, _OVER)
47,523!
116
  SDB_SET_DATALEN(pRaw, dataPos, _OVER)
47,523!
117

118
  terrno = 0;
47,523✔
119

120
_OVER:
47,523✔
121
  if (terrno != 0) {
47,523!
122
    mError("vgId:%d, failed to encode to raw:%p since %s", pVgroup->vgId, pRaw, terrstr());
×
123
    sdbFreeRaw(pRaw);
×
124
    return NULL;
×
125
  }
126

127
  mTrace("vgId:%d, encode to raw:%p, row:%p", pVgroup->vgId, pRaw, pVgroup);
47,523✔
128
  return pRaw;
47,523✔
129
}
130

131
SSdbRow *mndVgroupActionDecode(SSdbRaw *pRaw) {
40,301✔
132
  int32_t code = 0;
40,301✔
133
  int32_t lino = 0;
40,301✔
134
  terrno = TSDB_CODE_OUT_OF_MEMORY;
40,301✔
135
  SSdbRow *pRow = NULL;
40,301✔
136
  SVgObj  *pVgroup = NULL;
40,301✔
137

138
  int8_t sver = 0;
40,301✔
139
  if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto _OVER;
40,301!
140

141
  if (sver < 1 || sver > VGROUP_VER_NUMBER) {
40,301!
142
    terrno = TSDB_CODE_SDB_INVALID_DATA_VER;
×
143
    goto _OVER;
×
144
  }
145

146
  pRow = sdbAllocRow(sizeof(SVgObj));
40,301✔
147
  if (pRow == NULL) goto _OVER;
40,301!
148

149
  pVgroup = sdbGetRowObj(pRow);
40,301✔
150
  if (pVgroup == NULL) goto _OVER;
40,301!
151

152
  int32_t dataPos = 0;
40,301✔
153
  SDB_GET_INT32(pRaw, dataPos, &pVgroup->vgId, _OVER)
40,301!
154
  SDB_GET_INT64(pRaw, dataPos, &pVgroup->createdTime, _OVER)
40,301!
155
  SDB_GET_INT64(pRaw, dataPos, &pVgroup->updateTime, _OVER)
40,301!
156
  SDB_GET_INT32(pRaw, dataPos, &pVgroup->version, _OVER)
40,301!
157
  SDB_GET_INT32(pRaw, dataPos, &pVgroup->hashBegin, _OVER)
40,301!
158
  SDB_GET_INT32(pRaw, dataPos, &pVgroup->hashEnd, _OVER)
40,301!
159
  SDB_GET_BINARY(pRaw, dataPos, pVgroup->dbName, TSDB_DB_FNAME_LEN, _OVER)
40,301!
160
  SDB_GET_INT64(pRaw, dataPos, &pVgroup->dbUid, _OVER)
40,301!
161
  SDB_GET_INT8(pRaw, dataPos, &pVgroup->isTsma, _OVER)
40,301!
162
  SDB_GET_INT8(pRaw, dataPos, &pVgroup->replica, _OVER)
40,301!
163
  for (int8_t i = 0; i < pVgroup->replica; ++i) {
86,942✔
164
    SVnodeGid *pVgid = &pVgroup->vnodeGid[i];
46,641✔
165
    SDB_GET_INT32(pRaw, dataPos, &pVgid->dnodeId, _OVER)
46,641!
166
    if (pVgroup->replica == 1) {
46,641✔
167
      pVgid->syncState = TAOS_SYNC_STATE_LEADER;
37,059✔
168
    }
169
  }
170
  if (dataPos + sizeof(int32_t) + VGROUP_RESERVE_SIZE <= pRaw->dataLen) {
40,301!
171
    SDB_GET_INT32(pRaw, dataPos, &pVgroup->syncConfChangeVer, _OVER)
40,301!
172
  }
173

174
  SDB_GET_RESERVE(pRaw, dataPos, VGROUP_RESERVE_SIZE, _OVER)
40,301!
175

176
  terrno = 0;
40,301✔
177

178
_OVER:
40,301✔
179
  if (terrno != 0) {
40,301!
180
    mError("vgId:%d, failed to decode from raw:%p since %s", pVgroup == NULL ? 0 : pVgroup->vgId, pRaw, terrstr());
×
181
    taosMemoryFreeClear(pRow);
×
182
    return NULL;
×
183
  }
184

185
  mTrace("vgId:%d, decode from raw:%p, row:%p", pVgroup->vgId, pRaw, pVgroup);
40,301✔
186
  return pRow;
40,301✔
187
}
188

189
static int32_t mndNewVgActionValidate(SMnode *pMnode, STrans *pTrans, SSdbRaw *pRaw) {
11,195✔
190
  SSdb    *pSdb = pMnode->pSdb;
11,195✔
191
  SSdbRow *pRow = NULL;
11,195✔
192
  SVgObj  *pVgroup = NULL;
11,195✔
193
  int      code = -1;
11,195✔
194

195
  pRow = mndVgroupActionDecode(pRaw);
11,195✔
196
  if (pRow == NULL) {
11,195!
197
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
198
    if (terrno != 0) code = terrno;
×
199
    goto _OVER;
×
200
  }
201
  pVgroup = sdbGetRowObj(pRow);
11,195✔
202
  if (pVgroup == NULL) {
11,195!
203
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
204
    if (terrno != 0) code = terrno;
×
205
    goto _OVER;
×
206
  }
207

208
  int32_t maxVgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP);
11,195✔
209
  if (maxVgId > pVgroup->vgId) {
11,195!
210
    mError("trans:%d, vgroup id %d already in use. maxVgId:%d", pTrans->id, pVgroup->vgId, maxVgId);
×
211
    goto _OVER;
×
212
  }
213

214
  code = 0;
11,195✔
215
_OVER:
11,195✔
216
  if (pVgroup) mndVgroupActionDelete(pSdb, pVgroup);
11,195!
217
  taosMemoryFreeClear(pRow);
11,195!
218
  TAOS_RETURN(code);
11,195✔
219
}
220

221
static int32_t mndVgroupActionInsert(SSdb *pSdb, SVgObj *pVgroup) {
12,271✔
222
  mTrace("vgId:%d, perform insert action, row:%p", pVgroup->vgId, pVgroup);
12,271✔
223
  return 0;
12,271✔
224
}
225

226
static int32_t mndVgroupActionDelete(SSdb *pSdb, SVgObj *pVgroup) {
40,301✔
227
  mTrace("vgId:%d, perform delete action, row:%p", pVgroup->vgId, pVgroup);
40,301✔
228
  return 0;
40,301✔
229
}
230

231
static int32_t mndVgroupActionUpdate(SSdb *pSdb, SVgObj *pOld, SVgObj *pNew) {
11,921✔
232
  mTrace("vgId:%d, perform update action, old row:%p new row:%p", pOld->vgId, pOld, pNew);
11,921✔
233
  pOld->updateTime = pNew->updateTime;
11,921✔
234
  pOld->version = pNew->version;
11,921✔
235
  pOld->hashBegin = pNew->hashBegin;
11,921✔
236
  pOld->hashEnd = pNew->hashEnd;
11,921✔
237
  pOld->replica = pNew->replica;
11,921✔
238
  pOld->isTsma = pNew->isTsma;
11,921✔
239
  for (int32_t i = 0; i < pNew->replica; ++i) {
26,427✔
240
    SVnodeGid *pNewGid = &pNew->vnodeGid[i];
14,506✔
241
    for (int32_t j = 0; j < pOld->replica; ++j) {
36,854✔
242
      SVnodeGid *pOldGid = &pOld->vnodeGid[j];
22,348✔
243
      if (pNewGid->dnodeId == pOldGid->dnodeId) {
22,348✔
244
        pNewGid->syncState = pOldGid->syncState;
14,064✔
245
        pNewGid->syncRestore = pOldGid->syncRestore;
14,064✔
246
        pNewGid->syncCanRead = pOldGid->syncCanRead;
14,064✔
247
        pNewGid->syncAppliedIndex = pOldGid->syncAppliedIndex;
14,064✔
248
        pNewGid->syncCommitIndex = pOldGid->syncCommitIndex;
14,064✔
249
        pNewGid->bufferSegmentUsed = pOldGid->bufferSegmentUsed;
14,064✔
250
        pNewGid->bufferSegmentSize = pOldGid->bufferSegmentSize;
14,064✔
251
      }
252
    }
253
  }
254
  pNew->numOfTables = pOld->numOfTables;
11,921✔
255
  pNew->numOfTimeSeries = pOld->numOfTimeSeries;
11,921✔
256
  pNew->totalStorage = pOld->totalStorage;
11,921✔
257
  pNew->compStorage = pOld->compStorage;
11,921✔
258
  pNew->pointsWritten = pOld->pointsWritten;
11,921✔
259
  pNew->compact = pOld->compact;
11,921✔
260
  memcpy(pOld->vnodeGid, pNew->vnodeGid, (TSDB_MAX_REPLICA + TSDB_MAX_LEARNER_REPLICA) * sizeof(SVnodeGid));
11,921✔
261
  pOld->syncConfChangeVer = pNew->syncConfChangeVer;
11,921✔
262
  return 0;
11,921✔
263
}
264

265
SVgObj *mndAcquireVgroup(SMnode *pMnode, int32_t vgId) {
737,198✔
266
  SSdb   *pSdb = pMnode->pSdb;
737,198✔
267
  SVgObj *pVgroup = sdbAcquire(pSdb, SDB_VGROUP, &vgId);
737,198✔
268
  if (pVgroup == NULL && terrno == TSDB_CODE_SDB_OBJ_NOT_THERE) {
737,200✔
269
    terrno = TSDB_CODE_MND_VGROUP_NOT_EXIST;
4,496✔
270
  }
271
  return pVgroup;
737,200✔
272
}
273

274
void mndReleaseVgroup(SMnode *pMnode, SVgObj *pVgroup) {
734,985✔
275
  SSdb *pSdb = pMnode->pSdb;
734,985✔
276
  sdbRelease(pSdb, pVgroup);
734,985✔
277
}
734,984✔
278

279
void *mndBuildCreateVnodeReq(SMnode *pMnode, SDnodeObj *pDnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen) {
11,456✔
280
  SCreateVnodeReq createReq = {0};
11,456✔
281
  createReq.vgId = pVgroup->vgId;
11,456✔
282
  memcpy(createReq.db, pDb->name, TSDB_DB_FNAME_LEN);
11,456✔
283
  createReq.dbUid = pDb->uid;
11,456✔
284
  createReq.vgVersion = pVgroup->version;
11,456✔
285
  createReq.numOfStables = pDb->cfg.numOfStables;
11,456✔
286
  createReq.buffer = pDb->cfg.buffer;
11,456✔
287
  createReq.pageSize = pDb->cfg.pageSize;
11,456✔
288
  createReq.pages = pDb->cfg.pages;
11,456✔
289
  createReq.cacheLastSize = pDb->cfg.cacheLastSize;
11,456✔
290
  createReq.daysPerFile = pDb->cfg.daysPerFile;
11,456✔
291
  createReq.daysToKeep0 = pDb->cfg.daysToKeep0;
11,456✔
292
  createReq.daysToKeep1 = pDb->cfg.daysToKeep1;
11,456✔
293
  createReq.daysToKeep2 = pDb->cfg.daysToKeep2;
11,456✔
294
  createReq.keepTimeOffset = pDb->cfg.keepTimeOffset;
11,456✔
295
  createReq.s3ChunkSize = pDb->cfg.s3ChunkSize;
11,456✔
296
  createReq.s3KeepLocal = pDb->cfg.s3KeepLocal;
11,456✔
297
  createReq.s3Compact = pDb->cfg.s3Compact;
11,456✔
298
  createReq.minRows = pDb->cfg.minRows;
11,456✔
299
  createReq.maxRows = pDb->cfg.maxRows;
11,456✔
300
  createReq.walFsyncPeriod = pDb->cfg.walFsyncPeriod;
11,456✔
301
  createReq.walLevel = pDb->cfg.walLevel;
11,456✔
302
  createReq.precision = pDb->cfg.precision;
11,456✔
303
  createReq.compression = pDb->cfg.compression;
11,456✔
304
  createReq.strict = pDb->cfg.strict;
11,456✔
305
  createReq.cacheLast = pDb->cfg.cacheLast;
11,456✔
306
  createReq.replica = 0;
11,456✔
307
  createReq.learnerReplica = 0;
11,456✔
308
  createReq.selfIndex = -1;
11,456✔
309
  createReq.learnerSelfIndex = -1;
11,456✔
310
  createReq.hashBegin = pVgroup->hashBegin;
11,456✔
311
  createReq.hashEnd = pVgroup->hashEnd;
11,456✔
312
  createReq.hashMethod = pDb->cfg.hashMethod;
11,456✔
313
  createReq.numOfRetensions = pDb->cfg.numOfRetensions;
11,456✔
314
  createReq.pRetensions = pDb->cfg.pRetensions;
11,456✔
315
  createReq.isTsma = pVgroup->isTsma;
11,456✔
316
  createReq.pTsma = pVgroup->pTsma;
11,456✔
317
  createReq.walRetentionPeriod = pDb->cfg.walRetentionPeriod;
11,456✔
318
  createReq.walRetentionSize = pDb->cfg.walRetentionSize;
11,456✔
319
  createReq.walRollPeriod = pDb->cfg.walRollPeriod;
11,456✔
320
  createReq.walSegmentSize = pDb->cfg.walSegmentSize;
11,456✔
321
  createReq.sstTrigger = pDb->cfg.sstTrigger;
11,456✔
322
  createReq.hashPrefix = pDb->cfg.hashPrefix;
11,456✔
323
  createReq.hashSuffix = pDb->cfg.hashSuffix;
11,456✔
324
  createReq.tsdbPageSize = pDb->cfg.tsdbPageSize;
11,456✔
325
  createReq.changeVersion = ++(pVgroup->syncConfChangeVer);
11,456✔
326
  createReq.encryptAlgorithm = pDb->cfg.encryptAlgorithm;
11,456✔
327
  int32_t code = 0;
11,456✔
328

329
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
25,837✔
330
    SReplica *pReplica = NULL;
14,381✔
331

332
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
14,381✔
333
      pReplica = &createReq.replicas[createReq.replica];
14,170✔
334
    } else {
335
      pReplica = &createReq.learnerReplicas[createReq.learnerReplica];
211✔
336
    }
337

338
    SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
14,381✔
339
    SDnodeObj *pVgidDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
14,381✔
340
    if (pVgidDnode == NULL) {
14,381!
341
      return NULL;
×
342
    }
343

344
    pReplica->id = pVgidDnode->id;
14,381✔
345
    pReplica->port = pVgidDnode->port;
14,381✔
346
    memcpy(pReplica->fqdn, pVgidDnode->fqdn, TSDB_FQDN_LEN);
14,381✔
347
    mndReleaseDnode(pMnode, pVgidDnode);
14,381✔
348

349
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
14,381✔
350
      if (pDnode->id == pVgid->dnodeId) {
14,170✔
351
        createReq.selfIndex = createReq.replica;
11,245✔
352
      }
353
    } else {
354
      if (pDnode->id == pVgid->dnodeId) {
211!
355
        createReq.learnerSelfIndex = createReq.learnerReplica;
211✔
356
      }
357
    }
358

359
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
14,381✔
360
      createReq.replica++;
14,170✔
361
    } else {
362
      createReq.learnerReplica++;
211✔
363
    }
364
  }
365

366
  if (createReq.selfIndex == -1 && createReq.learnerSelfIndex == -1) {
11,456!
367
    terrno = TSDB_CODE_APP_ERROR;
×
368
    return NULL;
×
369
  }
370

371
  createReq.changeVersion = pVgroup->syncConfChangeVer;
11,456✔
372

373
  mInfo(
11,456!
374
      "vgId:%d, build create vnode req, replica:%d selfIndex:%d learnerReplica:%d learnerSelfIndex:%d strict:%d "
375
      "changeVersion:%d",
376
      createReq.vgId, createReq.replica, createReq.selfIndex, createReq.learnerReplica, createReq.learnerSelfIndex,
377
      createReq.strict, createReq.changeVersion);
378
  for (int32_t i = 0; i < createReq.replica; ++i) {
25,626✔
379
    mInfo("vgId:%d, replica:%d ep:%s:%u", createReq.vgId, i, createReq.replicas[i].fqdn, createReq.replicas[i].port);
14,170!
380
  }
381
  for (int32_t i = 0; i < createReq.learnerReplica; ++i) {
11,667✔
382
    mInfo("vgId:%d, replica:%d ep:%s:%u", createReq.vgId, i, createReq.learnerReplicas[i].fqdn,
211!
383
          createReq.learnerReplicas[i].port);
384
  }
385

386
  int32_t contLen = tSerializeSCreateVnodeReq(NULL, 0, &createReq);
11,456✔
387
  if (contLen < 0) {
11,456!
388
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
389
    return NULL;
×
390
  }
391

392
  void *pReq = taosMemoryMalloc(contLen);
11,456!
393
  if (pReq == NULL) {
11,456!
394
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
395
    return NULL;
×
396
  }
397

398
  code = tSerializeSCreateVnodeReq(pReq, contLen, &createReq);
11,456✔
399
  if (code < 0) {
11,456!
400
    terrno = TSDB_CODE_APP_ERROR;
×
401
    taosMemoryFree(pReq);
×
402
    mError("vgId:%d, failed to serialize create vnode req,since %s", createReq.vgId, terrstr());
×
403
    return NULL;
×
404
  }
405
  *pContLen = contLen;
11,456✔
406
  return pReq;
11,456✔
407
}
408

409
static void *mndBuildAlterVnodeConfigReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen) {
612✔
410
  SAlterVnodeConfigReq alterReq = {0};
612✔
411
  alterReq.vgVersion = pVgroup->version;
612✔
412
  alterReq.buffer = pDb->cfg.buffer;
612✔
413
  alterReq.pageSize = pDb->cfg.pageSize;
612✔
414
  alterReq.pages = pDb->cfg.pages;
612✔
415
  alterReq.cacheLastSize = pDb->cfg.cacheLastSize;
612✔
416
  alterReq.daysPerFile = pDb->cfg.daysPerFile;
612✔
417
  alterReq.daysToKeep0 = pDb->cfg.daysToKeep0;
612✔
418
  alterReq.daysToKeep1 = pDb->cfg.daysToKeep1;
612✔
419
  alterReq.daysToKeep2 = pDb->cfg.daysToKeep2;
612✔
420
  alterReq.keepTimeOffset = pDb->cfg.keepTimeOffset;
612✔
421
  alterReq.walFsyncPeriod = pDb->cfg.walFsyncPeriod;
612✔
422
  alterReq.walLevel = pDb->cfg.walLevel;
612✔
423
  alterReq.strict = pDb->cfg.strict;
612✔
424
  alterReq.cacheLast = pDb->cfg.cacheLast;
612✔
425
  alterReq.sttTrigger = pDb->cfg.sstTrigger;
612✔
426
  alterReq.minRows = pDb->cfg.minRows;
612✔
427
  alterReq.walRetentionPeriod = pDb->cfg.walRetentionPeriod;
612✔
428
  alterReq.walRetentionSize = pDb->cfg.walRetentionSize;
612✔
429
  alterReq.s3KeepLocal = pDb->cfg.s3KeepLocal;
612✔
430
  alterReq.s3Compact = pDb->cfg.s3Compact;
612✔
431

432
  mInfo("vgId:%d, build alter vnode config req", pVgroup->vgId);
612!
433
  int32_t contLen = tSerializeSAlterVnodeConfigReq(NULL, 0, &alterReq);
612✔
434
  if (contLen < 0) {
612!
435
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
436
    return NULL;
×
437
  }
438
  contLen += sizeof(SMsgHead);
612✔
439

440
  void *pReq = taosMemoryMalloc(contLen);
612!
441
  if (pReq == NULL) {
612!
442
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
443
    return NULL;
×
444
  }
445

446
  SMsgHead *pHead = pReq;
612✔
447
  pHead->contLen = htonl(contLen);
612✔
448
  pHead->vgId = htonl(pVgroup->vgId);
612✔
449

450
  if (tSerializeSAlterVnodeConfigReq((char *)pReq + sizeof(SMsgHead), contLen, &alterReq) < 0) {
612!
451
    taosMemoryFree(pReq);
×
452
    mError("vgId:%d, failed to serialize alter vnode config req,since %s", pVgroup->vgId, terrstr());
×
453
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
454
    return NULL;
×
455
  }
456
  *pContLen = contLen;
612✔
457
  return pReq;
612✔
458
}
459

460
static void *mndBuildAlterVnodeReplicaReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId,
1,464✔
461
                                          int32_t *pContLen) {
462
  SAlterVnodeReplicaReq alterReq = {
1,464✔
463
      .vgId = pVgroup->vgId,
1,464✔
464
      .strict = pDb->cfg.strict,
1,464✔
465
      .replica = 0,
466
      .learnerReplica = 0,
467
      .selfIndex = -1,
468
      .learnerSelfIndex = -1,
469
      .changeVersion = ++(pVgroup->syncConfChangeVer),
1,464✔
470
  };
471

472
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
5,817✔
473
    SReplica *pReplica = NULL;
4,353✔
474

475
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
4,353✔
476
      pReplica = &alterReq.replicas[alterReq.replica];
4,008✔
477
      alterReq.replica++;
4,008✔
478
    } else {
479
      pReplica = &alterReq.learnerReplicas[alterReq.learnerReplica];
345✔
480
      alterReq.learnerReplica++;
345✔
481
    }
482

483
    SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
4,353✔
484
    SDnodeObj *pVgidDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
4,353✔
485
    if (pVgidDnode == NULL) return NULL;
4,353!
486

487
    pReplica->id = pVgidDnode->id;
4,353✔
488
    pReplica->port = pVgidDnode->port;
4,353✔
489
    memcpy(pReplica->fqdn, pVgidDnode->fqdn, TSDB_FQDN_LEN);
4,353✔
490
    mndReleaseDnode(pMnode, pVgidDnode);
4,353✔
491

492
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
4,353✔
493
      if (dnodeId == pVgid->dnodeId) {
4,008✔
494
        alterReq.selfIndex = v;
1,464✔
495
      }
496
    } else {
497
      if (dnodeId == pVgid->dnodeId) {
345!
498
        alterReq.learnerSelfIndex = v;
×
499
      }
500
    }
501
  }
502

503
  mInfo(
1,464!
504
      "vgId:%d, build alter vnode req, replica:%d selfIndex:%d learnerReplica:%d learnerSelfIndex:%d strict:%d "
505
      "changeVersion:%d",
506
      alterReq.vgId, alterReq.replica, alterReq.selfIndex, alterReq.learnerReplica, alterReq.learnerSelfIndex,
507
      alterReq.strict, alterReq.changeVersion);
508
  for (int32_t i = 0; i < alterReq.replica; ++i) {
5,472✔
509
    mInfo("vgId:%d, replica:%d ep:%s:%u", alterReq.vgId, i, alterReq.replicas[i].fqdn, alterReq.replicas[i].port);
4,008!
510
  }
511
  for (int32_t i = 0; i < alterReq.learnerReplica; ++i) {
1,809✔
512
    mInfo("vgId:%d, learnerReplica:%d ep:%s:%u", alterReq.vgId, i, alterReq.learnerReplicas[i].fqdn,
345!
513
          alterReq.learnerReplicas[i].port);
514
  }
515

516
  if (alterReq.selfIndex == -1 && alterReq.learnerSelfIndex == -1) {
1,464!
517
    terrno = TSDB_CODE_APP_ERROR;
×
518
    return NULL;
×
519
  }
520

521
  int32_t contLen = tSerializeSAlterVnodeReplicaReq(NULL, 0, &alterReq);
1,464✔
522
  if (contLen < 0) {
1,464!
523
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
524
    return NULL;
×
525
  }
526

527
  void *pReq = taosMemoryMalloc(contLen);
1,464!
528
  if (pReq == NULL) {
1,464!
529
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
530
    return NULL;
×
531
  }
532

533
  if (tSerializeSAlterVnodeReplicaReq(pReq, contLen, &alterReq) < 0) {
1,464!
534
    mError("vgId:%d, failed to serialize alter vnode req,since %s", alterReq.vgId, terrstr());
×
535
    taosMemoryFree(pReq);
×
536
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
537
    return NULL;
×
538
  }
539
  *pContLen = contLen;
1,464✔
540
  return pReq;
1,464✔
541
}
542

543
static void *mndBuildCheckLearnCatchupReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId,
×
544
                                          int32_t *pContLen) {
545
  SCheckLearnCatchupReq req = {
×
546
      .vgId = pVgroup->vgId,
×
547
      .strict = pDb->cfg.strict,
×
548
      .replica = 0,
549
      .learnerReplica = 0,
550
      .selfIndex = -1,
551
      .learnerSelfIndex = -1,
552
  };
553

554
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
×
555
    SReplica *pReplica = NULL;
×
556

557
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
×
558
      pReplica = &req.replicas[req.replica];
×
559
      req.replica++;
×
560
    } else {
561
      pReplica = &req.learnerReplicas[req.learnerReplica];
×
562
      req.learnerReplica++;
×
563
    }
564

565
    SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
×
566
    SDnodeObj *pVgidDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
×
567
    if (pVgidDnode == NULL) return NULL;
×
568

569
    pReplica->id = pVgidDnode->id;
×
570
    pReplica->port = pVgidDnode->port;
×
571
    memcpy(pReplica->fqdn, pVgidDnode->fqdn, TSDB_FQDN_LEN);
×
572
    mndReleaseDnode(pMnode, pVgidDnode);
×
573

574
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
×
575
      if (dnodeId == pVgid->dnodeId) {
×
576
        req.selfIndex = v;
×
577
      }
578
    } else {
579
      if (dnodeId == pVgid->dnodeId) {
×
580
        req.learnerSelfIndex = v;
×
581
      }
582
    }
583
  }
584

585
  mInfo("vgId:%d, build alter vnode req, replica:%d selfIndex:%d learnerReplica:%d learnerSelfIndex:%d strict:%d",
×
586
        req.vgId, req.replica, req.selfIndex, req.learnerReplica, req.learnerSelfIndex, req.strict);
587
  for (int32_t i = 0; i < req.replica; ++i) {
×
588
    mInfo("vgId:%d, replica:%d ep:%s:%u", req.vgId, i, req.replicas[i].fqdn, req.replicas[i].port);
×
589
  }
590
  for (int32_t i = 0; i < req.learnerReplica; ++i) {
×
591
    mInfo("vgId:%d, learnerReplica:%d ep:%s:%u", req.vgId, i, req.learnerReplicas[i].fqdn, req.learnerReplicas[i].port);
×
592
  }
593

594
  if (req.selfIndex == -1 && req.learnerSelfIndex == -1) {
×
595
    terrno = TSDB_CODE_APP_ERROR;
×
596
    return NULL;
×
597
  }
598

599
  int32_t contLen = tSerializeSAlterVnodeReplicaReq(NULL, 0, &req);
×
600
  if (contLen < 0) {
×
601
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
602
    return NULL;
×
603
  }
604

605
  void *pReq = taosMemoryMalloc(contLen);
×
606
  if (pReq == NULL) {
×
607
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
608
    return NULL;
×
609
  }
610

611
  if (tSerializeSAlterVnodeReplicaReq(pReq, contLen, &req) < 0) {
×
612
    mError("vgId:%d, failed to serialize alter vnode req,since %s", req.vgId, terrstr());
×
613
    taosMemoryFree(pReq);
×
614
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
615
    return NULL;
×
616
  }
617
  *pContLen = contLen;
×
618
  return pReq;
×
619
}
620

621
static void *mndBuildDisableVnodeWriteReq(SMnode *pMnode, SDbObj *pDb, int32_t vgId, int32_t *pContLen) {
64✔
622
  SDisableVnodeWriteReq disableReq = {
64✔
623
      .vgId = vgId,
624
      .disable = 1,
625
  };
626

627
  mInfo("vgId:%d, build disable vnode write req", vgId);
64!
628
  int32_t contLen = tSerializeSDisableVnodeWriteReq(NULL, 0, &disableReq);
64✔
629
  if (contLen < 0) {
64!
630
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
631
    return NULL;
×
632
  }
633

634
  void *pReq = taosMemoryMalloc(contLen);
64!
635
  if (pReq == NULL) {
64!
636
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
637
    return NULL;
×
638
  }
639

640
  if (tSerializeSDisableVnodeWriteReq(pReq, contLen, &disableReq) < 0) {
64!
641
    mError("vgId:%d, failed to serialize disable vnode write req,since %s", vgId, terrstr());
×
642
    taosMemoryFree(pReq);
×
643
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
644
    return NULL;
×
645
  }
646
  *pContLen = contLen;
64✔
647
  return pReq;
64✔
648
}
649

650
static void *mndBuildAlterVnodeHashRangeReq(SMnode *pMnode, int32_t srcVgId, SVgObj *pVgroup, int32_t *pContLen) {
64✔
651
  SAlterVnodeHashRangeReq alterReq = {
64✔
652
      .srcVgId = srcVgId,
653
      .dstVgId = pVgroup->vgId,
64✔
654
      .hashBegin = pVgroup->hashBegin,
64✔
655
      .hashEnd = pVgroup->hashEnd,
64✔
656
      .changeVersion = ++(pVgroup->syncConfChangeVer),
64✔
657
  };
658

659
  mInfo("vgId:%d, build alter vnode hashrange req, dstVgId:%d, hashrange:[%u, %u]", srcVgId, pVgroup->vgId,
64!
660
        pVgroup->hashBegin, pVgroup->hashEnd);
661
  int32_t contLen = tSerializeSAlterVnodeHashRangeReq(NULL, 0, &alterReq);
64✔
662
  if (contLen < 0) {
64!
663
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
664
    return NULL;
×
665
  }
666

667
  void *pReq = taosMemoryMalloc(contLen);
64!
668
  if (pReq == NULL) {
64!
669
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
670
    return NULL;
×
671
  }
672

673
  if (tSerializeSAlterVnodeHashRangeReq(pReq, contLen, &alterReq) < 0) {
64!
674
    mError("vgId:%d, failed to serialize alter vnode hashrange req,since %s", srcVgId, terrstr());
×
675
    taosMemoryFree(pReq);
×
676
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
677
    return NULL;
×
678
  }
679
  *pContLen = contLen;
64✔
680
  return pReq;
64✔
681
}
682

683
void *mndBuildDropVnodeReq(SMnode *pMnode, SDnodeObj *pDnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen) {
16,216✔
684
  SDropVnodeReq dropReq = {0};
16,216✔
685
  dropReq.dnodeId = pDnode->id;
16,216✔
686
  dropReq.vgId = pVgroup->vgId;
16,216✔
687
  memcpy(dropReq.db, pDb->name, TSDB_DB_FNAME_LEN);
16,216✔
688
  dropReq.dbUid = pDb->uid;
16,216✔
689

690
  mInfo("vgId:%d, build drop vnode req", dropReq.vgId);
16,216!
691
  int32_t contLen = tSerializeSDropVnodeReq(NULL, 0, &dropReq);
16,216✔
692
  if (contLen < 0) {
16,216!
693
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
694
    return NULL;
×
695
  }
696

697
  void *pReq = taosMemoryMalloc(contLen);
16,216!
698
  if (pReq == NULL) {
16,216!
699
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
700
    return NULL;
×
701
  }
702

703
  if (tSerializeSDropVnodeReq(pReq, contLen, &dropReq) < 0) {
16,216!
704
    mError("vgId:%d, failed to serialize drop vnode req,since %s", dropReq.vgId, terrstr());
×
705
    taosMemoryFree(pReq);
×
706
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
707
    return NULL;
×
708
  }
709
  *pContLen = contLen;
16,216✔
710
  return pReq;
16,216✔
711
}
712

713
static bool mndResetDnodesArrayFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
7,028✔
714
  SDnodeObj *pDnode = pObj;
7,028✔
715
  pDnode->numOfVnodes = 0;
7,028✔
716
  pDnode->numOfOtherNodes = 0;
7,028✔
717
  return true;
7,028✔
718
}
719

720
static bool mndBuildDnodesArrayFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
7,022✔
721
  SDnodeObj *pDnode = pObj;
7,022✔
722
  SArray    *pArray = p1;
7,022✔
723
  int32_t    exceptDnodeId = *(int32_t *)p2;
7,022✔
724
  SArray    *dnodeList = p3;
7,022✔
725

726
  if (exceptDnodeId == pDnode->id) {
7,022✔
727
    return true;
16✔
728
  }
729

730
  if (dnodeList != NULL) {
7,006✔
731
    int32_t dnodeListSize = taosArrayGetSize(dnodeList);
101✔
732
    if (dnodeListSize > 0) {
101!
733
      bool inDnodeList = false;
101✔
734
      for (int32_t index = 0; index < dnodeListSize; ++index) {
328✔
735
        int32_t dnodeId = *(int32_t *)taosArrayGet(dnodeList, index);
227✔
736
        if (pDnode->id == dnodeId) {
227✔
737
          inDnodeList = true;
47✔
738
        }
739
      }
740
      if (!inDnodeList) {
101✔
741
        return true;
54✔
742
      }
743
    } else {
744
      return true;  // TS-6191
×
745
    }
746
  }
747

748
  int64_t curMs = taosGetTimestampMs();
6,952✔
749
  bool    online = mndIsDnodeOnline(pDnode, curMs);
6,952✔
750
  bool    isMnode = mndIsMnode(pMnode, pDnode->id);
6,952✔
751
  pDnode->numOfVnodes = mndGetVnodesNum(pMnode, pDnode->id);
6,952✔
752
  pDnode->memUsed = mndGetVnodesMemory(pMnode, pDnode->id);
6,952✔
753

754
  mInfo("dnode:%d, vnodes:%d supportVnodes:%d isMnode:%d online:%d memory avail:%" PRId64 " used:%" PRId64, pDnode->id,
6,952!
755
        pDnode->numOfVnodes, pDnode->numOfSupportVnodes, isMnode, online, pDnode->memAvail, pDnode->memUsed);
756

757
  if (isMnode) {
6,952✔
758
    pDnode->numOfOtherNodes++;
5,824✔
759
  }
760

761
  if (online && pDnode->numOfSupportVnodes > 0) {
6,952✔
762
    if (taosArrayPush(pArray, pDnode) == NULL) return false;
6,318!
763
  }
764
  return true;
6,952✔
765
}
766

767
static bool isDnodeInList(SArray *dnodeList, int32_t dnodeId) {
2✔
768
  int32_t dnodeListSize = taosArrayGetSize(dnodeList);
2✔
769
  for (int32_t i = 0; i < dnodeListSize; ++i) {
5!
770
    int32_t id = *(int32_t *)TARRAY_GET_ELEM(dnodeList, i);
5✔
771
    if (id == dnodeId) {
5✔
772
      return true;
2✔
773
    }
774
  }
775
  return false;
×
776
}
777

778
#ifdef TD_ENTERPRISE
779
static float mndGetDnodeScore1(SDnodeObj *pDnode, int32_t additionDnodes, float ratio) {
12✔
780
  float totalDnodes = pDnode->numOfVnodes + (float)pDnode->numOfOtherNodes * ratio + additionDnodes;
12✔
781
  float result = totalDnodes / pDnode->numOfSupportVnodes;
12✔
782
  return pDnode->numOfVnodes > 0 ? -result : result;
12✔
783
}
784

785
static int32_t mndCompareDnodeVnodes1(SDnodeObj *pDnode1, SDnodeObj *pDnode2) {
6✔
786
  float d1Score = mndGetDnodeScore1(pDnode1, 0, 0.9);
6✔
787
  float d2Score = mndGetDnodeScore1(pDnode2, 0, 0.9);
6✔
788
  if (d1Score == d2Score) {
6✔
789
    if (pDnode1->id == pDnode2->id) {
2!
790
      return 0;
×
791
    }
792
    return pDnode1->id > pDnode2->id ? 1 : -1;
2!
793
  }
794
  return d1Score > d2Score ? 1 : -1;
4!
795
}
796

797
static bool mndBuildDnodesListFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
6✔
798
  SDnodeObj *pDnode = pObj;
6✔
799
  SArray    *pArray = p1;
6✔
800

801
  bool isMnode = mndIsMnode(pMnode, pDnode->id);
6✔
802
  pDnode->numOfVnodes = mndGetVnodesNum(pMnode, pDnode->id);
6✔
803

804
  if (isMnode) {
6✔
805
    pDnode->numOfOtherNodes++;
2✔
806
  }
807

808
  if (pDnode->numOfSupportVnodes > 0) {
6!
809
    if (taosArrayPush(pArray, pDnode) == NULL) return false;
6!
810
  }
811
  return true;
6✔
812
}
813

814
// TS-6191
815
static int32_t mndBuildNodesCheckDualReplica(SMnode *pMnode, int32_t nDnodes, SArray *dnodeList, SArray **ppDnodeList) {
5,534✔
816
  int32_t code = 0;
5,534✔
817
  if (!grantCheckDualReplicaDnodes(pMnode)) {
5,534✔
818
    TAOS_RETURN(code);
5,532✔
819
  }
820
  SSdb   *pSdb = pMnode->pSdb;
2✔
821
  SArray *pArray = taosArrayInit(nDnodes, sizeof(SDnodeObj));
2✔
822
  if (pArray == NULL) {
2!
823
    TAOS_RETURN(code = terrno);
×
824
  }
825
  *ppDnodeList = pArray;
2✔
826

827
  sdbTraverse(pSdb, SDB_DNODE, mndResetDnodesArrayFp, NULL, NULL, NULL);
2✔
828
  sdbTraverse(pSdb, SDB_DNODE, mndBuildDnodesListFp, pArray, NULL, NULL);
2✔
829

830
  int32_t arrSize = taosArrayGetSize(pArray);
2✔
831
  if (arrSize <= 0) {
2!
832
    TAOS_RETURN(code);
×
833
  }
834
  if (arrSize > 1) taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes1);
2!
835

836
  int32_t dnodeListSize = taosArrayGetSize(dnodeList);
2✔
837
  if (dnodeListSize <= 0) {
2✔
838
    if (arrSize > 2) taosArrayRemoveBatch(pArray, 2, arrSize - 2, NULL);
1!
839
  } else {
840
    int32_t nDnodesWithVnodes = 0;
1✔
841
    for (int32_t i = 0; i < arrSize; ++i) {
3!
842
      SDnodeObj *pDnode = TARRAY_GET_ELEM(pArray, i);
3✔
843
      if (pDnode->numOfVnodes <= 0) {
3✔
844
        break;
1✔
845
      }
846
      ++nDnodesWithVnodes;
2✔
847
    }
848
    int32_t dnodeId = -1;
1✔
849
    if (nDnodesWithVnodes == 1) {
1!
850
      dnodeId = ((SDnodeObj *)TARRAY_GET_ELEM(pArray, 0))->id;
×
851
    } else if (nDnodesWithVnodes >= 2) {
1!
852
      // must select the dnodes from the 1st 2 dnodes
853
      taosArrayRemoveBatch(pArray, 2, arrSize - 2, NULL);
1✔
854
    }
855
    for (int32_t i = 0; i < TARRAY_SIZE(pArray);) {
3✔
856
      SDnodeObj *pDnode = taosArrayGet(pArray, i);
2✔
857
      if (!isDnodeInList(dnodeList, pDnode->id)) {
2!
858
        taosArrayRemove(pArray, i);
×
859
        continue;
×
860
      }
861
      ++i;
2✔
862
    }
863
    if (nDnodesWithVnodes == 1) {
1!
864
      SDnodeObj *pDnode = taosArrayGet(pArray, 0);
×
865
      if (pDnode && (pDnode->id != dnodeId)) {  // the first dnode is not in dnodeList, remove the last element
×
866
        taosArrayRemove(pArray, taosArrayGetSize(pArray) - 1);
×
867
      }
868
    }
869
  }
870

871
  TAOS_RETURN(code);
2✔
872
}
873
#endif
874

875
SArray *mndBuildDnodesArray(SMnode *pMnode, int32_t exceptDnodeId, SArray *dnodeList) {
5,534✔
876
  SSdb   *pSdb = pMnode->pSdb;
5,534✔
877
  int32_t numOfDnodes = mndGetDnodeSize(pMnode);
5,534✔
878
  SArray *tDnodeList = NULL;
5,534✔
879
  SArray *pDnodeList = NULL;
5,534✔
880

881
  SArray *pArray = taosArrayInit(numOfDnodes, sizeof(SDnodeObj));
5,534✔
882
  if (pArray == NULL) {
5,534!
883
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
884
    return NULL;
×
885
  }
886
  if (taosArrayGetSize(dnodeList) > 0) {
5,534✔
887
    tDnodeList = dnodeList;
20✔
888
  }
889
#ifdef TD_ENTERPRISE
890
  if (0 != mndBuildNodesCheckDualReplica(pMnode, numOfDnodes, tDnodeList, &pDnodeList)) {
5,534!
891
    taosArrayDestroy(pArray);
×
892
    return NULL;
×
893
  }
894
#endif
895
  sdbTraverse(pSdb, SDB_DNODE, mndResetDnodesArrayFp, NULL, NULL, NULL);
5,534✔
896
  sdbTraverse(pSdb, SDB_DNODE, mndBuildDnodesArrayFp, pArray, &exceptDnodeId, pDnodeList ? pDnodeList : tDnodeList);
5,534✔
897

898
  mDebug("build %d dnodes array", (int32_t)taosArrayGetSize(pArray));
5,534✔
899
  for (int32_t i = 0; i < (int32_t)taosArrayGetSize(pArray); ++i) {
11,852✔
900
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
6,318✔
901
    mDebug("dnode:%d, vnodes:%d others:%d", pDnode->id, pDnode->numOfVnodes, pDnode->numOfOtherNodes);
6,318✔
902
  }
903
  taosArrayDestroy(pDnodeList);
5,534✔
904
  return pArray;
5,534✔
905
}
906

907
static int32_t mndCompareDnodeId(int32_t *dnode1Id, int32_t *dnode2Id) {
×
908
  if (*dnode1Id == *dnode2Id) {
×
909
    return 0;
×
910
  }
911
  return *dnode1Id > *dnode2Id ? 1 : -1;
×
912
}
913

914
static float mndGetDnodeScore(SDnodeObj *pDnode, int32_t additionDnodes, float ratio) {
21,373✔
915
  float totalDnodes = pDnode->numOfVnodes + (float)pDnode->numOfOtherNodes * ratio + additionDnodes;
21,373✔
916
  return totalDnodes / pDnode->numOfSupportVnodes;
21,373✔
917
}
918

919
static int32_t mndCompareDnodeVnodes(SDnodeObj *pDnode1, SDnodeObj *pDnode2) {
4,945✔
920
  float d1Score = mndGetDnodeScore(pDnode1, 0, 0.9);
4,945✔
921
  float d2Score = mndGetDnodeScore(pDnode2, 0, 0.9);
4,945✔
922
  if (d1Score == d2Score) {
4,945✔
923
    return 0;
1,995✔
924
  }
925
  return d1Score > d2Score ? 1 : -1;
2,950✔
926
}
927

928
void mndSortVnodeGid(SVgObj *pVgroup) {
10,480✔
929
  for (int32_t i = 0; i < pVgroup->replica; ++i) {
21,969✔
930
    for (int32_t j = 0; j < pVgroup->replica - 1 - i; ++j) {
12,999✔
931
      if (pVgroup->vnodeGid[j].dnodeId > pVgroup->vnodeGid[j + 1].dnodeId) {
1,510✔
932
        TSWAP(pVgroup->vnodeGid[j], pVgroup->vnodeGid[j + 1]);
458✔
933
      }
934
    }
935
  }
936
}
10,480✔
937

938
static int32_t mndGetAvailableDnode(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, SArray *pArray) {
10,876✔
939
  mDebug("start to sort %d dnodes", (int32_t)taosArrayGetSize(pArray));
10,876✔
940
  taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
10,876✔
941
  for (int32_t i = 0; i < (int32_t)taosArrayGetSize(pArray); ++i) {
24,131✔
942
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
13,255✔
943
    mDebug("dnode:%d, score:%f", pDnode->id, mndGetDnodeScore(pDnode, 0, 0.9));
13,255✔
944
  }
945

946
  int32_t size = taosArrayGetSize(pArray);
10,876✔
947
  if (size < pVgroup->replica) {
10,876✔
948
    mError("db:%s, vgId:%d, no enough online dnodes:%d to alloc %d replica", pVgroup->dbName, pVgroup->vgId, size,
456!
949
           pVgroup->replica);
950
    TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_DNODES);
456✔
951
  }
952

953
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
21,737✔
954
    SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
11,317✔
955
    SDnodeObj *pDnode = taosArrayGet(pArray, v);
11,317✔
956
    if (pDnode == NULL) {
11,317!
957
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_DNODES);
×
958
    }
959
    if (pDnode->numOfVnodes >= pDnode->numOfSupportVnodes) {
11,317!
960
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_VNODES);
×
961
    }
962

963
    int64_t vgMem = mndGetVgroupMemory(pMnode, pDb, pVgroup);
11,317✔
964
    if (pDnode->memAvail - vgMem - pDnode->memUsed <= 0) {
11,317!
965
      mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d, avail:%" PRId64 " used:%" PRId64,
×
966
             pVgroup->dbName, pVgroup->vgId, vgMem, pDnode->id, pDnode->memAvail, pDnode->memUsed);
967
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE);
×
968
    } else {
969
      pDnode->memUsed += vgMem;
11,317✔
970
    }
971

972
    pVgid->dnodeId = pDnode->id;
11,317✔
973
    if (pVgroup->replica == 1) {
11,317✔
974
      pVgid->syncState = TAOS_SYNC_STATE_LEADER;
9,968✔
975
    } else {
976
      pVgid->syncState = TAOS_SYNC_STATE_FOLLOWER;
1,349✔
977
    }
978

979
    mInfo("db:%s, vgId:%d, vn:%d is alloced, memory:%" PRId64 ", dnode:%d avail:%" PRId64 " used:%" PRId64,
11,317!
980
          pVgroup->dbName, pVgroup->vgId, v, vgMem, pVgid->dnodeId, pDnode->memAvail, pDnode->memUsed);
981
    pDnode->numOfVnodes++;
11,317✔
982
  }
983

984
  mndSortVnodeGid(pVgroup);
10,420✔
985
  return 0;
10,420✔
986
}
987

988
int32_t mndAllocSmaVgroup(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup) {
×
989
  int32_t code = 0;
×
990
  SArray *pArray = mndBuildDnodesArray(pMnode, 0, NULL);
×
991
  if (pArray == NULL) {
×
992
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
993
    if (terrno != 0) code = terrno;
×
994
    TAOS_RETURN(code);
×
995
  }
996

997
  pVgroup->vgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP);
×
998
  pVgroup->isTsma = 1;
×
999
  pVgroup->createdTime = taosGetTimestampMs();
×
1000
  pVgroup->updateTime = pVgroup->createdTime;
×
1001
  pVgroup->version = 1;
×
1002
  memcpy(pVgroup->dbName, pDb->name, TSDB_DB_FNAME_LEN);
×
1003
  pVgroup->dbUid = pDb->uid;
×
1004
  pVgroup->replica = 1;
×
1005

1006
  if (mndGetAvailableDnode(pMnode, pDb, pVgroup, pArray) != 0) return -1;
×
1007
  taosArrayDestroy(pArray);
×
1008

1009
  mInfo("db:%s, sma vgId:%d is alloced", pDb->name, pVgroup->vgId);
×
1010
  return 0;
×
1011
}
1012

1013
int32_t mndAllocVgroup(SMnode *pMnode, SDbObj *pDb, SVgObj **ppVgroups, SArray *dnodeList) {
5,237✔
1014
  int32_t code = -1;
5,237✔
1015
  SArray *pArray = NULL;
5,237✔
1016
  SVgObj *pVgroups = NULL;
5,237✔
1017

1018
  pVgroups = taosMemoryCalloc(pDb->cfg.numOfVgroups, sizeof(SVgObj));
5,237!
1019
  if (pVgroups == NULL) {
5,237!
1020
    code = terrno;
×
1021
    goto _OVER;
×
1022
  }
1023

1024
  pArray = mndBuildDnodesArray(pMnode, 0, dnodeList);
5,237✔
1025
  if (pArray == NULL) {
5,237!
1026
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1027
    if (terrno != 0) code = terrno;
×
1028
    goto _OVER;
×
1029
  }
1030

1031
  mInfo("db:%s, total %d dnodes used to create %d vgroups (%d vnodes)", pDb->name, (int32_t)taosArrayGetSize(pArray),
5,237!
1032
        pDb->cfg.numOfVgroups, pDb->cfg.numOfVgroups * pDb->cfg.replications);
1033

1034
  int32_t  allocedVgroups = 0;
5,237✔
1035
  int32_t  maxVgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP);
5,237✔
1036
  uint32_t hashMin = 0;
5,237✔
1037
  uint32_t hashMax = UINT32_MAX;
5,237✔
1038
  uint32_t hashInterval = (hashMax - hashMin) / pDb->cfg.numOfVgroups;
5,237✔
1039

1040
  if (maxVgId < 2) maxVgId = 2;
5,237✔
1041

1042
  for (uint32_t v = 0; v < pDb->cfg.numOfVgroups; v++) {
15,657✔
1043
    SVgObj *pVgroup = &pVgroups[v];
10,876✔
1044
    pVgroup->vgId = maxVgId++;
10,876✔
1045
    pVgroup->createdTime = taosGetTimestampMs();
10,876✔
1046
    pVgroup->updateTime = pVgroups->createdTime;
10,876✔
1047
    pVgroup->version = 1;
10,876✔
1048
    pVgroup->hashBegin = hashMin + hashInterval * v;
10,876✔
1049
    if (v == pDb->cfg.numOfVgroups - 1) {
10,876✔
1050
      pVgroup->hashEnd = hashMax;
4,881✔
1051
    } else {
1052
      pVgroup->hashEnd = hashMin + hashInterval * (v + 1) - 1;
5,995✔
1053
    }
1054

1055
    memcpy(pVgroup->dbName, pDb->name, TSDB_DB_FNAME_LEN);
10,876✔
1056
    pVgroup->dbUid = pDb->uid;
10,876✔
1057
    pVgroup->replica = pDb->cfg.replications;
10,876✔
1058

1059
    if ((code = mndGetAvailableDnode(pMnode, pDb, pVgroup, pArray)) != 0) {
10,876✔
1060
      goto _OVER;
456✔
1061
    }
1062

1063
    allocedVgroups++;
10,420✔
1064
  }
1065

1066
  *ppVgroups = pVgroups;
4,781✔
1067
  code = 0;
4,781✔
1068

1069
  mInfo("db:%s, total %d vgroups is alloced, replica:%d", pDb->name, pDb->cfg.numOfVgroups, pDb->cfg.replications);
4,781!
1070

1071
_OVER:
×
1072
  if (code != 0) taosMemoryFree(pVgroups);
5,237!
1073
  taosArrayDestroy(pArray);
5,237✔
1074
  TAOS_RETURN(code);
5,237✔
1075
}
1076

1077
SEpSet mndGetVgroupEpset(SMnode *pMnode, const SVgObj *pVgroup) {
192,448✔
1078
  SEpSet epset = {0};
192,448✔
1079

1080
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
399,247✔
1081
    const SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
206,799✔
1082
    SDnodeObj       *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
206,799✔
1083
    if (pDnode == NULL) continue;
206,799✔
1084

1085
    if (pVgid->syncState == TAOS_SYNC_STATE_LEADER || pVgid->syncState == TAOS_SYNC_STATE_ASSIGNED_LEADER) {
206,764!
1086
      epset.inUse = epset.numOfEps;
191,422✔
1087
    }
1088

1089
    if (addEpIntoEpSet(&epset, pDnode->fqdn, pDnode->port) != 0) {
206,764!
1090
      mWarn("vgId:%d, failed to add ep:%s:%d into epset", pVgroup->vgId, pDnode->fqdn, pDnode->port);
×
1091
    }
1092
    mndReleaseDnode(pMnode, pDnode);
206,764✔
1093
  }
1094
  epsetSort(&epset);
192,448✔
1095

1096
  return epset;
192,448✔
1097
}
1098

1099
SEpSet mndGetVgroupEpsetById(SMnode *pMnode, int32_t vgId) {
15✔
1100
  SEpSet epset = {0};
15✔
1101

1102
  SVgObj *pVgroup = mndAcquireVgroup(pMnode, vgId);
15✔
1103
  if (!pVgroup) return epset;
15!
1104

1105
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
45✔
1106
    const SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
30✔
1107
    SDnodeObj       *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
30✔
1108
    if (pDnode == NULL) continue;
30!
1109

1110
    if (pVgid->syncState == TAOS_SYNC_STATE_LEADER || pVgid->syncState == TAOS_SYNC_STATE_ASSIGNED_LEADER) {
30!
1111
      epset.inUse = epset.numOfEps;
6✔
1112
    }
1113

1114
    if (addEpIntoEpSet(&epset, pDnode->fqdn, pDnode->port) != 0) {
30!
1115
      mWarn("vgId:%d, failed to add ep:%s:%d into epset", pVgroup->vgId, pDnode->fqdn, pDnode->port);
×
1116
    }
1117
    mndReleaseDnode(pMnode, pDnode);
30✔
1118
  }
1119

1120
  mndReleaseVgroup(pMnode, pVgroup);
15✔
1121
  return epset;
15✔
1122
}
1123

1124
static int32_t mndRetrieveVgroups(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
13,691✔
1125
  SMnode *pMnode = pReq->info.node;
13,691✔
1126
  SSdb   *pSdb = pMnode->pSdb;
13,691✔
1127
  int32_t numOfRows = 0;
13,691✔
1128
  SVgObj *pVgroup = NULL;
13,691✔
1129
  int32_t cols = 0;
13,691✔
1130
  int64_t curMs = taosGetTimestampMs();
13,691✔
1131
  int32_t code = 0;
13,691✔
1132

1133
  SDbObj *pDb = NULL;
13,691✔
1134
  if (strlen(pShow->db) > 0) {
13,691✔
1135
    pDb = mndAcquireDb(pMnode, pShow->db);
674✔
1136
    if (pDb == NULL) {
674!
1137
      return 0;
×
1138
    }
1139
  }
1140

1141
  while (numOfRows < rows) {
674,764✔
1142
    pShow->pIter = sdbFetch(pSdb, SDB_VGROUP, pShow->pIter, (void **)&pVgroup);
674,755✔
1143
    if (pShow->pIter == NULL) break;
674,629✔
1144

1145
    if (pDb != NULL && pVgroup->dbUid != pDb->uid) {
660,932✔
1146
      sdbRelease(pSdb, pVgroup);
579✔
1147
      continue;
579✔
1148
    }
1149

1150
    cols = 0;
660,353✔
1151
    SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
660,353✔
1152
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->vgId, false);
657,812✔
1153
    if (code != 0) {
653,785!
1154
      mError("vgId:%d, failed to set vgId, since %s", pVgroup->vgId, tstrerror(code));
×
1155
      return code;
×
1156
    }
1157

1158
    SName name = {0};
653,785✔
1159
    char  db[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
653,785✔
1160
    code = tNameFromString(&name, pVgroup->dbName, T_NAME_ACCT | T_NAME_DB);
653,785✔
1161
    if (code != 0) {
660,297!
1162
      mError("vgId:%d, failed to set dbName, since %s", pVgroup->vgId, tstrerror(code));
×
1163
      return code;
×
1164
    }
1165
    (void)tNameGetDbName(&name, varDataVal(db));
660,297✔
1166
    varDataSetLen(db, strlen(varDataVal(db)));
660,247✔
1167

1168
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
660,247✔
1169
    code = colDataSetVal(pColInfo, numOfRows, (const char *)db, false);
657,058✔
1170
    if (code != 0) {
650,775!
1171
      mError("vgId:%d, failed to set dbName, since %s", pVgroup->vgId, tstrerror(code));
×
1172
      return code;
×
1173
    }
1174

1175
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
650,775✔
1176
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->numOfTables, false);
648,336✔
1177
    if (code != 0) {
646,266!
1178
      mError("vgId:%d, failed to set numOfTables, since %s", pVgroup->vgId, tstrerror(code));
×
1179
      return code;
×
1180
    }
1181

1182
    // default 3 replica, add 1 replica if move vnode
1183
    for (int32_t i = 0; i < 4; ++i) {
3,195,485✔
1184
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
2,487,857✔
1185
      if (i < pVgroup->replica) {
2,475,989✔
1186
        int16_t dnodeId = (int16_t)pVgroup->vnodeGid[i].dnodeId;
564,186✔
1187
        code = colDataSetVal(pColInfo, numOfRows, (const char *)&dnodeId, false);
564,186✔
1188
        if (code != 0) {
649,113!
1189
          mError("vgId:%d, failed to set dnodeId, since %s", pVgroup->vgId, tstrerror(code));
×
1190
          return code;
×
1191
        }
1192

1193
        bool       exist = false;
649,113✔
1194
        bool       online = false;
649,113✔
1195
        SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgroup->vnodeGid[i].dnodeId);
649,113✔
1196
        if (pDnode != NULL) {
661,628!
1197
          exist = true;
661,649✔
1198
          online = mndIsDnodeOnline(pDnode, curMs);
661,649✔
1199
          mndReleaseDnode(pMnode, pDnode);
661,328✔
1200
        }
1201

1202
        char buf1[20] = {0};
662,253✔
1203
        char role[20] = "offline";
662,253✔
1204
        if (!exist) {
662,253!
1205
          tstrncpy(role, "dropping", sizeof(role));
×
1206
        } else if (online) {
662,253✔
1207
          char *star = "";
662,165✔
1208
          if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_LEADER ||
662,165✔
1209
              pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_ASSIGNED_LEADER) {
2,037!
1210
            if (!pVgroup->vnodeGid[i].syncRestore && !pVgroup->vnodeGid[i].syncCanRead) {
660,128!
1211
              star = "**";
1,296✔
1212
            } else if (!pVgroup->vnodeGid[i].syncRestore && pVgroup->vnodeGid[i].syncCanRead) {
658,832!
1213
              star = "*";
×
1214
            } else {
1215
            }
1216
          }
1217
          snprintf(role, sizeof(role), "%s%s", syncStr(pVgroup->vnodeGid[i].syncState), star);
662,165✔
1218
          /*
1219
          mInfo("db:%s, learner progress:%d", pDb->name, pVgroup->vnodeGid[i].learnerProgress);
1220

1221
          if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_LEARNER) {
1222
            if(pVgroup->vnodeGid[i].learnerProgress < 0){
1223
              snprintf(role, sizeof(role), "%s-",
1224
                syncStr(pVgroup->vnodeGid[i].syncState));
1225

1226
            }
1227
            else if(pVgroup->vnodeGid[i].learnerProgress >= 100){
1228
              snprintf(role, sizeof(role), "%s--",
1229
                syncStr(pVgroup->vnodeGid[i].syncState));
1230
            }
1231
            else{
1232
              snprintf(role, sizeof(role), "%s%d",
1233
                syncStr(pVgroup->vnodeGid[i].syncState), pVgroup->vnodeGid[i].learnerProgress);
1234
            }
1235
          }
1236
          else{
1237
            snprintf(role, sizeof(role), "%s%s", syncStr(pVgroup->vnodeGid[i].syncState), star);
1238
          }
1239
          */
1240
        } else {
1241
        }
1242
        STR_WITH_MAXSIZE_TO_VARSTR(buf1, role, pShow->pMeta->pSchemas[cols].bytes);
662,225✔
1243

1244
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
662,225✔
1245
        code = colDataSetVal(pColInfo, numOfRows, (const char *)buf1, false);
659,009✔
1246
        if (code != 0) {
654,550!
1247
          mError("vgId:%d, failed to set role, since %s", pVgroup->vgId, tstrerror(code));
×
1248
          return code;
×
1249
        }
1250

1251
        char applyStr[TSDB_SYNC_APPLY_COMMIT_LEN + 1] = {0};
654,550✔
1252
        char buf[TSDB_SYNC_APPLY_COMMIT_LEN + VARSTR_HEADER_SIZE + 1] = {0};
654,550✔
1253
        snprintf(applyStr, sizeof(applyStr), "%" PRId64 "/%" PRId64, pVgroup->vnodeGid[i].syncAppliedIndex,
654,550✔
1254
                 pVgroup->vnodeGid[i].syncCommitIndex);
654,550✔
1255
        STR_WITH_MAXSIZE_TO_VARSTR(buf, applyStr, pShow->pMeta->pSchemas[cols].bytes);
654,550✔
1256

1257
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
654,550✔
1258
        code = colDataSetVal(pColInfo, numOfRows, (const char *)&buf, false);
657,788✔
1259
        if (code != 0) {
653,310!
1260
          mError("vgId:%d, failed to set role, since %s", pVgroup->vgId, tstrerror(code));
×
1261
          return code;
×
1262
        }
1263
      } else {
1264
        colDataSetNULL(pColInfo, numOfRows);
1,911,803✔
1265
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,911,803✔
1266
        colDataSetNULL(pColInfo, numOfRows);
1,901,897!
1267
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,901,897✔
1268
        colDataSetNULL(pColInfo, numOfRows);
1,895,909!
1269
      }
1270
    }
1271

1272
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
707,628✔
1273
    int32_t cacheUsage = (int32_t)pVgroup->cacheUsage;
652,900✔
1274
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&cacheUsage, false);
652,900✔
1275
    if (code != 0) {
651,736!
1276
      mError("vgId:%d, failed to set cacheUsage, since %s", pVgroup->vgId, tstrerror(code));
×
1277
      return code;
×
1278
    }
1279

1280
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
651,736✔
1281
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->numOfCachedTables, false);
648,491✔
1282
    if (code != 0) {
647,606!
1283
      mError("vgId:%d, failed to set numOfCachedTables, since %s", pVgroup->vgId, tstrerror(code));
×
1284
      return code;
×
1285
    }
1286

1287
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
647,606✔
1288
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->isTsma, false);
645,048✔
1289
    if (code != 0) {
646,110!
1290
      mError("vgId:%d, failed to set isTsma, since %s", pVgroup->vgId, tstrerror(code));
×
1291
      return code;
×
1292
    }
1293
    numOfRows++;
646,110✔
1294
    sdbRelease(pSdb, pVgroup);
646,110✔
1295
  }
1296

1297
  if (pDb != NULL) {
13,706✔
1298
    mndReleaseDb(pMnode, pDb);
674✔
1299
  }
1300

1301
  pShow->numOfRows += numOfRows;
13,697✔
1302
  return numOfRows;
13,697✔
1303
}
1304

1305
static void mndCancelGetNextVgroup(SMnode *pMnode, void *pIter) {
×
1306
  SSdb *pSdb = pMnode->pSdb;
×
1307
  sdbCancelFetchByType(pSdb, pIter, SDB_VGROUP);
×
1308
}
×
1309

1310
static bool mndGetVnodesNumFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
338,628✔
1311
  SVgObj  *pVgroup = pObj;
338,628✔
1312
  int32_t  dnodeId = *(int32_t *)p1;
338,628✔
1313
  int32_t *pNumOfVnodes = (int32_t *)p2;
338,628✔
1314

1315
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
693,370✔
1316
    if (pVgroup->vnodeGid[v].dnodeId == dnodeId) {
354,742✔
1317
      (*pNumOfVnodes)++;
328,968✔
1318
    }
1319
  }
1320

1321
  return true;
338,628✔
1322
}
1323

1324
int32_t mndGetVnodesNum(SMnode *pMnode, int32_t dnodeId) {
17,385✔
1325
  int32_t numOfVnodes = 0;
17,385✔
1326
  sdbTraverse(pMnode->pSdb, SDB_VGROUP, mndGetVnodesNumFp, &dnodeId, &numOfVnodes, NULL);
17,385✔
1327
  return numOfVnodes;
17,410✔
1328
}
1329

1330
int64_t mndGetVgroupMemory(SMnode *pMnode, SDbObj *pDbInput, SVgObj *pVgroup) {
36,870✔
1331
  SDbObj *pDb = pDbInput;
36,870✔
1332
  if (pDbInput == NULL) {
36,870✔
1333
    pDb = mndAcquireDb(pMnode, pVgroup->dbName);
23,913✔
1334
  }
1335

1336
  int64_t vgroupMemroy = 0;
36,870✔
1337
  if (pDb != NULL) {
36,870✔
1338
    int64_t buffer = (int64_t)pDb->cfg.buffer * 1024 * 1024;
36,852✔
1339
    int64_t cache = (int64_t)pDb->cfg.pages * pDb->cfg.pageSize * 1024;
36,852✔
1340
    vgroupMemroy = buffer + cache;
36,852✔
1341
    int64_t cacheLast = (int64_t)pDb->cfg.cacheLastSize * 1024 * 1024;
36,852✔
1342
    if (pDb->cfg.cacheLast > 0) {
36,852✔
1343
      vgroupMemroy += cacheLast;
9,665✔
1344
    }
1345
    mDebug("db:%s, vgroup:%d, buffer:%" PRId64 " cache:%" PRId64 " cacheLast:%" PRId64, pDb->name, pVgroup->vgId,
36,852✔
1346
           buffer, cache, cacheLast);
1347
  }
1348

1349
  if (pDbInput == NULL) {
36,870✔
1350
    mndReleaseDb(pMnode, pDb);
23,913✔
1351
  }
1352
  return vgroupMemroy;
36,870✔
1353
}
1354

1355
static bool mndGetVnodeMemroyFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
26,924✔
1356
  SVgObj  *pVgroup = pObj;
26,924✔
1357
  int32_t  dnodeId = *(int32_t *)p1;
26,924✔
1358
  int64_t *pVnodeMemory = (int64_t *)p2;
26,924✔
1359

1360
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
59,977✔
1361
    if (pVgroup->vnodeGid[v].dnodeId == dnodeId) {
33,053✔
1362
      *pVnodeMemory += mndGetVgroupMemory(pMnode, NULL, pVgroup);
23,617✔
1363
    }
1364
  }
1365

1366
  return true;
26,924✔
1367
}
1368

1369
int64_t mndGetVnodesMemory(SMnode *pMnode, int32_t dnodeId) {
6,952✔
1370
  int64_t vnodeMemory = 0;
6,952✔
1371
  sdbTraverse(pMnode->pSdb, SDB_VGROUP, mndGetVnodeMemroyFp, &dnodeId, &vnodeMemory, NULL);
6,952✔
1372
  return vnodeMemory;
6,952✔
1373
}
1374

1375
void calculateRstoreFinishTime(double rate, int64_t applyCount, char *restoreStr, size_t restoreStrSize) {
1✔
1376
  if (rate == 0) {
1!
1377
    snprintf(restoreStr, restoreStrSize, "0:0:0");
1✔
1378
    return;
1✔
1379
  }
1380

1381
  int64_t costTime = applyCount / rate;
×
1382
  int64_t totalSeconds = costTime / 1000;
×
1383
  int64_t hours = totalSeconds / 3600;
×
1384
  totalSeconds %= 3600;
×
1385
  int64_t minutes = totalSeconds / 60;
×
1386
  int64_t seconds = totalSeconds % 60;
×
1387
  snprintf(restoreStr, restoreStrSize, "%" PRId64 ":%" PRId64 ":%" PRId64, hours, minutes, seconds);
×
1388
}
1389

1390
static int32_t mndRetrieveVnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
8,073✔
1391
  SMnode *pMnode = pReq->info.node;
8,073✔
1392
  SSdb   *pSdb = pMnode->pSdb;
8,073✔
1393
  int32_t numOfRows = 0;
8,073✔
1394
  SVgObj *pVgroup = NULL;
8,073✔
1395
  int32_t cols = 0;
8,073✔
1396
  int64_t curMs = taosGetTimestampMs();
8,073✔
1397
  int32_t code = 0;
8,073✔
1398

1399
  while (numOfRows < rows - TSDB_MAX_REPLICA) {
411,484!
1400
    pShow->pIter = sdbFetch(pSdb, SDB_VGROUP, pShow->pIter, (void **)&pVgroup);
411,484✔
1401
    if (pShow->pIter == NULL) break;
411,420✔
1402

1403
    for (int32_t i = 0; i < pVgroup->replica && numOfRows < rows; ++i) {
807,142!
1404
      SVnodeGid       *pGid = &pVgroup->vnodeGid[i];
403,716✔
1405
      SColumnInfoData *pColInfo = NULL;
403,716✔
1406
      cols = 0;
403,716✔
1407

1408
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
403,716✔
1409
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&pGid->dnodeId, false);
402,674✔
1410
      if (code != 0) {
398,238!
1411
        mError("vgId:%d, failed to set dnodeId, since %s", pVgroup->vgId, tstrerror(code));
×
1412
        return code;
×
1413
      }
1414
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
398,238✔
1415
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->vgId, false);
397,204✔
1416
      if (code != 0) {
396,045!
1417
        mError("vgId:%d, failed to set vgId, since %s", pVgroup->vgId, tstrerror(code));
×
1418
        return code;
×
1419
      }
1420

1421
      // db_name
1422
      const char *dbname = mndGetDbStr(pVgroup->dbName);
396,045✔
1423
      char        b1[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
398,489✔
1424
      if (dbname != NULL) {
398,489!
1425
        STR_WITH_MAXSIZE_TO_VARSTR(b1, dbname, TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE);
401,639✔
1426
      } else {
1427
        STR_WITH_MAXSIZE_TO_VARSTR(b1, "NULL", TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE);
×
1428
      }
1429
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
398,489✔
1430
      code = colDataSetVal(pColInfo, numOfRows, (const char *)b1, false);
400,296✔
1431
      if (code != 0) {
397,948!
1432
        mError("vgId:%d, failed to set dbName, since %s", pVgroup->vgId, tstrerror(code));
×
1433
        return code;
×
1434
      }
1435

1436
      // dnode is online?
1437
      SDnodeObj *pDnode = mndAcquireDnode(pMnode, pGid->dnodeId);
397,948✔
1438
      if (pDnode == NULL) {
403,459!
1439
        mError("failed to acquire dnode. dnodeId:%d", pGid->dnodeId);
×
1440
        break;
×
1441
      }
1442
      bool isDnodeOnline = mndIsDnodeOnline(pDnode, curMs);
403,459✔
1443

1444
      char       buf[20] = {0};
403,283✔
1445
      ESyncState syncState = (isDnodeOnline) ? pGid->syncState : TAOS_SYNC_STATE_OFFLINE;
403,283✔
1446
      STR_TO_VARSTR(buf, syncStr(syncState));
403,283✔
1447
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
403,057✔
1448
      code = colDataSetVal(pColInfo, numOfRows, (const char *)buf, false);
401,298✔
1449
      if (code != 0) {
396,484!
1450
        mError("vgId:%d, failed to set syncState, since %s", pVgroup->vgId, tstrerror(code));
×
1451
        return code;
×
1452
      }
1453

1454
      int64_t roleTimeMs = (isDnodeOnline) ? pGid->roleTimeMs : 0;
396,484✔
1455
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
396,484✔
1456
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&roleTimeMs, false);
395,552✔
1457
      if (code != 0) {
394,359!
1458
        mError("vgId:%d, failed to set roleTimeMs, since %s", pVgroup->vgId, tstrerror(code));
×
1459
        return code;
×
1460
      }
1461

1462
      int64_t startTimeMs = (isDnodeOnline) ? pGid->startTimeMs : 0;
394,359✔
1463
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
394,359✔
1464
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&startTimeMs, false);
393,455✔
1465
      if (code != 0) {
393,900!
1466
        mError("vgId:%d, failed to set startTimeMs, since %s", pVgroup->vgId, tstrerror(code));
×
1467
        return code;
×
1468
      }
1469

1470
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
393,900✔
1471
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&pGid->syncRestore, false);
393,017✔
1472
      if (code != 0) {
392,717!
1473
        mError("vgId:%d, failed to set syncRestore, since %s", pVgroup->vgId, tstrerror(code));
×
1474
        return code;
×
1475
      }
1476

1477
      int64_t unappliedCount = pGid->syncCommitIndex - pGid->syncAppliedIndex;
392,717✔
1478
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
392,717✔
1479
      char restoreStr[20] = {0};
391,999✔
1480
      if (unappliedCount > 0) {
391,999✔
1481
        calculateRstoreFinishTime(pGid->appliedRate, unappliedCount, restoreStr, sizeof(restoreStr));
1✔
1482
      }
1483
      STR_TO_VARSTR(buf, restoreStr);
391,999✔
1484
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&buf, false);
391,999✔
1485
      if (code != 0) {
396,475!
1486
        mError("vgId:%d, failed to set syncRestore finish time, since %s", pVgroup->vgId, tstrerror(code));
×
1487
        return code;
×
1488
      }
1489

1490
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
396,475✔
1491
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&unappliedCount, false);
395,024✔
1492
      if (code != 0) {
394,125!
1493
        mError("vgId:%d, failed to set syncRestore, since %s", pVgroup->vgId, tstrerror(code));
×
1494
        return code;
×
1495
      }
1496

1497
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
394,125✔
1498
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&pGid->bufferSegmentUsed, false);
393,122✔
1499
      if (code != 0) {
393,139!
1500
        mError("vgId:%d, failed to set buffer segment used, since %s", pVgroup->vgId, tstrerror(code));
×
1501
        return code;
×
1502
      }
1503

1504
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
393,139✔
1505
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&pGid->bufferSegmentSize, false);
392,358✔
1506
      if (code != 0) {
393,372!
1507
        mError("vgId:%d, failed to set buffer segment size, since %s", pVgroup->vgId, tstrerror(code));
×
1508
        return code;
×
1509
      }
1510

1511
      numOfRows++;
393,372✔
1512
      sdbRelease(pSdb, pDnode);
393,372✔
1513
    }
1514

1515
    sdbRelease(pSdb, pVgroup);
403,426✔
1516
  }
1517

1518
  pShow->numOfRows += numOfRows;
8,083✔
1519
  return numOfRows;
8,083✔
1520
}
1521

1522
static void mndCancelGetNextVnode(SMnode *pMnode, void *pIter) {
×
1523
  SSdb *pSdb = pMnode->pSdb;
×
1524
  sdbCancelFetchByType(pSdb, pIter, SDB_VGROUP);
×
1525
}
×
1526

1527
static int32_t mndAddVnodeToVgroup(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup, SArray *pArray) {
176✔
1528
  int32_t code = 0;
176✔
1529
  taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
176✔
1530
  for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
689✔
1531
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
513✔
1532
    mInfo("trans:%d, dnode:%d, equivalent vnodes:%d others:%d", pTrans->id, pDnode->id, pDnode->numOfVnodes,
513!
1533
          pDnode->numOfOtherNodes);
1534
  }
1535

1536
  SVnodeGid *pVgid = &pVgroup->vnodeGid[pVgroup->replica];
176✔
1537
  for (int32_t d = 0; d < taosArrayGetSize(pArray); ++d) {
228✔
1538
    SDnodeObj *pDnode = taosArrayGet(pArray, d);
216✔
1539

1540
    bool used = false;
216✔
1541
    for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
493✔
1542
      if (pDnode->id == pVgroup->vnodeGid[vn].dnodeId) {
329✔
1543
        used = true;
52✔
1544
        break;
52✔
1545
      }
1546
    }
1547
    if (used) continue;
216✔
1548

1549
    if (pDnode == NULL) {
164!
UNCOV
1550
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_DNODES);
×
1551
    }
1552
    if (pDnode->numOfVnodes >= pDnode->numOfSupportVnodes) {
164!
UNCOV
1553
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_VNODES);
×
1554
    }
1555

1556
    int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
164✔
1557
    if (pDnode->memAvail - vgMem - pDnode->memUsed <= 0) {
164!
UNCOV
1558
      mError("trans:%d, db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
×
1559
             pTrans->id, pVgroup->dbName, pVgroup->vgId, vgMem, pDnode->id, pDnode->memAvail, pDnode->memUsed);
UNCOV
1560
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE);
×
1561
    } else {
1562
      pDnode->memUsed += vgMem;
164✔
1563
    }
1564

1565
    pVgid->dnodeId = pDnode->id;
164✔
1566
    pVgid->syncState = TAOS_SYNC_STATE_OFFLINE;
164✔
1567
    mInfo("trans:%id, db:%s, vgId:%d, vn:%d is added, memory:%" PRId64 ", dnode:%d avail:%" PRId64 " used:%" PRId64,
164!
1568
          pTrans->id, pVgroup->dbName, pVgroup->vgId, pVgroup->replica, vgMem, pVgid->dnodeId, pDnode->memAvail,
1569
          pDnode->memUsed);
1570

1571
    pVgroup->replica++;
164✔
1572
    pDnode->numOfVnodes++;
164✔
1573

1574
    SSdbRaw *pVgRaw = mndVgroupActionEncode(pVgroup);
164✔
1575
    if (pVgRaw == NULL) {
164!
1576
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1577
      if (terrno != 0) code = terrno;
×
UNCOV
1578
      TAOS_RETURN(code);
×
1579
    }
1580
    if ((code = mndTransAppendGroupRedolog(pTrans, pVgRaw, pVgroup->vgId)) != 0) {
164!
UNCOV
1581
      sdbFreeRaw(pVgRaw);
×
UNCOV
1582
      TAOS_RETURN(code);
×
1583
    }
1584
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
164✔
1585
    if (code != 0) {
164!
UNCOV
1586
      mError("trans:%d, vgId:%d, failed to set raw status since %s at line:%d", pTrans->id, pVgroup->vgId,
×
1587
             tstrerror(code), __LINE__);
1588
    }
1589
    TAOS_RETURN(code);
164✔
1590
  }
1591

1592
  code = TSDB_CODE_MND_NO_ENOUGH_DNODES;
12✔
1593
  mError("trans:%d, db:%s, failed to add vnode to vgId:%d since %s", pTrans->id, pVgroup->dbName, pVgroup->vgId,
12!
1594
         tstrerror(code));
1595
  TAOS_RETURN(code);
12✔
1596
}
1597

1598
static int32_t mndRemoveVnodeFromVgroup(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup, SArray *pArray,
31✔
1599
                                        SVnodeGid *pDelVgid) {
1600
  taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
31✔
1601
  for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
137✔
1602
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
106✔
1603
    mInfo("trans:%d, dnode:%d, equivalent vnodes:%d others:%d", pTrans->id, pDnode->id, pDnode->numOfVnodes,
106!
1604
          pDnode->numOfOtherNodes);
1605
  }
1606

1607
  int32_t code = -1;
31✔
1608
  for (int32_t d = taosArrayGetSize(pArray) - 1; d >= 0; --d) {
43!
1609
    SDnodeObj *pDnode = taosArrayGet(pArray, d);
43✔
1610

1611
    for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
103✔
1612
      SVnodeGid *pVgid = &pVgroup->vnodeGid[vn];
91✔
1613
      if (pVgid->dnodeId == pDnode->id) {
91✔
1614
        int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
31✔
1615
        pDnode->memUsed -= vgMem;
31✔
1616
        mInfo("trans:%d, db:%s, vgId:%d, vn:%d is removed, memory:%" PRId64 ", dnode:%d avail:%" PRId64
31!
1617
              " used:%" PRId64,
1618
              pTrans->id, pVgroup->dbName, pVgroup->vgId, vn, vgMem, pVgid->dnodeId, pDnode->memAvail, pDnode->memUsed);
1619
        pDnode->numOfVnodes--;
31✔
1620
        pVgroup->replica--;
31✔
1621
        *pDelVgid = *pVgid;
31✔
1622
        *pVgid = pVgroup->vnodeGid[pVgroup->replica];
31✔
1623
        memset(&pVgroup->vnodeGid[pVgroup->replica], 0, sizeof(SVnodeGid));
31✔
1624
        code = 0;
31✔
1625
        goto _OVER;
31✔
1626
      }
1627
    }
1628
  }
1629

UNCOV
1630
_OVER:
×
1631
  if (code != 0) {
31!
UNCOV
1632
    code = TSDB_CODE_APP_ERROR;
×
UNCOV
1633
    mError("trans:%d, db:%s, failed to remove vnode from vgId:%d since %s", pTrans->id, pVgroup->dbName, pVgroup->vgId,
×
1634
           tstrerror(code));
UNCOV
1635
    TAOS_RETURN(code);
×
1636
  }
1637

1638
  for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
89✔
1639
    SVnodeGid *pVgid = &pVgroup->vnodeGid[vn];
58✔
1640
    mInfo("trans:%d, db:%s, vgId:%d, vn:%d dnode:%d is reserved", pTrans->id, pVgroup->dbName, pVgroup->vgId, vn,
58!
1641
          pVgid->dnodeId);
1642
  }
1643

1644
  SSdbRaw *pVgRaw = mndVgroupActionEncode(pVgroup);
31✔
1645
  if (pVgRaw == NULL) {
31!
UNCOV
1646
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1647
    if (terrno != 0) code = terrno;
×
1648
    TAOS_RETURN(code);
×
1649
  }
1650
  if (mndTransAppendGroupRedolog(pTrans, pVgRaw, pVgroup->vgId) != 0) {
31!
UNCOV
1651
    sdbFreeRaw(pVgRaw);
×
UNCOV
1652
    TAOS_RETURN(code);
×
1653
  }
1654
  code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
31✔
1655
  if (code != 0) {
31!
1656
    mError("trans:%d, vgId:%d, failed to set raw status since %s at line:%d", pTrans->id, pVgroup->vgId,
×
1657
           tstrerror(code), __LINE__);
1658
  }
1659

1660
  TAOS_RETURN(code);
31✔
1661
}
1662

1663
static int32_t mndRemoveVnodeFromVgroupWithoutSave(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup, SArray *pArray,
×
1664
                                                   SVnodeGid *pDelVgid) {
UNCOV
1665
  taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
×
1666
  for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
×
1667
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
×
1668
    mInfo("dnode:%d, equivalent vnodes:%d others:%d", pDnode->id, pDnode->numOfVnodes, pDnode->numOfOtherNodes);
×
1669
  }
1670

1671
  int32_t code = -1;
×
UNCOV
1672
  for (int32_t d = taosArrayGetSize(pArray) - 1; d >= 0; --d) {
×
1673
    SDnodeObj *pDnode = taosArrayGet(pArray, d);
×
1674

1675
    for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
×
1676
      SVnodeGid *pVgid = &pVgroup->vnodeGid[vn];
×
1677
      if (pVgid->dnodeId == pDnode->id) {
×
1678
        int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
×
1679
        pDnode->memUsed -= vgMem;
×
UNCOV
1680
        mInfo("db:%s, vgId:%d, vn:%d is removed, memory:%" PRId64 ", dnode:%d avail:%" PRId64 " used:%" PRId64,
×
1681
              pVgroup->dbName, pVgroup->vgId, vn, vgMem, pVgid->dnodeId, pDnode->memAvail, pDnode->memUsed);
UNCOV
1682
        pDnode->numOfVnodes--;
×
UNCOV
1683
        pVgroup->replica--;
×
1684
        *pDelVgid = *pVgid;
×
1685
        *pVgid = pVgroup->vnodeGid[pVgroup->replica];
×
1686
        memset(&pVgroup->vnodeGid[pVgroup->replica], 0, sizeof(SVnodeGid));
×
1687
        code = 0;
×
1688
        goto _OVER;
×
1689
      }
1690
    }
1691
  }
1692

1693
_OVER:
×
UNCOV
1694
  if (code != 0) {
×
UNCOV
1695
    code = TSDB_CODE_APP_ERROR;
×
1696
    mError("db:%s, failed to remove vnode from vgId:%d since %s", pVgroup->dbName, pVgroup->vgId, tstrerror(code));
×
UNCOV
1697
    TAOS_RETURN(code);
×
1698
  }
1699

UNCOV
1700
  for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
×
UNCOV
1701
    SVnodeGid *pVgid = &pVgroup->vnodeGid[vn];
×
UNCOV
1702
    mInfo("db:%s, vgId:%d, vn:%d dnode:%d is reserved", pVgroup->dbName, pVgroup->vgId, vn, pVgid->dnodeId);
×
1703
  }
1704

UNCOV
1705
  TAOS_RETURN(code);
×
1706
}
1707

1708
int32_t mndAddCreateVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, SVnodeGid *pVgid) {
11,446✔
1709
  int32_t      code = 0;
11,446✔
1710
  STransAction action = {0};
11,446✔
1711

1712
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
11,446✔
1713
  if (pDnode == NULL) return -1;
11,446!
1714
  action.epSet = mndGetDnodeEpset(pDnode);
11,446✔
1715
  mndReleaseDnode(pMnode, pDnode);
11,446✔
1716

1717
  int32_t contLen = 0;
11,446✔
1718
  void   *pReq = mndBuildCreateVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen);
11,446✔
1719
  if (pReq == NULL) return -1;
11,446!
1720

1721
  action.pCont = pReq;
11,446✔
1722
  action.contLen = contLen;
11,446✔
1723
  action.msgType = TDMT_DND_CREATE_VNODE;
11,446✔
1724
  action.acceptableCode = TSDB_CODE_VND_ALREADY_EXIST;
11,446✔
1725
  action.groupId = pVgroup->vgId;
11,446✔
1726

1727
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
11,446!
UNCOV
1728
    taosMemoryFree(pReq);
×
UNCOV
1729
    TAOS_RETURN(code);
×
1730
  }
1731

1732
  TAOS_RETURN(code);
11,446✔
1733
}
1734

1735
int32_t mndRestoreAddCreateVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
10✔
1736
                                       SDnodeObj *pDnode) {
1737
  int32_t      code = 0;
10✔
1738
  STransAction action = {0};
10✔
1739

1740
  action.epSet = mndGetDnodeEpset(pDnode);
10✔
1741

1742
  int32_t contLen = 0;
10✔
1743
  void   *pReq = mndBuildCreateVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen);
10✔
1744
  if (pReq == NULL) {
10!
UNCOV
1745
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1746
    if (terrno != 0) code = terrno;
×
1747
    TAOS_RETURN(code);
×
1748
  }
1749

1750
  action.pCont = pReq;
10✔
1751
  action.contLen = contLen;
10✔
1752
  action.msgType = TDMT_DND_CREATE_VNODE;
10✔
1753
  action.acceptableCode = TSDB_CODE_VND_ALREADY_EXIST;
10✔
1754
  action.groupId = pVgroup->vgId;
10✔
1755

1756
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
10!
UNCOV
1757
    taosMemoryFree(pReq);
×
UNCOV
1758
    TAOS_RETURN(code);
×
1759
  }
1760

1761
  TAOS_RETURN(code);
10✔
1762
}
1763

1764
int32_t mndAddAlterVnodeConfirmAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) {
546✔
1765
  int32_t      code = 0;
546✔
1766
  STransAction action = {0};
546✔
1767
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
546✔
1768

1769
  mInfo("trans:%d, vgId:%d, build alter vnode confirm req", pTrans->id, pVgroup->vgId);
546!
1770
  int32_t   contLen = sizeof(SMsgHead);
546✔
1771
  SMsgHead *pHead = taosMemoryMalloc(contLen);
546!
1772
  if (pHead == NULL) {
546!
UNCOV
1773
    TAOS_RETURN(terrno);
×
1774
  }
1775

1776
  pHead->contLen = htonl(contLen);
546✔
1777
  pHead->vgId = htonl(pVgroup->vgId);
546✔
1778

1779
  action.pCont = pHead;
546✔
1780
  action.contLen = contLen;
546✔
1781
  action.msgType = TDMT_VND_ALTER_CONFIRM;
546✔
1782
  // incorrect redirect result will cause this erro
1783
  action.retryCode = TSDB_CODE_VND_INVALID_VGROUP_ID;
546✔
1784
  action.groupId = pVgroup->vgId;
546✔
1785

1786
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
546!
UNCOV
1787
    taosMemoryFree(pHead);
×
1788
    TAOS_RETURN(code);
×
1789
  }
1790

1791
  TAOS_RETURN(code);
546✔
1792
}
1793

UNCOV
1794
int32_t mndAddChangeConfigAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pOldVgroup, SVgObj *pNewVgroup,
×
1795
                                 int32_t dnodeId) {
1796
  int32_t      code = 0;
×
UNCOV
1797
  STransAction action = {0};
×
1798
  action.epSet = mndGetVgroupEpset(pMnode, pNewVgroup);
×
1799

1800
  int32_t contLen = 0;
×
1801
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pNewVgroup, dnodeId, &contLen);
×
UNCOV
1802
  if (pReq == NULL) {
×
UNCOV
1803
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1804
    if (terrno != 0) code = terrno;
×
1805
    TAOS_RETURN(code);
×
1806
  }
1807

1808
  int32_t totallen = contLen + sizeof(SMsgHead);
×
1809

1810
  SMsgHead *pHead = taosMemoryMalloc(totallen);
×
1811
  if (pHead == NULL) {
×
1812
    taosMemoryFree(pReq);
×
UNCOV
1813
    TAOS_RETURN(terrno);
×
1814
  }
1815

1816
  pHead->contLen = htonl(totallen);
×
UNCOV
1817
  pHead->vgId = htonl(pNewVgroup->vgId);
×
1818

1819
  memcpy((void *)(pHead + 1), pReq, contLen);
×
UNCOV
1820
  taosMemoryFree(pReq);
×
1821

UNCOV
1822
  action.pCont = pHead;
×
UNCOV
1823
  action.contLen = totallen;
×
UNCOV
1824
  action.msgType = TDMT_SYNC_CONFIG_CHANGE;
×
1825

UNCOV
1826
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
×
UNCOV
1827
    taosMemoryFree(pHead);
×
UNCOV
1828
    TAOS_RETURN(code);
×
1829
  }
1830

1831
  TAOS_RETURN(code);
×
1832
}
1833

1834
static int32_t mndAddAlterVnodeHashRangeAction(SMnode *pMnode, STrans *pTrans, int32_t srcVgId, SVgObj *pVgroup) {
64✔
1835
  int32_t      code = 0;
64✔
1836
  STransAction action = {0};
64✔
1837
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
64✔
1838

1839
  int32_t contLen = 0;
64✔
1840
  void   *pReq = mndBuildAlterVnodeHashRangeReq(pMnode, srcVgId, pVgroup, &contLen);
64✔
1841
  if (pReq == NULL) {
64!
1842
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1843
    if (terrno != 0) code = terrno;
×
UNCOV
1844
    TAOS_RETURN(code);
×
1845
  }
1846

1847
  action.pCont = pReq;
64✔
1848
  action.contLen = contLen;
64✔
1849
  action.msgType = TDMT_VND_ALTER_HASHRANGE;
64✔
1850
  action.acceptableCode = TSDB_CODE_VND_ALREADY_EXIST;
64✔
1851

1852
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
64!
UNCOV
1853
    taosMemoryFree(pReq);
×
UNCOV
1854
    TAOS_RETURN(code);
×
1855
  }
1856

1857
  mInfo("trans:%d, add alter vnode hash range action for from vgId:%d to vgId:%d", pTrans->id, srcVgId, pVgroup->vgId);
64!
1858
  TAOS_RETURN(code);
64✔
1859
}
1860

1861
int32_t mndAddAlterVnodeConfigAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) {
612✔
1862
  int32_t      code = 0;
612✔
1863
  STransAction action = {0};
612✔
1864
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
612✔
1865

1866
  int32_t contLen = 0;
612✔
1867
  void   *pReq = mndBuildAlterVnodeConfigReq(pMnode, pDb, pVgroup, &contLen);
612✔
1868
  if (pReq == NULL) {
612!
UNCOV
1869
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1870
    if (terrno != 0) code = terrno;
×
UNCOV
1871
    TAOS_RETURN(code);
×
1872
  }
1873

1874
  action.pCont = pReq;
612✔
1875
  action.contLen = contLen;
612✔
1876
  action.msgType = TDMT_VND_ALTER_CONFIG;
612✔
1877
  action.groupId = pVgroup->vgId;
612✔
1878

1879
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
612!
1880
    taosMemoryFree(pReq);
×
UNCOV
1881
    TAOS_RETURN(code);
×
1882
  }
1883

1884
  TAOS_RETURN(code);
612✔
1885
}
1886

1887
int32_t mndAddNewVgPrepareAction(SMnode *pMnode, STrans *pTrans, SVgObj *pVg) {
10,424✔
1888
  int32_t  code = 0;
10,424✔
1889
  SSdbRaw *pRaw = mndVgroupActionEncode(pVg);
10,424✔
1890
  if (pRaw == NULL) {
10,424!
UNCOV
1891
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1892
    if (terrno != 0) code = terrno;
×
UNCOV
1893
    goto _err;
×
1894
  }
1895

1896
  TAOS_CHECK_GOTO(mndTransAppendPrepareLog(pTrans, pRaw), NULL, _err);
10,424!
1897
  if (sdbSetRawStatus(pRaw, SDB_STATUS_CREATING) != 0) {
10,424!
UNCOV
1898
    mError("vgId:%d, failed to set raw status at line:%d", pVg->vgId, __LINE__);
×
1899
  }
1900
  if (code != 0) {
10,424!
UNCOV
1901
    mError("vgId:%d, failed to set raw status since %s at line:%d", pVg->vgId, tstrerror(code), __LINE__);
×
UNCOV
1902
    TAOS_RETURN(code);
×
1903
  }
1904
  pRaw = NULL;
10,424✔
1905
  TAOS_RETURN(code);
10,424✔
1906

UNCOV
1907
_err:
×
UNCOV
1908
  sdbFreeRaw(pRaw);
×
UNCOV
1909
  TAOS_RETURN(code);
×
1910
}
1911

1912
int32_t mndAddAlterVnodeReplicaAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId) {
1,253✔
1913
  int32_t    code = 0;
1,253✔
1914
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
1,253✔
1915
  if (pDnode == NULL) {
1,253!
1916
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1917
    if (terrno != 0) code = terrno;
×
UNCOV
1918
    TAOS_RETURN(code);
×
1919
  }
1920

1921
  STransAction action = {0};
1,253✔
1922
  action.epSet = mndGetDnodeEpset(pDnode);
1,253✔
1923
  mndReleaseDnode(pMnode, pDnode);
1,253✔
1924

1925
  int32_t contLen = 0;
1,253✔
1926
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pVgroup, dnodeId, &contLen);
1,253✔
1927
  if (pReq == NULL) {
1,253!
UNCOV
1928
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1929
    if (terrno != 0) code = terrno;
×
UNCOV
1930
    TAOS_RETURN(code);
×
1931
  }
1932

1933
  action.pCont = pReq;
1,253✔
1934
  action.contLen = contLen;
1,253✔
1935
  action.msgType = TDMT_VND_ALTER_REPLICA;
1,253✔
1936
  action.groupId = pVgroup->vgId;
1,253✔
1937

1938
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
1,253!
UNCOV
1939
    taosMemoryFree(pReq);
×
UNCOV
1940
    TAOS_RETURN(code);
×
1941
  }
1942

1943
  TAOS_RETURN(code);
1,253✔
1944
}
1945

1946
int32_t mndAddCheckLearnerCatchupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId) {
×
1947
  int32_t    code = 0;
×
1948
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
×
1949
  if (pDnode == NULL) {
×
1950
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1951
    if (terrno != 0) code = terrno;
×
UNCOV
1952
    TAOS_RETURN(code);
×
1953
  }
1954

1955
  STransAction action = {0};
×
1956
  action.epSet = mndGetDnodeEpset(pDnode);
×
1957
  mndReleaseDnode(pMnode, pDnode);
×
1958

1959
  int32_t contLen = 0;
×
1960
  void   *pReq = mndBuildCheckLearnCatchupReq(pMnode, pDb, pVgroup, dnodeId, &contLen);
×
1961
  if (pReq == NULL) {
×
UNCOV
1962
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1963
    if (terrno != 0) code = terrno;
×
1964
    TAOS_RETURN(code);
×
1965
  }
1966

UNCOV
1967
  action.pCont = pReq;
×
UNCOV
1968
  action.contLen = contLen;
×
UNCOV
1969
  action.msgType = TDMT_DND_CHECK_VNODE_LEARNER_CATCHUP;
×
UNCOV
1970
  action.acceptableCode = TSDB_CODE_VND_ALREADY_IS_VOTER;
×
1971
  action.retryCode = TSDB_CODE_VND_NOT_CATCH_UP;
×
1972

1973
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
×
UNCOV
1974
    taosMemoryFree(pReq);
×
UNCOV
1975
    TAOS_RETURN(code);
×
1976
  }
1977

UNCOV
1978
  TAOS_RETURN(code);
×
1979
}
1980

1981
int32_t mndAddAlterVnodeTypeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId) {
201✔
1982
  int32_t    code = 0;
201✔
1983
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
201✔
1984
  if (pDnode == NULL) {
201!
1985
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1986
    if (terrno != 0) code = terrno;
×
UNCOV
1987
    TAOS_RETURN(code);
×
1988
  }
1989

1990
  STransAction action = {0};
201✔
1991
  action.epSet = mndGetDnodeEpset(pDnode);
201✔
1992
  mndReleaseDnode(pMnode, pDnode);
201✔
1993

1994
  int32_t contLen = 0;
201✔
1995
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pVgroup, dnodeId, &contLen);
201✔
1996
  if (pReq == NULL) {
201!
UNCOV
1997
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1998
    if (terrno != 0) code = terrno;
×
UNCOV
1999
    TAOS_RETURN(code);
×
2000
  }
2001

2002
  action.pCont = pReq;
201✔
2003
  action.contLen = contLen;
201✔
2004
  action.msgType = TDMT_DND_ALTER_VNODE_TYPE;
201✔
2005
  action.acceptableCode = TSDB_CODE_VND_ALREADY_IS_VOTER;
201✔
2006
  action.retryCode = TSDB_CODE_VND_NOT_CATCH_UP;
201✔
2007
  action.groupId = pVgroup->vgId;
201✔
2008

2009
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
201!
UNCOV
2010
    taosMemoryFree(pReq);
×
2011
    TAOS_RETURN(code);
×
2012
  }
2013

2014
  TAOS_RETURN(code);
201✔
2015
}
2016

2017
int32_t mndRestoreAddAlterVnodeTypeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
10✔
2018
                                          SDnodeObj *pDnode) {
2019
  int32_t      code = 0;
10✔
2020
  STransAction action = {0};
10✔
2021
  action.epSet = mndGetDnodeEpset(pDnode);
10✔
2022

2023
  int32_t contLen = 0;
10✔
2024
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pVgroup, pDnode->id, &contLen);
10✔
2025
  if (pReq == NULL) {
10!
UNCOV
2026
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2027
    if (terrno != 0) code = terrno;
×
UNCOV
2028
    TAOS_RETURN(code);
×
2029
  }
2030

2031
  action.pCont = pReq;
10✔
2032
  action.contLen = contLen;
10✔
2033
  action.msgType = TDMT_DND_ALTER_VNODE_TYPE;
10✔
2034
  action.acceptableCode = TSDB_CODE_VND_ALREADY_IS_VOTER;
10✔
2035
  action.retryCode = TSDB_CODE_VND_NOT_CATCH_UP;
10✔
2036
  action.groupId = pVgroup->vgId;
10✔
2037

2038
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
10!
UNCOV
2039
    taosMemoryFree(pReq);
×
UNCOV
2040
    TAOS_RETURN(code);
×
2041
  }
2042

2043
  TAOS_RETURN(code);
10✔
2044
}
2045

2046
static int32_t mndAddDisableVnodeWriteAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
64✔
2047
                                             int32_t dnodeId) {
2048
  int32_t    code = 0;
64✔
2049
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
64✔
2050
  if (pDnode == NULL) {
64!
UNCOV
2051
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2052
    if (terrno != 0) code = terrno;
×
UNCOV
2053
    TAOS_RETURN(code);
×
2054
  }
2055

2056
  STransAction action = {0};
64✔
2057
  action.epSet = mndGetDnodeEpset(pDnode);
64✔
2058
  mndReleaseDnode(pMnode, pDnode);
64✔
2059

2060
  int32_t contLen = 0;
64✔
2061
  void   *pReq = mndBuildDisableVnodeWriteReq(pMnode, pDb, pVgroup->vgId, &contLen);
64✔
2062
  if (pReq == NULL) {
64!
UNCOV
2063
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2064
    if (terrno != 0) code = terrno;
×
UNCOV
2065
    TAOS_RETURN(code);
×
2066
  }
2067

2068
  action.pCont = pReq;
64✔
2069
  action.contLen = contLen;
64✔
2070
  action.msgType = TDMT_VND_DISABLE_WRITE;
64✔
2071

2072
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
64!
2073
    taosMemoryFree(pReq);
×
UNCOV
2074
    TAOS_RETURN(code);
×
2075
  }
2076

2077
  TAOS_RETURN(code);
64✔
2078
}
2079

2080
int32_t mndAddDropVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, SVnodeGid *pVgid,
16,216✔
2081
                              bool isRedo) {
2082
  int32_t      code = 0;
16,216✔
2083
  STransAction action = {0};
16,216✔
2084

2085
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
16,216✔
2086
  if (pDnode == NULL) {
16,216!
UNCOV
2087
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2088
    if (terrno != 0) code = terrno;
×
UNCOV
2089
    TAOS_RETURN(code);
×
2090
  }
2091
  action.epSet = mndGetDnodeEpset(pDnode);
16,216✔
2092
  mndReleaseDnode(pMnode, pDnode);
16,216✔
2093

2094
  int32_t contLen = 0;
16,216✔
2095
  void   *pReq = mndBuildDropVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen);
16,216✔
2096
  if (pReq == NULL) {
16,216!
UNCOV
2097
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2098
    if (terrno != 0) code = terrno;
×
2099
    TAOS_RETURN(code);
×
2100
  }
2101

2102
  action.pCont = pReq;
16,216✔
2103
  action.contLen = contLen;
16,216✔
2104
  action.msgType = TDMT_DND_DROP_VNODE;
16,216✔
2105
  action.acceptableCode = TSDB_CODE_VND_NOT_EXIST;
16,216✔
2106
  action.groupId = pVgroup->vgId;
16,216✔
2107

2108
  if (isRedo) {
16,216✔
2109
    if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
5,059!
UNCOV
2110
      taosMemoryFree(pReq);
×
UNCOV
2111
      TAOS_RETURN(code);
×
2112
    }
2113
  } else {
2114
    if ((code = mndTransAppendUndoAction(pTrans, &action)) != 0) {
11,157!
UNCOV
2115
      taosMemoryFree(pReq);
×
UNCOV
2116
      TAOS_RETURN(code);
×
2117
    }
2118
  }
2119

2120
  TAOS_RETURN(code);
16,216✔
2121
}
2122

2123
int32_t mndSetMoveVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t vnIndex,
33✔
2124
                                    SArray *pArray, bool force, bool unsafe) {
2125
  int32_t code = 0;
33✔
2126
  SVgObj  newVg = {0};
33✔
2127
  memcpy(&newVg, pVgroup, sizeof(SVgObj));
33✔
2128

2129
  mInfo("vgId:%d, trans:%d, vgroup info before move, replica:%d", newVg.vgId, pTrans->id, newVg.replica);
33!
2130
  for (int32_t i = 0; i < newVg.replica; ++i) {
102✔
2131
    mInfo("vgId:%d, trans:%d, vnode:%d dnode:%d", newVg.vgId, pTrans->id, i, newVg.vnodeGid[i].dnodeId);
69!
2132
  }
2133

2134
  if (!force) {
33✔
2135
#if 1
2136
    {
2137
#else
2138
    if (newVg.replica == 1) {
2139
#endif
2140
      mInfo("vgId:%d, trans:%d, will add 1 vnode, replca:%d", pVgroup->vgId, pTrans->id, newVg.replica);
29!
2141
      TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVg, pArray));
29✔
2142
      for (int32_t i = 0; i < newVg.replica - 1; ++i) {
88✔
2143
        TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg, newVg.vnodeGid[i].dnodeId));
60!
2144
      }
2145
      TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg, &newVg.vnodeGid[newVg.replica - 1]));
28!
2146
      TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg));
28!
2147

2148
      mInfo("vgId:%d, trans:%d, will remove 1 vnode, replca:2", pVgroup->vgId, pTrans->id);
28!
2149
      newVg.replica--;
28✔
2150
      SVnodeGid del = newVg.vnodeGid[vnIndex];
28✔
2151
      newVg.vnodeGid[vnIndex] = newVg.vnodeGid[newVg.replica];
28✔
2152
      memset(&newVg.vnodeGid[newVg.replica], 0, sizeof(SVnodeGid));
28✔
2153
      {
2154
        SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
28✔
2155
        if (pRaw == NULL) {
28!
UNCOV
2156
          code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2157
          if (terrno != 0) code = terrno;
×
UNCOV
2158
          TAOS_RETURN(code);
×
2159
        }
2160
        if ((code = mndTransAppendGroupRedolog(pTrans, pRaw, pVgroup->vgId)) != 0) {
28!
UNCOV
2161
          sdbFreeRaw(pRaw);
×
UNCOV
2162
          TAOS_RETURN(code);
×
2163
        }
2164
        code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
28✔
2165
        if (code != 0) {
28!
UNCOV
2166
          mError("vgId:%d, failed to set raw status since %s at line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
UNCOV
2167
          return code;
×
2168
        }
2169
      }
2170

2171
      TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pDb, &newVg, &del, true));
28!
2172
      for (int32_t i = 0; i < newVg.replica; ++i) {
88✔
2173
        TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg, newVg.vnodeGid[i].dnodeId));
60!
2174
      }
2175
      TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg));
28!
2176
#if 1
2177
    }
2178
#else
2179
    } else {  // new replica == 3
2180
      mInfo("vgId:%d, will add 1 vnode, replca:3", pVgroup->vgId);
2181
      if (mndAddVnodeToVgroup(pMnode, pTrans, &newVg, pArray) != 0) return -1;
2182
      mInfo("vgId:%d, will remove 1 vnode, replca:4", pVgroup->vgId);
2183
      newVg.replica--;
2184
      SVnodeGid del = newVg.vnodeGid[vnIndex];
2185
      newVg.vnodeGid[vnIndex] = newVg.vnodeGid[newVg.replica];
2186
      memset(&newVg.vnodeGid[newVg.replica], 0, sizeof(SVnodeGid));
2187
      {
2188
        SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
2189
        if (pRaw == NULL) return -1;
2190
        if (mndTransAppendRedolog(pTrans, pRaw) != 0) {
2191
          sdbFreeRaw(pRaw);
2192
          return -1;
2193
        }
2194
      }
2195

2196
      if (mndAddDropVnodeAction(pMnode, pTrans, pDb, &newVg, &del, true) != 0) return -1;
2197
      for (int32_t i = 0; i < newVg.replica; ++i) {
2198
        if (i == vnIndex) continue;
2199
        if (mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg, newVg.vnodeGid[i].dnodeId) != 0) return -1;
2200
      }
2201
      if (mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg, &newVg.vnodeGid[vnIndex]) != 0) return -1;
2202
      if (mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg) != 0) return -1;
2203
    }
2204
#endif
2205
  } else {
2206
    mInfo("vgId:%d, will add 1 vnode and force remove 1 vnode", pVgroup->vgId);
4!
2207
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVg, pArray));
4!
2208
    newVg.replica--;
4✔
2209
    // SVnodeGid del = newVg.vnodeGid[vnIndex];
2210
    newVg.vnodeGid[vnIndex] = newVg.vnodeGid[newVg.replica];
4✔
2211
    memset(&newVg.vnodeGid[newVg.replica], 0, sizeof(SVnodeGid));
4✔
2212
    {
2213
      SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
4✔
2214
      if (pRaw == NULL) {
4!
UNCOV
2215
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2216
        if (terrno != 0) code = terrno;
×
UNCOV
2217
        TAOS_RETURN(code);
×
2218
      }
2219
      if ((code = mndTransAppendGroupRedolog(pTrans, pRaw, pVgroup->vgId)) != 0) {
4!
UNCOV
2220
        sdbFreeRaw(pRaw);
×
UNCOV
2221
        TAOS_RETURN(code);
×
2222
      }
2223
      code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
4✔
2224
      if (code != 0) {
4!
UNCOV
2225
        mError("vgId:%d, failed to set raw status since %s at line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
UNCOV
2226
        return code;
×
2227
      }
2228
    }
2229

2230
    for (int32_t i = 0; i < newVg.replica; ++i) {
12✔
2231
      if (i != vnIndex) {
8✔
2232
        TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg, newVg.vnodeGid[i].dnodeId));
4!
2233
      }
2234
    }
2235
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg, &newVg.vnodeGid[vnIndex]));
4!
2236
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg));
4!
2237

2238
    if (newVg.replica == 1) {
4✔
2239
      if (force && !unsafe) {
2!
2240
        TAOS_RETURN(TSDB_CODE_VND_META_DATA_UNSAFE_DELETE);
1✔
2241
      }
2242

2243
      SSdb *pSdb = pMnode->pSdb;
1✔
2244
      void *pIter = NULL;
1✔
2245

2246
      while (1) {
3✔
2247
        SStbObj *pStb = NULL;
4✔
2248
        pIter = sdbFetch(pSdb, SDB_STB, pIter, (void **)&pStb);
4✔
2249
        if (pIter == NULL) break;
4✔
2250

2251
        if (strcmp(pStb->db, pDb->name) == 0) {
3✔
2252
          if ((code = mndSetForceDropCreateStbRedoActions(pMnode, pTrans, &newVg, pStb)) != 0) {
2!
2253
            sdbCancelFetch(pSdb, pIter);
×
2254
            sdbRelease(pSdb, pStb);
×
UNCOV
2255
            TAOS_RETURN(code);
×
2256
          }
2257
        }
2258

2259
        sdbRelease(pSdb, pStb);
3✔
2260
      }
2261

2262
      mInfo("vgId:%d, all data is dropped since replica=1", pVgroup->vgId);
1!
2263
    }
2264
  }
2265

2266
  {
2267
    SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
31✔
2268
    if (pRaw == NULL) {
31!
UNCOV
2269
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2270
      if (terrno != 0) code = terrno;
×
UNCOV
2271
      TAOS_RETURN(code);
×
2272
    }
2273
    if ((code = mndTransAppendCommitlog(pTrans, pRaw)) != 0) {
31!
UNCOV
2274
      sdbFreeRaw(pRaw);
×
UNCOV
2275
      TAOS_RETURN(code);
×
2276
    }
2277
    code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
31✔
2278
    if (code != 0) {
31!
2279
      mError("vgId:%d, failed to set raw status since %s at line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
2280
      return code;
×
2281
    }
2282
  }
2283

2284
  mInfo("vgId:%d, vgroup info after move, replica:%d", newVg.vgId, newVg.replica);
31!
2285
  for (int32_t i = 0; i < newVg.replica; ++i) {
98✔
2286
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
67!
2287
  }
2288
  TAOS_RETURN(code);
31✔
2289
}
2290

2291
int32_t mndSetMoveVgroupsInfoToTrans(SMnode *pMnode, STrans *pTrans, int32_t delDnodeId, bool force, bool unsafe) {
16✔
2292
  int32_t code = 0;
16✔
2293
  SArray *pArray = mndBuildDnodesArray(pMnode, delDnodeId, NULL);
16✔
2294
  if (pArray == NULL) {
16!
UNCOV
2295
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2296
    if (terrno != 0) code = terrno;
×
UNCOV
2297
    TAOS_RETURN(code);
×
2298
  }
2299

2300
  void *pIter = NULL;
16✔
2301
  while (1) {
44✔
2302
    SVgObj *pVgroup = NULL;
60✔
2303
    pIter = sdbFetch(pMnode->pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
60✔
2304
    if (pIter == NULL) break;
60✔
2305

2306
    int32_t vnIndex = -1;
46✔
2307
    for (int32_t i = 0; i < pVgroup->replica; ++i) {
81✔
2308
      if (pVgroup->vnodeGid[i].dnodeId == delDnodeId) {
68✔
2309
        vnIndex = i;
33✔
2310
        break;
33✔
2311
      }
2312
    }
2313

2314
    code = 0;
46✔
2315
    if (vnIndex != -1) {
46✔
2316
      mInfo("vgId:%d, trans:%d, vnode:%d will be removed from dnode:%d, force:%d", pVgroup->vgId, pTrans->id, vnIndex,
33!
2317
            delDnodeId, force);
2318
      SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName);
33✔
2319
      code = mndSetMoveVgroupInfoToTrans(pMnode, pTrans, pDb, pVgroup, vnIndex, pArray, force, unsafe);
33✔
2320
      mndReleaseDb(pMnode, pDb);
33✔
2321
    }
2322

2323
    sdbRelease(pMnode->pSdb, pVgroup);
46✔
2324

2325
    if (code != 0) {
46✔
2326
      sdbCancelFetch(pMnode->pSdb, pIter);
2✔
2327
      break;
2✔
2328
    }
2329
  }
2330

2331
  taosArrayDestroy(pArray);
16✔
2332
  TAOS_RETURN(code);
16✔
2333
}
2334

2335
static int32_t mndAddIncVgroupReplicaToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
125✔
2336
                                             int32_t newDnodeId) {
2337
  int32_t code = 0;
125✔
2338
  mInfo("vgId:%d, will add 1 vnode, replica:%d dnode:%d", pVgroup->vgId, pVgroup->replica, newDnodeId);
125!
2339

2340
  // assoc dnode
2341
  SVnodeGid *pGid = &pVgroup->vnodeGid[pVgroup->replica];
125✔
2342
  pVgroup->replica++;
125✔
2343
  pGid->dnodeId = newDnodeId;
125✔
2344
  pGid->syncState = TAOS_SYNC_STATE_OFFLINE;
125✔
2345
  pGid->nodeRole = TAOS_SYNC_ROLE_LEARNER;
125✔
2346

2347
  SSdbRaw *pVgRaw = mndVgroupActionEncode(pVgroup);
125✔
2348
  if (pVgRaw == NULL) {
125!
UNCOV
2349
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2350
    if (terrno != 0) code = terrno;
×
UNCOV
2351
    TAOS_RETURN(code);
×
2352
  }
2353
  if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
125!
UNCOV
2354
    sdbFreeRaw(pVgRaw);
×
UNCOV
2355
    TAOS_RETURN(code);
×
2356
  }
2357
  code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
125✔
2358
  if (code != 0) {
125!
UNCOV
2359
    mError("vgId:%d, failed to set raw status since %s at line:%d", pVgroup->vgId, tstrerror(code), __LINE__);
×
UNCOV
2360
    TAOS_RETURN(code);
×
2361
  }
2362

2363
  // learner
2364
  for (int32_t i = 0; i < pVgroup->replica - 1; ++i) {
394✔
2365
    TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, pVgroup, pVgroup->vnodeGid[i].dnodeId));
269!
2366
  }
2367
  TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pDb, pVgroup, pGid));
125!
2368

2369
  // voter
2370
  pGid->nodeRole = TAOS_SYNC_ROLE_VOTER;
125✔
2371
  TAOS_CHECK_RETURN(mndAddAlterVnodeTypeAction(pMnode, pTrans, pDb, pVgroup, pGid->dnodeId));
125!
2372
  for (int32_t i = 0; i < pVgroup->replica - 1; ++i) {
394✔
2373
    TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, pVgroup, pVgroup->vnodeGid[i].dnodeId));
269!
2374
  }
2375

2376
  // confirm
2377
  TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, pVgroup));
125!
2378

2379
  TAOS_RETURN(code);
125✔
2380
}
2381

2382
static int32_t mndAddDecVgroupReplicaFromTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
125✔
2383
                                               int32_t delDnodeId) {
2384
  int32_t code = 0;
125✔
2385
  mInfo("vgId:%d, will remove 1 vnode, replica:%d dnode:%d", pVgroup->vgId, pVgroup->replica, delDnodeId);
125!
2386

2387
  SVnodeGid *pGid = NULL;
125✔
2388
  SVnodeGid  delGid = {0};
125✔
2389
  for (int32_t i = 0; i < pVgroup->replica; ++i) {
198!
2390
    if (pVgroup->vnodeGid[i].dnodeId == delDnodeId) {
198✔
2391
      pGid = &pVgroup->vnodeGid[i];
125✔
2392
      break;
125✔
2393
    }
2394
  }
2395

2396
  if (pGid == NULL) return 0;
125!
2397

2398
  pVgroup->replica--;
125✔
2399
  memcpy(&delGid, pGid, sizeof(SVnodeGid));
125✔
2400
  memcpy(pGid, &pVgroup->vnodeGid[pVgroup->replica], sizeof(SVnodeGid));
125✔
2401
  memset(&pVgroup->vnodeGid[pVgroup->replica], 0, sizeof(SVnodeGid));
125✔
2402

2403
  SSdbRaw *pVgRaw = mndVgroupActionEncode(pVgroup);
125✔
2404
  if (pVgRaw == NULL) {
125!
UNCOV
2405
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2406
    if (terrno != 0) code = terrno;
×
UNCOV
2407
    TAOS_RETURN(code);
×
2408
  }
2409
  if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
125!
UNCOV
2410
    sdbFreeRaw(pVgRaw);
×
UNCOV
2411
    TAOS_RETURN(code);
×
2412
  }
2413
  code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
125✔
2414
  if (code != 0) {
125!
UNCOV
2415
    mError("vgId:%d, failed to set raw status since %s at line:%d", pVgroup->vgId, tstrerror(code), __LINE__);
×
UNCOV
2416
    TAOS_RETURN(code);
×
2417
  }
2418

2419
  TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pDb, pVgroup, &delGid, true));
125!
2420
  for (int32_t i = 0; i < pVgroup->replica; ++i) {
394✔
2421
    TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, pVgroup, pVgroup->vnodeGid[i].dnodeId));
269!
2422
  }
2423
  TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, pVgroup));
125!
2424

2425
  TAOS_RETURN(code);
125✔
2426
}
2427

2428
static int32_t mndRedistributeVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SVgObj *pVgroup, SDnodeObj *pNew1,
79✔
2429
                                     SDnodeObj *pOld1, SDnodeObj *pNew2, SDnodeObj *pOld2, SDnodeObj *pNew3,
2430
                                     SDnodeObj *pOld3) {
2431
  int32_t code = -1;
79✔
2432
  STrans *pTrans = NULL;
79✔
2433

2434
  pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_GLOBAL, pReq, "red-vgroup");
79✔
2435
  if (pTrans == NULL) {
79!
UNCOV
2436
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2437
    if (terrno != 0) code = terrno;
×
UNCOV
2438
    goto _OVER;
×
2439
  }
2440

2441
  mndTransSetDbName(pTrans, pVgroup->dbName, NULL);
79✔
2442
  TAOS_CHECK_GOTO(mndTransCheckConflictWithCompact(pMnode, pTrans), NULL, _OVER);
79✔
2443

2444
  mndTransSetSerial(pTrans);
78✔
2445
  mInfo("trans:%d, used to redistribute vgroup, vgId:%d", pTrans->id, pVgroup->vgId);
78!
2446

2447
  SVgObj newVg = {0};
78✔
2448
  memcpy(&newVg, pVgroup, sizeof(SVgObj));
78✔
2449
  mInfo("vgId:%d, vgroup info before redistribute, replica:%d", newVg.vgId, newVg.replica);
78!
2450
  for (int32_t i = 0; i < newVg.replica; ++i) {
234✔
2451
    mInfo("vgId:%d, vnode:%d dnode:%d role:%s", newVg.vgId, i, newVg.vnodeGid[i].dnodeId,
156!
2452
          syncStr(newVg.vnodeGid[i].syncState));
2453
  }
2454

2455
  if (pNew1 != NULL && pOld1 != NULL) {
78!
2456
    int32_t numOfVnodes = mndGetVnodesNum(pMnode, pNew1->id);
78✔
2457
    if (numOfVnodes >= pNew1->numOfSupportVnodes) {
78✔
2458
      mError("vgId:%d, no enough vnodes in dnode:%d, numOfVnodes:%d support:%d", newVg.vgId, pNew1->id, numOfVnodes,
1!
2459
             pNew1->numOfSupportVnodes);
2460
      code = TSDB_CODE_MND_NO_ENOUGH_VNODES;
1✔
2461
      goto _OVER;
1✔
2462
    }
2463

2464
    int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
77✔
2465
    if (pNew1->memAvail - vgMem - pNew1->memUsed <= 0) {
77!
2466
      mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
×
2467
             pVgroup->dbName, pVgroup->vgId, vgMem, pNew1->id, pNew1->memAvail, pNew1->memUsed);
UNCOV
2468
      code = TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE;
×
UNCOV
2469
      goto _OVER;
×
2470
    } else {
2471
      pNew1->memUsed += vgMem;
77✔
2472
    }
2473

2474
    TAOS_CHECK_GOTO(mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pNew1->id), NULL, _OVER);
77!
2475
    TAOS_CHECK_GOTO(mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pOld1->id), NULL, _OVER);
77!
2476
  }
2477

2478
  if (pNew2 != NULL && pOld2 != NULL) {
77!
2479
    int32_t numOfVnodes = mndGetVnodesNum(pMnode, pNew2->id);
16✔
2480
    if (numOfVnodes >= pNew2->numOfSupportVnodes) {
16!
UNCOV
2481
      mError("vgId:%d, no enough vnodes in dnode:%d, numOfVnodes:%d support:%d", newVg.vgId, pNew2->id, numOfVnodes,
×
2482
             pNew2->numOfSupportVnodes);
UNCOV
2483
      code = TSDB_CODE_MND_NO_ENOUGH_VNODES;
×
2484
      goto _OVER;
×
2485
    }
2486
    int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
16✔
2487
    if (pNew2->memAvail - vgMem - pNew2->memUsed <= 0) {
16!
UNCOV
2488
      mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
×
2489
             pVgroup->dbName, pVgroup->vgId, vgMem, pNew2->id, pNew2->memAvail, pNew2->memUsed);
UNCOV
2490
      code = TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE;
×
2491
      goto _OVER;
×
2492
    } else {
2493
      pNew2->memUsed += vgMem;
16✔
2494
    }
2495
    TAOS_CHECK_GOTO(mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pNew2->id), NULL, _OVER);
16!
2496
    TAOS_CHECK_GOTO(mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pOld2->id), NULL, _OVER);
16!
2497
  }
2498

2499
  if (pNew3 != NULL && pOld3 != NULL) {
77!
2500
    int32_t numOfVnodes = mndGetVnodesNum(pMnode, pNew3->id);
8✔
2501
    if (numOfVnodes >= pNew3->numOfSupportVnodes) {
8!
UNCOV
2502
      mError("vgId:%d, no enough vnodes in dnode:%d, numOfVnodes:%d support:%d", newVg.vgId, pNew3->id, numOfVnodes,
×
2503
             pNew3->numOfSupportVnodes);
UNCOV
2504
      code = TSDB_CODE_MND_NO_ENOUGH_VNODES;
×
2505
      goto _OVER;
×
2506
    }
2507
    int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
8✔
2508
    if (pNew3->memAvail - vgMem - pNew3->memUsed <= 0) {
8!
UNCOV
2509
      mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
×
2510
             pVgroup->dbName, pVgroup->vgId, vgMem, pNew3->id, pNew3->memAvail, pNew3->memUsed);
2511
      code = TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE;
×
UNCOV
2512
      goto _OVER;
×
2513
    } else {
2514
      pNew3->memUsed += vgMem;
8✔
2515
    }
2516
    TAOS_CHECK_GOTO(mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pNew3->id), NULL, _OVER);
8!
2517
    TAOS_CHECK_GOTO(mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pOld3->id), NULL, _OVER);
8!
2518
  }
2519

2520
  {
2521
    SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
77✔
2522
    if (pRaw == NULL) {
77!
UNCOV
2523
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2524
      if (terrno != 0) code = terrno;
×
UNCOV
2525
      goto _OVER;
×
2526
    }
2527
    if ((code = mndTransAppendCommitlog(pTrans, pRaw)) != 0) {
77!
UNCOV
2528
      sdbFreeRaw(pRaw);
×
UNCOV
2529
      goto _OVER;
×
2530
    }
2531
    code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
77✔
2532
    if (code != 0) {
77!
UNCOV
2533
      mError("vgId:%d, failed to set raw status since %s at line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
UNCOV
2534
      goto _OVER;
×
2535
    }
2536
  }
2537

2538
  mInfo("vgId:%d, vgroup info after redistribute, replica:%d", newVg.vgId, newVg.replica);
77!
2539
  for (int32_t i = 0; i < newVg.replica; ++i) {
230✔
2540
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
153!
2541
  }
2542

2543
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
77!
2544
  code = 0;
77✔
2545

2546
_OVER:
79✔
2547
  mndTransDrop(pTrans);
79✔
2548
  mndReleaseDb(pMnode, pDb);
79✔
2549
  TAOS_RETURN(code);
79✔
2550
}
2551

2552
static int32_t mndProcessRedistributeVgroupMsg(SRpcMsg *pReq) {
95✔
2553
  SMnode    *pMnode = pReq->info.node;
95✔
2554
  SDnodeObj *pNew1 = NULL;
95✔
2555
  SDnodeObj *pNew2 = NULL;
95✔
2556
  SDnodeObj *pNew3 = NULL;
95✔
2557
  SDnodeObj *pOld1 = NULL;
95✔
2558
  SDnodeObj *pOld2 = NULL;
95✔
2559
  SDnodeObj *pOld3 = NULL;
95✔
2560
  SVgObj    *pVgroup = NULL;
95✔
2561
  SDbObj    *pDb = NULL;
95✔
2562
  int32_t    code = -1;
95✔
2563
  int64_t    curMs = taosGetTimestampMs();
95✔
2564
  int32_t    newDnodeId[3] = {0};
95✔
2565
  int32_t    oldDnodeId[3] = {0};
95✔
2566
  int32_t    newIndex = -1;
95✔
2567
  int32_t    oldIndex = -1;
95✔
2568

2569
  SRedistributeVgroupReq req = {0};
95✔
2570
  if (tDeserializeSRedistributeVgroupReq(pReq->pCont, pReq->contLen, &req) != 0) {
95!
2571
    code = TSDB_CODE_INVALID_MSG;
×
2572
    goto _OVER;
×
2573
  }
2574

2575
  mInfo("vgId:%d, start to redistribute vgroup to dnode %d:%d:%d", req.vgId, req.dnodeId1, req.dnodeId2, req.dnodeId3);
95!
2576
  if ((code = mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_REDISTRIBUTE_VGROUP)) != 0) {
95✔
2577
    goto _OVER;
1✔
2578
  }
2579

2580
  pVgroup = mndAcquireVgroup(pMnode, req.vgId);
94✔
2581
  if (pVgroup == NULL) {
94✔
2582
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
3✔
2583
    if (terrno != 0) code = terrno;
3!
2584
    goto _OVER;
3✔
2585
  }
2586

2587
  pDb = mndAcquireDb(pMnode, pVgroup->dbName);
91✔
2588
  if (pDb == NULL) {
91!
UNCOV
2589
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2590
    if (terrno != 0) code = terrno;
×
2591
    goto _OVER;
×
2592
  }
2593

2594
  if (pVgroup->replica == 1) {
91✔
2595
    if (req.dnodeId1 <= 0 || req.dnodeId2 > 0 || req.dnodeId3 > 0) {
43!
2596
      code = TSDB_CODE_MND_INVALID_REPLICA;
×
UNCOV
2597
      goto _OVER;
×
2598
    }
2599

2600
    if (req.dnodeId1 == pVgroup->vnodeGid[0].dnodeId) {
43✔
2601
      // terrno = TSDB_CODE_MND_VGROUP_UN_CHANGED;
2602
      code = 0;
1✔
2603
      goto _OVER;
1✔
2604
    }
2605

2606
    pNew1 = mndAcquireDnode(pMnode, req.dnodeId1);
42✔
2607
    if (pNew1 == NULL) {
42!
UNCOV
2608
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2609
      if (terrno != 0) code = terrno;
×
UNCOV
2610
      goto _OVER;
×
2611
    }
2612
    if (!mndIsDnodeOnline(pNew1, curMs)) {
42!
UNCOV
2613
      code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2614
      goto _OVER;
×
2615
    }
2616

2617
    pOld1 = mndAcquireDnode(pMnode, pVgroup->vnodeGid[0].dnodeId);
42✔
2618
    if (pOld1 == NULL) {
42!
UNCOV
2619
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2620
      if (terrno != 0) code = terrno;
×
UNCOV
2621
      goto _OVER;
×
2622
    }
2623
    if (!mndIsDnodeOnline(pOld1, curMs)) {
42✔
2624
      code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
2✔
2625
      goto _OVER;
2✔
2626
    }
2627

2628
    code = mndRedistributeVgroup(pMnode, pReq, pDb, pVgroup, pNew1, pOld1, NULL, NULL, NULL, NULL);
40✔
2629

2630
  } else if (pVgroup->replica == 3) {
48!
2631
    if (req.dnodeId1 <= 0 || req.dnodeId2 <= 0 || req.dnodeId3 <= 0) {
48!
2632
      code = TSDB_CODE_MND_INVALID_REPLICA;
4✔
2633
      goto _OVER;
4✔
2634
    }
2635

2636
    if (req.dnodeId1 == req.dnodeId2 || req.dnodeId1 == req.dnodeId3 || req.dnodeId2 == req.dnodeId3) {
44!
2637
      code = TSDB_CODE_MND_INVALID_REPLICA;
1✔
2638
      goto _OVER;
1✔
2639
    }
2640

2641
    if (req.dnodeId1 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId1 != pVgroup->vnodeGid[1].dnodeId &&
43✔
2642
        req.dnodeId1 != pVgroup->vnodeGid[2].dnodeId) {
22✔
2643
      newDnodeId[++newIndex] = req.dnodeId1;
19✔
2644
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
19!
2645
    }
2646

2647
    if (req.dnodeId2 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[1].dnodeId &&
43✔
2648
        req.dnodeId2 != pVgroup->vnodeGid[2].dnodeId) {
29✔
2649
      newDnodeId[++newIndex] = req.dnodeId2;
22✔
2650
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
22!
2651
    }
2652

2653
    if (req.dnodeId3 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId3 != pVgroup->vnodeGid[1].dnodeId &&
43✔
2654
        req.dnodeId3 != pVgroup->vnodeGid[2].dnodeId) {
35✔
2655
      newDnodeId[++newIndex] = req.dnodeId3;
29✔
2656
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
29!
2657
    }
2658

2659
    if (req.dnodeId1 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[0].dnodeId &&
43✔
2660
        req.dnodeId3 != pVgroup->vnodeGid[0].dnodeId) {
28✔
2661
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[0].dnodeId;
25✔
2662
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
25!
2663
    }
2664

2665
    if (req.dnodeId1 != pVgroup->vnodeGid[1].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[1].dnodeId &&
43✔
2666
        req.dnodeId3 != pVgroup->vnodeGid[1].dnodeId) {
23✔
2667
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[1].dnodeId;
18✔
2668
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
18!
2669
    }
2670

2671
    if (req.dnodeId1 != pVgroup->vnodeGid[2].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[2].dnodeId &&
43✔
2672
        req.dnodeId3 != pVgroup->vnodeGid[2].dnodeId) {
33✔
2673
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[2].dnodeId;
27✔
2674
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
27!
2675
    }
2676

2677
    if (newDnodeId[0] != 0) {
43✔
2678
      pNew1 = mndAcquireDnode(pMnode, newDnodeId[0]);
42✔
2679
      if (pNew1 == NULL) {
42!
2680
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2681
        if (terrno != 0) code = terrno;
×
UNCOV
2682
        goto _OVER;
×
2683
      }
2684
      if (!mndIsDnodeOnline(pNew1, curMs)) {
42✔
2685
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
1✔
2686
        goto _OVER;
1✔
2687
      }
2688
    }
2689

2690
    if (newDnodeId[1] != 0) {
42✔
2691
      pNew2 = mndAcquireDnode(pMnode, newDnodeId[1]);
18✔
2692
      if (pNew2 == NULL) {
18!
2693
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2694
        if (terrno != 0) code = terrno;
×
UNCOV
2695
        goto _OVER;
×
2696
      }
2697
      if (!mndIsDnodeOnline(pNew2, curMs)) {
18!
UNCOV
2698
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2699
        goto _OVER;
×
2700
      }
2701
    }
2702

2703
    if (newDnodeId[2] != 0) {
42✔
2704
      pNew3 = mndAcquireDnode(pMnode, newDnodeId[2]);
10✔
2705
      if (pNew3 == NULL) {
10!
UNCOV
2706
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2707
        if (terrno != 0) code = terrno;
×
UNCOV
2708
        goto _OVER;
×
2709
      }
2710
      if (!mndIsDnodeOnline(pNew3, curMs)) {
10!
UNCOV
2711
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2712
        goto _OVER;
×
2713
      }
2714
    }
2715

2716
    if (oldDnodeId[0] != 0) {
42✔
2717
      pOld1 = mndAcquireDnode(pMnode, oldDnodeId[0]);
41✔
2718
      if (pOld1 == NULL) {
41!
2719
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2720
        if (terrno != 0) code = terrno;
×
UNCOV
2721
        goto _OVER;
×
2722
      }
2723
      if (!mndIsDnodeOnline(pOld1, curMs)) {
41✔
2724
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
2✔
2725
        goto _OVER;
2✔
2726
      }
2727
    }
2728

2729
    if (oldDnodeId[1] != 0) {
40✔
2730
      pOld2 = mndAcquireDnode(pMnode, oldDnodeId[1]);
16✔
2731
      if (pOld2 == NULL) {
16!
2732
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2733
        if (terrno != 0) code = terrno;
×
UNCOV
2734
        goto _OVER;
×
2735
      }
2736
      if (!mndIsDnodeOnline(pOld2, curMs)) {
16!
UNCOV
2737
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2738
        goto _OVER;
×
2739
      }
2740
    }
2741

2742
    if (oldDnodeId[2] != 0) {
40✔
2743
      pOld3 = mndAcquireDnode(pMnode, oldDnodeId[2]);
8✔
2744
      if (pOld3 == NULL) {
8!
UNCOV
2745
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2746
        if (terrno != 0) code = terrno;
×
2747
        goto _OVER;
×
2748
      }
2749
      if (!mndIsDnodeOnline(pOld3, curMs)) {
8!
UNCOV
2750
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2751
        goto _OVER;
×
2752
      }
2753
    }
2754

2755
    if (pNew1 == NULL && pOld1 == NULL && pNew2 == NULL && pOld2 == NULL && pNew3 == NULL && pOld3 == NULL) {
40!
2756
      // terrno = TSDB_CODE_MND_VGROUP_UN_CHANGED;
2757
      code = 0;
1✔
2758
      goto _OVER;
1✔
2759
    }
2760

2761
    code = mndRedistributeVgroup(pMnode, pReq, pDb, pVgroup, pNew1, pOld1, pNew2, pOld2, pNew3, pOld3);
39✔
2762

2763
  } else {
UNCOV
2764
    code = TSDB_CODE_MND_REQ_REJECTED;
×
UNCOV
2765
    goto _OVER;
×
2766
  }
2767

2768
  if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
79✔
2769

2770
  char obj[33] = {0};
79✔
2771
  (void)tsnprintf(obj, sizeof(obj), "%d", req.vgId);
79✔
2772

2773
  auditRecord(pReq, pMnode->clusterId, "RedistributeVgroup", "", obj, req.sql, req.sqlLen);
79✔
2774

2775
_OVER:
95✔
2776
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
95✔
2777
    mError("vgId:%d, failed to redistribute to dnode %d:%d:%d since %s", req.vgId, req.dnodeId1, req.dnodeId2,
16!
2778
           req.dnodeId3, tstrerror(code));
2779
  }
2780

2781
  mndReleaseDnode(pMnode, pNew1);
95✔
2782
  mndReleaseDnode(pMnode, pNew2);
95✔
2783
  mndReleaseDnode(pMnode, pNew3);
95✔
2784
  mndReleaseDnode(pMnode, pOld1);
95✔
2785
  mndReleaseDnode(pMnode, pOld2);
95✔
2786
  mndReleaseDnode(pMnode, pOld3);
95✔
2787
  mndReleaseVgroup(pMnode, pVgroup);
95✔
2788
  mndReleaseDb(pMnode, pDb);
95✔
2789
  tFreeSRedistributeVgroupReq(&req);
95✔
2790

2791
  TAOS_RETURN(code);
95✔
2792
}
2793

2794
static void *mndBuildSForceBecomeFollowerReq(SMnode *pMnode, SVgObj *pVgroup, int32_t dnodeId, int32_t *pContLen) {
12✔
2795
  SForceBecomeFollowerReq balanceReq = {
12✔
2796
      .vgId = pVgroup->vgId,
12✔
2797
  };
2798

2799
  int32_t contLen = tSerializeSForceBecomeFollowerReq(NULL, 0, &balanceReq);
12✔
2800
  if (contLen < 0) {
12!
2801
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
2802
    return NULL;
×
2803
  }
2804
  contLen += sizeof(SMsgHead);
12✔
2805

2806
  void *pReq = taosMemoryMalloc(contLen);
12!
2807
  if (pReq == NULL) {
12!
UNCOV
2808
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
2809
    return NULL;
×
2810
  }
2811

2812
  SMsgHead *pHead = pReq;
12✔
2813
  pHead->contLen = htonl(contLen);
12✔
2814
  pHead->vgId = htonl(pVgroup->vgId);
12✔
2815

2816
  if (tSerializeSForceBecomeFollowerReq((char *)pReq + sizeof(SMsgHead), contLen, &balanceReq) < 0) {
12!
UNCOV
2817
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
2818
    taosMemoryFree(pReq);
×
UNCOV
2819
    return NULL;
×
2820
  }
2821
  *pContLen = contLen;
12✔
2822
  return pReq;
12✔
2823
}
2824

2825
int32_t mndAddBalanceVgroupLeaderAction(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup, int32_t dnodeId) {
12✔
2826
  int32_t    code = 0;
12✔
2827
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
12✔
2828
  if (pDnode == NULL) {
12!
UNCOV
2829
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2830
    if (terrno != 0) code = terrno;
×
UNCOV
2831
    TAOS_RETURN(code);
×
2832
  }
2833

2834
  STransAction action = {0};
12✔
2835
  action.epSet = mndGetDnodeEpset(pDnode);
12✔
2836
  mndReleaseDnode(pMnode, pDnode);
12✔
2837

2838
  int32_t contLen = 0;
12✔
2839
  void   *pReq = mndBuildSForceBecomeFollowerReq(pMnode, pVgroup, dnodeId, &contLen);
12✔
2840
  if (pReq == NULL) {
12!
UNCOV
2841
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2842
    if (terrno != 0) code = terrno;
×
UNCOV
2843
    TAOS_RETURN(code);
×
2844
  }
2845

2846
  action.pCont = pReq;
12✔
2847
  action.contLen = contLen;
12✔
2848
  action.msgType = TDMT_SYNC_FORCE_FOLLOWER;
12✔
2849

2850
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
12!
UNCOV
2851
    taosMemoryFree(pReq);
×
UNCOV
2852
    TAOS_RETURN(code);
×
2853
  }
2854

2855
  TAOS_RETURN(code);
12✔
2856
}
2857

2858
int32_t mndAddVgroupBalanceToTrans(SMnode *pMnode, SVgObj *pVgroup, STrans *pTrans) {
14✔
2859
  int32_t code = 0;
14✔
2860
  SSdb   *pSdb = pMnode->pSdb;
14✔
2861

2862
  int32_t vgid = pVgroup->vgId;
14✔
2863
  int8_t  replica = pVgroup->replica;
14✔
2864

2865
  if (pVgroup->replica <= 1) {
14✔
2866
    mInfo("trans:%d, vgid:%d no need to balance, replica:%d", pTrans->id, vgid, replica);
1!
2867
    return -1;
1✔
2868
  }
2869

2870
  int32_t dnodeId = 0;
13✔
2871

2872
  for (int i = 0; i < replica; i++) {
31✔
2873
    if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_LEADER) {
30✔
2874
      dnodeId = pVgroup->vnodeGid[i].dnodeId;
12✔
2875
      break;
12✔
2876
    }
2877
  }
2878

2879
  bool       exist = false;
13✔
2880
  bool       online = false;
13✔
2881
  int64_t    curMs = taosGetTimestampMs();
13✔
2882
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
13✔
2883
  if (pDnode != NULL) {
13✔
2884
    exist = true;
12✔
2885
    online = mndIsDnodeOnline(pDnode, curMs);
12✔
2886
    mndReleaseDnode(pMnode, pDnode);
12✔
2887
  }
2888

2889
  if (exist && online) {
25!
2890
    mInfo("trans:%d, vgid:%d leader to dnode:%d", pTrans->id, vgid, dnodeId);
12!
2891

2892
    if ((code = mndAddBalanceVgroupLeaderAction(pMnode, pTrans, pVgroup, dnodeId)) != 0) {
12!
UNCOV
2893
      mError("trans:%d, vgid:%d failed to be balanced to dnode:%d", pTrans->id, vgid, dnodeId);
×
UNCOV
2894
      TAOS_RETURN(code);
×
2895
    }
2896

2897
    SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName);
12✔
2898
    if (pDb == NULL) {
12!
UNCOV
2899
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2900
      if (terrno != 0) code = terrno;
×
UNCOV
2901
      mError("trans:%d, vgid:%d failed to be balanced to dnode:%d, because db not exist", pTrans->id, vgid, dnodeId);
×
UNCOV
2902
      TAOS_RETURN(code);
×
2903
    }
2904

2905
    mndReleaseDb(pMnode, pDb);
12✔
2906
  } else {
2907
    mInfo("trans:%d, vgid:%d cant be balanced to dnode:%d, exist:%d, online:%d", pTrans->id, vgid, dnodeId, exist,
1!
2908
          online);
2909
  }
2910

2911
  TAOS_RETURN(code);
13✔
2912
}
2913

2914
extern int32_t mndProcessVgroupBalanceLeaderMsgImp(SRpcMsg *pReq);
2915

2916
int32_t mndProcessVgroupBalanceLeaderMsg(SRpcMsg *pReq) { return mndProcessVgroupBalanceLeaderMsgImp(pReq); }
5✔
2917

2918
#ifndef TD_ENTERPRISE
2919
int32_t mndProcessVgroupBalanceLeaderMsgImp(SRpcMsg *pReq) { return 0; }
2920
#endif
2921

2922
static int32_t mndCheckDnodeMemory(SMnode *pMnode, SDbObj *pOldDb, SDbObj *pNewDb, SVgObj *pOldVgroup,
612✔
2923
                                   SVgObj *pNewVgroup, SArray *pArray) {
2924
  for (int32_t i = 0; i < (int32_t)taosArrayGetSize(pArray); ++i) {
1,462✔
2925
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
850✔
2926
    bool       inVgroup = false;
850✔
2927
    int64_t    oldMemUsed = 0;
850✔
2928
    int64_t    newMemUsed = 0;
850✔
2929
    mDebug("db:%s, vgId:%d, check dnode:%d, avail:%" PRId64 " used:%" PRId64, pNewVgroup->dbName, pNewVgroup->vgId,
850✔
2930
           pDnode->id, pDnode->memAvail, pDnode->memUsed);
2931
    for (int32_t j = 0; j < pOldVgroup->replica; ++j) {
2,324✔
2932
      SVnodeGid *pVgId = &pOldVgroup->vnodeGid[j];
1,474✔
2933
      if (pDnode->id == pVgId->dnodeId) {
1,474✔
2934
        oldMemUsed = mndGetVgroupMemory(pMnode, pOldDb, pOldVgroup);
820✔
2935
        inVgroup = true;
820✔
2936
      }
2937
    }
2938
    for (int32_t j = 0; j < pNewVgroup->replica; ++j) {
2,324✔
2939
      SVnodeGid *pVgId = &pNewVgroup->vnodeGid[j];
1,474✔
2940
      if (pDnode->id == pVgId->dnodeId) {
1,474✔
2941
        newMemUsed = mndGetVgroupMemory(pMnode, pNewDb, pNewVgroup);
820✔
2942
        inVgroup = true;
820✔
2943
      }
2944
    }
2945

2946
    mDebug("db:%s, vgId:%d, memory in dnode:%d, oldUsed:%" PRId64 ", newUsed:%" PRId64, pNewVgroup->dbName,
850✔
2947
           pNewVgroup->vgId, pDnode->id, oldMemUsed, newMemUsed);
2948

2949
    pDnode->memUsed = pDnode->memUsed - oldMemUsed + newMemUsed;
850✔
2950
    if (pDnode->memAvail - pDnode->memUsed <= 0) {
850!
UNCOV
2951
      mError("db:%s, vgId:%d, no enough memory in dnode:%d, avail:%" PRId64 " used:%" PRId64, pNewVgroup->dbName,
×
2952
             pNewVgroup->vgId, pDnode->id, pDnode->memAvail, pDnode->memUsed);
UNCOV
2953
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE);
×
2954
    } else if (inVgroup) {
850✔
2955
      mInfo("db:%s, vgId:%d, memory in dnode:%d, avail:%" PRId64 " used:%" PRId64, pNewVgroup->dbName, pNewVgroup->vgId,
820!
2956
            pDnode->id, pDnode->memAvail, pDnode->memUsed);
2957
    } else {
2958
    }
2959
  }
2960
  return 0;
612✔
2961
}
2962

2963
int32_t mndBuildAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pOldDb, SDbObj *pNewDb, SVgObj *pVgroup,
683✔
2964
                                  SArray *pArray, SVgObj *pNewVgroup) {
2965
  int32_t code = 0;
683✔
2966
  memcpy(pNewVgroup, pVgroup, sizeof(SVgObj));
683✔
2967

2968
  if (pVgroup->replica <= 0 || pVgroup->replica == pNewDb->cfg.replications) {
683!
2969
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfigAction(pMnode, pTrans, pNewDb, pVgroup));
612!
2970
    TAOS_CHECK_RETURN(mndCheckDnodeMemory(pMnode, pOldDb, pNewDb, pNewVgroup, pVgroup, pArray));
612!
2971
    return 0;
612✔
2972
  }
2973

2974
  // mndTransSetGroupParallel(pTrans);
2975

2976
  if (pNewDb->cfg.replications == 3) {
71✔
2977
    mInfo("trans:%d, db:%s, vgId:%d, will add 2 vnodes, vn:0 dnode:%d", pTrans->id, pVgroup->dbName, pVgroup->vgId,
67!
2978
          pVgroup->vnodeGid[0].dnodeId);
2979

2980
    // add second
2981
    if (pNewVgroup->replica == 1) {
67!
2982
      TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, pNewVgroup, pArray));
67!
2983
    }
2984

2985
    // learner stage
2986
    pNewVgroup->vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
67✔
2987
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
67✔
2988
    TAOS_CHECK_RETURN(
67!
2989
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
2990

2991
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &pNewVgroup->vnodeGid[1]));
67!
2992

2993
    // follower stage
2994
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
67✔
2995
    TAOS_CHECK_RETURN(mndAddAlterVnodeTypeAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
67!
2996
    TAOS_CHECK_RETURN(
67!
2997
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
2998

2999
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
67!
3000

3001
    // add third
3002
    if (pNewVgroup->replica == 2) {
67!
3003
      TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, pNewVgroup, pArray));
67✔
3004
    }
3005

3006
    pNewVgroup->vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
56✔
3007
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
56✔
3008
    pNewVgroup->vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_VOTER;
56✔
3009
    TAOS_CHECK_RETURN(
56!
3010
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3011
    TAOS_CHECK_RETURN(
56!
3012
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
3013
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &pNewVgroup->vnodeGid[2]));
56!
3014

3015
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
56!
3016
  } else if (pNewDb->cfg.replications == 1) {
4!
3017
    mInfo("trans:%d, db:%s, vgId:%d, will remove 2 vnodes, vn:0 dnode:%d vn:1 dnode:%d vn:2 dnode:%d", pTrans->id,
4!
3018
          pVgroup->dbName, pVgroup->vgId, pVgroup->vnodeGid[0].dnodeId, pVgroup->vnodeGid[1].dnodeId,
3019
          pVgroup->vnodeGid[2].dnodeId);
3020

3021
    SVnodeGid del1 = {0};
4✔
3022
    SVnodeGid del2 = {0};
4✔
3023
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroup(pMnode, pTrans, pNewVgroup, pArray, &del1));
4!
3024
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &del1, true));
4!
3025
    TAOS_CHECK_RETURN(
4!
3026
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3027
    TAOS_CHECK_RETURN(
4!
3028
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
3029
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
4!
3030

3031
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroup(pMnode, pTrans, pNewVgroup, pArray, &del2));
4!
3032
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &del2, true));
4!
3033
    TAOS_CHECK_RETURN(
4!
3034
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3035
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
4!
UNCOV
3036
  } else if (pNewDb->cfg.replications == 2) {
×
UNCOV
3037
    mInfo("trans:%d, db:%s, vgId:%d, will add 1 vnode, vn:0 dnode:%d", pTrans->id, pVgroup->dbName, pVgroup->vgId,
×
3038
          pVgroup->vnodeGid[0].dnodeId);
3039

3040
    // add second
UNCOV
3041
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, pNewVgroup, pArray));
×
3042

3043
    // learner stage
UNCOV
3044
    pNewVgroup->vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3045
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
UNCOV
3046
    TAOS_CHECK_RETURN(
×
3047
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3048

3049
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &pNewVgroup->vnodeGid[1]));
×
3050

3051
    // follower stage
UNCOV
3052
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3053
    TAOS_CHECK_RETURN(mndAddAlterVnodeTypeAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
×
3054
    TAOS_CHECK_RETURN(
×
3055
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3056

UNCOV
3057
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
×
3058
  } else {
3059
    return -1;
×
3060
  }
3061

3062
  mndSortVnodeGid(pNewVgroup);
60✔
3063

3064
  {
3065
    SSdbRaw *pVgRaw = mndVgroupActionEncode(pNewVgroup);
60✔
3066
    if (pVgRaw == NULL) {
60!
UNCOV
3067
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3068
      if (terrno != 0) code = terrno;
×
3069
      TAOS_RETURN(code);
×
3070
    }
3071
    if ((code = mndTransAppendCommitlog(pTrans, pVgRaw)) != 0) {
60!
3072
      sdbFreeRaw(pVgRaw);
×
3073
      TAOS_RETURN(code);
×
3074
    }
3075
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
60✔
3076
    if (code != 0) {
60!
UNCOV
3077
      mError("vgId:%d, failed to set raw status since %s at line:%d", pNewVgroup->vgId, tstrerror(code), __LINE__);
×
3078
      TAOS_RETURN(code);
×
3079
    }
3080
  }
3081

3082
  TAOS_RETURN(code);
60✔
3083
}
3084

UNCOV
3085
int32_t mndBuildRaftAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pOldDb, SDbObj *pNewDb, SVgObj *pVgroup,
×
3086
                                      SArray *pArray) {
UNCOV
3087
  int32_t code = 0;
×
3088
  SVgObj  newVgroup = {0};
×
UNCOV
3089
  memcpy(&newVgroup, pVgroup, sizeof(SVgObj));
×
3090

UNCOV
3091
  if (pVgroup->replica <= 0 || pVgroup->replica == pNewDb->cfg.replications) {
×
UNCOV
3092
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfigAction(pMnode, pTrans, pNewDb, pVgroup));
×
3093
    TAOS_CHECK_RETURN(mndCheckDnodeMemory(pMnode, pOldDb, pNewDb, &newVgroup, pVgroup, pArray));
×
3094
    return 0;
×
3095
  }
3096

UNCOV
3097
  mndTransSetSerial(pTrans);
×
3098

UNCOV
3099
  mInfo("trans:%d, vgId:%d, alter vgroup, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id, pVgroup->vgId,
×
3100
        pVgroup->syncConfChangeVer, pVgroup->version, pVgroup->replica);
3101

UNCOV
3102
  if (newVgroup.replica == 1 && pNewDb->cfg.replications == 3) {
×
3103
    mInfo("db:%s, vgId:%d, will add 2 vnodes, vn:0 dnode:%d", pVgroup->dbName, pVgroup->vgId,
×
3104
          pVgroup->vnodeGid[0].dnodeId);
3105

3106
    // add second
UNCOV
3107
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVgroup, pArray));
×
3108
    // add third
3109
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVgroup, pArray));
×
3110

3111
    // add learner stage
UNCOV
3112
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3113
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
UNCOV
3114
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
UNCOV
3115
    TAOS_CHECK_RETURN(
×
3116
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3117
    mInfo("trans:%d, vgId:%d, add change config, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id,
×
3118
          pVgroup->vgId, newVgroup.syncConfChangeVer, pVgroup->version, pVgroup->replica);
3119
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &newVgroup.vnodeGid[1]));
×
3120
    mInfo("trans:%d, vgId:%d, create vnode, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id, pVgroup->vgId,
×
3121
          newVgroup.syncConfChangeVer, pVgroup->version, pVgroup->replica);
UNCOV
3122
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &newVgroup.vnodeGid[2]));
×
3123
    mInfo("trans:%d, vgId:%d, create vnode, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id, pVgroup->vgId,
×
3124
          newVgroup.syncConfChangeVer, pVgroup->version, pVgroup->replica);
3125

3126
    // check learner
3127
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3128
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3129
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3130
    TAOS_CHECK_RETURN(
×
3131
        mndAddCheckLearnerCatchupAction(pMnode, pTrans, pNewDb, &newVgroup, newVgroup.vnodeGid[1].dnodeId));
UNCOV
3132
    TAOS_CHECK_RETURN(
×
3133
        mndAddCheckLearnerCatchupAction(pMnode, pTrans, pNewDb, &newVgroup, newVgroup.vnodeGid[2].dnodeId));
3134

3135
    // change raft type
3136
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3137
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3138
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3139
    TAOS_CHECK_RETURN(
×
3140
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3141

UNCOV
3142
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
3143

3144
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3145
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3146
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3147
    TAOS_CHECK_RETURN(
×
3148
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3149

3150
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
3151

UNCOV
3152
    SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
×
3153
    if (pVgRaw == NULL) {
×
3154
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3155
      if (terrno != 0) code = terrno;
×
3156
      TAOS_RETURN(code);
×
3157
    }
UNCOV
3158
    if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
×
3159
      sdbFreeRaw(pVgRaw);
×
UNCOV
3160
      TAOS_RETURN(code);
×
3161
    }
UNCOV
3162
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
3163
    if (code != 0) {
×
3164
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
3165
             __LINE__);
3166
      TAOS_RETURN(code);
×
3167
    }
UNCOV
3168
  } else if (newVgroup.replica == 3 && pNewDb->cfg.replications == 1) {
×
3169
    mInfo("db:%s, vgId:%d, will remove 2 vnodes, vn:0 dnode:%d vn:1 dnode:%d vn:2 dnode:%d", pVgroup->dbName,
×
3170
          pVgroup->vgId, pVgroup->vnodeGid[0].dnodeId, pVgroup->vnodeGid[1].dnodeId, pVgroup->vnodeGid[2].dnodeId);
3171

UNCOV
3172
    SVnodeGid del1 = {0};
×
3173
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroupWithoutSave(pMnode, pTrans, &newVgroup, pArray, &del1));
×
3174

3175
    TAOS_CHECK_RETURN(
×
3176
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3177

UNCOV
3178
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
3179

3180
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &del1, true));
×
3181

UNCOV
3182
    SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
×
3183
    if (pVgRaw == NULL) {
×
UNCOV
3184
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3185
      if (terrno != 0) code = terrno;
×
3186
      TAOS_RETURN(code);
×
3187
    }
3188
    if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
×
UNCOV
3189
      sdbFreeRaw(pVgRaw);
×
3190
      TAOS_RETURN(code);
×
3191
    }
3192
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
3193
    if (code != 0) {
×
3194
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
3195
             __LINE__);
3196
      TAOS_RETURN(code);
×
3197
    }
3198

UNCOV
3199
    SVnodeGid del2 = {0};
×
3200
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroupWithoutSave(pMnode, pTrans, &newVgroup, pArray, &del2));
×
3201

3202
    TAOS_CHECK_RETURN(
×
3203
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3204

UNCOV
3205
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
3206

3207
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &del2, true));
×
3208

UNCOV
3209
    pVgRaw = mndVgroupActionEncode(&newVgroup);
×
3210
    if (pVgRaw == NULL) {
×
UNCOV
3211
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3212
      if (terrno != 0) code = terrno;
×
3213
      TAOS_RETURN(code);
×
3214
    }
3215
    if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
×
3216
      sdbFreeRaw(pVgRaw);
×
3217
      TAOS_RETURN(code);
×
3218
    }
3219
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
3220
    if (code != 0) {
×
3221
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
3222
             __LINE__);
3223
      TAOS_RETURN(code);
×
3224
    }
3225
  } else {
UNCOV
3226
    return -1;
×
3227
  }
3228

UNCOV
3229
  mndSortVnodeGid(&newVgroup);
×
3230

3231
  {
UNCOV
3232
    SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
×
UNCOV
3233
    if (pVgRaw == NULL) {
×
UNCOV
3234
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3235
      if (terrno != 0) code = terrno;
×
UNCOV
3236
      TAOS_RETURN(code);
×
3237
    }
UNCOV
3238
    if ((code = mndTransAppendCommitlog(pTrans, pVgRaw)) != 0) {
×
UNCOV
3239
      sdbFreeRaw(pVgRaw);
×
UNCOV
3240
      TAOS_RETURN(code);
×
3241
    }
UNCOV
3242
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
3243
    if (code != 0) {
×
3244
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
3245
             __LINE__);
3246
      TAOS_RETURN(code);
×
3247
    }
3248
  }
3249

3250
  TAOS_RETURN(code);
×
3251
}
3252

3253
int32_t mndBuildRestoreAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *db, SVgObj *pVgroup, SDnodeObj *pDnode,
10✔
3254
                                         SDnodeObj *pAnotherDnode) {
3255
  int32_t code = 0;
10✔
3256
  SVgObj  newVgroup = {0};
10✔
3257
  memcpy(&newVgroup, pVgroup, sizeof(SVgObj));
10✔
3258

3259
  mInfo("trans:%d, db:%s, vgId:%d, restore vnodes, vn:0 dnode:%d", pTrans->id, pVgroup->dbName, pVgroup->vgId,
10!
3260
        pVgroup->vnodeGid[0].dnodeId);
3261

3262
  if (newVgroup.replica == 1) {
10!
3263
    int selected = 0;
×
UNCOV
3264
    for (int i = 0; i < newVgroup.replica; i++) {
×
3265
      newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3266
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
UNCOV
3267
        selected = i;
×
3268
      }
3269
    }
3270
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, db, &newVgroup, &newVgroup.vnodeGid[selected]));
×
3271
  } else if (newVgroup.replica == 2) {
10!
3272
    for (int i = 0; i < newVgroup.replica; i++) {
×
UNCOV
3273
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
UNCOV
3274
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3275
      } else {
3276
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3277
      }
3278
    }
UNCOV
3279
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pAnotherDnode));
×
3280

UNCOV
3281
    for (int i = 0; i < newVgroup.replica; i++) {
×
UNCOV
3282
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
UNCOV
3283
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3284
      } else {
UNCOV
3285
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3286
      }
3287
    }
UNCOV
3288
    TAOS_CHECK_RETURN(mndRestoreAddCreateVnodeAction(pMnode, pTrans, db, &newVgroup, pDnode));
×
3289

UNCOV
3290
    for (int i = 0; i < newVgroup.replica; i++) {
×
UNCOV
3291
      newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3292
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
3293
      }
3294
    }
UNCOV
3295
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pDnode));
×
3296
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pAnotherDnode));
×
3297
  } else if (newVgroup.replica == 3) {
10!
3298
    for (int i = 0; i < newVgroup.replica; i++) {
40✔
3299
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
30✔
3300
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_LEARNER;
10✔
3301
      } else {
3302
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
20✔
3303
      }
3304
    }
3305
    TAOS_CHECK_RETURN(mndRestoreAddCreateVnodeAction(pMnode, pTrans, db, &newVgroup, pDnode));
10!
3306

3307
    for (int i = 0; i < newVgroup.replica; i++) {
40✔
3308
      newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
30✔
3309
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
30✔
3310
      }
3311
    }
3312
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pDnode));
10!
3313
  }
3314
  SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
10✔
3315
  if (pVgRaw == NULL) {
10!
UNCOV
3316
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3317
    if (terrno != 0) code = terrno;
×
UNCOV
3318
    TAOS_RETURN(code);
×
3319
  }
3320
  if ((code = mndTransAppendCommitlog(pTrans, pVgRaw)) != 0) {
10!
UNCOV
3321
    sdbFreeRaw(pVgRaw);
×
UNCOV
3322
    TAOS_RETURN(code);
×
3323
  }
3324
  code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
10✔
3325
  if (code != 0) {
10!
3326
    mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code), __LINE__);
×
UNCOV
3327
    TAOS_RETURN(code);
×
3328
  }
3329

3330
  TAOS_RETURN(code);
10✔
3331
}
3332

UNCOV
3333
static int32_t mndAddAdjustVnodeHashRangeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) {
×
UNCOV
3334
  return 0;
×
3335
}
3336

3337
typedef int32_t (*FpTransActionCb)(STrans *pTrans, SSdbRaw *pRaw);
3338

3339
static int32_t mndAddVgStatusAction(STrans *pTrans, SVgObj *pVg, ESdbStatus vgStatus, ETrnStage stage) {
135✔
3340
  int32_t         code = 0;
135✔
3341
  FpTransActionCb appendActionCb = (stage == TRN_STAGE_COMMIT_ACTION) ? mndTransAppendCommitlog : mndTransAppendRedolog;
135✔
3342
  SSdbRaw        *pRaw = mndVgroupActionEncode(pVg);
135✔
3343
  if (pRaw == NULL) {
135!
UNCOV
3344
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3345
    if (terrno != 0) code = terrno;
×
3346
    goto _err;
×
3347
  }
3348
  if ((code = appendActionCb(pTrans, pRaw)) != 0) goto _err;
135!
3349
  code = sdbSetRawStatus(pRaw, vgStatus);
135✔
3350
  if (code != 0) {
135!
UNCOV
3351
    mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", pVg->vgId, tstrerror(code), __LINE__);
×
UNCOV
3352
    goto _err;
×
3353
  }
3354
  pRaw = NULL;
135✔
3355
  TAOS_RETURN(code);
135✔
UNCOV
3356
_err:
×
UNCOV
3357
  sdbFreeRaw(pRaw);
×
3358
  TAOS_RETURN(code);
×
3359
}
3360

3361
static int32_t mndAddDbStatusAction(STrans *pTrans, SDbObj *pDb, ESdbStatus dbStatus, ETrnStage stage) {
53✔
3362
  int32_t         code = 0;
53✔
3363
  FpTransActionCb appendActionCb = (stage == TRN_STAGE_COMMIT_ACTION) ? mndTransAppendCommitlog : mndTransAppendRedolog;
53✔
3364
  SSdbRaw        *pRaw = mndDbActionEncode(pDb);
53✔
3365
  if (pRaw == NULL) {
53!
UNCOV
3366
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3367
    if (terrno != 0) code = terrno;
×
UNCOV
3368
    goto _err;
×
3369
  }
3370
  if ((code = appendActionCb(pTrans, pRaw)) != 0) goto _err;
53!
3371
  code = sdbSetRawStatus(pRaw, dbStatus);
53✔
3372
  if (code != 0) {
53!
UNCOV
3373
    mError("db:%s, failed to set raw status to ready, error:%s, line:%d", pDb->name, tstrerror(code), __LINE__);
×
3374
    goto _err;
×
3375
  }
3376
  pRaw = NULL;
53✔
3377
  TAOS_RETURN(code);
53✔
UNCOV
3378
_err:
×
UNCOV
3379
  sdbFreeRaw(pRaw);
×
UNCOV
3380
  TAOS_RETURN(code);
×
3381
}
3382

3383
int32_t mndSplitVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SVgObj *pVgroup) {
33✔
3384
  int32_t code = -1;
33✔
3385
  STrans *pTrans = NULL;
33✔
3386
  SDbObj  dbObj = {0};
33✔
3387
  SArray *pArray = mndBuildDnodesArray(pMnode, 0, NULL);
33✔
3388

3389
  int32_t numOfStreams = 0;
33✔
3390
  if ((code = mndGetNumOfStreams(pMnode, pDb->name, &numOfStreams)) != 0) {
33!
UNCOV
3391
    goto _OVER;
×
3392
  }
3393
  if (numOfStreams > 0) {
33!
UNCOV
3394
    code = TSDB_CODE_MND_STREAM_MUST_BE_DELETED;
×
3395
    goto _OVER;
×
3396
  }
3397

3398
#if defined(USE_S3)
3399
  extern int8_t tsS3Enabled;
3400
  if (tsS3Enabled) {
33!
UNCOV
3401
    code = TSDB_CODE_OPS_NOT_SUPPORT;
×
UNCOV
3402
    mError("vgId:%d, db:%s, s3 exists, split vgroup not allowed", pVgroup->vgId, pVgroup->dbName);
×
UNCOV
3403
    goto _OVER;
×
3404
  }
3405
#endif
3406

3407
  if (pDb->cfg.withArbitrator) {
33!
UNCOV
3408
    code = TSDB_CODE_OPS_NOT_SUPPORT;
×
UNCOV
3409
    mError("vgId:%d, db:%s, with arbitrator, split vgroup not allowed", pVgroup->vgId, pVgroup->dbName);
×
UNCOV
3410
    goto _OVER;
×
3411
  }
3412

3413
  pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB, pReq, "split-vgroup");
33✔
3414
  if (pTrans == NULL) {
33!
UNCOV
3415
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3416
    if (terrno != 0) code = terrno;
×
UNCOV
3417
    goto _OVER;
×
3418
  }
3419
  mndTransSetSerial(pTrans);
33✔
3420
  mInfo("trans:%d, used to split vgroup, vgId:%d", pTrans->id, pVgroup->vgId);
33!
3421

3422
  mndTransSetDbName(pTrans, pDb->name, NULL);
33✔
3423
  TAOS_CHECK_GOTO(mndTransCheckConflictWithCompact(pMnode, pTrans), NULL, _OVER);
33✔
3424

3425
  SVgObj newVg1 = {0};
32✔
3426
  memcpy(&newVg1, pVgroup, sizeof(SVgObj));
32✔
3427
  mInfo("vgId:%d, vgroup info before split, replica:%d hashBegin:%u hashEnd:%u", newVg1.vgId, newVg1.replica,
32!
3428
        newVg1.hashBegin, newVg1.hashEnd);
3429
  for (int32_t i = 0; i < newVg1.replica; ++i) {
110✔
3430
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg1.vgId, i, newVg1.vnodeGid[i].dnodeId);
78!
3431
  }
3432

3433
  if (newVg1.replica == 1) {
32✔
3434
    TAOS_CHECK_GOTO(mndAddVnodeToVgroup(pMnode, pTrans, &newVg1, pArray), NULL, _OVER);
9!
3435

3436
    newVg1.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
9✔
3437
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[0].dnodeId), NULL,
9!
3438
                    _OVER);
3439
    TAOS_CHECK_GOTO(mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg1, &newVg1.vnodeGid[1]), NULL, _OVER);
9!
3440

3441
    newVg1.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
9✔
3442
    TAOS_CHECK_GOTO(mndAddAlterVnodeTypeAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[1].dnodeId), NULL, _OVER);
9!
3443
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[0].dnodeId), NULL,
9!
3444
                    _OVER);
3445

3446
    TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg1), NULL, _OVER);
9!
3447
  } else if (newVg1.replica == 3) {
23!
3448
    SVnodeGid del1 = {0};
23✔
3449
    TAOS_CHECK_GOTO(mndRemoveVnodeFromVgroup(pMnode, pTrans, &newVg1, pArray, &del1), NULL, _OVER);
23!
3450
    TAOS_CHECK_GOTO(mndAddDropVnodeAction(pMnode, pTrans, pDb, &newVg1, &del1, true), NULL, _OVER);
23!
3451
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[0].dnodeId), NULL,
23!
3452
                    _OVER);
3453
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[1].dnodeId), NULL,
23!
3454
                    _OVER);
3455
  } else {
UNCOV
3456
    goto _OVER;
×
3457
  }
3458

3459
  for (int32_t i = 0; i < newVg1.replica; ++i) {
96✔
3460
    TAOS_CHECK_GOTO(mndAddDisableVnodeWriteAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[i].dnodeId), NULL,
64!
3461
                    _OVER);
3462
  }
3463
  TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg1), NULL, _OVER);
32!
3464

3465
  SVgObj newVg2 = {0};
32✔
3466
  memcpy(&newVg2, &newVg1, sizeof(SVgObj));
32✔
3467
  newVg1.replica = 1;
32✔
3468
  newVg1.hashEnd = newVg1.hashBegin / 2 + newVg1.hashEnd / 2;
32✔
3469
  memset(&newVg1.vnodeGid[1], 0, sizeof(SVnodeGid));
32✔
3470

3471
  newVg2.replica = 1;
32✔
3472
  newVg2.hashBegin = newVg1.hashEnd + 1;
32✔
3473
  memcpy(&newVg2.vnodeGid[0], &newVg2.vnodeGid[1], sizeof(SVnodeGid));
32✔
3474
  memset(&newVg2.vnodeGid[1], 0, sizeof(SVnodeGid));
32✔
3475

3476
  mInfo("vgId:%d, vgroup info after split, replica:%d hashrange:[%u, %u] vnode:0 dnode:%d", newVg1.vgId, newVg1.replica,
32!
3477
        newVg1.hashBegin, newVg1.hashEnd, newVg1.vnodeGid[0].dnodeId);
3478
  for (int32_t i = 0; i < newVg1.replica; ++i) {
64✔
3479
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg1.vgId, i, newVg1.vnodeGid[i].dnodeId);
32!
3480
  }
3481
  mInfo("vgId:%d, vgroup info after split, replica:%d hashrange:[%u, %u] vnode:0 dnode:%d", newVg2.vgId, newVg2.replica,
32!
3482
        newVg2.hashBegin, newVg2.hashEnd, newVg2.vnodeGid[0].dnodeId);
3483
  for (int32_t i = 0; i < newVg1.replica; ++i) {
64✔
3484
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg2.vgId, i, newVg2.vnodeGid[i].dnodeId);
32!
3485
  }
3486

3487
  // alter vgId and hash range
3488
  int32_t maxVgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP);
32✔
3489
  int32_t srcVgId = newVg1.vgId;
32✔
3490
  newVg1.vgId = maxVgId;
32✔
3491
  TAOS_CHECK_GOTO(mndAddNewVgPrepareAction(pMnode, pTrans, &newVg1), NULL, _OVER);
32!
3492
  TAOS_CHECK_GOTO(mndAddAlterVnodeHashRangeAction(pMnode, pTrans, srcVgId, &newVg1), NULL, _OVER);
32!
3493

3494
  maxVgId++;
32✔
3495
  srcVgId = newVg2.vgId;
32✔
3496
  newVg2.vgId = maxVgId;
32✔
3497
  TAOS_CHECK_GOTO(mndAddNewVgPrepareAction(pMnode, pTrans, &newVg2), NULL, _OVER);
32!
3498
  TAOS_CHECK_GOTO(mndAddAlterVnodeHashRangeAction(pMnode, pTrans, srcVgId, &newVg2), NULL, _OVER);
32!
3499

3500
  TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg1), NULL, _OVER);
32!
3501
  TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg2), NULL, _OVER);
32!
3502

3503
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg1, SDB_STATUS_READY, TRN_STAGE_REDO_ACTION), NULL, _OVER);
32!
3504
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg2, SDB_STATUS_READY, TRN_STAGE_REDO_ACTION), NULL, _OVER);
32!
3505
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, pVgroup, SDB_STATUS_DROPPED, TRN_STAGE_REDO_ACTION), NULL, _OVER);
32!
3506

3507
  // update db status
3508
  memcpy(&dbObj, pDb, sizeof(SDbObj));
32✔
3509
  if (dbObj.cfg.pRetensions != NULL) {
32!
UNCOV
3510
    dbObj.cfg.pRetensions = taosArrayDup(pDb->cfg.pRetensions, NULL);
×
UNCOV
3511
    if (dbObj.cfg.pRetensions == NULL) {
×
UNCOV
3512
      code = terrno;
×
UNCOV
3513
      goto _OVER;
×
3514
    }
3515
  }
3516
  dbObj.vgVersion++;
32✔
3517
  dbObj.updateTime = taosGetTimestampMs();
32✔
3518
  dbObj.cfg.numOfVgroups++;
32✔
3519
  TAOS_CHECK_GOTO(mndAddDbStatusAction(pTrans, &dbObj, SDB_STATUS_READY, TRN_STAGE_REDO_ACTION), NULL, _OVER);
32!
3520

3521
  // adjust vgroup replica
3522
  if (pDb->cfg.replications != newVg1.replica) {
32✔
3523
    SVgObj tmpGroup = {0};
23✔
3524
    TAOS_CHECK_GOTO(mndBuildAlterVgroupAction(pMnode, pTrans, pDb, pDb, &newVg1, pArray, &tmpGroup), NULL, _OVER);
23!
3525
  } else {
3526
    TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg1, SDB_STATUS_READY, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
9!
3527
  }
3528

3529
  if (pDb->cfg.replications != newVg2.replica) {
32✔
3530
    SVgObj tmpGroup = {0};
23✔
3531
    TAOS_CHECK_GOTO(mndBuildAlterVgroupAction(pMnode, pTrans, pDb, pDb, &newVg2, pArray, &tmpGroup), NULL, _OVER);
23✔
3532
  } else {
3533
    TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg2, SDB_STATUS_READY, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
9!
3534
  }
3535

3536
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, pVgroup, SDB_STATUS_DROPPED, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
21!
3537

3538
  // commit db status
3539
  dbObj.vgVersion++;
21✔
3540
  dbObj.updateTime = taosGetTimestampMs();
21✔
3541
  TAOS_CHECK_GOTO(mndAddDbStatusAction(pTrans, &dbObj, SDB_STATUS_READY, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
21!
3542

3543
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
21!
3544
  code = 0;
21✔
3545

3546
_OVER:
33✔
3547
  taosArrayDestroy(pArray);
33✔
3548
  mndTransDrop(pTrans);
33✔
3549
  taosArrayDestroy(dbObj.cfg.pRetensions);
33✔
3550
  TAOS_RETURN(code);
33✔
3551
}
3552

3553
extern int32_t mndProcessSplitVgroupMsgImp(SRpcMsg *pReq);
3554

3555
static int32_t mndProcessSplitVgroupMsg(SRpcMsg *pReq) { return mndProcessSplitVgroupMsgImp(pReq); }
33✔
3556

3557
#ifndef TD_ENTERPRISE
3558
int32_t mndProcessSplitVgroupMsgImp(SRpcMsg *pReq) { return 0; }
3559
#endif
3560

3561
static int32_t mndSetBalanceVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
24✔
3562
                                              SDnodeObj *pSrc, SDnodeObj *pDst) {
3563
  int32_t code = 0;
24✔
3564
  SVgObj  newVg = {0};
24✔
3565
  memcpy(&newVg, pVgroup, sizeof(SVgObj));
24✔
3566
  mInfo("vgId:%d, vgroup info before balance, replica:%d", newVg.vgId, newVg.replica);
24!
3567
  for (int32_t i = 0; i < newVg.replica; ++i) {
68✔
3568
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
44!
3569
  }
3570

3571
  TAOS_CHECK_RETURN(mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pDst->id));
24!
3572
  TAOS_CHECK_RETURN(mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pSrc->id));
24!
3573

3574
  {
3575
    SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
24✔
3576
    if (pRaw == NULL) {
24!
UNCOV
3577
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3578
      if (terrno != 0) code = terrno;
×
UNCOV
3579
      TAOS_RETURN(code);
×
3580
    }
3581
    if ((code = mndTransAppendCommitlog(pTrans, pRaw)) != 0) {
24!
UNCOV
3582
      sdbFreeRaw(pRaw);
×
UNCOV
3583
      TAOS_RETURN(code);
×
3584
    }
3585
    code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
24✔
3586
    if (code != 0) {
24!
UNCOV
3587
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
UNCOV
3588
      TAOS_RETURN(code);
×
3589
    }
3590
  }
3591

3592
  mInfo("vgId:%d, vgroup info after balance, replica:%d", newVg.vgId, newVg.replica);
24!
3593
  for (int32_t i = 0; i < newVg.replica; ++i) {
68✔
3594
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
44!
3595
  }
3596
  TAOS_RETURN(code);
24✔
3597
}
3598

3599
static int32_t mndBalanceVgroupBetweenDnode(SMnode *pMnode, STrans *pTrans, SDnodeObj *pSrc, SDnodeObj *pDst,
24✔
3600
                                            SHashObj *pBalancedVgroups) {
3601
  void   *pIter = NULL;
24✔
3602
  int32_t code = -1;
24✔
3603
  SSdb   *pSdb = pMnode->pSdb;
24✔
3604

3605
  while (1) {
16✔
3606
    SVgObj *pVgroup = NULL;
40✔
3607
    pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
40✔
3608
    if (pIter == NULL) break;
40!
3609
    if (taosHashGet(pBalancedVgroups, &pVgroup->vgId, sizeof(int32_t)) != NULL) {
40✔
3610
      sdbRelease(pSdb, pVgroup);
15✔
3611
      continue;
16✔
3612
    }
3613

3614
    bool existInSrc = false;
25✔
3615
    bool existInDst = false;
25✔
3616
    for (int32_t i = 0; i < pVgroup->replica; ++i) {
70✔
3617
      SVnodeGid *pGid = &pVgroup->vnodeGid[i];
45✔
3618
      if (pGid->dnodeId == pSrc->id) existInSrc = true;
45✔
3619
      if (pGid->dnodeId == pDst->id) existInDst = true;
45!
3620
    }
3621

3622
    if (!existInSrc || existInDst) {
25!
3623
      sdbRelease(pSdb, pVgroup);
1✔
3624
      continue;
1✔
3625
    }
3626

3627
    SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName);
24✔
3628
    if (pDb == NULL) {
24!
UNCOV
3629
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3630
      if (terrno != 0) code = terrno;
×
UNCOV
3631
      mError("vgId:%d, balance vgroup can't find db obj dbName:%s", pVgroup->vgId, pVgroup->dbName);
×
UNCOV
3632
      goto _OUT;
×
3633
    }
3634

3635
    if (pDb->cfg.withArbitrator) {
24!
UNCOV
3636
      mInfo("vgId:%d, db:%s, with arbitrator, balance vgroup not allowed", pVgroup->vgId, pVgroup->dbName);
×
UNCOV
3637
      goto _OUT;
×
3638
    }
3639

3640
    code = mndSetBalanceVgroupInfoToTrans(pMnode, pTrans, pDb, pVgroup, pSrc, pDst);
24✔
3641
    if (code == 0) {
24!
3642
      code = taosHashPut(pBalancedVgroups, &pVgroup->vgId, sizeof(int32_t), &pVgroup->vgId, sizeof(int32_t));
24✔
3643
    }
3644

UNCOV
3645
  _OUT:
×
3646
    mndReleaseDb(pMnode, pDb);
24✔
3647
    sdbRelease(pSdb, pVgroup);
24✔
3648
    sdbCancelFetch(pSdb, pIter);
24✔
3649
    break;
24✔
3650
  }
3651

3652
  return code;
24✔
3653
}
3654

3655
static int32_t mndBalanceVgroup(SMnode *pMnode, SRpcMsg *pReq, SArray *pArray) {
16✔
3656
  int32_t   code = -1;
16✔
3657
  int32_t   numOfVgroups = 0;
16✔
3658
  STrans   *pTrans = NULL;
16✔
3659
  SHashObj *pBalancedVgroups = NULL;
16✔
3660

3661
  pBalancedVgroups = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
16✔
3662
  if (pBalancedVgroups == NULL) goto _OVER;
16!
3663

3664
  pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_GLOBAL, pReq, "balance-vgroup");
16✔
3665
  if (pTrans == NULL) {
16!
UNCOV
3666
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3667
    if (terrno != 0) code = terrno;
×
UNCOV
3668
    goto _OVER;
×
3669
  }
3670
  mndTransSetSerial(pTrans);
16✔
3671
  mInfo("trans:%d, used to balance vgroup", pTrans->id);
16!
3672
  TAOS_CHECK_GOTO(mndTransCheckConflict(pMnode, pTrans), NULL, _OVER);
16!
3673
  TAOS_CHECK_GOTO(mndTransCheckConflictWithCompact(pMnode, pTrans), NULL, _OVER);
16✔
3674

3675
  while (1) {
24✔
3676
    taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
39✔
3677
    for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
169✔
3678
      SDnodeObj *pDnode = taosArrayGet(pArray, i);
130✔
3679
      mInfo("dnode:%d, equivalent vnodes:%d others:%d support:%d, score:%f", pDnode->id, pDnode->numOfVnodes,
130!
3680
            pDnode->numOfSupportVnodes, pDnode->numOfOtherNodes, mndGetDnodeScore(pDnode, 0, 1));
3681
    }
3682

3683
    SDnodeObj *pSrc = taosArrayGet(pArray, taosArrayGetSize(pArray) - 1);
39✔
3684
    SDnodeObj *pDst = taosArrayGet(pArray, 0);
39✔
3685

3686
    float srcScore = mndGetDnodeScore(pSrc, -1, 1);
39✔
3687
    float dstScore = mndGetDnodeScore(pDst, 1, 1);
39✔
3688
    mInfo("trans:%d, after balance, src dnode:%d score:%f, dst dnode:%d score:%f", pTrans->id, pSrc->id, dstScore,
39!
3689
          pDst->id, dstScore);
3690

3691
    if (srcScore > dstScore - 0.000001) {
39✔
3692
      code = mndBalanceVgroupBetweenDnode(pMnode, pTrans, pSrc, pDst, pBalancedVgroups);
24✔
3693
      if (code == 0) {
24!
3694
        pSrc->numOfVnodes--;
24✔
3695
        pDst->numOfVnodes++;
24✔
3696
        numOfVgroups++;
24✔
3697
        continue;
24✔
3698
      } else {
UNCOV
3699
        mInfo("trans:%d, no vgroup need to balance from dnode:%d to dnode:%d", pTrans->id, pSrc->id, pDst->id);
×
UNCOV
3700
        break;
×
3701
      }
3702
    } else {
3703
      mInfo("trans:%d, no vgroup need to balance any more", pTrans->id);
15!
3704
      break;
15✔
3705
    }
3706
  }
3707

3708
  if (numOfVgroups <= 0) {
15✔
3709
    mInfo("no need to balance vgroup");
1!
3710
    code = 0;
1✔
3711
  } else {
3712
    mInfo("start to balance vgroup, numOfVgroups:%d", numOfVgroups);
14!
3713
    if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER;
14!
3714
    code = TSDB_CODE_ACTION_IN_PROGRESS;
14✔
3715
  }
3716

3717
_OVER:
16✔
3718
  taosHashCleanup(pBalancedVgroups);
16✔
3719
  mndTransDrop(pTrans);
16✔
3720
  TAOS_RETURN(code);
16✔
3721
}
3722

3723
static int32_t mndProcessBalanceVgroupMsg(SRpcMsg *pReq) {
19✔
3724
  SMnode *pMnode = pReq->info.node;
19✔
3725
  int32_t code = -1;
19✔
3726
  SArray *pArray = NULL;
19✔
3727
  void   *pIter = NULL;
19✔
3728
  int64_t curMs = taosGetTimestampMs();
19✔
3729

3730
  SBalanceVgroupReq req = {0};
19✔
3731
  if (tDeserializeSBalanceVgroupReq(pReq->pCont, pReq->contLen, &req) != 0) {
19!
UNCOV
3732
    code = TSDB_CODE_INVALID_MSG;
×
UNCOV
3733
    goto _OVER;
×
3734
  }
3735

3736
  mInfo("start to balance vgroup");
19!
3737
  if ((code = mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_BALANCE_VGROUP)) != 0) {
19✔
3738
    goto _OVER;
1✔
3739
  }
3740

3741
  while (1) {
56✔
3742
    SDnodeObj *pDnode = NULL;
74✔
3743
    pIter = sdbFetch(pMnode->pSdb, SDB_DNODE, pIter, (void **)&pDnode);
74✔
3744
    if (pIter == NULL) break;
74✔
3745
    if (!mndIsDnodeOnline(pDnode, curMs)) {
57✔
3746
      sdbCancelFetch(pMnode->pSdb, pIter);
1✔
3747
      code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
1✔
3748
      mError("failed to balance vgroup since %s, dnode:%d", terrstr(), pDnode->id);
1!
3749
      sdbRelease(pMnode->pSdb, pDnode);
1✔
3750
      goto _OVER;
1✔
3751
    }
3752

3753
    sdbRelease(pMnode->pSdb, pDnode);
56✔
3754
  }
3755

3756
  pArray = mndBuildDnodesArray(pMnode, 0, NULL);
17✔
3757
  if (pArray == NULL) {
17!
UNCOV
3758
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3759
    if (terrno != 0) code = terrno;
×
UNCOV
3760
    goto _OVER;
×
3761
  }
3762

3763
  if (taosArrayGetSize(pArray) < 2) {
17✔
3764
    mInfo("no need to balance vgroup since dnode num less than 2");
1!
3765
    code = 0;
1✔
3766
  } else {
3767
    code = mndBalanceVgroup(pMnode, pReq, pArray);
16✔
3768
  }
3769

3770
  auditRecord(pReq, pMnode->clusterId, "balanceVgroup", "", "", req.sql, req.sqlLen);
17✔
3771

3772
_OVER:
19✔
3773
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
19✔
3774
    mError("failed to balance vgroup since %s", tstrerror(code));
3!
3775
  }
3776

3777
  taosArrayDestroy(pArray);
19✔
3778
  tFreeSBalanceVgroupReq(&req);
19✔
3779
  TAOS_RETURN(code);
19✔
3780
}
3781

3782
bool mndVgroupInDb(SVgObj *pVgroup, int64_t dbUid) { return !pVgroup->isTsma && pVgroup->dbUid == dbUid; }
90,358,039!
3783

3784
bool mndVgroupInDnode(SVgObj *pVgroup, int32_t dnodeId) {
16✔
3785
  for (int i = 0; i < pVgroup->replica; i++) {
42✔
3786
    if (pVgroup->vnodeGid[i].dnodeId == dnodeId) return true;
36✔
3787
  }
3788
  return false;
6✔
3789
}
3790

3791
static void *mndBuildCompactVnodeReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen, int64_t compactTs,
28✔
3792
                                     STimeWindow tw, bool metaOnly) {
3793
  SCompactVnodeReq compactReq = {0};
28✔
3794
  compactReq.dbUid = pDb->uid;
28✔
3795
  compactReq.compactStartTime = compactTs;
28✔
3796
  compactReq.tw = tw;
28✔
3797
  compactReq.metaOnly = metaOnly;
28✔
3798
  tstrncpy(compactReq.db, pDb->name, TSDB_DB_FNAME_LEN);
28✔
3799

3800
  mInfo("vgId:%d, build compact vnode config req", pVgroup->vgId);
28!
3801
  int32_t contLen = tSerializeSCompactVnodeReq(NULL, 0, &compactReq);
28✔
3802
  if (contLen < 0) {
28!
UNCOV
3803
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
3804
    return NULL;
×
3805
  }
3806
  contLen += sizeof(SMsgHead);
28✔
3807

3808
  void *pReq = taosMemoryMalloc(contLen);
28!
3809
  if (pReq == NULL) {
28!
UNCOV
3810
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
3811
    return NULL;
×
3812
  }
3813

3814
  SMsgHead *pHead = pReq;
28✔
3815
  pHead->contLen = htonl(contLen);
28✔
3816
  pHead->vgId = htonl(pVgroup->vgId);
28✔
3817

3818
  if (tSerializeSCompactVnodeReq((char *)pReq + sizeof(SMsgHead), contLen, &compactReq) < 0) {
28!
UNCOV
3819
    taosMemoryFree(pReq);
×
UNCOV
3820
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
3821
    return NULL;
×
3822
  }
3823
  *pContLen = contLen;
28✔
3824
  return pReq;
28✔
3825
}
3826

3827
static int32_t mndAddCompactVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int64_t compactTs,
28✔
3828
                                        STimeWindow tw, bool metaOnly) {
3829
  int32_t      code = 0;
28✔
3830
  STransAction action = {0};
28✔
3831
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
28✔
3832

3833
  int32_t contLen = 0;
28✔
3834
  void   *pReq = mndBuildCompactVnodeReq(pMnode, pDb, pVgroup, &contLen, compactTs, tw, metaOnly);
28✔
3835
  if (pReq == NULL) {
28!
UNCOV
3836
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3837
    if (terrno != 0) code = terrno;
×
UNCOV
3838
    TAOS_RETURN(code);
×
3839
  }
3840

3841
  action.pCont = pReq;
28✔
3842
  action.contLen = contLen;
28✔
3843
  action.msgType = TDMT_VND_COMPACT;
28✔
3844

3845
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
28!
UNCOV
3846
    taosMemoryFree(pReq);
×
UNCOV
3847
    TAOS_RETURN(code);
×
3848
  }
3849

3850
  TAOS_RETURN(code);
28✔
3851
}
3852

3853
int32_t mndBuildCompactVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int64_t compactTs,
28✔
3854
                                    STimeWindow tw, bool metaOnly) {
3855
  TAOS_CHECK_RETURN(mndAddCompactVnodeAction(pMnode, pTrans, pDb, pVgroup, compactTs, tw, metaOnly));
28!
3856
  return 0;
28✔
3857
}
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