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

taosdata / TDengine / #4041

09 May 2025 07:58AM UTC coverage: 62.508% (-0.3%) from 62.788%
#4041

push

travis-ci

web-flow
enh: update database fetch functions to include status in JSON output (#31005)

155567 of 317611 branches covered (48.98%)

Branch coverage included in aggregate %.

15 of 18 new or added lines in 1 file covered. (83.33%)

3906 existing lines in 185 files now uncovered.

240901 of 316655 relevant lines covered (76.08%)

6304979.72 hits per line

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

59.15
/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) {
1,981✔
51
  SSdbTable table = {
1,981✔
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);
1,981✔
63
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_REPLICA_RSP, mndTransProcessRsp);
1,981✔
64
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_CONFIG_RSP, mndTransProcessRsp);
1,981✔
65
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_CONFIRM_RSP, mndTransProcessRsp);
1,981✔
66
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_HASHRANGE_RSP, mndTransProcessRsp);
1,981✔
67
  mndSetMsgHandle(pMnode, TDMT_DND_DROP_VNODE_RSP, mndTransProcessRsp);
1,981✔
68
  mndSetMsgHandle(pMnode, TDMT_VND_COMPACT_RSP, mndTransProcessRsp);
1,981✔
69
  mndSetMsgHandle(pMnode, TDMT_VND_DISABLE_WRITE_RSP, mndTransProcessRsp);
1,981✔
70
  mndSetMsgHandle(pMnode, TDMT_SYNC_FORCE_FOLLOWER_RSP, mndTransProcessRsp);
1,981✔
71
  mndSetMsgHandle(pMnode, TDMT_DND_ALTER_VNODE_TYPE_RSP, mndTransProcessRsp);
1,981✔
72
  mndSetMsgHandle(pMnode, TDMT_DND_CHECK_VNODE_LEARNER_CATCHUP_RSP, mndTransProcessRsp);
1,981✔
73
  mndSetMsgHandle(pMnode, TDMT_SYNC_CONFIG_CHANGE_RSP, mndTransProcessRsp);
1,981✔
74

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

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

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

89
void mndCleanupVgroup(SMnode *pMnode) {}
1,980✔
90

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

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

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

118
  terrno = 0;
36,449✔
119

120
_OVER:
36,449✔
121
  if (terrno != 0) {
36,449!
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);
36,449✔
128
  return pRaw;
36,449✔
129
}
130

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

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

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

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

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

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

174
  SDB_GET_RESERVE(pRaw, dataPos, VGROUP_RESERVE_SIZE, _OVER)
32,365!
175

176
  terrno = 0;
32,365✔
177

178
_OVER:
32,365✔
179
  if (terrno != 0) {
32,365!
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);
32,365✔
186
  return pRow;
32,365✔
187
}
188

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

195
  pRow = mndVgroupActionDecode(pRaw);
9,189✔
196
  if (pRow == NULL) {
9,189!
197
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
198
    if (terrno != 0) code = terrno;
×
199
    goto _OVER;
×
200
  }
201
  pVgroup = sdbGetRowObj(pRow);
9,189✔
202
  if (pVgroup == NULL) {
9,189!
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);
9,189✔
209
  if (maxVgId > pVgroup->vgId) {
9,189!
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;
9,189✔
215
_OVER:
9,189✔
216
  if (pVgroup) mndVgroupActionDelete(pSdb, pVgroup);
9,189!
217
  taosMemoryFreeClear(pRow);
9,189!
218
  TAOS_RETURN(code);
9,189✔
219
}
220

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

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

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

263
SVgObj *mndAcquireVgroup(SMnode *pMnode, int32_t vgId) {
951,187✔
264
  SSdb   *pSdb = pMnode->pSdb;
951,187✔
265
  SVgObj *pVgroup = sdbAcquire(pSdb, SDB_VGROUP, &vgId);
951,187✔
266
  if (pVgroup == NULL && terrno == TSDB_CODE_SDB_OBJ_NOT_THERE) {
951,187✔
267
    terrno = TSDB_CODE_MND_VGROUP_NOT_EXIST;
725,932✔
268
  }
269
  return pVgroup;
951,187✔
270
}
271

272
void mndReleaseVgroup(SMnode *pMnode, SVgObj *pVgroup) {
226,020✔
273
  SSdb *pSdb = pMnode->pSdb;
226,020✔
274
  sdbRelease(pSdb, pVgroup);
226,020✔
275
}
226,020✔
276

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

327
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
21,798✔
328
    SReplica *pReplica = NULL;
12,314✔
329

330
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
12,314✔
331
      pReplica = &createReq.replicas[createReq.replica];
12,132✔
332
    } else {
333
      pReplica = &createReq.learnerReplicas[createReq.learnerReplica];
182✔
334
    }
335

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

342
    pReplica->id = pVgidDnode->id;
12,314✔
343
    pReplica->port = pVgidDnode->port;
12,314✔
344
    memcpy(pReplica->fqdn, pVgidDnode->fqdn, TSDB_FQDN_LEN);
12,314✔
345
    mndReleaseDnode(pMnode, pVgidDnode);
12,314✔
346

347
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
12,314✔
348
      if (pDnode->id == pVgid->dnodeId) {
12,132✔
349
        createReq.selfIndex = createReq.replica;
9,302✔
350
      }
351
    } else {
352
      if (pDnode->id == pVgid->dnodeId) {
182!
353
        createReq.learnerSelfIndex = createReq.learnerReplica;
182✔
354
      }
355
    }
356

357
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
12,314✔
358
      createReq.replica++;
12,132✔
359
    } else {
360
      createReq.learnerReplica++;
182✔
361
    }
362
  }
363

364
  if (createReq.selfIndex == -1 && createReq.learnerSelfIndex == -1) {
9,484!
365
    terrno = TSDB_CODE_APP_ERROR;
×
366
    return NULL;
×
367
  }
368

369
  createReq.changeVersion = pVgroup->syncConfChangeVer;
9,484✔
370

371
  mInfo(
9,484!
372
      "vgId:%d, build create vnode req, replica:%d selfIndex:%d learnerReplica:%d learnerSelfIndex:%d strict:%d "
373
      "changeVersion:%d",
374
      createReq.vgId, createReq.replica, createReq.selfIndex, createReq.learnerReplica, createReq.learnerSelfIndex,
375
      createReq.strict, createReq.changeVersion);
376
  for (int32_t i = 0; i < createReq.replica; ++i) {
21,616✔
377
    mInfo("vgId:%d, replica:%d ep:%s:%u", createReq.vgId, i, createReq.replicas[i].fqdn, createReq.replicas[i].port);
12,132!
378
  }
379
  for (int32_t i = 0; i < createReq.learnerReplica; ++i) {
9,666✔
380
    mInfo("vgId:%d, replica:%d ep:%s:%u", createReq.vgId, i, createReq.learnerReplicas[i].fqdn,
182!
381
          createReq.learnerReplicas[i].port);
382
  }
383

384
  int32_t contLen = tSerializeSCreateVnodeReq(NULL, 0, &createReq);
9,484✔
385
  if (contLen < 0) {
9,484!
386
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
387
    return NULL;
×
388
  }
389

390
  void *pReq = taosMemoryMalloc(contLen);
9,484!
391
  if (pReq == NULL) {
9,484!
392
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
393
    return NULL;
×
394
  }
395

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

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

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

438
  void *pReq = taosMemoryMalloc(contLen);
368!
439
  if (pReq == NULL) {
368!
440
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
441
    return NULL;
×
442
  }
443

444
  SMsgHead *pHead = pReq;
368✔
445
  pHead->contLen = htonl(contLen);
368✔
446
  pHead->vgId = htonl(pVgroup->vgId);
368✔
447

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

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

470
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
5,456✔
471
    SReplica *pReplica = NULL;
4,111✔
472

473
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
4,111✔
474
      pReplica = &alterReq.replicas[alterReq.replica];
3,795✔
475
      alterReq.replica++;
3,795✔
476
    } else {
477
      pReplica = &alterReq.learnerReplicas[alterReq.learnerReplica];
316✔
478
      alterReq.learnerReplica++;
316✔
479
    }
480

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

485
    pReplica->id = pVgidDnode->id;
4,111✔
486
    pReplica->port = pVgidDnode->port;
4,111✔
487
    memcpy(pReplica->fqdn, pVgidDnode->fqdn, TSDB_FQDN_LEN);
4,111✔
488
    mndReleaseDnode(pMnode, pVgidDnode);
4,111✔
489

490
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
4,111✔
491
      if (dnodeId == pVgid->dnodeId) {
3,795✔
492
        alterReq.selfIndex = v;
1,345✔
493
      }
494
    } else {
495
      if (dnodeId == pVgid->dnodeId) {
316!
496
        alterReq.learnerSelfIndex = v;
×
497
      }
498
    }
499
  }
500

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

632
  void *pReq = taosMemoryMalloc(contLen);
52!
633
  if (pReq == NULL) {
52!
634
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
635
    return NULL;
×
636
  }
637

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

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

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

665
  void *pReq = taosMemoryMalloc(contLen);
52!
666
  if (pReq == NULL) {
52!
667
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
668
    return NULL;
×
669
  }
670

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

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

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

695
  void *pReq = taosMemoryMalloc(contLen);
12,768!
696
  if (pReq == NULL) {
12,768!
697
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
698
    return NULL;
×
699
  }
700

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

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

718
static bool mndBuildDnodesArrayFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
5,821✔
719
  SDnodeObj *pDnode = pObj;
5,821✔
720
  SArray    *pArray = p1;
5,821✔
721
  int32_t    exceptDnodeId = *(int32_t *)p2;
5,821✔
722
  SArray    *dnodeList = p3;
5,821✔
723

724
  if (exceptDnodeId == pDnode->id) {
5,821✔
725
    return true;
16✔
726
  }
727

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

746
  int64_t curMs = taosGetTimestampMs();
5,751✔
747
  bool    online = mndIsDnodeOnline(pDnode, curMs);
5,751✔
748
  bool    isMnode = mndIsMnode(pMnode, pDnode->id);
5,751✔
749
  pDnode->numOfVnodes = mndGetVnodesNum(pMnode, pDnode->id);
5,751✔
750
  pDnode->memUsed = mndGetVnodesMemory(pMnode, pDnode->id);
5,751✔
751

752
  mInfo("dnode:%d, vnodes:%d supportVnodes:%d isMnode:%d online:%d memory avail:%" PRId64 " used:%" PRId64, pDnode->id,
5,751!
753
        pDnode->numOfVnodes, pDnode->numOfSupportVnodes, isMnode, online, pDnode->memAvail, pDnode->memUsed);
754

755
  if (isMnode) {
5,751✔
756
    pDnode->numOfOtherNodes++;
4,722✔
757
  }
758

759
  if (online && pDnode->numOfSupportVnodes > 0) {
5,751✔
760
    if (taosArrayPush(pArray, pDnode) == NULL) return false;
5,098!
761
  }
762
  return true;
5,751✔
763
}
764

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

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

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

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

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

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

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

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

825
  sdbTraverse(pSdb, SDB_DNODE, mndResetDnodesArrayFp, NULL, NULL, NULL);
2✔
826
  sdbTraverse(pSdb, SDB_DNODE, mndBuildDnodesListFp, pArray, NULL, NULL);
2✔
827

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

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

869
  TAOS_RETURN(code);
2✔
870
}
871
#endif
872

873
SArray *mndBuildDnodesArray(SMnode *pMnode, int32_t exceptDnodeId, SArray *dnodeList) {
4,453✔
874
  SSdb   *pSdb = pMnode->pSdb;
4,453✔
875
  int32_t numOfDnodes = mndGetDnodeSize(pMnode);
4,453✔
876
  SArray *tDnodeList = NULL;
4,453✔
877
  SArray *pDnodeList = NULL;
4,453✔
878

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

896
  mDebug("build %d dnodes array", (int32_t)taosArrayGetSize(pArray));
4,453✔
897
  for (int32_t i = 0; i < (int32_t)taosArrayGetSize(pArray); ++i) {
9,551✔
898
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
5,098✔
899
    mDebug("dnode:%d, vnodes:%d others:%d", pDnode->id, pDnode->numOfVnodes, pDnode->numOfOtherNodes);
5,098✔
900
  }
901
  taosArrayDestroy(pDnodeList);
4,453✔
902
  return pArray;
4,453✔
903
}
904

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

912
static float mndGetDnodeScore(SDnodeObj *pDnode, int32_t additionDnodes, float ratio) {
19,319✔
913
  float totalDnodes = pDnode->numOfVnodes + (float)pDnode->numOfOtherNodes * ratio + additionDnodes;
19,319✔
914
  return totalDnodes / pDnode->numOfSupportVnodes;
19,319✔
915
}
916

917
static int32_t mndCompareDnodeVnodes(SDnodeObj *pDnode1, SDnodeObj *pDnode2) {
4,436✔
918
  float d1Score = mndGetDnodeScore(pDnode1, 0, 0.9);
4,436✔
919
  float d2Score = mndGetDnodeScore(pDnode2, 0, 0.9);
4,436✔
920
  if (d1Score == d2Score) {
4,436✔
921
    return 0;
1,583✔
922
  }
923
  return d1Score > d2Score ? 1 : -1;
2,853✔
924
}
925

926
void mndSortVnodeGid(SVgObj *pVgroup) {
8,511✔
927
  for (int32_t i = 0; i < pVgroup->replica; ++i) {
17,921✔
928
    for (int32_t j = 0; j < pVgroup->replica - 1 - i; ++j) {
10,755✔
929
      if (pVgroup->vnodeGid[j].dnodeId > pVgroup->vnodeGid[j + 1].dnodeId) {
1,345✔
930
        TSWAP(pVgroup->vnodeGid[j], pVgroup->vnodeGid[j + 1]);
503✔
931
      }
932
    }
933
  }
934
}
8,511✔
935

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

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

951
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
17,725✔
952
    SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
9,265✔
953
    SDnodeObj *pDnode = taosArrayGet(pArray, v);
9,265✔
954
    if (pDnode == NULL) {
9,265!
UNCOV
955
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_DNODES);
×
956
    }
957
    if (pDnode->numOfVnodes >= pDnode->numOfSupportVnodes) {
9,265!
UNCOV
958
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_VNODES);
×
959
    }
960

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

970
    pVgid->dnodeId = pDnode->id;
9,265✔
971
    if (pVgroup->replica == 1) {
9,265✔
972
      pVgid->syncState = TAOS_SYNC_STATE_LEADER;
8,054✔
973
    } else {
974
      pVgid->syncState = TAOS_SYNC_STATE_FOLLOWER;
1,211✔
975
    }
976

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

982
  mndSortVnodeGid(pVgroup);
8,460✔
983
  return 0;
8,460✔
984
}
985

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

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

UNCOV
1004
  if (mndGetAvailableDnode(pMnode, pDb, pVgroup, pArray) != 0) return -1;
×
UNCOV
1005
  taosArrayDestroy(pArray);
×
1006

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

1011
int32_t mndAllocVgroup(SMnode *pMnode, SDbObj *pDb, SVgObj **ppVgroups, SArray *dnodeList) {
4,279✔
1012
  int32_t code = -1;
4,279✔
1013
  SArray *pArray = NULL;
4,279✔
1014
  SVgObj *pVgroups = NULL;
4,279✔
1015

1016
  pVgroups = taosMemoryCalloc(pDb->cfg.numOfVgroups, sizeof(SVgObj));
4,279!
1017
  if (pVgroups == NULL) {
4,279!
UNCOV
1018
    code = terrno;
×
UNCOV
1019
    goto _OVER;
×
1020
  }
1021

1022
  pArray = mndBuildDnodesArray(pMnode, 0, dnodeList);
4,279✔
1023
  if (pArray == NULL) {
4,279!
UNCOV
1024
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1025
    if (terrno != 0) code = terrno;
×
UNCOV
1026
    goto _OVER;
×
1027
  }
1028

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

1032
  int32_t  allocedVgroups = 0;
4,279✔
1033
  int32_t  maxVgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP);
4,279✔
1034
  uint32_t hashMin = 0;
4,279✔
1035
  uint32_t hashMax = UINT32_MAX;
4,279✔
1036
  uint32_t hashInterval = (hashMax - hashMin) / pDb->cfg.numOfVgroups;
4,279✔
1037

1038
  if (maxVgId < 2) maxVgId = 2;
4,279✔
1039

1040
  for (uint32_t v = 0; v < pDb->cfg.numOfVgroups; v++) {
12,739✔
1041
    SVgObj *pVgroup = &pVgroups[v];
8,932✔
1042
    pVgroup->vgId = maxVgId++;
8,932✔
1043
    pVgroup->createdTime = taosGetTimestampMs();
8,932✔
1044
    pVgroup->updateTime = pVgroups->createdTime;
8,932✔
1045
    pVgroup->version = 1;
8,932✔
1046
    pVgroup->hashBegin = hashMin + hashInterval * v;
8,932✔
1047
    if (v == pDb->cfg.numOfVgroups - 1) {
8,932✔
1048
      pVgroup->hashEnd = hashMax;
3,912✔
1049
    } else {
1050
      pVgroup->hashEnd = hashMin + hashInterval * (v + 1) - 1;
5,020✔
1051
    }
1052

1053
    memcpy(pVgroup->dbName, pDb->name, TSDB_DB_FNAME_LEN);
8,932✔
1054
    pVgroup->dbUid = pDb->uid;
8,932✔
1055
    pVgroup->replica = pDb->cfg.replications;
8,932✔
1056

1057
    if ((code = mndGetAvailableDnode(pMnode, pDb, pVgroup, pArray)) != 0) {
8,932✔
1058
      goto _OVER;
472✔
1059
    }
1060

1061
    allocedVgroups++;
8,460✔
1062
  }
1063

1064
  *ppVgroups = pVgroups;
3,807✔
1065
  code = 0;
3,807✔
1066

1067
  mInfo("db:%s, total %d vgroups is alloced, replica:%d", pDb->name, pDb->cfg.numOfVgroups, pDb->cfg.replications);
3,807!
1068

UNCOV
1069
_OVER:
×
1070
  if (code != 0) taosMemoryFree(pVgroups);
4,279!
1071
  taosArrayDestroy(pArray);
4,279✔
1072
  TAOS_RETURN(code);
4,279✔
1073
}
1074

1075
SEpSet mndGetVgroupEpset(SMnode *pMnode, const SVgObj *pVgroup) {
134,577✔
1076
  SEpSet epset = {0};
134,577✔
1077

1078
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
314,846✔
1079
    const SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
180,269✔
1080
    SDnodeObj       *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
180,269✔
1081
    if (pDnode == NULL) continue;
180,269✔
1082

1083
    if (pVgid->syncState == TAOS_SYNC_STATE_LEADER || pVgid->syncState == TAOS_SYNC_STATE_ASSIGNED_LEADER) {
180,124!
1084
      epset.inUse = epset.numOfEps;
123,937✔
1085
    }
1086

1087
    if (addEpIntoEpSet(&epset, pDnode->fqdn, pDnode->port) != 0) {
180,124!
UNCOV
1088
      mWarn("vgId:%d, failed to add ep:%s:%d into epset", pVgroup->vgId, pDnode->fqdn, pDnode->port);
×
1089
    }
1090
    mndReleaseDnode(pMnode, pDnode);
180,124✔
1091
  }
1092
  epsetSort(&epset);
134,577✔
1093

1094
  return epset;
134,577✔
1095
}
1096

1097
SEpSet mndGetVgroupEpsetById(SMnode *pMnode, int32_t vgId) {
18✔
1098
  SEpSet epset = {0};
18✔
1099

1100
  SVgObj *pVgroup = mndAcquireVgroup(pMnode, vgId);
18✔
1101
  if (!pVgroup) return epset;
18!
1102

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

1108
    if (pVgid->syncState == TAOS_SYNC_STATE_LEADER || pVgid->syncState == TAOS_SYNC_STATE_ASSIGNED_LEADER) {
36!
1109
      epset.inUse = epset.numOfEps;
8✔
1110
    }
1111

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

1118
  mndReleaseVgroup(pMnode, pVgroup);
18✔
1119
  return epset;
18✔
1120
}
1121

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

1131
  SDbObj *pDb = NULL;
578✔
1132
  if (strlen(pShow->db) > 0) {
578✔
1133
    pDb = mndAcquireDb(pMnode, pShow->db);
544✔
1134
    if (pDb == NULL) {
544!
UNCOV
1135
      return 0;
×
1136
    }
1137
  }
1138

1139
  while (numOfRows < rows) {
2,491!
1140
    pShow->pIter = sdbFetch(pSdb, SDB_VGROUP, pShow->pIter, (void **)&pVgroup);
2,491✔
1141
    if (pShow->pIter == NULL) break;
2,491✔
1142

1143
    if (pDb != NULL && pVgroup->dbUid != pDb->uid) {
1,913✔
1144
      sdbRelease(pSdb, pVgroup);
146✔
1145
      continue;
146✔
1146
    }
1147

1148
    cols = 0;
1,767✔
1149
    SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,767✔
1150
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->vgId, false);
1,767✔
1151
    if (code != 0) {
1,767!
UNCOV
1152
      mError("vgId:%d, failed to set vgId, since %s", pVgroup->vgId, tstrerror(code));
×
1153
      return code;
×
1154
    }
1155

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

1166
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,767✔
1167
    code = colDataSetVal(pColInfo, numOfRows, (const char *)db, false);
1,767✔
1168
    if (code != 0) {
1,767!
UNCOV
1169
      mError("vgId:%d, failed to set dbName, since %s", pVgroup->vgId, tstrerror(code));
×
UNCOV
1170
      return code;
×
1171
    }
1172

1173
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,767✔
1174
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->numOfTables, false);
1,767✔
1175
    if (code != 0) {
1,767!
UNCOV
1176
      mError("vgId:%d, failed to set numOfTables, since %s", pVgroup->vgId, tstrerror(code));
×
UNCOV
1177
      return code;
×
1178
    }
1179

1180
    // default 3 replica, add 1 replica if move vnode
1181
    for (int32_t i = 0; i < 4; ++i) {
8,835✔
1182
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
7,068✔
1183
      if (i < pVgroup->replica) {
7,068✔
1184
        int16_t dnodeId = (int16_t)pVgroup->vnodeGid[i].dnodeId;
3,170✔
1185
        code = colDataSetVal(pColInfo, numOfRows, (const char *)&dnodeId, false);
3,170✔
1186
        if (code != 0) {
3,170!
UNCOV
1187
          mError("vgId:%d, failed to set dnodeId, since %s", pVgroup->vgId, tstrerror(code));
×
UNCOV
1188
          return code;
×
1189
        }
1190

1191
        bool       exist = false;
3,170✔
1192
        bool       online = false;
3,170✔
1193
        SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgroup->vnodeGid[i].dnodeId);
3,170✔
1194
        if (pDnode != NULL) {
3,170!
1195
          exist = true;
3,170✔
1196
          online = mndIsDnodeOnline(pDnode, curMs);
3,170✔
1197
          mndReleaseDnode(pMnode, pDnode);
3,170✔
1198
        }
1199

1200
        char buf1[20] = {0};
3,170✔
1201
        char role[20] = "offline";
3,170✔
1202
        if (!exist) {
3,170!
UNCOV
1203
          tstrncpy(role, "dropping", sizeof(role));
×
1204
        } else if (online) {
3,170✔
1205
          char *star = "";
3,029✔
1206
          if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_LEADER ||
3,029✔
1207
              pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_ASSIGNED_LEADER) {
1,476!
1208
            if (!pVgroup->vnodeGid[i].syncRestore && !pVgroup->vnodeGid[i].syncCanRead) {
1,553!
1209
              star = "**";
409✔
1210
            } else if (!pVgroup->vnodeGid[i].syncRestore && pVgroup->vnodeGid[i].syncCanRead) {
1,144!
UNCOV
1211
              star = "*";
×
1212
            } else {
1213
            }
1214
          }
1215
          snprintf(role, sizeof(role), "%s%s", syncStr(pVgroup->vnodeGid[i].syncState), star);
3,029✔
1216
          /*
1217
          mInfo("db:%s, learner progress:%d", pDb->name, pVgroup->vnodeGid[i].learnerProgress);
1218

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

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

1242
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
3,170✔
1243
        code = colDataSetVal(pColInfo, numOfRows, (const char *)buf1, false);
3,170✔
1244
        if (code != 0) {
3,170!
UNCOV
1245
          mError("vgId:%d, failed to set role, since %s", pVgroup->vgId, tstrerror(code));
×
UNCOV
1246
          return code;
×
1247
        }
1248

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

1255
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
3,170✔
1256
        code = colDataSetVal(pColInfo, numOfRows, (const char *)&buf, false);
3,170✔
1257
        if (code != 0) {
3,170!
1258
          mError("vgId:%d, failed to set role, since %s", pVgroup->vgId, tstrerror(code));
×
1259
          return code;
×
1260
        }
1261
      } else {
1262
        colDataSetNULL(pColInfo, numOfRows);
3,898!
1263
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
3,898✔
1264
        colDataSetNULL(pColInfo, numOfRows);
3,898!
1265
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
3,898✔
1266
        colDataSetNULL(pColInfo, numOfRows);
3,898!
1267
      }
1268
    }
1269

1270
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,767✔
1271
    int32_t cacheUsage = (int32_t)pVgroup->cacheUsage;
1,767✔
1272
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&cacheUsage, false);
1,767✔
1273
    if (code != 0) {
1,767!
UNCOV
1274
      mError("vgId:%d, failed to set cacheUsage, since %s", pVgroup->vgId, tstrerror(code));
×
UNCOV
1275
      return code;
×
1276
    }
1277

1278
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,767✔
1279
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->numOfCachedTables, false);
1,767✔
1280
    if (code != 0) {
1,767!
UNCOV
1281
      mError("vgId:%d, failed to set numOfCachedTables, since %s", pVgroup->vgId, tstrerror(code));
×
UNCOV
1282
      return code;
×
1283
    }
1284

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

1295
  if (pDb != NULL) {
578✔
1296
    mndReleaseDb(pMnode, pDb);
544✔
1297
  }
1298

1299
  pShow->numOfRows += numOfRows;
578✔
1300
  return numOfRows;
578✔
1301
}
1302

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

1308
static bool mndGetVnodesNumFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
21,240✔
1309
  SVgObj  *pVgroup = pObj;
21,240✔
1310
  int32_t  dnodeId = *(int32_t *)p1;
21,240✔
1311
  int32_t *pNumOfVnodes = (int32_t *)p2;
21,240✔
1312

1313
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
55,043✔
1314
    if (pVgroup->vnodeGid[v].dnodeId == dnodeId) {
33,803✔
1315
      (*pNumOfVnodes)++;
13,004✔
1316
    }
1317
  }
1318

1319
  return true;
21,240✔
1320
}
1321

1322
int32_t mndGetVnodesNum(SMnode *pMnode, int32_t dnodeId) {
8,841✔
1323
  int32_t numOfVnodes = 0;
8,841✔
1324
  sdbTraverse(pMnode->pSdb, SDB_VGROUP, mndGetVnodesNumFp, &dnodeId, &numOfVnodes, NULL);
8,841✔
1325
  return numOfVnodes;
8,841✔
1326
}
1327

1328
int64_t mndGetVgroupMemory(SMnode *pMnode, SDbObj *pDbInput, SVgObj *pVgroup) {
20,598✔
1329
  SDbObj *pDb = pDbInput;
20,598✔
1330
  if (pDbInput == NULL) {
20,598✔
1331
    pDb = mndAcquireDb(pMnode, pVgroup->dbName);
10,181✔
1332
  }
1333

1334
  int64_t vgroupMemroy = 0;
20,598✔
1335
  if (pDb != NULL) {
20,598!
1336
    int64_t buffer = (int64_t)pDb->cfg.buffer * 1024 * 1024;
20,598✔
1337
    int64_t cache = (int64_t)pDb->cfg.pages * pDb->cfg.pageSize * 1024;
20,598✔
1338
    vgroupMemroy = buffer + cache;
20,598✔
1339
    int64_t cacheLast = (int64_t)pDb->cfg.cacheLastSize * 1024 * 1024;
20,598✔
1340
    if (pDb->cfg.cacheLast > 0) {
20,598✔
1341
      vgroupMemroy += cacheLast;
1,743✔
1342
    }
1343
    mDebug("db:%s, vgroup:%d, buffer:%" PRId64 " cache:%" PRId64 " cacheLast:%" PRId64, pDb->name, pVgroup->vgId,
20,598✔
1344
           buffer, cache, cacheLast);
1345
  }
1346

1347
  if (pDbInput == NULL) {
20,598✔
1348
    mndReleaseDb(pMnode, pDb);
10,181✔
1349
  }
1350
  return vgroupMemroy;
20,598✔
1351
}
1352

1353
static bool mndGetVnodeMemroyFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
12,925✔
1354
  SVgObj  *pVgroup = pObj;
12,925✔
1355
  int32_t  dnodeId = *(int32_t *)p1;
12,925✔
1356
  int64_t *pVnodeMemory = (int64_t *)p2;
12,925✔
1357

1358
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
31,199✔
1359
    if (pVgroup->vnodeGid[v].dnodeId == dnodeId) {
18,274✔
1360
      *pVnodeMemory += mndGetVgroupMemory(pMnode, NULL, pVgroup);
9,923✔
1361
    }
1362
  }
1363

1364
  return true;
12,925✔
1365
}
1366

1367
int64_t mndGetVnodesMemory(SMnode *pMnode, int32_t dnodeId) {
5,751✔
1368
  int64_t vnodeMemory = 0;
5,751✔
1369
  sdbTraverse(pMnode->pSdb, SDB_VGROUP, mndGetVnodeMemroyFp, &dnodeId, &vnodeMemory, NULL);
5,751✔
1370
  return vnodeMemory;
5,751✔
1371
}
1372

UNCOV
1373
void calculateRstoreFinishTime(double rate, int64_t applyCount, char *restoreStr, size_t restoreStrSize) {
×
UNCOV
1374
  if (rate == 0) {
×
UNCOV
1375
    snprintf(restoreStr, restoreStrSize, "0:0:0");
×
UNCOV
1376
    return;
×
1377
  }
1378

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

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

1397
  while (numOfRows < rows - TSDB_MAX_REPLICA) {
299!
1398
    pShow->pIter = sdbFetch(pSdb, SDB_VGROUP, pShow->pIter, (void **)&pVgroup);
299✔
1399
    if (pShow->pIter == NULL) break;
299✔
1400

1401
    for (int32_t i = 0; i < pVgroup->replica && numOfRows < rows; ++i) {
618!
1402
      SVnodeGid       *pGid = &pVgroup->vnodeGid[i];
407✔
1403
      SColumnInfoData *pColInfo = NULL;
407✔
1404
      cols = 0;
407✔
1405

1406
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
407✔
1407
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&pGid->dnodeId, false);
407✔
1408
      if (code != 0) {
407!
UNCOV
1409
        mError("vgId:%d, failed to set dnodeId, since %s", pVgroup->vgId, tstrerror(code));
×
UNCOV
1410
        return code;
×
1411
      }
1412
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
407✔
1413
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->vgId, false);
407✔
1414
      if (code != 0) {
407!
1415
        mError("vgId:%d, failed to set vgId, since %s", pVgroup->vgId, tstrerror(code));
×
UNCOV
1416
        return code;
×
1417
      }
1418

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

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

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

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

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

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

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

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

1495
      numOfRows++;
407✔
1496
      sdbRelease(pSdb, pDnode);
407✔
1497
    }
1498

1499
    sdbRelease(pSdb, pVgroup);
211✔
1500
  }
1501

1502
  pShow->numOfRows += numOfRows;
88✔
1503
  return numOfRows;
88✔
1504
}
1505

1506
static void mndCancelGetNextVnode(SMnode *pMnode, void *pIter) {
×
1507
  SSdb *pSdb = pMnode->pSdb;
×
UNCOV
1508
  sdbCancelFetchByType(pSdb, pIter, SDB_VGROUP);
×
UNCOV
1509
}
×
1510

1511
static int32_t mndAddVnodeToVgroup(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup, SArray *pArray) {
152✔
1512
  int32_t code = 0;
152✔
1513
  taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
152✔
1514
  for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
575✔
1515
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
423✔
1516
    mInfo("dnode:%d, equivalent vnodes:%d others:%d", pDnode->id, pDnode->numOfVnodes, pDnode->numOfOtherNodes);
423!
1517
  }
1518

1519
  SVnodeGid *pVgid = &pVgroup->vnodeGid[pVgroup->replica];
152✔
1520
  for (int32_t d = 0; d < taosArrayGetSize(pArray); ++d) {
192✔
1521
    SDnodeObj *pDnode = taosArrayGet(pArray, d);
180✔
1522

1523
    bool used = false;
180✔
1524
    for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
421✔
1525
      if (pDnode->id == pVgroup->vnodeGid[vn].dnodeId) {
281✔
1526
        used = true;
40✔
1527
        break;
40✔
1528
      }
1529
    }
1530
    if (used) continue;
180✔
1531

1532
    if (pDnode == NULL) {
140!
1533
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_DNODES);
×
1534
    }
1535
    if (pDnode->numOfVnodes >= pDnode->numOfSupportVnodes) {
140!
1536
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_VNODES);
×
1537
    }
1538

1539
    int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
140✔
1540
    if (pDnode->memAvail - vgMem - pDnode->memUsed <= 0) {
140!
1541
      mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
×
1542
             pVgroup->dbName, pVgroup->vgId, vgMem, pDnode->id, pDnode->memAvail, pDnode->memUsed);
UNCOV
1543
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE);
×
1544
    } else {
1545
      pDnode->memUsed += vgMem;
140✔
1546
    }
1547

1548
    pVgid->dnodeId = pDnode->id;
140✔
1549
    pVgid->syncState = TAOS_SYNC_STATE_OFFLINE;
140✔
1550
    mInfo("db:%s, vgId:%d, vn:%d is added, memory:%" PRId64 ", dnode:%d avail:%" PRId64 " used:%" PRId64,
140!
1551
          pVgroup->dbName, pVgroup->vgId, pVgroup->replica, vgMem, pVgid->dnodeId, pDnode->memAvail, pDnode->memUsed);
1552

1553
    pVgroup->replica++;
140✔
1554
    pDnode->numOfVnodes++;
140✔
1555

1556
    SSdbRaw *pVgRaw = mndVgroupActionEncode(pVgroup);
140✔
1557
    if (pVgRaw == NULL) {
140!
UNCOV
1558
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1559
      if (terrno != 0) code = terrno;
×
UNCOV
1560
      TAOS_RETURN(code);
×
1561
    }
1562
    if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
140!
UNCOV
1563
      sdbFreeRaw(pVgRaw);
×
UNCOV
1564
      TAOS_RETURN(code);
×
1565
    }
1566
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
140✔
1567
    if (code != 0) {
140!
UNCOV
1568
      mError("vgId:%d, failed to set raw status since %s at line:%d", pVgroup->vgId, tstrerror(code), __LINE__);
×
1569
    }
1570
    TAOS_RETURN(code);
140✔
1571
  }
1572

1573
  code = TSDB_CODE_MND_NO_ENOUGH_DNODES;
12✔
1574
  mError("db:%s, failed to add vnode to vgId:%d since %s", pVgroup->dbName, pVgroup->vgId, tstrerror(code));
12!
1575
  TAOS_RETURN(code);
12✔
1576
}
1577

1578
static int32_t mndRemoveVnodeFromVgroup(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup, SArray *pArray,
31✔
1579
                                        SVnodeGid *pDelVgid) {
1580
  taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
31✔
1581
  for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
137✔
1582
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
106✔
1583
    mInfo("dnode:%d, equivalent vnodes:%d others:%d", pDnode->id, pDnode->numOfVnodes, pDnode->numOfOtherNodes);
106!
1584
  }
1585

1586
  int32_t code = -1;
31✔
1587
  for (int32_t d = taosArrayGetSize(pArray) - 1; d >= 0; --d) {
43!
1588
    SDnodeObj *pDnode = taosArrayGet(pArray, d);
43✔
1589

1590
    for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
103✔
1591
      SVnodeGid *pVgid = &pVgroup->vnodeGid[vn];
91✔
1592
      if (pVgid->dnodeId == pDnode->id) {
91✔
1593
        int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
31✔
1594
        pDnode->memUsed -= vgMem;
31✔
1595
        mInfo("db:%s, vgId:%d, vn:%d is removed, memory:%" PRId64 ", dnode:%d avail:%" PRId64 " used:%" PRId64,
31!
1596
              pVgroup->dbName, pVgroup->vgId, vn, vgMem, pVgid->dnodeId, pDnode->memAvail, pDnode->memUsed);
1597
        pDnode->numOfVnodes--;
31✔
1598
        pVgroup->replica--;
31✔
1599
        *pDelVgid = *pVgid;
31✔
1600
        *pVgid = pVgroup->vnodeGid[pVgroup->replica];
31✔
1601
        memset(&pVgroup->vnodeGid[pVgroup->replica], 0, sizeof(SVnodeGid));
31✔
1602
        code = 0;
31✔
1603
        goto _OVER;
31✔
1604
      }
1605
    }
1606
  }
1607

UNCOV
1608
_OVER:
×
1609
  if (code != 0) {
31!
1610
    code = TSDB_CODE_APP_ERROR;
×
UNCOV
1611
    mError("db:%s, failed to remove vnode from vgId:%d since %s", pVgroup->dbName, pVgroup->vgId, tstrerror(code));
×
UNCOV
1612
    TAOS_RETURN(code);
×
1613
  }
1614

1615
  for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
89✔
1616
    SVnodeGid *pVgid = &pVgroup->vnodeGid[vn];
58✔
1617
    mInfo("db:%s, vgId:%d, vn:%d dnode:%d is reserved", pVgroup->dbName, pVgroup->vgId, vn, pVgid->dnodeId);
58!
1618
  }
1619

1620
  SSdbRaw *pVgRaw = mndVgroupActionEncode(pVgroup);
31✔
1621
  if (pVgRaw == NULL) {
31!
UNCOV
1622
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1623
    if (terrno != 0) code = terrno;
×
UNCOV
1624
    TAOS_RETURN(code);
×
1625
  }
1626
  if (mndTransAppendRedolog(pTrans, pVgRaw) != 0) {
31!
UNCOV
1627
    sdbFreeRaw(pVgRaw);
×
UNCOV
1628
    TAOS_RETURN(code);
×
1629
  }
1630
  code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
31✔
1631
  if (code != 0) {
31!
UNCOV
1632
    mError("vgId:%d, failed to set raw status since %s at line:%d", pVgroup->vgId, tstrerror(code), __LINE__);
×
1633
  }
1634

1635
  TAOS_RETURN(code);
31✔
1636
}
1637

1638
static int32_t mndRemoveVnodeFromVgroupWithoutSave(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup, SArray *pArray,
×
1639
                                                   SVnodeGid *pDelVgid) {
UNCOV
1640
  taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
×
UNCOV
1641
  for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
×
UNCOV
1642
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
×
UNCOV
1643
    mInfo("dnode:%d, equivalent vnodes:%d others:%d", pDnode->id, pDnode->numOfVnodes, pDnode->numOfOtherNodes);
×
1644
  }
1645

UNCOV
1646
  int32_t code = -1;
×
1647
  for (int32_t d = taosArrayGetSize(pArray) - 1; d >= 0; --d) {
×
1648
    SDnodeObj *pDnode = taosArrayGet(pArray, d);
×
1649

UNCOV
1650
    for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
×
1651
      SVnodeGid *pVgid = &pVgroup->vnodeGid[vn];
×
1652
      if (pVgid->dnodeId == pDnode->id) {
×
1653
        int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
×
1654
        pDnode->memUsed -= vgMem;
×
1655
        mInfo("db:%s, vgId:%d, vn:%d is removed, memory:%" PRId64 ", dnode:%d avail:%" PRId64 " used:%" PRId64,
×
1656
              pVgroup->dbName, pVgroup->vgId, vn, vgMem, pVgid->dnodeId, pDnode->memAvail, pDnode->memUsed);
UNCOV
1657
        pDnode->numOfVnodes--;
×
UNCOV
1658
        pVgroup->replica--;
×
1659
        *pDelVgid = *pVgid;
×
UNCOV
1660
        *pVgid = pVgroup->vnodeGid[pVgroup->replica];
×
1661
        memset(&pVgroup->vnodeGid[pVgroup->replica], 0, sizeof(SVnodeGid));
×
1662
        code = 0;
×
1663
        goto _OVER;
×
1664
      }
1665
    }
1666
  }
1667

1668
_OVER:
×
UNCOV
1669
  if (code != 0) {
×
1670
    code = TSDB_CODE_APP_ERROR;
×
1671
    mError("db:%s, failed to remove vnode from vgId:%d since %s", pVgroup->dbName, pVgroup->vgId, tstrerror(code));
×
UNCOV
1672
    TAOS_RETURN(code);
×
1673
  }
1674

1675
  for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
×
UNCOV
1676
    SVnodeGid *pVgid = &pVgroup->vnodeGid[vn];
×
1677
    mInfo("db:%s, vgId:%d, vn:%d dnode:%d is reserved", pVgroup->dbName, pVgroup->vgId, vn, pVgid->dnodeId);
×
1678
  }
1679

UNCOV
1680
  TAOS_RETURN(code);
×
1681
}
1682

1683
int32_t mndAddCreateVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, SVnodeGid *pVgid) {
9,474✔
1684
  int32_t      code = 0;
9,474✔
1685
  STransAction action = {0};
9,474✔
1686

1687
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
9,474✔
1688
  if (pDnode == NULL) return -1;
9,474!
1689
  action.epSet = mndGetDnodeEpset(pDnode);
9,474✔
1690
  mndReleaseDnode(pMnode, pDnode);
9,474✔
1691

1692
  int32_t contLen = 0;
9,474✔
1693
  void   *pReq = mndBuildCreateVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen);
9,474✔
1694
  if (pReq == NULL) return -1;
9,474!
1695

1696
  action.pCont = pReq;
9,474✔
1697
  action.contLen = contLen;
9,474✔
1698
  action.msgType = TDMT_DND_CREATE_VNODE;
9,474✔
1699
  action.acceptableCode = TSDB_CODE_VND_ALREADY_EXIST;
9,474✔
1700

1701
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
9,474!
UNCOV
1702
    taosMemoryFree(pReq);
×
UNCOV
1703
    TAOS_RETURN(code);
×
1704
  }
1705

1706
  TAOS_RETURN(code);
9,474✔
1707
}
1708

1709
int32_t mndRestoreAddCreateVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
10✔
1710
                                       SDnodeObj *pDnode) {
1711
  int32_t      code = 0;
10✔
1712
  STransAction action = {0};
10✔
1713

1714
  action.epSet = mndGetDnodeEpset(pDnode);
10✔
1715

1716
  int32_t contLen = 0;
10✔
1717
  void   *pReq = mndBuildCreateVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen);
10✔
1718
  if (pReq == NULL) {
10!
UNCOV
1719
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1720
    if (terrno != 0) code = terrno;
×
1721
    TAOS_RETURN(code);
×
1722
  }
1723

1724
  action.pCont = pReq;
10✔
1725
  action.contLen = contLen;
10✔
1726
  action.msgType = TDMT_DND_CREATE_VNODE;
10✔
1727
  action.acceptableCode = TSDB_CODE_VND_ALREADY_EXIST;
10✔
1728

1729
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
10!
1730
    taosMemoryFree(pReq);
×
1731
    TAOS_RETURN(code);
×
1732
  }
1733

1734
  TAOS_RETURN(code);
10✔
1735
}
1736

1737
int32_t mndAddAlterVnodeConfirmAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) {
476✔
1738
  int32_t      code = 0;
476✔
1739
  STransAction action = {0};
476✔
1740
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
476✔
1741

1742
  mInfo("vgId:%d, build alter vnode confirm req", pVgroup->vgId);
476!
1743
  int32_t   contLen = sizeof(SMsgHead);
476✔
1744
  SMsgHead *pHead = taosMemoryMalloc(contLen);
476!
1745
  if (pHead == NULL) {
476!
UNCOV
1746
    TAOS_RETURN(terrno);
×
1747
  }
1748

1749
  pHead->contLen = htonl(contLen);
476✔
1750
  pHead->vgId = htonl(pVgroup->vgId);
476✔
1751

1752
  action.pCont = pHead;
476✔
1753
  action.contLen = contLen;
476✔
1754
  action.msgType = TDMT_VND_ALTER_CONFIRM;
476✔
1755
  // incorrect redirect result will cause this erro
1756
  action.retryCode = TSDB_CODE_VND_INVALID_VGROUP_ID;
476✔
1757

1758
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
476!
1759
    taosMemoryFree(pHead);
×
UNCOV
1760
    TAOS_RETURN(code);
×
1761
  }
1762

1763
  TAOS_RETURN(code);
476✔
1764
}
1765

1766
int32_t mndAddChangeConfigAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pOldVgroup, SVgObj *pNewVgroup,
×
1767
                                 int32_t dnodeId) {
1768
  int32_t      code = 0;
×
UNCOV
1769
  STransAction action = {0};
×
UNCOV
1770
  action.epSet = mndGetVgroupEpset(pMnode, pNewVgroup);
×
1771

UNCOV
1772
  int32_t contLen = 0;
×
UNCOV
1773
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pNewVgroup, dnodeId, &contLen);
×
UNCOV
1774
  if (pReq == NULL) {
×
UNCOV
1775
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1776
    if (terrno != 0) code = terrno;
×
UNCOV
1777
    TAOS_RETURN(code);
×
1778
  }
1779

1780
  int32_t totallen = contLen + sizeof(SMsgHead);
×
1781

UNCOV
1782
  SMsgHead *pHead = taosMemoryMalloc(totallen);
×
UNCOV
1783
  if (pHead == NULL) {
×
UNCOV
1784
    taosMemoryFree(pReq);
×
UNCOV
1785
    TAOS_RETURN(terrno);
×
1786
  }
1787

1788
  pHead->contLen = htonl(totallen);
×
1789
  pHead->vgId = htonl(pNewVgroup->vgId);
×
1790

UNCOV
1791
  memcpy((void *)(pHead + 1), pReq, contLen);
×
UNCOV
1792
  taosMemoryFree(pReq);
×
1793

UNCOV
1794
  action.pCont = pHead;
×
1795
  action.contLen = totallen;
×
1796
  action.msgType = TDMT_SYNC_CONFIG_CHANGE;
×
1797

1798
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
×
1799
    taosMemoryFree(pHead);
×
1800
    TAOS_RETURN(code);
×
1801
  }
1802

UNCOV
1803
  TAOS_RETURN(code);
×
1804
}
1805

1806
static int32_t mndAddAlterVnodeHashRangeAction(SMnode *pMnode, STrans *pTrans, int32_t srcVgId, SVgObj *pVgroup) {
52✔
1807
  int32_t      code = 0;
52✔
1808
  STransAction action = {0};
52✔
1809
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
52✔
1810

1811
  int32_t contLen = 0;
52✔
1812
  void   *pReq = mndBuildAlterVnodeHashRangeReq(pMnode, srcVgId, pVgroup, &contLen);
52✔
1813
  if (pReq == NULL) {
52!
UNCOV
1814
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1815
    if (terrno != 0) code = terrno;
×
1816
    TAOS_RETURN(code);
×
1817
  }
1818

1819
  action.pCont = pReq;
52✔
1820
  action.contLen = contLen;
52✔
1821
  action.msgType = TDMT_VND_ALTER_HASHRANGE;
52✔
1822
  action.acceptableCode = TSDB_CODE_VND_ALREADY_EXIST;
52✔
1823

1824
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
52!
UNCOV
1825
    taosMemoryFree(pReq);
×
UNCOV
1826
    TAOS_RETURN(code);
×
1827
  }
1828

1829
  mInfo("trans:%d, add alter vnode hash range action for from vgId:%d to vgId:%d", pTrans->id, srcVgId, pVgroup->vgId);
52!
1830
  TAOS_RETURN(code);
52✔
1831
}
1832

1833
int32_t mndAddAlterVnodeConfigAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) {
368✔
1834
  int32_t      code = 0;
368✔
1835
  STransAction action = {0};
368✔
1836
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
368✔
1837

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

1846
  action.pCont = pReq;
368✔
1847
  action.contLen = contLen;
368✔
1848
  action.msgType = TDMT_VND_ALTER_CONFIG;
368✔
1849

1850
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
368!
UNCOV
1851
    taosMemoryFree(pReq);
×
UNCOV
1852
    TAOS_RETURN(code);
×
1853
  }
1854

1855
  TAOS_RETURN(code);
368✔
1856
}
1857

1858
int32_t mndAddNewVgPrepareAction(SMnode *pMnode, STrans *pTrans, SVgObj *pVg) {
8,494✔
1859
  int32_t  code = 0;
8,494✔
1860
  SSdbRaw *pRaw = mndVgroupActionEncode(pVg);
8,494✔
1861
  if (pRaw == NULL) {
8,494!
UNCOV
1862
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1863
    if (terrno != 0) code = terrno;
×
UNCOV
1864
    goto _err;
×
1865
  }
1866

1867
  TAOS_CHECK_GOTO(mndTransAppendPrepareLog(pTrans, pRaw), NULL, _err);
8,494!
1868
  if (sdbSetRawStatus(pRaw, SDB_STATUS_CREATING) != 0) {
8,494!
UNCOV
1869
    mError("vgId:%d, failed to set raw status at line:%d", pVg->vgId, __LINE__);
×
1870
  }
1871
  if (code != 0) {
8,494!
UNCOV
1872
    mError("vgId:%d, failed to set raw status since %s at line:%d", pVg->vgId, tstrerror(code), __LINE__);
×
UNCOV
1873
    TAOS_RETURN(code);
×
1874
  }
1875
  pRaw = NULL;
8,494✔
1876
  TAOS_RETURN(code);
8,494✔
1877

UNCOV
1878
_err:
×
UNCOV
1879
  sdbFreeRaw(pRaw);
×
UNCOV
1880
  TAOS_RETURN(code);
×
1881
}
1882

1883
int32_t mndAddAlterVnodeReplicaAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId) {
1,163✔
1884
  int32_t    code = 0;
1,163✔
1885
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
1,163✔
1886
  if (pDnode == NULL) {
1,163!
1887
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1888
    if (terrno != 0) code = terrno;
×
UNCOV
1889
    TAOS_RETURN(code);
×
1890
  }
1891

1892
  STransAction action = {0};
1,163✔
1893
  action.epSet = mndGetDnodeEpset(pDnode);
1,163✔
1894
  mndReleaseDnode(pMnode, pDnode);
1,163✔
1895

1896
  int32_t contLen = 0;
1,163✔
1897
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pVgroup, dnodeId, &contLen);
1,163✔
1898
  if (pReq == NULL) {
1,163!
1899
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1900
    if (terrno != 0) code = terrno;
×
UNCOV
1901
    TAOS_RETURN(code);
×
1902
  }
1903

1904
  action.pCont = pReq;
1,163✔
1905
  action.contLen = contLen;
1,163✔
1906
  action.msgType = TDMT_VND_ALTER_REPLICA;
1,163✔
1907

1908
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
1,163!
UNCOV
1909
    taosMemoryFree(pReq);
×
1910
    TAOS_RETURN(code);
×
1911
  }
1912

1913
  TAOS_RETURN(code);
1,163✔
1914
}
1915

UNCOV
1916
int32_t mndAddCheckLearnerCatchupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId) {
×
UNCOV
1917
  int32_t    code = 0;
×
UNCOV
1918
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
×
UNCOV
1919
  if (pDnode == NULL) {
×
1920
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1921
    if (terrno != 0) code = terrno;
×
UNCOV
1922
    TAOS_RETURN(code);
×
1923
  }
1924

UNCOV
1925
  STransAction action = {0};
×
UNCOV
1926
  action.epSet = mndGetDnodeEpset(pDnode);
×
UNCOV
1927
  mndReleaseDnode(pMnode, pDnode);
×
1928

UNCOV
1929
  int32_t contLen = 0;
×
UNCOV
1930
  void   *pReq = mndBuildCheckLearnCatchupReq(pMnode, pDb, pVgroup, dnodeId, &contLen);
×
UNCOV
1931
  if (pReq == NULL) {
×
UNCOV
1932
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1933
    if (terrno != 0) code = terrno;
×
1934
    TAOS_RETURN(code);
×
1935
  }
1936

UNCOV
1937
  action.pCont = pReq;
×
UNCOV
1938
  action.contLen = contLen;
×
UNCOV
1939
  action.msgType = TDMT_DND_CHECK_VNODE_LEARNER_CATCHUP;
×
UNCOV
1940
  action.acceptableCode = TSDB_CODE_VND_ALREADY_IS_VOTER;
×
UNCOV
1941
  action.retryCode = TSDB_CODE_VND_NOT_CATCH_UP;
×
1942

UNCOV
1943
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
×
1944
    taosMemoryFree(pReq);
×
1945
    TAOS_RETURN(code);
×
1946
  }
1947

UNCOV
1948
  TAOS_RETURN(code);
×
1949
}
1950

1951
int32_t mndAddAlterVnodeTypeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId) {
172✔
1952
  int32_t    code = 0;
172✔
1953
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
172✔
1954
  if (pDnode == NULL) {
172!
UNCOV
1955
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1956
    if (terrno != 0) code = terrno;
×
1957
    TAOS_RETURN(code);
×
1958
  }
1959

1960
  STransAction action = {0};
172✔
1961
  action.epSet = mndGetDnodeEpset(pDnode);
172✔
1962
  mndReleaseDnode(pMnode, pDnode);
172✔
1963

1964
  int32_t contLen = 0;
172✔
1965
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pVgroup, dnodeId, &contLen);
172✔
1966
  if (pReq == NULL) {
172!
UNCOV
1967
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1968
    if (terrno != 0) code = terrno;
×
UNCOV
1969
    TAOS_RETURN(code);
×
1970
  }
1971

1972
  action.pCont = pReq;
172✔
1973
  action.contLen = contLen;
172✔
1974
  action.msgType = TDMT_DND_ALTER_VNODE_TYPE;
172✔
1975
  action.acceptableCode = TSDB_CODE_VND_ALREADY_IS_VOTER;
172✔
1976
  action.retryCode = TSDB_CODE_VND_NOT_CATCH_UP;
172✔
1977

1978
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
172!
UNCOV
1979
    taosMemoryFree(pReq);
×
UNCOV
1980
    TAOS_RETURN(code);
×
1981
  }
1982

1983
  TAOS_RETURN(code);
172✔
1984
}
1985

1986
int32_t mndRestoreAddAlterVnodeTypeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
10✔
1987
                                          SDnodeObj *pDnode) {
1988
  int32_t      code = 0;
10✔
1989
  STransAction action = {0};
10✔
1990
  action.epSet = mndGetDnodeEpset(pDnode);
10✔
1991

1992
  int32_t contLen = 0;
10✔
1993
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pVgroup, pDnode->id, &contLen);
10✔
1994
  if (pReq == NULL) {
10!
UNCOV
1995
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1996
    if (terrno != 0) code = terrno;
×
UNCOV
1997
    TAOS_RETURN(code);
×
1998
  }
1999

2000
  action.pCont = pReq;
10✔
2001
  action.contLen = contLen;
10✔
2002
  action.msgType = TDMT_DND_ALTER_VNODE_TYPE;
10✔
2003
  action.acceptableCode = TSDB_CODE_VND_ALREADY_IS_VOTER;
10✔
2004
  action.retryCode = TSDB_CODE_VND_NOT_CATCH_UP;
10✔
2005

2006
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
10!
2007
    taosMemoryFree(pReq);
×
2008
    TAOS_RETURN(code);
×
2009
  }
2010

2011
  TAOS_RETURN(code);
10✔
2012
}
2013

2014
static int32_t mndAddDisableVnodeWriteAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
52✔
2015
                                             int32_t dnodeId) {
2016
  int32_t    code = 0;
52✔
2017
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
52✔
2018
  if (pDnode == NULL) {
52!
UNCOV
2019
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2020
    if (terrno != 0) code = terrno;
×
UNCOV
2021
    TAOS_RETURN(code);
×
2022
  }
2023

2024
  STransAction action = {0};
52✔
2025
  action.epSet = mndGetDnodeEpset(pDnode);
52✔
2026
  mndReleaseDnode(pMnode, pDnode);
52✔
2027

2028
  int32_t contLen = 0;
52✔
2029
  void   *pReq = mndBuildDisableVnodeWriteReq(pMnode, pDb, pVgroup->vgId, &contLen);
52✔
2030
  if (pReq == NULL) {
52!
UNCOV
2031
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2032
    if (terrno != 0) code = terrno;
×
UNCOV
2033
    TAOS_RETURN(code);
×
2034
  }
2035

2036
  action.pCont = pReq;
52✔
2037
  action.contLen = contLen;
52✔
2038
  action.msgType = TDMT_VND_DISABLE_WRITE;
52✔
2039

2040
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
52!
UNCOV
2041
    taosMemoryFree(pReq);
×
UNCOV
2042
    TAOS_RETURN(code);
×
2043
  }
2044

2045
  TAOS_RETURN(code);
52✔
2046
}
2047

2048
int32_t mndAddDropVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, SVnodeGid *pVgid,
12,768✔
2049
                              bool isRedo) {
2050
  int32_t      code = 0;
12,768✔
2051
  STransAction action = {0};
12,768✔
2052

2053
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
12,768✔
2054
  if (pDnode == NULL) {
12,768!
UNCOV
2055
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2056
    if (terrno != 0) code = terrno;
×
UNCOV
2057
    TAOS_RETURN(code);
×
2058
  }
2059
  action.epSet = mndGetDnodeEpset(pDnode);
12,768✔
2060
  mndReleaseDnode(pMnode, pDnode);
12,768✔
2061

2062
  int32_t contLen = 0;
12,768✔
2063
  void   *pReq = mndBuildDropVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen);
12,768✔
2064
  if (pReq == NULL) {
12,768!
UNCOV
2065
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2066
    if (terrno != 0) code = terrno;
×
2067
    TAOS_RETURN(code);
×
2068
  }
2069

2070
  action.pCont = pReq;
12,768✔
2071
  action.contLen = contLen;
12,768✔
2072
  action.msgType = TDMT_DND_DROP_VNODE;
12,768✔
2073
  action.acceptableCode = TSDB_CODE_VND_NOT_EXIST;
12,768✔
2074

2075
  if (isRedo) {
12,768✔
2076
    if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
3,545!
UNCOV
2077
      taosMemoryFree(pReq);
×
UNCOV
2078
      TAOS_RETURN(code);
×
2079
    }
2080
  } else {
2081
    if ((code = mndTransAppendUndoAction(pTrans, &action)) != 0) {
9,223!
UNCOV
2082
      taosMemoryFree(pReq);
×
UNCOV
2083
      TAOS_RETURN(code);
×
2084
    }
2085
  }
2086

2087
  TAOS_RETURN(code);
12,768✔
2088
}
2089

2090
int32_t mndSetMoveVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t vnIndex,
33✔
2091
                                    SArray *pArray, bool force, bool unsafe) {
2092
  int32_t code = 0;
33✔
2093
  SVgObj  newVg = {0};
33✔
2094
  memcpy(&newVg, pVgroup, sizeof(SVgObj));
33✔
2095

2096
  mInfo("vgId:%d, vgroup info before move, replica:%d", newVg.vgId, newVg.replica);
33!
2097
  for (int32_t i = 0; i < newVg.replica; ++i) {
102✔
2098
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
69!
2099
  }
2100

2101
  if (!force) {
33✔
2102
#if 1
2103
    {
2104
#else
2105
    if (newVg.replica == 1) {
2106
#endif
2107
      mInfo("vgId:%d, will add 1 vnode, replca:%d", pVgroup->vgId, newVg.replica);
29!
2108
      TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVg, pArray));
29✔
2109
      for (int32_t i = 0; i < newVg.replica - 1; ++i) {
88✔
2110
        TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg, newVg.vnodeGid[i].dnodeId));
60!
2111
      }
2112
      TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg, &newVg.vnodeGid[newVg.replica - 1]));
28!
2113
      TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg));
28!
2114

2115
      mInfo("vgId:%d, will remove 1 vnode, replca:2", pVgroup->vgId);
28!
2116
      newVg.replica--;
28✔
2117
      SVnodeGid del = newVg.vnodeGid[vnIndex];
28✔
2118
      newVg.vnodeGid[vnIndex] = newVg.vnodeGid[newVg.replica];
28✔
2119
      memset(&newVg.vnodeGid[newVg.replica], 0, sizeof(SVnodeGid));
28✔
2120
      {
2121
        SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
28✔
2122
        if (pRaw == NULL) {
28!
UNCOV
2123
          code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2124
          if (terrno != 0) code = terrno;
×
2125
          TAOS_RETURN(code);
×
2126
        }
2127
        if ((code = mndTransAppendRedolog(pTrans, pRaw)) != 0) {
28!
UNCOV
2128
          sdbFreeRaw(pRaw);
×
UNCOV
2129
          TAOS_RETURN(code);
×
2130
        }
2131
        code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
28✔
2132
        if (code != 0) {
28!
UNCOV
2133
          mError("vgId:%d, failed to set raw status since %s at line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
UNCOV
2134
          return code;
×
2135
        }
2136
      }
2137

2138
      TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pDb, &newVg, &del, true));
28!
2139
      for (int32_t i = 0; i < newVg.replica; ++i) {
88✔
2140
        TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg, newVg.vnodeGid[i].dnodeId));
60!
2141
      }
2142
      TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg));
28!
2143
#if 1
2144
    }
2145
#else
2146
    } else {  // new replica == 3
2147
      mInfo("vgId:%d, will add 1 vnode, replca:3", pVgroup->vgId);
2148
      if (mndAddVnodeToVgroup(pMnode, pTrans, &newVg, pArray) != 0) return -1;
2149
      mInfo("vgId:%d, will remove 1 vnode, replca:4", pVgroup->vgId);
2150
      newVg.replica--;
2151
      SVnodeGid del = newVg.vnodeGid[vnIndex];
2152
      newVg.vnodeGid[vnIndex] = newVg.vnodeGid[newVg.replica];
2153
      memset(&newVg.vnodeGid[newVg.replica], 0, sizeof(SVnodeGid));
2154
      {
2155
        SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
2156
        if (pRaw == NULL) return -1;
2157
        if (mndTransAppendRedolog(pTrans, pRaw) != 0) {
2158
          sdbFreeRaw(pRaw);
2159
          return -1;
2160
        }
2161
      }
2162

2163
      if (mndAddDropVnodeAction(pMnode, pTrans, pDb, &newVg, &del, true) != 0) return -1;
2164
      for (int32_t i = 0; i < newVg.replica; ++i) {
2165
        if (i == vnIndex) continue;
2166
        if (mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg, newVg.vnodeGid[i].dnodeId) != 0) return -1;
2167
      }
2168
      if (mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg, &newVg.vnodeGid[vnIndex]) != 0) return -1;
2169
      if (mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg) != 0) return -1;
2170
    }
2171
#endif
2172
  } else {
2173
    mInfo("vgId:%d, will add 1 vnode and force remove 1 vnode", pVgroup->vgId);
4!
2174
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVg, pArray));
4!
2175
    newVg.replica--;
4✔
2176
    // SVnodeGid del = newVg.vnodeGid[vnIndex];
2177
    newVg.vnodeGid[vnIndex] = newVg.vnodeGid[newVg.replica];
4✔
2178
    memset(&newVg.vnodeGid[newVg.replica], 0, sizeof(SVnodeGid));
4✔
2179
    {
2180
      SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
4✔
2181
      if (pRaw == NULL) {
4!
UNCOV
2182
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2183
        if (terrno != 0) code = terrno;
×
UNCOV
2184
        TAOS_RETURN(code);
×
2185
      }
2186
      if ((code = mndTransAppendRedolog(pTrans, pRaw)) != 0) {
4!
UNCOV
2187
        sdbFreeRaw(pRaw);
×
UNCOV
2188
        TAOS_RETURN(code);
×
2189
      }
2190
      code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
4✔
2191
      if (code != 0) {
4!
UNCOV
2192
        mError("vgId:%d, failed to set raw status since %s at line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
UNCOV
2193
        return code;
×
2194
      }
2195
    }
2196

2197
    for (int32_t i = 0; i < newVg.replica; ++i) {
12✔
2198
      if (i != vnIndex) {
8✔
2199
        TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg, newVg.vnodeGid[i].dnodeId));
4!
2200
      }
2201
    }
2202
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg, &newVg.vnodeGid[vnIndex]));
4!
2203
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg));
4!
2204

2205
    if (newVg.replica == 1) {
4✔
2206
      if (force && !unsafe) {
2!
2207
        TAOS_RETURN(TSDB_CODE_VND_META_DATA_UNSAFE_DELETE);
1✔
2208
      }
2209

2210
      SSdb *pSdb = pMnode->pSdb;
1✔
2211
      void *pIter = NULL;
1✔
2212

2213
      while (1) {
3✔
2214
        SStbObj *pStb = NULL;
4✔
2215
        pIter = sdbFetch(pSdb, SDB_STB, pIter, (void **)&pStb);
4✔
2216
        if (pIter == NULL) break;
4✔
2217

2218
        if (strcmp(pStb->db, pDb->name) == 0) {
3✔
2219
          if ((code = mndSetForceDropCreateStbRedoActions(pMnode, pTrans, &newVg, pStb)) != 0) {
2!
UNCOV
2220
            sdbCancelFetch(pSdb, pIter);
×
UNCOV
2221
            sdbRelease(pSdb, pStb);
×
UNCOV
2222
            TAOS_RETURN(code);
×
2223
          }
2224
        }
2225

2226
        sdbRelease(pSdb, pStb);
3✔
2227
      }
2228

2229
      mInfo("vgId:%d, all data is dropped since replica=1", pVgroup->vgId);
1!
2230
    }
2231
  }
2232

2233
  {
2234
    SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
31✔
2235
    if (pRaw == NULL) {
31!
UNCOV
2236
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2237
      if (terrno != 0) code = terrno;
×
UNCOV
2238
      TAOS_RETURN(code);
×
2239
    }
2240
    if ((code = mndTransAppendCommitlog(pTrans, pRaw)) != 0) {
31!
UNCOV
2241
      sdbFreeRaw(pRaw);
×
UNCOV
2242
      TAOS_RETURN(code);
×
2243
    }
2244
    code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
31✔
2245
    if (code != 0) {
31!
UNCOV
2246
      mError("vgId:%d, failed to set raw status since %s at line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
UNCOV
2247
      return code;
×
2248
    }
2249
  }
2250

2251
  mInfo("vgId:%d, vgroup info after move, replica:%d", newVg.vgId, newVg.replica);
31!
2252
  for (int32_t i = 0; i < newVg.replica; ++i) {
98✔
2253
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
67!
2254
  }
2255
  TAOS_RETURN(code);
31✔
2256
}
2257

2258
int32_t mndSetMoveVgroupsInfoToTrans(SMnode *pMnode, STrans *pTrans, int32_t delDnodeId, bool force, bool unsafe) {
16✔
2259
  int32_t code = 0;
16✔
2260
  SArray *pArray = mndBuildDnodesArray(pMnode, delDnodeId, NULL);
16✔
2261
  if (pArray == NULL) {
16!
UNCOV
2262
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2263
    if (terrno != 0) code = terrno;
×
UNCOV
2264
    TAOS_RETURN(code);
×
2265
  }
2266

2267
  void *pIter = NULL;
16✔
2268
  while (1) {
44✔
2269
    SVgObj *pVgroup = NULL;
60✔
2270
    pIter = sdbFetch(pMnode->pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
60✔
2271
    if (pIter == NULL) break;
60✔
2272

2273
    int32_t vnIndex = -1;
46✔
2274
    for (int32_t i = 0; i < pVgroup->replica; ++i) {
81✔
2275
      if (pVgroup->vnodeGid[i].dnodeId == delDnodeId) {
68✔
2276
        vnIndex = i;
33✔
2277
        break;
33✔
2278
      }
2279
    }
2280

2281
    code = 0;
46✔
2282
    if (vnIndex != -1) {
46✔
2283
      mInfo("vgId:%d, vnode:%d will be removed from dnode:%d, force:%d", pVgroup->vgId, vnIndex, delDnodeId, force);
33!
2284
      SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName);
33✔
2285
      code = mndSetMoveVgroupInfoToTrans(pMnode, pTrans, pDb, pVgroup, vnIndex, pArray, force, unsafe);
33✔
2286
      mndReleaseDb(pMnode, pDb);
33✔
2287
    }
2288

2289
    sdbRelease(pMnode->pSdb, pVgroup);
46✔
2290

2291
    if (code != 0) {
46✔
2292
      sdbCancelFetch(pMnode->pSdb, pIter);
2✔
2293
      break;
2✔
2294
    }
2295
  }
2296

2297
  taosArrayDestroy(pArray);
16✔
2298
  TAOS_RETURN(code);
16✔
2299
}
2300

2301
static int32_t mndAddIncVgroupReplicaToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
111✔
2302
                                             int32_t newDnodeId) {
2303
  int32_t code = 0;
111✔
2304
  mInfo("vgId:%d, will add 1 vnode, replica:%d dnode:%d", pVgroup->vgId, pVgroup->replica, newDnodeId);
111!
2305

2306
  // assoc dnode
2307
  SVnodeGid *pGid = &pVgroup->vnodeGid[pVgroup->replica];
111✔
2308
  pVgroup->replica++;
111✔
2309
  pGid->dnodeId = newDnodeId;
111✔
2310
  pGid->syncState = TAOS_SYNC_STATE_OFFLINE;
111✔
2311
  pGid->nodeRole = TAOS_SYNC_ROLE_LEARNER;
111✔
2312

2313
  SSdbRaw *pVgRaw = mndVgroupActionEncode(pVgroup);
111✔
2314
  if (pVgRaw == NULL) {
111!
UNCOV
2315
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2316
    if (terrno != 0) code = terrno;
×
UNCOV
2317
    TAOS_RETURN(code);
×
2318
  }
2319
  if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
111!
UNCOV
2320
    sdbFreeRaw(pVgRaw);
×
UNCOV
2321
    TAOS_RETURN(code);
×
2322
  }
2323
  code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
111✔
2324
  if (code != 0) {
111!
UNCOV
2325
    mError("vgId:%d, failed to set raw status since %s at line:%d", pVgroup->vgId, tstrerror(code), __LINE__);
×
2326
    TAOS_RETURN(code);
×
2327
  }
2328

2329
  // learner
2330
  for (int32_t i = 0; i < pVgroup->replica - 1; ++i) {
366✔
2331
    TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, pVgroup, pVgroup->vnodeGid[i].dnodeId));
255!
2332
  }
2333
  TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pDb, pVgroup, pGid));
111!
2334

2335
  // voter
2336
  pGid->nodeRole = TAOS_SYNC_ROLE_VOTER;
111✔
2337
  TAOS_CHECK_RETURN(mndAddAlterVnodeTypeAction(pMnode, pTrans, pDb, pVgroup, pGid->dnodeId));
111!
2338
  for (int32_t i = 0; i < pVgroup->replica - 1; ++i) {
366✔
2339
    TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, pVgroup, pVgroup->vnodeGid[i].dnodeId));
255!
2340
  }
2341

2342
  // confirm
2343
  TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, pVgroup));
111!
2344

2345
  TAOS_RETURN(code);
111✔
2346
}
2347

2348
static int32_t mndAddDecVgroupReplicaFromTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
111✔
2349
                                               int32_t delDnodeId) {
2350
  int32_t code = 0;
111✔
2351
  mInfo("vgId:%d, will remove 1 vnode, replica:%d dnode:%d", pVgroup->vgId, pVgroup->replica, delDnodeId);
111!
2352

2353
  SVnodeGid *pGid = NULL;
111✔
2354
  SVnodeGid  delGid = {0};
111✔
2355
  for (int32_t i = 0; i < pVgroup->replica; ++i) {
188!
2356
    if (pVgroup->vnodeGid[i].dnodeId == delDnodeId) {
188✔
2357
      pGid = &pVgroup->vnodeGid[i];
111✔
2358
      break;
111✔
2359
    }
2360
  }
2361

2362
  if (pGid == NULL) return 0;
111!
2363

2364
  pVgroup->replica--;
111✔
2365
  memcpy(&delGid, pGid, sizeof(SVnodeGid));
111✔
2366
  memcpy(pGid, &pVgroup->vnodeGid[pVgroup->replica], sizeof(SVnodeGid));
111✔
2367
  memset(&pVgroup->vnodeGid[pVgroup->replica], 0, sizeof(SVnodeGid));
111✔
2368

2369
  SSdbRaw *pVgRaw = mndVgroupActionEncode(pVgroup);
111✔
2370
  if (pVgRaw == NULL) {
111!
UNCOV
2371
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2372
    if (terrno != 0) code = terrno;
×
2373
    TAOS_RETURN(code);
×
2374
  }
2375
  if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
111!
UNCOV
2376
    sdbFreeRaw(pVgRaw);
×
UNCOV
2377
    TAOS_RETURN(code);
×
2378
  }
2379
  code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
111✔
2380
  if (code != 0) {
111!
UNCOV
2381
    mError("vgId:%d, failed to set raw status since %s at line:%d", pVgroup->vgId, tstrerror(code), __LINE__);
×
UNCOV
2382
    TAOS_RETURN(code);
×
2383
  }
2384

2385
  TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pDb, pVgroup, &delGid, true));
111!
2386
  for (int32_t i = 0; i < pVgroup->replica; ++i) {
366✔
2387
    TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, pVgroup, pVgroup->vnodeGid[i].dnodeId));
255!
2388
  }
2389
  TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, pVgroup));
111!
2390

2391
  TAOS_RETURN(code);
111✔
2392
}
2393

2394
static int32_t mndRedistributeVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SVgObj *pVgroup, SDnodeObj *pNew1,
65✔
2395
                                     SDnodeObj *pOld1, SDnodeObj *pNew2, SDnodeObj *pOld2, SDnodeObj *pNew3,
2396
                                     SDnodeObj *pOld3) {
2397
  int32_t code = -1;
65✔
2398
  STrans *pTrans = NULL;
65✔
2399

2400
  pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_GLOBAL, pReq, "red-vgroup");
65✔
2401
  if (pTrans == NULL) {
65!
UNCOV
2402
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2403
    if (terrno != 0) code = terrno;
×
UNCOV
2404
    goto _OVER;
×
2405
  }
2406

2407
  mndTransSetDbName(pTrans, pVgroup->dbName, NULL);
65✔
2408
  TAOS_CHECK_GOTO(mndTransCheckConflictWithCompact(pMnode, pTrans), NULL, _OVER);
65✔
2409

2410
  mndTransSetSerial(pTrans);
64✔
2411
  mInfo("trans:%d, used to redistribute vgroup, vgId:%d", pTrans->id, pVgroup->vgId);
64!
2412

2413
  SVgObj newVg = {0};
64✔
2414
  memcpy(&newVg, pVgroup, sizeof(SVgObj));
64✔
2415
  mInfo("vgId:%d, vgroup info before redistribute, replica:%d", newVg.vgId, newVg.replica);
64!
2416
  for (int32_t i = 0; i < newVg.replica; ++i) {
206✔
2417
    mInfo("vgId:%d, vnode:%d dnode:%d role:%s", newVg.vgId, i, newVg.vnodeGid[i].dnodeId,
142!
2418
          syncStr(newVg.vnodeGid[i].syncState));
2419
  }
2420

2421
  if (pNew1 != NULL && pOld1 != NULL) {
64!
2422
    int32_t numOfVnodes = mndGetVnodesNum(pMnode, pNew1->id);
64✔
2423
    if (numOfVnodes >= pNew1->numOfSupportVnodes) {
64✔
2424
      mError("vgId:%d, no enough vnodes in dnode:%d, numOfVnodes:%d support:%d", newVg.vgId, pNew1->id, numOfVnodes,
1!
2425
             pNew1->numOfSupportVnodes);
2426
      code = TSDB_CODE_MND_NO_ENOUGH_VNODES;
1✔
2427
      goto _OVER;
1✔
2428
    }
2429

2430
    int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
63✔
2431
    if (pNew1->memAvail - vgMem - pNew1->memUsed <= 0) {
63!
UNCOV
2432
      mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
×
2433
             pVgroup->dbName, pVgroup->vgId, vgMem, pNew1->id, pNew1->memAvail, pNew1->memUsed);
2434
      code = TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE;
×
2435
      goto _OVER;
×
2436
    } else {
2437
      pNew1->memUsed += vgMem;
63✔
2438
    }
2439

2440
    TAOS_CHECK_GOTO(mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pNew1->id), NULL, _OVER);
63!
2441
    TAOS_CHECK_GOTO(mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pOld1->id), NULL, _OVER);
63!
2442
  }
2443

2444
  if (pNew2 != NULL && pOld2 != NULL) {
63!
2445
    int32_t numOfVnodes = mndGetVnodesNum(pMnode, pNew2->id);
16✔
2446
    if (numOfVnodes >= pNew2->numOfSupportVnodes) {
16!
UNCOV
2447
      mError("vgId:%d, no enough vnodes in dnode:%d, numOfVnodes:%d support:%d", newVg.vgId, pNew2->id, numOfVnodes,
×
2448
             pNew2->numOfSupportVnodes);
UNCOV
2449
      code = TSDB_CODE_MND_NO_ENOUGH_VNODES;
×
UNCOV
2450
      goto _OVER;
×
2451
    }
2452
    int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
16✔
2453
    if (pNew2->memAvail - vgMem - pNew2->memUsed <= 0) {
16!
2454
      mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
×
2455
             pVgroup->dbName, pVgroup->vgId, vgMem, pNew2->id, pNew2->memAvail, pNew2->memUsed);
UNCOV
2456
      code = TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE;
×
UNCOV
2457
      goto _OVER;
×
2458
    } else {
2459
      pNew2->memUsed += vgMem;
16✔
2460
    }
2461
    TAOS_CHECK_GOTO(mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pNew2->id), NULL, _OVER);
16!
2462
    TAOS_CHECK_GOTO(mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pOld2->id), NULL, _OVER);
16!
2463
  }
2464

2465
  if (pNew3 != NULL && pOld3 != NULL) {
63!
2466
    int32_t numOfVnodes = mndGetVnodesNum(pMnode, pNew3->id);
8✔
2467
    if (numOfVnodes >= pNew3->numOfSupportVnodes) {
8!
UNCOV
2468
      mError("vgId:%d, no enough vnodes in dnode:%d, numOfVnodes:%d support:%d", newVg.vgId, pNew3->id, numOfVnodes,
×
2469
             pNew3->numOfSupportVnodes);
UNCOV
2470
      code = TSDB_CODE_MND_NO_ENOUGH_VNODES;
×
UNCOV
2471
      goto _OVER;
×
2472
    }
2473
    int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
8✔
2474
    if (pNew3->memAvail - vgMem - pNew3->memUsed <= 0) {
8!
UNCOV
2475
      mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
×
2476
             pVgroup->dbName, pVgroup->vgId, vgMem, pNew3->id, pNew3->memAvail, pNew3->memUsed);
UNCOV
2477
      code = TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE;
×
UNCOV
2478
      goto _OVER;
×
2479
    } else {
2480
      pNew3->memUsed += vgMem;
8✔
2481
    }
2482
    TAOS_CHECK_GOTO(mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pNew3->id), NULL, _OVER);
8!
2483
    TAOS_CHECK_GOTO(mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pOld3->id), NULL, _OVER);
8!
2484
  }
2485

2486
  {
2487
    SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
63✔
2488
    if (pRaw == NULL) {
63!
UNCOV
2489
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2490
      if (terrno != 0) code = terrno;
×
UNCOV
2491
      goto _OVER;
×
2492
    }
2493
    if ((code = mndTransAppendCommitlog(pTrans, pRaw)) != 0) {
63!
UNCOV
2494
      sdbFreeRaw(pRaw);
×
UNCOV
2495
      goto _OVER;
×
2496
    }
2497
    code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
63✔
2498
    if (code != 0) {
63!
UNCOV
2499
      mError("vgId:%d, failed to set raw status since %s at line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
UNCOV
2500
      goto _OVER;
×
2501
    }
2502
  }
2503

2504
  mInfo("vgId:%d, vgroup info after redistribute, replica:%d", newVg.vgId, newVg.replica);
63!
2505
  for (int32_t i = 0; i < newVg.replica; ++i) {
202✔
2506
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
139!
2507
  }
2508

2509
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
63!
2510
  code = 0;
63✔
2511

2512
_OVER:
65✔
2513
  mndTransDrop(pTrans);
65✔
2514
  mndReleaseDb(pMnode, pDb);
65✔
2515
  TAOS_RETURN(code);
65✔
2516
}
2517

2518
static int32_t mndProcessRedistributeVgroupMsg(SRpcMsg *pReq) {
81✔
2519
  SMnode    *pMnode = pReq->info.node;
81✔
2520
  SDnodeObj *pNew1 = NULL;
81✔
2521
  SDnodeObj *pNew2 = NULL;
81✔
2522
  SDnodeObj *pNew3 = NULL;
81✔
2523
  SDnodeObj *pOld1 = NULL;
81✔
2524
  SDnodeObj *pOld2 = NULL;
81✔
2525
  SDnodeObj *pOld3 = NULL;
81✔
2526
  SVgObj    *pVgroup = NULL;
81✔
2527
  SDbObj    *pDb = NULL;
81✔
2528
  int32_t    code = -1;
81✔
2529
  int64_t    curMs = taosGetTimestampMs();
81✔
2530
  int32_t    newDnodeId[3] = {0};
81✔
2531
  int32_t    oldDnodeId[3] = {0};
81✔
2532
  int32_t    newIndex = -1;
81✔
2533
  int32_t    oldIndex = -1;
81✔
2534

2535
  SRedistributeVgroupReq req = {0};
81✔
2536
  if (tDeserializeSRedistributeVgroupReq(pReq->pCont, pReq->contLen, &req) != 0) {
81!
UNCOV
2537
    code = TSDB_CODE_INVALID_MSG;
×
2538
    goto _OVER;
×
2539
  }
2540

2541
  mInfo("vgId:%d, start to redistribute vgroup to dnode %d:%d:%d", req.vgId, req.dnodeId1, req.dnodeId2, req.dnodeId3);
81!
2542
  if ((code = mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_REDISTRIBUTE_VGROUP)) != 0) {
81✔
2543
    goto _OVER;
1✔
2544
  }
2545

2546
  pVgroup = mndAcquireVgroup(pMnode, req.vgId);
80✔
2547
  if (pVgroup == NULL) {
80✔
2548
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
3✔
2549
    if (terrno != 0) code = terrno;
3!
2550
    goto _OVER;
3✔
2551
  }
2552

2553
  pDb = mndAcquireDb(pMnode, pVgroup->dbName);
77✔
2554
  if (pDb == NULL) {
77!
UNCOV
2555
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2556
    if (terrno != 0) code = terrno;
×
2557
    goto _OVER;
×
2558
  }
2559

2560
  if (pVgroup->replica == 1) {
77✔
2561
    if (req.dnodeId1 <= 0 || req.dnodeId2 > 0 || req.dnodeId3 > 0) {
29!
UNCOV
2562
      code = TSDB_CODE_MND_INVALID_REPLICA;
×
UNCOV
2563
      goto _OVER;
×
2564
    }
2565

2566
    if (req.dnodeId1 == pVgroup->vnodeGid[0].dnodeId) {
29✔
2567
      // terrno = TSDB_CODE_MND_VGROUP_UN_CHANGED;
2568
      code = 0;
1✔
2569
      goto _OVER;
1✔
2570
    }
2571

2572
    pNew1 = mndAcquireDnode(pMnode, req.dnodeId1);
28✔
2573
    if (pNew1 == NULL) {
28!
UNCOV
2574
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2575
      if (terrno != 0) code = terrno;
×
UNCOV
2576
      goto _OVER;
×
2577
    }
2578
    if (!mndIsDnodeOnline(pNew1, curMs)) {
28!
2579
      code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2580
      goto _OVER;
×
2581
    }
2582

2583
    pOld1 = mndAcquireDnode(pMnode, pVgroup->vnodeGid[0].dnodeId);
28✔
2584
    if (pOld1 == NULL) {
28!
UNCOV
2585
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2586
      if (terrno != 0) code = terrno;
×
UNCOV
2587
      goto _OVER;
×
2588
    }
2589
    if (!mndIsDnodeOnline(pOld1, curMs)) {
28✔
2590
      code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
2✔
2591
      goto _OVER;
2✔
2592
    }
2593

2594
    code = mndRedistributeVgroup(pMnode, pReq, pDb, pVgroup, pNew1, pOld1, NULL, NULL, NULL, NULL);
26✔
2595

2596
  } else if (pVgroup->replica == 3) {
48!
2597
    if (req.dnodeId1 <= 0 || req.dnodeId2 <= 0 || req.dnodeId3 <= 0) {
48!
2598
      code = TSDB_CODE_MND_INVALID_REPLICA;
4✔
2599
      goto _OVER;
4✔
2600
    }
2601

2602
    if (req.dnodeId1 == req.dnodeId2 || req.dnodeId1 == req.dnodeId3 || req.dnodeId2 == req.dnodeId3) {
44!
2603
      code = TSDB_CODE_MND_INVALID_REPLICA;
1✔
2604
      goto _OVER;
1✔
2605
    }
2606

2607
    if (req.dnodeId1 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId1 != pVgroup->vnodeGid[1].dnodeId &&
43✔
2608
        req.dnodeId1 != pVgroup->vnodeGid[2].dnodeId) {
22✔
2609
      newDnodeId[++newIndex] = req.dnodeId1;
19✔
2610
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
19!
2611
    }
2612

2613
    if (req.dnodeId2 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[1].dnodeId &&
43✔
2614
        req.dnodeId2 != pVgroup->vnodeGid[2].dnodeId) {
29✔
2615
      newDnodeId[++newIndex] = req.dnodeId2;
22✔
2616
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
22!
2617
    }
2618

2619
    if (req.dnodeId3 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId3 != pVgroup->vnodeGid[1].dnodeId &&
43✔
2620
        req.dnodeId3 != pVgroup->vnodeGid[2].dnodeId) {
35✔
2621
      newDnodeId[++newIndex] = req.dnodeId3;
29✔
2622
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
29!
2623
    }
2624

2625
    if (req.dnodeId1 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[0].dnodeId &&
43✔
2626
        req.dnodeId3 != pVgroup->vnodeGid[0].dnodeId) {
22✔
2627
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[0].dnodeId;
21✔
2628
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
21!
2629
    }
2630

2631
    if (req.dnodeId1 != pVgroup->vnodeGid[1].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[1].dnodeId &&
43✔
2632
        req.dnodeId3 != pVgroup->vnodeGid[1].dnodeId) {
29✔
2633
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[1].dnodeId;
22✔
2634
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
22!
2635
    }
2636

2637
    if (req.dnodeId1 != pVgroup->vnodeGid[2].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[2].dnodeId &&
43✔
2638
        req.dnodeId3 != pVgroup->vnodeGid[2].dnodeId) {
33✔
2639
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[2].dnodeId;
27✔
2640
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
27!
2641
    }
2642

2643
    if (newDnodeId[0] != 0) {
43✔
2644
      pNew1 = mndAcquireDnode(pMnode, newDnodeId[0]);
42✔
2645
      if (pNew1 == NULL) {
42!
2646
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2647
        if (terrno != 0) code = terrno;
×
UNCOV
2648
        goto _OVER;
×
2649
      }
2650
      if (!mndIsDnodeOnline(pNew1, curMs)) {
42✔
2651
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
1✔
2652
        goto _OVER;
1✔
2653
      }
2654
    }
2655

2656
    if (newDnodeId[1] != 0) {
42✔
2657
      pNew2 = mndAcquireDnode(pMnode, newDnodeId[1]);
18✔
2658
      if (pNew2 == NULL) {
18!
UNCOV
2659
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2660
        if (terrno != 0) code = terrno;
×
UNCOV
2661
        goto _OVER;
×
2662
      }
2663
      if (!mndIsDnodeOnline(pNew2, curMs)) {
18!
2664
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2665
        goto _OVER;
×
2666
      }
2667
    }
2668

2669
    if (newDnodeId[2] != 0) {
42✔
2670
      pNew3 = mndAcquireDnode(pMnode, newDnodeId[2]);
10✔
2671
      if (pNew3 == NULL) {
10!
UNCOV
2672
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2673
        if (terrno != 0) code = terrno;
×
2674
        goto _OVER;
×
2675
      }
2676
      if (!mndIsDnodeOnline(pNew3, curMs)) {
10!
UNCOV
2677
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2678
        goto _OVER;
×
2679
      }
2680
    }
2681

2682
    if (oldDnodeId[0] != 0) {
42✔
2683
      pOld1 = mndAcquireDnode(pMnode, oldDnodeId[0]);
41✔
2684
      if (pOld1 == NULL) {
41!
UNCOV
2685
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2686
        if (terrno != 0) code = terrno;
×
2687
        goto _OVER;
×
2688
      }
2689
      if (!mndIsDnodeOnline(pOld1, curMs)) {
41✔
2690
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
2✔
2691
        goto _OVER;
2✔
2692
      }
2693
    }
2694

2695
    if (oldDnodeId[1] != 0) {
40✔
2696
      pOld2 = mndAcquireDnode(pMnode, oldDnodeId[1]);
16✔
2697
      if (pOld2 == NULL) {
16!
UNCOV
2698
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2699
        if (terrno != 0) code = terrno;
×
UNCOV
2700
        goto _OVER;
×
2701
      }
2702
      if (!mndIsDnodeOnline(pOld2, curMs)) {
16!
UNCOV
2703
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2704
        goto _OVER;
×
2705
      }
2706
    }
2707

2708
    if (oldDnodeId[2] != 0) {
40✔
2709
      pOld3 = mndAcquireDnode(pMnode, oldDnodeId[2]);
8✔
2710
      if (pOld3 == NULL) {
8!
UNCOV
2711
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2712
        if (terrno != 0) code = terrno;
×
UNCOV
2713
        goto _OVER;
×
2714
      }
2715
      if (!mndIsDnodeOnline(pOld3, curMs)) {
8!
UNCOV
2716
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2717
        goto _OVER;
×
2718
      }
2719
    }
2720

2721
    if (pNew1 == NULL && pOld1 == NULL && pNew2 == NULL && pOld2 == NULL && pNew3 == NULL && pOld3 == NULL) {
40!
2722
      // terrno = TSDB_CODE_MND_VGROUP_UN_CHANGED;
2723
      code = 0;
1✔
2724
      goto _OVER;
1✔
2725
    }
2726

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

2729
  } else {
UNCOV
2730
    code = TSDB_CODE_MND_REQ_REJECTED;
×
UNCOV
2731
    goto _OVER;
×
2732
  }
2733

2734
  if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
65✔
2735

2736
  char obj[33] = {0};
65✔
2737
  (void)tsnprintf(obj, sizeof(obj), "%d", req.vgId);
65✔
2738

2739
  auditRecord(pReq, pMnode->clusterId, "RedistributeVgroup", "", obj, req.sql, req.sqlLen);
65✔
2740

2741
_OVER:
81✔
2742
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
81✔
2743
    mError("vgId:%d, failed to redistribute to dnode %d:%d:%d since %s", req.vgId, req.dnodeId1, req.dnodeId2,
16!
2744
           req.dnodeId3, tstrerror(code));
2745
  }
2746

2747
  mndReleaseDnode(pMnode, pNew1);
81✔
2748
  mndReleaseDnode(pMnode, pNew2);
81✔
2749
  mndReleaseDnode(pMnode, pNew3);
81✔
2750
  mndReleaseDnode(pMnode, pOld1);
81✔
2751
  mndReleaseDnode(pMnode, pOld2);
81✔
2752
  mndReleaseDnode(pMnode, pOld3);
81✔
2753
  mndReleaseVgroup(pMnode, pVgroup);
81✔
2754
  mndReleaseDb(pMnode, pDb);
81✔
2755
  tFreeSRedistributeVgroupReq(&req);
81✔
2756

2757
  TAOS_RETURN(code);
81✔
2758
}
2759

2760
static void *mndBuildSForceBecomeFollowerReq(SMnode *pMnode, SVgObj *pVgroup, int32_t dnodeId, int32_t *pContLen) {
12✔
2761
  SForceBecomeFollowerReq balanceReq = {
12✔
2762
      .vgId = pVgroup->vgId,
12✔
2763
  };
2764

2765
  int32_t contLen = tSerializeSForceBecomeFollowerReq(NULL, 0, &balanceReq);
12✔
2766
  if (contLen < 0) {
12!
UNCOV
2767
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
2768
    return NULL;
×
2769
  }
2770
  contLen += sizeof(SMsgHead);
12✔
2771

2772
  void *pReq = taosMemoryMalloc(contLen);
12!
2773
  if (pReq == NULL) {
12!
UNCOV
2774
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
2775
    return NULL;
×
2776
  }
2777

2778
  SMsgHead *pHead = pReq;
12✔
2779
  pHead->contLen = htonl(contLen);
12✔
2780
  pHead->vgId = htonl(pVgroup->vgId);
12✔
2781

2782
  if (tSerializeSForceBecomeFollowerReq((char *)pReq + sizeof(SMsgHead), contLen, &balanceReq) < 0) {
12!
UNCOV
2783
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
2784
    taosMemoryFree(pReq);
×
UNCOV
2785
    return NULL;
×
2786
  }
2787
  *pContLen = contLen;
12✔
2788
  return pReq;
12✔
2789
}
2790

2791
int32_t mndAddBalanceVgroupLeaderAction(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup, int32_t dnodeId) {
12✔
2792
  int32_t    code = 0;
12✔
2793
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
12✔
2794
  if (pDnode == NULL) {
12!
UNCOV
2795
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2796
    if (terrno != 0) code = terrno;
×
UNCOV
2797
    TAOS_RETURN(code);
×
2798
  }
2799

2800
  STransAction action = {0};
12✔
2801
  action.epSet = mndGetDnodeEpset(pDnode);
12✔
2802
  mndReleaseDnode(pMnode, pDnode);
12✔
2803

2804
  int32_t contLen = 0;
12✔
2805
  void   *pReq = mndBuildSForceBecomeFollowerReq(pMnode, pVgroup, dnodeId, &contLen);
12✔
2806
  if (pReq == NULL) {
12!
UNCOV
2807
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2808
    if (terrno != 0) code = terrno;
×
UNCOV
2809
    TAOS_RETURN(code);
×
2810
  }
2811

2812
  action.pCont = pReq;
12✔
2813
  action.contLen = contLen;
12✔
2814
  action.msgType = TDMT_SYNC_FORCE_FOLLOWER;
12✔
2815

2816
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
12!
UNCOV
2817
    taosMemoryFree(pReq);
×
UNCOV
2818
    TAOS_RETURN(code);
×
2819
  }
2820

2821
  TAOS_RETURN(code);
12✔
2822
}
2823

2824
int32_t mndAddVgroupBalanceToTrans(SMnode *pMnode, SVgObj *pVgroup, STrans *pTrans) {
14✔
2825
  int32_t code = 0;
14✔
2826
  SSdb   *pSdb = pMnode->pSdb;
14✔
2827

2828
  int32_t vgid = pVgroup->vgId;
14✔
2829
  int8_t  replica = pVgroup->replica;
14✔
2830

2831
  if (pVgroup->replica <= 1) {
14✔
2832
    mInfo("trans:%d, vgid:%d no need to balance, replica:%d", pTrans->id, vgid, replica);
1!
2833
    return -1;
1✔
2834
  }
2835

2836
  int32_t dnodeId = 0;
13✔
2837

2838
  for (int i = 0; i < replica; i++) {
26✔
2839
    if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_LEADER) {
25✔
2840
      dnodeId = pVgroup->vnodeGid[i].dnodeId;
12✔
2841
      break;
12✔
2842
    }
2843
  }
2844

2845
  bool       exist = false;
13✔
2846
  bool       online = false;
13✔
2847
  int64_t    curMs = taosGetTimestampMs();
13✔
2848
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
13✔
2849
  if (pDnode != NULL) {
13✔
2850
    exist = true;
12✔
2851
    online = mndIsDnodeOnline(pDnode, curMs);
12✔
2852
    mndReleaseDnode(pMnode, pDnode);
12✔
2853
  }
2854

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

2858
    if ((code = mndAddBalanceVgroupLeaderAction(pMnode, pTrans, pVgroup, dnodeId)) != 0) {
12!
UNCOV
2859
      mError("trans:%d, vgid:%d failed to be balanced to dnode:%d", pTrans->id, vgid, dnodeId);
×
UNCOV
2860
      TAOS_RETURN(code);
×
2861
    }
2862

2863
    SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName);
12✔
2864
    if (pDb == NULL) {
12!
UNCOV
2865
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2866
      if (terrno != 0) code = terrno;
×
UNCOV
2867
      mError("trans:%d, vgid:%d failed to be balanced to dnode:%d, because db not exist", pTrans->id, vgid, dnodeId);
×
UNCOV
2868
      TAOS_RETURN(code);
×
2869
    }
2870

2871
    mndReleaseDb(pMnode, pDb);
12✔
2872
  } else {
2873
    mInfo("trans:%d, vgid:%d cant be balanced to dnode:%d, exist:%d, online:%d", pTrans->id, vgid, dnodeId, exist,
1!
2874
          online);
2875
  }
2876

2877
  TAOS_RETURN(code);
13✔
2878
}
2879

2880
extern int32_t mndProcessVgroupBalanceLeaderMsgImp(SRpcMsg *pReq);
2881

2882
int32_t mndProcessVgroupBalanceLeaderMsg(SRpcMsg *pReq) { return mndProcessVgroupBalanceLeaderMsgImp(pReq); }
5✔
2883

2884
#ifndef TD_ENTERPRISE
2885
int32_t mndProcessVgroupBalanceLeaderMsgImp(SRpcMsg *pReq) { return 0; }
2886
#endif
2887

2888
static int32_t mndCheckDnodeMemory(SMnode *pMnode, SDbObj *pOldDb, SDbObj *pNewDb, SVgObj *pOldVgroup,
368✔
2889
                                   SVgObj *pNewVgroup, SArray *pArray) {
2890
  for (int32_t i = 0; i < (int32_t)taosArrayGetSize(pArray); ++i) {
944✔
2891
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
576✔
2892
    bool       inVgroup = false;
576✔
2893
    int64_t    oldMemUsed = 0;
576✔
2894
    int64_t    newMemUsed = 0;
576✔
2895
    mDebug("db:%s, vgId:%d, check dnode:%d, avail:%" PRId64 " used:%" PRId64, pNewVgroup->dbName, pNewVgroup->vgId,
576✔
2896
           pDnode->id, pDnode->memAvail, pDnode->memUsed);
2897
    for (int32_t j = 0; j < pOldVgroup->replica; ++j) {
1,776✔
2898
      SVnodeGid *pVgId = &pOldVgroup->vnodeGid[j];
1,200✔
2899
      if (pDnode->id == pVgId->dnodeId) {
1,200✔
2900
        oldMemUsed = mndGetVgroupMemory(pMnode, pOldDb, pOldVgroup);
576✔
2901
        inVgroup = true;
576✔
2902
      }
2903
    }
2904
    for (int32_t j = 0; j < pNewVgroup->replica; ++j) {
1,776✔
2905
      SVnodeGid *pVgId = &pNewVgroup->vnodeGid[j];
1,200✔
2906
      if (pDnode->id == pVgId->dnodeId) {
1,200✔
2907
        newMemUsed = mndGetVgroupMemory(pMnode, pNewDb, pNewVgroup);
576✔
2908
        inVgroup = true;
576✔
2909
      }
2910
    }
2911

2912
    mDebug("db:%s, vgId:%d, memory in dnode:%d, oldUsed:%" PRId64 ", newUsed:%" PRId64, pNewVgroup->dbName,
576✔
2913
           pNewVgroup->vgId, pDnode->id, oldMemUsed, newMemUsed);
2914

2915
    pDnode->memUsed = pDnode->memUsed - oldMemUsed + newMemUsed;
576✔
2916
    if (pDnode->memAvail - pDnode->memUsed <= 0) {
576!
2917
      mError("db:%s, vgId:%d, no enough memory in dnode:%d, avail:%" PRId64 " used:%" PRId64, pNewVgroup->dbName,
×
2918
             pNewVgroup->vgId, pDnode->id, pDnode->memAvail, pDnode->memUsed);
UNCOV
2919
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE);
×
2920
    } else if (inVgroup) {
576!
2921
      mInfo("db:%s, vgId:%d, memory in dnode:%d, avail:%" PRId64 " used:%" PRId64, pNewVgroup->dbName, pNewVgroup->vgId,
576!
2922
            pDnode->id, pDnode->memAvail, pDnode->memUsed);
2923
    } else {
2924
    }
2925
  }
2926
  return 0;
368✔
2927
}
2928

2929
int32_t mndBuildAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pOldDb, SDbObj *pNewDb, SVgObj *pVgroup,
430✔
2930
                                  SArray *pArray, SVgObj *pNewVgroup) {
2931
  int32_t code = 0;
430✔
2932
  memcpy(pNewVgroup, pVgroup, sizeof(SVgObj));
430✔
2933

2934
  if (pVgroup->replica <= 0 || pVgroup->replica == pNewDb->cfg.replications) {
430!
2935
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfigAction(pMnode, pTrans, pNewDb, pVgroup));
368!
2936
    TAOS_CHECK_RETURN(mndCheckDnodeMemory(pMnode, pOldDb, pNewDb, pNewVgroup, pVgroup, pArray));
368!
2937
    return 0;
368✔
2938
  }
2939

2940
  mndTransSetSerial(pTrans);
62✔
2941

2942
  if (pNewDb->cfg.replications == 3) {
62✔
2943
    mInfo("db:%s, vgId:%d, will add 2 vnodes, vn:0 dnode:%d", pVgroup->dbName, pVgroup->vgId,
58!
2944
          pVgroup->vnodeGid[0].dnodeId);
2945

2946
    // add second
2947
    if (pNewVgroup->replica == 1) {
58!
2948
      TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, pNewVgroup, pArray));
58!
2949
    }
2950

2951
    // learner stage
2952
    pNewVgroup->vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
58✔
2953
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
58✔
2954
    TAOS_CHECK_RETURN(
58!
2955
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
2956

2957
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &pNewVgroup->vnodeGid[1]));
58!
2958

2959
    // follower stage
2960
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
58✔
2961
    TAOS_CHECK_RETURN(mndAddAlterVnodeTypeAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
58!
2962
    TAOS_CHECK_RETURN(
58!
2963
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
2964

2965
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
58!
2966

2967
    // add third
2968
    if (pNewVgroup->replica == 2) {
58!
2969
      TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, pNewVgroup, pArray));
58✔
2970
    }
2971

2972
    pNewVgroup->vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
47✔
2973
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
47✔
2974
    pNewVgroup->vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_VOTER;
47✔
2975
    TAOS_CHECK_RETURN(
47!
2976
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
2977
    TAOS_CHECK_RETURN(
47!
2978
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
2979
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &pNewVgroup->vnodeGid[2]));
47!
2980

2981
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
47!
2982
  } else if (pNewDb->cfg.replications == 1) {
4!
2983
    mInfo("db:%s, vgId:%d, will remove 2 vnodes, vn:0 dnode:%d vn:1 dnode:%d vn:2 dnode:%d", pVgroup->dbName,
4!
2984
          pVgroup->vgId, pVgroup->vnodeGid[0].dnodeId, pVgroup->vnodeGid[1].dnodeId, pVgroup->vnodeGid[2].dnodeId);
2985

2986
    SVnodeGid del1 = {0};
4✔
2987
    SVnodeGid del2 = {0};
4✔
2988
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroup(pMnode, pTrans, pNewVgroup, pArray, &del1));
4!
2989
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &del1, true));
4!
2990
    TAOS_CHECK_RETURN(
4!
2991
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
2992
    TAOS_CHECK_RETURN(
4!
2993
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
2994
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
4!
2995

2996
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroup(pMnode, pTrans, pNewVgroup, pArray, &del2));
4!
2997
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &del2, true));
4!
2998
    TAOS_CHECK_RETURN(
4!
2999
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3000
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
4!
UNCOV
3001
  } else if (pNewDb->cfg.replications == 2) {
×
3002
    mInfo("db:%s, vgId:%d, will add 1 vnode, vn:0 dnode:%d", pVgroup->dbName, pVgroup->vgId,
×
3003
          pVgroup->vnodeGid[0].dnodeId);
3004

3005
    // add second
3006
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, pNewVgroup, pArray));
×
3007

3008
    // learner stage
UNCOV
3009
    pNewVgroup->vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3010
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
UNCOV
3011
    TAOS_CHECK_RETURN(
×
3012
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3013

UNCOV
3014
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &pNewVgroup->vnodeGid[1]));
×
3015

3016
    // follower stage
3017
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3018
    TAOS_CHECK_RETURN(mndAddAlterVnodeTypeAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
×
3019
    TAOS_CHECK_RETURN(
×
3020
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3021

3022
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
×
3023
  } else {
3024
    return -1;
×
3025
  }
3026

3027
  mndSortVnodeGid(pNewVgroup);
51✔
3028

3029
  {
3030
    SSdbRaw *pVgRaw = mndVgroupActionEncode(pNewVgroup);
51✔
3031
    if (pVgRaw == NULL) {
51!
3032
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3033
      if (terrno != 0) code = terrno;
×
3034
      TAOS_RETURN(code);
×
3035
    }
3036
    if ((code = mndTransAppendCommitlog(pTrans, pVgRaw)) != 0) {
51!
3037
      sdbFreeRaw(pVgRaw);
×
3038
      TAOS_RETURN(code);
×
3039
    }
3040
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
51✔
3041
    if (code != 0) {
51!
UNCOV
3042
      mError("vgId:%d, failed to set raw status since %s at line:%d", pNewVgroup->vgId, tstrerror(code), __LINE__);
×
3043
      TAOS_RETURN(code);
×
3044
    }
3045
  }
3046

3047
  TAOS_RETURN(code);
51✔
3048
}
3049

UNCOV
3050
int32_t mndBuildRaftAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pOldDb, SDbObj *pNewDb, SVgObj *pVgroup,
×
3051
                                      SArray *pArray) {
UNCOV
3052
  int32_t code = 0;
×
3053
  SVgObj  newVgroup = {0};
×
3054
  memcpy(&newVgroup, pVgroup, sizeof(SVgObj));
×
3055

3056
  if (pVgroup->replica <= 0 || pVgroup->replica == pNewDb->cfg.replications) {
×
3057
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfigAction(pMnode, pTrans, pNewDb, pVgroup));
×
UNCOV
3058
    TAOS_CHECK_RETURN(mndCheckDnodeMemory(pMnode, pOldDb, pNewDb, &newVgroup, pVgroup, pArray));
×
3059
    return 0;
×
3060
  }
3061

UNCOV
3062
  mndTransSetSerial(pTrans);
×
3063

3064
  mInfo("trans:%d, vgId:%d, alter vgroup, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id, pVgroup->vgId,
×
3065
        pVgroup->syncConfChangeVer, pVgroup->version, pVgroup->replica);
3066

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

3071
    // add second
UNCOV
3072
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVgroup, pArray));
×
3073
    // add third
UNCOV
3074
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVgroup, pArray));
×
3075

3076
    // add learner stage
3077
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3078
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3079
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3080
    TAOS_CHECK_RETURN(
×
3081
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3082
    mInfo("trans:%d, vgId:%d, add change config, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id,
×
3083
          pVgroup->vgId, newVgroup.syncConfChangeVer, pVgroup->version, pVgroup->replica);
3084
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &newVgroup.vnodeGid[1]));
×
UNCOV
3085
    mInfo("trans:%d, vgId:%d, create vnode, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id, pVgroup->vgId,
×
3086
          newVgroup.syncConfChangeVer, pVgroup->version, pVgroup->replica);
3087
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &newVgroup.vnodeGid[2]));
×
3088
    mInfo("trans:%d, vgId:%d, create vnode, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id, pVgroup->vgId,
×
3089
          newVgroup.syncConfChangeVer, pVgroup->version, pVgroup->replica);
3090

3091
    // check learner
UNCOV
3092
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3093
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3094
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3095
    TAOS_CHECK_RETURN(
×
3096
        mndAddCheckLearnerCatchupAction(pMnode, pTrans, pNewDb, &newVgroup, newVgroup.vnodeGid[1].dnodeId));
UNCOV
3097
    TAOS_CHECK_RETURN(
×
3098
        mndAddCheckLearnerCatchupAction(pMnode, pTrans, pNewDb, &newVgroup, newVgroup.vnodeGid[2].dnodeId));
3099

3100
    // change raft type
UNCOV
3101
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3102
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3103
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
UNCOV
3104
    TAOS_CHECK_RETURN(
×
3105
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3106

3107
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
3108

3109
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3110
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3111
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3112
    TAOS_CHECK_RETURN(
×
3113
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3114

3115
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
3116

3117
    SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
×
UNCOV
3118
    if (pVgRaw == NULL) {
×
3119
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3120
      if (terrno != 0) code = terrno;
×
UNCOV
3121
      TAOS_RETURN(code);
×
3122
    }
UNCOV
3123
    if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
×
3124
      sdbFreeRaw(pVgRaw);
×
3125
      TAOS_RETURN(code);
×
3126
    }
UNCOV
3127
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
3128
    if (code != 0) {
×
UNCOV
3129
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
3130
             __LINE__);
3131
      TAOS_RETURN(code);
×
3132
    }
3133
  } else if (newVgroup.replica == 3 && pNewDb->cfg.replications == 1) {
×
3134
    mInfo("db:%s, vgId:%d, will remove 2 vnodes, vn:0 dnode:%d vn:1 dnode:%d vn:2 dnode:%d", pVgroup->dbName,
×
3135
          pVgroup->vgId, pVgroup->vnodeGid[0].dnodeId, pVgroup->vnodeGid[1].dnodeId, pVgroup->vnodeGid[2].dnodeId);
3136

UNCOV
3137
    SVnodeGid del1 = {0};
×
3138
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroupWithoutSave(pMnode, pTrans, &newVgroup, pArray, &del1));
×
3139

UNCOV
3140
    TAOS_CHECK_RETURN(
×
3141
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3142

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

UNCOV
3145
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &del1, true));
×
3146

UNCOV
3147
    SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
×
UNCOV
3148
    if (pVgRaw == NULL) {
×
UNCOV
3149
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3150
      if (terrno != 0) code = terrno;
×
UNCOV
3151
      TAOS_RETURN(code);
×
3152
    }
UNCOV
3153
    if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
×
UNCOV
3154
      sdbFreeRaw(pVgRaw);
×
UNCOV
3155
      TAOS_RETURN(code);
×
3156
    }
UNCOV
3157
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
UNCOV
3158
    if (code != 0) {
×
3159
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
3160
             __LINE__);
3161
      TAOS_RETURN(code);
×
3162
    }
3163

3164
    SVnodeGid del2 = {0};
×
3165
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroupWithoutSave(pMnode, pTrans, &newVgroup, pArray, &del2));
×
3166

UNCOV
3167
    TAOS_CHECK_RETURN(
×
3168
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3169

3170
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
3171

UNCOV
3172
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &del2, true));
×
3173

UNCOV
3174
    pVgRaw = mndVgroupActionEncode(&newVgroup);
×
UNCOV
3175
    if (pVgRaw == NULL) {
×
3176
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3177
      if (terrno != 0) code = terrno;
×
UNCOV
3178
      TAOS_RETURN(code);
×
3179
    }
UNCOV
3180
    if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
×
UNCOV
3181
      sdbFreeRaw(pVgRaw);
×
UNCOV
3182
      TAOS_RETURN(code);
×
3183
    }
UNCOV
3184
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
UNCOV
3185
    if (code != 0) {
×
UNCOV
3186
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
3187
             __LINE__);
3188
      TAOS_RETURN(code);
×
3189
    }
3190
  } else {
UNCOV
3191
    return -1;
×
3192
  }
3193

3194
  mndSortVnodeGid(&newVgroup);
×
3195

3196
  {
UNCOV
3197
    SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
×
UNCOV
3198
    if (pVgRaw == NULL) {
×
3199
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3200
      if (terrno != 0) code = terrno;
×
3201
      TAOS_RETURN(code);
×
3202
    }
UNCOV
3203
    if ((code = mndTransAppendCommitlog(pTrans, pVgRaw)) != 0) {
×
UNCOV
3204
      sdbFreeRaw(pVgRaw);
×
UNCOV
3205
      TAOS_RETURN(code);
×
3206
    }
UNCOV
3207
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
UNCOV
3208
    if (code != 0) {
×
3209
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
3210
             __LINE__);
3211
      TAOS_RETURN(code);
×
3212
    }
3213
  }
3214

UNCOV
3215
  TAOS_RETURN(code);
×
3216
}
3217

3218
int32_t mndBuildRestoreAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *db, SVgObj *pVgroup, SDnodeObj *pDnode,
10✔
3219
                                         SDnodeObj *pAnotherDnode) {
3220
  int32_t code = 0;
10✔
3221
  SVgObj  newVgroup = {0};
10✔
3222
  memcpy(&newVgroup, pVgroup, sizeof(SVgObj));
10✔
3223

3224
  mInfo("db:%s, vgId:%d, restore vnodes, vn:0 dnode:%d", pVgroup->dbName, pVgroup->vgId, pVgroup->vnodeGid[0].dnodeId);
10!
3225

3226
  if (newVgroup.replica == 1) {
10!
UNCOV
3227
    int selected = 0;
×
UNCOV
3228
    for (int i = 0; i < newVgroup.replica; i++) {
×
UNCOV
3229
      newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3230
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
UNCOV
3231
        selected = i;
×
3232
      }
3233
    }
3234
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, db, &newVgroup, &newVgroup.vnodeGid[selected]));
×
3235
  } else if (newVgroup.replica == 2) {
10!
UNCOV
3236
    for (int i = 0; i < newVgroup.replica; i++) {
×
3237
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
3238
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3239
      } else {
UNCOV
3240
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3241
      }
3242
    }
UNCOV
3243
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pAnotherDnode));
×
3244

3245
    for (int i = 0; i < newVgroup.replica; i++) {
×
3246
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
UNCOV
3247
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3248
      } else {
UNCOV
3249
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3250
      }
3251
    }
3252
    TAOS_CHECK_RETURN(mndRestoreAddCreateVnodeAction(pMnode, pTrans, db, &newVgroup, pDnode));
×
3253

UNCOV
3254
    for (int i = 0; i < newVgroup.replica; i++) {
×
UNCOV
3255
      newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3256
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
3257
      }
3258
    }
3259
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pDnode));
×
3260
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pAnotherDnode));
×
3261
  } else if (newVgroup.replica == 3) {
10!
3262
    for (int i = 0; i < newVgroup.replica; i++) {
40✔
3263
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
30✔
3264
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_LEARNER;
10✔
3265
      } else {
3266
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
20✔
3267
      }
3268
    }
3269
    TAOS_CHECK_RETURN(mndRestoreAddCreateVnodeAction(pMnode, pTrans, db, &newVgroup, pDnode));
10!
3270

3271
    for (int i = 0; i < newVgroup.replica; i++) {
40✔
3272
      newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
30✔
3273
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
30✔
3274
      }
3275
    }
3276
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pDnode));
10!
3277
  }
3278
  SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
10✔
3279
  if (pVgRaw == NULL) {
10!
UNCOV
3280
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3281
    if (terrno != 0) code = terrno;
×
UNCOV
3282
    TAOS_RETURN(code);
×
3283
  }
3284
  if ((code = mndTransAppendCommitlog(pTrans, pVgRaw)) != 0) {
10!
UNCOV
3285
    sdbFreeRaw(pVgRaw);
×
UNCOV
3286
    TAOS_RETURN(code);
×
3287
  }
3288
  code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
10✔
3289
  if (code != 0) {
10!
UNCOV
3290
    mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code), __LINE__);
×
UNCOV
3291
    TAOS_RETURN(code);
×
3292
  }
3293

3294
  TAOS_RETURN(code);
10✔
3295
}
3296

UNCOV
3297
static int32_t mndAddAdjustVnodeHashRangeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) {
×
UNCOV
3298
  return 0;
×
3299
}
3300

3301
typedef int32_t (*FpTransActionCb)(STrans *pTrans, SSdbRaw *pRaw);
3302

3303
static int32_t mndAddVgStatusAction(STrans *pTrans, SVgObj *pVg, ESdbStatus vgStatus, ETrnStage stage) {
99✔
3304
  int32_t         code = 0;
99✔
3305
  FpTransActionCb appendActionCb = (stage == TRN_STAGE_COMMIT_ACTION) ? mndTransAppendCommitlog : mndTransAppendRedolog;
99✔
3306
  SSdbRaw        *pRaw = mndVgroupActionEncode(pVg);
99✔
3307
  if (pRaw == NULL) {
99!
UNCOV
3308
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3309
    if (terrno != 0) code = terrno;
×
UNCOV
3310
    goto _err;
×
3311
  }
3312
  if ((code = appendActionCb(pTrans, pRaw)) != 0) goto _err;
99!
3313
  code = sdbSetRawStatus(pRaw, vgStatus);
99✔
3314
  if (code != 0) {
99!
UNCOV
3315
    mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", pVg->vgId, tstrerror(code), __LINE__);
×
UNCOV
3316
    goto _err;
×
3317
  }
3318
  pRaw = NULL;
99✔
3319
  TAOS_RETURN(code);
99✔
UNCOV
3320
_err:
×
UNCOV
3321
  sdbFreeRaw(pRaw);
×
UNCOV
3322
  TAOS_RETURN(code);
×
3323
}
3324

3325
static int32_t mndAddDbStatusAction(STrans *pTrans, SDbObj *pDb, ESdbStatus dbStatus, ETrnStage stage) {
41✔
3326
  int32_t         code = 0;
41✔
3327
  FpTransActionCb appendActionCb = (stage == TRN_STAGE_COMMIT_ACTION) ? mndTransAppendCommitlog : mndTransAppendRedolog;
41✔
3328
  SSdbRaw        *pRaw = mndDbActionEncode(pDb);
41✔
3329
  if (pRaw == NULL) {
41!
UNCOV
3330
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3331
    if (terrno != 0) code = terrno;
×
UNCOV
3332
    goto _err;
×
3333
  }
3334
  if ((code = appendActionCb(pTrans, pRaw)) != 0) goto _err;
41!
3335
  code = sdbSetRawStatus(pRaw, dbStatus);
41✔
3336
  if (code != 0) {
41!
UNCOV
3337
    mError("db:%s, failed to set raw status to ready, error:%s, line:%d", pDb->name, tstrerror(code), __LINE__);
×
UNCOV
3338
    goto _err;
×
3339
  }
3340
  pRaw = NULL;
41✔
3341
  TAOS_RETURN(code);
41✔
UNCOV
3342
_err:
×
UNCOV
3343
  sdbFreeRaw(pRaw);
×
UNCOV
3344
  TAOS_RETURN(code);
×
3345
}
3346

3347
int32_t mndSplitVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SVgObj *pVgroup) {
27✔
3348
  int32_t code = -1;
27✔
3349
  STrans *pTrans = NULL;
27✔
3350
  SDbObj  dbObj = {0};
27✔
3351
  SArray *pArray = mndBuildDnodesArray(pMnode, 0, NULL);
27✔
3352

3353
  int32_t numOfStreams = 0;
27✔
3354
  if ((code = mndGetNumOfStreams(pMnode, pDb->name, &numOfStreams)) != 0) {
27!
3355
    goto _OVER;
×
3356
  }
3357
  if (numOfStreams > 0) {
27!
UNCOV
3358
    code = TSDB_CODE_MND_STREAM_MUST_BE_DELETED;
×
UNCOV
3359
    goto _OVER;
×
3360
  }
3361

3362
#if defined(USE_S3)
3363
  extern int8_t tsS3Enabled;
3364
  if (tsS3Enabled) {
27!
UNCOV
3365
    code = TSDB_CODE_OPS_NOT_SUPPORT;
×
UNCOV
3366
    mError("vgId:%d, db:%s, s3 exists, split vgroup not allowed", pVgroup->vgId, pVgroup->dbName);
×
UNCOV
3367
    goto _OVER;
×
3368
  }
3369
#endif
3370

3371
  if (pDb->cfg.withArbitrator) {
27!
UNCOV
3372
    code = TSDB_CODE_OPS_NOT_SUPPORT;
×
UNCOV
3373
    mError("vgId:%d, db:%s, with arbitrator, split vgroup not allowed", pVgroup->vgId, pVgroup->dbName);
×
UNCOV
3374
    goto _OVER;
×
3375
  }
3376

3377
  pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB, pReq, "split-vgroup");
27✔
3378
  if (pTrans == NULL) {
27!
UNCOV
3379
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3380
    if (terrno != 0) code = terrno;
×
UNCOV
3381
    goto _OVER;
×
3382
  }
3383
  mndTransSetSerial(pTrans);
27✔
3384
  mInfo("trans:%d, used to split vgroup, vgId:%d", pTrans->id, pVgroup->vgId);
27!
3385

3386
  mndTransSetDbName(pTrans, pDb->name, NULL);
27✔
3387
  TAOS_CHECK_GOTO(mndTransCheckConflictWithCompact(pMnode, pTrans), NULL, _OVER);
27✔
3388

3389
  SVgObj newVg1 = {0};
26✔
3390
  memcpy(&newVg1, pVgroup, sizeof(SVgObj));
26✔
3391
  mInfo("vgId:%d, vgroup info before split, replica:%d hashBegin:%u hashEnd:%u", newVg1.vgId, newVg1.replica,
26!
3392
        newVg1.hashBegin, newVg1.hashEnd);
3393
  for (int32_t i = 0; i < newVg1.replica; ++i) {
98✔
3394
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg1.vgId, i, newVg1.vnodeGid[i].dnodeId);
72!
3395
  }
3396

3397
  if (newVg1.replica == 1) {
26✔
3398
    TAOS_CHECK_GOTO(mndAddVnodeToVgroup(pMnode, pTrans, &newVg1, pArray), NULL, _OVER);
3!
3399

3400
    newVg1.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
3✔
3401
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[0].dnodeId), NULL,
3!
3402
                    _OVER);
3403
    TAOS_CHECK_GOTO(mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg1, &newVg1.vnodeGid[1]), NULL, _OVER);
3!
3404

3405
    newVg1.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
3✔
3406
    TAOS_CHECK_GOTO(mndAddAlterVnodeTypeAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[1].dnodeId), NULL, _OVER);
3!
3407
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[0].dnodeId), NULL,
3!
3408
                    _OVER);
3409

3410
    TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg1), NULL, _OVER);
3!
3411
  } else if (newVg1.replica == 3) {
23!
3412
    SVnodeGid del1 = {0};
23✔
3413
    TAOS_CHECK_GOTO(mndRemoveVnodeFromVgroup(pMnode, pTrans, &newVg1, pArray, &del1), NULL, _OVER);
23!
3414
    TAOS_CHECK_GOTO(mndAddDropVnodeAction(pMnode, pTrans, pDb, &newVg1, &del1, true), NULL, _OVER);
23!
3415
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[0].dnodeId), NULL,
23!
3416
                    _OVER);
3417
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[1].dnodeId), NULL,
23!
3418
                    _OVER);
3419
  } else {
3420
    goto _OVER;
×
3421
  }
3422

3423
  for (int32_t i = 0; i < newVg1.replica; ++i) {
78✔
3424
    TAOS_CHECK_GOTO(mndAddDisableVnodeWriteAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[i].dnodeId), NULL,
52!
3425
                    _OVER);
3426
  }
3427
  TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg1), NULL, _OVER);
26!
3428

3429
  SVgObj newVg2 = {0};
26✔
3430
  memcpy(&newVg2, &newVg1, sizeof(SVgObj));
26✔
3431
  newVg1.replica = 1;
26✔
3432
  newVg1.hashEnd = newVg1.hashBegin / 2 + newVg1.hashEnd / 2;
26✔
3433
  memset(&newVg1.vnodeGid[1], 0, sizeof(SVnodeGid));
26✔
3434

3435
  newVg2.replica = 1;
26✔
3436
  newVg2.hashBegin = newVg1.hashEnd + 1;
26✔
3437
  memcpy(&newVg2.vnodeGid[0], &newVg2.vnodeGid[1], sizeof(SVnodeGid));
26✔
3438
  memset(&newVg2.vnodeGid[1], 0, sizeof(SVnodeGid));
26✔
3439

3440
  mInfo("vgId:%d, vgroup info after split, replica:%d hashrange:[%u, %u] vnode:0 dnode:%d", newVg1.vgId, newVg1.replica,
26!
3441
        newVg1.hashBegin, newVg1.hashEnd, newVg1.vnodeGid[0].dnodeId);
3442
  for (int32_t i = 0; i < newVg1.replica; ++i) {
52✔
3443
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg1.vgId, i, newVg1.vnodeGid[i].dnodeId);
26!
3444
  }
3445
  mInfo("vgId:%d, vgroup info after split, replica:%d hashrange:[%u, %u] vnode:0 dnode:%d", newVg2.vgId, newVg2.replica,
26!
3446
        newVg2.hashBegin, newVg2.hashEnd, newVg2.vnodeGid[0].dnodeId);
3447
  for (int32_t i = 0; i < newVg1.replica; ++i) {
52✔
3448
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg2.vgId, i, newVg2.vnodeGid[i].dnodeId);
26!
3449
  }
3450

3451
  // alter vgId and hash range
3452
  int32_t maxVgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP);
26✔
3453
  int32_t srcVgId = newVg1.vgId;
26✔
3454
  newVg1.vgId = maxVgId;
26✔
3455
  TAOS_CHECK_GOTO(mndAddNewVgPrepareAction(pMnode, pTrans, &newVg1), NULL, _OVER);
26!
3456
  TAOS_CHECK_GOTO(mndAddAlterVnodeHashRangeAction(pMnode, pTrans, srcVgId, &newVg1), NULL, _OVER);
26!
3457

3458
  maxVgId++;
26✔
3459
  srcVgId = newVg2.vgId;
26✔
3460
  newVg2.vgId = maxVgId;
26✔
3461
  TAOS_CHECK_GOTO(mndAddNewVgPrepareAction(pMnode, pTrans, &newVg2), NULL, _OVER);
26!
3462
  TAOS_CHECK_GOTO(mndAddAlterVnodeHashRangeAction(pMnode, pTrans, srcVgId, &newVg2), NULL, _OVER);
26!
3463

3464
  TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg1), NULL, _OVER);
26!
3465
  TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg2), NULL, _OVER);
26!
3466

3467
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg1, SDB_STATUS_READY, TRN_STAGE_REDO_ACTION), NULL, _OVER);
26!
3468
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg2, SDB_STATUS_READY, TRN_STAGE_REDO_ACTION), NULL, _OVER);
26!
3469
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, pVgroup, SDB_STATUS_DROPPED, TRN_STAGE_REDO_ACTION), NULL, _OVER);
26!
3470

3471
  // update db status
3472
  memcpy(&dbObj, pDb, sizeof(SDbObj));
26✔
3473
  if (dbObj.cfg.pRetensions != NULL) {
26!
3474
    dbObj.cfg.pRetensions = taosArrayDup(pDb->cfg.pRetensions, NULL);
×
3475
    if (dbObj.cfg.pRetensions == NULL) {
×
UNCOV
3476
      code = terrno;
×
UNCOV
3477
      goto _OVER;
×
3478
    }
3479
  }
3480
  dbObj.vgVersion++;
26✔
3481
  dbObj.updateTime = taosGetTimestampMs();
26✔
3482
  dbObj.cfg.numOfVgroups++;
26✔
3483
  TAOS_CHECK_GOTO(mndAddDbStatusAction(pTrans, &dbObj, SDB_STATUS_READY, TRN_STAGE_REDO_ACTION), NULL, _OVER);
26!
3484

3485
  // adjust vgroup replica
3486
  if (pDb->cfg.replications != newVg1.replica) {
26✔
3487
    SVgObj tmpGroup = {0};
23✔
3488
    TAOS_CHECK_GOTO(mndBuildAlterVgroupAction(pMnode, pTrans, pDb, pDb, &newVg1, pArray, &tmpGroup), NULL, _OVER);
23!
3489
  } else {
3490
    TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg1, SDB_STATUS_READY, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
3!
3491
  }
3492

3493
  if (pDb->cfg.replications != newVg2.replica) {
26✔
3494
    SVgObj tmpGroup = {0};
23✔
3495
    TAOS_CHECK_GOTO(mndBuildAlterVgroupAction(pMnode, pTrans, pDb, pDb, &newVg2, pArray, &tmpGroup), NULL, _OVER);
23✔
3496
  } else {
3497
    TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg2, SDB_STATUS_READY, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
3!
3498
  }
3499

3500
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, pVgroup, SDB_STATUS_DROPPED, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
15!
3501

3502
  // commit db status
3503
  dbObj.vgVersion++;
15✔
3504
  dbObj.updateTime = taosGetTimestampMs();
15✔
3505
  TAOS_CHECK_GOTO(mndAddDbStatusAction(pTrans, &dbObj, SDB_STATUS_READY, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
15!
3506

3507
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
15!
3508
  code = 0;
15✔
3509

3510
_OVER:
27✔
3511
  taosArrayDestroy(pArray);
27✔
3512
  mndTransDrop(pTrans);
27✔
3513
  taosArrayDestroy(dbObj.cfg.pRetensions);
27✔
3514
  TAOS_RETURN(code);
27✔
3515
}
3516

3517
extern int32_t mndProcessSplitVgroupMsgImp(SRpcMsg *pReq);
3518

3519
static int32_t mndProcessSplitVgroupMsg(SRpcMsg *pReq) { return mndProcessSplitVgroupMsgImp(pReq); }
27✔
3520

3521
#ifndef TD_ENTERPRISE
3522
int32_t mndProcessSplitVgroupMsgImp(SRpcMsg *pReq) { return 0; }
3523
#endif
3524

3525
static int32_t mndSetBalanceVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
24✔
3526
                                              SDnodeObj *pSrc, SDnodeObj *pDst) {
3527
  int32_t code = 0;
24✔
3528
  SVgObj  newVg = {0};
24✔
3529
  memcpy(&newVg, pVgroup, sizeof(SVgObj));
24✔
3530
  mInfo("vgId:%d, vgroup info before balance, replica:%d", newVg.vgId, newVg.replica);
24!
3531
  for (int32_t i = 0; i < newVg.replica; ++i) {
68✔
3532
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
44!
3533
  }
3534

3535
  TAOS_CHECK_RETURN(mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pDst->id));
24!
3536
  TAOS_CHECK_RETURN(mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pSrc->id));
24!
3537

3538
  {
3539
    SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
24✔
3540
    if (pRaw == NULL) {
24!
UNCOV
3541
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3542
      if (terrno != 0) code = terrno;
×
3543
      TAOS_RETURN(code);
×
3544
    }
3545
    if ((code = mndTransAppendCommitlog(pTrans, pRaw)) != 0) {
24!
UNCOV
3546
      sdbFreeRaw(pRaw);
×
UNCOV
3547
      TAOS_RETURN(code);
×
3548
    }
3549
    code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
24✔
3550
    if (code != 0) {
24!
UNCOV
3551
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
3552
      TAOS_RETURN(code);
×
3553
    }
3554
  }
3555

3556
  mInfo("vgId:%d, vgroup info after balance, replica:%d", newVg.vgId, newVg.replica);
24!
3557
  for (int32_t i = 0; i < newVg.replica; ++i) {
68✔
3558
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
44!
3559
  }
3560
  TAOS_RETURN(code);
24✔
3561
}
3562

3563
static int32_t mndBalanceVgroupBetweenDnode(SMnode *pMnode, STrans *pTrans, SDnodeObj *pSrc, SDnodeObj *pDst,
24✔
3564
                                            SHashObj *pBalancedVgroups) {
3565
  void   *pIter = NULL;
24✔
3566
  int32_t code = -1;
24✔
3567
  SSdb   *pSdb = pMnode->pSdb;
24✔
3568

3569
  while (1) {
16✔
3570
    SVgObj *pVgroup = NULL;
40✔
3571
    pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
40✔
3572
    if (pIter == NULL) break;
40!
3573
    if (taosHashGet(pBalancedVgroups, &pVgroup->vgId, sizeof(int32_t)) != NULL) {
40✔
3574
      sdbRelease(pSdb, pVgroup);
15✔
3575
      continue;
16✔
3576
    }
3577

3578
    bool existInSrc = false;
25✔
3579
    bool existInDst = false;
25✔
3580
    for (int32_t i = 0; i < pVgroup->replica; ++i) {
70✔
3581
      SVnodeGid *pGid = &pVgroup->vnodeGid[i];
45✔
3582
      if (pGid->dnodeId == pSrc->id) existInSrc = true;
45✔
3583
      if (pGid->dnodeId == pDst->id) existInDst = true;
45!
3584
    }
3585

3586
    if (!existInSrc || existInDst) {
25!
3587
      sdbRelease(pSdb, pVgroup);
1✔
3588
      continue;
1✔
3589
    }
3590

3591
    SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName);
24✔
3592
    if (pDb == NULL) {
24!
UNCOV
3593
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3594
      if (terrno != 0) code = terrno;
×
UNCOV
3595
      mError("vgId:%d, balance vgroup can't find db obj dbName:%s", pVgroup->vgId, pVgroup->dbName);
×
UNCOV
3596
      goto _OUT;
×
3597
    }
3598

3599
    if (pDb->cfg.withArbitrator) {
24!
UNCOV
3600
      mInfo("vgId:%d, db:%s, with arbitrator, balance vgroup not allowed", pVgroup->vgId, pVgroup->dbName);
×
3601
      goto _OUT;
×
3602
    }
3603

3604
    code = mndSetBalanceVgroupInfoToTrans(pMnode, pTrans, pDb, pVgroup, pSrc, pDst);
24✔
3605
    if (code == 0) {
24!
3606
      code = taosHashPut(pBalancedVgroups, &pVgroup->vgId, sizeof(int32_t), &pVgroup->vgId, sizeof(int32_t));
24✔
3607
    }
3608

UNCOV
3609
  _OUT:
×
3610
    mndReleaseDb(pMnode, pDb);
24✔
3611
    sdbRelease(pSdb, pVgroup);
24✔
3612
    sdbCancelFetch(pSdb, pIter);
24✔
3613
    break;
24✔
3614
  }
3615

3616
  return code;
24✔
3617
}
3618

3619
static int32_t mndBalanceVgroup(SMnode *pMnode, SRpcMsg *pReq, SArray *pArray) {
15✔
3620
  int32_t   code = -1;
15✔
3621
  int32_t   numOfVgroups = 0;
15✔
3622
  STrans   *pTrans = NULL;
15✔
3623
  SHashObj *pBalancedVgroups = NULL;
15✔
3624

3625
  pBalancedVgroups = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
15✔
3626
  if (pBalancedVgroups == NULL) goto _OVER;
15!
3627

3628
  pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_GLOBAL, pReq, "balance-vgroup");
15✔
3629
  if (pTrans == NULL) {
15!
UNCOV
3630
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3631
    if (terrno != 0) code = terrno;
×
UNCOV
3632
    goto _OVER;
×
3633
  }
3634
  mndTransSetSerial(pTrans);
15✔
3635
  mInfo("trans:%d, used to balance vgroup", pTrans->id);
15!
3636
  TAOS_CHECK_GOTO(mndTransCheckConflict(pMnode, pTrans), NULL, _OVER);
15!
3637
  TAOS_CHECK_GOTO(mndTransCheckConflictWithCompact(pMnode, pTrans), NULL, _OVER);
15✔
3638

3639
  while (1) {
24✔
3640
    taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
38✔
3641
    for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
163✔
3642
      SDnodeObj *pDnode = taosArrayGet(pArray, i);
125✔
3643
      mInfo("dnode:%d, equivalent vnodes:%d others:%d support:%d, score:%f", pDnode->id, pDnode->numOfVnodes,
125!
3644
            pDnode->numOfSupportVnodes, pDnode->numOfOtherNodes, mndGetDnodeScore(pDnode, 0, 1));
3645
    }
3646

3647
    SDnodeObj *pSrc = taosArrayGet(pArray, taosArrayGetSize(pArray) - 1);
38✔
3648
    SDnodeObj *pDst = taosArrayGet(pArray, 0);
38✔
3649

3650
    float srcScore = mndGetDnodeScore(pSrc, -1, 1);
38✔
3651
    float dstScore = mndGetDnodeScore(pDst, 1, 1);
38✔
3652
    mInfo("trans:%d, after balance, src dnode:%d score:%f, dst dnode:%d score:%f", pTrans->id, pSrc->id, dstScore,
38!
3653
          pDst->id, dstScore);
3654

3655
    if (srcScore > dstScore - 0.000001) {
38✔
3656
      code = mndBalanceVgroupBetweenDnode(pMnode, pTrans, pSrc, pDst, pBalancedVgroups);
24✔
3657
      if (code == 0) {
24!
3658
        pSrc->numOfVnodes--;
24✔
3659
        pDst->numOfVnodes++;
24✔
3660
        numOfVgroups++;
24✔
3661
        continue;
24✔
3662
      } else {
3663
        mInfo("trans:%d, no vgroup need to balance from dnode:%d to dnode:%d", pTrans->id, pSrc->id, pDst->id);
×
3664
        break;
×
3665
      }
3666
    } else {
3667
      mInfo("trans:%d, no vgroup need to balance any more", pTrans->id);
14!
3668
      break;
14✔
3669
    }
3670
  }
3671

3672
  if (numOfVgroups <= 0) {
14!
UNCOV
3673
    mInfo("no need to balance vgroup");
×
UNCOV
3674
    code = 0;
×
3675
  } else {
3676
    mInfo("start to balance vgroup, numOfVgroups:%d", numOfVgroups);
14!
3677
    if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER;
14!
3678
    code = TSDB_CODE_ACTION_IN_PROGRESS;
14✔
3679
  }
3680

3681
_OVER:
15✔
3682
  taosHashCleanup(pBalancedVgroups);
15✔
3683
  mndTransDrop(pTrans);
15✔
3684
  TAOS_RETURN(code);
15✔
3685
}
3686

3687
static int32_t mndProcessBalanceVgroupMsg(SRpcMsg *pReq) {
19✔
3688
  SMnode *pMnode = pReq->info.node;
19✔
3689
  int32_t code = -1;
19✔
3690
  SArray *pArray = NULL;
19✔
3691
  void   *pIter = NULL;
19✔
3692
  int64_t curMs = taosGetTimestampMs();
19✔
3693

3694
  SBalanceVgroupReq req = {0};
19✔
3695
  if (tDeserializeSBalanceVgroupReq(pReq->pCont, pReq->contLen, &req) != 0) {
19!
UNCOV
3696
    code = TSDB_CODE_INVALID_MSG;
×
UNCOV
3697
    goto _OVER;
×
3698
  }
3699

3700
  mInfo("start to balance vgroup");
19!
3701
  if ((code = mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_BALANCE_VGROUP)) != 0) {
19✔
3702
    goto _OVER;
1✔
3703
  }
3704

3705
  while (1) {
51✔
3706
    SDnodeObj *pDnode = NULL;
69✔
3707
    pIter = sdbFetch(pMnode->pSdb, SDB_DNODE, pIter, (void **)&pDnode);
69✔
3708
    if (pIter == NULL) break;
69✔
3709
    if (!mndIsDnodeOnline(pDnode, curMs)) {
53✔
3710
      sdbCancelFetch(pMnode->pSdb, pIter);
2✔
3711
      code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
2✔
3712
      mError("failed to balance vgroup since %s, dnode:%d", terrstr(), pDnode->id);
2!
3713
      sdbRelease(pMnode->pSdb, pDnode);
2✔
3714
      goto _OVER;
2✔
3715
    }
3716

3717
    sdbRelease(pMnode->pSdb, pDnode);
51✔
3718
  }
3719

3720
  pArray = mndBuildDnodesArray(pMnode, 0, NULL);
16✔
3721
  if (pArray == NULL) {
16!
UNCOV
3722
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3723
    if (terrno != 0) code = terrno;
×
UNCOV
3724
    goto _OVER;
×
3725
  }
3726

3727
  if (taosArrayGetSize(pArray) < 2) {
16✔
3728
    mInfo("no need to balance vgroup since dnode num less than 2");
1!
3729
    code = 0;
1✔
3730
  } else {
3731
    code = mndBalanceVgroup(pMnode, pReq, pArray);
15✔
3732
  }
3733

3734
  auditRecord(pReq, pMnode->clusterId, "balanceVgroup", "", "", req.sql, req.sqlLen);
16✔
3735

3736
_OVER:
19✔
3737
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
19✔
3738
    mError("failed to balance vgroup since %s", tstrerror(code));
4!
3739
  }
3740

3741
  taosArrayDestroy(pArray);
19✔
3742
  tFreeSBalanceVgroupReq(&req);
19✔
3743
  TAOS_RETURN(code);
19✔
3744
}
3745

3746
bool mndVgroupInDb(SVgObj *pVgroup, int64_t dbUid) { return !pVgroup->isTsma && pVgroup->dbUid == dbUid; }
487,733!
3747

3748
bool mndVgroupInDnode(SVgObj *pVgroup, int32_t dnodeId) {
16✔
3749
  for (int i = 0; i < pVgroup->replica; i++) {
42✔
3750
    if (pVgroup->vnodeGid[i].dnodeId == dnodeId) return true;
36✔
3751
  }
3752
  return false;
6✔
3753
}
3754

3755
static void *mndBuildCompactVnodeReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen, int64_t compactTs,
18✔
3756
                                     STimeWindow tw, bool metaOnly) {
3757
  SCompactVnodeReq compactReq = {0};
18✔
3758
  compactReq.dbUid = pDb->uid;
18✔
3759
  compactReq.compactStartTime = compactTs;
18✔
3760
  compactReq.tw = tw;
18✔
3761
  compactReq.metaOnly = metaOnly;
18✔
3762
  tstrncpy(compactReq.db, pDb->name, TSDB_DB_FNAME_LEN);
18✔
3763

3764
  mInfo("vgId:%d, build compact vnode config req", pVgroup->vgId);
18!
3765
  int32_t contLen = tSerializeSCompactVnodeReq(NULL, 0, &compactReq);
18✔
3766
  if (contLen < 0) {
18!
UNCOV
3767
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
3768
    return NULL;
×
3769
  }
3770
  contLen += sizeof(SMsgHead);
18✔
3771

3772
  void *pReq = taosMemoryMalloc(contLen);
18!
3773
  if (pReq == NULL) {
18!
UNCOV
3774
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
3775
    return NULL;
×
3776
  }
3777

3778
  SMsgHead *pHead = pReq;
18✔
3779
  pHead->contLen = htonl(contLen);
18✔
3780
  pHead->vgId = htonl(pVgroup->vgId);
18✔
3781

3782
  if (tSerializeSCompactVnodeReq((char *)pReq + sizeof(SMsgHead), contLen, &compactReq) < 0) {
18!
UNCOV
3783
    taosMemoryFree(pReq);
×
UNCOV
3784
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
3785
    return NULL;
×
3786
  }
3787
  *pContLen = contLen;
18✔
3788
  return pReq;
18✔
3789
}
3790

3791
static int32_t mndAddCompactVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int64_t compactTs,
18✔
3792
                                        STimeWindow tw, bool metaOnly) {
3793
  int32_t      code = 0;
18✔
3794
  STransAction action = {0};
18✔
3795
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
18✔
3796

3797
  int32_t contLen = 0;
18✔
3798
  void   *pReq = mndBuildCompactVnodeReq(pMnode, pDb, pVgroup, &contLen, compactTs, tw, metaOnly);
18✔
3799
  if (pReq == NULL) {
18!
UNCOV
3800
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3801
    if (terrno != 0) code = terrno;
×
UNCOV
3802
    TAOS_RETURN(code);
×
3803
  }
3804

3805
  action.pCont = pReq;
18✔
3806
  action.contLen = contLen;
18✔
3807
  action.msgType = TDMT_VND_COMPACT;
18✔
3808

3809
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
18!
UNCOV
3810
    taosMemoryFree(pReq);
×
UNCOV
3811
    TAOS_RETURN(code);
×
3812
  }
3813

3814
  TAOS_RETURN(code);
18✔
3815
}
3816

3817
int32_t mndBuildCompactVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int64_t compactTs,
18✔
3818
                                    STimeWindow tw, bool metaOnly) {
3819
  TAOS_CHECK_RETURN(mndAddCompactVnodeAction(pMnode, pTrans, pDb, pVgroup, compactTs, tw, metaOnly));
18!
3820
  return 0;
18✔
3821
}
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