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

taosdata / TDengine / #4852

14 Nov 2025 08:06AM UTC coverage: 63.812% (+0.06%) from 63.754%
#4852

push

travis-ci

guanshengliang
Merge branch '3.0' into cover/3.0

355 of 675 new or added lines in 18 files covered. (52.59%)

3142 existing lines in 128 files now uncovered.

149263 of 233910 relevant lines covered (63.81%)

118719500.98 hits per line

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

67.09
/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 60
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) {
490,573✔
51
  SSdbTable table = {
490,573✔
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);
490,573✔
63
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_REPLICA_RSP, mndTransProcessRsp);
490,573✔
64
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_CONFIG_RSP, mndTransProcessRsp);
490,573✔
65
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_CONFIRM_RSP, mndTransProcessRsp);
490,573✔
66
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_HASHRANGE_RSP, mndTransProcessRsp);
490,573✔
67
  mndSetMsgHandle(pMnode, TDMT_DND_DROP_VNODE_RSP, mndTransProcessRsp);
490,573✔
68
  mndSetMsgHandle(pMnode, TDMT_VND_COMPACT_RSP, mndTransProcessRsp);
490,573✔
69
  mndSetMsgHandle(pMnode, TDMT_VND_SCAN_RSP, mndTransProcessRsp);
490,573✔
70
  mndSetMsgHandle(pMnode, TDMT_VND_DISABLE_WRITE_RSP, mndTransProcessRsp);
490,573✔
71
  mndSetMsgHandle(pMnode, TDMT_SYNC_FORCE_FOLLOWER_RSP, mndTransProcessRsp);
490,573✔
72
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_ELECTBASELINE_RSP, mndTransProcessRsp);
490,573✔
73
  
74
  mndSetMsgHandle(pMnode, TDMT_DND_ALTER_VNODE_TYPE_RSP, mndTransProcessRsp);
490,573✔
75
  mndSetMsgHandle(pMnode, TDMT_DND_CHECK_VNODE_LEARNER_CATCHUP_RSP, mndTransProcessRsp);
490,573✔
76
  mndSetMsgHandle(pMnode, TDMT_SYNC_CONFIG_CHANGE_RSP, mndTransProcessRsp);
490,573✔
77

78
  mndSetMsgHandle(pMnode, TDMT_MND_REDISTRIBUTE_VGROUP, mndProcessRedistributeVgroupMsg);
490,573✔
79
  mndSetMsgHandle(pMnode, TDMT_MND_SPLIT_VGROUP, mndProcessSplitVgroupMsg);
490,573✔
80
  // mndSetMsgHandle(pMnode, TDMT_MND_BALANCE_VGROUP, mndProcessVgroupBalanceLeaderMsg);
81
  mndSetMsgHandle(pMnode, TDMT_MND_BALANCE_VGROUP, mndProcessBalanceVgroupMsg);
490,573✔
82
  mndSetMsgHandle(pMnode, TDMT_MND_BALANCE_VGROUP_LEADER, mndProcessVgroupBalanceLeaderMsg);
490,573✔
83

84
  mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_VGROUP, mndRetrieveVgroups);
490,573✔
85
  mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_VGROUP, mndCancelGetNextVgroup);
490,573✔
86
  mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_VNODES, mndRetrieveVnodes);
490,573✔
87
  mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_VNODES, mndCancelGetNextVnode);
490,573✔
88

89
  return sdbSetTable(pMnode->pSdb, table);
490,573✔
90
}
91

92
void mndCleanupVgroup(SMnode *pMnode) {}
489,760✔
93

94
SSdbRaw *mndVgroupActionEncode(SVgObj *pVgroup) {
11,570,571✔
95
  int32_t code = 0;
11,570,571✔
96
  int32_t lino = 0;
11,570,571✔
97
  terrno = TSDB_CODE_OUT_OF_MEMORY;
11,570,571✔
98

99
  SSdbRaw *pRaw = sdbAllocRaw(SDB_VGROUP, VGROUP_VER_NUMBER, sizeof(SVgObj) + VGROUP_RESERVE_SIZE);
11,570,571✔
100
  if (pRaw == NULL) goto _OVER;
11,570,571✔
101

102
  int32_t dataPos = 0;
11,570,571✔
103
  SDB_SET_INT32(pRaw, dataPos, pVgroup->vgId, _OVER)
11,570,571✔
104
  SDB_SET_INT64(pRaw, dataPos, pVgroup->createdTime, _OVER)
11,570,571✔
105
  SDB_SET_INT64(pRaw, dataPos, pVgroup->updateTime, _OVER)
11,570,571✔
106
  SDB_SET_INT32(pRaw, dataPos, pVgroup->version, _OVER)
11,570,571✔
107
  SDB_SET_INT32(pRaw, dataPos, pVgroup->hashBegin, _OVER)
11,570,571✔
108
  SDB_SET_INT32(pRaw, dataPos, pVgroup->hashEnd, _OVER)
11,570,571✔
109
  SDB_SET_BINARY(pRaw, dataPos, pVgroup->dbName, TSDB_DB_FNAME_LEN, _OVER)
11,570,571✔
110
  SDB_SET_INT64(pRaw, dataPos, pVgroup->dbUid, _OVER)
11,570,571✔
111
  SDB_SET_INT8(pRaw, dataPos, pVgroup->isTsma, _OVER)
11,570,571✔
112
  SDB_SET_INT8(pRaw, dataPos, pVgroup->replica, _OVER)
11,570,571✔
113
  for (int8_t i = 0; i < pVgroup->replica; ++i) {
25,459,082✔
114
    SVnodeGid *pVgid = &pVgroup->vnodeGid[i];
13,888,511✔
115
    SDB_SET_INT32(pRaw, dataPos, pVgid->dnodeId, _OVER)
13,888,511✔
116
  }
117
  SDB_SET_INT32(pRaw, dataPos, pVgroup->syncConfChangeVer, _OVER)
11,570,571✔
118
  SDB_SET_INT32(pRaw, dataPos, pVgroup->mountVgId, _OVER)
11,570,571✔
119
  SDB_SET_RESERVE(pRaw, dataPos, VGROUP_RESERVE_SIZE, _OVER)
11,570,571✔
120
  SDB_SET_DATALEN(pRaw, dataPos, _OVER)
11,570,571✔
121

122
  terrno = 0;
11,570,571✔
123

124
_OVER:
11,570,571✔
125
  if (terrno != 0) {
11,570,571✔
126
    mError("vgId:%d, failed to encode to raw:%p since %s", pVgroup->vgId, pRaw, terrstr());
×
127
    sdbFreeRaw(pRaw);
×
128
    return NULL;
×
129
  }
130

131
  mTrace("vgId:%d, encode to raw:%p, row:%p", pVgroup->vgId, pRaw, pVgroup);
11,570,571✔
132
  return pRaw;
11,570,571✔
133
}
134

135
SSdbRow *mndVgroupActionDecode(SSdbRaw *pRaw) {
10,889,708✔
136
  int32_t code = 0;
10,889,708✔
137
  int32_t lino = 0;
10,889,708✔
138
  terrno = TSDB_CODE_OUT_OF_MEMORY;
10,889,708✔
139
  SSdbRow *pRow = NULL;
10,889,708✔
140
  SVgObj  *pVgroup = NULL;
10,889,708✔
141

142
  int8_t sver = 0;
10,889,708✔
143
  if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto _OVER;
10,889,708✔
144

145
  if (sver < 1 || sver > VGROUP_VER_NUMBER) {
10,889,708✔
146
    terrno = TSDB_CODE_SDB_INVALID_DATA_VER;
×
147
    goto _OVER;
×
148
  }
149

150
  pRow = sdbAllocRow(sizeof(SVgObj));
10,889,708✔
151
  if (pRow == NULL) goto _OVER;
10,889,708✔
152

153
  pVgroup = sdbGetRowObj(pRow);
10,889,708✔
154
  if (pVgroup == NULL) goto _OVER;
10,889,708✔
155

156
  int32_t dataPos = 0;
10,889,708✔
157
  SDB_GET_INT32(pRaw, dataPos, &pVgroup->vgId, _OVER)
10,889,708✔
158
  SDB_GET_INT64(pRaw, dataPos, &pVgroup->createdTime, _OVER)
10,889,708✔
159
  SDB_GET_INT64(pRaw, dataPos, &pVgroup->updateTime, _OVER)
10,889,708✔
160
  SDB_GET_INT32(pRaw, dataPos, &pVgroup->version, _OVER)
10,889,708✔
161
  SDB_GET_INT32(pRaw, dataPos, &pVgroup->hashBegin, _OVER)
10,889,708✔
162
  SDB_GET_INT32(pRaw, dataPos, &pVgroup->hashEnd, _OVER)
10,889,708✔
163
  SDB_GET_BINARY(pRaw, dataPos, pVgroup->dbName, TSDB_DB_FNAME_LEN, _OVER)
10,889,708✔
164
  SDB_GET_INT64(pRaw, dataPos, &pVgroup->dbUid, _OVER)
10,889,708✔
165
  SDB_GET_INT8(pRaw, dataPos, &pVgroup->isTsma, _OVER)
10,889,708✔
166
  SDB_GET_INT8(pRaw, dataPos, &pVgroup->replica, _OVER)
10,889,708✔
167
  for (int8_t i = 0; i < pVgroup->replica; ++i) {
24,362,187✔
168
    SVnodeGid *pVgid = &pVgroup->vnodeGid[i];
13,472,479✔
169
    SDB_GET_INT32(pRaw, dataPos, &pVgid->dnodeId, _OVER)
13,472,479✔
170
    if (pVgroup->replica == 1) {
13,472,479✔
171
      pVgid->syncState = TAOS_SYNC_STATE_LEADER;
9,535,245✔
172
    }
173
  }
174
  if (dataPos + 2 * sizeof(int32_t) + VGROUP_RESERVE_SIZE <= pRaw->dataLen) {
10,889,708✔
175
    SDB_GET_INT32(pRaw, dataPos, &pVgroup->syncConfChangeVer, _OVER)
10,889,708✔
176
  }
177
  SDB_GET_INT32(pRaw, dataPos, &pVgroup->mountVgId, _OVER)
10,889,708✔
178
  SDB_GET_RESERVE(pRaw, dataPos, VGROUP_RESERVE_SIZE, _OVER)
10,889,708✔
179

180
  terrno = 0;
10,889,708✔
181

182
_OVER:
10,889,708✔
183
  if (terrno != 0) {
10,889,708✔
184
    mError("vgId:%d, failed to decode from raw:%p since %s", pVgroup == NULL ? 0 : pVgroup->vgId, pRaw, terrstr());
×
185
    taosMemoryFreeClear(pRow);
×
186
    return NULL;
×
187
  }
188

189
  mTrace("vgId:%d, decode from raw:%p, row:%p", pVgroup->vgId, pRaw, pVgroup);
10,889,708✔
190
  return pRow;
10,889,708✔
191
}
192

193
static int32_t mndNewVgActionValidate(SMnode *pMnode, STrans *pTrans, SSdbRaw *pRaw) {
2,824,604✔
194
  SSdb    *pSdb = pMnode->pSdb;
2,824,604✔
195
  SSdbRow *pRow = NULL;
2,824,604✔
196
  SVgObj  *pVgroup = NULL;
2,824,604✔
197
  int      code = -1;
2,824,604✔
198

199
  pRow = mndVgroupActionDecode(pRaw);
2,824,604✔
200
  if (pRow == NULL) {
2,824,604✔
201
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
202
    if (terrno != 0) code = terrno;
×
203
    goto _OVER;
×
204
  }
205
  pVgroup = sdbGetRowObj(pRow);
2,824,604✔
206
  if (pVgroup == NULL) {
2,824,604✔
207
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
208
    if (terrno != 0) code = terrno;
×
209
    goto _OVER;
×
210
  }
211

212
  int32_t maxVgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP);
2,824,604✔
213
  if (maxVgId > pVgroup->vgId) {
2,824,604✔
214
    mError("trans:%d, vgroup id %d already in use. maxVgId:%d", pTrans->id, pVgroup->vgId, maxVgId);
×
215
    goto _OVER;
×
216
  }
217

218
  code = 0;
2,824,604✔
219
_OVER:
2,824,604✔
220
  if (pVgroup) mndVgroupActionDelete(pSdb, pVgroup);
2,824,604✔
221
  taosMemoryFreeClear(pRow);
2,824,604✔
222
  TAOS_RETURN(code);
2,824,604✔
223
}
224

225
static int32_t mndVgroupActionInsert(SSdb *pSdb, SVgObj *pVgroup) {
3,259,804✔
226
  mTrace("vgId:%d, perform insert action, row:%p", pVgroup->vgId, pVgroup);
3,259,804✔
227
  return 0;
3,259,804✔
228
}
229

230
static int32_t mndVgroupActionDelete(SSdb *pSdb, SVgObj *pVgroup) {
10,866,732✔
231
  mTrace("vgId:%d, perform delete action, row:%p", pVgroup->vgId, pVgroup);
10,866,732✔
232
  return 0;
10,866,732✔
233
}
234

235
static int32_t mndVgroupActionUpdate(SSdb *pSdb, SVgObj *pOld, SVgObj *pNew) {
3,281,216✔
236
  mTrace("vgId:%d, perform update action, old row:%p new row:%p", pOld->vgId, pOld, pNew);
3,281,216✔
237
  pOld->updateTime = pNew->updateTime;
3,281,216✔
238
  pOld->version = pNew->version;
3,281,216✔
239
  pOld->hashBegin = pNew->hashBegin;
3,281,216✔
240
  pOld->hashEnd = pNew->hashEnd;
3,281,216✔
241
  pOld->replica = pNew->replica;
3,281,216✔
242
  pOld->isTsma = pNew->isTsma;
3,281,216✔
243
  for (int32_t i = 0; i < pNew->replica; ++i) {
7,742,255✔
244
    SVnodeGid *pNewGid = &pNew->vnodeGid[i];
4,461,039✔
245
    for (int32_t j = 0; j < pOld->replica; ++j) {
12,484,104✔
246
      SVnodeGid *pOldGid = &pOld->vnodeGid[j];
8,023,065✔
247
      if (pNewGid->dnodeId == pOldGid->dnodeId) {
8,023,065✔
248
        pNewGid->syncState = pOldGid->syncState;
4,235,013✔
249
        pNewGid->syncRestore = pOldGid->syncRestore;
4,235,013✔
250
        pNewGid->syncCanRead = pOldGid->syncCanRead;
4,235,013✔
251
        pNewGid->syncAppliedIndex = pOldGid->syncAppliedIndex;
4,235,013✔
252
        pNewGid->syncCommitIndex = pOldGid->syncCommitIndex;
4,235,013✔
253
        pNewGid->bufferSegmentUsed = pOldGid->bufferSegmentUsed;
4,235,013✔
254
        pNewGid->bufferSegmentSize = pOldGid->bufferSegmentSize;
4,235,013✔
255
      }
256
    }
257
  }
258
  pNew->numOfTables = pOld->numOfTables;
3,281,216✔
259
  pNew->numOfTimeSeries = pOld->numOfTimeSeries;
3,281,216✔
260
  pNew->totalStorage = pOld->totalStorage;
3,281,216✔
261
  pNew->compStorage = pOld->compStorage;
3,281,216✔
262
  pNew->pointsWritten = pOld->pointsWritten;
3,281,216✔
263
  pNew->compact = pOld->compact;
3,281,216✔
264
  memcpy(pOld->vnodeGid, pNew->vnodeGid, (TSDB_MAX_REPLICA + TSDB_MAX_LEARNER_REPLICA) * sizeof(SVnodeGid));
3,281,216✔
265
  pOld->syncConfChangeVer = pNew->syncConfChangeVer;
3,281,216✔
266
  tstrncpy(pOld->dbName, pNew->dbName, TSDB_DB_FNAME_LEN);
3,281,216✔
267
  return 0;
3,281,216✔
268
}
269

270
SVgObj *mndAcquireVgroup(SMnode *pMnode, int32_t vgId) {
119,930,475✔
271
  SSdb   *pSdb = pMnode->pSdb;
119,930,475✔
272
  SVgObj *pVgroup = sdbAcquire(pSdb, SDB_VGROUP, &vgId);
119,930,475✔
273
  if (pVgroup == NULL && terrno == TSDB_CODE_SDB_OBJ_NOT_THERE) {
119,930,475✔
274
    terrno = TSDB_CODE_MND_VGROUP_NOT_EXIST;
245,542✔
275
  }
276
  return pVgroup;
119,930,475✔
277
}
278

279
void mndReleaseVgroup(SMnode *pMnode, SVgObj *pVgroup) {
119,839,308✔
280
  SSdb *pSdb = pMnode->pSdb;
119,839,308✔
281
  sdbRelease(pSdb, pVgroup);
119,839,308✔
282
}
119,839,308✔
283

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

334
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
7,298,327✔
335
    SReplica *pReplica = NULL;
4,266,098✔
336

337
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
4,266,098✔
338
      pReplica = &createReq.replicas[createReq.replica];
4,159,252✔
339
    } else {
340
      pReplica = &createReq.learnerReplicas[createReq.learnerReplica];
106,846✔
341
    }
342

343
    SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
4,266,098✔
344
    SDnodeObj *pVgidDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
4,266,098✔
345
    if (pVgidDnode == NULL) {
4,266,098✔
346
      return NULL;
×
347
    }
348

349
    pReplica->id = pVgidDnode->id;
4,266,098✔
350
    pReplica->port = pVgidDnode->port;
4,266,098✔
351
    memcpy(pReplica->fqdn, pVgidDnode->fqdn, TSDB_FQDN_LEN);
4,266,098✔
352
    mndReleaseDnode(pMnode, pVgidDnode);
4,266,098✔
353

354
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
4,266,098✔
355
      if (pDnode->id == pVgid->dnodeId) {
4,159,252✔
356
        createReq.selfIndex = createReq.replica;
2,925,383✔
357
      }
358
    } else {
359
      if (pDnode->id == pVgid->dnodeId) {
106,846✔
360
        createReq.learnerSelfIndex = createReq.learnerReplica;
106,846✔
361
      }
362
    }
363

364
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
4,266,098✔
365
      createReq.replica++;
4,159,252✔
366
    } else {
367
      createReq.learnerReplica++;
106,846✔
368
    }
369
  }
370

371
  if (createReq.selfIndex == -1 && createReq.learnerSelfIndex == -1) {
3,032,229✔
372
    terrno = TSDB_CODE_APP_ERROR;
×
373
    return NULL;
×
374
  }
375

376
  createReq.changeVersion = pVgroup->syncConfChangeVer;
3,032,229✔
377

378
  mInfo(
3,032,229✔
379
      "vgId:%d, build create vnode req, replica:%d selfIndex:%d learnerReplica:%d learnerSelfIndex:%d strict:%d "
380
      "changeVersion:%d",
381
      createReq.vgId, createReq.replica, createReq.selfIndex, createReq.learnerReplica, createReq.learnerSelfIndex,
382
      createReq.strict, createReq.changeVersion);
383
  for (int32_t i = 0; i < createReq.replica; ++i) {
7,191,481✔
384
    mInfo("vgId:%d, replica:%d ep:%s:%u", createReq.vgId, i, createReq.replicas[i].fqdn, createReq.replicas[i].port);
4,159,252✔
385
  }
386
  for (int32_t i = 0; i < createReq.learnerReplica; ++i) {
3,139,075✔
387
    mInfo("vgId:%d, replica:%d ep:%s:%u", createReq.vgId, i, createReq.learnerReplicas[i].fqdn,
106,846✔
388
          createReq.learnerReplicas[i].port);
389
  }
390

391
  int32_t contLen = tSerializeSCreateVnodeReq(NULL, 0, &createReq);
3,032,229✔
392
  if (contLen < 0) {
3,032,229✔
393
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
394
    return NULL;
×
395
  }
396

397
  void *pReq = taosMemoryMalloc(contLen);
3,032,229✔
398
  if (pReq == NULL) {
3,032,229✔
399
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
400
    return NULL;
×
401
  }
402

403
  code = tSerializeSCreateVnodeReq(pReq, contLen, &createReq);
3,032,229✔
404
  if (code < 0) {
3,032,229✔
405
    terrno = TSDB_CODE_APP_ERROR;
×
406
    taosMemoryFree(pReq);
×
407
    mError("vgId:%d, failed to serialize create vnode req,since %s", createReq.vgId, terrstr());
×
408
    return NULL;
×
409
  }
410
  *pContLen = contLen;
3,032,229✔
411
  return pReq;
3,032,229✔
412
}
413

414
static void *mndBuildAlterVnodeConfigReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen) {
205,568✔
415
  SAlterVnodeConfigReq alterReq = {0};
205,568✔
416
  alterReq.vgVersion = pVgroup->version;
205,568✔
417
  alterReq.buffer = pDb->cfg.buffer;
205,568✔
418
  alterReq.pageSize = pDb->cfg.pageSize;
205,568✔
419
  alterReq.pages = pDb->cfg.pages;
205,568✔
420
  alterReq.cacheLastSize = pDb->cfg.cacheLastSize;
205,568✔
421
  alterReq.daysPerFile = pDb->cfg.daysPerFile;
205,568✔
422
  alterReq.daysToKeep0 = pDb->cfg.daysToKeep0;
205,568✔
423
  alterReq.daysToKeep1 = pDb->cfg.daysToKeep1;
205,568✔
424
  alterReq.daysToKeep2 = pDb->cfg.daysToKeep2;
205,568✔
425
  alterReq.keepTimeOffset = pDb->cfg.keepTimeOffset;
205,568✔
426
  alterReq.walFsyncPeriod = pDb->cfg.walFsyncPeriod;
205,568✔
427
  alterReq.walLevel = pDb->cfg.walLevel;
205,568✔
428
  alterReq.strict = pDb->cfg.strict;
205,568✔
429
  alterReq.cacheLast = pDb->cfg.cacheLast;
205,568✔
430
  alterReq.sttTrigger = pDb->cfg.sstTrigger;
205,568✔
431
  alterReq.minRows = pDb->cfg.minRows;
205,568✔
432
  alterReq.walRetentionPeriod = pDb->cfg.walRetentionPeriod;
205,568✔
433
  alterReq.walRetentionSize = pDb->cfg.walRetentionSize;
205,568✔
434
  alterReq.ssKeepLocal = pDb->cfg.ssKeepLocal;
205,568✔
435
  alterReq.ssCompact = pDb->cfg.ssCompact;
205,568✔
436

437
  mInfo("vgId:%d, build alter vnode config req", pVgroup->vgId);
205,568✔
438
  int32_t contLen = tSerializeSAlterVnodeConfigReq(NULL, 0, &alterReq);
205,568✔
439
  if (contLen < 0) {
205,568✔
440
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
441
    return NULL;
×
442
  }
443
  contLen += sizeof(SMsgHead);
205,568✔
444

445
  void *pReq = taosMemoryMalloc(contLen);
205,568✔
446
  if (pReq == NULL) {
205,568✔
447
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
448
    return NULL;
×
449
  }
450

451
  SMsgHead *pHead = pReq;
205,568✔
452
  pHead->contLen = htonl(contLen);
205,568✔
453
  pHead->vgId = htonl(pVgroup->vgId);
205,568✔
454

455
  if (tSerializeSAlterVnodeConfigReq((char *)pReq + sizeof(SMsgHead), contLen, &alterReq) < 0) {
205,568✔
456
    taosMemoryFree(pReq);
×
457
    mError("vgId:%d, failed to serialize alter vnode config req,since %s", pVgroup->vgId, terrstr());
×
458
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
459
    return NULL;
×
460
  }
461
  *pContLen = contLen;
205,568✔
462
  return pReq;
205,568✔
463
}
464

465
static void *mndBuildAlterVnodeReplicaReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId,
787,395✔
466
                                          int32_t *pContLen) {
467
  SAlterVnodeReplicaReq alterReq = {
1,574,790✔
468
      .vgId = pVgroup->vgId,
787,395✔
469
      .strict = pDb->cfg.strict,
787,395✔
470
      .replica = 0,
471
      .learnerReplica = 0,
472
      .selfIndex = -1,
473
      .learnerSelfIndex = -1,
474
      .changeVersion = ++(pVgroup->syncConfChangeVer),
1,574,790✔
475
  };
476

477
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
3,208,225✔
478
    SReplica *pReplica = NULL;
2,420,830✔
479

480
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
2,420,830✔
481
      pReplica = &alterReq.replicas[alterReq.replica];
2,234,294✔
482
      alterReq.replica++;
2,234,294✔
483
    } else {
484
      pReplica = &alterReq.learnerReplicas[alterReq.learnerReplica];
186,536✔
485
      alterReq.learnerReplica++;
186,536✔
486
    }
487

488
    SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
2,420,830✔
489
    SDnodeObj *pVgidDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
2,420,830✔
490
    if (pVgidDnode == NULL) return NULL;
2,420,830✔
491

492
    pReplica->id = pVgidDnode->id;
2,420,830✔
493
    pReplica->port = pVgidDnode->port;
2,420,830✔
494
    memcpy(pReplica->fqdn, pVgidDnode->fqdn, TSDB_FQDN_LEN);
2,420,830✔
495
    mndReleaseDnode(pMnode, pVgidDnode);
2,420,830✔
496

497
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
2,420,830✔
498
      if (dnodeId == pVgid->dnodeId) {
2,234,294✔
499
        alterReq.selfIndex = v;
787,395✔
500
      }
501
    } else {
502
      if (dnodeId == pVgid->dnodeId) {
186,536✔
503
        alterReq.learnerSelfIndex = v;
×
504
      }
505
    }
506
  }
507

508
  mInfo(
787,395✔
509
      "vgId:%d, build alter vnode req, replica:%d selfIndex:%d learnerReplica:%d learnerSelfIndex:%d strict:%d "
510
      "changeVersion:%d",
511
      alterReq.vgId, alterReq.replica, alterReq.selfIndex, alterReq.learnerReplica, alterReq.learnerSelfIndex,
512
      alterReq.strict, alterReq.changeVersion);
513
  for (int32_t i = 0; i < alterReq.replica; ++i) {
3,021,689✔
514
    mInfo("vgId:%d, replica:%d ep:%s:%u", alterReq.vgId, i, alterReq.replicas[i].fqdn, alterReq.replicas[i].port);
2,234,294✔
515
  }
516
  for (int32_t i = 0; i < alterReq.learnerReplica; ++i) {
973,931✔
517
    mInfo("vgId:%d, learnerReplica:%d ep:%s:%u", alterReq.vgId, i, alterReq.learnerReplicas[i].fqdn,
186,536✔
518
          alterReq.learnerReplicas[i].port);
519
  }
520

521
  if (alterReq.selfIndex == -1 && alterReq.learnerSelfIndex == -1) {
787,395✔
522
    terrno = TSDB_CODE_APP_ERROR;
×
523
    return NULL;
×
524
  }
525

526
  int32_t contLen = tSerializeSAlterVnodeReplicaReq(NULL, 0, &alterReq);
787,395✔
527
  if (contLen < 0) {
787,395✔
528
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
529
    return NULL;
×
530
  }
531

532
  void *pReq = taosMemoryMalloc(contLen);
787,395✔
533
  if (pReq == NULL) {
787,395✔
534
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
535
    return NULL;
×
536
  }
537

538
  if (tSerializeSAlterVnodeReplicaReq(pReq, contLen, &alterReq) < 0) {
787,395✔
539
    mError("vgId:%d, failed to serialize alter vnode req,since %s", alterReq.vgId, terrstr());
×
540
    taosMemoryFree(pReq);
×
541
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
542
    return NULL;
×
543
  }
544
  *pContLen = contLen;
787,395✔
545
  return pReq;
787,395✔
546
}
547

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

559
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
×
560
    SReplica *pReplica = NULL;
×
561

562
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
×
563
      pReplica = &req.replicas[req.replica];
×
564
      req.replica++;
×
565
    } else {
566
      pReplica = &req.learnerReplicas[req.learnerReplica];
×
567
      req.learnerReplica++;
×
568
    }
569

570
    SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
×
571
    SDnodeObj *pVgidDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
×
572
    if (pVgidDnode == NULL) return NULL;
×
573

574
    pReplica->id = pVgidDnode->id;
×
575
    pReplica->port = pVgidDnode->port;
×
576
    memcpy(pReplica->fqdn, pVgidDnode->fqdn, TSDB_FQDN_LEN);
×
577
    mndReleaseDnode(pMnode, pVgidDnode);
×
578

579
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
×
580
      if (dnodeId == pVgid->dnodeId) {
×
581
        req.selfIndex = v;
×
582
      }
583
    } else {
584
      if (dnodeId == pVgid->dnodeId) {
×
585
        req.learnerSelfIndex = v;
×
586
      }
587
    }
588
  }
589

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

599
  if (req.selfIndex == -1 && req.learnerSelfIndex == -1) {
×
600
    terrno = TSDB_CODE_APP_ERROR;
×
601
    return NULL;
×
602
  }
603

604
  int32_t contLen = tSerializeSAlterVnodeReplicaReq(NULL, 0, &req);
×
605
  if (contLen < 0) {
×
606
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
607
    return NULL;
×
608
  }
609

610
  void *pReq = taosMemoryMalloc(contLen);
×
611
  if (pReq == NULL) {
×
612
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
613
    return NULL;
×
614
  }
615

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

626
static void *mndBuildDisableVnodeWriteReq(SMnode *pMnode, SDbObj *pDb, int32_t vgId, int32_t *pContLen) {
23,680✔
627
  SDisableVnodeWriteReq disableReq = {
23,680✔
628
      .vgId = vgId,
629
      .disable = 1,
630
  };
631

632
  mInfo("vgId:%d, build disable vnode write req", vgId);
23,680✔
633
  int32_t contLen = tSerializeSDisableVnodeWriteReq(NULL, 0, &disableReq);
23,680✔
634
  if (contLen < 0) {
23,680✔
635
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
636
    return NULL;
×
637
  }
638

639
  void *pReq = taosMemoryMalloc(contLen);
23,680✔
640
  if (pReq == NULL) {
23,680✔
641
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
642
    return NULL;
×
643
  }
644

645
  if (tSerializeSDisableVnodeWriteReq(pReq, contLen, &disableReq) < 0) {
23,680✔
646
    mError("vgId:%d, failed to serialize disable vnode write req,since %s", vgId, terrstr());
×
647
    taosMemoryFree(pReq);
×
648
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
649
    return NULL;
×
650
  }
651
  *pContLen = contLen;
23,680✔
652
  return pReq;
23,680✔
653
}
654

655
static void *mndBuildAlterVnodeHashRangeReq(SMnode *pMnode, int32_t srcVgId, SVgObj *pVgroup, int32_t *pContLen) {
23,680✔
656
  SAlterVnodeHashRangeReq alterReq = {
47,360✔
657
      .srcVgId = srcVgId,
658
      .dstVgId = pVgroup->vgId,
23,680✔
659
      .hashBegin = pVgroup->hashBegin,
23,680✔
660
      .hashEnd = pVgroup->hashEnd,
23,680✔
661
      .changeVersion = ++(pVgroup->syncConfChangeVer),
47,360✔
662
  };
663

664
  mInfo("vgId:%d, build alter vnode hashrange req, dstVgId:%d, hashrange:[%u, %u]", srcVgId, pVgroup->vgId,
23,680✔
665
        pVgroup->hashBegin, pVgroup->hashEnd);
666
  int32_t contLen = tSerializeSAlterVnodeHashRangeReq(NULL, 0, &alterReq);
23,680✔
667
  if (contLen < 0) {
23,680✔
668
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
669
    return NULL;
×
670
  }
671

672
  void *pReq = taosMemoryMalloc(contLen);
23,680✔
673
  if (pReq == NULL) {
23,680✔
674
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
675
    return NULL;
×
676
  }
677

678
  if (tSerializeSAlterVnodeHashRangeReq(pReq, contLen, &alterReq) < 0) {
23,680✔
679
    mError("vgId:%d, failed to serialize alter vnode hashrange req,since %s", srcVgId, terrstr());
×
680
    taosMemoryFree(pReq);
×
681
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
682
    return NULL;
×
683
  }
684
  *pContLen = contLen;
23,680✔
685
  return pReq;
23,680✔
686
}
687

688
void *mndBuildDropVnodeReq(SMnode *pMnode, SDnodeObj *pDnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen) {
4,488,326✔
689
  SDropVnodeReq dropReq = {0};
4,488,326✔
690
  dropReq.dnodeId = pDnode->id;
4,488,326✔
691
  dropReq.vgId = pVgroup->vgId;
4,488,326✔
692
  memcpy(dropReq.db, pDb->name, TSDB_DB_FNAME_LEN);
4,488,326✔
693
  dropReq.dbUid = pDb->uid;
4,488,326✔
694

695
  mInfo("vgId:%d, build drop vnode req", dropReq.vgId);
4,488,326✔
696
  int32_t contLen = tSerializeSDropVnodeReq(NULL, 0, &dropReq);
4,488,326✔
697
  if (contLen < 0) {
4,488,326✔
698
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
699
    return NULL;
×
700
  }
701

702
  void *pReq = taosMemoryMalloc(contLen);
4,488,326✔
703
  if (pReq == NULL) {
4,488,326✔
704
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
705
    return NULL;
×
706
  }
707

708
  if (tSerializeSDropVnodeReq(pReq, contLen, &dropReq) < 0) {
4,488,326✔
709
    mError("vgId:%d, failed to serialize drop vnode req,since %s", dropReq.vgId, terrstr());
×
710
    taosMemoryFree(pReq);
×
711
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
712
    return NULL;
×
713
  }
714
  *pContLen = contLen;
4,488,326✔
715
  return pReq;
4,488,326✔
716
}
717

718
static bool mndResetDnodesArrayFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
1,989,980✔
719
  SDnodeObj *pDnode = pObj;
1,989,980✔
720
  pDnode->numOfVnodes = 0;
1,989,980✔
721
  pDnode->numOfOtherNodes = 0;
1,989,980✔
722
  return true;
1,989,980✔
723
}
724

725
static bool mndBuildDnodesArrayFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
1,989,980✔
726
  SDnodeObj *pDnode = pObj;
1,989,980✔
727
  SArray    *pArray = p1;
1,989,980✔
728
  int32_t    exceptDnodeId = *(int32_t *)p2;
1,989,980✔
729
  SArray    *dnodeList = p3;
1,989,980✔
730

731
  if (exceptDnodeId == pDnode->id) {
1,989,980✔
732
    return true;
8,283✔
733
  }
734

735
  if (dnodeList != NULL) {
1,981,697✔
736
    int32_t dnodeListSize = taosArrayGetSize(dnodeList);
71,155✔
737
    if (dnodeListSize > 0) {
71,155✔
738
      bool inDnodeList = false;
71,155✔
739
      for (int32_t index = 0; index < dnodeListSize; ++index) {
232,190✔
740
        int32_t dnodeId = *(int32_t *)taosArrayGet(dnodeList, index);
161,035✔
741
        if (pDnode->id == dnodeId) {
161,035✔
742
          inDnodeList = true;
32,207✔
743
        }
744
      }
745
      if (!inDnodeList) {
71,155✔
746
        return true;
38,948✔
747
      }
748
    } else {
749
      return true;  // TS-6191
×
750
    }
751
  }
752

753
  int64_t curMs = taosGetTimestampMs();
1,942,749✔
754
  bool    online = mndIsDnodeOnline(pDnode, curMs);
1,942,749✔
755
  bool    isMnode = mndIsMnode(pMnode, pDnode->id);
1,942,749✔
756
  pDnode->numOfVnodes = mndGetVnodesNum(pMnode, pDnode->id);
1,942,749✔
757
  pDnode->memUsed = mndGetVnodesMemory(pMnode, pDnode->id);
1,942,749✔
758

759
  mInfo("dnode:%d, vnodes:%d supportVnodes:%d isMnode:%d online:%d memory avail:%" PRId64 " used:%" PRId64, pDnode->id,
1,942,749✔
760
        pDnode->numOfVnodes, pDnode->numOfSupportVnodes, isMnode, online, pDnode->memAvail, pDnode->memUsed);
761

762
  if (isMnode) {
1,942,749✔
763
    pDnode->numOfOtherNodes++;
1,418,610✔
764
  }
765

766
  if (online && pDnode->numOfSupportVnodes > 0) {
1,942,749✔
767
    if (taosArrayPush(pArray, pDnode) == NULL) return false;
1,897,341✔
768
  }
769
  return true;
1,942,749✔
770
}
771

772
static bool isDnodeInList(SArray *dnodeList, int32_t dnodeId) {
×
773
  int32_t dnodeListSize = taosArrayGetSize(dnodeList);
×
774
  for (int32_t i = 0; i < dnodeListSize; ++i) {
×
775
    int32_t id = *(int32_t *)TARRAY_GET_ELEM(dnodeList, i);
×
776
    if (id == dnodeId) {
×
777
      return true;
×
778
    }
779
  }
780
  return false;
×
781
}
782

783
#ifdef TD_ENTERPRISE
784
static float mndGetDnodeScore1(SDnodeObj *pDnode, int32_t additionDnodes, float ratio) {
×
785
  float totalDnodes = pDnode->numOfVnodes + (float)pDnode->numOfOtherNodes * ratio + additionDnodes;
×
786
  float result = totalDnodes / pDnode->numOfSupportVnodes;
×
787
  return pDnode->numOfVnodes > 0 ? -result : result;
×
788
}
789

790
static int32_t mndCompareDnodeVnodes1(SDnodeObj *pDnode1, SDnodeObj *pDnode2) {
×
791
  float d1Score = mndGetDnodeScore1(pDnode1, 0, 0.9);
×
792
  float d2Score = mndGetDnodeScore1(pDnode2, 0, 0.9);
×
793
  if (d1Score == d2Score) {
×
794
    if (pDnode1->id == pDnode2->id) {
×
795
      return 0;
×
796
    }
797
    return pDnode1->id > pDnode2->id ? 1 : -1;
×
798
  }
799
  return d1Score > d2Score ? 1 : -1;
×
800
}
801

802
static bool mndBuildDnodesListFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
×
803
  SDnodeObj *pDnode = pObj;
×
804
  SArray    *pArray = p1;
×
805

806
  bool isMnode = mndIsMnode(pMnode, pDnode->id);
×
807
  pDnode->numOfVnodes = mndGetVnodesNum(pMnode, pDnode->id);
×
808

809
  if (isMnode) {
×
810
    pDnode->numOfOtherNodes++;
×
811
  }
812

813
  if (pDnode->numOfSupportVnodes > 0) {
×
814
    if (taosArrayPush(pArray, pDnode) == NULL) return false;
×
815
  }
816
  return true;
×
817
}
818

819
// TS-6191
820
static int32_t mndBuildNodesCheckDualReplica(SMnode *pMnode, int32_t nDnodes, SArray *dnodeList, SArray **ppDnodeList) {
1,348,709✔
821
  int32_t code = 0;
1,348,709✔
822
  if (!grantCheckDualReplicaDnodes(pMnode)) {
1,348,709✔
823
    TAOS_RETURN(code);
1,348,709✔
824
  }
825
  SSdb   *pSdb = pMnode->pSdb;
×
826
  SArray *pArray = taosArrayInit(nDnodes, sizeof(SDnodeObj));
×
827
  if (pArray == NULL) {
×
828
    TAOS_RETURN(code = terrno);
×
829
  }
830
  *ppDnodeList = pArray;
×
831

832
  sdbTraverse(pSdb, SDB_DNODE, mndResetDnodesArrayFp, NULL, NULL, NULL);
×
833
  sdbTraverse(pSdb, SDB_DNODE, mndBuildDnodesListFp, pArray, NULL, NULL);
×
834

835
  int32_t arrSize = taosArrayGetSize(pArray);
×
836
  if (arrSize <= 0) {
×
837
    TAOS_RETURN(code);
×
838
  }
839
  if (arrSize > 1) taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes1);
×
840

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

876
  TAOS_RETURN(code);
×
877
}
878
#endif
879

880
SArray *mndBuildDnodesArray(SMnode *pMnode, int32_t exceptDnodeId, SArray *dnodeList) {
1,348,709✔
881
  SSdb   *pSdb = pMnode->pSdb;
1,348,709✔
882
  int32_t numOfDnodes = mndGetDnodeSize(pMnode);
1,348,709✔
883
  SArray *tDnodeList = NULL;
1,348,709✔
884
  SArray *pDnodeList = NULL;
1,348,709✔
885

886
  SArray *pArray = taosArrayInit(numOfDnodes, sizeof(SDnodeObj));
1,348,709✔
887
  if (pArray == NULL) {
1,348,709✔
888
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
889
    return NULL;
×
890
  }
891
  if (taosArrayGetSize(dnodeList) > 0) {
1,348,709✔
892
    tDnodeList = dnodeList;
14,231✔
893
  }
894
#ifdef TD_ENTERPRISE
895
  if (0 != mndBuildNodesCheckDualReplica(pMnode, numOfDnodes, tDnodeList, &pDnodeList)) {
1,348,709✔
896
    taosArrayDestroy(pArray);
×
897
    return NULL;
×
898
  }
899
#endif
900
  sdbTraverse(pSdb, SDB_DNODE, mndResetDnodesArrayFp, NULL, NULL, NULL);
1,348,709✔
901
  sdbTraverse(pSdb, SDB_DNODE, mndBuildDnodesArrayFp, pArray, &exceptDnodeId, pDnodeList ? pDnodeList : tDnodeList);
1,348,709✔
902

903
  mDebug("build %d dnodes array", (int32_t)taosArrayGetSize(pArray));
1,348,709✔
904
  for (int32_t i = 0; i < (int32_t)taosArrayGetSize(pArray); ++i) {
3,246,050✔
905
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
1,897,341✔
906
    mDebug("dnode:%d, vnodes:%d others:%d", pDnode->id, pDnode->numOfVnodes, pDnode->numOfOtherNodes);
1,897,341✔
907
  }
908
  taosArrayDestroy(pDnodeList);
1,348,709✔
909
  return pArray;
1,348,709✔
910
}
911

912
static int32_t mndCompareDnodeId(int32_t *dnode1Id, int32_t *dnode2Id) {
×
913
  if (*dnode1Id == *dnode2Id) {
×
914
    return 0;
×
915
  }
916
  return *dnode1Id > *dnode2Id ? 1 : -1;
×
917
}
918

919
static float mndGetDnodeScore(SDnodeObj *pDnode, int32_t additionDnodes, float ratio) {
10,888,906✔
920
  float totalDnodes = pDnode->numOfVnodes + (float)pDnode->numOfOtherNodes * ratio + additionDnodes;
10,888,906✔
921
  return totalDnodes / pDnode->numOfSupportVnodes;
10,888,906✔
922
}
923

924
static int32_t mndCompareDnodeVnodes(SDnodeObj *pDnode1, SDnodeObj *pDnode2) {
3,538,372✔
925
  float d1Score = mndGetDnodeScore(pDnode1, 0, 0.9);
3,538,372✔
926
  float d2Score = mndGetDnodeScore(pDnode2, 0, 0.9);
3,538,372✔
927
  if (d1Score == d2Score) {
3,538,372✔
928
    return 0;
1,333,974✔
929
  }
930
  return d1Score > d2Score ? 1 : -1;
2,204,398✔
931
}
932

933
void mndSortVnodeGid(SVgObj *pVgroup) {
2,599,541✔
934
  for (int32_t i = 0; i < pVgroup->replica; ++i) {
5,573,002✔
935
    for (int32_t j = 0; j < pVgroup->replica - 1 - i; ++j) {
3,530,632✔
936
      if (pVgroup->vnodeGid[j].dnodeId > pVgroup->vnodeGid[j + 1].dnodeId) {
557,171✔
937
        TSWAP(pVgroup->vnodeGid[j], pVgroup->vnodeGid[j + 1]);
202,329✔
938
      }
939
    }
940
  }
941
}
2,599,541✔
942

943
static int32_t mndGetAvailableDnode(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, SArray *pArray) {
2,569,997✔
944
  mDebug("start to sort %d dnodes", (int32_t)taosArrayGetSize(pArray));
2,569,997✔
945
  taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
2,569,997✔
946
  for (int32_t i = 0; i < (int32_t)taosArrayGetSize(pArray); ++i) {
6,287,820✔
947
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
3,717,823✔
948
    mDebug("dnode:%d, score:%f", pDnode->id, mndGetDnodeScore(pDnode, 0, 0.9));
3,717,823✔
949
  }
950

951
  int32_t size = taosArrayGetSize(pArray);
2,569,997✔
952
  if (size < pVgroup->replica) {
2,569,997✔
953
    mError("db:%s, vgId:%d, no enough online dnodes:%d to alloc %d replica", pVgroup->dbName, pVgroup->vgId, size,
5,334✔
954
           pVgroup->replica);
955
    TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_DNODES);
5,334✔
956
  }
957

958
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
5,444,696✔
959
    SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
2,880,033✔
960
    SDnodeObj *pDnode = taosArrayGet(pArray, v);
2,880,033✔
961
    if (pDnode == NULL) {
2,880,033✔
962
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_DNODES);
×
963
    }
964
    if (pDnode->numOfVnodes >= pDnode->numOfSupportVnodes) {
2,880,033✔
965
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_VNODES);
×
966
    }
967

968
    int64_t vgMem = mndGetVgroupMemory(pMnode, pDb, pVgroup);
2,880,033✔
969
    if (pDnode->memAvail - vgMem - pDnode->memUsed <= 0) {
2,880,033✔
970
      mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d, avail:%" PRId64 " used:%" PRId64,
×
971
             pVgroup->dbName, pVgroup->vgId, vgMem, pDnode->id, pDnode->memAvail, pDnode->memUsed);
972
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE);
×
973
    } else {
974
      pDnode->memUsed += vgMem;
2,880,033✔
975
    }
976

977
    pVgid->dnodeId = pDnode->id;
2,880,033✔
978
    if (pVgroup->replica == 1) {
2,880,033✔
979
      pVgid->syncState = TAOS_SYNC_STATE_LEADER;
2,403,995✔
980
    } else {
981
      pVgid->syncState = TAOS_SYNC_STATE_FOLLOWER;
476,038✔
982
    }
983

984
    mInfo("db:%s, vgId:%d, vn:%d is alloced, memory:%" PRId64 ", dnode:%d avail:%" PRId64 " used:%" PRId64,
2,880,033✔
985
          pVgroup->dbName, pVgroup->vgId, v, vgMem, pVgid->dnodeId, pDnode->memAvail, pDnode->memUsed);
986
    pDnode->numOfVnodes++;
2,880,033✔
987
  }
988

989
  mndSortVnodeGid(pVgroup);
2,564,663✔
990
  return 0;
2,564,663✔
991
}
992

993
int32_t mndAllocSmaVgroup(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup) {
×
994
  int32_t code = 0;
×
995
  SArray *pArray = mndBuildDnodesArray(pMnode, 0, NULL);
×
996
  if (pArray == NULL) {
×
997
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
998
    if (terrno != 0) code = terrno;
×
999
    TAOS_RETURN(code);
×
1000
  }
1001

1002
  pVgroup->vgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP);
×
1003
  pVgroup->isTsma = 1;
×
1004
  pVgroup->createdTime = taosGetTimestampMs();
×
1005
  pVgroup->updateTime = pVgroup->createdTime;
×
1006
  pVgroup->version = 1;
×
1007
  memcpy(pVgroup->dbName, pDb->name, TSDB_DB_FNAME_LEN);
×
1008
  pVgroup->dbUid = pDb->uid;
×
1009
  pVgroup->replica = 1;
×
1010

1011
  if (mndGetAvailableDnode(pMnode, pDb, pVgroup, pArray) != 0) return -1;
×
1012
  taosArrayDestroy(pArray);
×
1013

1014
  mInfo("db:%s, sma vgId:%d is alloced", pDb->name, pVgroup->vgId);
×
1015
  return 0;
×
1016
}
1017

1018
int32_t mndAllocVgroup(SMnode *pMnode, SDbObj *pDb, SVgObj **ppVgroups, SArray *dnodeList) {
1,223,950✔
1019
  int32_t code = -1;
1,223,950✔
1020
  SArray *pArray = NULL;
1,223,950✔
1021
  SVgObj *pVgroups = NULL;
1,223,950✔
1022

1023
  pVgroups = taosMemoryCalloc(pDb->cfg.numOfVgroups, sizeof(SVgObj));
1,223,950✔
1024
  if (pVgroups == NULL) {
1,223,950✔
1025
    code = terrno;
×
1026
    goto _OVER;
×
1027
  }
1028

1029
  pArray = mndBuildDnodesArray(pMnode, 0, dnodeList);
1,223,950✔
1030
  if (pArray == NULL) {
1,223,950✔
1031
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1032
    if (terrno != 0) code = terrno;
×
1033
    goto _OVER;
×
1034
  }
1035

1036
  mInfo("db:%s, total %d dnodes used to create %d vgroups (%d vnodes)", pDb->name, (int32_t)taosArrayGetSize(pArray),
1,223,950✔
1037
        pDb->cfg.numOfVgroups, pDb->cfg.numOfVgroups * pDb->cfg.replications);
1038

1039
  int32_t  allocedVgroups = 0;
1,223,950✔
1040
  int32_t  maxVgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP);
1,223,950✔
1041
  uint32_t hashMin = 0;
1,223,950✔
1042
  uint32_t hashMax = UINT32_MAX;
1,223,950✔
1043
  uint32_t hashInterval = (hashMax - hashMin) / pDb->cfg.numOfVgroups;
1,223,950✔
1044

1045
  if (maxVgId < 2) maxVgId = 2;
1,223,950✔
1046

1047
  for (uint32_t v = 0; v < pDb->cfg.numOfVgroups; v++) {
3,788,613✔
1048
    SVgObj *pVgroup = &pVgroups[v];
2,569,997✔
1049
    pVgroup->vgId = maxVgId++;
2,569,997✔
1050
    pVgroup->createdTime = taosGetTimestampMs();
2,569,997✔
1051
    pVgroup->updateTime = pVgroups->createdTime;
2,569,997✔
1052
    pVgroup->version = 1;
2,569,997✔
1053
    pVgroup->hashBegin = hashMin + hashInterval * v;
2,569,997✔
1054
    if (v == pDb->cfg.numOfVgroups - 1) {
2,569,997✔
1055
      pVgroup->hashEnd = hashMax;
1,221,151✔
1056
    } else {
1057
      pVgroup->hashEnd = hashMin + hashInterval * (v + 1) - 1;
1,348,846✔
1058
    }
1059

1060
    memcpy(pVgroup->dbName, pDb->name, TSDB_DB_FNAME_LEN);
2,569,997✔
1061
    pVgroup->dbUid = pDb->uid;
2,569,997✔
1062
    pVgroup->replica = pDb->cfg.replications;
2,569,997✔
1063

1064
    if ((code = mndGetAvailableDnode(pMnode, pDb, pVgroup, pArray)) != 0) {
2,569,997✔
1065
      goto _OVER;
5,334✔
1066
    }
1067

1068
    allocedVgroups++;
2,564,663✔
1069
  }
1070

1071
  *ppVgroups = pVgroups;
1,218,616✔
1072
  code = 0;
1,218,616✔
1073

1074
  mInfo("db:%s, total %d vgroups is alloced, replica:%d", pDb->name, pDb->cfg.numOfVgroups, pDb->cfg.replications);
1,218,616✔
1075

1076
_OVER:
×
1077
  if (code != 0) taosMemoryFree(pVgroups);
1,223,950✔
1078
  taosArrayDestroy(pArray);
1,223,950✔
1079
  TAOS_RETURN(code);
1,223,950✔
1080
}
1081

1082
SEpSet mndGetVgroupEpset(SMnode *pMnode, const SVgObj *pVgroup) {
29,726,466✔
1083
  SEpSet epset = {0};
29,726,466✔
1084

1085
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
67,234,062✔
1086
    const SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
37,507,596✔
1087
    SDnodeObj       *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
37,507,596✔
1088
    if (pDnode == NULL) continue;
37,507,596✔
1089

1090
    if (pVgid->syncState == TAOS_SYNC_STATE_LEADER || pVgid->syncState == TAOS_SYNC_STATE_ASSIGNED_LEADER) {
37,489,354✔
1091
      epset.inUse = epset.numOfEps;
29,379,352✔
1092
    }
1093

1094
    if (addEpIntoEpSet(&epset, pDnode->fqdn, pDnode->port) != 0) {
37,489,354✔
1095
      mWarn("vgId:%d, failed to add ep:%s:%d into epset", pVgroup->vgId, pDnode->fqdn, pDnode->port);
×
1096
    }
1097
    mndReleaseDnode(pMnode, pDnode);
37,489,354✔
1098
  }
1099
  epsetSort(&epset);
29,726,466✔
1100

1101
  return epset;
29,726,466✔
1102
}
1103

1104
SEpSet mndGetVgroupEpsetById(SMnode *pMnode, int32_t vgId) {
577,538✔
1105
  SEpSet epset = {0};
577,538✔
1106

1107
  SVgObj *pVgroup = mndAcquireVgroup(pMnode, vgId);
577,538✔
1108
  if (!pVgroup) return epset;
577,538✔
1109

1110
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
1,189,909✔
1111
    const SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
612,371✔
1112
    SDnodeObj       *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
612,371✔
1113
    if (pDnode == NULL) continue;
612,371✔
1114

1115
    if (pVgid->syncState == TAOS_SYNC_STATE_LEADER || pVgid->syncState == TAOS_SYNC_STATE_ASSIGNED_LEADER) {
612,371✔
1116
      epset.inUse = epset.numOfEps;
564,131✔
1117
    }
1118

1119
    if (addEpIntoEpSet(&epset, pDnode->fqdn, pDnode->port) != 0) {
612,371✔
1120
      mWarn("vgId:%d, failed to add ep:%s:%d into epset", pVgroup->vgId, pDnode->fqdn, pDnode->port);
×
1121
    }
1122
    mndReleaseDnode(pMnode, pDnode);
612,371✔
1123
  }
1124

1125
  mndReleaseVgroup(pMnode, pVgroup);
577,538✔
1126
  return epset;
577,538✔
1127
}
1128

1129
static int32_t mndRetrieveVgroups(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
350,202✔
1130
  SMnode *pMnode = pReq->info.node;
350,202✔
1131
  SSdb   *pSdb = pMnode->pSdb;
350,202✔
1132
  int32_t numOfRows = 0;
350,202✔
1133
  SVgObj *pVgroup = NULL;
350,202✔
1134
  int32_t cols = 0;
350,202✔
1135
  int64_t curMs = taosGetTimestampMs();
350,202✔
1136
  int32_t code = 0, lino = 0;
350,202✔
1137

1138
  SDbObj *pDb = NULL;
350,202✔
1139
  if (strlen(pShow->db) > 0) {
350,202✔
1140
    pDb = mndAcquireDb(pMnode, pShow->db);
303,339✔
1141
    if (pDb == NULL) {
303,339✔
1142
      return 0;
×
1143
    }
1144
  }
1145

1146
  while (numOfRows < rows) {
1,842,250✔
1147
    pShow->pIter = sdbFetch(pSdb, SDB_VGROUP, pShow->pIter, (void **)&pVgroup);
1,842,250✔
1148
    if (pShow->pIter == NULL) break;
1,842,250✔
1149

1150
    if (pDb != NULL && pVgroup->dbUid != pDb->uid) {
1,492,048✔
1151
      sdbRelease(pSdb, pVgroup);
405,768✔
1152
      continue;
405,768✔
1153
    }
1154

1155
    cols = 0;
1,086,280✔
1156
    SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,086,280✔
1157
    COL_DATA_SET_VAL_GOTO((const char *)&pVgroup->vgId, false, pVgroup, pShow->pIter, _OVER);
1,086,280✔
1158

1159
    SName name = {0};
1,086,280✔
1160
    char  db[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
1,086,280✔
1161
    code = tNameFromString(&name, pVgroup->dbName, T_NAME_ACCT | T_NAME_DB);
1,086,280✔
1162
    if (code != 0) {
1,086,280✔
1163
      mError("vgId:%d, failed to set dbName, since %s", pVgroup->vgId, tstrerror(code));
×
1164
      sdbRelease(pSdb, pVgroup);
×
1165
      sdbCancelFetch(pSdb, pShow->pIter);
×
1166
      return code;
×
1167
    }
1168
    (void)tNameGetDbName(&name, varDataVal(db));
1,086,280✔
1169
    varDataSetLen(db, strlen(varDataVal(db)));
1,086,280✔
1170

1171
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,086,280✔
1172
    COL_DATA_SET_VAL_GOTO((const char *)db, false, pVgroup, pShow->pIter, _OVER);
1,086,280✔
1173

1174
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,086,280✔
1175
    COL_DATA_SET_VAL_GOTO((const char *)&pVgroup->numOfTables, false, pVgroup, pShow->pIter, _OVER);
1,086,280✔
1176

1177
    // default 3 replica, add 1 replica if move vnode
1178
    for (int32_t i = 0; i < 4; ++i) {
5,431,400✔
1179
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
4,345,120✔
1180
      if (i < pVgroup->replica) {
4,345,120✔
1181
        int16_t dnodeId = (int16_t)pVgroup->vnodeGid[i].dnodeId;
2,338,927✔
1182
        COL_DATA_SET_VAL_GOTO((const char *)&dnodeId, false, pVgroup, pShow->pIter, _OVER);
2,338,927✔
1183

1184
        bool       exist = false;
2,338,927✔
1185
        bool       online = false;
2,338,927✔
1186
        SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgroup->vnodeGid[i].dnodeId);
2,338,927✔
1187
        if (pDnode != NULL) {
2,338,927✔
1188
          exist = true;
2,338,927✔
1189
          online = mndIsDnodeOnline(pDnode, curMs);
2,338,927✔
1190
          mndReleaseDnode(pMnode, pDnode);
2,338,927✔
1191
        }
1192

1193
        char buf1[20] = {0};
2,338,927✔
1194
        char role[20] = "offline";
2,338,927✔
1195
        if (!exist) {
2,338,927✔
1196
          tstrncpy(role, "dropping", sizeof(role));
×
1197
        } else if (online) {
2,338,927✔
1198
          char *star = "";
2,312,405✔
1199
          if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_LEADER ||
2,312,405✔
1200
              pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_ASSIGNED_LEADER) {
1,492,863✔
1201
            if (!pVgroup->vnodeGid[i].syncRestore && !pVgroup->vnodeGid[i].syncCanRead) {
819,542✔
1202
              star = "**";
102,237✔
1203
            } else if (!pVgroup->vnodeGid[i].syncRestore && pVgroup->vnodeGid[i].syncCanRead) {
717,305✔
1204
              star = "*";
×
1205
            } else {
1206
            }
1207
          }
1208
          snprintf(role, sizeof(role), "%s%s", syncStr(pVgroup->vnodeGid[i].syncState), star);
2,312,405✔
1209
          /*
1210
          mInfo("db:%s, learner progress:%d", pDb->name, pVgroup->vnodeGid[i].learnerProgress);
1211

1212
          if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_LEARNER) {
1213
            if(pVgroup->vnodeGid[i].learnerProgress < 0){
1214
              snprintf(role, sizeof(role), "%s-",
1215
                syncStr(pVgroup->vnodeGid[i].syncState));
1216

1217
            }
1218
            else if(pVgroup->vnodeGid[i].learnerProgress >= 100){
1219
              snprintf(role, sizeof(role), "%s--",
1220
                syncStr(pVgroup->vnodeGid[i].syncState));
1221
            }
1222
            else{
1223
              snprintf(role, sizeof(role), "%s%d",
1224
                syncStr(pVgroup->vnodeGid[i].syncState), pVgroup->vnodeGid[i].learnerProgress);
1225
            }
1226
          }
1227
          else{
1228
            snprintf(role, sizeof(role), "%s%s", syncStr(pVgroup->vnodeGid[i].syncState), star);
1229
          }
1230
          */
1231
        } else {
1232
        }
1233
        STR_WITH_MAXSIZE_TO_VARSTR(buf1, role, pShow->pMeta->pSchemas[cols].bytes);
2,338,927✔
1234

1235
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
2,338,927✔
1236
        COL_DATA_SET_VAL_GOTO((const char *)buf1, false, pVgroup, pShow->pIter, _OVER);
2,338,927✔
1237

1238
        char applyStr[TSDB_SYNC_APPLY_COMMIT_LEN + 1] = {0};
2,338,927✔
1239
        char buf[TSDB_SYNC_APPLY_COMMIT_LEN + VARSTR_HEADER_SIZE + 1] = {0};
2,338,927✔
1240
        snprintf(applyStr, sizeof(applyStr), "%" PRId64 "/%" PRId64, pVgroup->vnodeGid[i].syncAppliedIndex,
2,338,927✔
1241
                 pVgroup->vnodeGid[i].syncCommitIndex);
2,338,927✔
1242
        STR_WITH_MAXSIZE_TO_VARSTR(buf, applyStr, pShow->pMeta->pSchemas[cols].bytes);
2,338,927✔
1243

1244
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
2,338,927✔
1245
        COL_DATA_SET_VAL_GOTO((const char *)&buf, false, pVgroup, pShow->pIter, _OVER);
2,338,927✔
1246
      } else {
1247
        colDataSetNULL(pColInfo, numOfRows);
2,006,193✔
1248
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
2,006,193✔
1249
        colDataSetNULL(pColInfo, numOfRows);
2,006,193✔
1250
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
2,006,193✔
1251
        colDataSetNULL(pColInfo, numOfRows);
2,006,193✔
1252
      }
1253
    }
1254

1255
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,086,280✔
1256
    int32_t cacheUsage = (int32_t)pVgroup->cacheUsage;
1,086,280✔
1257
    COL_DATA_SET_VAL_GOTO((const char *)&cacheUsage, false, pVgroup, pShow->pIter, _OVER);
1,086,280✔
1258

1259
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,086,280✔
1260
    COL_DATA_SET_VAL_GOTO((const char *)&pVgroup->numOfCachedTables, false, pVgroup, pShow->pIter, _OVER);
1,086,280✔
1261

1262
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,086,280✔
1263
    COL_DATA_SET_VAL_GOTO((const char *)&pVgroup->isTsma, false, pVgroup, pShow->pIter, _OVER);
1,086,280✔
1264

1265
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,086,280✔
1266
    COL_DATA_SET_VAL_GOTO((const char *)&pVgroup->mountVgId, false, pVgroup, pShow->pIter, _OVER);
1,086,280✔
1267

1268
    numOfRows++;
1,086,280✔
1269
    sdbRelease(pSdb, pVgroup);
1,086,280✔
1270
  }
1271
_OVER:
350,202✔
1272
  if (pDb != NULL) {
350,202✔
1273
    mndReleaseDb(pMnode, pDb);
303,339✔
1274
  }
1275
  if (code != 0) {
350,202✔
1276
    mError("failed to retrieve vgroup info at line %d since %s", lino, tstrerror(code));
×
1277
    TAOS_RETURN(code);
×
1278
  }
1279

1280
  pShow->numOfRows += numOfRows;
350,202✔
1281
  return numOfRows;
350,202✔
1282
}
1283

1284
static void mndCancelGetNextVgroup(SMnode *pMnode, void *pIter) {
×
1285
  SSdb *pSdb = pMnode->pSdb;
×
1286
  sdbCancelFetchByType(pSdb, pIter, SDB_VGROUP);
×
1287
}
×
1288

1289
static bool mndGetVnodesNumFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
11,682,697✔
1290
  SVgObj  *pVgroup = pObj;
11,682,697✔
1291
  int32_t  dnodeId = *(int32_t *)p1;
11,682,697✔
1292
  int32_t *pNumOfVnodes = (int32_t *)p2;
11,682,697✔
1293

1294
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
33,435,620✔
1295
    if (pVgroup->vnodeGid[v].dnodeId == dnodeId) {
21,752,923✔
1296
      (*pNumOfVnodes)++;
7,024,646✔
1297
    }
1298
  }
1299

1300
  return true;
11,682,697✔
1301
}
1302

1303
int32_t mndGetVnodesNum(SMnode *pMnode, int32_t dnodeId) {
4,399,277✔
1304
  int32_t numOfVnodes = 0;
4,399,277✔
1305
  sdbTraverse(pMnode->pSdb, SDB_VGROUP, mndGetVnodesNumFp, &dnodeId, &numOfVnodes, NULL);
4,399,277✔
1306
  return numOfVnodes;
4,399,277✔
1307
}
1308

1309
int64_t mndGetVgroupMemory(SMnode *pMnode, SDbObj *pDbInput, SVgObj *pVgroup) {
7,864,099✔
1310
  SDbObj *pDb = pDbInput;
7,864,099✔
1311
  if (pDbInput == NULL) {
7,864,099✔
1312
    pDb = mndAcquireDb(pMnode, pVgroup->dbName);
4,367,502✔
1313
  }
1314

1315
  int64_t vgroupMemroy = 0;
7,864,099✔
1316
  if (pDb != NULL) {
7,864,099✔
1317
    int64_t buffer = (int64_t)pDb->cfg.buffer * 1024 * 1024;
7,864,099✔
1318
    int64_t cache = (int64_t)pDb->cfg.pages * pDb->cfg.pageSize * 1024;
7,864,099✔
1319
    vgroupMemroy = buffer + cache;
7,864,099✔
1320
    int64_t cacheLast = (int64_t)pDb->cfg.cacheLastSize * 1024 * 1024;
7,864,099✔
1321
    if (pDb->cfg.cacheLast > 0) {
7,864,099✔
1322
      vgroupMemroy += cacheLast;
964,963✔
1323
    }
1324
    mDebug("db:%s, vgroup:%d, buffer:%" PRId64 " cache:%" PRId64 " cacheLast:%" PRId64, pDb->name, pVgroup->vgId,
7,864,099✔
1325
           buffer, cache, cacheLast);
1326
  }
1327

1328
  if (pDbInput == NULL) {
7,864,099✔
1329
    mndReleaseDb(pMnode, pDb);
4,367,502✔
1330
  }
1331
  return vgroupMemroy;
7,864,099✔
1332
}
1333

1334
static bool mndGetVnodeMemroyFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
6,248,340✔
1335
  SVgObj  *pVgroup = pObj;
6,248,340✔
1336
  int32_t  dnodeId = *(int32_t *)p1;
6,248,340✔
1337
  int64_t *pVnodeMemory = (int64_t *)p2;
6,248,340✔
1338

1339
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
15,218,788✔
1340
    if (pVgroup->vnodeGid[v].dnodeId == dnodeId) {
8,970,448✔
1341
      *pVnodeMemory += mndGetVgroupMemory(pMnode, NULL, pVgroup);
4,221,990✔
1342
    }
1343
  }
1344

1345
  return true;
6,248,340✔
1346
}
1347

1348
int64_t mndGetVnodesMemory(SMnode *pMnode, int32_t dnodeId) {
1,943,416✔
1349
  int64_t vnodeMemory = 0;
1,943,416✔
1350
  sdbTraverse(pMnode->pSdb, SDB_VGROUP, mndGetVnodeMemroyFp, &dnodeId, &vnodeMemory, NULL);
1,943,416✔
1351
  return vnodeMemory;
1,943,416✔
1352
}
1353

UNCOV
1354
void calculateRstoreFinishTime(double rate, int64_t applyCount, char *restoreStr, size_t restoreStrSize) {
×
UNCOV
1355
  if (rate == 0) {
×
UNCOV
1356
    snprintf(restoreStr, restoreStrSize, "0:0:0");
×
UNCOV
1357
    return;
×
1358
  }
1359

1360
  int64_t costTime = applyCount / rate;
×
1361
  int64_t totalSeconds = costTime / 1000;
×
1362
  int64_t hours = totalSeconds / 3600;
×
1363
  totalSeconds %= 3600;
×
1364
  int64_t minutes = totalSeconds / 60;
×
1365
  int64_t seconds = totalSeconds % 60;
×
1366
  snprintf(restoreStr, restoreStrSize, "%" PRId64 ":%" PRId64 ":%" PRId64, hours, minutes, seconds);
×
1367
}
1368

1369
static int32_t mndRetrieveVnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
1,884✔
1370
  SMnode *pMnode = pReq->info.node;
1,884✔
1371
  SSdb   *pSdb = pMnode->pSdb;
1,884✔
1372
  int32_t numOfRows = 0;
1,884✔
1373
  SVgObj *pVgroup = NULL;
1,884✔
1374
  int32_t cols = 0;
1,884✔
1375
  int64_t curMs = taosGetTimestampMs();
1,884✔
1376
  int32_t code = 0;
1,884✔
1377

1378
  while (numOfRows < rows - TSDB_MAX_REPLICA) {
6,012✔
1379
    pShow->pIter = sdbFetch(pSdb, SDB_VGROUP, pShow->pIter, (void **)&pVgroup);
6,012✔
1380
    if (pShow->pIter == NULL) break;
6,012✔
1381

1382
    for (int32_t i = 0; i < pVgroup->replica && numOfRows < rows; ++i) {
10,868✔
1383
      SVnodeGid       *pGid = &pVgroup->vnodeGid[i];
6,740✔
1384
      SColumnInfoData *pColInfo = NULL;
6,740✔
1385
      cols = 0;
6,740✔
1386

1387
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
6,740✔
1388
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&pGid->dnodeId, false);
6,740✔
1389
      if (code != 0) {
6,740✔
1390
        mError("vgId:%d, failed to set dnodeId, since %s", pVgroup->vgId, tstrerror(code));
×
1391
        return code;
×
1392
      }
1393
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
6,740✔
1394
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->vgId, false);
6,740✔
1395
      if (code != 0) {
6,740✔
1396
        mError("vgId:%d, failed to set vgId, since %s", pVgroup->vgId, tstrerror(code));
×
1397
        return code;
×
1398
      }
1399

1400
      // db_name
1401
      const char *dbname = mndGetDbStr(pVgroup->dbName);
6,740✔
1402
      char        b1[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
6,740✔
1403
      if (dbname != NULL) {
6,740✔
1404
        STR_WITH_MAXSIZE_TO_VARSTR(b1, dbname, TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE);
6,740✔
1405
      } else {
1406
        STR_WITH_MAXSIZE_TO_VARSTR(b1, "NULL", TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE);
×
1407
      }
1408
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
6,740✔
1409
      code = colDataSetVal(pColInfo, numOfRows, (const char *)b1, false);
6,740✔
1410
      if (code != 0) {
6,740✔
1411
        mError("vgId:%d, failed to set dbName, since %s", pVgroup->vgId, tstrerror(code));
×
1412
        return code;
×
1413
      }
1414

1415
      // dnode is online?
1416
      SDnodeObj *pDnode = mndAcquireDnode(pMnode, pGid->dnodeId);
6,740✔
1417
      if (pDnode == NULL) {
6,740✔
1418
        mError("failed to acquire dnode. dnodeId:%d", pGid->dnodeId);
×
1419
        break;
×
1420
      }
1421
      bool isDnodeOnline = mndIsDnodeOnline(pDnode, curMs);
6,740✔
1422

1423
      char       buf[20] = {0};
6,740✔
1424
      ESyncState syncState = (isDnodeOnline) ? pGid->syncState : TAOS_SYNC_STATE_OFFLINE;
6,740✔
1425
      STR_TO_VARSTR(buf, syncStr(syncState));
6,740✔
1426
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
6,740✔
1427
      code = colDataSetVal(pColInfo, numOfRows, (const char *)buf, false);
6,740✔
1428
      if (code != 0) {
6,740✔
1429
        mError("vgId:%d, failed to set syncState, since %s", pVgroup->vgId, tstrerror(code));
×
1430
        return code;
×
1431
      }
1432

1433
      int64_t roleTimeMs = (isDnodeOnline) ? pGid->roleTimeMs : 0;
6,740✔
1434
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
6,740✔
1435
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&roleTimeMs, false);
6,740✔
1436
      if (code != 0) {
6,740✔
1437
        mError("vgId:%d, failed to set roleTimeMs, since %s", pVgroup->vgId, tstrerror(code));
×
1438
        return code;
×
1439
      }
1440

1441
      int64_t startTimeMs = (isDnodeOnline) ? pGid->startTimeMs : 0;
6,740✔
1442
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
6,740✔
1443
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&startTimeMs, false);
6,740✔
1444
      if (code != 0) {
6,740✔
1445
        mError("vgId:%d, failed to set startTimeMs, since %s", pVgroup->vgId, tstrerror(code));
×
1446
        return code;
×
1447
      }
1448

1449
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
6,740✔
1450
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&pGid->syncRestore, false);
6,740✔
1451
      if (code != 0) {
6,740✔
1452
        mError("vgId:%d, failed to set syncRestore, since %s", pVgroup->vgId, tstrerror(code));
×
1453
        return code;
×
1454
      }
1455

1456
      int64_t unappliedCount = pGid->syncCommitIndex - pGid->syncAppliedIndex;
6,740✔
1457
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
6,740✔
1458
      char restoreStr[20] = {0};
6,740✔
1459
      if (unappliedCount > 0) {
6,740✔
UNCOV
1460
        calculateRstoreFinishTime(pGid->appliedRate, unappliedCount, restoreStr, sizeof(restoreStr));
×
1461
      }
1462
      STR_TO_VARSTR(buf, restoreStr);
6,740✔
1463
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&buf, false);
6,740✔
1464
      if (code != 0) {
6,740✔
1465
        mError("vgId:%d, failed to set syncRestore finish time, since %s", pVgroup->vgId, tstrerror(code));
×
1466
        return code;
×
1467
      }
1468

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

1476
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
6,740✔
1477
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&pGid->bufferSegmentUsed, false);
6,740✔
1478
      if (code != 0) {
6,740✔
1479
        mError("vgId:%d, failed to set buffer segment used, since %s", pVgroup->vgId, tstrerror(code));
×
1480
        return code;
×
1481
      }
1482

1483
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
6,740✔
1484
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&pGid->bufferSegmentSize, false);
6,740✔
1485
      if (code != 0) {
6,740✔
1486
        mError("vgId:%d, failed to set buffer segment size, since %s", pVgroup->vgId, tstrerror(code));
×
1487
        return code;
×
1488
      }
1489

1490
      numOfRows++;
6,740✔
1491
      sdbRelease(pSdb, pDnode);
6,740✔
1492
    }
1493

1494
    sdbRelease(pSdb, pVgroup);
4,128✔
1495
  }
1496

1497
  pShow->numOfRows += numOfRows;
1,884✔
1498
  return numOfRows;
1,884✔
1499
}
1500

1501
static void mndCancelGetNextVnode(SMnode *pMnode, void *pIter) {
×
1502
  SSdb *pSdb = pMnode->pSdb;
×
1503
  sdbCancelFetchByType(pSdb, pIter, SDB_VGROUP);
×
1504
}
×
1505

1506
static int32_t mndAddVnodeToVgroup(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup, SArray *pArray) {
82,436✔
1507
  int32_t code = 0;
82,436✔
1508
  taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
82,436✔
1509
  for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
343,663✔
1510
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
261,227✔
1511
    mInfo("trans:%d, dnode:%d, equivalent vnodes:%d others:%d", pTrans->id, pDnode->id, pDnode->numOfVnodes,
261,227✔
1512
          pDnode->numOfOtherNodes);
1513
  }
1514

1515
  SVnodeGid *pVgid = &pVgroup->vnodeGid[pVgroup->replica];
82,436✔
1516
  for (int32_t d = 0; d < taosArrayGetSize(pArray); ++d) {
106,231✔
1517
    SDnodeObj *pDnode = taosArrayGet(pArray, d);
105,311✔
1518

1519
    bool used = false;
105,311✔
1520
    for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
246,433✔
1521
      if (pDnode->id == pVgroup->vnodeGid[vn].dnodeId) {
164,917✔
1522
        used = true;
23,795✔
1523
        break;
23,795✔
1524
      }
1525
    }
1526
    if (used) continue;
105,311✔
1527

1528
    if (pDnode == NULL) {
81,516✔
1529
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_DNODES);
×
1530
    }
1531
    if (pDnode->numOfVnodes >= pDnode->numOfSupportVnodes) {
81,516✔
1532
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_VNODES);
×
1533
    }
1534

1535
    int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
81,516✔
1536
    if (pDnode->memAvail - vgMem - pDnode->memUsed <= 0) {
81,516✔
1537
      mError("trans:%d, db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
×
1538
             pTrans->id, pVgroup->dbName, pVgroup->vgId, vgMem, pDnode->id, pDnode->memAvail, pDnode->memUsed);
1539
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE);
×
1540
    } else {
1541
      pDnode->memUsed += vgMem;
81,516✔
1542
    }
1543

1544
    pVgid->dnodeId = pDnode->id;
81,516✔
1545
    pVgid->syncState = TAOS_SYNC_STATE_OFFLINE;
81,516✔
1546
    mInfo("trans:%id, db:%s, vgId:%d, vn:%d is added, memory:%" PRId64 ", dnode:%d avail:%" PRId64 " used:%" PRId64,
81,516✔
1547
          pTrans->id, pVgroup->dbName, pVgroup->vgId, pVgroup->replica, vgMem, pVgid->dnodeId, pDnode->memAvail,
1548
          pDnode->memUsed);
1549

1550
    pVgroup->replica++;
81,516✔
1551
    pDnode->numOfVnodes++;
81,516✔
1552

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

1571
  code = TSDB_CODE_MND_NO_ENOUGH_DNODES;
920✔
1572
  mError("trans:%d, db:%s, failed to add vnode to vgId:%d since %s", pTrans->id, pVgroup->dbName, pVgroup->vgId,
920✔
1573
         tstrerror(code));
1574
  TAOS_RETURN(code);
920✔
1575
}
1576

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

1586
  int32_t code = -1;
14,936✔
1587
  for (int32_t d = taosArrayGetSize(pArray) - 1; d >= 0; --d) {
20,126✔
1588
    SDnodeObj *pDnode = taosArrayGet(pArray, d);
20,102✔
1589

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

1609
_OVER:
24✔
1610
  if (code != 0) {
14,936✔
1611
    code = TSDB_CODE_APP_ERROR;
24✔
1612
    mError("trans:%d, db:%s, failed to remove vnode from vgId:%d since %s", pTrans->id, pVgroup->dbName, pVgroup->vgId,
24✔
1613
           tstrerror(code));
1614
    TAOS_RETURN(code);
24✔
1615
  }
1616

1617
  for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
39,859✔
1618
    SVnodeGid *pVgid = &pVgroup->vnodeGid[vn];
24,947✔
1619
    mInfo("trans:%d, db:%s, vgId:%d, vn:%d dnode:%d is reserved", pTrans->id, pVgroup->dbName, pVgroup->vgId, vn,
24,947✔
1620
          pVgid->dnodeId);
1621
  }
1622

1623
  SSdbRaw *pVgRaw = mndVgroupActionEncode(pVgroup);
14,912✔
1624
  if (pVgRaw == NULL) {
14,912✔
1625
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1626
    if (terrno != 0) code = terrno;
×
1627
    TAOS_RETURN(code);
×
1628
  }
1629
  if (mndTransAppendGroupRedolog(pTrans, pVgRaw, pVgroup->vgId) != 0) {
14,912✔
1630
    sdbFreeRaw(pVgRaw);
×
1631
    TAOS_RETURN(code);
×
1632
  }
1633
  code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
14,912✔
1634
  if (code != 0) {
14,912✔
1635
    mError("trans:%d, vgId:%d, failed to set raw status since %s at line:%d", pTrans->id, pVgroup->vgId,
×
1636
           tstrerror(code), __LINE__);
1637
  }
1638

1639
  TAOS_RETURN(code);
14,912✔
1640
}
1641

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

1650
  int32_t code = -1;
×
1651
  for (int32_t d = taosArrayGetSize(pArray) - 1; d >= 0; --d) {
×
1652
    SDnodeObj *pDnode = taosArrayGet(pArray, d);
×
1653

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

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

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

1684
  TAOS_RETURN(code);
×
1685
}
1686

1687
int32_t mndAddCreateVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, SVnodeGid *pVgid) {
3,025,949✔
1688
  int32_t      code = 0;
3,025,949✔
1689
  STransAction action = {0};
3,025,949✔
1690

1691
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
3,025,949✔
1692
  if (pDnode == NULL) return -1;
3,025,949✔
1693
  action.epSet = mndGetDnodeEpset(pDnode);
3,025,949✔
1694
  mndReleaseDnode(pMnode, pDnode);
3,025,949✔
1695

1696
  int32_t contLen = 0;
3,025,949✔
1697
  void   *pReq = mndBuildCreateVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen);
3,025,949✔
1698
  if (pReq == NULL) return -1;
3,025,949✔
1699

1700
  action.pCont = pReq;
3,025,949✔
1701
  action.contLen = contLen;
3,025,949✔
1702
  action.msgType = TDMT_DND_CREATE_VNODE;
3,025,949✔
1703
  action.acceptableCode = TSDB_CODE_VND_ALREADY_EXIST;
3,025,949✔
1704
  action.groupId = pVgroup->vgId;
3,025,949✔
1705

1706
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
3,025,949✔
1707
    taosMemoryFree(pReq);
×
1708
    TAOS_RETURN(code);
×
1709
  }
1710

1711
  TAOS_RETURN(code);
3,025,949✔
1712
}
1713

1714
int32_t mndRestoreAddCreateVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
6,280✔
1715
                                       SDnodeObj *pDnode) {
1716
  int32_t      code = 0;
6,280✔
1717
  STransAction action = {0};
6,280✔
1718

1719
  action.epSet = mndGetDnodeEpset(pDnode);
6,280✔
1720

1721
  int32_t contLen = 0;
6,280✔
1722
  void   *pReq = mndBuildCreateVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen);
6,280✔
1723
  if (pReq == NULL) {
6,280✔
1724
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1725
    if (terrno != 0) code = terrno;
×
1726
    TAOS_RETURN(code);
×
1727
  }
1728

1729
  action.pCont = pReq;
6,280✔
1730
  action.contLen = contLen;
6,280✔
1731
  action.msgType = TDMT_DND_CREATE_VNODE;
6,280✔
1732
  action.acceptableCode = TSDB_CODE_VND_ALREADY_EXIST;
6,280✔
1733
  action.groupId = pVgroup->vgId;
6,280✔
1734

1735
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
6,280✔
1736
    taosMemoryFree(pReq);
×
1737
    TAOS_RETURN(code);
×
1738
  }
1739

1740
  TAOS_RETURN(code);
6,280✔
1741
}
1742

1743
int32_t mndAddAlterVnodeConfirmAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) {
278,869✔
1744
  int32_t      code = 0;
278,869✔
1745
  STransAction action = {0};
278,869✔
1746
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
278,869✔
1747

1748
  mInfo("trans:%d, vgId:%d, build alter vnode confirm req", pTrans->id, pVgroup->vgId);
278,869✔
1749
  int32_t   contLen = sizeof(SMsgHead);
278,869✔
1750
  SMsgHead *pHead = taosMemoryMalloc(contLen);
278,869✔
1751
  if (pHead == NULL) {
278,869✔
1752
    TAOS_RETURN(terrno);
×
1753
  }
1754

1755
  pHead->contLen = htonl(contLen);
278,869✔
1756
  pHead->vgId = htonl(pVgroup->vgId);
278,869✔
1757

1758
  action.pCont = pHead;
278,869✔
1759
  action.contLen = contLen;
278,869✔
1760
  action.msgType = TDMT_VND_ALTER_CONFIRM;
278,869✔
1761
  // incorrect redirect result will cause this erro
1762
  action.retryCode = TSDB_CODE_VND_INVALID_VGROUP_ID;
278,869✔
1763
  action.groupId = pVgroup->vgId;
278,869✔
1764

1765
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
278,869✔
1766
    taosMemoryFree(pHead);
×
1767
    TAOS_RETURN(code);
×
1768
  }
1769

1770
  TAOS_RETURN(code);
278,869✔
1771
}
1772

1773
int32_t mndAddChangeConfigAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pOldVgroup, SVgObj *pNewVgroup,
×
1774
                                 int32_t dnodeId) {
1775
  int32_t      code = 0;
×
1776
  STransAction action = {0};
×
1777
  action.epSet = mndGetVgroupEpset(pMnode, pNewVgroup);
×
1778

1779
  int32_t contLen = 0;
×
1780
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pNewVgroup, dnodeId, &contLen);
×
1781
  if (pReq == NULL) {
×
1782
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1783
    if (terrno != 0) code = terrno;
×
1784
    TAOS_RETURN(code);
×
1785
  }
1786

1787
  int32_t totallen = contLen + sizeof(SMsgHead);
×
1788

1789
  SMsgHead *pHead = taosMemoryMalloc(totallen);
×
1790
  if (pHead == NULL) {
×
1791
    taosMemoryFree(pReq);
×
1792
    TAOS_RETURN(terrno);
×
1793
  }
1794

1795
  pHead->contLen = htonl(totallen);
×
1796
  pHead->vgId = htonl(pNewVgroup->vgId);
×
1797

1798
  memcpy((void *)(pHead + 1), pReq, contLen);
×
1799
  taosMemoryFree(pReq);
×
1800

1801
  action.pCont = pHead;
×
1802
  action.contLen = totallen;
×
1803
  action.msgType = TDMT_SYNC_CONFIG_CHANGE;
×
1804

1805
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
×
1806
    taosMemoryFree(pHead);
×
1807
    TAOS_RETURN(code);
×
1808
  }
1809

1810
  TAOS_RETURN(code);
×
1811
}
1812

1813
static int32_t mndAddAlterVnodeHashRangeAction(SMnode *pMnode, STrans *pTrans, int32_t srcVgId, SVgObj *pVgroup) {
23,680✔
1814
  int32_t      code = 0;
23,680✔
1815
  STransAction action = {0};
23,680✔
1816
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
23,680✔
1817

1818
  int32_t contLen = 0;
23,680✔
1819
  void   *pReq = mndBuildAlterVnodeHashRangeReq(pMnode, srcVgId, pVgroup, &contLen);
23,680✔
1820
  if (pReq == NULL) {
23,680✔
1821
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1822
    if (terrno != 0) code = terrno;
×
1823
    TAOS_RETURN(code);
×
1824
  }
1825

1826
  action.pCont = pReq;
23,680✔
1827
  action.contLen = contLen;
23,680✔
1828
  action.msgType = TDMT_VND_ALTER_HASHRANGE;
23,680✔
1829
  action.acceptableCode = TSDB_CODE_VND_ALREADY_EXIST;
23,680✔
1830

1831
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
23,680✔
1832
    taosMemoryFree(pReq);
×
1833
    TAOS_RETURN(code);
×
1834
  }
1835

1836
  mInfo("trans:%d, add alter vnode hash range action for from vgId:%d to vgId:%d", pTrans->id, srcVgId, pVgroup->vgId);
23,680✔
1837
  TAOS_RETURN(code);
23,680✔
1838
}
1839

1840
int32_t mndAddAlterVnodeConfigAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) {
205,568✔
1841
  int32_t      code = 0;
205,568✔
1842
  STransAction action = {0};
205,568✔
1843
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
205,568✔
1844

1845
  int32_t contLen = 0;
205,568✔
1846
  void   *pReq = mndBuildAlterVnodeConfigReq(pMnode, pDb, pVgroup, &contLen);
205,568✔
1847
  if (pReq == NULL) {
205,568✔
1848
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1849
    if (terrno != 0) code = terrno;
×
1850
    TAOS_RETURN(code);
×
1851
  }
1852

1853
  action.pCont = pReq;
205,568✔
1854
  action.contLen = contLen;
205,568✔
1855
  action.msgType = TDMT_VND_ALTER_CONFIG;
205,568✔
1856
  action.groupId = pVgroup->vgId;
205,568✔
1857

1858
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
205,568✔
1859
    taosMemoryFree(pReq);
×
1860
    TAOS_RETURN(code);
×
1861
  }
1862

1863
  TAOS_RETURN(code);
205,568✔
1864
}
1865

1866
int32_t mndAddNewVgPrepareAction(SMnode *pMnode, STrans *pTrans, SVgObj *pVg) {
2,591,011✔
1867
  int32_t  code = 0;
2,591,011✔
1868
  SSdbRaw *pRaw = mndVgroupActionEncode(pVg);
2,591,011✔
1869
  if (pRaw == NULL) {
2,591,011✔
1870
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1871
    if (terrno != 0) code = terrno;
×
1872
    goto _err;
×
1873
  }
1874

1875
  TAOS_CHECK_GOTO(mndTransAppendPrepareLog(pTrans, pRaw), NULL, _err);
2,591,011✔
1876
  if (sdbSetRawStatus(pRaw, SDB_STATUS_CREATING) != 0) {
2,591,011✔
1877
    mError("vgId:%d, failed to set raw status at line:%d", pVg->vgId, __LINE__);
×
1878
  }
1879
  if (code != 0) {
2,591,011✔
1880
    mError("vgId:%d, failed to set raw status since %s at line:%d", pVg->vgId, tstrerror(code), __LINE__);
×
1881
    TAOS_RETURN(code);
×
1882
  }
1883
  pRaw = NULL;
2,591,011✔
1884
  TAOS_RETURN(code);
2,591,011✔
1885

1886
_err:
×
1887
  sdbFreeRaw(pRaw);
×
1888
  TAOS_RETURN(code);
×
1889
}
1890

1891
int32_t mndAddAlterVnodeReplicaAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId) {
680,549✔
1892
  int32_t    code = 0;
680,549✔
1893
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
680,549✔
1894
  if (pDnode == NULL) {
680,549✔
1895
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1896
    if (terrno != 0) code = terrno;
×
1897
    TAOS_RETURN(code);
×
1898
  }
1899

1900
  STransAction action = {0};
680,549✔
1901
  action.epSet = mndGetDnodeEpset(pDnode);
680,549✔
1902
  mndReleaseDnode(pMnode, pDnode);
680,549✔
1903

1904
  int32_t contLen = 0;
680,549✔
1905
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pVgroup, dnodeId, &contLen);
680,549✔
1906
  if (pReq == NULL) {
680,549✔
1907
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1908
    if (terrno != 0) code = terrno;
×
1909
    TAOS_RETURN(code);
×
1910
  }
1911

1912
  action.pCont = pReq;
680,549✔
1913
  action.contLen = contLen;
680,549✔
1914
  action.msgType = TDMT_VND_ALTER_REPLICA;
680,549✔
1915
  action.groupId = pVgroup->vgId;
680,549✔
1916

1917
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
680,549✔
1918
    taosMemoryFree(pReq);
×
1919
    TAOS_RETURN(code);
×
1920
  }
1921

1922
  TAOS_RETURN(code);
680,549✔
1923
}
1924

1925
int32_t mndAddCheckLearnerCatchupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId) {
×
1926
  int32_t    code = 0;
×
1927
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
×
1928
  if (pDnode == NULL) {
×
1929
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1930
    if (terrno != 0) code = terrno;
×
1931
    TAOS_RETURN(code);
×
1932
  }
1933

1934
  STransAction action = {0};
×
1935
  action.epSet = mndGetDnodeEpset(pDnode);
×
1936
  mndReleaseDnode(pMnode, pDnode);
×
1937

1938
  int32_t contLen = 0;
×
1939
  void   *pReq = mndBuildCheckLearnCatchupReq(pMnode, pDb, pVgroup, dnodeId, &contLen);
×
1940
  if (pReq == NULL) {
×
1941
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1942
    if (terrno != 0) code = terrno;
×
1943
    TAOS_RETURN(code);
×
1944
  }
1945

1946
  action.pCont = pReq;
×
1947
  action.contLen = contLen;
×
1948
  action.msgType = TDMT_DND_CHECK_VNODE_LEARNER_CATCHUP;
×
1949
  action.acceptableCode = TSDB_CODE_VND_ALREADY_IS_VOTER;
×
1950
  action.retryCode = TSDB_CODE_VND_NOT_CATCH_UP;
×
1951

1952
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
×
1953
    taosMemoryFree(pReq);
×
1954
    TAOS_RETURN(code);
×
1955
  }
1956

1957
  TAOS_RETURN(code);
×
1958
}
1959

1960
int32_t mndAddAlterVnodeTypeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId) {
100,566✔
1961
  int32_t    code = 0;
100,566✔
1962
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
100,566✔
1963
  if (pDnode == NULL) {
100,566✔
1964
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1965
    if (terrno != 0) code = terrno;
×
1966
    TAOS_RETURN(code);
×
1967
  }
1968

1969
  STransAction action = {0};
100,566✔
1970
  action.epSet = mndGetDnodeEpset(pDnode);
100,566✔
1971
  mndReleaseDnode(pMnode, pDnode);
100,566✔
1972

1973
  int32_t contLen = 0;
100,566✔
1974
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pVgroup, dnodeId, &contLen);
100,566✔
1975
  if (pReq == NULL) {
100,566✔
1976
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1977
    if (terrno != 0) code = terrno;
×
1978
    TAOS_RETURN(code);
×
1979
  }
1980

1981
  action.pCont = pReq;
100,566✔
1982
  action.contLen = contLen;
100,566✔
1983
  action.msgType = TDMT_DND_ALTER_VNODE_TYPE;
100,566✔
1984
  action.acceptableCode = TSDB_CODE_VND_ALREADY_IS_VOTER;
100,566✔
1985
  action.retryCode = TSDB_CODE_VND_NOT_CATCH_UP;
100,566✔
1986
  action.groupId = pVgroup->vgId;
100,566✔
1987

1988
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
100,566✔
1989
    taosMemoryFree(pReq);
×
1990
    TAOS_RETURN(code);
×
1991
  }
1992

1993
  TAOS_RETURN(code);
100,566✔
1994
}
1995

1996
int32_t mndRestoreAddAlterVnodeTypeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
6,280✔
1997
                                          SDnodeObj *pDnode) {
1998
  int32_t      code = 0;
6,280✔
1999
  STransAction action = {0};
6,280✔
2000
  action.epSet = mndGetDnodeEpset(pDnode);
6,280✔
2001

2002
  int32_t contLen = 0;
6,280✔
2003
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pVgroup, pDnode->id, &contLen);
6,280✔
2004
  if (pReq == NULL) {
6,280✔
2005
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2006
    if (terrno != 0) code = terrno;
×
2007
    TAOS_RETURN(code);
×
2008
  }
2009

2010
  action.pCont = pReq;
6,280✔
2011
  action.contLen = contLen;
6,280✔
2012
  action.msgType = TDMT_DND_ALTER_VNODE_TYPE;
6,280✔
2013
  action.acceptableCode = TSDB_CODE_VND_ALREADY_IS_VOTER;
6,280✔
2014
  action.retryCode = TSDB_CODE_VND_NOT_CATCH_UP;
6,280✔
2015
  action.groupId = pVgroup->vgId;
6,280✔
2016

2017
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
6,280✔
2018
    taosMemoryFree(pReq);
×
2019
    TAOS_RETURN(code);
×
2020
  }
2021

2022
  TAOS_RETURN(code);
6,280✔
2023
}
2024

2025
static int32_t mndAddDisableVnodeWriteAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
23,680✔
2026
                                             int32_t dnodeId) {
2027
  int32_t    code = 0;
23,680✔
2028
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
23,680✔
2029
  if (pDnode == NULL) {
23,680✔
2030
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2031
    if (terrno != 0) code = terrno;
×
2032
    TAOS_RETURN(code);
×
2033
  }
2034

2035
  STransAction action = {0};
23,680✔
2036
  action.epSet = mndGetDnodeEpset(pDnode);
23,680✔
2037
  mndReleaseDnode(pMnode, pDnode);
23,680✔
2038

2039
  int32_t contLen = 0;
23,680✔
2040
  void   *pReq = mndBuildDisableVnodeWriteReq(pMnode, pDb, pVgroup->vgId, &contLen);
23,680✔
2041
  if (pReq == NULL) {
23,680✔
2042
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2043
    if (terrno != 0) code = terrno;
×
2044
    TAOS_RETURN(code);
×
2045
  }
2046

2047
  action.pCont = pReq;
23,680✔
2048
  action.contLen = contLen;
23,680✔
2049
  action.msgType = TDMT_VND_DISABLE_WRITE;
23,680✔
2050

2051
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
23,680✔
2052
    taosMemoryFree(pReq);
×
2053
    TAOS_RETURN(code);
×
2054
  }
2055

2056
  TAOS_RETURN(code);
23,680✔
2057
}
2058

2059
int32_t mndAddDropVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, SVnodeGid *pVgid,
4,488,326✔
2060
                              bool isRedo) {
2061
  int32_t      code = 0;
4,488,326✔
2062
  STransAction action = {0};
4,488,326✔
2063

2064
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
4,488,326✔
2065
  if (pDnode == NULL) {
4,488,326✔
2066
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2067
    if (terrno != 0) code = terrno;
×
2068
    TAOS_RETURN(code);
×
2069
  }
2070
  action.epSet = mndGetDnodeEpset(pDnode);
4,488,326✔
2071
  mndReleaseDnode(pMnode, pDnode);
4,488,326✔
2072

2073
  int32_t contLen = 0;
4,488,326✔
2074
  void   *pReq = mndBuildDropVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen);
4,488,326✔
2075
  if (pReq == NULL) {
4,488,326✔
2076
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2077
    if (terrno != 0) code = terrno;
×
2078
    TAOS_RETURN(code);
×
2079
  }
2080

2081
  action.pCont = pReq;
4,488,326✔
2082
  action.contLen = contLen;
4,488,326✔
2083
  action.msgType = TDMT_DND_DROP_VNODE;
4,488,326✔
2084
  action.acceptableCode = TSDB_CODE_VND_NOT_EXIST;
4,488,326✔
2085
  action.groupId = pVgroup->vgId;
4,488,326✔
2086

2087
  if (isRedo) {
4,488,326✔
2088
    if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
1,608,293✔
2089
      taosMemoryFree(pReq);
×
2090
      TAOS_RETURN(code);
×
2091
    }
2092
  } else {
2093
    if ((code = mndTransAppendUndoAction(pTrans, &action)) != 0) {
2,880,033✔
2094
      taosMemoryFree(pReq);
×
2095
      TAOS_RETURN(code);
×
2096
    }
2097
  }
2098

2099
  TAOS_RETURN(code);
4,488,326✔
2100
}
2101

2102
int32_t mndSetMoveVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t vnIndex,
16,801✔
2103
                                    SArray *pArray, bool force, bool unsafe) {
2104
  int32_t code = 0;
16,801✔
2105
  SVgObj  newVg = {0};
16,801✔
2106
  memcpy(&newVg, pVgroup, sizeof(SVgObj));
16,801✔
2107

2108
  mInfo("vgId:%d, trans:%d, vgroup info before move, replica:%d", newVg.vgId, pTrans->id, newVg.replica);
16,801✔
2109
  for (int32_t i = 0; i < newVg.replica; ++i) {
54,332✔
2110
    mInfo("vgId:%d, trans:%d, vnode:%d dnode:%d", newVg.vgId, pTrans->id, i, newVg.vnodeGid[i].dnodeId);
37,531✔
2111
  }
2112

2113
  if (!force) {
16,801✔
2114
#if 1
2115
    {
2116
#else
2117
    if (newVg.replica == 1) {
2118
#endif
2119
      mInfo("vgId:%d, trans:%d, will add 1 vnode, replca:%d", pVgroup->vgId, pTrans->id, newVg.replica);
16,801✔
2120
      TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVg, pArray));
16,801✔
2121
      for (int32_t i = 0; i < newVg.replica - 1; ++i) {
54,332✔
2122
        TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg, newVg.vnodeGid[i].dnodeId));
37,531✔
2123
      }
2124
      TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg, &newVg.vnodeGid[newVg.replica - 1]));
16,801✔
2125
      TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg));
16,801✔
2126

2127
      mInfo("vgId:%d, trans:%d, will remove 1 vnode, replca:2", pVgroup->vgId, pTrans->id);
16,801✔
2128
      newVg.replica--;
16,801✔
2129
      SVnodeGid del = newVg.vnodeGid[vnIndex];
16,801✔
2130
      newVg.vnodeGid[vnIndex] = newVg.vnodeGid[newVg.replica];
16,801✔
2131
      memset(&newVg.vnodeGid[newVg.replica], 0, sizeof(SVnodeGid));
16,801✔
2132
      {
2133
        SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
16,801✔
2134
        if (pRaw == NULL) {
16,801✔
2135
          code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2136
          if (terrno != 0) code = terrno;
×
2137
          TAOS_RETURN(code);
×
2138
        }
2139
        if ((code = mndTransAppendGroupRedolog(pTrans, pRaw, pVgroup->vgId)) != 0) {
16,801✔
2140
          sdbFreeRaw(pRaw);
×
2141
          TAOS_RETURN(code);
×
2142
        }
2143
        code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
16,801✔
2144
        if (code != 0) {
16,801✔
2145
          mError("vgId:%d, failed to set raw status since %s at line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
2146
          return code;
×
2147
        }
2148
      }
2149

2150
      TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pDb, &newVg, &del, true));
16,801✔
2151
      for (int32_t i = 0; i < newVg.replica; ++i) {
54,332✔
2152
        TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg, newVg.vnodeGid[i].dnodeId));
37,531✔
2153
      }
2154
      TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg));
16,801✔
2155
#if 1
2156
    }
2157
#else
2158
    } else {  // new replica == 3
2159
      mInfo("vgId:%d, will add 1 vnode, replca:3", pVgroup->vgId);
2160
      if (mndAddVnodeToVgroup(pMnode, pTrans, &newVg, pArray) != 0) return -1;
2161
      mInfo("vgId:%d, will remove 1 vnode, replca:4", pVgroup->vgId);
2162
      newVg.replica--;
2163
      SVnodeGid del = newVg.vnodeGid[vnIndex];
2164
      newVg.vnodeGid[vnIndex] = newVg.vnodeGid[newVg.replica];
2165
      memset(&newVg.vnodeGid[newVg.replica], 0, sizeof(SVnodeGid));
2166
      {
2167
        SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
2168
        if (pRaw == NULL) return -1;
2169
        if (mndTransAppendRedolog(pTrans, pRaw) != 0) {
2170
          sdbFreeRaw(pRaw);
2171
          return -1;
2172
        }
2173
      }
2174

2175
      if (mndAddDropVnodeAction(pMnode, pTrans, pDb, &newVg, &del, true) != 0) return -1;
2176
      for (int32_t i = 0; i < newVg.replica; ++i) {
2177
        if (i == vnIndex) continue;
2178
        if (mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg, newVg.vnodeGid[i].dnodeId) != 0) return -1;
2179
      }
2180
      if (mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg, &newVg.vnodeGid[vnIndex]) != 0) return -1;
2181
      if (mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg) != 0) return -1;
2182
    }
2183
#endif
2184
  } else {
2185
    mInfo("vgId:%d, will add 1 vnode and force remove 1 vnode", pVgroup->vgId);
×
2186
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVg, pArray));
×
2187
    newVg.replica--;
×
2188
    // SVnodeGid del = newVg.vnodeGid[vnIndex];
2189
    newVg.vnodeGid[vnIndex] = newVg.vnodeGid[newVg.replica];
×
2190
    memset(&newVg.vnodeGid[newVg.replica], 0, sizeof(SVnodeGid));
×
2191
    {
2192
      SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
×
2193
      if (pRaw == NULL) {
×
2194
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2195
        if (terrno != 0) code = terrno;
×
2196
        TAOS_RETURN(code);
×
2197
      }
2198
      if ((code = mndTransAppendGroupRedolog(pTrans, pRaw, pVgroup->vgId)) != 0) {
×
2199
        sdbFreeRaw(pRaw);
×
2200
        TAOS_RETURN(code);
×
2201
      }
2202
      code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
×
2203
      if (code != 0) {
×
2204
        mError("vgId:%d, failed to set raw status since %s at line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
2205
        return code;
×
2206
      }
2207
    }
2208

2209
    for (int32_t i = 0; i < newVg.replica; ++i) {
×
2210
      if (i != vnIndex) {
×
2211
        TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg, newVg.vnodeGid[i].dnodeId));
×
2212
      }
2213
    }
2214
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg, &newVg.vnodeGid[vnIndex]));
×
2215
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg));
×
2216

2217
    if (newVg.replica == 1) {
×
2218
      if (force && !unsafe) {
×
2219
        TAOS_RETURN(TSDB_CODE_VND_META_DATA_UNSAFE_DELETE);
×
2220
      }
2221

2222
      SSdb *pSdb = pMnode->pSdb;
×
2223
      void *pIter = NULL;
×
2224

2225
      while (1) {
×
2226
        SStbObj *pStb = NULL;
×
2227
        pIter = sdbFetch(pSdb, SDB_STB, pIter, (void **)&pStb);
×
2228
        if (pIter == NULL) break;
×
2229

2230
        if (strcmp(pStb->db, pDb->name) == 0) {
×
2231
          if ((code = mndSetForceDropCreateStbRedoActions(pMnode, pTrans, &newVg, pStb)) != 0) {
×
2232
            sdbCancelFetch(pSdb, pIter);
×
2233
            sdbRelease(pSdb, pStb);
×
2234
            TAOS_RETURN(code);
×
2235
          }
2236
        }
2237

2238
        sdbRelease(pSdb, pStb);
×
2239
      }
2240

2241
      mInfo("vgId:%d, all data is dropped since replica=1", pVgroup->vgId);
×
2242
    }
2243
  }
2244

2245
  {
2246
    SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
16,801✔
2247
    if (pRaw == NULL) {
16,801✔
2248
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2249
      if (terrno != 0) code = terrno;
×
2250
      TAOS_RETURN(code);
×
2251
    }
2252
    if ((code = mndTransAppendCommitlog(pTrans, pRaw)) != 0) {
16,801✔
2253
      sdbFreeRaw(pRaw);
×
2254
      TAOS_RETURN(code);
×
2255
    }
2256
    code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
16,801✔
2257
    if (code != 0) {
16,801✔
2258
      mError("vgId:%d, failed to set raw status since %s at line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
2259
      return code;
×
2260
    }
2261
  }
2262

2263
  mInfo("vgId:%d, vgroup info after move, replica:%d", newVg.vgId, newVg.replica);
16,801✔
2264
  for (int32_t i = 0; i < newVg.replica; ++i) {
54,332✔
2265
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
37,531✔
2266
  }
2267
  TAOS_RETURN(code);
16,801✔
2268
}
2269

2270
int32_t mndSetMoveVgroupsInfoToTrans(SMnode *pMnode, STrans *pTrans, int32_t delDnodeId, bool force, bool unsafe) {
8,283✔
2271
  int32_t code = 0;
8,283✔
2272
  SArray *pArray = mndBuildDnodesArray(pMnode, delDnodeId, NULL);
8,283✔
2273
  if (pArray == NULL) {
8,283✔
2274
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2275
    if (terrno != 0) code = terrno;
×
2276
    TAOS_RETURN(code);
×
2277
  }
2278

2279
  void *pIter = NULL;
8,283✔
2280
  while (1) {
23,994✔
2281
    SVgObj *pVgroup = NULL;
32,277✔
2282
    pIter = sdbFetch(pMnode->pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
32,277✔
2283
    if (pIter == NULL) break;
32,277✔
2284

2285
    int32_t vnIndex = -1;
23,994✔
2286
    for (int32_t i = 0; i < pVgroup->replica; ++i) {
46,304✔
2287
      if (pVgroup->vnodeGid[i].dnodeId == delDnodeId) {
39,111✔
2288
        vnIndex = i;
16,801✔
2289
        break;
16,801✔
2290
      }
2291
    }
2292

2293
    code = 0;
23,994✔
2294
    if (vnIndex != -1) {
23,994✔
2295
      mInfo("vgId:%d, trans:%d, vnode:%d will be removed from dnode:%d, force:%d", pVgroup->vgId, pTrans->id, vnIndex,
16,801✔
2296
            delDnodeId, force);
2297
      SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName);
16,801✔
2298
      code = mndSetMoveVgroupInfoToTrans(pMnode, pTrans, pDb, pVgroup, vnIndex, pArray, force, unsafe);
16,801✔
2299
      mndReleaseDb(pMnode, pDb);
16,801✔
2300
    }
2301

2302
    sdbRelease(pMnode->pSdb, pVgroup);
23,994✔
2303

2304
    if (code != 0) {
23,994✔
2305
      sdbCancelFetch(pMnode->pSdb, pIter);
×
2306
      break;
×
2307
    }
2308
  }
2309

2310
  taosArrayDestroy(pArray);
8,283✔
2311
  TAOS_RETURN(code);
8,283✔
2312
}
2313

2314
static int32_t mndAddIncVgroupReplicaToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
64,400✔
2315
                                             int32_t newDnodeId) {
2316
  int32_t code = 0;
64,400✔
2317
  mInfo("vgId:%d, will add 1 vnode, replica:%d dnode:%d", pVgroup->vgId, pVgroup->replica, newDnodeId);
64,400✔
2318

2319
  // assoc dnode
2320
  SVnodeGid *pGid = &pVgroup->vnodeGid[pVgroup->replica];
64,400✔
2321
  pVgroup->replica++;
64,400✔
2322
  pGid->dnodeId = newDnodeId;
64,400✔
2323
  pGid->syncState = TAOS_SYNC_STATE_OFFLINE;
64,400✔
2324
  pGid->nodeRole = TAOS_SYNC_ROLE_LEARNER;
64,400✔
2325

2326
  SSdbRaw *pVgRaw = mndVgroupActionEncode(pVgroup);
64,400✔
2327
  if (pVgRaw == NULL) {
64,400✔
2328
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2329
    if (terrno != 0) code = terrno;
×
2330
    TAOS_RETURN(code);
×
2331
  }
2332
  if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
64,400✔
2333
    sdbFreeRaw(pVgRaw);
×
2334
    TAOS_RETURN(code);
×
2335
  }
2336
  code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
64,400✔
2337
  if (code != 0) {
64,400✔
2338
    mError("vgId:%d, failed to set raw status since %s at line:%d", pVgroup->vgId, tstrerror(code), __LINE__);
×
2339
    TAOS_RETURN(code);
×
2340
  }
2341

2342
  // learner
2343
  for (int32_t i = 0; i < pVgroup->replica - 1; ++i) {
214,770✔
2344
    TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, pVgroup, pVgroup->vnodeGid[i].dnodeId));
150,370✔
2345
  }
2346
  TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pDb, pVgroup, pGid));
64,400✔
2347

2348
  // voter
2349
  pGid->nodeRole = TAOS_SYNC_ROLE_VOTER;
64,400✔
2350
  TAOS_CHECK_RETURN(mndAddAlterVnodeTypeAction(pMnode, pTrans, pDb, pVgroup, pGid->dnodeId));
64,400✔
2351
  for (int32_t i = 0; i < pVgroup->replica - 1; ++i) {
214,770✔
2352
    TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, pVgroup, pVgroup->vnodeGid[i].dnodeId));
150,370✔
2353
  }
2354

2355
  // confirm
2356
  TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, pVgroup));
64,400✔
2357

2358
  TAOS_RETURN(code);
64,400✔
2359
}
2360

2361
static int32_t mndAddDecVgroupReplicaFromTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
64,400✔
2362
                                               int32_t delDnodeId) {
2363
  int32_t code = 0;
64,400✔
2364
  mInfo("vgId:%d, will remove 1 vnode, replica:%d dnode:%d", pVgroup->vgId, pVgroup->replica, delDnodeId);
64,400✔
2365

2366
  SVnodeGid *pGid = NULL;
64,400✔
2367
  SVnodeGid  delGid = {0};
64,400✔
2368
  for (int32_t i = 0; i < pVgroup->replica; ++i) {
104,439✔
2369
    if (pVgroup->vnodeGid[i].dnodeId == delDnodeId) {
104,439✔
2370
      pGid = &pVgroup->vnodeGid[i];
64,400✔
2371
      break;
64,400✔
2372
    }
2373
  }
2374

2375
  if (pGid == NULL) return 0;
64,400✔
2376

2377
  pVgroup->replica--;
64,400✔
2378
  memcpy(&delGid, pGid, sizeof(SVnodeGid));
64,400✔
2379
  memcpy(pGid, &pVgroup->vnodeGid[pVgroup->replica], sizeof(SVnodeGid));
64,400✔
2380
  memset(&pVgroup->vnodeGid[pVgroup->replica], 0, sizeof(SVnodeGid));
64,400✔
2381

2382
  SSdbRaw *pVgRaw = mndVgroupActionEncode(pVgroup);
64,400✔
2383
  if (pVgRaw == NULL) {
64,400✔
2384
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2385
    if (terrno != 0) code = terrno;
×
2386
    TAOS_RETURN(code);
×
2387
  }
2388
  if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
64,400✔
2389
    sdbFreeRaw(pVgRaw);
×
2390
    TAOS_RETURN(code);
×
2391
  }
2392
  code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
64,400✔
2393
  if (code != 0) {
64,400✔
2394
    mError("vgId:%d, failed to set raw status since %s at line:%d", pVgroup->vgId, tstrerror(code), __LINE__);
×
2395
    TAOS_RETURN(code);
×
2396
  }
2397

2398
  TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pDb, pVgroup, &delGid, true));
64,400✔
2399
  for (int32_t i = 0; i < pVgroup->replica; ++i) {
214,770✔
2400
    TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, pVgroup, pVgroup->vnodeGid[i].dnodeId));
150,370✔
2401
  }
2402
  TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, pVgroup));
64,400✔
2403

2404
  TAOS_RETURN(code);
64,400✔
2405
}
2406

2407
static int32_t mndRedistributeVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SVgObj *pVgroup, SDnodeObj *pNew1,
37,400✔
2408
                                     SDnodeObj *pOld1, SDnodeObj *pNew2, SDnodeObj *pOld2, SDnodeObj *pNew3,
2409
                                     SDnodeObj *pOld3) {
2410
  int32_t code = -1;
37,400✔
2411
  STrans *pTrans = NULL;
37,400✔
2412

2413
  pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_GLOBAL, pReq, "red-vgroup");
37,400✔
2414
  if (pTrans == NULL) {
37,400✔
2415
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2416
    if (terrno != 0) code = terrno;
×
2417
    goto _OVER;
×
2418
  }
2419

2420
  mndTransSetDbName(pTrans, pVgroup->dbName, NULL);
37,400✔
2421
  TAOS_CHECK_GOTO(mndTransCheckConflictWithCompact(pMnode, pTrans), NULL, _OVER);
37,400✔
2422
  TAOS_CHECK_GOTO(mndTransCheckConflictWithRetention(pMnode, pTrans), NULL, _OVER);
37,161✔
2423

2424
  mndTransSetSerial(pTrans);
37,161✔
2425
  mInfo("trans:%d, used to redistribute vgroup, vgId:%d", pTrans->id, pVgroup->vgId);
37,161✔
2426

2427
  SVgObj newVg = {0};
37,161✔
2428
  memcpy(&newVg, pVgroup, sizeof(SVgObj));
37,161✔
2429
  mInfo("vgId:%d, vgroup info before redistribute, replica:%d", newVg.vgId, newVg.replica);
37,161✔
2430
  for (int32_t i = 0; i < newVg.replica; ++i) {
123,598✔
2431
    mInfo("vgId:%d, vnode:%d dnode:%d role:%s", newVg.vgId, i, newVg.vnodeGid[i].dnodeId,
86,437✔
2432
          syncStr(newVg.vnodeGid[i].syncState));
2433
  }
2434

2435
  if (pNew1 != NULL && pOld1 != NULL) {
37,161✔
2436
    int32_t numOfVnodes = mndGetVnodesNum(pMnode, pNew1->id);
37,161✔
2437
    if (numOfVnodes >= pNew1->numOfSupportVnodes) {
37,161✔
2438
      mError("vgId:%d, no enough vnodes in dnode:%d, numOfVnodes:%d support:%d", newVg.vgId, pNew1->id, numOfVnodes,
709✔
2439
             pNew1->numOfSupportVnodes);
2440
      code = TSDB_CODE_MND_NO_ENOUGH_VNODES;
709✔
2441
      goto _OVER;
709✔
2442
    }
2443

2444
    int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
36,452✔
2445
    if (pNew1->memAvail - vgMem - pNew1->memUsed <= 0) {
36,452✔
2446
      mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
×
2447
             pVgroup->dbName, pVgroup->vgId, vgMem, pNew1->id, pNew1->memAvail, pNew1->memUsed);
2448
      code = TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE;
×
2449
      goto _OVER;
×
2450
    } else {
2451
      pNew1->memUsed += vgMem;
36,452✔
2452
    }
2453

2454
    TAOS_CHECK_GOTO(mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pNew1->id), NULL, _OVER);
36,452✔
2455
    TAOS_CHECK_GOTO(mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pOld1->id), NULL, _OVER);
36,452✔
2456
  }
2457

2458
  if (pNew2 != NULL && pOld2 != NULL) {
36,452✔
2459
    int32_t numOfVnodes = mndGetVnodesNum(pMnode, pNew2->id);
9,760✔
2460
    if (numOfVnodes >= pNew2->numOfSupportVnodes) {
9,760✔
2461
      mError("vgId:%d, no enough vnodes in dnode:%d, numOfVnodes:%d support:%d", newVg.vgId, pNew2->id, numOfVnodes,
×
2462
             pNew2->numOfSupportVnodes);
2463
      code = TSDB_CODE_MND_NO_ENOUGH_VNODES;
×
2464
      goto _OVER;
×
2465
    }
2466
    int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
9,760✔
2467
    if (pNew2->memAvail - vgMem - pNew2->memUsed <= 0) {
9,760✔
2468
      mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
×
2469
             pVgroup->dbName, pVgroup->vgId, vgMem, pNew2->id, pNew2->memAvail, pNew2->memUsed);
2470
      code = TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE;
×
2471
      goto _OVER;
×
2472
    } else {
2473
      pNew2->memUsed += vgMem;
9,760✔
2474
    }
2475
    TAOS_CHECK_GOTO(mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pNew2->id), NULL, _OVER);
9,760✔
2476
    TAOS_CHECK_GOTO(mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pOld2->id), NULL, _OVER);
9,760✔
2477
  }
2478

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

2500
  {
2501
    SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
36,452✔
2502
    if (pRaw == NULL) {
36,452✔
2503
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2504
      if (terrno != 0) code = terrno;
×
2505
      goto _OVER;
×
2506
    }
2507
    if ((code = mndTransAppendCommitlog(pTrans, pRaw)) != 0) {
36,452✔
2508
      sdbFreeRaw(pRaw);
×
2509
      goto _OVER;
×
2510
    }
2511
    code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
36,452✔
2512
    if (code != 0) {
36,452✔
2513
      mError("vgId:%d, failed to set raw status since %s at line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
2514
      goto _OVER;
×
2515
    }
2516
  }
2517

2518
  mInfo("vgId:%d, vgroup info after redistribute, replica:%d", newVg.vgId, newVg.replica);
36,452✔
2519
  for (int32_t i = 0; i < newVg.replica; ++i) {
120,762✔
2520
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
84,310✔
2521
  }
2522

2523
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
36,452✔
2524
  code = 0;
34,062✔
2525

2526
_OVER:
37,400✔
2527
  mndTransDrop(pTrans);
37,400✔
2528
  mndReleaseDb(pMnode, pDb);
37,400✔
2529
  TAOS_RETURN(code);
37,400✔
2530
}
2531

2532
static int32_t mndProcessRedistributeVgroupMsg(SRpcMsg *pReq) {
45,308✔
2533
  SMnode    *pMnode = pReq->info.node;
45,308✔
2534
  SDnodeObj *pNew1 = NULL;
45,308✔
2535
  SDnodeObj *pNew2 = NULL;
45,308✔
2536
  SDnodeObj *pNew3 = NULL;
45,308✔
2537
  SDnodeObj *pOld1 = NULL;
45,308✔
2538
  SDnodeObj *pOld2 = NULL;
45,308✔
2539
  SDnodeObj *pOld3 = NULL;
45,308✔
2540
  SVgObj    *pVgroup = NULL;
45,308✔
2541
  SDbObj    *pDb = NULL;
45,308✔
2542
  int32_t    code = -1;
45,308✔
2543
  int64_t    curMs = taosGetTimestampMs();
45,308✔
2544
  int32_t    newDnodeId[3] = {0};
45,308✔
2545
  int32_t    oldDnodeId[3] = {0};
45,308✔
2546
  int32_t    newIndex = -1;
45,308✔
2547
  int32_t    oldIndex = -1;
45,308✔
2548

2549
  SRedistributeVgroupReq req = {0};
45,308✔
2550
  if (tDeserializeSRedistributeVgroupReq(pReq->pCont, pReq->contLen, &req) != 0) {
45,308✔
2551
    code = TSDB_CODE_INVALID_MSG;
×
2552
    goto _OVER;
×
2553
  }
2554

2555
  mInfo("vgId:%d, start to redistribute vgroup to dnode %d:%d:%d", req.vgId, req.dnodeId1, req.dnodeId2, req.dnodeId3);
45,308✔
2556
  if ((code = mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_REDISTRIBUTE_VGROUP)) != 0) {
45,308✔
2557
    goto _OVER;
358✔
2558
  }
2559

2560
  pVgroup = mndAcquireVgroup(pMnode, req.vgId);
44,950✔
2561
  if (pVgroup == NULL) {
44,950✔
2562
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
2,127✔
2563
    if (terrno != 0) code = terrno;
2,127✔
2564
    goto _OVER;
2,127✔
2565
  }
2566
  if (pVgroup->mountVgId) {
42,823✔
2567
    code = TSDB_CODE_MND_MOUNT_OBJ_NOT_SUPPORT;
×
2568
    goto _OVER;
×
2569
  }
2570
  pDb = mndAcquireDb(pMnode, pVgroup->dbName);
42,823✔
2571
  if (pDb == NULL) {
42,823✔
2572
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2573
    if (terrno != 0) code = terrno;
×
2574
    goto _OVER;
×
2575
  }
2576

2577
  if (pVgroup->replica == 1) {
42,823✔
2578
    if (req.dnodeId1 <= 0 || req.dnodeId2 > 0 || req.dnodeId3 > 0) {
12,100✔
2579
      code = TSDB_CODE_MND_INVALID_REPLICA;
×
2580
      goto _OVER;
×
2581
    }
2582

2583
    if (req.dnodeId1 == pVgroup->vnodeGid[0].dnodeId) {
12,100✔
2584
      // terrno = TSDB_CODE_MND_VGROUP_UN_CHANGED;
2585
      code = 0;
×
2586
      goto _OVER;
×
2587
    }
2588

2589
    pNew1 = mndAcquireDnode(pMnode, req.dnodeId1);
12,100✔
2590
    if (pNew1 == NULL) {
12,100✔
2591
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2592
      if (terrno != 0) code = terrno;
×
2593
      goto _OVER;
×
2594
    }
2595
    if (!mndIsDnodeOnline(pNew1, curMs)) {
12,100✔
2596
      code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
25✔
2597
      goto _OVER;
25✔
2598
    }
2599

2600
    pOld1 = mndAcquireDnode(pMnode, pVgroup->vnodeGid[0].dnodeId);
12,075✔
2601
    if (pOld1 == NULL) {
12,075✔
2602
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2603
      if (terrno != 0) code = terrno;
×
2604
      goto _OVER;
×
2605
    }
2606
    if (!mndIsDnodeOnline(pOld1, curMs)) {
12,075✔
2607
      code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
33✔
2608
      goto _OVER;
33✔
2609
    }
2610

2611
    code = mndRedistributeVgroup(pMnode, pReq, pDb, pVgroup, pNew1, pOld1, NULL, NULL, NULL, NULL);
12,042✔
2612

2613
  } else if (pVgroup->replica == 3) {
30,723✔
2614
    if (req.dnodeId1 <= 0 || req.dnodeId2 <= 0 || req.dnodeId3 <= 0) {
29,283✔
2615
      code = TSDB_CODE_MND_INVALID_REPLICA;
2,836✔
2616
      goto _OVER;
2,836✔
2617
    }
2618

2619
    if (req.dnodeId1 == req.dnodeId2 || req.dnodeId1 == req.dnodeId3 || req.dnodeId2 == req.dnodeId3) {
26,447✔
2620
      code = TSDB_CODE_MND_INVALID_REPLICA;
709✔
2621
      goto _OVER;
709✔
2622
    }
2623

2624
    if (req.dnodeId1 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId1 != pVgroup->vnodeGid[1].dnodeId &&
25,738✔
2625
        req.dnodeId1 != pVgroup->vnodeGid[2].dnodeId) {
17,398✔
2626
      newDnodeId[++newIndex] = req.dnodeId1;
9,241✔
2627
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
9,241✔
2628
    }
2629

2630
    if (req.dnodeId2 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[1].dnodeId &&
25,738✔
2631
        req.dnodeId2 != pVgroup->vnodeGid[2].dnodeId) {
14,036✔
2632
      newDnodeId[++newIndex] = req.dnodeId2;
11,228✔
2633
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
11,228✔
2634
    }
2635

2636
    if (req.dnodeId3 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId3 != pVgroup->vnodeGid[1].dnodeId &&
25,738✔
2637
        req.dnodeId3 != pVgroup->vnodeGid[2].dnodeId) {
19,027✔
2638
      newDnodeId[++newIndex] = req.dnodeId3;
15,482✔
2639
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
15,482✔
2640
    }
2641

2642
    if (req.dnodeId1 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[0].dnodeId &&
25,738✔
2643
        req.dnodeId3 != pVgroup->vnodeGid[0].dnodeId) {
15,896✔
2644
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[0].dnodeId;
13,439✔
2645
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
13,439✔
2646
    }
2647

2648
    if (req.dnodeId1 != pVgroup->vnodeGid[1].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[1].dnodeId &&
25,738✔
2649
        req.dnodeId3 != pVgroup->vnodeGid[1].dnodeId) {
15,538✔
2650
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[1].dnodeId;
11,284✔
2651
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
11,284✔
2652
    }
2653

2654
    if (req.dnodeId1 != pVgroup->vnodeGid[2].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[2].dnodeId &&
25,738✔
2655
        req.dnodeId3 != pVgroup->vnodeGid[2].dnodeId) {
14,773✔
2656
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[2].dnodeId;
11,228✔
2657
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
11,228✔
2658
    }
2659

2660
    if (newDnodeId[0] != 0) {
25,738✔
2661
      pNew1 = mndAcquireDnode(pMnode, newDnodeId[0]);
24,671✔
2662
      if (pNew1 == NULL) {
24,671✔
2663
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2664
        if (terrno != 0) code = terrno;
×
2665
        goto _OVER;
×
2666
      }
2667
      if (!mndIsDnodeOnline(pNew1, curMs)) {
24,671✔
2668
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
709✔
2669
        goto _OVER;
709✔
2670
      }
2671
    }
2672

2673
    if (newDnodeId[1] != 0) {
25,029✔
2674
      pNew2 = mndAcquireDnode(pMnode, newDnodeId[1]);
8,364✔
2675
      if (pNew2 == NULL) {
8,364✔
2676
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2677
        if (terrno != 0) code = terrno;
×
2678
        goto _OVER;
×
2679
      }
2680
      if (!mndIsDnodeOnline(pNew2, curMs)) {
8,364✔
UNCOV
2681
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2682
        goto _OVER;
×
2683
      }
2684
    }
2685

2686
    if (newDnodeId[2] != 0) {
25,029✔
2687
      pNew3 = mndAcquireDnode(pMnode, newDnodeId[2]);
2,916✔
2688
      if (pNew3 == NULL) {
2,916✔
2689
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2690
        if (terrno != 0) code = terrno;
×
2691
        goto _OVER;
×
2692
      }
2693
      if (!mndIsDnodeOnline(pNew3, curMs)) {
2,916✔
2694
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
2695
        goto _OVER;
×
2696
      }
2697
    }
2698

2699
    if (oldDnodeId[0] != 0) {
25,029✔
2700
      pOld1 = mndAcquireDnode(pMnode, oldDnodeId[0]);
23,962✔
2701
      if (pOld1 == NULL) {
23,962✔
2702
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2703
        if (terrno != 0) code = terrno;
×
2704
        goto _OVER;
×
2705
      }
2706
      if (!mndIsDnodeOnline(pOld1, curMs)) {
23,962✔
2707
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
44✔
2708
        goto _OVER;
44✔
2709
      }
2710
    }
2711

2712
    if (oldDnodeId[1] != 0) {
24,985✔
2713
      pOld2 = mndAcquireDnode(pMnode, oldDnodeId[1]);
8,320✔
2714
      if (pOld2 == NULL) {
8,320✔
2715
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2716
        if (terrno != 0) code = terrno;
×
2717
        goto _OVER;
×
2718
      }
2719
      if (!mndIsDnodeOnline(pOld2, curMs)) {
8,320✔
2720
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
2721
        goto _OVER;
×
2722
      }
2723
    }
2724

2725
    if (oldDnodeId[2] != 0) {
24,985✔
2726
      pOld3 = mndAcquireDnode(pMnode, oldDnodeId[2]);
2,872✔
2727
      if (pOld3 == NULL) {
2,872✔
2728
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2729
        if (terrno != 0) code = terrno;
×
2730
        goto _OVER;
×
2731
      }
2732
      if (!mndIsDnodeOnline(pOld3, curMs)) {
2,872✔
2733
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
2734
        goto _OVER;
×
2735
      }
2736
    }
2737

2738
    if (pNew1 == NULL && pOld1 == NULL && pNew2 == NULL && pOld2 == NULL && pNew3 == NULL && pOld3 == NULL) {
24,985✔
2739
      // terrno = TSDB_CODE_MND_VGROUP_UN_CHANGED;
2740
      code = 0;
1,067✔
2741
      goto _OVER;
1,067✔
2742
    }
2743

2744
    code = mndRedistributeVgroup(pMnode, pReq, pDb, pVgroup, pNew1, pOld1, pNew2, pOld2, pNew3, pOld3);
23,918✔
2745

2746
  } else if (pVgroup->replica == 2) {
1,440✔
2747
    if (req.dnodeId1 <= 0 || req.dnodeId2 <= 0) {
1,440✔
2748
      code = TSDB_CODE_MND_INVALID_REPLICA;
×
2749
      goto _OVER;
×
2750
    }
2751

2752
    if (req.dnodeId1 == req.dnodeId2) {
1,440✔
2753
      code = TSDB_CODE_MND_INVALID_REPLICA;
×
2754
      goto _OVER;
×
2755
    }
2756

2757
    if (req.dnodeId1 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId1 != pVgroup->vnodeGid[1].dnodeId) {
1,440✔
2758
      newDnodeId[++newIndex] = req.dnodeId1;
1,440✔
2759
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
1,440✔
2760
    }
2761

2762
    if (req.dnodeId2 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[1].dnodeId) {
1,440✔
2763
      newDnodeId[++newIndex] = req.dnodeId2;
1,440✔
2764
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
1,440✔
2765
    }
2766

2767
    if (req.dnodeId1 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[0].dnodeId) {
1,440✔
2768
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[0].dnodeId;
1,440✔
2769
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
1,440✔
2770
    }
2771

2772
    if (req.dnodeId1 != pVgroup->vnodeGid[1].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[1].dnodeId) {
1,440✔
2773
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[1].dnodeId;
1,440✔
2774
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
1,440✔
2775
    }
2776

2777
    if (newDnodeId[0] != 0) {
1,440✔
2778
      pNew1 = mndAcquireDnode(pMnode, newDnodeId[0]);
1,440✔
2779
      if (pNew1 == NULL) {
1,440✔
2780
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2781
        if (terrno != 0) code = terrno;
×
2782
        goto _OVER;
×
2783
      }
2784
      if (!mndIsDnodeOnline(pNew1, curMs)) {
1,440✔
2785
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
2786
        goto _OVER;
×
2787
      }
2788
    }
2789

2790
    if (newDnodeId[1] != 0) {
1,440✔
2791
      pNew2 = mndAcquireDnode(pMnode, newDnodeId[1]);
1,440✔
2792
      if (pNew2 == NULL) {
1,440✔
2793
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2794
        if (terrno != 0) code = terrno;
×
2795
        goto _OVER;
×
2796
      }
2797
      if (!mndIsDnodeOnline(pNew2, curMs)) {
1,440✔
2798
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
2799
        goto _OVER;
×
2800
      }
2801
    }
2802

2803
    if (oldDnodeId[0] != 0) {
1,440✔
2804
      pOld1 = mndAcquireDnode(pMnode, oldDnodeId[0]);
1,440✔
2805
      if (pOld1 == NULL) {
1,440✔
2806
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2807
        if (terrno != 0) code = terrno;
×
2808
        goto _OVER;
×
2809
      }
2810
      if (!mndIsDnodeOnline(pOld1, curMs)) {
1,440✔
2811
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
2812
        goto _OVER;
×
2813
      }
2814
    }
2815

2816
    if (oldDnodeId[1] != 0) {
1,440✔
2817
      pOld2 = mndAcquireDnode(pMnode, oldDnodeId[1]);
1,440✔
2818
      if (pOld2 == NULL) {
1,440✔
2819
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2820
        if (terrno != 0) code = terrno;
×
2821
        goto _OVER;
×
2822
      }
2823
      if (!mndIsDnodeOnline(pOld2, curMs)) {
1,440✔
2824
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
2825
        goto _OVER;
×
2826
      }
2827
    }
2828

2829
    if (pNew1 == NULL && pOld1 == NULL && pNew2 == NULL && pOld2 == NULL) {
1,440✔
2830
      // terrno = TSDB_CODE_MND_VGROUP_UN_CHANGED;
2831
      code = 0;
×
2832
      goto _OVER;
×
2833
    }
2834

2835
    code = mndRedistributeVgroup(pMnode, pReq, pDb, pVgroup, pNew1, pOld1, pNew2, pOld2, NULL, NULL);
1,440✔
2836
  } else {
2837
    code = TSDB_CODE_MND_REQ_REJECTED;
×
2838
    goto _OVER;
×
2839
  }
2840

2841
  if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
37,400✔
2842

2843
  char obj[33] = {0};
37,400✔
2844
  (void)tsnprintf(obj, sizeof(obj), "%d", req.vgId);
37,400✔
2845

2846
  auditRecord(pReq, pMnode->clusterId, "RedistributeVgroup", "", obj, req.sql, req.sqlLen);
37,400✔
2847

2848
_OVER:
45,308✔
2849
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
45,308✔
2850
    mError("vgId:%d, failed to redistribute to dnode %d:%d:%d since %s", req.vgId, req.dnodeId1, req.dnodeId2,
10,179✔
2851
           req.dnodeId3, tstrerror(code));
2852
  }
2853

2854
  mndReleaseDnode(pMnode, pNew1);
45,308✔
2855
  mndReleaseDnode(pMnode, pNew2);
45,308✔
2856
  mndReleaseDnode(pMnode, pNew3);
45,308✔
2857
  mndReleaseDnode(pMnode, pOld1);
45,308✔
2858
  mndReleaseDnode(pMnode, pOld2);
45,308✔
2859
  mndReleaseDnode(pMnode, pOld3);
45,308✔
2860
  mndReleaseVgroup(pMnode, pVgroup);
45,308✔
2861
  mndReleaseDb(pMnode, pDb);
45,308✔
2862
  tFreeSRedistributeVgroupReq(&req);
45,308✔
2863

2864
  TAOS_RETURN(code);
45,308✔
2865
}
2866

2867
static void *mndBuildSForceBecomeFollowerReq(SMnode *pMnode, SVgObj *pVgroup, int32_t dnodeId, int32_t *pContLen) {
6,478✔
2868
  SForceBecomeFollowerReq balanceReq = {
6,478✔
2869
      .vgId = pVgroup->vgId,
6,478✔
2870
  };
2871

2872
  int32_t contLen = tSerializeSForceBecomeFollowerReq(NULL, 0, &balanceReq);
6,478✔
2873
  if (contLen < 0) {
6,478✔
2874
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
2875
    return NULL;
×
2876
  }
2877
  contLen += sizeof(SMsgHead);
6,478✔
2878

2879
  void *pReq = taosMemoryMalloc(contLen);
6,478✔
2880
  if (pReq == NULL) {
6,478✔
2881
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
2882
    return NULL;
×
2883
  }
2884

2885
  SMsgHead *pHead = pReq;
6,478✔
2886
  pHead->contLen = htonl(contLen);
6,478✔
2887
  pHead->vgId = htonl(pVgroup->vgId);
6,478✔
2888

2889
  if (tSerializeSForceBecomeFollowerReq((char *)pReq + sizeof(SMsgHead), contLen, &balanceReq) < 0) {
6,478✔
2890
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
2891
    taosMemoryFree(pReq);
×
2892
    return NULL;
×
2893
  }
2894
  *pContLen = contLen;
6,478✔
2895
  return pReq;
6,478✔
2896
}
2897

2898
int32_t mndAddBalanceVgroupLeaderAction(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup, int32_t dnodeId) {
6,478✔
2899
  int32_t    code = 0;
6,478✔
2900
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
6,478✔
2901
  if (pDnode == NULL) {
6,478✔
2902
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2903
    if (terrno != 0) code = terrno;
×
2904
    TAOS_RETURN(code);
×
2905
  }
2906

2907
  STransAction action = {0};
6,478✔
2908
  action.epSet = mndGetDnodeEpset(pDnode);
6,478✔
2909
  mndReleaseDnode(pMnode, pDnode);
6,478✔
2910

2911
  int32_t contLen = 0;
6,478✔
2912
  void   *pReq = mndBuildSForceBecomeFollowerReq(pMnode, pVgroup, dnodeId, &contLen);
6,478✔
2913
  if (pReq == NULL) {
6,478✔
2914
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2915
    if (terrno != 0) code = terrno;
×
2916
    TAOS_RETURN(code);
×
2917
  }
2918

2919
  action.pCont = pReq;
6,478✔
2920
  action.contLen = contLen;
6,478✔
2921
  action.msgType = TDMT_SYNC_FORCE_FOLLOWER;
6,478✔
2922

2923
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
6,478✔
2924
    taosMemoryFree(pReq);
×
2925
    TAOS_RETURN(code);
×
2926
  }
2927

2928
  TAOS_RETURN(code);
6,478✔
2929
}
2930

2931
static void *mndBuildAlterVnodeElectBaselineReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId,
38,868✔
2932
                                          int32_t *pContLen, int32_t ms) {
2933
  SAlterVnodeElectBaselineReq alterReq = {
38,868✔
2934
      .vgId = pVgroup->vgId,
38,868✔
2935
      .electBaseLine = ms,
2936
  };
2937

2938
  int32_t contLen = tSerializeSAlterVnodeReplicaReq(NULL, 0, &alterReq);
38,868✔
2939
  if (contLen < 0) {
38,868✔
2940
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
2941
    return NULL;
×
2942
  }
2943

2944
  void *pReq = taosMemoryMalloc(contLen);
38,868✔
2945
  if (pReq == NULL) {
38,868✔
2946
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
2947
    return NULL;
×
2948
  }
2949

2950
  if (tSerializeSAlterVnodeReplicaReq(pReq, contLen, &alterReq) < 0) {
38,868✔
2951
    mError("vgId:%d, failed to serialize alter vnode req,since %s", alterReq.vgId, terrstr());
×
2952
    taosMemoryFree(pReq);
×
2953
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
2954
    return NULL;
×
2955
  }
2956
  *pContLen = contLen;
38,868✔
2957
  return pReq;
38,868✔
2958
}
2959

2960
static int32_t mndAddAlterVnodeElectionBaselineActionToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId, int32_t ms) {
38,868✔
2961
  int32_t    code = 0;
38,868✔
2962
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
38,868✔
2963
  if (pDnode == NULL) {
38,868✔
2964
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2965
    if (terrno != 0) code = terrno;
×
2966
    TAOS_RETURN(code);
×
2967
  }
2968

2969
  STransAction action = {0};
38,868✔
2970
  action.epSet = mndGetDnodeEpset(pDnode);
38,868✔
2971
  mndReleaseDnode(pMnode, pDnode);
38,868✔
2972

2973
  int32_t contLen = 0;
38,868✔
2974
  void   *pReq = mndBuildAlterVnodeElectBaselineReq(pMnode, pDb, pVgroup, dnodeId, &contLen, ms);
38,868✔
2975
  if (pReq == NULL) {
38,868✔
2976
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2977
    if (terrno != 0) code = terrno;
×
2978
    TAOS_RETURN(code);
×
2979
  }
2980

2981
  action.pCont = pReq;
38,868✔
2982
  action.contLen = contLen;
38,868✔
2983
  action.msgType = TDMT_VND_ALTER_ELECTBASELINE;
38,868✔
2984
  action.groupId = pVgroup->vgId;
38,868✔
2985

2986
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
38,868✔
2987
    taosMemoryFree(pReq);
×
2988
    TAOS_RETURN(code);
×
2989
  }
2990

2991
  TAOS_RETURN(code);
38,868✔
2992
}
2993

2994
static int32_t mndAddAlterVgroupElectionBaselineActionToTrans(SMnode *pMnode, SVgObj *pVgroup, STrans *pTrans, int32_t index){
12,956✔
2995
  int32_t code = 0;
12,956✔
2996
  SSdb   *pSdb = pMnode->pSdb;
12,956✔
2997

2998
  int32_t vgid = pVgroup->vgId;
12,956✔
2999
  int8_t  replica = pVgroup->replica;
12,956✔
3000

3001
  if (pVgroup->replica <= 1) {
12,956✔
3002
    mInfo("trans:%d, vgid:%d no need to balance, replica:%d", pTrans->id, vgid, replica);
×
3003
    return -1;
×
3004
  }
3005

3006
  for(int32_t i = 0; i < 3; i++){
51,824✔
3007
    if(i == index%3){
38,868✔
3008
    TAOS_CHECK_RETURN(
6,478✔
3009
        mndAddAlterVnodeElectionBaselineActionToTrans(pMnode, pTrans, NULL, pVgroup, pVgroup->vnodeGid[i].dnodeId, 1500));
3010
    }
3011
    else{
3012
    TAOS_CHECK_RETURN(
32,390✔
3013
        mndAddAlterVnodeElectionBaselineActionToTrans(pMnode, pTrans, NULL, pVgroup, pVgroup->vnodeGid[i].dnodeId, 5000));
3014
    }
3015
  }
3016
  return code; 
12,956✔
3017
}
3018

3019
int32_t mndAddVgroupBalanceToTrans(SMnode *pMnode, SVgObj *pVgroup, STrans *pTrans, int32_t index) {
6,964✔
3020
  int32_t code = 0;
6,964✔
3021
  SSdb   *pSdb = pMnode->pSdb;
6,964✔
3022

3023
  int32_t vgid = pVgroup->vgId;
6,964✔
3024
  int8_t  replica = pVgroup->replica;
6,964✔
3025

3026
  if (pVgroup->replica <= 1) {
6,964✔
3027
    mInfo("trans:%d, vgid:%d no need to balance, replica:%d", pTrans->id, vgid, replica);
19✔
3028
    return -1;
19✔
3029
  }
3030

3031
  int32_t dnodeId = 0;
6,945✔
3032

3033
  for (int i = 0; i < replica; i++) {
14,734✔
3034
    if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_LEADER) {
14,267✔
3035
      dnodeId = pVgroup->vnodeGid[i].dnodeId;
6,478✔
3036
      break;
6,478✔
3037
    }
3038
  }
3039

3040
  bool       exist = false;
6,945✔
3041
  bool       online = false;
6,945✔
3042
  int64_t    curMs = taosGetTimestampMs();
6,945✔
3043
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
6,945✔
3044
  if (pDnode != NULL) {
6,945✔
3045
    exist = true;
6,478✔
3046
    online = mndIsDnodeOnline(pDnode, curMs);
6,478✔
3047
    mndReleaseDnode(pMnode, pDnode);
6,478✔
3048
  }
3049

3050
  if (exist && online) {
13,423✔
3051
    mInfo("trans:%d, vgid:%d leader to dnode:%d", pTrans->id, vgid, dnodeId);
6,478✔
3052
    
3053
    TAOS_CHECK_RETURN(mndAddAlterVgroupElectionBaselineActionToTrans(pMnode, pVgroup, pTrans, index));
6,478✔
3054

3055
    if ((code = mndAddBalanceVgroupLeaderAction(pMnode, pTrans, pVgroup, dnodeId)) != 0) {
6,478✔
3056
      mError("trans:%d, vgid:%d failed to be balanced to dnode:%d", pTrans->id, vgid, dnodeId);
×
3057
      TAOS_RETURN(code);
×
3058
    }
3059

3060
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, NULL, pVgroup));
6,478✔
3061

3062
    TAOS_CHECK_RETURN(mndAddAlterVgroupElectionBaselineActionToTrans(pMnode, pVgroup, pTrans, -1));
6,478✔
3063

3064
    SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName);
6,478✔
3065
    if (pDb == NULL) {
6,478✔
3066
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3067
      if (terrno != 0) code = terrno;
×
3068
      mError("trans:%d, vgid:%d failed to be balanced to dnode:%d, because db not exist", pTrans->id, vgid, dnodeId);
×
3069
      TAOS_RETURN(code);
×
3070
    }
3071

3072
    mndReleaseDb(pMnode, pDb);
6,478✔
3073
  } else {
3074
    mInfo("trans:%d, vgid:%d cant be balanced to dnode:%d, exist:%d, online:%d", pTrans->id, vgid, dnodeId, exist,
467✔
3075
          online);
3076
  }
3077

3078
  TAOS_RETURN(code);
6,945✔
3079
}
3080

3081
extern int32_t mndProcessVgroupBalanceLeaderMsgImp(SRpcMsg *pReq);
3082

3083
int32_t mndProcessVgroupBalanceLeaderMsg(SRpcMsg *pReq) { return mndProcessVgroupBalanceLeaderMsgImp(pReq); }
2,512✔
3084

3085
#ifndef TD_ENTERPRISE
3086
int32_t mndProcessVgroupBalanceLeaderMsgImp(SRpcMsg *pReq) { return 0; }
3087
#endif
3088

3089
static int32_t mndCheckDnodeMemory(SMnode *pMnode, SDbObj *pOldDb, SDbObj *pNewDb, SVgObj *pOldVgroup,
205,568✔
3090
                                   SVgObj *pNewVgroup, SArray *pArray) {
3091
  for (int32_t i = 0; i < (int32_t)taosArrayGetSize(pArray); ++i) {
595,100✔
3092
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
389,532✔
3093
    bool       inVgroup = false;
389,532✔
3094
    int64_t    oldMemUsed = 0;
389,532✔
3095
    int64_t    newMemUsed = 0;
389,532✔
3096
    mDebug("db:%s, vgId:%d, check dnode:%d, avail:%" PRId64 " used:%" PRId64, pNewVgroup->dbName, pNewVgroup->vgId,
389,532✔
3097
           pDnode->id, pDnode->memAvail, pDnode->memUsed);
3098
    for (int32_t j = 0; j < pOldVgroup->replica; ++j) {
1,083,204✔
3099
      SVnodeGid *pVgId = &pOldVgroup->vnodeGid[j];
693,672✔
3100
      if (pDnode->id == pVgId->dnodeId) {
693,672✔
3101
        oldMemUsed = mndGetVgroupMemory(pMnode, pOldDb, pOldVgroup);
306,948✔
3102
        inVgroup = true;
306,948✔
3103
      }
3104
    }
3105
    for (int32_t j = 0; j < pNewVgroup->replica; ++j) {
1,083,204✔
3106
      SVnodeGid *pVgId = &pNewVgroup->vnodeGid[j];
693,672✔
3107
      if (pDnode->id == pVgId->dnodeId) {
693,672✔
3108
        newMemUsed = mndGetVgroupMemory(pMnode, pNewDb, pNewVgroup);
306,948✔
3109
        inVgroup = true;
306,948✔
3110
      }
3111
    }
3112

3113
    mDebug("db:%s, vgId:%d, memory in dnode:%d, oldUsed:%" PRId64 ", newUsed:%" PRId64, pNewVgroup->dbName,
389,532✔
3114
           pNewVgroup->vgId, pDnode->id, oldMemUsed, newMemUsed);
3115

3116
    pDnode->memUsed = pDnode->memUsed - oldMemUsed + newMemUsed;
389,532✔
3117
    if (pDnode->memAvail - pDnode->memUsed <= 0) {
389,532✔
3118
      mError("db:%s, vgId:%d, no enough memory in dnode:%d, avail:%" PRId64 " used:%" PRId64, pNewVgroup->dbName,
×
3119
             pNewVgroup->vgId, pDnode->id, pDnode->memAvail, pDnode->memUsed);
3120
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE);
×
3121
    } else if (inVgroup) {
389,532✔
3122
      mInfo("db:%s, vgId:%d, memory in dnode:%d, avail:%" PRId64 " used:%" PRId64, pNewVgroup->dbName, pNewVgroup->vgId,
306,948✔
3123
            pDnode->id, pDnode->memAvail, pDnode->memUsed);
3124
    } else {
3125
    }
3126
  }
3127
  return 0;
205,568✔
3128
}
3129

3130
int32_t mndBuildAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pOldDb, SDbObj *pNewDb, SVgObj *pVgroup,
241,366✔
3131
                                  SArray *pArray, SVgObj *pNewVgroup) {
3132
  int32_t code = 0;
241,366✔
3133
  memcpy(pNewVgroup, pVgroup, sizeof(SVgObj));
241,366✔
3134

3135
  if (pVgroup->replica <= 0 || pVgroup->replica == pNewDb->cfg.replications) {
241,366✔
3136
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfigAction(pMnode, pTrans, pNewDb, pVgroup));
205,568✔
3137
    TAOS_CHECK_RETURN(mndCheckDnodeMemory(pMnode, pOldDb, pNewDb, pNewVgroup, pVgroup, pArray));
205,568✔
3138
    return 0;
205,568✔
3139
  }
3140

3141
  // mndTransSetGroupParallel(pTrans);
3142

3143
  if (pNewDb->cfg.replications == 3) {
35,798✔
3144
    mInfo("trans:%d, db:%s, vgId:%d, will add 2 vnodes, vn:0 dnode:%d", pTrans->id, pVgroup->dbName, pVgroup->vgId,
29,469✔
3145
          pVgroup->vnodeGid[0].dnodeId);
3146

3147
    // add second
3148
    if (pNewVgroup->replica == 1) {
29,469✔
3149
      TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, pNewVgroup, pArray));
29,469✔
3150
    }
3151

3152
    // learner stage
3153
    pNewVgroup->vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
28,758✔
3154
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
28,758✔
3155
    TAOS_CHECK_RETURN(
28,758✔
3156
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3157

3158
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &pNewVgroup->vnodeGid[1]));
28,758✔
3159

3160
    // follower stage
3161
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
28,758✔
3162
    TAOS_CHECK_RETURN(mndAddAlterVnodeTypeAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
28,758✔
3163
    TAOS_CHECK_RETURN(
28,758✔
3164
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3165

3166
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
28,758✔
3167

3168
    // add third
3169
    if (pNewVgroup->replica == 2) {
28,758✔
3170
      TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, pNewVgroup, pArray));
28,758✔
3171
    }
3172

3173
    pNewVgroup->vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
28,549✔
3174
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
28,549✔
3175
    pNewVgroup->vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_VOTER;
28,549✔
3176
    TAOS_CHECK_RETURN(
28,549✔
3177
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3178
    TAOS_CHECK_RETURN(
28,549✔
3179
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
3180
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &pNewVgroup->vnodeGid[2]));
28,549✔
3181

3182
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
28,549✔
3183
  } else if (pNewDb->cfg.replications == 1) {
6,329✔
3184
    mInfo("trans:%d, db:%s, vgId:%d, will remove 2 vnodes, vn:0 dnode:%d vn:1 dnode:%d vn:2 dnode:%d", pTrans->id,
4,877✔
3185
          pVgroup->dbName, pVgroup->vgId, pVgroup->vnodeGid[0].dnodeId, pVgroup->vnodeGid[1].dnodeId,
3186
          pVgroup->vnodeGid[2].dnodeId);
3187

3188
    SVnodeGid del1 = {0};
4,877✔
3189
    SVnodeGid del2 = {0};
4,877✔
3190
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroup(pMnode, pTrans, pNewVgroup, pArray, &del1));
4,877✔
3191
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &del1, true));
4,877✔
3192
    TAOS_CHECK_RETURN(
4,877✔
3193
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3194
    TAOS_CHECK_RETURN(
4,877✔
3195
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
3196
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
4,877✔
3197

3198
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroup(pMnode, pTrans, pNewVgroup, pArray, &del2));
4,877✔
3199
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &del2, true));
4,877✔
3200
    TAOS_CHECK_RETURN(
4,877✔
3201
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3202
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
4,877✔
3203
  } else if (pNewDb->cfg.replications == 2) {
1,452✔
3204
    mInfo("trans:%d, db:%s, vgId:%d, will add 1 vnode, vn:0 dnode:%d", pTrans->id, pVgroup->dbName, pVgroup->vgId,
1,452✔
3205
          pVgroup->vnodeGid[0].dnodeId);
3206

3207
    // add second
3208
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, pNewVgroup, pArray));
1,452✔
3209

3210
    // learner stage
3211
    pNewVgroup->vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
1,452✔
3212
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
1,452✔
3213
    TAOS_CHECK_RETURN(
1,452✔
3214
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3215

3216
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &pNewVgroup->vnodeGid[1]));
1,452✔
3217

3218
    // follower stage
3219
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
1,452✔
3220
    TAOS_CHECK_RETURN(mndAddAlterVnodeTypeAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
1,452✔
3221
    TAOS_CHECK_RETURN(
1,452✔
3222
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3223

3224
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
1,452✔
3225
  } else {
3226
    return -1;
×
3227
  }
3228

3229
  mndSortVnodeGid(pNewVgroup);
34,878✔
3230

3231
  {
3232
    SSdbRaw *pVgRaw = mndVgroupActionEncode(pNewVgroup);
34,878✔
3233
    if (pVgRaw == NULL) {
34,878✔
3234
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3235
      if (terrno != 0) code = terrno;
×
3236
      TAOS_RETURN(code);
×
3237
    }
3238
    if ((code = mndTransAppendCommitlog(pTrans, pVgRaw)) != 0) {
34,878✔
3239
      sdbFreeRaw(pVgRaw);
×
3240
      TAOS_RETURN(code);
×
3241
    }
3242
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
34,878✔
3243
    if (code != 0) {
34,878✔
3244
      mError("vgId:%d, failed to set raw status since %s at line:%d", pNewVgroup->vgId, tstrerror(code), __LINE__);
×
3245
      TAOS_RETURN(code);
×
3246
    }
3247
  }
3248

3249
  TAOS_RETURN(code);
34,878✔
3250
}
3251

3252
int32_t mndBuildRaftAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pOldDb, SDbObj *pNewDb, SVgObj *pVgroup,
×
3253
                                      SArray *pArray) {
3254
  int32_t code = 0;
×
3255
  SVgObj  newVgroup = {0};
×
3256
  memcpy(&newVgroup, pVgroup, sizeof(SVgObj));
×
3257

3258
  if (pVgroup->replica <= 0 || pVgroup->replica == pNewDb->cfg.replications) {
×
3259
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfigAction(pMnode, pTrans, pNewDb, pVgroup));
×
3260
    TAOS_CHECK_RETURN(mndCheckDnodeMemory(pMnode, pOldDb, pNewDb, &newVgroup, pVgroup, pArray));
×
3261
    return 0;
×
3262
  }
3263

3264
  mndTransSetSerial(pTrans);
×
3265

3266
  mInfo("trans:%d, vgId:%d, alter vgroup, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id, pVgroup->vgId,
×
3267
        pVgroup->syncConfChangeVer, pVgroup->version, pVgroup->replica);
3268

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

3273
    // add second
3274
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVgroup, pArray));
×
3275
    // add third
3276
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVgroup, pArray));
×
3277

3278
    // add learner stage
3279
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3280
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3281
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3282
    TAOS_CHECK_RETURN(
×
3283
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3284
    mInfo("trans:%d, vgId:%d, add change config, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id,
×
3285
          pVgroup->vgId, newVgroup.syncConfChangeVer, pVgroup->version, pVgroup->replica);
3286
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &newVgroup.vnodeGid[1]));
×
3287
    mInfo("trans:%d, vgId:%d, create vnode, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id, pVgroup->vgId,
×
3288
          newVgroup.syncConfChangeVer, pVgroup->version, pVgroup->replica);
3289
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &newVgroup.vnodeGid[2]));
×
3290
    mInfo("trans:%d, vgId:%d, create vnode, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id, pVgroup->vgId,
×
3291
          newVgroup.syncConfChangeVer, pVgroup->version, pVgroup->replica);
3292

3293
    // check learner
3294
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3295
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3296
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3297
    TAOS_CHECK_RETURN(
×
3298
        mndAddCheckLearnerCatchupAction(pMnode, pTrans, pNewDb, &newVgroup, newVgroup.vnodeGid[1].dnodeId));
3299
    TAOS_CHECK_RETURN(
×
3300
        mndAddCheckLearnerCatchupAction(pMnode, pTrans, pNewDb, &newVgroup, newVgroup.vnodeGid[2].dnodeId));
3301

3302
    // change raft type
3303
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3304
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3305
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3306
    TAOS_CHECK_RETURN(
×
3307
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3308

3309
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
3310

3311
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3312
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3313
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3314
    TAOS_CHECK_RETURN(
×
3315
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3316

3317
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
3318

3319
    SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
×
3320
    if (pVgRaw == NULL) {
×
3321
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3322
      if (terrno != 0) code = terrno;
×
3323
      TAOS_RETURN(code);
×
3324
    }
3325
    if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
×
3326
      sdbFreeRaw(pVgRaw);
×
3327
      TAOS_RETURN(code);
×
3328
    }
3329
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
3330
    if (code != 0) {
×
3331
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
3332
             __LINE__);
3333
      TAOS_RETURN(code);
×
3334
    }
3335
  } else if (newVgroup.replica == 3 && pNewDb->cfg.replications == 1) {
×
3336
    mInfo("db:%s, vgId:%d, will remove 2 vnodes, vn:0 dnode:%d vn:1 dnode:%d vn:2 dnode:%d", pVgroup->dbName,
×
3337
          pVgroup->vgId, pVgroup->vnodeGid[0].dnodeId, pVgroup->vnodeGid[1].dnodeId, pVgroup->vnodeGid[2].dnodeId);
3338

3339
    SVnodeGid del1 = {0};
×
3340
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroupWithoutSave(pMnode, pTrans, &newVgroup, pArray, &del1));
×
3341

3342
    TAOS_CHECK_RETURN(
×
3343
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3344

3345
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
3346

3347
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &del1, true));
×
3348

3349
    SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
×
3350
    if (pVgRaw == NULL) {
×
3351
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3352
      if (terrno != 0) code = terrno;
×
3353
      TAOS_RETURN(code);
×
3354
    }
3355
    if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
×
3356
      sdbFreeRaw(pVgRaw);
×
3357
      TAOS_RETURN(code);
×
3358
    }
3359
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
3360
    if (code != 0) {
×
3361
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
3362
             __LINE__);
3363
      TAOS_RETURN(code);
×
3364
    }
3365

3366
    SVnodeGid del2 = {0};
×
3367
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroupWithoutSave(pMnode, pTrans, &newVgroup, pArray, &del2));
×
3368

3369
    TAOS_CHECK_RETURN(
×
3370
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3371

3372
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
3373

3374
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &del2, true));
×
3375

3376
    pVgRaw = mndVgroupActionEncode(&newVgroup);
×
3377
    if (pVgRaw == NULL) {
×
3378
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3379
      if (terrno != 0) code = terrno;
×
3380
      TAOS_RETURN(code);
×
3381
    }
3382
    if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
×
3383
      sdbFreeRaw(pVgRaw);
×
3384
      TAOS_RETURN(code);
×
3385
    }
3386
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
3387
    if (code != 0) {
×
3388
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
3389
             __LINE__);
3390
      TAOS_RETURN(code);
×
3391
    }
3392
  } else {
3393
    return -1;
×
3394
  }
3395

3396
  mndSortVnodeGid(&newVgroup);
×
3397

3398
  {
3399
    SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
×
3400
    if (pVgRaw == NULL) {
×
3401
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3402
      if (terrno != 0) code = terrno;
×
3403
      TAOS_RETURN(code);
×
3404
    }
3405
    if ((code = mndTransAppendCommitlog(pTrans, pVgRaw)) != 0) {
×
3406
      sdbFreeRaw(pVgRaw);
×
3407
      TAOS_RETURN(code);
×
3408
    }
3409
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
3410
    if (code != 0) {
×
3411
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
3412
             __LINE__);
3413
      TAOS_RETURN(code);
×
3414
    }
3415
  }
3416

3417
  TAOS_RETURN(code);
×
3418
}
3419

3420
int32_t mndBuildRestoreAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *db, SVgObj *pVgroup, SDnodeObj *pDnode,
6,280✔
3421
                                         SDnodeObj *pAnotherDnode) {
3422
  int32_t code = 0;
6,280✔
3423
  SVgObj  newVgroup = {0};
6,280✔
3424
  memcpy(&newVgroup, pVgroup, sizeof(SVgObj));
6,280✔
3425

3426
  mInfo("trans:%d, db:%s, vgId:%d, restore vnodes, vn:0 dnode:%d", pTrans->id, pVgroup->dbName, pVgroup->vgId,
6,280✔
3427
        pVgroup->vnodeGid[0].dnodeId);
3428

3429
  if (newVgroup.replica == 1) {
6,280✔
3430
    int selected = 0;
×
3431
    for (int i = 0; i < newVgroup.replica; i++) {
×
3432
      newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3433
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
3434
        selected = i;
×
3435
      }
3436
    }
3437
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, db, &newVgroup, &newVgroup.vnodeGid[selected]));
×
3438
  } else if (newVgroup.replica == 2) {
6,280✔
3439
    for (int i = 0; i < newVgroup.replica; i++) {
×
3440
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
3441
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3442
      } else {
3443
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3444
      }
3445
    }
3446
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pAnotherDnode));
×
3447

3448
    for (int i = 0; i < newVgroup.replica; i++) {
×
3449
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
3450
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3451
      } else {
3452
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3453
      }
3454
    }
3455
    TAOS_CHECK_RETURN(mndRestoreAddCreateVnodeAction(pMnode, pTrans, db, &newVgroup, pDnode));
×
3456

3457
    for (int i = 0; i < newVgroup.replica; i++) {
×
3458
      newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3459
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
3460
      }
3461
    }
3462
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pDnode));
×
3463
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pAnotherDnode));
×
3464
  } else if (newVgroup.replica == 3) {
6,280✔
3465
    for (int i = 0; i < newVgroup.replica; i++) {
25,120✔
3466
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
18,840✔
3467
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_LEARNER;
6,280✔
3468
      } else {
3469
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
12,560✔
3470
      }
3471
    }
3472
    TAOS_CHECK_RETURN(mndRestoreAddCreateVnodeAction(pMnode, pTrans, db, &newVgroup, pDnode));
6,280✔
3473

3474
    for (int i = 0; i < newVgroup.replica; i++) {
25,120✔
3475
      newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
18,840✔
3476
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
18,840✔
3477
      }
3478
    }
3479
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pDnode));
6,280✔
3480
  }
3481
  SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
6,280✔
3482
  if (pVgRaw == NULL) {
6,280✔
3483
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3484
    if (terrno != 0) code = terrno;
×
3485
    TAOS_RETURN(code);
×
3486
  }
3487
  if ((code = mndTransAppendCommitlog(pTrans, pVgRaw)) != 0) {
6,280✔
3488
    sdbFreeRaw(pVgRaw);
×
3489
    TAOS_RETURN(code);
×
3490
  }
3491
  code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
6,280✔
3492
  if (code != 0) {
6,280✔
3493
    mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code), __LINE__);
×
3494
    TAOS_RETURN(code);
×
3495
  }
3496

3497
  TAOS_RETURN(code);
6,280✔
3498
}
3499

3500
static int32_t mndAddAdjustVnodeHashRangeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) {
×
3501
  return 0;
×
3502
}
3503

3504
typedef int32_t (*FpTransActionCb)(STrans *pTrans, SSdbRaw *pRaw);
3505

3506
static int32_t mndAddVgStatusAction(STrans *pTrans, SVgObj *pVg, ESdbStatus vgStatus, ETrnStage stage) {
59,063✔
3507
  int32_t         code = 0;
59,063✔
3508
  FpTransActionCb appendActionCb = (stage == TRN_STAGE_COMMIT_ACTION) ? mndTransAppendCommitlog : mndTransAppendRedolog;
59,063✔
3509
  SSdbRaw        *pRaw = mndVgroupActionEncode(pVg);
59,063✔
3510
  if (pRaw == NULL) {
59,063✔
3511
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3512
    if (terrno != 0) code = terrno;
×
3513
    goto _err;
×
3514
  }
3515
  if ((code = appendActionCb(pTrans, pRaw)) != 0) goto _err;
59,063✔
3516
  code = sdbSetRawStatus(pRaw, vgStatus);
59,063✔
3517
  if (code != 0) {
59,063✔
3518
    mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", pVg->vgId, tstrerror(code), __LINE__);
×
3519
    goto _err;
×
3520
  }
3521
  pRaw = NULL;
59,063✔
3522
  TAOS_RETURN(code);
59,063✔
3523
_err:
×
3524
  sdbFreeRaw(pRaw);
×
3525
  TAOS_RETURN(code);
×
3526
}
3527

3528
static int32_t mndAddDbStatusAction(STrans *pTrans, SDbObj *pDb, ESdbStatus dbStatus, ETrnStage stage) {
23,471✔
3529
  int32_t         code = 0;
23,471✔
3530
  FpTransActionCb appendActionCb = (stage == TRN_STAGE_COMMIT_ACTION) ? mndTransAppendCommitlog : mndTransAppendRedolog;
23,471✔
3531
  SSdbRaw        *pRaw = mndDbActionEncode(pDb);
23,471✔
3532
  if (pRaw == NULL) {
23,471✔
3533
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3534
    if (terrno != 0) code = terrno;
×
3535
    goto _err;
×
3536
  }
3537
  if ((code = appendActionCb(pTrans, pRaw)) != 0) goto _err;
23,471✔
3538
  code = sdbSetRawStatus(pRaw, dbStatus);
23,471✔
3539
  if (code != 0) {
23,471✔
3540
    mError("db:%s, failed to set raw status to ready, error:%s, line:%d", pDb->name, tstrerror(code), __LINE__);
×
3541
    goto _err;
×
3542
  }
3543
  pRaw = NULL;
23,471✔
3544
  TAOS_RETURN(code);
23,471✔
3545
_err:
×
3546
  sdbFreeRaw(pRaw);
×
3547
  TAOS_RETURN(code);
×
3548
}
3549

3550
int32_t mndSplitVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SVgObj *pVgroup) {
12,103✔
3551
  int32_t code = -1;
12,103✔
3552
  STrans *pTrans = NULL;
12,103✔
3553
  SDbObj  dbObj = {0};
12,103✔
3554
  SArray *pArray = mndBuildDnodesArray(pMnode, 0, NULL);
12,103✔
3555

3556
#if defined(USE_SHARED_STORAGE)
3557
  if (tsSsEnabled) {
12,103✔
3558
    code = TSDB_CODE_OPS_NOT_SUPPORT;
×
3559
    mError("vgId:%d, db:%s, shared storage exists, split vgroup not allowed", pVgroup->vgId, pVgroup->dbName);
×
3560
    goto _OVER;
×
3561
  }
3562
#endif
3563

3564
  /*
3565
    if (pDb->cfg.withArbitrator) {
3566
      code = TSDB_CODE_OPS_NOT_SUPPORT;
3567
      mError("vgId:%d, db:%s, with arbitrator, split vgroup not allowed", pVgroup->vgId, pVgroup->dbName);
3568
      goto _OVER;
3569
    }
3570
  */
3571

3572
  pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB, pReq, "split-vgroup");
12,103✔
3573
  if (pTrans == NULL) {
12,103✔
3574
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3575
    if (terrno != 0) code = terrno;
×
3576
    goto _OVER;
×
3577
  }
3578
  mndTransSetSerial(pTrans);
12,103✔
3579
  mInfo("trans:%d, used to split vgroup, vgId:%d", pTrans->id, pVgroup->vgId);
12,103✔
3580

3581
  mndTransSetDbName(pTrans, pDb->name, NULL);
12,103✔
3582
  TAOS_CHECK_GOTO(mndTransCheckConflictWithCompact(pMnode, pTrans), NULL, _OVER);
12,103✔
3583
  TAOS_CHECK_GOTO(mndTransCheckConflictWithRetention(pMnode, pTrans), NULL, _OVER);
11,864✔
3584

3585
  SVgObj newVg1 = {0};
11,864✔
3586
  memcpy(&newVg1, pVgroup, sizeof(SVgObj));
11,864✔
3587
  mInfo("vgId:%d, vgroup info before split, replica:%d hashBegin:%u hashEnd:%u", newVg1.vgId, newVg1.replica,
11,864✔
3588
        newVg1.hashBegin, newVg1.hashEnd);
3589
  for (int32_t i = 0; i < newVg1.replica; ++i) {
34,818✔
3590
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg1.vgId, i, newVg1.vnodeGid[i].dnodeId);
22,954✔
3591
  }
3592

3593
  if (newVg1.replica == 1) {
11,864✔
3594
    TAOS_CHECK_GOTO(mndAddVnodeToVgroup(pMnode, pTrans, &newVg1, pArray), NULL, _OVER);
5,956✔
3595

3596
    newVg1.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
5,956✔
3597
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[0].dnodeId), NULL,
5,956✔
3598
                    _OVER);
3599
    TAOS_CHECK_GOTO(mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg1, &newVg1.vnodeGid[1]), NULL, _OVER);
5,956✔
3600

3601
    newVg1.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
5,956✔
3602
    TAOS_CHECK_GOTO(mndAddAlterVnodeTypeAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[1].dnodeId), NULL, _OVER);
5,956✔
3603
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[0].dnodeId), NULL,
5,956✔
3604
                    _OVER);
3605

3606
    TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg1), NULL, _OVER);
5,956✔
3607
  } else if (newVg1.replica == 3) {
5,908✔
3608
    SVnodeGid del1 = {0};
5,182✔
3609
    TAOS_CHECK_GOTO(mndRemoveVnodeFromVgroup(pMnode, pTrans, &newVg1, pArray, &del1), NULL, _OVER);
5,182✔
3610
    TAOS_CHECK_GOTO(mndAddDropVnodeAction(pMnode, pTrans, pDb, &newVg1, &del1, true), NULL, _OVER);
5,158✔
3611
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[0].dnodeId), NULL,
5,158✔
3612
                    _OVER);
3613
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[1].dnodeId), NULL,
5,158✔
3614
                    _OVER);
3615
  } else {
3616
    // goto _OVER;
3617
  }
3618

3619
  for (int32_t i = 0; i < newVg1.replica; ++i) {
35,520✔
3620
    TAOS_CHECK_GOTO(mndAddDisableVnodeWriteAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[i].dnodeId), NULL,
23,680✔
3621
                    _OVER);
3622
  }
3623
  TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg1), NULL, _OVER);
11,840✔
3624

3625
  SVgObj newVg2 = {0};
11,840✔
3626
  memcpy(&newVg2, &newVg1, sizeof(SVgObj));
11,840✔
3627
  newVg1.replica = 1;
11,840✔
3628
  newVg1.hashEnd = newVg1.hashBegin / 2 + newVg1.hashEnd / 2;
11,840✔
3629
  memset(&newVg1.vnodeGid[1], 0, sizeof(SVnodeGid));
11,840✔
3630

3631
  newVg2.replica = 1;
11,840✔
3632
  newVg2.hashBegin = newVg1.hashEnd + 1;
11,840✔
3633
  memcpy(&newVg2.vnodeGid[0], &newVg2.vnodeGid[1], sizeof(SVnodeGid));
11,840✔
3634
  memset(&newVg2.vnodeGid[1], 0, sizeof(SVnodeGid));
11,840✔
3635

3636
  mInfo("vgId:%d, vgroup info after split, replica:%d hashrange:[%u, %u] vnode:0 dnode:%d", newVg1.vgId, newVg1.replica,
11,840✔
3637
        newVg1.hashBegin, newVg1.hashEnd, newVg1.vnodeGid[0].dnodeId);
3638
  for (int32_t i = 0; i < newVg1.replica; ++i) {
23,680✔
3639
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg1.vgId, i, newVg1.vnodeGid[i].dnodeId);
11,840✔
3640
  }
3641
  mInfo("vgId:%d, vgroup info after split, replica:%d hashrange:[%u, %u] vnode:0 dnode:%d", newVg2.vgId, newVg2.replica,
11,840✔
3642
        newVg2.hashBegin, newVg2.hashEnd, newVg2.vnodeGid[0].dnodeId);
3643
  for (int32_t i = 0; i < newVg1.replica; ++i) {
23,680✔
3644
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg2.vgId, i, newVg2.vnodeGid[i].dnodeId);
11,840✔
3645
  }
3646

3647
  // alter vgId and hash range
3648
  int32_t maxVgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP);
11,840✔
3649
  int32_t srcVgId = newVg1.vgId;
11,840✔
3650
  newVg1.vgId = maxVgId;
11,840✔
3651
  TAOS_CHECK_GOTO(mndAddNewVgPrepareAction(pMnode, pTrans, &newVg1), NULL, _OVER);
11,840✔
3652
  TAOS_CHECK_GOTO(mndAddAlterVnodeHashRangeAction(pMnode, pTrans, srcVgId, &newVg1), NULL, _OVER);
11,840✔
3653

3654
  maxVgId++;
11,840✔
3655
  srcVgId = newVg2.vgId;
11,840✔
3656
  newVg2.vgId = maxVgId;
11,840✔
3657
  TAOS_CHECK_GOTO(mndAddNewVgPrepareAction(pMnode, pTrans, &newVg2), NULL, _OVER);
11,840✔
3658
  TAOS_CHECK_GOTO(mndAddAlterVnodeHashRangeAction(pMnode, pTrans, srcVgId, &newVg2), NULL, _OVER);
11,840✔
3659

3660
  TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg1), NULL, _OVER);
11,840✔
3661
  TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg2), NULL, _OVER);
11,840✔
3662

3663
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg1, SDB_STATUS_READY, TRN_STAGE_REDO_ACTION), NULL, _OVER);
11,840✔
3664
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg2, SDB_STATUS_READY, TRN_STAGE_REDO_ACTION), NULL, _OVER);
11,840✔
3665
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, pVgroup, SDB_STATUS_DROPPED, TRN_STAGE_REDO_ACTION), NULL, _OVER);
11,840✔
3666

3667
  // update db status
3668
  memcpy(&dbObj, pDb, sizeof(SDbObj));
11,840✔
3669
  if (dbObj.cfg.pRetensions != NULL) {
11,840✔
3670
    dbObj.cfg.pRetensions = taosArrayDup(pDb->cfg.pRetensions, NULL);
×
3671
    if (dbObj.cfg.pRetensions == NULL) {
×
3672
      code = terrno;
×
3673
      goto _OVER;
×
3674
    }
3675
  }
3676
  dbObj.vgVersion++;
11,840✔
3677
  dbObj.updateTime = taosGetTimestampMs();
11,840✔
3678
  dbObj.cfg.numOfVgroups++;
11,840✔
3679
  TAOS_CHECK_GOTO(mndAddDbStatusAction(pTrans, &dbObj, SDB_STATUS_READY, TRN_STAGE_REDO_ACTION), NULL, _OVER);
11,840✔
3680

3681
  // adjust vgroup replica
3682
  if (pDb->cfg.replications != newVg1.replica) {
11,840✔
3683
    SVgObj tmpGroup = {0};
5,884✔
3684
    TAOS_CHECK_GOTO(mndBuildAlterVgroupAction(pMnode, pTrans, pDb, pDb, &newVg1, pArray, &tmpGroup), NULL, _OVER);
5,884✔
3685
  } else {
3686
    TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg1, SDB_STATUS_READY, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
5,956✔
3687
  }
3688

3689
  if (pDb->cfg.replications != newVg2.replica) {
11,709✔
3690
    SVgObj tmpGroup = {0};
5,753✔
3691
    TAOS_CHECK_GOTO(mndBuildAlterVgroupAction(pMnode, pTrans, pDb, pDb, &newVg2, pArray, &tmpGroup), NULL, _OVER);
5,753✔
3692
  } else {
3693
    TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg2, SDB_STATUS_READY, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
5,956✔
3694
  }
3695

3696
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, pVgroup, SDB_STATUS_DROPPED, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
11,631✔
3697

3698
  // commit db status
3699
  dbObj.vgVersion++;
11,631✔
3700
  dbObj.updateTime = taosGetTimestampMs();
11,631✔
3701
  TAOS_CHECK_GOTO(mndAddDbStatusAction(pTrans, &dbObj, SDB_STATUS_READY, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
11,631✔
3702

3703
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
11,631✔
3704
  code = 0;
11,631✔
3705

3706
_OVER:
12,103✔
3707
  taosArrayDestroy(pArray);
12,103✔
3708
  mndTransDrop(pTrans);
12,103✔
3709
  taosArrayDestroy(dbObj.cfg.pRetensions);
12,103✔
3710
  TAOS_RETURN(code);
12,103✔
3711
}
3712

3713
extern int32_t mndProcessSplitVgroupMsgImp(SRpcMsg *pReq);
3714

3715
static int32_t mndProcessSplitVgroupMsg(SRpcMsg *pReq) { return mndProcessSplitVgroupMsgImp(pReq); }
12,825✔
3716

3717
#ifndef TD_ENTERPRISE
3718
int32_t mndProcessSplitVgroupMsgImp(SRpcMsg *pReq) { return 0; }
3719
#endif
3720

3721
static int32_t mndSetBalanceVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
15,316✔
3722
                                              SDnodeObj *pSrc, SDnodeObj *pDst) {
3723
  int32_t code = 0;
15,316✔
3724
  SVgObj  newVg = {0};
15,316✔
3725
  memcpy(&newVg, pVgroup, sizeof(SVgObj));
15,316✔
3726
  mInfo("vgId:%d, vgroup info before balance, replica:%d", newVg.vgId, newVg.replica);
15,316✔
3727
  for (int32_t i = 0; i < newVg.replica; ++i) {
44,920✔
3728
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
29,604✔
3729
  }
3730

3731
  TAOS_CHECK_RETURN(mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pDst->id));
15,316✔
3732
  TAOS_CHECK_RETURN(mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pSrc->id));
15,316✔
3733

3734
  {
3735
    SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
15,316✔
3736
    if (pRaw == NULL) {
15,316✔
3737
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3738
      if (terrno != 0) code = terrno;
×
3739
      TAOS_RETURN(code);
×
3740
    }
3741
    if ((code = mndTransAppendCommitlog(pTrans, pRaw)) != 0) {
15,316✔
3742
      sdbFreeRaw(pRaw);
×
3743
      TAOS_RETURN(code);
×
3744
    }
3745
    code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
15,316✔
3746
    if (code != 0) {
15,316✔
3747
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
3748
      TAOS_RETURN(code);
×
3749
    }
3750
  }
3751

3752
  mInfo("vgId:%d, vgroup info after balance, replica:%d", newVg.vgId, newVg.replica);
15,316✔
3753
  for (int32_t i = 0; i < newVg.replica; ++i) {
44,920✔
3754
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
29,604✔
3755
  }
3756
  TAOS_RETURN(code);
15,316✔
3757
}
3758

3759
static int32_t mndBalanceVgroupBetweenDnode(SMnode *pMnode, STrans *pTrans, SDnodeObj *pSrc, SDnodeObj *pDst,
15,316✔
3760
                                            SHashObj *pBalancedVgroups) {
3761
  void   *pIter = NULL;
15,316✔
3762
  int32_t code = -1;
15,316✔
3763
  SSdb   *pSdb = pMnode->pSdb;
15,316✔
3764

3765
  while (1) {
9,538✔
3766
    SVgObj *pVgroup = NULL;
24,854✔
3767
    pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
24,854✔
3768
    if (pIter == NULL) break;
24,854✔
3769
    if (taosHashGet(pBalancedVgroups, &pVgroup->vgId, sizeof(int32_t)) != NULL) {
24,854✔
3770
      sdbRelease(pSdb, pVgroup);
8,578✔
3771
      continue;
8,578✔
3772
    }
3773

3774
    bool existInSrc = false;
16,276✔
3775
    bool existInDst = false;
16,276✔
3776
    for (int32_t i = 0; i < pVgroup->replica; ++i) {
46,840✔
3777
      SVnodeGid *pGid = &pVgroup->vnodeGid[i];
30,564✔
3778
      if (pGid->dnodeId == pSrc->id) existInSrc = true;
30,564✔
3779
      if (pGid->dnodeId == pDst->id) existInDst = true;
30,564✔
3780
    }
3781

3782
    if (!existInSrc || existInDst) {
16,276✔
3783
      sdbRelease(pSdb, pVgroup);
960✔
3784
      continue;
960✔
3785
    }
3786

3787
    SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName);
15,316✔
3788
    if (pDb == NULL) {
15,316✔
3789
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3790
      if (terrno != 0) code = terrno;
×
3791
      mError("vgId:%d, balance vgroup can't find db obj dbName:%s", pVgroup->vgId, pVgroup->dbName);
×
3792
      goto _OUT;
×
3793
    }
3794

3795
    if (pDb->cfg.withArbitrator) {
15,316✔
3796
      mInfo("vgId:%d, db:%s, with arbitrator, balance vgroup not allowed", pVgroup->vgId, pVgroup->dbName);
×
3797
      goto _OUT;
×
3798
    }
3799

3800
    code = mndSetBalanceVgroupInfoToTrans(pMnode, pTrans, pDb, pVgroup, pSrc, pDst);
15,316✔
3801
    if (code == 0) {
15,316✔
3802
      code = taosHashPut(pBalancedVgroups, &pVgroup->vgId, sizeof(int32_t), &pVgroup->vgId, sizeof(int32_t));
15,316✔
3803
    }
3804

3805
  _OUT:
15,316✔
3806
    mndReleaseDb(pMnode, pDb);
15,316✔
3807
    sdbRelease(pSdb, pVgroup);
15,316✔
3808
    sdbCancelFetch(pSdb, pIter);
15,316✔
3809
    break;
15,316✔
3810
  }
3811

3812
  return code;
15,316✔
3813
}
3814

3815
static int32_t mndBalanceVgroup(SMnode *pMnode, SRpcMsg *pReq, SArray *pArray) {
11,265✔
3816
  int32_t   code = -1;
11,265✔
3817
  int32_t   numOfVgroups = 0;
11,265✔
3818
  STrans   *pTrans = NULL;
11,265✔
3819
  SHashObj *pBalancedVgroups = NULL;
11,265✔
3820

3821
  pBalancedVgroups = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
11,265✔
3822
  if (pBalancedVgroups == NULL) goto _OVER;
11,265✔
3823

3824
  pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_GLOBAL, pReq, "balance-vgroup");
11,265✔
3825
  if (pTrans == NULL) {
11,265✔
3826
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3827
    if (terrno != 0) code = terrno;
×
3828
    goto _OVER;
×
3829
  }
3830
  mndTransSetSerial(pTrans);
11,265✔
3831
  mInfo("trans:%d, used to balance vgroup", pTrans->id);
11,265✔
3832
  TAOS_CHECK_GOTO(mndTransCheckConflict(pMnode, pTrans), NULL, _OVER);
11,265✔
3833
  TAOS_CHECK_GOTO(mndTransCheckConflictWithCompact(pMnode, pTrans), NULL, _OVER);
9,831✔
3834
  TAOS_CHECK_GOTO(mndTransCheckConflictWithRetention(pMnode, pTrans), NULL, _OVER);
9,592✔
3835

3836
  while (1) {
15,316✔
3837
    taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
24,908✔
3838
    for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
107,433✔
3839
      SDnodeObj *pDnode = taosArrayGet(pArray, i);
82,525✔
3840
      mInfo("dnode:%d, equivalent vnodes:%d others:%d support:%d, score:%f", pDnode->id, pDnode->numOfVnodes,
82,525✔
3841
            pDnode->numOfSupportVnodes, pDnode->numOfOtherNodes, mndGetDnodeScore(pDnode, 0, 1));
3842
    }
3843

3844
    SDnodeObj *pSrc = taosArrayGet(pArray, taosArrayGetSize(pArray) - 1);
24,908✔
3845
    SDnodeObj *pDst = taosArrayGet(pArray, 0);
24,908✔
3846

3847
    float srcScore = mndGetDnodeScore(pSrc, -1, 1);
24,908✔
3848
    float dstScore = mndGetDnodeScore(pDst, 1, 1);
24,908✔
3849
    mInfo("trans:%d, after balance, src dnode:%d score:%f, dst dnode:%d score:%f", pTrans->id, pSrc->id, dstScore,
24,908✔
3850
          pDst->id, dstScore);
3851

3852
    if (srcScore > dstScore - 0.000001) {
24,908✔
3853
      code = mndBalanceVgroupBetweenDnode(pMnode, pTrans, pSrc, pDst, pBalancedVgroups);
15,316✔
3854
      if (code == 0) {
15,316✔
3855
        pSrc->numOfVnodes--;
15,316✔
3856
        pDst->numOfVnodes++;
15,316✔
3857
        numOfVgroups++;
15,316✔
3858
        continue;
15,316✔
3859
      } else {
3860
        mInfo("trans:%d, no vgroup need to balance from dnode:%d to dnode:%d", pTrans->id, pSrc->id, pDst->id);
×
3861
        break;
×
3862
      }
3863
    } else {
3864
      mInfo("trans:%d, no vgroup need to balance any more", pTrans->id);
9,592✔
3865
      break;
9,592✔
3866
    }
3867
  }
3868

3869
  if (numOfVgroups <= 0) {
9,592✔
3870
    mInfo("no need to balance vgroup");
×
3871
    code = 0;
×
3872
  } else {
3873
    mInfo("start to balance vgroup, numOfVgroups:%d", numOfVgroups);
9,592✔
3874
    if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER;
9,592✔
3875
    code = TSDB_CODE_ACTION_IN_PROGRESS;
9,592✔
3876
  }
3877

3878
_OVER:
11,265✔
3879
  taosHashCleanup(pBalancedVgroups);
11,265✔
3880
  mndTransDrop(pTrans);
11,265✔
3881
  TAOS_RETURN(code);
11,265✔
3882
}
3883

3884
static int32_t mndProcessBalanceVgroupMsg(SRpcMsg *pReq) {
13,075✔
3885
  SMnode *pMnode = pReq->info.node;
13,075✔
3886
  int32_t code = -1;
13,075✔
3887
  SArray *pArray = NULL;
13,075✔
3888
  void   *pIter = NULL;
13,075✔
3889
  int64_t curMs = taosGetTimestampMs();
13,075✔
3890

3891
  SBalanceVgroupReq req = {0};
13,075✔
3892
  if (tDeserializeSBalanceVgroupReq(pReq->pCont, pReq->contLen, &req) != 0) {
13,075✔
3893
    code = TSDB_CODE_INVALID_MSG;
×
3894
    goto _OVER;
×
3895
  }
3896

3897
  mInfo("start to balance vgroup");
13,075✔
3898
  if ((code = mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_BALANCE_VGROUP)) != 0) {
13,075✔
3899
    goto _OVER;
358✔
3900
  }
3901

3902
  if (sdbGetSize(pMnode->pSdb, SDB_MOUNT) > 0) {
12,717✔
3903
    code = TSDB_CODE_MND_MOUNT_NOT_EMPTY;
×
3904
    goto _OVER;
×
3905
  }
3906

3907
  while (1) {
38,822✔
3908
    SDnodeObj *pDnode = NULL;
51,539✔
3909
    pIter = sdbFetch(pMnode->pSdb, SDB_DNODE, pIter, (void **)&pDnode);
51,539✔
3910
    if (pIter == NULL) break;
51,539✔
3911
    if (!mndIsDnodeOnline(pDnode, curMs)) {
40,274✔
3912
      sdbCancelFetch(pMnode->pSdb, pIter);
1,452✔
3913
      code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
1,452✔
3914
      mError("failed to balance vgroup since %s, dnode:%d", terrstr(), pDnode->id);
1,452✔
3915
      sdbRelease(pMnode->pSdb, pDnode);
1,452✔
3916
      goto _OVER;
1,452✔
3917
    }
3918

3919
    sdbRelease(pMnode->pSdb, pDnode);
38,822✔
3920
  }
3921

3922
  pArray = mndBuildDnodesArray(pMnode, 0, NULL);
11,265✔
3923
  if (pArray == NULL) {
11,265✔
3924
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3925
    if (terrno != 0) code = terrno;
×
3926
    goto _OVER;
×
3927
  }
3928

3929
  if (taosArrayGetSize(pArray) < 2) {
11,265✔
3930
    mInfo("no need to balance vgroup since dnode num less than 2");
×
3931
    code = 0;
×
3932
  } else {
3933
    code = mndBalanceVgroup(pMnode, pReq, pArray);
11,265✔
3934
  }
3935

3936
  auditRecord(pReq, pMnode->clusterId, "balanceVgroup", "", "", req.sql, req.sqlLen);
11,265✔
3937

3938
_OVER:
13,075✔
3939
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
13,075✔
3940
    mError("failed to balance vgroup since %s", tstrerror(code));
3,483✔
3941
  }
3942

3943
  taosArrayDestroy(pArray);
13,075✔
3944
  tFreeSBalanceVgroupReq(&req);
13,075✔
3945
  TAOS_RETURN(code);
13,075✔
3946
}
3947

3948
bool mndVgroupInDb(SVgObj *pVgroup, int64_t dbUid) { return !pVgroup->isTsma && pVgroup->dbUid == dbUid; }
111,091,545✔
3949

3950
bool mndVgroupInDnode(SVgObj *pVgroup, int32_t dnodeId) {
10,048✔
3951
  for (int i = 0; i < pVgroup->replica; i++) {
25,116✔
3952
    if (pVgroup->vnodeGid[i].dnodeId == dnodeId) return true;
21,348✔
3953
  }
3954
  return false;
3,768✔
3955
}
3956

3957
static void *mndBuildCompactVnodeReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen, int64_t compactTs,
127,757✔
3958
                                     STimeWindow tw, bool metaOnly, bool force, ETsdbOpType type,
3959
                                     ETriggerType triggerType) {
3960
  SCompactVnodeReq compactReq = {0};
127,757✔
3961
  compactReq.dbUid = pDb->uid;
127,757✔
3962
  compactReq.compactStartTime = compactTs;
127,757✔
3963
  compactReq.tw = tw;
127,757✔
3964
  compactReq.metaOnly = metaOnly;
127,757✔
3965
  compactReq.force = force;
127,757✔
3966
  compactReq.optrType = type;
127,757✔
3967
  compactReq.triggerType = triggerType;
127,757✔
3968
  tstrncpy(compactReq.db, pDb->name, TSDB_DB_FNAME_LEN);
127,757✔
3969

3970
  mInfo("vgId:%d, build compact vnode config req", pVgroup->vgId);
127,757✔
3971
  int32_t contLen = tSerializeSCompactVnodeReq(NULL, 0, &compactReq);
127,757✔
3972
  if (contLen < 0) {
127,757✔
3973
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
3974
    return NULL;
×
3975
  }
3976
  contLen += sizeof(SMsgHead);
127,757✔
3977

3978
  void *pReq = taosMemoryMalloc(contLen);
127,757✔
3979
  if (pReq == NULL) {
127,757✔
3980
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
3981
    return NULL;
×
3982
  }
3983

3984
  SMsgHead *pHead = pReq;
127,757✔
3985
  pHead->contLen = htonl(contLen);
127,757✔
3986
  pHead->vgId = htonl(pVgroup->vgId);
127,757✔
3987

3988
  if (tSerializeSCompactVnodeReq((char *)pReq + sizeof(SMsgHead), contLen, &compactReq) < 0) {
127,757✔
3989
    taosMemoryFree(pReq);
×
3990
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
3991
    return NULL;
×
3992
  }
3993
  *pContLen = contLen;
127,757✔
3994
  return pReq;
127,757✔
3995
}
3996

3997
static int32_t mndAddCompactVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int64_t compactTs,
62,100✔
3998
                                        STimeWindow tw, bool metaOnly, bool force, ETsdbOpType type,
3999
                                        ETriggerType triggerType) {
4000
  int32_t      code = 0;
62,100✔
4001
  STransAction action = {0};
62,100✔
4002
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
62,100✔
4003

4004
  int32_t contLen = 0;
62,100✔
4005
  void   *pReq =
4006
      mndBuildCompactVnodeReq(pMnode, pDb, pVgroup, &contLen, compactTs, tw, metaOnly, force, type, triggerType);
62,100✔
4007
  if (pReq == NULL) {
62,100✔
4008
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
4009
    if (terrno != 0) code = terrno;
×
4010
    TAOS_RETURN(code);
×
4011
  }
4012

4013
  action.pCont = pReq;
62,100✔
4014
  action.contLen = contLen;
62,100✔
4015
  action.msgType = TDMT_VND_COMPACT;
62,100✔
4016

4017
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
62,100✔
4018
    taosMemoryFree(pReq);
×
4019
    TAOS_RETURN(code);
×
4020
  }
4021

4022
  TAOS_RETURN(code);
62,100✔
4023
}
4024

4025
int32_t mndBuildCompactVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int64_t compactTs,
62,100✔
4026
                                    STimeWindow tw, bool metaOnly, bool force, ETsdbOpType type,
4027
                                    ETriggerType triggerType) {
4028
  TAOS_CHECK_RETURN(
62,100✔
4029
      mndAddCompactVnodeAction(pMnode, pTrans, pDb, pVgroup, compactTs, tw, metaOnly, force, type, triggerType));
4030
  return 0;
62,100✔
4031
}
4032

4033
int32_t mndBuildTrimVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int64_t startTs,
65,657✔
4034
                                 STimeWindow tw, ETsdbOpType type, ETriggerType triggerType) {
4035
  int32_t      code = 0;
65,657✔
4036
  STransAction action = {0};
65,657✔
4037
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
65,657✔
4038

4039
  int32_t contLen = 0;
65,657✔
4040
  // reuse SCompactVnodeReq as SVTrimDbReq
4041
  void *pReq = mndBuildCompactVnodeReq(pMnode, pDb, pVgroup, &contLen, startTs, tw, false, false, type, triggerType);
65,657✔
4042
  if (pReq == NULL) {
65,657✔
4043
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
4044
    if (terrno != 0) code = terrno;
×
4045
    TAOS_RETURN(code);
×
4046
  }
4047

4048
  action.pCont = pReq;
65,657✔
4049
  action.contLen = contLen;
65,657✔
4050
  action.msgType = TDMT_VND_TRIM;
65,657✔
4051

4052
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
65,657✔
4053
    taosMemoryFree(pReq);
×
4054
    TAOS_RETURN(code);
×
4055
  }
4056

4057
  TAOS_RETURN(code);
65,657✔
4058
}
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