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

taosdata / TDengine / #4880

11 Dec 2025 02:43AM UTC coverage: 64.544%. Remained the same
#4880

push

travis-ci

guanshengliang
feat(TS-7270): internal dependence

307 of 617 new or added lines in 24 files covered. (49.76%)

3380 existing lines in 25 files now uncovered.

163565 of 253417 relevant lines covered (64.54%)

105600506.39 hits per line

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

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

33
#define VGROUP_VER_NUMBER   1
34
#define VGROUP_RESERVE_SIZE 60
35

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

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

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

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

64
  mndSetMsgHandle(pMnode, TDMT_DND_CREATE_VNODE_RSP, mndTransProcessRsp);
495,504✔
65
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_REPLICA_RSP, mndTransProcessRsp);
495,504✔
66
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_CONFIG_RSP, mndTransProcessRsp);
495,504✔
67
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_CONFIRM_RSP, mndTransProcessRsp);
495,504✔
68
  mndSetMsgHandle(pMnode, TDMT_VND_SET_KEEP_VERSION_RSP, mndTransProcessRsp);
495,504✔
69
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_HASHRANGE_RSP, mndTransProcessRsp);
495,504✔
70
  mndSetMsgHandle(pMnode, TDMT_DND_DROP_VNODE_RSP, mndTransProcessRsp);
495,504✔
71
  mndSetMsgHandle(pMnode, TDMT_VND_COMPACT_RSP, mndTransProcessRsp);
495,504✔
72
  mndSetMsgHandle(pMnode, TDMT_VND_SCAN_RSP, mndTransProcessRsp);
495,504✔
73
  mndSetMsgHandle(pMnode, TDMT_VND_DISABLE_WRITE_RSP, mndTransProcessRsp);
495,504✔
74
  mndSetMsgHandle(pMnode, TDMT_SYNC_FORCE_FOLLOWER_RSP, mndTransProcessRsp);
495,504✔
75
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_ELECTBASELINE_RSP, mndTransProcessRsp);
495,504✔
76
  
77
  mndSetMsgHandle(pMnode, TDMT_DND_ALTER_VNODE_TYPE_RSP, mndTransProcessRsp);
495,504✔
78
  mndSetMsgHandle(pMnode, TDMT_DND_CHECK_VNODE_LEARNER_CATCHUP_RSP, mndTransProcessRsp);
495,504✔
79
  mndSetMsgHandle(pMnode, TDMT_SYNC_CONFIG_CHANGE_RSP, mndTransProcessRsp);
495,504✔
80

81
  mndSetMsgHandle(pMnode, TDMT_MND_REDISTRIBUTE_VGROUP, mndProcessRedistributeVgroupMsg);
495,504✔
82
  mndSetMsgHandle(pMnode, TDMT_MND_SPLIT_VGROUP, mndProcessSplitVgroupMsg);
495,504✔
83
  // mndSetMsgHandle(pMnode, TDMT_MND_BALANCE_VGROUP, mndProcessVgroupBalanceLeaderMsg);
84
  mndSetMsgHandle(pMnode, TDMT_MND_BALANCE_VGROUP, mndProcessBalanceVgroupMsg);
495,504✔
85
  mndSetMsgHandle(pMnode, TDMT_MND_BALANCE_VGROUP_LEADER, mndProcessVgroupBalanceLeaderMsg);
495,504✔
86
  mndSetMsgHandle(pMnode, TDMT_MND_SET_VGROUP_KEEP_VERSION, mndProcessSetVgroupKeepVersionReq);
495,504✔
87

88
  mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_VGROUP, mndRetrieveVgroups);
495,504✔
89
  mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_VGROUP, mndCancelGetNextVgroup);
495,504✔
90
  mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_VNODES, mndRetrieveVnodes);
495,504✔
91
  mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_VNODES, mndCancelGetNextVnode);
495,504✔
92

93
  return sdbSetTable(pMnode->pSdb, table);
495,504✔
94
}
95

96
void mndCleanupVgroup(SMnode *pMnode) {}
494,719✔
97

98
SSdbRaw *mndVgroupActionEncode(SVgObj *pVgroup) {
11,486,898✔
99
  int32_t code = 0;
11,486,898✔
100
  int32_t lino = 0;
11,486,898✔
101
  terrno = TSDB_CODE_OUT_OF_MEMORY;
11,486,898✔
102

103
  SSdbRaw *pRaw = sdbAllocRaw(SDB_VGROUP, VGROUP_VER_NUMBER, sizeof(SVgObj) + VGROUP_RESERVE_SIZE);
11,486,898✔
104
  if (pRaw == NULL) goto _OVER;
11,486,898✔
105

106
  int32_t dataPos = 0;
11,486,898✔
107
  SDB_SET_INT32(pRaw, dataPos, pVgroup->vgId, _OVER)
11,486,898✔
108
  SDB_SET_INT64(pRaw, dataPos, pVgroup->createdTime, _OVER)
11,486,898✔
109
  SDB_SET_INT64(pRaw, dataPos, pVgroup->updateTime, _OVER)
11,486,898✔
110
  SDB_SET_INT32(pRaw, dataPos, pVgroup->version, _OVER)
11,486,898✔
111
  SDB_SET_INT32(pRaw, dataPos, pVgroup->hashBegin, _OVER)
11,486,898✔
112
  SDB_SET_INT32(pRaw, dataPos, pVgroup->hashEnd, _OVER)
11,486,898✔
113
  SDB_SET_BINARY(pRaw, dataPos, pVgroup->dbName, TSDB_DB_FNAME_LEN, _OVER)
11,486,898✔
114
  SDB_SET_INT64(pRaw, dataPos, pVgroup->dbUid, _OVER)
11,486,898✔
115
  SDB_SET_INT8(pRaw, dataPos, pVgroup->isTsma, _OVER)
11,486,898✔
116
  SDB_SET_INT8(pRaw, dataPos, pVgroup->replica, _OVER)
11,486,898✔
117
  for (int8_t i = 0; i < pVgroup->replica; ++i) {
25,308,323✔
118
    SVnodeGid *pVgid = &pVgroup->vnodeGid[i];
13,821,425✔
119
    SDB_SET_INT32(pRaw, dataPos, pVgid->dnodeId, _OVER)
13,821,425✔
120
  }
121
  SDB_SET_INT32(pRaw, dataPos, pVgroup->syncConfChangeVer, _OVER)
11,486,898✔
122
  SDB_SET_INT32(pRaw, dataPos, pVgroup->mountVgId, _OVER)
11,486,898✔
123
  SDB_SET_INT64(pRaw, dataPos, pVgroup->keepVersion, _OVER)
11,486,898✔
124
  SDB_SET_INT64(pRaw, dataPos, pVgroup->keepVersionTime, _OVER)
11,486,898✔
125
  SDB_SET_RESERVE(pRaw, dataPos, VGROUP_RESERVE_SIZE, _OVER)
11,486,898✔
126
  SDB_SET_DATALEN(pRaw, dataPos, _OVER)
11,486,898✔
127

128
  terrno = 0;
11,486,898✔
129

130
_OVER:
11,486,898✔
131
  if (terrno != 0) {
11,486,898✔
132
    mError("vgId:%d, failed to encode to raw:%p since %s", pVgroup->vgId, pRaw, terrstr());
×
133
    sdbFreeRaw(pRaw);
×
134
    return NULL;
×
135
  }
136

137
  mTrace("vgId:%d, encode to raw:%p, row:%p", pVgroup->vgId, pRaw, pVgroup);
11,486,898✔
138
  return pRaw;
11,486,898✔
139
}
140

141
SSdbRow *mndVgroupActionDecode(SSdbRaw *pRaw) {
10,790,893✔
142
  int32_t code = 0;
10,790,893✔
143
  int32_t lino = 0;
10,790,893✔
144
  terrno = TSDB_CODE_OUT_OF_MEMORY;
10,790,893✔
145
  SSdbRow *pRow = NULL;
10,790,893✔
146
  SVgObj  *pVgroup = NULL;
10,790,893✔
147

148
  int8_t sver = 0;
10,790,893✔
149
  if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto _OVER;
10,790,893✔
150

151
  if (sver < 1 || sver > VGROUP_VER_NUMBER) {
10,790,893✔
152
    terrno = TSDB_CODE_SDB_INVALID_DATA_VER;
×
153
    goto _OVER;
×
154
  }
155

156
  pRow = sdbAllocRow(sizeof(SVgObj));
10,790,893✔
157
  if (pRow == NULL) goto _OVER;
10,790,893✔
158

159
  pVgroup = sdbGetRowObj(pRow);
10,790,893✔
160
  if (pVgroup == NULL) goto _OVER;
10,790,893✔
161

162
  int32_t dataPos = 0;
10,790,893✔
163
  SDB_GET_INT32(pRaw, dataPos, &pVgroup->vgId, _OVER)
10,790,893✔
164
  SDB_GET_INT64(pRaw, dataPos, &pVgroup->createdTime, _OVER)
10,790,893✔
165
  SDB_GET_INT64(pRaw, dataPos, &pVgroup->updateTime, _OVER)
10,790,893✔
166
  SDB_GET_INT32(pRaw, dataPos, &pVgroup->version, _OVER)
10,790,893✔
167
  SDB_GET_INT32(pRaw, dataPos, &pVgroup->hashBegin, _OVER)
10,790,893✔
168
  SDB_GET_INT32(pRaw, dataPos, &pVgroup->hashEnd, _OVER)
10,790,893✔
169
  SDB_GET_BINARY(pRaw, dataPos, pVgroup->dbName, TSDB_DB_FNAME_LEN, _OVER)
10,790,893✔
170
  SDB_GET_INT64(pRaw, dataPos, &pVgroup->dbUid, _OVER)
10,790,893✔
171
  SDB_GET_INT8(pRaw, dataPos, &pVgroup->isTsma, _OVER)
10,790,893✔
172
  SDB_GET_INT8(pRaw, dataPos, &pVgroup->replica, _OVER)
10,790,893✔
173
  for (int8_t i = 0; i < pVgroup->replica; ++i) {
24,141,473✔
174
    SVnodeGid *pVgid = &pVgroup->vnodeGid[i];
13,350,580✔
175
    SDB_GET_INT32(pRaw, dataPos, &pVgid->dnodeId, _OVER)
13,350,580✔
176
    if (pVgroup->replica == 1) {
13,350,580✔
177
      pVgid->syncState = TAOS_SYNC_STATE_LEADER;
9,449,654✔
178
    }
179
  }
180
  if (dataPos + 2 * sizeof(int32_t) + VGROUP_RESERVE_SIZE <= pRaw->dataLen) {
10,790,893✔
181
    SDB_GET_INT32(pRaw, dataPos, &pVgroup->syncConfChangeVer, _OVER)
10,790,893✔
182
  }
183
  SDB_GET_INT32(pRaw, dataPos, &pVgroup->mountVgId, _OVER)
10,790,893✔
184
  if (dataPos + sizeof(int64_t) + VGROUP_RESERVE_SIZE <= pRaw->dataLen) {
10,790,893✔
185
    SDB_GET_INT64(pRaw, dataPos, &pVgroup->keepVersion, _OVER)
10,790,893✔
186
  }
187
  if (dataPos + sizeof(int64_t) + VGROUP_RESERVE_SIZE <= pRaw->dataLen) {
10,790,893✔
188
    SDB_GET_INT64(pRaw, dataPos, &pVgroup->keepVersionTime, _OVER)
10,790,893✔
189
  }
190
  SDB_GET_RESERVE(pRaw, dataPos, VGROUP_RESERVE_SIZE, _OVER)
10,790,893✔
191

192
  terrno = 0;
10,790,893✔
193

194
_OVER:
10,790,893✔
195
  if (terrno != 0) {
10,790,893✔
196
    mError("vgId:%d, failed to decode from raw:%p since %s", pVgroup == NULL ? 0 : pVgroup->vgId, pRaw, terrstr());
×
197
    taosMemoryFreeClear(pRow);
×
198
    return NULL;
×
199
  }
200

201
  mTrace("vgId:%d, decode from raw:%p, row:%p", pVgroup->vgId, pRaw, pVgroup);
10,790,893✔
202
  return pRow;
10,790,893✔
203
}
204

205
static int32_t mndNewVgActionValidate(SMnode *pMnode, STrans *pTrans, SSdbRaw *pRaw) {
2,794,688✔
206
  SSdb    *pSdb = pMnode->pSdb;
2,794,688✔
207
  SSdbRow *pRow = NULL;
2,794,688✔
208
  SVgObj  *pVgroup = NULL;
2,794,688✔
209
  int      code = -1;
2,794,688✔
210

211
  pRow = mndVgroupActionDecode(pRaw);
2,794,688✔
212
  if (pRow == NULL) {
2,794,688✔
213
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
214
    if (terrno != 0) code = terrno;
×
215
    goto _OVER;
×
216
  }
217
  pVgroup = sdbGetRowObj(pRow);
2,794,688✔
218
  if (pVgroup == NULL) {
2,794,688✔
219
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
220
    if (terrno != 0) code = terrno;
×
221
    goto _OVER;
×
222
  }
223

224
  int32_t maxVgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP);
2,794,688✔
225
  if (maxVgId > pVgroup->vgId) {
2,794,688✔
226
    mError("trans:%d, vgroup id %d already in use. maxVgId:%d", pTrans->id, pVgroup->vgId, maxVgId);
×
227
    goto _OVER;
×
228
  }
229

230
  code = 0;
2,794,688✔
231
_OVER:
2,794,688✔
232
  if (pVgroup) mndVgroupActionDelete(pSdb, pVgroup);
2,794,688✔
233
  taosMemoryFreeClear(pRow);
2,794,688✔
234
  TAOS_RETURN(code);
2,794,688✔
235
}
236

237
static int32_t mndVgroupActionInsert(SSdb *pSdb, SVgObj *pVgroup) {
3,225,972✔
238
  mTrace("vgId:%d, perform insert action, row:%p", pVgroup->vgId, pVgroup);
3,225,972✔
239
  return 0;
3,225,972✔
240
}
241

242
static int32_t mndVgroupActionDelete(SSdb *pSdb, SVgObj *pVgroup) {
10,767,981✔
243
  mTrace("vgId:%d, perform delete action, row:%p", pVgroup->vgId, pVgroup);
10,767,981✔
244
  return 0;
10,767,981✔
245
}
246

247
static int32_t mndVgroupActionUpdate(SSdb *pSdb, SVgObj *pOld, SVgObj *pNew) {
3,235,863✔
248
  mTrace("vgId:%d, perform update action, old row:%p new row:%p", pOld->vgId, pOld, pNew);
3,235,863✔
249
  pOld->updateTime = pNew->updateTime;
3,235,863✔
250
  pOld->version = pNew->version;
3,235,863✔
251
  pOld->hashBegin = pNew->hashBegin;
3,235,863✔
252
  pOld->hashEnd = pNew->hashEnd;
3,235,863✔
253
  pOld->replica = pNew->replica;
3,235,863✔
254
  pOld->isTsma = pNew->isTsma;
3,235,863✔
255
  pOld->keepVersion = pNew->keepVersion;
3,235,863✔
256
  pOld->keepVersionTime = pNew->keepVersionTime;
3,235,863✔
257
  for (int32_t i = 0; i < pNew->replica; ++i) {
7,640,385✔
258
    SVnodeGid *pNewGid = &pNew->vnodeGid[i];
4,404,522✔
259
    for (int32_t j = 0; j < pOld->replica; ++j) {
12,342,680✔
260
      SVnodeGid *pOldGid = &pOld->vnodeGid[j];
7,938,158✔
261
      if (pNewGid->dnodeId == pOldGid->dnodeId) {
7,938,158✔
262
        pNewGid->syncState = pOldGid->syncState;
4,179,366✔
263
        pNewGid->syncRestore = pOldGid->syncRestore;
4,179,366✔
264
        pNewGid->syncCanRead = pOldGid->syncCanRead;
4,179,366✔
265
        pNewGid->syncAppliedIndex = pOldGid->syncAppliedIndex;
4,179,366✔
266
        pNewGid->syncCommitIndex = pOldGid->syncCommitIndex;
4,179,366✔
267
        pNewGid->bufferSegmentUsed = pOldGid->bufferSegmentUsed;
4,179,366✔
268
        pNewGid->bufferSegmentSize = pOldGid->bufferSegmentSize;
4,179,366✔
269
      }
270
    }
271
  }
272
  pNew->numOfTables = pOld->numOfTables;
3,235,863✔
273
  pNew->numOfTimeSeries = pOld->numOfTimeSeries;
3,235,863✔
274
  pNew->totalStorage = pOld->totalStorage;
3,235,863✔
275
  pNew->compStorage = pOld->compStorage;
3,235,863✔
276
  pNew->pointsWritten = pOld->pointsWritten;
3,235,863✔
277
  pNew->compact = pOld->compact;
3,235,863✔
278
  memcpy(pOld->vnodeGid, pNew->vnodeGid, (TSDB_MAX_REPLICA + TSDB_MAX_LEARNER_REPLICA) * sizeof(SVnodeGid));
3,235,863✔
279
  pOld->syncConfChangeVer = pNew->syncConfChangeVer;
3,235,863✔
280
  tstrncpy(pOld->dbName, pNew->dbName, TSDB_DB_FNAME_LEN);
3,235,863✔
281
  return 0;
3,235,863✔
282
}
283

284
SVgObj *mndAcquireVgroup(SMnode *pMnode, int32_t vgId) {
100,519,481✔
285
  SSdb   *pSdb = pMnode->pSdb;
100,519,481✔
286
  SVgObj *pVgroup = sdbAcquire(pSdb, SDB_VGROUP, &vgId);
100,519,481✔
287
  if (pVgroup == NULL && terrno == TSDB_CODE_SDB_OBJ_NOT_THERE) {
100,519,481✔
288
    terrno = TSDB_CODE_MND_VGROUP_NOT_EXIST;
242,236✔
289
  }
290
  return pVgroup;
100,519,481✔
291
}
292

293
void mndReleaseVgroup(SMnode *pMnode, SVgObj *pVgroup) {
100,436,415✔
294
  SSdb *pSdb = pMnode->pSdb;
100,436,415✔
295
  sdbRelease(pSdb, pVgroup);
100,436,415✔
296
}
100,436,415✔
297

298
void *mndBuildCreateVnodeReq(SMnode *pMnode, SDnodeObj *pDnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen) {
3,017,751✔
299
  SCreateVnodeReq createReq = {0};
3,017,751✔
300
  createReq.vgId = pVgroup->vgId;
3,017,751✔
301
  memcpy(createReq.db, pDb->name, TSDB_DB_FNAME_LEN);
3,017,751✔
302
  createReq.dbUid = pDb->uid;
3,017,751✔
303
  createReq.vgVersion = pVgroup->version;
3,017,751✔
304
  createReq.numOfStables = pDb->cfg.numOfStables;
3,017,751✔
305
  createReq.buffer = pDb->cfg.buffer;
3,017,751✔
306
  createReq.pageSize = pDb->cfg.pageSize;
3,017,751✔
307
  createReq.pages = pDb->cfg.pages;
3,017,751✔
308
  createReq.cacheLastSize = pDb->cfg.cacheLastSize;
3,017,751✔
309
  createReq.daysPerFile = pDb->cfg.daysPerFile;
3,017,751✔
310
  createReq.daysToKeep0 = pDb->cfg.daysToKeep0;
3,017,751✔
311
  createReq.daysToKeep1 = pDb->cfg.daysToKeep1;
3,017,751✔
312
  createReq.daysToKeep2 = pDb->cfg.daysToKeep2;
3,017,751✔
313
  createReq.keepTimeOffset = pDb->cfg.keepTimeOffset;
3,017,751✔
314
  createReq.ssChunkSize = pDb->cfg.ssChunkSize;
3,017,751✔
315
  createReq.ssKeepLocal = pDb->cfg.ssKeepLocal;
3,017,751✔
316
  createReq.ssCompact = pDb->cfg.ssCompact;
3,017,751✔
317
  createReq.minRows = pDb->cfg.minRows;
3,017,751✔
318
  createReq.maxRows = pDb->cfg.maxRows;
3,017,751✔
319
  createReq.walFsyncPeriod = pDb->cfg.walFsyncPeriod;
3,017,751✔
320
  createReq.walLevel = pDb->cfg.walLevel;
3,017,751✔
321
  createReq.precision = pDb->cfg.precision;
3,017,751✔
322
  createReq.compression = pDb->cfg.compression;
3,017,751✔
323
  createReq.strict = pDb->cfg.strict;
3,017,751✔
324
  createReq.cacheLast = pDb->cfg.cacheLast;
3,017,751✔
325
  createReq.replica = 0;
3,017,751✔
326
  createReq.learnerReplica = 0;
3,017,751✔
327
  createReq.selfIndex = -1;
3,017,751✔
328
  createReq.learnerSelfIndex = -1;
3,017,751✔
329
  createReq.hashBegin = pVgroup->hashBegin;
3,017,751✔
330
  createReq.hashEnd = pVgroup->hashEnd;
3,017,751✔
331
  createReq.hashMethod = pDb->cfg.hashMethod;
3,017,751✔
332
  createReq.numOfRetensions = pDb->cfg.numOfRetensions;
3,017,751✔
333
  createReq.pRetensions = pDb->cfg.pRetensions;
3,017,751✔
334
  createReq.isTsma = pVgroup->isTsma;
3,017,751✔
335
  createReq.pTsma = pVgroup->pTsma;
3,017,751✔
336
  createReq.walRetentionPeriod = pDb->cfg.walRetentionPeriod;
3,017,751✔
337
  createReq.walRetentionSize = pDb->cfg.walRetentionSize;
3,017,751✔
338
  createReq.walRollPeriod = pDb->cfg.walRollPeriod;
3,017,751✔
339
  createReq.walSegmentSize = pDb->cfg.walSegmentSize;
3,017,751✔
340
  createReq.sstTrigger = pDb->cfg.sstTrigger;
3,017,751✔
341
  createReq.hashPrefix = pDb->cfg.hashPrefix;
3,017,751✔
342
  createReq.hashSuffix = pDb->cfg.hashSuffix;
3,017,751✔
343
  createReq.tsdbPageSize = pDb->cfg.tsdbPageSize;
3,017,751✔
344
  createReq.changeVersion = ++(pVgroup->syncConfChangeVer);
3,017,751✔
345
  // createReq.encryptAlgorithm = pDb->cfg.encryptAlgorithm;
346
  memset(createReq.encryptAlgrName, 0, TSDB_ENCRYPT_ALGR_NAME_LEN);
3,017,751✔
347
  if (pDb->cfg.encryptAlgorithm > 0) {
3,017,751✔
348
    mndGetEncryptOsslAlgrNameById(pMnode, pDb->cfg.encryptAlgorithm, createReq.encryptAlgrName);
1,653✔
349
  }
350
  int32_t code = 0;
3,017,751✔
351

352
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
7,281,850✔
353
    SReplica *pReplica = NULL;
4,264,099✔
354

355
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
4,264,099✔
356
      pReplica = &createReq.replicas[createReq.replica];
4,156,583✔
357
    } else {
358
      pReplica = &createReq.learnerReplicas[createReq.learnerReplica];
107,516✔
359
    }
360

361
    SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
4,264,099✔
362
    SDnodeObj *pVgidDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
4,264,099✔
363
    if (pVgidDnode == NULL) {
4,264,099✔
364
      return NULL;
×
365
    }
366

367
    pReplica->id = pVgidDnode->id;
4,264,099✔
368
    pReplica->port = pVgidDnode->port;
4,264,099✔
369
    memcpy(pReplica->fqdn, pVgidDnode->fqdn, TSDB_FQDN_LEN);
4,264,099✔
370
    mndReleaseDnode(pMnode, pVgidDnode);
4,264,099✔
371

372
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
4,264,099✔
373
      if (pDnode->id == pVgid->dnodeId) {
4,156,583✔
374
        createReq.selfIndex = createReq.replica;
2,910,235✔
375
      }
376
    } else {
377
      if (pDnode->id == pVgid->dnodeId) {
107,516✔
378
        createReq.learnerSelfIndex = createReq.learnerReplica;
107,516✔
379
      }
380
    }
381

382
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
4,264,099✔
383
      createReq.replica++;
4,156,583✔
384
    } else {
385
      createReq.learnerReplica++;
107,516✔
386
    }
387
  }
388

389
  if (createReq.selfIndex == -1 && createReq.learnerSelfIndex == -1) {
3,017,751✔
390
    terrno = TSDB_CODE_APP_ERROR;
×
391
    return NULL;
×
392
  }
393

394
  createReq.changeVersion = pVgroup->syncConfChangeVer;
3,017,751✔
395

396
  mInfo(
3,017,751✔
397
      "vgId:%d, build create vnode req, replica:%d selfIndex:%d learnerReplica:%d learnerSelfIndex:%d strict:%d "
398
      "changeVersion:%d",
399
      createReq.vgId, createReq.replica, createReq.selfIndex, createReq.learnerReplica, createReq.learnerSelfIndex,
400
      createReq.strict, createReq.changeVersion);
401
  for (int32_t i = 0; i < createReq.replica; ++i) {
7,174,334✔
402
    mInfo("vgId:%d, replica:%d ep:%s:%u", createReq.vgId, i, createReq.replicas[i].fqdn, createReq.replicas[i].port);
4,156,583✔
403
  }
404
  for (int32_t i = 0; i < createReq.learnerReplica; ++i) {
3,125,267✔
405
    mInfo("vgId:%d, replica:%d ep:%s:%u", createReq.vgId, i, createReq.learnerReplicas[i].fqdn,
107,516✔
406
          createReq.learnerReplicas[i].port);
407
  }
408

409
  int32_t contLen = tSerializeSCreateVnodeReq(NULL, 0, &createReq);
3,017,751✔
410
  if (contLen < 0) {
3,017,751✔
411
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
412
    return NULL;
×
413
  }
414

415
  void *pReq = taosMemoryMalloc(contLen);
3,017,751✔
416
  if (pReq == NULL) {
3,017,751✔
417
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
418
    return NULL;
×
419
  }
420

421
  code = tSerializeSCreateVnodeReq(pReq, contLen, &createReq);
3,017,751✔
422
  if (code < 0) {
3,017,751✔
423
    terrno = TSDB_CODE_APP_ERROR;
×
424
    taosMemoryFree(pReq);
×
425
    mError("vgId:%d, failed to serialize create vnode req,since %s", createReq.vgId, terrstr());
×
426
    return NULL;
×
427
  }
428
  *pContLen = contLen;
3,017,751✔
429
  return pReq;
3,017,751✔
430
}
431

432
static void *mndBuildAlterVnodeConfigReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen) {
207,657✔
433
  SAlterVnodeConfigReq alterReq = {0};
207,657✔
434
  alterReq.vgVersion = pVgroup->version;
207,657✔
435
  alterReq.buffer = pDb->cfg.buffer;
207,657✔
436
  alterReq.pageSize = pDb->cfg.pageSize;
207,657✔
437
  alterReq.pages = pDb->cfg.pages;
207,657✔
438
  alterReq.cacheLastSize = pDb->cfg.cacheLastSize;
207,657✔
439
  alterReq.daysPerFile = pDb->cfg.daysPerFile;
207,657✔
440
  alterReq.daysToKeep0 = pDb->cfg.daysToKeep0;
207,657✔
441
  alterReq.daysToKeep1 = pDb->cfg.daysToKeep1;
207,657✔
442
  alterReq.daysToKeep2 = pDb->cfg.daysToKeep2;
207,657✔
443
  alterReq.keepTimeOffset = pDb->cfg.keepTimeOffset;
207,657✔
444
  alterReq.walFsyncPeriod = pDb->cfg.walFsyncPeriod;
207,657✔
445
  alterReq.walLevel = pDb->cfg.walLevel;
207,657✔
446
  alterReq.strict = pDb->cfg.strict;
207,657✔
447
  alterReq.cacheLast = pDb->cfg.cacheLast;
207,657✔
448
  alterReq.sttTrigger = pDb->cfg.sstTrigger;
207,657✔
449
  alterReq.minRows = pDb->cfg.minRows;
207,657✔
450
  alterReq.walRetentionPeriod = pDb->cfg.walRetentionPeriod;
207,657✔
451
  alterReq.walRetentionSize = pDb->cfg.walRetentionSize;
207,657✔
452
  alterReq.ssKeepLocal = pDb->cfg.ssKeepLocal;
207,657✔
453
  alterReq.ssCompact = pDb->cfg.ssCompact;
207,657✔
454

455
  mInfo("vgId:%d, build alter vnode config req", pVgroup->vgId);
207,657✔
456
  int32_t contLen = tSerializeSAlterVnodeConfigReq(NULL, 0, &alterReq);
207,657✔
457
  if (contLen < 0) {
207,657✔
458
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
459
    return NULL;
×
460
  }
461
  contLen += sizeof(SMsgHead);
207,657✔
462

463
  void *pReq = taosMemoryMalloc(contLen);
207,657✔
464
  if (pReq == NULL) {
207,657✔
465
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
466
    return NULL;
×
467
  }
468

469
  SMsgHead *pHead = pReq;
207,657✔
470
  pHead->contLen = htonl(contLen);
207,657✔
471
  pHead->vgId = htonl(pVgroup->vgId);
207,657✔
472

473
  if (tSerializeSAlterVnodeConfigReq((char *)pReq + sizeof(SMsgHead), contLen, &alterReq) < 0) {
207,657✔
474
    taosMemoryFree(pReq);
×
475
    mError("vgId:%d, failed to serialize alter vnode config req,since %s", pVgroup->vgId, terrstr());
×
476
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
477
    return NULL;
×
478
  }
479
  *pContLen = contLen;
207,657✔
480
  return pReq;
207,657✔
481
}
482

483
static void *mndBuildAlterVnodeReplicaReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId,
791,565✔
484
                                          int32_t *pContLen) {
485
  SAlterVnodeReplicaReq alterReq = {
1,583,130✔
486
      .vgId = pVgroup->vgId,
791,565✔
487
      .strict = pDb->cfg.strict,
791,565✔
488
      .replica = 0,
489
      .learnerReplica = 0,
490
      .selfIndex = -1,
491
      .learnerSelfIndex = -1,
492
      .changeVersion = ++(pVgroup->syncConfChangeVer),
1,583,130✔
493
  };
494

495
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
3,224,788✔
496
    SReplica *pReplica = NULL;
2,433,223✔
497

498
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
2,433,223✔
499
      pReplica = &alterReq.replicas[alterReq.replica];
2,245,515✔
500
      alterReq.replica++;
2,245,515✔
501
    } else {
502
      pReplica = &alterReq.learnerReplicas[alterReq.learnerReplica];
187,708✔
503
      alterReq.learnerReplica++;
187,708✔
504
    }
505

506
    SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
2,433,223✔
507
    SDnodeObj *pVgidDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
2,433,223✔
508
    if (pVgidDnode == NULL) return NULL;
2,433,223✔
509

510
    pReplica->id = pVgidDnode->id;
2,433,223✔
511
    pReplica->port = pVgidDnode->port;
2,433,223✔
512
    memcpy(pReplica->fqdn, pVgidDnode->fqdn, TSDB_FQDN_LEN);
2,433,223✔
513
    mndReleaseDnode(pMnode, pVgidDnode);
2,433,223✔
514

515
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
2,433,223✔
516
      if (dnodeId == pVgid->dnodeId) {
2,245,515✔
517
        alterReq.selfIndex = v;
791,565✔
518
      }
519
    } else {
520
      if (dnodeId == pVgid->dnodeId) {
187,708✔
521
        alterReq.learnerSelfIndex = v;
×
522
      }
523
    }
524
  }
525

526
  mInfo(
791,565✔
527
      "vgId:%d, build alter vnode req, replica:%d selfIndex:%d learnerReplica:%d learnerSelfIndex:%d strict:%d "
528
      "changeVersion:%d",
529
      alterReq.vgId, alterReq.replica, alterReq.selfIndex, alterReq.learnerReplica, alterReq.learnerSelfIndex,
530
      alterReq.strict, alterReq.changeVersion);
531
  for (int32_t i = 0; i < alterReq.replica; ++i) {
3,037,080✔
532
    mInfo("vgId:%d, replica:%d ep:%s:%u", alterReq.vgId, i, alterReq.replicas[i].fqdn, alterReq.replicas[i].port);
2,245,515✔
533
  }
534
  for (int32_t i = 0; i < alterReq.learnerReplica; ++i) {
979,273✔
535
    mInfo("vgId:%d, learnerReplica:%d ep:%s:%u", alterReq.vgId, i, alterReq.learnerReplicas[i].fqdn,
187,708✔
536
          alterReq.learnerReplicas[i].port);
537
  }
538

539
  if (alterReq.selfIndex == -1 && alterReq.learnerSelfIndex == -1) {
791,565✔
540
    terrno = TSDB_CODE_APP_ERROR;
×
541
    return NULL;
×
542
  }
543

544
  int32_t contLen = tSerializeSAlterVnodeReplicaReq(NULL, 0, &alterReq);
791,565✔
545
  if (contLen < 0) {
791,565✔
546
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
547
    return NULL;
×
548
  }
549

550
  void *pReq = taosMemoryMalloc(contLen);
791,565✔
551
  if (pReq == NULL) {
791,565✔
552
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
553
    return NULL;
×
554
  }
555

556
  if (tSerializeSAlterVnodeReplicaReq(pReq, contLen, &alterReq) < 0) {
791,565✔
557
    mError("vgId:%d, failed to serialize alter vnode req,since %s", alterReq.vgId, terrstr());
×
558
    taosMemoryFree(pReq);
×
559
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
560
    return NULL;
×
561
  }
562
  *pContLen = contLen;
791,565✔
563
  return pReq;
791,565✔
564
}
565

566
static void *mndBuildCheckLearnCatchupReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId,
×
567
                                          int32_t *pContLen) {
568
  SCheckLearnCatchupReq req = {
×
569
      .vgId = pVgroup->vgId,
×
570
      .strict = pDb->cfg.strict,
×
571
      .replica = 0,
572
      .learnerReplica = 0,
573
      .selfIndex = -1,
574
      .learnerSelfIndex = -1,
575
  };
576

577
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
×
578
    SReplica *pReplica = NULL;
×
579

580
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
×
581
      pReplica = &req.replicas[req.replica];
×
582
      req.replica++;
×
583
    } else {
584
      pReplica = &req.learnerReplicas[req.learnerReplica];
×
585
      req.learnerReplica++;
×
586
    }
587

588
    SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
×
589
    SDnodeObj *pVgidDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
×
590
    if (pVgidDnode == NULL) return NULL;
×
591

592
    pReplica->id = pVgidDnode->id;
×
593
    pReplica->port = pVgidDnode->port;
×
594
    memcpy(pReplica->fqdn, pVgidDnode->fqdn, TSDB_FQDN_LEN);
×
595
    mndReleaseDnode(pMnode, pVgidDnode);
×
596

597
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
×
598
      if (dnodeId == pVgid->dnodeId) {
×
599
        req.selfIndex = v;
×
600
      }
601
    } else {
602
      if (dnodeId == pVgid->dnodeId) {
×
603
        req.learnerSelfIndex = v;
×
604
      }
605
    }
606
  }
607

608
  mInfo("vgId:%d, build alter vnode req, replica:%d selfIndex:%d learnerReplica:%d learnerSelfIndex:%d strict:%d",
×
609
        req.vgId, req.replica, req.selfIndex, req.learnerReplica, req.learnerSelfIndex, req.strict);
610
  for (int32_t i = 0; i < req.replica; ++i) {
×
611
    mInfo("vgId:%d, replica:%d ep:%s:%u", req.vgId, i, req.replicas[i].fqdn, req.replicas[i].port);
×
612
  }
613
  for (int32_t i = 0; i < req.learnerReplica; ++i) {
×
614
    mInfo("vgId:%d, learnerReplica:%d ep:%s:%u", req.vgId, i, req.learnerReplicas[i].fqdn, req.learnerReplicas[i].port);
×
615
  }
616

617
  if (req.selfIndex == -1 && req.learnerSelfIndex == -1) {
×
618
    terrno = TSDB_CODE_APP_ERROR;
×
619
    return NULL;
×
620
  }
621

622
  int32_t contLen = tSerializeSAlterVnodeReplicaReq(NULL, 0, &req);
×
623
  if (contLen < 0) {
×
624
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
625
    return NULL;
×
626
  }
627

628
  void *pReq = taosMemoryMalloc(contLen);
×
629
  if (pReq == NULL) {
×
630
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
631
    return NULL;
×
632
  }
633

634
  if (tSerializeSAlterVnodeReplicaReq(pReq, contLen, &req) < 0) {
×
635
    mError("vgId:%d, failed to serialize alter vnode req,since %s", req.vgId, terrstr());
×
636
    taosMemoryFree(pReq);
×
637
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
638
    return NULL;
×
639
  }
640
  *pContLen = contLen;
×
641
  return pReq;
×
642
}
643

644
static void *mndBuildDisableVnodeWriteReq(SMnode *pMnode, SDbObj *pDb, int32_t vgId, int32_t *pContLen) {
23,786✔
645
  SDisableVnodeWriteReq disableReq = {
23,786✔
646
      .vgId = vgId,
647
      .disable = 1,
648
  };
649

650
  mInfo("vgId:%d, build disable vnode write req", vgId);
23,786✔
651
  int32_t contLen = tSerializeSDisableVnodeWriteReq(NULL, 0, &disableReq);
23,786✔
652
  if (contLen < 0) {
23,786✔
653
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
654
    return NULL;
×
655
  }
656

657
  void *pReq = taosMemoryMalloc(contLen);
23,786✔
658
  if (pReq == NULL) {
23,786✔
659
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
660
    return NULL;
×
661
  }
662

663
  if (tSerializeSDisableVnodeWriteReq(pReq, contLen, &disableReq) < 0) {
23,786✔
664
    mError("vgId:%d, failed to serialize disable vnode write req,since %s", vgId, terrstr());
×
665
    taosMemoryFree(pReq);
×
666
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
667
    return NULL;
×
668
  }
669
  *pContLen = contLen;
23,786✔
670
  return pReq;
23,786✔
671
}
672

673
static void *mndBuildAlterVnodeHashRangeReq(SMnode *pMnode, int32_t srcVgId, SVgObj *pVgroup, int32_t *pContLen) {
23,786✔
674
  SAlterVnodeHashRangeReq alterReq = {
47,572✔
675
      .srcVgId = srcVgId,
676
      .dstVgId = pVgroup->vgId,
23,786✔
677
      .hashBegin = pVgroup->hashBegin,
23,786✔
678
      .hashEnd = pVgroup->hashEnd,
23,786✔
679
      .changeVersion = ++(pVgroup->syncConfChangeVer),
47,572✔
680
  };
681

682
  mInfo("vgId:%d, build alter vnode hashrange req, dstVgId:%d, hashrange:[%u, %u]", srcVgId, pVgroup->vgId,
23,786✔
683
        pVgroup->hashBegin, pVgroup->hashEnd);
684
  int32_t contLen = tSerializeSAlterVnodeHashRangeReq(NULL, 0, &alterReq);
23,786✔
685
  if (contLen < 0) {
23,786✔
686
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
687
    return NULL;
×
688
  }
689

690
  void *pReq = taosMemoryMalloc(contLen);
23,786✔
691
  if (pReq == NULL) {
23,786✔
692
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
693
    return NULL;
×
694
  }
695

696
  if (tSerializeSAlterVnodeHashRangeReq(pReq, contLen, &alterReq) < 0) {
23,786✔
697
    mError("vgId:%d, failed to serialize alter vnode hashrange req,since %s", srcVgId, terrstr());
×
698
    taosMemoryFree(pReq);
×
699
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
700
    return NULL;
×
701
  }
702
  *pContLen = contLen;
23,786✔
703
  return pReq;
23,786✔
704
}
705

706
void *mndBuildDropVnodeReq(SMnode *pMnode, SDnodeObj *pDnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen) {
4,488,700✔
707
  SDropVnodeReq dropReq = {0};
4,488,700✔
708
  dropReq.dnodeId = pDnode->id;
4,488,700✔
709
  dropReq.vgId = pVgroup->vgId;
4,488,700✔
710
  memcpy(dropReq.db, pDb->name, TSDB_DB_FNAME_LEN);
4,488,700✔
711
  dropReq.dbUid = pDb->uid;
4,488,700✔
712

713
  mInfo("vgId:%d, build drop vnode req", dropReq.vgId);
4,488,700✔
714
  int32_t contLen = tSerializeSDropVnodeReq(NULL, 0, &dropReq);
4,488,700✔
715
  if (contLen < 0) {
4,488,700✔
716
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
717
    return NULL;
×
718
  }
719

720
  void *pReq = taosMemoryMalloc(contLen);
4,488,700✔
721
  if (pReq == NULL) {
4,488,700✔
722
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
723
    return NULL;
×
724
  }
725

726
  if (tSerializeSDropVnodeReq(pReq, contLen, &dropReq) < 0) {
4,488,700✔
727
    mError("vgId:%d, failed to serialize drop vnode req,since %s", dropReq.vgId, terrstr());
×
728
    taosMemoryFree(pReq);
×
729
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
730
    return NULL;
×
731
  }
732
  *pContLen = contLen;
4,488,700✔
733
  return pReq;
4,488,700✔
734
}
735

736
static bool mndResetDnodesArrayFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
1,986,234✔
737
  SDnodeObj *pDnode = pObj;
1,986,234✔
738
  pDnode->numOfVnodes = 0;
1,986,234✔
739
  pDnode->numOfOtherNodes = 0;
1,986,234✔
740
  return true;
1,986,234✔
741
}
742

743
static bool mndBuildDnodesArrayFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
1,986,234✔
744
  SDnodeObj *pDnode = pObj;
1,986,234✔
745
  SArray    *pArray = p1;
1,986,234✔
746
  int32_t    exceptDnodeId = *(int32_t *)p2;
1,986,234✔
747
  SArray    *dnodeList = p3;
1,986,234✔
748

749
  if (exceptDnodeId == pDnode->id) {
1,986,234✔
750
    return true;
8,388✔
751
  }
752

753
  if (dnodeList != NULL) {
1,977,846✔
754
    int32_t dnodeListSize = taosArrayGetSize(dnodeList);
73,759✔
755
    if (dnodeListSize > 0) {
73,759✔
756
      bool inDnodeList = false;
73,759✔
757
      for (int32_t index = 0; index < dnodeListSize; ++index) {
240,352✔
758
        int32_t dnodeId = *(int32_t *)taosArrayGet(dnodeList, index);
166,593✔
759
        if (pDnode->id == dnodeId) {
166,593✔
760
          inDnodeList = true;
34,083✔
761
        }
762
      }
763
      if (!inDnodeList) {
73,759✔
764
        return true;
39,676✔
765
      }
766
    } else {
767
      return true;  // TS-6191
×
768
    }
769
  }
770

771
  int64_t curMs = taosGetTimestampMs();
1,938,170✔
772
  bool    online = mndIsDnodeOnline(pDnode, curMs);
1,938,170✔
773
  bool    isMnode = mndIsMnode(pMnode, pDnode->id);
1,938,170✔
774
  pDnode->numOfVnodes = mndGetVnodesNum(pMnode, pDnode->id);
1,938,170✔
775
  pDnode->memUsed = mndGetVnodesMemory(pMnode, pDnode->id);
1,938,170✔
776

777
  mInfo("dnode:%d, vnodes:%d supportVnodes:%d isMnode:%d online:%d memory avail:%" PRId64 " used:%" PRId64, pDnode->id,
1,938,170✔
778
        pDnode->numOfVnodes, pDnode->numOfSupportVnodes, isMnode, online, pDnode->memAvail, pDnode->memUsed);
779

780
  if (isMnode) {
1,938,170✔
781
    pDnode->numOfOtherNodes++;
1,406,358✔
782
  }
783

784
  if (online && pDnode->numOfSupportVnodes > 0) {
1,938,170✔
785
    if (taosArrayPush(pArray, pDnode) == NULL) return false;
1,890,108✔
786
  }
787
  return true;
1,938,170✔
788
}
789

790
static bool isDnodeInList(SArray *dnodeList, int32_t dnodeId) {
×
791
  int32_t dnodeListSize = taosArrayGetSize(dnodeList);
×
792
  for (int32_t i = 0; i < dnodeListSize; ++i) {
×
793
    int32_t id = *(int32_t *)TARRAY_GET_ELEM(dnodeList, i);
×
794
    if (id == dnodeId) {
×
795
      return true;
×
796
    }
797
  }
798
  return false;
×
799
}
800

801
#ifdef TD_ENTERPRISE
802
static float mndGetDnodeScore1(SDnodeObj *pDnode, int32_t additionDnodes, float ratio) {
×
803
  float totalDnodes = pDnode->numOfVnodes + (float)pDnode->numOfOtherNodes * ratio + additionDnodes;
×
804
  float result = totalDnodes / pDnode->numOfSupportVnodes;
×
805
  return pDnode->numOfVnodes > 0 ? -result : result;
×
806
}
807

808
static int32_t mndCompareDnodeVnodes1(SDnodeObj *pDnode1, SDnodeObj *pDnode2) {
×
809
  float d1Score = mndGetDnodeScore1(pDnode1, 0, 0.9);
×
810
  float d2Score = mndGetDnodeScore1(pDnode2, 0, 0.9);
×
811
  if (d1Score == d2Score) {
×
812
    if (pDnode1->id == pDnode2->id) {
×
813
      return 0;
×
814
    }
815
    return pDnode1->id > pDnode2->id ? 1 : -1;
×
816
  }
817
  return d1Score > d2Score ? 1 : -1;
×
818
}
819

820
static bool mndBuildDnodesListFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
×
821
  SDnodeObj *pDnode = pObj;
×
822
  SArray    *pArray = p1;
×
823

824
  bool isMnode = mndIsMnode(pMnode, pDnode->id);
×
825
  pDnode->numOfVnodes = mndGetVnodesNum(pMnode, pDnode->id);
×
826

827
  if (isMnode) {
×
828
    pDnode->numOfOtherNodes++;
×
829
  }
830

831
  if (pDnode->numOfSupportVnodes > 0) {
×
832
    if (taosArrayPush(pArray, pDnode) == NULL) return false;
×
833
  }
834
  return true;
×
835
}
836

837
// TS-6191
838
static int32_t mndBuildNodesCheckDualReplica(SMnode *pMnode, int32_t nDnodes, SArray *dnodeList, SArray **ppDnodeList) {
1,338,273✔
839
  int32_t code = 0;
1,338,273✔
840
  if (!grantCheckDualReplicaDnodes(pMnode)) {
1,338,273✔
841
    TAOS_RETURN(code);
1,338,273✔
842
  }
843
  SSdb   *pSdb = pMnode->pSdb;
×
844
  SArray *pArray = taosArrayInit(nDnodes, sizeof(SDnodeObj));
×
845
  if (pArray == NULL) {
×
846
    TAOS_RETURN(code = terrno);
×
847
  }
848
  *ppDnodeList = pArray;
×
849

850
  sdbTraverse(pSdb, SDB_DNODE, mndResetDnodesArrayFp, NULL, NULL, NULL);
×
851
  sdbTraverse(pSdb, SDB_DNODE, mndBuildDnodesListFp, pArray, NULL, NULL);
×
852

853
  int32_t arrSize = taosArrayGetSize(pArray);
×
854
  if (arrSize <= 0) {
×
855
    TAOS_RETURN(code);
×
856
  }
857
  if (arrSize > 1) taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes1);
×
858

859
  int32_t dnodeListSize = taosArrayGetSize(dnodeList);
×
860
  if (dnodeListSize <= 0) {
×
861
    if (arrSize > 2) taosArrayRemoveBatch(pArray, 2, arrSize - 2, NULL);
×
862
  } else {
863
    int32_t nDnodesWithVnodes = 0;
×
864
    for (int32_t i = 0; i < arrSize; ++i) {
×
865
      SDnodeObj *pDnode = TARRAY_GET_ELEM(pArray, i);
×
866
      if (pDnode->numOfVnodes <= 0) {
×
867
        break;
×
868
      }
869
      ++nDnodesWithVnodes;
×
870
    }
871
    int32_t dnodeId = -1;
×
872
    if (nDnodesWithVnodes == 1) {
×
873
      dnodeId = ((SDnodeObj *)TARRAY_GET_ELEM(pArray, 0))->id;
×
874
    } else if (nDnodesWithVnodes >= 2) {
×
875
      // must select the dnodes from the 1st 2 dnodes
876
      taosArrayRemoveBatch(pArray, 2, arrSize - 2, NULL);
×
877
    }
878
    for (int32_t i = 0; i < TARRAY_SIZE(pArray);) {
×
879
      SDnodeObj *pDnode = taosArrayGet(pArray, i);
×
880
      if (!isDnodeInList(dnodeList, pDnode->id)) {
×
881
        taosArrayRemove(pArray, i);
×
882
        continue;
×
883
      }
884
      ++i;
×
885
    }
886
    if (nDnodesWithVnodes == 1) {
×
887
      SDnodeObj *pDnode = taosArrayGet(pArray, 0);
×
888
      if (pDnode && (pDnode->id != dnodeId)) {  // the first dnode is not in dnodeList, remove the last element
×
889
        taosArrayRemove(pArray, taosArrayGetSize(pArray) - 1);
×
890
      }
891
    }
892
  }
893

894
  TAOS_RETURN(code);
×
895
}
896
#endif
897

898
SArray *mndBuildDnodesArray(SMnode *pMnode, int32_t exceptDnodeId, SArray *dnodeList) {
1,338,273✔
899
  SSdb   *pSdb = pMnode->pSdb;
1,338,273✔
900
  int32_t numOfDnodes = mndGetDnodeSize(pMnode);
1,338,273✔
901
  SArray *tDnodeList = NULL;
1,338,273✔
902
  SArray *pDnodeList = NULL;
1,338,273✔
903

904
  SArray *pArray = taosArrayInit(numOfDnodes, sizeof(SDnodeObj));
1,338,273✔
905
  if (pArray == NULL) {
1,338,273✔
906
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
907
    return NULL;
×
908
  }
909
  if (taosArrayGetSize(dnodeList) > 0) {
1,338,273✔
910
    tDnodeList = dnodeList;
15,134✔
911
  }
912
#ifdef TD_ENTERPRISE
913
  if (0 != mndBuildNodesCheckDualReplica(pMnode, numOfDnodes, tDnodeList, &pDnodeList)) {
1,338,273✔
914
    taosArrayDestroy(pArray);
×
915
    return NULL;
×
916
  }
917
#endif
918
  sdbTraverse(pSdb, SDB_DNODE, mndResetDnodesArrayFp, NULL, NULL, NULL);
1,338,273✔
919
  sdbTraverse(pSdb, SDB_DNODE, mndBuildDnodesArrayFp, pArray, &exceptDnodeId, pDnodeList ? pDnodeList : tDnodeList);
1,338,273✔
920

921
  mDebug("build %d dnodes array", (int32_t)taosArrayGetSize(pArray));
1,338,273✔
922
  for (int32_t i = 0; i < (int32_t)taosArrayGetSize(pArray); ++i) {
3,228,381✔
923
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
1,890,108✔
924
    mDebug("dnode:%d, vnodes:%d others:%d", pDnode->id, pDnode->numOfVnodes, pDnode->numOfOtherNodes);
1,890,108✔
925
  }
926
  taosArrayDestroy(pDnodeList);
1,338,273✔
927
  return pArray;
1,338,273✔
928
}
929

930
static int32_t mndCompareDnodeId(int32_t *dnode1Id, int32_t *dnode2Id) {
×
931
  if (*dnode1Id == *dnode2Id) {
×
932
    return 0;
×
933
  }
934
  return *dnode1Id > *dnode2Id ? 1 : -1;
×
935
}
936

937
static float mndGetDnodeScore(SDnodeObj *pDnode, int32_t additionDnodes, float ratio) {
10,798,670✔
938
  float totalDnodes = pDnode->numOfVnodes + (float)pDnode->numOfOtherNodes * ratio + additionDnodes;
10,798,670✔
939
  return totalDnodes / pDnode->numOfSupportVnodes;
10,798,670✔
940
}
941

942
static int32_t mndCompareDnodeVnodes(SDnodeObj *pDnode1, SDnodeObj *pDnode2) {
3,508,481✔
943
  float d1Score = mndGetDnodeScore(pDnode1, 0, 0.9);
3,508,481✔
944
  float d2Score = mndGetDnodeScore(pDnode2, 0, 0.9);
3,508,481✔
945
  if (d1Score == d2Score) {
3,508,481✔
946
    return 0;
1,300,645✔
947
  }
948
  return d1Score > d2Score ? 1 : -1;
2,207,836✔
949
}
950

951
void mndSortVnodeGid(SVgObj *pVgroup) {
2,580,161✔
952
  for (int32_t i = 0; i < pVgroup->replica; ++i) {
5,538,289✔
953
    for (int32_t j = 0; j < pVgroup->replica - 1 - i; ++j) {
3,521,122✔
954
      if (pVgroup->vnodeGid[j].dnodeId > pVgroup->vnodeGid[j + 1].dnodeId) {
562,994✔
955
        TSWAP(pVgroup->vnodeGid[j], pVgroup->vnodeGid[j + 1]);
213,322✔
956
      }
957
    }
958
  }
959
}
2,580,161✔
960

961
static int32_t mndGetAvailableDnode(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, SArray *pArray) {
2,550,809✔
962
  mDebug("start to sort %d dnodes", (int32_t)taosArrayGetSize(pArray));
2,550,809✔
963
  taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
2,550,809✔
964
  for (int32_t i = 0; i < (int32_t)taosArrayGetSize(pArray); ++i) {
6,241,036✔
965
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
3,690,227✔
966
    mDebug("dnode:%d, score:%f", pDnode->id, mndGetDnodeScore(pDnode, 0, 0.9));
3,690,227✔
967
  }
968

969
  int32_t size = taosArrayGetSize(pArray);
2,550,809✔
970
  if (size < pVgroup->replica) {
2,550,809✔
971
    mError("db:%s, vgId:%d, no enough online dnodes:%d to alloc %d replica", pVgroup->dbName, pVgroup->vgId, size,
5,391✔
972
           pVgroup->replica);
973
    TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_DNODES);
5,391✔
974
  }
975

976
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
5,409,985✔
977
    SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
2,864,567✔
978
    SDnodeObj *pDnode = taosArrayGet(pArray, v);
2,864,567✔
979
    if (pDnode == NULL) {
2,864,567✔
980
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_DNODES);
×
981
    }
982
    if (pDnode->numOfVnodes >= pDnode->numOfSupportVnodes) {
2,864,567✔
983
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_VNODES);
×
984
    }
985

986
    int64_t vgMem = mndGetVgroupMemory(pMnode, pDb, pVgroup);
2,864,567✔
987
    if (pDnode->memAvail - vgMem - pDnode->memUsed <= 0) {
2,864,567✔
988
      mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d, avail:%" PRId64 " used:%" PRId64,
×
989
             pVgroup->dbName, pVgroup->vgId, vgMem, pDnode->id, pDnode->memAvail, pDnode->memUsed);
990
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE);
×
991
    } else {
992
      pDnode->memUsed += vgMem;
2,864,567✔
993
    }
994

995
    pVgid->dnodeId = pDnode->id;
2,864,567✔
996
    if (pVgroup->replica == 1) {
2,864,567✔
997
      pVgid->syncState = TAOS_SYNC_STATE_LEADER;
2,382,626✔
998
    } else {
999
      pVgid->syncState = TAOS_SYNC_STATE_FOLLOWER;
481,941✔
1000
    }
1001

1002
    mInfo("db:%s, vgId:%d, vn:%d is alloced, memory:%" PRId64 ", dnode:%d avail:%" PRId64 " used:%" PRId64,
2,864,567✔
1003
          pVgroup->dbName, pVgroup->vgId, v, vgMem, pVgid->dnodeId, pDnode->memAvail, pDnode->memUsed);
1004
    pDnode->numOfVnodes++;
2,864,567✔
1005
  }
1006

1007
  mndSortVnodeGid(pVgroup);
2,545,418✔
1008
  return 0;
2,545,418✔
1009
}
1010

1011
int32_t mndAllocSmaVgroup(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup) {
×
1012
  int32_t code = 0;
×
1013
  SArray *pArray = mndBuildDnodesArray(pMnode, 0, NULL);
×
1014
  if (pArray == NULL) {
×
1015
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1016
    if (terrno != 0) code = terrno;
×
1017
    TAOS_RETURN(code);
×
1018
  }
1019

1020
  pVgroup->vgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP);
×
1021
  pVgroup->isTsma = 1;
×
1022
  pVgroup->createdTime = taosGetTimestampMs();
×
1023
  pVgroup->updateTime = pVgroup->createdTime;
×
1024
  pVgroup->version = 1;
×
1025
  memcpy(pVgroup->dbName, pDb->name, TSDB_DB_FNAME_LEN);
×
1026
  pVgroup->dbUid = pDb->uid;
×
1027
  pVgroup->replica = 1;
×
1028
  pVgroup->keepVersion = -1;  // default: WAL keep version disabled
×
1029
  pVgroup->keepVersionTime = 0;
×
1030

1031
  if (mndGetAvailableDnode(pMnode, pDb, pVgroup, pArray) != 0) return -1;
×
1032
  taosArrayDestroy(pArray);
×
1033

1034
  mInfo("db:%s, sma vgId:%d is alloced", pDb->name, pVgroup->vgId);
×
1035
  return 0;
×
1036
}
1037

1038
int32_t mndAllocVgroup(SMnode *pMnode, SDbObj *pDb, SVgObj **ppVgroups, SArray *dnodeList) {
1,209,773✔
1039
  int32_t code = -1;
1,209,773✔
1040
  SArray *pArray = NULL;
1,209,773✔
1041
  SVgObj *pVgroups = NULL;
1,209,773✔
1042

1043
  pVgroups = taosMemoryCalloc(pDb->cfg.numOfVgroups, sizeof(SVgObj));
1,209,773✔
1044
  if (pVgroups == NULL) {
1,209,773✔
1045
    code = terrno;
×
1046
    goto _OVER;
×
1047
  }
1048

1049
  pArray = mndBuildDnodesArray(pMnode, 0, dnodeList);
1,209,773✔
1050
  if (pArray == NULL) {
1,209,773✔
1051
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1052
    if (terrno != 0) code = terrno;
×
1053
    goto _OVER;
×
1054
  }
1055

1056
  mInfo("db:%s, total %d dnodes used to create %d vgroups (%d vnodes)", pDb->name, (int32_t)taosArrayGetSize(pArray),
1,209,773✔
1057
        pDb->cfg.numOfVgroups, pDb->cfg.numOfVgroups * pDb->cfg.replications);
1058

1059
  int32_t  allocedVgroups = 0;
1,209,773✔
1060
  int32_t  maxVgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP);
1,209,773✔
1061
  uint32_t hashMin = 0;
1,209,773✔
1062
  uint32_t hashMax = UINT32_MAX;
1,209,773✔
1063
  uint32_t hashInterval = (hashMax - hashMin) / pDb->cfg.numOfVgroups;
1,209,773✔
1064

1065
  if (maxVgId < 2) maxVgId = 2;
1,209,773✔
1066

1067
  for (uint32_t v = 0; v < pDb->cfg.numOfVgroups; v++) {
3,755,191✔
1068
    SVgObj *pVgroup = &pVgroups[v];
2,550,809✔
1069
    pVgroup->vgId = maxVgId++;
2,550,809✔
1070
    pVgroup->createdTime = taosGetTimestampMs();
2,550,809✔
1071
    pVgroup->updateTime = pVgroups->createdTime;
2,550,809✔
1072
    pVgroup->version = 1;
2,550,809✔
1073
    pVgroup->hashBegin = hashMin + hashInterval * v;
2,550,809✔
1074
    if (v == pDb->cfg.numOfVgroups - 1) {
2,550,809✔
1075
      pVgroup->hashEnd = hashMax;
1,206,950✔
1076
    } else {
1077
      pVgroup->hashEnd = hashMin + hashInterval * (v + 1) - 1;
1,343,859✔
1078
    }
1079

1080
    memcpy(pVgroup->dbName, pDb->name, TSDB_DB_FNAME_LEN);
2,550,809✔
1081
    pVgroup->dbUid = pDb->uid;
2,550,809✔
1082
    pVgroup->replica = pDb->cfg.replications;
2,550,809✔
1083
    pVgroup->keepVersion = -1;  // default: WAL keep version disabled
2,550,809✔
1084
    pVgroup->keepVersionTime = 0;
2,550,809✔
1085

1086
    if ((code = mndGetAvailableDnode(pMnode, pDb, pVgroup, pArray)) != 0) {
2,550,809✔
1087
      goto _OVER;
5,391✔
1088
    }
1089

1090
    allocedVgroups++;
2,545,418✔
1091
  }
1092

1093
  *ppVgroups = pVgroups;
1,204,382✔
1094
  code = 0;
1,204,382✔
1095

1096
  mInfo("db:%s, total %d vgroups is alloced, replica:%d", pDb->name, pDb->cfg.numOfVgroups, pDb->cfg.replications);
1,204,382✔
1097

1098
_OVER:
×
1099
  if (code != 0) taosMemoryFree(pVgroups);
1,209,773✔
1100
  taosArrayDestroy(pArray);
1,209,773✔
1101
  TAOS_RETURN(code);
1,209,773✔
1102
}
1103

1104
SEpSet mndGetVgroupEpset(SMnode *pMnode, const SVgObj *pVgroup) {
26,202,263✔
1105
  SEpSet epset = {0};
26,202,263✔
1106

1107
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
60,036,756✔
1108
    const SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
33,834,493✔
1109
    SDnodeObj       *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
33,834,493✔
1110
    if (pDnode == NULL) continue;
33,834,493✔
1111

1112
    if (pVgid->syncState == TAOS_SYNC_STATE_LEADER || pVgid->syncState == TAOS_SYNC_STATE_ASSIGNED_LEADER) {
33,816,485✔
1113
      epset.inUse = epset.numOfEps;
25,879,692✔
1114
    }
1115

1116
    if (addEpIntoEpSet(&epset, pDnode->fqdn, pDnode->port) != 0) {
33,816,485✔
1117
      mWarn("vgId:%d, failed to add ep:%s:%d into epset", pVgroup->vgId, pDnode->fqdn, pDnode->port);
×
1118
    }
1119
    mndReleaseDnode(pMnode, pDnode);
33,816,485✔
1120
  }
1121
  epsetSort(&epset);
26,202,263✔
1122

1123
  return epset;
26,202,263✔
1124
}
1125

1126
SEpSet mndGetVgroupEpsetById(SMnode *pMnode, int32_t vgId) {
637,840✔
1127
  SEpSet epset = {0};
637,840✔
1128

1129
  SVgObj *pVgroup = mndAcquireVgroup(pMnode, vgId);
637,840✔
1130
  if (!pVgroup) return epset;
637,840✔
1131

1132
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
1,344,773✔
1133
    const SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
706,933✔
1134
    SDnodeObj       *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
706,933✔
1135
    if (pDnode == NULL) continue;
706,933✔
1136

1137
    if (pVgid->syncState == TAOS_SYNC_STATE_LEADER || pVgid->syncState == TAOS_SYNC_STATE_ASSIGNED_LEADER) {
706,933✔
1138
      epset.inUse = epset.numOfEps;
607,342✔
1139
    }
1140

1141
    if (addEpIntoEpSet(&epset, pDnode->fqdn, pDnode->port) != 0) {
706,933✔
1142
      mWarn("vgId:%d, failed to add ep:%s:%d into epset", pVgroup->vgId, pDnode->fqdn, pDnode->port);
×
1143
    }
1144
    mndReleaseDnode(pMnode, pDnode);
706,933✔
1145
  }
1146

1147
  mndReleaseVgroup(pMnode, pVgroup);
637,840✔
1148
  return epset;
637,840✔
1149
}
1150

1151
static int32_t mndRetrieveVgroups(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
294,264✔
1152
  SMnode *pMnode = pReq->info.node;
294,264✔
1153
  SSdb   *pSdb = pMnode->pSdb;
294,264✔
1154
  int32_t numOfRows = 0;
294,264✔
1155
  SVgObj *pVgroup = NULL;
294,264✔
1156
  int32_t cols = 0;
294,264✔
1157
  int64_t curMs = taosGetTimestampMs();
294,264✔
1158
  int32_t code = 0, lino = 0;
294,264✔
1159

1160
  SDbObj *pDb = NULL;
294,264✔
1161
  if (strlen(pShow->db) > 0) {
294,264✔
1162
    pDb = mndAcquireDb(pMnode, pShow->db);
246,650✔
1163
    if (pDb == NULL) {
246,650✔
1164
      return 0;
×
1165
    }
1166
  }
1167

1168
  while (numOfRows < rows) {
1,622,734✔
1169
    pShow->pIter = sdbFetch(pSdb, SDB_VGROUP, pShow->pIter, (void **)&pVgroup);
1,622,734✔
1170
    if (pShow->pIter == NULL) break;
1,622,734✔
1171

1172
    if (pDb != NULL && pVgroup->dbUid != pDb->uid) {
1,328,470✔
1173
      sdbRelease(pSdb, pVgroup);
436,806✔
1174
      continue;
436,806✔
1175
    }
1176

1177
    cols = 0;
891,664✔
1178
    SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
891,664✔
1179
    COL_DATA_SET_VAL_GOTO((const char *)&pVgroup->vgId, false, pVgroup, pShow->pIter, _OVER);
891,664✔
1180

1181
    SName name = {0};
891,664✔
1182
    char  db[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
891,664✔
1183
    code = tNameFromString(&name, pVgroup->dbName, T_NAME_ACCT | T_NAME_DB);
891,664✔
1184
    if (code != 0) {
891,664✔
1185
      mError("vgId:%d, failed to set dbName, since %s", pVgroup->vgId, tstrerror(code));
×
1186
      sdbRelease(pSdb, pVgroup);
×
1187
      sdbCancelFetch(pSdb, pShow->pIter);
×
1188
      return code;
×
1189
    }
1190
    (void)tNameGetDbName(&name, varDataVal(db));
891,664✔
1191
    varDataSetLen(db, strlen(varDataVal(db)));
891,664✔
1192

1193
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
891,664✔
1194
    COL_DATA_SET_VAL_GOTO((const char *)db, false, pVgroup, pShow->pIter, _OVER);
891,664✔
1195

1196
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
891,664✔
1197
    COL_DATA_SET_VAL_GOTO((const char *)&pVgroup->numOfTables, false, pVgroup, pShow->pIter, _OVER);
891,664✔
1198

1199
    bool isReady = false;
891,664✔
1200
    bool isLeaderRestored = false;
891,664✔
1201
    bool hasFollowerRestored = false;
891,664✔
1202
    ESyncState leaderState = TAOS_SYNC_STATE_OFFLINE;
891,664✔
1203
    // default 3 replica, add 1 replica if move vnode
1204
    for (int32_t i = 0; i < 4; ++i) {
4,458,320✔
1205
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
3,566,656✔
1206
      if (i < pVgroup->replica) {
3,566,656✔
1207
        int16_t dnodeId = (int16_t)pVgroup->vnodeGid[i].dnodeId;
1,850,840✔
1208
        COL_DATA_SET_VAL_GOTO((const char *)&dnodeId, false, pVgroup, pShow->pIter, _OVER);
1,850,840✔
1209

1210
        bool       exist = false;
1,850,840✔
1211
        bool       online = false;
1,850,840✔
1212
        SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgroup->vnodeGid[i].dnodeId);
1,850,840✔
1213
        if (pDnode != NULL) {
1,850,840✔
1214
          exist = true;
1,850,840✔
1215
          online = mndIsDnodeOnline(pDnode, curMs);
1,850,840✔
1216
          mndReleaseDnode(pMnode, pDnode);
1,850,840✔
1217
        }
1218

1219
        char buf1[20] = {0};
1,850,840✔
1220
        char role[20] = "offline";
1,850,840✔
1221
        if (!exist) {
1,850,840✔
UNCOV
1222
          tstrncpy(role, "dropping", sizeof(role));
×
1223
        } else if (online) {
1,850,840✔
1224
          if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_LEADER ||
1,816,216✔
1225
              pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_ASSIGNED_LEADER) {
1,119,943✔
1226
            if (pVgroup->vnodeGid[i].syncRestore) {
696,273✔
1227
              isLeaderRestored = true;
589,331✔
1228
            }
1229
          } else if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_FOLLOWER) {
1,119,943✔
1230
            if (pVgroup->vnodeGid[i].syncRestore) {
913,918✔
1231
              hasFollowerRestored = true;
521,400✔
1232
            }
1233
          }
1234
          if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_LEADER ||
1,816,216✔
1235
              pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_ASSIGNED_LEADER)
1,119,943✔
1236
            leaderState = pVgroup->vnodeGid[i].syncState;
696,273✔
1237
          snprintf(role, sizeof(role), "%s", syncStr(pVgroup->vnodeGid[i].syncState));
1,816,216✔
1238
          /*
1239
          mInfo("db:%s, learner progress:%d", pDb->name, pVgroup->vnodeGid[i].learnerProgress);
1240

1241
          if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_LEARNER) {
1242
            if(pVgroup->vnodeGid[i].learnerProgress < 0){
1243
              snprintf(role, sizeof(role), "%s-",
1244
                syncStr(pVgroup->vnodeGid[i].syncState));
1245

1246
            }
1247
            else if(pVgroup->vnodeGid[i].learnerProgress >= 100){
1248
              snprintf(role, sizeof(role), "%s--",
1249
                syncStr(pVgroup->vnodeGid[i].syncState));
1250
            }
1251
            else{
1252
              snprintf(role, sizeof(role), "%s%d",
1253
                syncStr(pVgroup->vnodeGid[i].syncState), pVgroup->vnodeGid[i].learnerProgress);
1254
            }
1255
          }
1256
          else{
1257
            snprintf(role, sizeof(role), "%s%s", syncStr(pVgroup->vnodeGid[i].syncState), star);
1258
          }
1259
          */
1260
        } else {
1261
        }
1262
        STR_WITH_MAXSIZE_TO_VARSTR(buf1, role, pShow->pMeta->pSchemas[cols].bytes);
1,850,840✔
1263

1264
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,850,840✔
1265
        COL_DATA_SET_VAL_GOTO((const char *)buf1, false, pVgroup, pShow->pIter, _OVER);
1,850,840✔
1266

1267
        char applyStr[TSDB_SYNC_APPLY_COMMIT_LEN + 1] = {0};
1,850,840✔
1268
        char buf[TSDB_SYNC_APPLY_COMMIT_LEN + VARSTR_HEADER_SIZE + 1] = {0};
1,850,840✔
1269
        snprintf(applyStr, sizeof(applyStr), "%" PRId64 "/%" PRId64, pVgroup->vnodeGid[i].syncAppliedIndex,
1,850,840✔
1270
                 pVgroup->vnodeGid[i].syncCommitIndex);
1,850,840✔
1271
        STR_WITH_MAXSIZE_TO_VARSTR(buf, applyStr, pShow->pMeta->pSchemas[cols].bytes);
1,850,840✔
1272

1273
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,850,840✔
1274
        COL_DATA_SET_VAL_GOTO((const char *)&buf, false, pVgroup, pShow->pIter, _OVER);
1,850,840✔
1275
      } else {
1276
        colDataSetNULL(pColInfo, numOfRows);
1,715,816✔
1277
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,715,816✔
1278
        colDataSetNULL(pColInfo, numOfRows);
1,715,816✔
1279
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,715,816✔
1280
        colDataSetNULL(pColInfo, numOfRows);
1,715,816✔
1281
      }
1282
    }
1283

1284
    if (pVgroup->replica >= 3) {
891,664✔
1285
      if (isLeaderRestored && hasFollowerRestored) isReady = true;
389,611✔
1286
    } else if (pVgroup->replica == 2) {
502,053✔
1287
      if (leaderState == TAOS_SYNC_STATE_LEADER) {
179,954✔
1288
        if (isLeaderRestored && hasFollowerRestored) isReady = true;
101,422✔
1289
      } else if (leaderState == TAOS_SYNC_STATE_ASSIGNED_LEADER) {
78,532✔
NEW
1290
        if (isLeaderRestored) isReady = true;
×
1291
      }
1292
    } else {
1293
      if (isLeaderRestored) isReady = true;
322,099✔
1294
    }
1295
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
891,664✔
1296
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&isReady, false);
891,664✔
1297
    if (code != 0) {
891,664✔
NEW
1298
      mError("vgId:%d, failed to set is_ready, since %s", pVgroup->vgId, tstrerror(code));
×
NEW
1299
      return code;
×
1300
    }
1301

1302
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
891,664✔
1303
    int32_t cacheUsage = (int32_t)pVgroup->cacheUsage;
891,664✔
1304
    COL_DATA_SET_VAL_GOTO((const char *)&cacheUsage, false, pVgroup, pShow->pIter, _OVER);
891,664✔
1305

1306
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
891,664✔
1307
    COL_DATA_SET_VAL_GOTO((const char *)&pVgroup->numOfCachedTables, false, pVgroup, pShow->pIter, _OVER);
891,664✔
1308

1309
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
891,664✔
1310
    COL_DATA_SET_VAL_GOTO((const char *)&pVgroup->isTsma, false, pVgroup, pShow->pIter, _OVER);
891,664✔
1311

1312
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
891,664✔
1313
    COL_DATA_SET_VAL_GOTO((const char *)&pVgroup->mountVgId, false, pVgroup, pShow->pIter, _OVER);
891,664✔
1314

1315
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
891,664✔
1316
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->keepVersion, false);
891,664✔
1317
    if (code != 0) {
891,664✔
UNCOV
1318
      mError("vgId:%d, failed to set keepVersion, since %s", pVgroup->vgId, tstrerror(code));
×
UNCOV
1319
      return code;
×
1320
    }
1321

1322
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
891,664✔
1323
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->keepVersionTime, false);
891,664✔
1324
    if (code != 0) {
891,664✔
UNCOV
1325
      mError("vgId:%d, failed to set keepVersionTime, since %s", pVgroup->vgId, tstrerror(code));
×
UNCOV
1326
      return code;
×
1327
    }
1328

1329
    numOfRows++;
891,664✔
1330
    sdbRelease(pSdb, pVgroup);
891,664✔
1331
  }
1332
_OVER:
294,264✔
1333
  if (pDb != NULL) {
294,264✔
1334
    mndReleaseDb(pMnode, pDb);
246,650✔
1335
  }
1336
  if (code != 0) {
294,264✔
UNCOV
1337
    mError("failed to retrieve vgroup info at line %d since %s", lino, tstrerror(code));
×
UNCOV
1338
    TAOS_RETURN(code);
×
1339
  }
1340

1341
  pShow->numOfRows += numOfRows;
294,264✔
1342
  return numOfRows;
294,264✔
1343
}
1344

UNCOV
1345
static void mndCancelGetNextVgroup(SMnode *pMnode, void *pIter) {
×
UNCOV
1346
  SSdb *pSdb = pMnode->pSdb;
×
UNCOV
1347
  sdbCancelFetchByType(pSdb, pIter, SDB_VGROUP);
×
UNCOV
1348
}
×
1349

1350
static bool mndGetVnodesNumFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
12,031,818✔
1351
  SVgObj  *pVgroup = pObj;
12,031,818✔
1352
  int32_t  dnodeId = *(int32_t *)p1;
12,031,818✔
1353
  int32_t *pNumOfVnodes = (int32_t *)p2;
12,031,818✔
1354

1355
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
34,027,404✔
1356
    if (pVgroup->vnodeGid[v].dnodeId == dnodeId) {
21,995,586✔
1357
      (*pNumOfVnodes)++;
7,021,708✔
1358
    }
1359
  }
1360

1361
  return true;
12,031,818✔
1362
}
1363

1364
int32_t mndGetVnodesNum(SMnode *pMnode, int32_t dnodeId) {
4,375,006✔
1365
  int32_t numOfVnodes = 0;
4,375,006✔
1366
  sdbTraverse(pMnode->pSdb, SDB_VGROUP, mndGetVnodesNumFp, &dnodeId, &numOfVnodes, NULL);
4,375,006✔
1367
  return numOfVnodes;
4,375,006✔
1368
}
1369

1370
int64_t mndGetVgroupMemory(SMnode *pMnode, SDbObj *pDbInput, SVgObj *pVgroup) {
7,821,541✔
1371
  SDbObj *pDb = pDbInput;
7,821,541✔
1372
  if (pDbInput == NULL) {
7,821,541✔
1373
    pDb = mndAcquireDb(pMnode, pVgroup->dbName);
4,325,156✔
1374
  }
1375

1376
  int64_t vgroupMemroy = 0;
7,821,541✔
1377
  if (pDb != NULL) {
7,821,541✔
1378
    int64_t buffer = (int64_t)pDb->cfg.buffer * 1024 * 1024;
7,821,541✔
1379
    int64_t cache = (int64_t)pDb->cfg.pages * pDb->cfg.pageSize * 1024;
7,821,541✔
1380
    vgroupMemroy = buffer + cache;
7,821,541✔
1381
    int64_t cacheLast = (int64_t)pDb->cfg.cacheLastSize * 1024 * 1024;
7,821,541✔
1382
    if (pDb->cfg.cacheLast > 0) {
7,821,541✔
1383
      vgroupMemroy += cacheLast;
966,735✔
1384
    }
1385
    mDebug("db:%s, vgroup:%d, buffer:%" PRId64 " cache:%" PRId64 " cacheLast:%" PRId64, pDb->name, pVgroup->vgId,
7,821,541✔
1386
           buffer, cache, cacheLast);
1387
  }
1388

1389
  if (pDbInput == NULL) {
7,821,541✔
1390
    mndReleaseDb(pMnode, pDb);
4,325,156✔
1391
  }
1392
  return vgroupMemroy;
7,821,541✔
1393
}
1394

1395
static bool mndGetVnodeMemroyFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
6,162,130✔
1396
  SVgObj  *pVgroup = pObj;
6,162,130✔
1397
  int32_t  dnodeId = *(int32_t *)p1;
6,162,130✔
1398
  int64_t *pVnodeMemory = (int64_t *)p2;
6,162,130✔
1399

1400
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
15,113,554✔
1401
    if (pVgroup->vnodeGid[v].dnodeId == dnodeId) {
8,951,424✔
1402
      *pVnodeMemory += mndGetVgroupMemory(pMnode, NULL, pVgroup);
4,179,192✔
1403
    }
1404
  }
1405

1406
  return true;
6,162,130✔
1407
}
1408

1409
int64_t mndGetVnodesMemory(SMnode *pMnode, int32_t dnodeId) {
1,938,812✔
1410
  int64_t vnodeMemory = 0;
1,938,812✔
1411
  sdbTraverse(pMnode->pSdb, SDB_VGROUP, mndGetVnodeMemroyFp, &dnodeId, &vnodeMemory, NULL);
1,938,812✔
1412
  return vnodeMemory;
1,938,812✔
1413
}
1414

UNCOV
1415
void calculateRstoreFinishTime(double rate, int64_t applyCount, char *restoreStr, size_t restoreStrSize) {
×
UNCOV
1416
  if (rate == 0) {
×
UNCOV
1417
    snprintf(restoreStr, restoreStrSize, "0:0:0");
×
UNCOV
1418
    return;
×
1419
  }
1420

UNCOV
1421
  int64_t costTime = applyCount / rate;
×
UNCOV
1422
  int64_t totalSeconds = costTime / 1000;
×
UNCOV
1423
  int64_t hours = totalSeconds / 3600;
×
UNCOV
1424
  totalSeconds %= 3600;
×
UNCOV
1425
  int64_t minutes = totalSeconds / 60;
×
UNCOV
1426
  int64_t seconds = totalSeconds % 60;
×
UNCOV
1427
  snprintf(restoreStr, restoreStrSize, "%" PRId64 ":%" PRId64 ":%" PRId64, hours, minutes, seconds);
×
1428
}
1429

1430
static int32_t mndRetrieveVnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
2,385✔
1431
  SMnode *pMnode = pReq->info.node;
2,385✔
1432
  SSdb   *pSdb = pMnode->pSdb;
2,385✔
1433
  int32_t numOfRows = 0;
2,385✔
1434
  SVgObj *pVgroup = NULL;
2,385✔
1435
  int32_t cols = 0;
2,385✔
1436
  int64_t curMs = taosGetTimestampMs();
2,385✔
1437
  int32_t code = 0;
2,385✔
1438

1439
  while (numOfRows < rows - TSDB_MAX_REPLICA) {
6,790✔
1440
    pShow->pIter = sdbFetch(pSdb, SDB_VGROUP, pShow->pIter, (void **)&pVgroup);
6,790✔
1441
    if (pShow->pIter == NULL) break;
6,790✔
1442

1443
    for (int32_t i = 0; i < pVgroup->replica && numOfRows < rows; ++i) {
12,556✔
1444
      SVnodeGid       *pGid = &pVgroup->vnodeGid[i];
8,151✔
1445
      SColumnInfoData *pColInfo = NULL;
8,151✔
1446
      cols = 0;
8,151✔
1447

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

1461
      // db_name
1462
      const char *dbname = mndGetDbStr(pVgroup->dbName);
8,151✔
1463
      char        b1[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
8,151✔
1464
      if (dbname != NULL) {
8,151✔
1465
        STR_WITH_MAXSIZE_TO_VARSTR(b1, dbname, TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE);
8,151✔
1466
      } else {
UNCOV
1467
        STR_WITH_MAXSIZE_TO_VARSTR(b1, "NULL", TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE);
×
1468
      }
1469
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
8,151✔
1470
      code = colDataSetVal(pColInfo, numOfRows, (const char *)b1, false);
8,151✔
1471
      if (code != 0) {
8,151✔
UNCOV
1472
        mError("vgId:%d, failed to set dbName, since %s", pVgroup->vgId, tstrerror(code));
×
UNCOV
1473
        return code;
×
1474
      }
1475

1476
      // dnode is online?
1477
      SDnodeObj *pDnode = mndAcquireDnode(pMnode, pGid->dnodeId);
8,151✔
1478
      if (pDnode == NULL) {
8,151✔
UNCOV
1479
        mError("failed to acquire dnode. dnodeId:%d", pGid->dnodeId);
×
UNCOV
1480
        break;
×
1481
      }
1482
      bool isDnodeOnline = mndIsDnodeOnline(pDnode, curMs);
8,151✔
1483

1484
      char       buf[20] = {0};
8,151✔
1485
      ESyncState syncState = (isDnodeOnline) ? pGid->syncState : TAOS_SYNC_STATE_OFFLINE;
8,151✔
1486
      STR_TO_VARSTR(buf, syncStr(syncState));
8,151✔
1487
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
8,151✔
1488
      code = colDataSetVal(pColInfo, numOfRows, (const char *)buf, false);
8,151✔
1489
      if (code != 0) {
8,151✔
UNCOV
1490
        mError("vgId:%d, failed to set syncState, since %s", pVgroup->vgId, tstrerror(code));
×
UNCOV
1491
        return code;
×
1492
      }
1493

1494
      int64_t roleTimeMs = (isDnodeOnline) ? pGid->roleTimeMs : 0;
8,151✔
1495
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
8,151✔
1496
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&roleTimeMs, false);
8,151✔
1497
      if (code != 0) {
8,151✔
1498
        mError("vgId:%d, failed to set roleTimeMs, since %s", pVgroup->vgId, tstrerror(code));
×
UNCOV
1499
        return code;
×
1500
      }
1501

1502
      int64_t startTimeMs = (isDnodeOnline) ? pGid->startTimeMs : 0;
8,151✔
1503
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
8,151✔
1504
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&startTimeMs, false);
8,151✔
1505
      if (code != 0) {
8,151✔
UNCOV
1506
        mError("vgId:%d, failed to set startTimeMs, since %s", pVgroup->vgId, tstrerror(code));
×
UNCOV
1507
        return code;
×
1508
      }
1509

1510
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
8,151✔
1511
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&pGid->syncRestore, false);
8,151✔
1512
      if (code != 0) {
8,151✔
UNCOV
1513
        mError("vgId:%d, failed to set syncRestore, since %s", pVgroup->vgId, tstrerror(code));
×
UNCOV
1514
        return code;
×
1515
      }
1516

1517
      int64_t unappliedCount = pGid->syncCommitIndex - pGid->syncAppliedIndex;
8,151✔
1518
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
8,151✔
1519
      char restoreStr[20] = {0};
8,151✔
1520
      if (unappliedCount > 0) {
8,151✔
UNCOV
1521
        calculateRstoreFinishTime(pGid->appliedRate, unappliedCount, restoreStr, sizeof(restoreStr));
×
1522
      }
1523
      STR_TO_VARSTR(buf, restoreStr);
8,151✔
1524
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&buf, false);
8,151✔
1525
      if (code != 0) {
8,151✔
UNCOV
1526
        mError("vgId:%d, failed to set syncRestore finish time, since %s", pVgroup->vgId, tstrerror(code));
×
UNCOV
1527
        return code;
×
1528
      }
1529

1530
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
8,151✔
1531
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&unappliedCount, false);
8,151✔
1532
      if (code != 0) {
8,151✔
UNCOV
1533
        mError("vgId:%d, failed to set syncRestore, since %s", pVgroup->vgId, tstrerror(code));
×
UNCOV
1534
        return code;
×
1535
      }
1536

1537
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
8,151✔
1538
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&pGid->bufferSegmentUsed, false);
8,151✔
1539
      if (code != 0) {
8,151✔
UNCOV
1540
        mError("vgId:%d, failed to set buffer segment used, since %s", pVgroup->vgId, tstrerror(code));
×
UNCOV
1541
        return code;
×
1542
      }
1543

1544
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
8,151✔
1545
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&pGid->bufferSegmentSize, false);
8,151✔
1546
      if (code != 0) {
8,151✔
UNCOV
1547
        mError("vgId:%d, failed to set buffer segment size, since %s", pVgroup->vgId, tstrerror(code));
×
UNCOV
1548
        return code;
×
1549
      }
1550

1551
      numOfRows++;
8,151✔
1552
      sdbRelease(pSdb, pDnode);
8,151✔
1553
    }
1554

1555
    sdbRelease(pSdb, pVgroup);
4,405✔
1556
  }
1557

1558
  pShow->numOfRows += numOfRows;
2,385✔
1559
  return numOfRows;
2,385✔
1560
}
1561

UNCOV
1562
static void mndCancelGetNextVnode(SMnode *pMnode, void *pIter) {
×
UNCOV
1563
  SSdb *pSdb = pMnode->pSdb;
×
UNCOV
1564
  sdbCancelFetchByType(pSdb, pIter, SDB_VGROUP);
×
1565
}
×
1566

1567
static int32_t mndAddVnodeToVgroup(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup, SArray *pArray) {
82,931✔
1568
  int32_t code = 0;
82,931✔
1569
  taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
82,931✔
1570
  for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
343,533✔
1571
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
260,602✔
1572
    mInfo("trans:%d, dnode:%d, equivalent vnodes:%d others:%d", pTrans->id, pDnode->id, pDnode->numOfVnodes,
260,602✔
1573
          pDnode->numOfOtherNodes);
1574
  }
1575

1576
  SVnodeGid *pVgid = &pVgroup->vnodeGid[pVgroup->replica];
82,931✔
1577
  for (int32_t d = 0; d < taosArrayGetSize(pArray); ++d) {
108,151✔
1578
    SDnodeObj *pDnode = taosArrayGet(pArray, d);
107,234✔
1579

1580
    bool used = false;
107,234✔
1581
    for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
249,537✔
1582
      if (pDnode->id == pVgroup->vnodeGid[vn].dnodeId) {
167,523✔
1583
        used = true;
25,220✔
1584
        break;
25,220✔
1585
      }
1586
    }
1587
    if (used) continue;
107,234✔
1588

1589
    if (pDnode == NULL) {
82,014✔
1590
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_DNODES);
×
1591
    }
1592
    if (pDnode->numOfVnodes >= pDnode->numOfSupportVnodes) {
82,014✔
UNCOV
1593
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_VNODES);
×
1594
    }
1595

1596
    int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
82,014✔
1597
    if (pDnode->memAvail - vgMem - pDnode->memUsed <= 0) {
82,014✔
UNCOV
1598
      mError("trans:%d, db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
×
1599
             pTrans->id, pVgroup->dbName, pVgroup->vgId, vgMem, pDnode->id, pDnode->memAvail, pDnode->memUsed);
UNCOV
1600
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE);
×
1601
    } else {
1602
      pDnode->memUsed += vgMem;
82,014✔
1603
    }
1604

1605
    pVgid->dnodeId = pDnode->id;
82,014✔
1606
    pVgid->syncState = TAOS_SYNC_STATE_OFFLINE;
82,014✔
1607
    mInfo("trans:%id, db:%s, vgId:%d, vn:%d is added, memory:%" PRId64 ", dnode:%d avail:%" PRId64 " used:%" PRId64,
82,014✔
1608
          pTrans->id, pVgroup->dbName, pVgroup->vgId, pVgroup->replica, vgMem, pVgid->dnodeId, pDnode->memAvail,
1609
          pDnode->memUsed);
1610

1611
    pVgroup->replica++;
82,014✔
1612
    pDnode->numOfVnodes++;
82,014✔
1613

1614
    SSdbRaw *pVgRaw = mndVgroupActionEncode(pVgroup);
82,014✔
1615
    if (pVgRaw == NULL) {
82,014✔
UNCOV
1616
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1617
      if (terrno != 0) code = terrno;
×
1618
      TAOS_RETURN(code);
×
1619
    }
1620
    if ((code = mndTransAppendGroupRedolog(pTrans, pVgRaw, pVgroup->vgId)) != 0) {
82,014✔
UNCOV
1621
      sdbFreeRaw(pVgRaw);
×
UNCOV
1622
      TAOS_RETURN(code);
×
1623
    }
1624
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
82,014✔
1625
    if (code != 0) {
82,014✔
UNCOV
1626
      mError("trans:%d, vgId:%d, failed to set raw status since %s at line:%d", pTrans->id, pVgroup->vgId,
×
1627
             tstrerror(code), __LINE__);
1628
    }
1629
    TAOS_RETURN(code);
82,014✔
1630
  }
1631

1632
  code = TSDB_CODE_MND_NO_ENOUGH_DNODES;
917✔
1633
  mError("trans:%d, db:%s, failed to add vnode to vgId:%d since %s", pTrans->id, pVgroup->dbName, pVgroup->vgId,
917✔
1634
         tstrerror(code));
1635
  TAOS_RETURN(code);
917✔
1636
}
1637

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

1647
  int32_t code = -1;
14,370✔
1648
  for (int32_t d = taosArrayGetSize(pArray) - 1; d >= 0; --d) {
18,292✔
1649
    SDnodeObj *pDnode = taosArrayGet(pArray, d);
18,237✔
1650

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

1670
_OVER:
55✔
1671
  if (code != 0) {
14,370✔
1672
    code = TSDB_CODE_APP_ERROR;
55✔
1673
    mError("trans:%d, db:%s, failed to remove vnode from vgId:%d since %s", pTrans->id, pVgroup->dbName, pVgroup->vgId,
55✔
1674
           tstrerror(code));
1675
    TAOS_RETURN(code);
55✔
1676
  }
1677

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

1684
  SSdbRaw *pVgRaw = mndVgroupActionEncode(pVgroup);
14,315✔
1685
  if (pVgRaw == NULL) {
14,315✔
UNCOV
1686
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1687
    if (terrno != 0) code = terrno;
×
UNCOV
1688
    TAOS_RETURN(code);
×
1689
  }
1690
  if (mndTransAppendGroupRedolog(pTrans, pVgRaw, pVgroup->vgId) != 0) {
14,315✔
UNCOV
1691
    sdbFreeRaw(pVgRaw);
×
UNCOV
1692
    TAOS_RETURN(code);
×
1693
  }
1694
  code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
14,315✔
1695
  if (code != 0) {
14,315✔
UNCOV
1696
    mError("trans:%d, vgId:%d, failed to set raw status since %s at line:%d", pTrans->id, pVgroup->vgId,
×
1697
           tstrerror(code), __LINE__);
1698
  }
1699

1700
  TAOS_RETURN(code);
14,315✔
1701
}
1702

UNCOV
1703
static int32_t mndRemoveVnodeFromVgroupWithoutSave(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup, SArray *pArray,
×
1704
                                                   SVnodeGid *pDelVgid) {
UNCOV
1705
  taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
×
UNCOV
1706
  for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
×
UNCOV
1707
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
×
UNCOV
1708
    mInfo("dnode:%d, equivalent vnodes:%d others:%d", pDnode->id, pDnode->numOfVnodes, pDnode->numOfOtherNodes);
×
1709
  }
1710

1711
  int32_t code = -1;
×
1712
  for (int32_t d = taosArrayGetSize(pArray) - 1; d >= 0; --d) {
×
1713
    SDnodeObj *pDnode = taosArrayGet(pArray, d);
×
1714

UNCOV
1715
    for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
×
1716
      SVnodeGid *pVgid = &pVgroup->vnodeGid[vn];
×
1717
      if (pVgid->dnodeId == pDnode->id) {
×
UNCOV
1718
        int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
×
UNCOV
1719
        pDnode->memUsed -= vgMem;
×
UNCOV
1720
        mInfo("db:%s, vgId:%d, vn:%d is removed, memory:%" PRId64 ", dnode:%d avail:%" PRId64 " used:%" PRId64,
×
1721
              pVgroup->dbName, pVgroup->vgId, vn, vgMem, pVgid->dnodeId, pDnode->memAvail, pDnode->memUsed);
UNCOV
1722
        pDnode->numOfVnodes--;
×
UNCOV
1723
        pVgroup->replica--;
×
UNCOV
1724
        *pDelVgid = *pVgid;
×
UNCOV
1725
        *pVgid = pVgroup->vnodeGid[pVgroup->replica];
×
UNCOV
1726
        memset(&pVgroup->vnodeGid[pVgroup->replica], 0, sizeof(SVnodeGid));
×
UNCOV
1727
        code = 0;
×
1728
        goto _OVER;
×
1729
      }
1730
    }
1731
  }
1732

1733
_OVER:
×
UNCOV
1734
  if (code != 0) {
×
UNCOV
1735
    code = TSDB_CODE_APP_ERROR;
×
1736
    mError("db:%s, failed to remove vnode from vgId:%d since %s", pVgroup->dbName, pVgroup->vgId, tstrerror(code));
×
1737
    TAOS_RETURN(code);
×
1738
  }
1739

1740
  for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
×
1741
    SVnodeGid *pVgid = &pVgroup->vnodeGid[vn];
×
1742
    mInfo("db:%s, vgId:%d, vn:%d dnode:%d is reserved", pVgroup->dbName, pVgroup->vgId, vn, pVgid->dnodeId);
×
1743
  }
1744

1745
  TAOS_RETURN(code);
×
1746
}
1747

1748
int32_t mndAddCreateVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, SVnodeGid *pVgid) {
3,011,581✔
1749
  int32_t      code = 0;
3,011,581✔
1750
  STransAction action = {0};
3,011,581✔
1751

1752
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
3,011,581✔
1753
  if (pDnode == NULL) return -1;
3,011,581✔
1754
  action.epSet = mndGetDnodeEpset(pDnode);
3,011,581✔
1755
  mndReleaseDnode(pMnode, pDnode);
3,011,581✔
1756

1757
  int32_t contLen = 0;
3,011,581✔
1758
  void   *pReq = mndBuildCreateVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen);
3,011,581✔
1759
  if (pReq == NULL) return -1;
3,011,581✔
1760

1761
  action.pCont = pReq;
3,011,581✔
1762
  action.contLen = contLen;
3,011,581✔
1763
  action.msgType = TDMT_DND_CREATE_VNODE;
3,011,581✔
1764
  action.acceptableCode = TSDB_CODE_VND_ALREADY_EXIST;
3,011,581✔
1765
  action.groupId = pVgroup->vgId;
3,011,581✔
1766

1767
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
3,011,581✔
UNCOV
1768
    taosMemoryFree(pReq);
×
UNCOV
1769
    TAOS_RETURN(code);
×
1770
  }
1771

1772
  TAOS_RETURN(code);
3,011,581✔
1773
}
1774

1775
int32_t mndRestoreAddCreateVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
6,170✔
1776
                                       SDnodeObj *pDnode) {
1777
  int32_t      code = 0;
6,170✔
1778
  STransAction action = {0};
6,170✔
1779

1780
  action.epSet = mndGetDnodeEpset(pDnode);
6,170✔
1781

1782
  int32_t contLen = 0;
6,170✔
1783
  void   *pReq = mndBuildCreateVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen);
6,170✔
1784
  if (pReq == NULL) {
6,170✔
UNCOV
1785
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1786
    if (terrno != 0) code = terrno;
×
UNCOV
1787
    TAOS_RETURN(code);
×
1788
  }
1789

1790
  action.pCont = pReq;
6,170✔
1791
  action.contLen = contLen;
6,170✔
1792
  action.msgType = TDMT_DND_CREATE_VNODE;
6,170✔
1793
  action.acceptableCode = TSDB_CODE_VND_ALREADY_EXIST;
6,170✔
1794
  action.groupId = pVgroup->vgId;
6,170✔
1795

1796
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
6,170✔
UNCOV
1797
    taosMemoryFree(pReq);
×
UNCOV
1798
    TAOS_RETURN(code);
×
1799
  }
1800

1801
  TAOS_RETURN(code);
6,170✔
1802
}
1803

1804
int32_t mndAddAlterVnodeConfirmAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) {
280,621✔
1805
  int32_t      code = 0;
280,621✔
1806
  STransAction action = {0};
280,621✔
1807
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
280,621✔
1808

1809
  mInfo("trans:%d, vgId:%d, build alter vnode confirm req", pTrans->id, pVgroup->vgId);
280,621✔
1810
  int32_t   contLen = sizeof(SMsgHead);
280,621✔
1811
  SMsgHead *pHead = taosMemoryMalloc(contLen);
280,621✔
1812
  if (pHead == NULL) {
280,621✔
UNCOV
1813
    TAOS_RETURN(terrno);
×
1814
  }
1815

1816
  pHead->contLen = htonl(contLen);
280,621✔
1817
  pHead->vgId = htonl(pVgroup->vgId);
280,621✔
1818

1819
  action.pCont = pHead;
280,621✔
1820
  action.contLen = contLen;
280,621✔
1821
  action.msgType = TDMT_VND_ALTER_CONFIRM;
280,621✔
1822
  // incorrect redirect result will cause this erro
1823
  action.retryCode = TSDB_CODE_VND_INVALID_VGROUP_ID;
280,621✔
1824
  action.groupId = pVgroup->vgId;
280,621✔
1825

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

1831
  TAOS_RETURN(code);
280,621✔
1832
}
1833

UNCOV
1834
int32_t mndAddChangeConfigAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pOldVgroup, SVgObj *pNewVgroup,
×
1835
                                 int32_t dnodeId) {
UNCOV
1836
  int32_t      code = 0;
×
UNCOV
1837
  STransAction action = {0};
×
1838
  action.epSet = mndGetVgroupEpset(pMnode, pNewVgroup);
×
1839

UNCOV
1840
  int32_t contLen = 0;
×
UNCOV
1841
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pNewVgroup, dnodeId, &contLen);
×
UNCOV
1842
  if (pReq == NULL) {
×
UNCOV
1843
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1844
    if (terrno != 0) code = terrno;
×
UNCOV
1845
    TAOS_RETURN(code);
×
1846
  }
1847

UNCOV
1848
  int32_t totallen = contLen + sizeof(SMsgHead);
×
1849

UNCOV
1850
  SMsgHead *pHead = taosMemoryMalloc(totallen);
×
UNCOV
1851
  if (pHead == NULL) {
×
1852
    taosMemoryFree(pReq);
×
1853
    TAOS_RETURN(terrno);
×
1854
  }
1855

UNCOV
1856
  pHead->contLen = htonl(totallen);
×
UNCOV
1857
  pHead->vgId = htonl(pNewVgroup->vgId);
×
1858

1859
  memcpy((void *)(pHead + 1), pReq, contLen);
×
UNCOV
1860
  taosMemoryFree(pReq);
×
1861

1862
  action.pCont = pHead;
×
1863
  action.contLen = totallen;
×
UNCOV
1864
  action.msgType = TDMT_SYNC_CONFIG_CHANGE;
×
1865

1866
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
×
1867
    taosMemoryFree(pHead);
×
1868
    TAOS_RETURN(code);
×
1869
  }
1870

UNCOV
1871
  TAOS_RETURN(code);
×
1872
}
1873

1874
static int32_t mndAddAlterVnodeHashRangeAction(SMnode *pMnode, STrans *pTrans, int32_t srcVgId, SVgObj *pVgroup) {
23,786✔
1875
  int32_t      code = 0;
23,786✔
1876
  STransAction action = {0};
23,786✔
1877
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
23,786✔
1878

1879
  int32_t contLen = 0;
23,786✔
1880
  void   *pReq = mndBuildAlterVnodeHashRangeReq(pMnode, srcVgId, pVgroup, &contLen);
23,786✔
1881
  if (pReq == NULL) {
23,786✔
1882
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1883
    if (terrno != 0) code = terrno;
×
1884
    TAOS_RETURN(code);
×
1885
  }
1886

1887
  action.pCont = pReq;
23,786✔
1888
  action.contLen = contLen;
23,786✔
1889
  action.msgType = TDMT_VND_ALTER_HASHRANGE;
23,786✔
1890
  action.acceptableCode = TSDB_CODE_VND_ALREADY_EXIST;
23,786✔
1891

1892
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
23,786✔
1893
    taosMemoryFree(pReq);
×
UNCOV
1894
    TAOS_RETURN(code);
×
1895
  }
1896

1897
  mInfo("trans:%d, add alter vnode hash range action for from vgId:%d to vgId:%d", pTrans->id, srcVgId, pVgroup->vgId);
23,786✔
1898
  TAOS_RETURN(code);
23,786✔
1899
}
1900

1901
int32_t mndAddAlterVnodeConfigAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) {
207,657✔
1902
  int32_t      code = 0;
207,657✔
1903
  STransAction action = {0};
207,657✔
1904
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
207,657✔
1905

1906
  int32_t contLen = 0;
207,657✔
1907
  void   *pReq = mndBuildAlterVnodeConfigReq(pMnode, pDb, pVgroup, &contLen);
207,657✔
1908
  if (pReq == NULL) {
207,657✔
1909
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1910
    if (terrno != 0) code = terrno;
×
UNCOV
1911
    TAOS_RETURN(code);
×
1912
  }
1913

1914
  action.pCont = pReq;
207,657✔
1915
  action.contLen = contLen;
207,657✔
1916
  action.msgType = TDMT_VND_ALTER_CONFIG;
207,657✔
1917
  action.groupId = pVgroup->vgId;
207,657✔
1918

1919
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
207,657✔
UNCOV
1920
    taosMemoryFree(pReq);
×
UNCOV
1921
    TAOS_RETURN(code);
×
1922
  }
1923

1924
  TAOS_RETURN(code);
207,657✔
1925
}
1926

1927
int32_t mndAddNewVgPrepareAction(SMnode *pMnode, STrans *pTrans, SVgObj *pVg) {
2,571,772✔
1928
  int32_t  code = 0;
2,571,772✔
1929
  SSdbRaw *pRaw = mndVgroupActionEncode(pVg);
2,571,772✔
1930
  if (pRaw == NULL) {
2,571,772✔
UNCOV
1931
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1932
    if (terrno != 0) code = terrno;
×
UNCOV
1933
    goto _err;
×
1934
  }
1935

1936
  TAOS_CHECK_GOTO(mndTransAppendPrepareLog(pTrans, pRaw), NULL, _err);
2,571,772✔
1937
  if (sdbSetRawStatus(pRaw, SDB_STATUS_CREATING) != 0) {
2,571,772✔
UNCOV
1938
    mError("vgId:%d, failed to set raw status at line:%d", pVg->vgId, __LINE__);
×
1939
  }
1940
  if (code != 0) {
2,571,772✔
UNCOV
1941
    mError("vgId:%d, failed to set raw status since %s at line:%d", pVg->vgId, tstrerror(code), __LINE__);
×
UNCOV
1942
    TAOS_RETURN(code);
×
1943
  }
1944
  pRaw = NULL;
2,571,772✔
1945
  TAOS_RETURN(code);
2,571,772✔
1946

UNCOV
1947
_err:
×
UNCOV
1948
  sdbFreeRaw(pRaw);
×
UNCOV
1949
  TAOS_RETURN(code);
×
1950
}
1951

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

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

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

1973
  action.pCont = pReq;
684,049✔
1974
  action.contLen = contLen;
684,049✔
1975
  action.msgType = TDMT_VND_ALTER_REPLICA;
684,049✔
1976
  action.groupId = pVgroup->vgId;
684,049✔
1977

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

1983
  TAOS_RETURN(code);
684,049✔
1984
}
1985

UNCOV
1986
int32_t mndAddCheckLearnerCatchupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId) {
×
UNCOV
1987
  int32_t    code = 0;
×
UNCOV
1988
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
×
UNCOV
1989
  if (pDnode == NULL) {
×
UNCOV
1990
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1991
    if (terrno != 0) code = terrno;
×
UNCOV
1992
    TAOS_RETURN(code);
×
1993
  }
1994

1995
  STransAction action = {0};
×
UNCOV
1996
  action.epSet = mndGetDnodeEpset(pDnode);
×
UNCOV
1997
  mndReleaseDnode(pMnode, pDnode);
×
1998

UNCOV
1999
  int32_t contLen = 0;
×
UNCOV
2000
  void   *pReq = mndBuildCheckLearnCatchupReq(pMnode, pDb, pVgroup, dnodeId, &contLen);
×
UNCOV
2001
  if (pReq == NULL) {
×
UNCOV
2002
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2003
    if (terrno != 0) code = terrno;
×
2004
    TAOS_RETURN(code);
×
2005
  }
2006

UNCOV
2007
  action.pCont = pReq;
×
UNCOV
2008
  action.contLen = contLen;
×
UNCOV
2009
  action.msgType = TDMT_DND_CHECK_VNODE_LEARNER_CATCHUP;
×
UNCOV
2010
  action.acceptableCode = TSDB_CODE_VND_ALREADY_IS_VOTER;
×
2011
  action.retryCode = TSDB_CODE_VND_NOT_CATCH_UP;
×
2012

2013
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
×
2014
    taosMemoryFree(pReq);
×
2015
    TAOS_RETURN(code);
×
2016
  }
2017

UNCOV
2018
  TAOS_RETURN(code);
×
2019
}
2020

2021
int32_t mndAddAlterVnodeTypeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId) {
101,346✔
2022
  int32_t    code = 0;
101,346✔
2023
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
101,346✔
2024
  if (pDnode == NULL) {
101,346✔
2025
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2026
    if (terrno != 0) code = terrno;
×
2027
    TAOS_RETURN(code);
×
2028
  }
2029

2030
  STransAction action = {0};
101,346✔
2031
  action.epSet = mndGetDnodeEpset(pDnode);
101,346✔
2032
  mndReleaseDnode(pMnode, pDnode);
101,346✔
2033

2034
  int32_t contLen = 0;
101,346✔
2035
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pVgroup, dnodeId, &contLen);
101,346✔
2036
  if (pReq == NULL) {
101,346✔
UNCOV
2037
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2038
    if (terrno != 0) code = terrno;
×
2039
    TAOS_RETURN(code);
×
2040
  }
2041

2042
  action.pCont = pReq;
101,346✔
2043
  action.contLen = contLen;
101,346✔
2044
  action.msgType = TDMT_DND_ALTER_VNODE_TYPE;
101,346✔
2045
  action.acceptableCode = TSDB_CODE_VND_ALREADY_IS_VOTER;
101,346✔
2046
  action.retryCode = TSDB_CODE_VND_NOT_CATCH_UP;
101,346✔
2047
  action.groupId = pVgroup->vgId;
101,346✔
2048

2049
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
101,346✔
2050
    taosMemoryFree(pReq);
×
2051
    TAOS_RETURN(code);
×
2052
  }
2053

2054
  TAOS_RETURN(code);
101,346✔
2055
}
2056

2057
int32_t mndRestoreAddAlterVnodeTypeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
6,170✔
2058
                                          SDnodeObj *pDnode) {
2059
  int32_t      code = 0;
6,170✔
2060
  STransAction action = {0};
6,170✔
2061
  action.epSet = mndGetDnodeEpset(pDnode);
6,170✔
2062

2063
  int32_t contLen = 0;
6,170✔
2064
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pVgroup, pDnode->id, &contLen);
6,170✔
2065
  if (pReq == NULL) {
6,170✔
UNCOV
2066
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2067
    if (terrno != 0) code = terrno;
×
UNCOV
2068
    TAOS_RETURN(code);
×
2069
  }
2070

2071
  action.pCont = pReq;
6,170✔
2072
  action.contLen = contLen;
6,170✔
2073
  action.msgType = TDMT_DND_ALTER_VNODE_TYPE;
6,170✔
2074
  action.acceptableCode = TSDB_CODE_VND_ALREADY_IS_VOTER;
6,170✔
2075
  action.retryCode = TSDB_CODE_VND_NOT_CATCH_UP;
6,170✔
2076
  action.groupId = pVgroup->vgId;
6,170✔
2077

2078
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
6,170✔
UNCOV
2079
    taosMemoryFree(pReq);
×
UNCOV
2080
    TAOS_RETURN(code);
×
2081
  }
2082

2083
  TAOS_RETURN(code);
6,170✔
2084
}
2085

2086
static int32_t mndAddDisableVnodeWriteAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
23,786✔
2087
                                             int32_t dnodeId) {
2088
  int32_t    code = 0;
23,786✔
2089
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
23,786✔
2090
  if (pDnode == NULL) {
23,786✔
2091
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2092
    if (terrno != 0) code = terrno;
×
2093
    TAOS_RETURN(code);
×
2094
  }
2095

2096
  STransAction action = {0};
23,786✔
2097
  action.epSet = mndGetDnodeEpset(pDnode);
23,786✔
2098
  mndReleaseDnode(pMnode, pDnode);
23,786✔
2099

2100
  int32_t contLen = 0;
23,786✔
2101
  void   *pReq = mndBuildDisableVnodeWriteReq(pMnode, pDb, pVgroup->vgId, &contLen);
23,786✔
2102
  if (pReq == NULL) {
23,786✔
UNCOV
2103
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2104
    if (terrno != 0) code = terrno;
×
2105
    TAOS_RETURN(code);
×
2106
  }
2107

2108
  action.pCont = pReq;
23,786✔
2109
  action.contLen = contLen;
23,786✔
2110
  action.msgType = TDMT_VND_DISABLE_WRITE;
23,786✔
2111

2112
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
23,786✔
UNCOV
2113
    taosMemoryFree(pReq);
×
UNCOV
2114
    TAOS_RETURN(code);
×
2115
  }
2116

2117
  TAOS_RETURN(code);
23,786✔
2118
}
2119

2120
int32_t mndAddDropVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, SVnodeGid *pVgid,
4,488,700✔
2121
                              bool isRedo) {
2122
  int32_t      code = 0;
4,488,700✔
2123
  STransAction action = {0};
4,488,700✔
2124

2125
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
4,488,700✔
2126
  if (pDnode == NULL) {
4,488,700✔
UNCOV
2127
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2128
    if (terrno != 0) code = terrno;
×
2129
    TAOS_RETURN(code);
×
2130
  }
2131
  action.epSet = mndGetDnodeEpset(pDnode);
4,488,700✔
2132
  mndReleaseDnode(pMnode, pDnode);
4,488,700✔
2133

2134
  int32_t contLen = 0;
4,488,700✔
2135
  void   *pReq = mndBuildDropVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen);
4,488,700✔
2136
  if (pReq == NULL) {
4,488,700✔
UNCOV
2137
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2138
    if (terrno != 0) code = terrno;
×
2139
    TAOS_RETURN(code);
×
2140
  }
2141

2142
  action.pCont = pReq;
4,488,700✔
2143
  action.contLen = contLen;
4,488,700✔
2144
  action.msgType = TDMT_DND_DROP_VNODE;
4,488,700✔
2145
  action.acceptableCode = TSDB_CODE_VND_NOT_EXIST;
4,488,700✔
2146
  action.groupId = pVgroup->vgId;
4,488,700✔
2147

2148
  if (isRedo) {
4,488,700✔
2149
    if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
1,624,133✔
UNCOV
2150
      taosMemoryFree(pReq);
×
UNCOV
2151
      TAOS_RETURN(code);
×
2152
    }
2153
  } else {
2154
    if ((code = mndTransAppendUndoAction(pTrans, &action)) != 0) {
2,864,567✔
UNCOV
2155
      taosMemoryFree(pReq);
×
UNCOV
2156
      TAOS_RETURN(code);
×
2157
    }
2158
  }
2159

2160
  TAOS_RETURN(code);
4,488,700✔
2161
}
2162

2163
int32_t mndSetMoveVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t vnIndex,
16,998✔
2164
                                    SArray *pArray, bool force, bool unsafe) {
2165
  int32_t code = 0;
16,998✔
2166
  SVgObj  newVg = {0};
16,998✔
2167
  memcpy(&newVg, pVgroup, sizeof(SVgObj));
16,998✔
2168

2169
  mInfo("vgId:%d, trans:%d, vgroup info before move, replica:%d", newVg.vgId, pTrans->id, newVg.replica);
16,998✔
2170
  for (int32_t i = 0; i < newVg.replica; ++i) {
54,946✔
2171
    mInfo("vgId:%d, trans:%d, vnode:%d dnode:%d", newVg.vgId, pTrans->id, i, newVg.vnodeGid[i].dnodeId);
37,948✔
2172
  }
2173

2174
  if (!force) {
16,998✔
2175
#if 1
2176
    {
2177
#else
2178
    if (newVg.replica == 1) {
2179
#endif
2180
      mInfo("vgId:%d, trans:%d, will add 1 vnode, replca:%d", pVgroup->vgId, pTrans->id, newVg.replica);
16,998✔
2181
      TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVg, pArray));
16,998✔
2182
      for (int32_t i = 0; i < newVg.replica - 1; ++i) {
54,946✔
2183
        TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg, newVg.vnodeGid[i].dnodeId));
37,948✔
2184
      }
2185
      TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg, &newVg.vnodeGid[newVg.replica - 1]));
16,998✔
2186
      TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg));
16,998✔
2187

2188
      mInfo("vgId:%d, trans:%d, will remove 1 vnode, replca:2", pVgroup->vgId, pTrans->id);
16,998✔
2189
      newVg.replica--;
16,998✔
2190
      SVnodeGid del = newVg.vnodeGid[vnIndex];
16,998✔
2191
      newVg.vnodeGid[vnIndex] = newVg.vnodeGid[newVg.replica];
16,998✔
2192
      memset(&newVg.vnodeGid[newVg.replica], 0, sizeof(SVnodeGid));
16,998✔
2193
      {
2194
        SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
16,998✔
2195
        if (pRaw == NULL) {
16,998✔
UNCOV
2196
          code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2197
          if (terrno != 0) code = terrno;
×
UNCOV
2198
          TAOS_RETURN(code);
×
2199
        }
2200
        if ((code = mndTransAppendGroupRedolog(pTrans, pRaw, pVgroup->vgId)) != 0) {
16,998✔
UNCOV
2201
          sdbFreeRaw(pRaw);
×
UNCOV
2202
          TAOS_RETURN(code);
×
2203
        }
2204
        code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
16,998✔
2205
        if (code != 0) {
16,998✔
UNCOV
2206
          mError("vgId:%d, failed to set raw status since %s at line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
UNCOV
2207
          return code;
×
2208
        }
2209
      }
2210

2211
      TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pDb, &newVg, &del, true));
16,998✔
2212
      for (int32_t i = 0; i < newVg.replica; ++i) {
54,946✔
2213
        TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg, newVg.vnodeGid[i].dnodeId));
37,948✔
2214
      }
2215
      TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg));
16,998✔
2216
#if 1
2217
    }
2218
#else
2219
    } else {  // new replica == 3
2220
      mInfo("vgId:%d, will add 1 vnode, replca:3", pVgroup->vgId);
2221
      if (mndAddVnodeToVgroup(pMnode, pTrans, &newVg, pArray) != 0) return -1;
2222
      mInfo("vgId:%d, will remove 1 vnode, replca:4", pVgroup->vgId);
2223
      newVg.replica--;
2224
      SVnodeGid del = newVg.vnodeGid[vnIndex];
2225
      newVg.vnodeGid[vnIndex] = newVg.vnodeGid[newVg.replica];
2226
      memset(&newVg.vnodeGid[newVg.replica], 0, sizeof(SVnodeGid));
2227
      {
2228
        SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
2229
        if (pRaw == NULL) return -1;
2230
        if (mndTransAppendRedolog(pTrans, pRaw) != 0) {
2231
          sdbFreeRaw(pRaw);
2232
          return -1;
2233
        }
2234
      }
2235

2236
      if (mndAddDropVnodeAction(pMnode, pTrans, pDb, &newVg, &del, true) != 0) return -1;
2237
      for (int32_t i = 0; i < newVg.replica; ++i) {
2238
        if (i == vnIndex) continue;
2239
        if (mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg, newVg.vnodeGid[i].dnodeId) != 0) return -1;
2240
      }
2241
      if (mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg, &newVg.vnodeGid[vnIndex]) != 0) return -1;
2242
      if (mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg) != 0) return -1;
2243
    }
2244
#endif
2245
  } else {
UNCOV
2246
    mInfo("vgId:%d, will add 1 vnode and force remove 1 vnode", pVgroup->vgId);
×
UNCOV
2247
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVg, pArray));
×
UNCOV
2248
    newVg.replica--;
×
2249
    // SVnodeGid del = newVg.vnodeGid[vnIndex];
UNCOV
2250
    newVg.vnodeGid[vnIndex] = newVg.vnodeGid[newVg.replica];
×
UNCOV
2251
    memset(&newVg.vnodeGid[newVg.replica], 0, sizeof(SVnodeGid));
×
2252
    {
UNCOV
2253
      SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
×
UNCOV
2254
      if (pRaw == NULL) {
×
UNCOV
2255
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2256
        if (terrno != 0) code = terrno;
×
UNCOV
2257
        TAOS_RETURN(code);
×
2258
      }
UNCOV
2259
      if ((code = mndTransAppendGroupRedolog(pTrans, pRaw, pVgroup->vgId)) != 0) {
×
UNCOV
2260
        sdbFreeRaw(pRaw);
×
UNCOV
2261
        TAOS_RETURN(code);
×
2262
      }
UNCOV
2263
      code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
×
UNCOV
2264
      if (code != 0) {
×
UNCOV
2265
        mError("vgId:%d, failed to set raw status since %s at line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
UNCOV
2266
        return code;
×
2267
      }
2268
    }
2269

UNCOV
2270
    for (int32_t i = 0; i < newVg.replica; ++i) {
×
2271
      if (i != vnIndex) {
×
2272
        TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg, newVg.vnodeGid[i].dnodeId));
×
2273
      }
2274
    }
2275
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg, &newVg.vnodeGid[vnIndex]));
×
2276
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg));
×
2277

2278
    if (newVg.replica == 1) {
×
2279
      if (force && !unsafe) {
×
2280
        TAOS_RETURN(TSDB_CODE_VND_META_DATA_UNSAFE_DELETE);
×
2281
      }
2282

UNCOV
2283
      SSdb *pSdb = pMnode->pSdb;
×
2284
      void *pIter = NULL;
×
2285

2286
      while (1) {
×
UNCOV
2287
        SStbObj *pStb = NULL;
×
2288
        pIter = sdbFetch(pSdb, SDB_STB, pIter, (void **)&pStb);
×
2289
        if (pIter == NULL) break;
×
2290

2291
        if (strcmp(pStb->db, pDb->name) == 0) {
×
UNCOV
2292
          if ((code = mndSetForceDropCreateStbRedoActions(pMnode, pTrans, &newVg, pStb)) != 0) {
×
UNCOV
2293
            sdbCancelFetch(pSdb, pIter);
×
UNCOV
2294
            sdbRelease(pSdb, pStb);
×
2295
            TAOS_RETURN(code);
×
2296
          }
2297
        }
2298

UNCOV
2299
        sdbRelease(pSdb, pStb);
×
2300
      }
2301

UNCOV
2302
      mInfo("vgId:%d, all data is dropped since replica=1", pVgroup->vgId);
×
2303
    }
2304
  }
2305

2306
  {
2307
    SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
16,998✔
2308
    if (pRaw == NULL) {
16,998✔
2309
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2310
      if (terrno != 0) code = terrno;
×
2311
      TAOS_RETURN(code);
×
2312
    }
2313
    if ((code = mndTransAppendCommitlog(pTrans, pRaw)) != 0) {
16,998✔
2314
      sdbFreeRaw(pRaw);
×
UNCOV
2315
      TAOS_RETURN(code);
×
2316
    }
2317
    code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
16,998✔
2318
    if (code != 0) {
16,998✔
2319
      mError("vgId:%d, failed to set raw status since %s at line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
2320
      return code;
×
2321
    }
2322
  }
2323

2324
  mInfo("vgId:%d, vgroup info after move, replica:%d", newVg.vgId, newVg.replica);
16,998✔
2325
  for (int32_t i = 0; i < newVg.replica; ++i) {
54,946✔
2326
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
37,948✔
2327
  }
2328
  TAOS_RETURN(code);
16,998✔
2329
}
2330

2331
int32_t mndSetMoveVgroupsInfoToTrans(SMnode *pMnode, STrans *pTrans, int32_t delDnodeId, bool force, bool unsafe) {
8,388✔
2332
  int32_t code = 0;
8,388✔
2333
  SArray *pArray = mndBuildDnodesArray(pMnode, delDnodeId, NULL);
8,388✔
2334
  if (pArray == NULL) {
8,388✔
2335
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2336
    if (terrno != 0) code = terrno;
×
UNCOV
2337
    TAOS_RETURN(code);
×
2338
  }
2339

2340
  void *pIter = NULL;
8,388✔
2341
  while (1) {
24,344✔
2342
    SVgObj *pVgroup = NULL;
32,732✔
2343
    pIter = sdbFetch(pMnode->pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
32,732✔
2344
    if (pIter == NULL) break;
32,732✔
2345

2346
    int32_t vnIndex = -1;
24,344✔
2347
    for (int32_t i = 0; i < pVgroup->replica; ++i) {
47,033✔
2348
      if (pVgroup->vnodeGid[i].dnodeId == delDnodeId) {
39,687✔
2349
        vnIndex = i;
16,998✔
2350
        break;
16,998✔
2351
      }
2352
    }
2353

2354
    code = 0;
24,344✔
2355
    if (vnIndex != -1) {
24,344✔
2356
      mInfo("vgId:%d, trans:%d, vnode:%d will be removed from dnode:%d, force:%d", pVgroup->vgId, pTrans->id, vnIndex,
16,998✔
2357
            delDnodeId, force);
2358
      SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName);
16,998✔
2359
      code = mndSetMoveVgroupInfoToTrans(pMnode, pTrans, pDb, pVgroup, vnIndex, pArray, force, unsafe);
16,998✔
2360
      mndReleaseDb(pMnode, pDb);
16,998✔
2361
    }
2362

2363
    sdbRelease(pMnode->pSdb, pVgroup);
24,344✔
2364

2365
    if (code != 0) {
24,344✔
UNCOV
2366
      sdbCancelFetch(pMnode->pSdb, pIter);
×
UNCOV
2367
      break;
×
2368
    }
2369
  }
2370

2371
  taosArrayDestroy(pArray);
8,388✔
2372
  TAOS_RETURN(code);
8,388✔
2373
}
2374

2375
static int32_t mndAddIncVgroupReplicaToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
65,000✔
2376
                                             int32_t newDnodeId) {
2377
  int32_t code = 0;
65,000✔
2378
  mInfo("vgId:%d, will add 1 vnode, replica:%d dnode:%d", pVgroup->vgId, pVgroup->replica, newDnodeId);
65,000✔
2379

2380
  // assoc dnode
2381
  SVnodeGid *pGid = &pVgroup->vnodeGid[pVgroup->replica];
65,000✔
2382
  pVgroup->replica++;
65,000✔
2383
  pGid->dnodeId = newDnodeId;
65,000✔
2384
  pGid->syncState = TAOS_SYNC_STATE_OFFLINE;
65,000✔
2385
  pGid->nodeRole = TAOS_SYNC_ROLE_LEARNER;
65,000✔
2386

2387
  SSdbRaw *pVgRaw = mndVgroupActionEncode(pVgroup);
65,000✔
2388
  if (pVgRaw == NULL) {
65,000✔
UNCOV
2389
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2390
    if (terrno != 0) code = terrno;
×
2391
    TAOS_RETURN(code);
×
2392
  }
2393
  if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
65,000✔
UNCOV
2394
    sdbFreeRaw(pVgRaw);
×
UNCOV
2395
    TAOS_RETURN(code);
×
2396
  }
2397
  code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
65,000✔
2398
  if (code != 0) {
65,000✔
UNCOV
2399
    mError("vgId:%d, failed to set raw status since %s at line:%d", pVgroup->vgId, tstrerror(code), __LINE__);
×
UNCOV
2400
    TAOS_RETURN(code);
×
2401
  }
2402

2403
  // learner
2404
  for (int32_t i = 0; i < pVgroup->replica - 1; ++i) {
216,362✔
2405
    TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, pVgroup, pVgroup->vnodeGid[i].dnodeId));
151,362✔
2406
  }
2407
  TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pDb, pVgroup, pGid));
65,000✔
2408

2409
  // voter
2410
  pGid->nodeRole = TAOS_SYNC_ROLE_VOTER;
65,000✔
2411
  TAOS_CHECK_RETURN(mndAddAlterVnodeTypeAction(pMnode, pTrans, pDb, pVgroup, pGid->dnodeId));
65,000✔
2412
  for (int32_t i = 0; i < pVgroup->replica - 1; ++i) {
216,362✔
2413
    TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, pVgroup, pVgroup->vnodeGid[i].dnodeId));
151,362✔
2414
  }
2415

2416
  // confirm
2417
  TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, pVgroup));
65,000✔
2418

2419
  TAOS_RETURN(code);
65,000✔
2420
}
2421

2422
static int32_t mndAddDecVgroupReplicaFromTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
65,000✔
2423
                                               int32_t delDnodeId) {
2424
  int32_t code = 0;
65,000✔
2425
  mInfo("vgId:%d, will remove 1 vnode, replica:%d dnode:%d", pVgroup->vgId, pVgroup->replica, delDnodeId);
65,000✔
2426

2427
  SVnodeGid *pGid = NULL;
65,000✔
2428
  SVnodeGid  delGid = {0};
65,000✔
2429
  for (int32_t i = 0; i < pVgroup->replica; ++i) {
113,039✔
2430
    if (pVgroup->vnodeGid[i].dnodeId == delDnodeId) {
113,039✔
2431
      pGid = &pVgroup->vnodeGid[i];
65,000✔
2432
      break;
65,000✔
2433
    }
2434
  }
2435

2436
  if (pGid == NULL) return 0;
65,000✔
2437

2438
  pVgroup->replica--;
65,000✔
2439
  memcpy(&delGid, pGid, sizeof(SVnodeGid));
65,000✔
2440
  memcpy(pGid, &pVgroup->vnodeGid[pVgroup->replica], sizeof(SVnodeGid));
65,000✔
2441
  memset(&pVgroup->vnodeGid[pVgroup->replica], 0, sizeof(SVnodeGid));
65,000✔
2442

2443
  SSdbRaw *pVgRaw = mndVgroupActionEncode(pVgroup);
65,000✔
2444
  if (pVgRaw == NULL) {
65,000✔
UNCOV
2445
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2446
    if (terrno != 0) code = terrno;
×
UNCOV
2447
    TAOS_RETURN(code);
×
2448
  }
2449
  if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
65,000✔
UNCOV
2450
    sdbFreeRaw(pVgRaw);
×
UNCOV
2451
    TAOS_RETURN(code);
×
2452
  }
2453
  code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
65,000✔
2454
  if (code != 0) {
65,000✔
UNCOV
2455
    mError("vgId:%d, failed to set raw status since %s at line:%d", pVgroup->vgId, tstrerror(code), __LINE__);
×
UNCOV
2456
    TAOS_RETURN(code);
×
2457
  }
2458

2459
  TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pDb, pVgroup, &delGid, true));
65,000✔
2460
  for (int32_t i = 0; i < pVgroup->replica; ++i) {
216,362✔
2461
    TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, pVgroup, pVgroup->vnodeGid[i].dnodeId));
151,362✔
2462
  }
2463
  TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, pVgroup));
65,000✔
2464

2465
  TAOS_RETURN(code);
65,000✔
2466
}
2467

2468
static int32_t mndRedistributeVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SVgObj *pVgroup, SDnodeObj *pNew1,
37,979✔
2469
                                     SDnodeObj *pOld1, SDnodeObj *pNew2, SDnodeObj *pOld2, SDnodeObj *pNew3,
2470
                                     SDnodeObj *pOld3) {
2471
  int32_t code = -1;
37,979✔
2472
  STrans *pTrans = NULL;
37,979✔
2473

2474
  pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_GLOBAL, pReq, "red-vgroup");
37,979✔
2475
  if (pTrans == NULL) {
37,979✔
2476
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2477
    if (terrno != 0) code = terrno;
×
UNCOV
2478
    goto _OVER;
×
2479
  }
2480

2481
  mndTransSetDbName(pTrans, pVgroup->dbName, NULL);
37,979✔
2482
  TAOS_CHECK_GOTO(mndTransCheckConflictWithCompact(pMnode, pTrans), NULL, _OVER);
37,979✔
2483
  TAOS_CHECK_GOTO(mndTransCheckConflictWithRetention(pMnode, pTrans), NULL, _OVER);
37,706✔
2484

2485
  mndTransSetSerial(pTrans);
37,706✔
2486
  mInfo("trans:%d, used to redistribute vgroup, vgId:%d", pTrans->id, pVgroup->vgId);
37,706✔
2487

2488
  SVgObj newVg = {0};
37,706✔
2489
  memcpy(&newVg, pVgroup, sizeof(SVgObj));
37,706✔
2490
  mInfo("vgId:%d, vgroup info before redistribute, replica:%d", newVg.vgId, newVg.replica);
37,706✔
2491
  for (int32_t i = 0; i < newVg.replica; ++i) {
124,896✔
2492
    mInfo("vgId:%d, vnode:%d dnode:%d role:%s", newVg.vgId, i, newVg.vnodeGid[i].dnodeId,
87,190✔
2493
          syncStr(newVg.vnodeGid[i].syncState));
2494
  }
2495

2496
  if (pNew1 != NULL && pOld1 != NULL) {
37,706✔
2497
    int32_t numOfVnodes = mndGetVnodesNum(pMnode, pNew1->id);
37,706✔
2498
    if (numOfVnodes >= pNew1->numOfSupportVnodes) {
37,706✔
2499
      mError("vgId:%d, no enough vnodes in dnode:%d, numOfVnodes:%d support:%d", newVg.vgId, pNew1->id, numOfVnodes,
713✔
2500
             pNew1->numOfSupportVnodes);
2501
      code = TSDB_CODE_MND_NO_ENOUGH_VNODES;
713✔
2502
      goto _OVER;
713✔
2503
    }
2504

2505
    int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
36,993✔
2506
    if (pNew1->memAvail - vgMem - pNew1->memUsed <= 0) {
36,993✔
UNCOV
2507
      mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
×
2508
             pVgroup->dbName, pVgroup->vgId, vgMem, pNew1->id, pNew1->memAvail, pNew1->memUsed);
UNCOV
2509
      code = TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE;
×
UNCOV
2510
      goto _OVER;
×
2511
    } else {
2512
      pNew1->memUsed += vgMem;
36,993✔
2513
    }
2514

2515
    TAOS_CHECK_GOTO(mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pNew1->id), NULL, _OVER);
36,993✔
2516
    TAOS_CHECK_GOTO(mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pOld1->id), NULL, _OVER);
36,993✔
2517
  }
2518

2519
  if (pNew2 != NULL && pOld2 != NULL) {
36,993✔
2520
    int32_t numOfVnodes = mndGetVnodesNum(pMnode, pNew2->id);
9,789✔
2521
    if (numOfVnodes >= pNew2->numOfSupportVnodes) {
9,789✔
UNCOV
2522
      mError("vgId:%d, no enough vnodes in dnode:%d, numOfVnodes:%d support:%d", newVg.vgId, pNew2->id, numOfVnodes,
×
2523
             pNew2->numOfSupportVnodes);
UNCOV
2524
      code = TSDB_CODE_MND_NO_ENOUGH_VNODES;
×
UNCOV
2525
      goto _OVER;
×
2526
    }
2527
    int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
9,789✔
2528
    if (pNew2->memAvail - vgMem - pNew2->memUsed <= 0) {
9,789✔
UNCOV
2529
      mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
×
2530
             pVgroup->dbName, pVgroup->vgId, vgMem, pNew2->id, pNew2->memAvail, pNew2->memUsed);
UNCOV
2531
      code = TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE;
×
2532
      goto _OVER;
×
2533
    } else {
2534
      pNew2->memUsed += vgMem;
9,789✔
2535
    }
2536
    TAOS_CHECK_GOTO(mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pNew2->id), NULL, _OVER);
9,789✔
2537
    TAOS_CHECK_GOTO(mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pOld2->id), NULL, _OVER);
9,789✔
2538
  }
2539

2540
  if (pNew3 != NULL && pOld3 != NULL) {
36,993✔
2541
    int32_t numOfVnodes = mndGetVnodesNum(pMnode, pNew3->id);
2,853✔
2542
    if (numOfVnodes >= pNew3->numOfSupportVnodes) {
2,853✔
UNCOV
2543
      mError("vgId:%d, no enough vnodes in dnode:%d, numOfVnodes:%d support:%d", newVg.vgId, pNew3->id, numOfVnodes,
×
2544
             pNew3->numOfSupportVnodes);
UNCOV
2545
      code = TSDB_CODE_MND_NO_ENOUGH_VNODES;
×
UNCOV
2546
      goto _OVER;
×
2547
    }
2548
    int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
2,853✔
2549
    if (pNew3->memAvail - vgMem - pNew3->memUsed <= 0) {
2,853✔
2550
      mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
×
2551
             pVgroup->dbName, pVgroup->vgId, vgMem, pNew3->id, pNew3->memAvail, pNew3->memUsed);
UNCOV
2552
      code = TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE;
×
UNCOV
2553
      goto _OVER;
×
2554
    } else {
2555
      pNew3->memUsed += vgMem;
2,853✔
2556
    }
2557
    TAOS_CHECK_GOTO(mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pNew3->id), NULL, _OVER);
2,853✔
2558
    TAOS_CHECK_GOTO(mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pOld3->id), NULL, _OVER);
2,853✔
2559
  }
2560

2561
  {
2562
    SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
36,993✔
2563
    if (pRaw == NULL) {
36,993✔
UNCOV
2564
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2565
      if (terrno != 0) code = terrno;
×
UNCOV
2566
      goto _OVER;
×
2567
    }
2568
    if ((code = mndTransAppendCommitlog(pTrans, pRaw)) != 0) {
36,993✔
UNCOV
2569
      sdbFreeRaw(pRaw);
×
2570
      goto _OVER;
×
2571
    }
2572
    code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
36,993✔
2573
    if (code != 0) {
36,993✔
UNCOV
2574
      mError("vgId:%d, failed to set raw status since %s at line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
2575
      goto _OVER;
×
2576
    }
2577
  }
2578

2579
  mInfo("vgId:%d, vgroup info after redistribute, replica:%d", newVg.vgId, newVg.replica);
36,993✔
2580
  for (int32_t i = 0; i < newVg.replica; ++i) {
122,044✔
2581
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
85,051✔
2582
  }
2583

2584
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
36,993✔
2585
  code = 0;
34,263✔
2586

2587
_OVER:
37,979✔
2588
  mndTransDrop(pTrans);
37,979✔
2589
  mndReleaseDb(pMnode, pDb);
37,979✔
2590
  TAOS_RETURN(code);
37,979✔
2591
}
2592

2593
static int32_t mndProcessRedistributeVgroupMsg(SRpcMsg *pReq) {
45,898✔
2594
  SMnode    *pMnode = pReq->info.node;
45,898✔
2595
  SDnodeObj *pNew1 = NULL;
45,898✔
2596
  SDnodeObj *pNew2 = NULL;
45,898✔
2597
  SDnodeObj *pNew3 = NULL;
45,898✔
2598
  SDnodeObj *pOld1 = NULL;
45,898✔
2599
  SDnodeObj *pOld2 = NULL;
45,898✔
2600
  SDnodeObj *pOld3 = NULL;
45,898✔
2601
  SVgObj    *pVgroup = NULL;
45,898✔
2602
  SDbObj    *pDb = NULL;
45,898✔
2603
  int32_t    code = -1;
45,898✔
2604
  int64_t    curMs = taosGetTimestampMs();
45,898✔
2605
  int32_t    newDnodeId[3] = {0};
45,898✔
2606
  int32_t    oldDnodeId[3] = {0};
45,898✔
2607
  int32_t    newIndex = -1;
45,898✔
2608
  int32_t    oldIndex = -1;
45,898✔
2609

2610
  SRedistributeVgroupReq req = {0};
45,898✔
2611
  if (tDeserializeSRedistributeVgroupReq(pReq->pCont, pReq->contLen, &req) != 0) {
45,898✔
UNCOV
2612
    code = TSDB_CODE_INVALID_MSG;
×
UNCOV
2613
    goto _OVER;
×
2614
  }
2615

2616
  mInfo("vgId:%d, start to redistribute vgroup to dnode %d:%d:%d", req.vgId, req.dnodeId1, req.dnodeId2, req.dnodeId3);
45,898✔
2617
  if ((code = mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_REDISTRIBUTE_VGROUP)) != 0) {
45,898✔
2618
    goto _OVER;
355✔
2619
  }
2620

2621
  pVgroup = mndAcquireVgroup(pMnode, req.vgId);
45,543✔
2622
  if (pVgroup == NULL) {
45,543✔
2623
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
2,139✔
2624
    if (terrno != 0) code = terrno;
2,139✔
2625
    goto _OVER;
2,139✔
2626
  }
2627
  if (pVgroup->mountVgId) {
43,404✔
UNCOV
2628
    code = TSDB_CODE_MND_MOUNT_OBJ_NOT_SUPPORT;
×
UNCOV
2629
    goto _OVER;
×
2630
  }
2631
  pDb = mndAcquireDb(pMnode, pVgroup->dbName);
43,404✔
2632
  if (pDb == NULL) {
43,404✔
UNCOV
2633
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2634
    if (terrno != 0) code = terrno;
×
UNCOV
2635
    goto _OVER;
×
2636
  }
2637

2638
  if (pVgroup->replica == 1) {
43,404✔
2639
    if (req.dnodeId1 <= 0 || req.dnodeId2 > 0 || req.dnodeId3 > 0) {
12,548✔
UNCOV
2640
      code = TSDB_CODE_MND_INVALID_REPLICA;
×
UNCOV
2641
      goto _OVER;
×
2642
    }
2643

2644
    if (req.dnodeId1 == pVgroup->vnodeGid[0].dnodeId) {
12,548✔
2645
      // terrno = TSDB_CODE_MND_VGROUP_UN_CHANGED;
UNCOV
2646
      code = 0;
×
UNCOV
2647
      goto _OVER;
×
2648
    }
2649

2650
    pNew1 = mndAcquireDnode(pMnode, req.dnodeId1);
12,548✔
2651
    if (pNew1 == NULL) {
12,548✔
UNCOV
2652
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2653
      if (terrno != 0) code = terrno;
×
2654
      goto _OVER;
×
2655
    }
2656
    if (!mndIsDnodeOnline(pNew1, curMs)) {
12,548✔
2657
      code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
23✔
2658
      goto _OVER;
23✔
2659
    }
2660

2661
    pOld1 = mndAcquireDnode(pMnode, pVgroup->vnodeGid[0].dnodeId);
12,525✔
2662
    if (pOld1 == NULL) {
12,525✔
UNCOV
2663
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2664
      if (terrno != 0) code = terrno;
×
2665
      goto _OVER;
×
2666
    }
2667
    if (!mndIsDnodeOnline(pOld1, curMs)) {
12,525✔
2668
      code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
24✔
2669
      goto _OVER;
24✔
2670
    }
2671

2672
    code = mndRedistributeVgroup(pMnode, pReq, pDb, pVgroup, pNew1, pOld1, NULL, NULL, NULL, NULL);
12,501✔
2673

2674
  } else if (pVgroup->replica == 3) {
30,856✔
2675
    if (req.dnodeId1 <= 0 || req.dnodeId2 <= 0 || req.dnodeId3 <= 0) {
29,384✔
2676
      code = TSDB_CODE_MND_INVALID_REPLICA;
2,852✔
2677
      goto _OVER;
2,852✔
2678
    }
2679

2680
    if (req.dnodeId1 == req.dnodeId2 || req.dnodeId1 == req.dnodeId3 || req.dnodeId2 == req.dnodeId3) {
26,532✔
2681
      code = TSDB_CODE_MND_INVALID_REPLICA;
713✔
2682
      goto _OVER;
713✔
2683
    }
2684

2685
    if (req.dnodeId1 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId1 != pVgroup->vnodeGid[1].dnodeId &&
25,819✔
2686
        req.dnodeId1 != pVgroup->vnodeGid[2].dnodeId) {
10,667✔
2687
      newDnodeId[++newIndex] = req.dnodeId1;
9,243✔
2688
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
9,243✔
2689
    }
2690

2691
    if (req.dnodeId2 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[1].dnodeId &&
25,819✔
2692
        req.dnodeId2 != pVgroup->vnodeGid[2].dnodeId) {
16,192✔
2693
      newDnodeId[++newIndex] = req.dnodeId2;
11,229✔
2694
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
11,229✔
2695
    }
2696

2697
    if (req.dnodeId3 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId3 != pVgroup->vnodeGid[1].dnodeId &&
25,819✔
2698
        req.dnodeId3 != pVgroup->vnodeGid[2].dnodeId) {
20,146✔
2699
      newDnodeId[++newIndex] = req.dnodeId3;
15,516✔
2700
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
15,516✔
2701
    }
2702

2703
    if (req.dnodeId1 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[0].dnodeId &&
25,819✔
2704
        req.dnodeId3 != pVgroup->vnodeGid[0].dnodeId) {
12,716✔
2705
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[0].dnodeId;
9,185✔
2706
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
9,185✔
2707
    }
2708

2709
    if (req.dnodeId1 != pVgroup->vnodeGid[1].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[1].dnodeId &&
25,819✔
2710
        req.dnodeId3 != pVgroup->vnodeGid[1].dnodeId) {
14,143✔
2711
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[1].dnodeId;
12,001✔
2712
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
12,001✔
2713
    }
2714

2715
    if (req.dnodeId1 != pVgroup->vnodeGid[2].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[2].dnodeId &&
25,819✔
2716
        req.dnodeId3 != pVgroup->vnodeGid[2].dnodeId) {
19,432✔
2717
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[2].dnodeId;
14,802✔
2718
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
14,802✔
2719
    }
2720

2721
    if (newDnodeId[0] != 0) {
25,819✔
2722
      pNew1 = mndAcquireDnode(pMnode, newDnodeId[0]);
24,752✔
2723
      if (pNew1 == NULL) {
24,752✔
UNCOV
2724
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2725
        if (terrno != 0) code = terrno;
×
UNCOV
2726
        goto _OVER;
×
2727
      }
2728
      if (!mndIsDnodeOnline(pNew1, curMs)) {
24,752✔
2729
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
723✔
2730
        goto _OVER;
723✔
2731
      }
2732
    }
2733

2734
    if (newDnodeId[1] != 0) {
25,096✔
2735
      pNew2 = mndAcquireDnode(pMnode, newDnodeId[1]);
8,340✔
2736
      if (pNew2 == NULL) {
8,340✔
UNCOV
2737
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2738
        if (terrno != 0) code = terrno;
×
UNCOV
2739
        goto _OVER;
×
2740
      }
2741
      if (!mndIsDnodeOnline(pNew2, curMs)) {
8,340✔
UNCOV
2742
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2743
        goto _OVER;
×
2744
      }
2745
    }
2746

2747
    if (newDnodeId[2] != 0) {
25,096✔
2748
      pNew3 = mndAcquireDnode(pMnode, newDnodeId[2]);
2,876✔
2749
      if (pNew3 == NULL) {
2,876✔
2750
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2751
        if (terrno != 0) code = terrno;
×
UNCOV
2752
        goto _OVER;
×
2753
      }
2754
      if (!mndIsDnodeOnline(pNew3, curMs)) {
2,876✔
UNCOV
2755
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2756
        goto _OVER;
×
2757
      }
2758
    }
2759

2760
    if (oldDnodeId[0] != 0) {
25,096✔
2761
      pOld1 = mndAcquireDnode(pMnode, oldDnodeId[0]);
24,029✔
2762
      if (pOld1 == NULL) {
24,029✔
2763
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2764
        if (terrno != 0) code = terrno;
×
UNCOV
2765
        goto _OVER;
×
2766
      }
2767
      if (!mndIsDnodeOnline(pOld1, curMs)) {
24,029✔
2768
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
23✔
2769
        goto _OVER;
23✔
2770
      }
2771
    }
2772

2773
    if (oldDnodeId[1] != 0) {
25,073✔
2774
      pOld2 = mndAcquireDnode(pMnode, oldDnodeId[1]);
8,317✔
2775
      if (pOld2 == NULL) {
8,317✔
2776
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2777
        if (terrno != 0) code = terrno;
×
UNCOV
2778
        goto _OVER;
×
2779
      }
2780
      if (!mndIsDnodeOnline(pOld2, curMs)) {
8,317✔
2781
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2782
        goto _OVER;
×
2783
      }
2784
    }
2785

2786
    if (oldDnodeId[2] != 0) {
25,073✔
2787
      pOld3 = mndAcquireDnode(pMnode, oldDnodeId[2]);
2,853✔
2788
      if (pOld3 == NULL) {
2,853✔
2789
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2790
        if (terrno != 0) code = terrno;
×
UNCOV
2791
        goto _OVER;
×
2792
      }
2793
      if (!mndIsDnodeOnline(pOld3, curMs)) {
2,853✔
UNCOV
2794
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2795
        goto _OVER;
×
2796
      }
2797
    }
2798

2799
    if (pNew1 == NULL && pOld1 == NULL && pNew2 == NULL && pOld2 == NULL && pNew3 == NULL && pOld3 == NULL) {
25,073✔
2800
      // terrno = TSDB_CODE_MND_VGROUP_UN_CHANGED;
2801
      code = 0;
1,067✔
2802
      goto _OVER;
1,067✔
2803
    }
2804

2805
    code = mndRedistributeVgroup(pMnode, pReq, pDb, pVgroup, pNew1, pOld1, pNew2, pOld2, pNew3, pOld3);
24,006✔
2806

2807
  } else if (pVgroup->replica == 2) {
1,472✔
2808
    if (req.dnodeId1 <= 0 || req.dnodeId2 <= 0) {
1,472✔
UNCOV
2809
      code = TSDB_CODE_MND_INVALID_REPLICA;
×
UNCOV
2810
      goto _OVER;
×
2811
    }
2812

2813
    if (req.dnodeId1 == req.dnodeId2) {
1,472✔
2814
      code = TSDB_CODE_MND_INVALID_REPLICA;
×
2815
      goto _OVER;
×
2816
    }
2817

2818
    if (req.dnodeId1 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId1 != pVgroup->vnodeGid[1].dnodeId) {
1,472✔
2819
      newDnodeId[++newIndex] = req.dnodeId1;
1,472✔
2820
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
1,472✔
2821
    }
2822

2823
    if (req.dnodeId2 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[1].dnodeId) {
1,472✔
2824
      newDnodeId[++newIndex] = req.dnodeId2;
1,472✔
2825
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
1,472✔
2826
    }
2827

2828
    if (req.dnodeId1 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[0].dnodeId) {
1,472✔
2829
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[0].dnodeId;
1,472✔
2830
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
1,472✔
2831
    }
2832

2833
    if (req.dnodeId1 != pVgroup->vnodeGid[1].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[1].dnodeId) {
1,472✔
2834
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[1].dnodeId;
1,472✔
2835
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
1,472✔
2836
    }
2837

2838
    if (newDnodeId[0] != 0) {
1,472✔
2839
      pNew1 = mndAcquireDnode(pMnode, newDnodeId[0]);
1,472✔
2840
      if (pNew1 == NULL) {
1,472✔
UNCOV
2841
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2842
        if (terrno != 0) code = terrno;
×
UNCOV
2843
        goto _OVER;
×
2844
      }
2845
      if (!mndIsDnodeOnline(pNew1, curMs)) {
1,472✔
UNCOV
2846
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2847
        goto _OVER;
×
2848
      }
2849
    }
2850

2851
    if (newDnodeId[1] != 0) {
1,472✔
2852
      pNew2 = mndAcquireDnode(pMnode, newDnodeId[1]);
1,472✔
2853
      if (pNew2 == NULL) {
1,472✔
UNCOV
2854
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2855
        if (terrno != 0) code = terrno;
×
UNCOV
2856
        goto _OVER;
×
2857
      }
2858
      if (!mndIsDnodeOnline(pNew2, curMs)) {
1,472✔
UNCOV
2859
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2860
        goto _OVER;
×
2861
      }
2862
    }
2863

2864
    if (oldDnodeId[0] != 0) {
1,472✔
2865
      pOld1 = mndAcquireDnode(pMnode, oldDnodeId[0]);
1,472✔
2866
      if (pOld1 == NULL) {
1,472✔
2867
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2868
        if (terrno != 0) code = terrno;
×
UNCOV
2869
        goto _OVER;
×
2870
      }
2871
      if (!mndIsDnodeOnline(pOld1, curMs)) {
1,472✔
2872
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2873
        goto _OVER;
×
2874
      }
2875
    }
2876

2877
    if (oldDnodeId[1] != 0) {
1,472✔
2878
      pOld2 = mndAcquireDnode(pMnode, oldDnodeId[1]);
1,472✔
2879
      if (pOld2 == NULL) {
1,472✔
2880
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2881
        if (terrno != 0) code = terrno;
×
UNCOV
2882
        goto _OVER;
×
2883
      }
2884
      if (!mndIsDnodeOnline(pOld2, curMs)) {
1,472✔
2885
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2886
        goto _OVER;
×
2887
      }
2888
    }
2889

2890
    if (pNew1 == NULL && pOld1 == NULL && pNew2 == NULL && pOld2 == NULL) {
1,472✔
2891
      // terrno = TSDB_CODE_MND_VGROUP_UN_CHANGED;
2892
      code = 0;
×
2893
      goto _OVER;
×
2894
    }
2895

2896
    code = mndRedistributeVgroup(pMnode, pReq, pDb, pVgroup, pNew1, pOld1, pNew2, pOld2, NULL, NULL);
1,472✔
2897
  } else {
2898
    code = TSDB_CODE_MND_REQ_REJECTED;
×
UNCOV
2899
    goto _OVER;
×
2900
  }
2901

2902
  if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
37,979✔
2903

2904
  char obj[33] = {0};
37,979✔
2905
  (void)tsnprintf(obj, sizeof(obj), "%d", req.vgId);
37,979✔
2906

2907
  auditRecord(pReq, pMnode->clusterId, "RedistributeVgroup", "", obj, req.sql, req.sqlLen);
37,979✔
2908

2909
_OVER:
45,898✔
2910
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
45,898✔
2911
    mError("vgId:%d, failed to redistribute to dnode %d:%d:%d since %s", req.vgId, req.dnodeId1, req.dnodeId2,
10,568✔
2912
           req.dnodeId3, tstrerror(code));
2913
  }
2914

2915
  mndReleaseDnode(pMnode, pNew1);
45,898✔
2916
  mndReleaseDnode(pMnode, pNew2);
45,898✔
2917
  mndReleaseDnode(pMnode, pNew3);
45,898✔
2918
  mndReleaseDnode(pMnode, pOld1);
45,898✔
2919
  mndReleaseDnode(pMnode, pOld2);
45,898✔
2920
  mndReleaseDnode(pMnode, pOld3);
45,898✔
2921
  mndReleaseVgroup(pMnode, pVgroup);
45,898✔
2922
  mndReleaseDb(pMnode, pDb);
45,898✔
2923
  tFreeSRedistributeVgroupReq(&req);
45,898✔
2924

2925
  TAOS_RETURN(code);
45,898✔
2926
}
2927

2928
static void *mndBuildSForceBecomeFollowerReq(SMnode *pMnode, SVgObj *pVgroup, int32_t dnodeId, int32_t *pContLen) {
6,740✔
2929
  SForceBecomeFollowerReq balanceReq = {
6,740✔
2930
      .vgId = pVgroup->vgId,
6,740✔
2931
  };
2932

2933
  int32_t contLen = tSerializeSForceBecomeFollowerReq(NULL, 0, &balanceReq);
6,740✔
2934
  if (contLen < 0) {
6,740✔
UNCOV
2935
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
2936
    return NULL;
×
2937
  }
2938
  contLen += sizeof(SMsgHead);
6,740✔
2939

2940
  void *pReq = taosMemoryMalloc(contLen);
6,740✔
2941
  if (pReq == NULL) {
6,740✔
UNCOV
2942
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
2943
    return NULL;
×
2944
  }
2945

2946
  SMsgHead *pHead = pReq;
6,740✔
2947
  pHead->contLen = htonl(contLen);
6,740✔
2948
  pHead->vgId = htonl(pVgroup->vgId);
6,740✔
2949

2950
  if (tSerializeSForceBecomeFollowerReq((char *)pReq + sizeof(SMsgHead), contLen, &balanceReq) < 0) {
6,740✔
UNCOV
2951
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
2952
    taosMemoryFree(pReq);
×
UNCOV
2953
    return NULL;
×
2954
  }
2955
  *pContLen = contLen;
6,740✔
2956
  return pReq;
6,740✔
2957
}
2958

2959
int32_t mndAddBalanceVgroupLeaderAction(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup, int32_t dnodeId) {
6,740✔
2960
  int32_t    code = 0;
6,740✔
2961
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
6,740✔
2962
  if (pDnode == NULL) {
6,740✔
UNCOV
2963
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2964
    if (terrno != 0) code = terrno;
×
UNCOV
2965
    TAOS_RETURN(code);
×
2966
  }
2967

2968
  STransAction action = {0};
6,740✔
2969
  action.epSet = mndGetDnodeEpset(pDnode);
6,740✔
2970
  mndReleaseDnode(pMnode, pDnode);
6,740✔
2971

2972
  int32_t contLen = 0;
6,740✔
2973
  void   *pReq = mndBuildSForceBecomeFollowerReq(pMnode, pVgroup, dnodeId, &contLen);
6,740✔
2974
  if (pReq == NULL) {
6,740✔
UNCOV
2975
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2976
    if (terrno != 0) code = terrno;
×
2977
    TAOS_RETURN(code);
×
2978
  }
2979

2980
  action.pCont = pReq;
6,740✔
2981
  action.contLen = contLen;
6,740✔
2982
  action.msgType = TDMT_SYNC_FORCE_FOLLOWER;
6,740✔
2983

2984
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
6,740✔
UNCOV
2985
    taosMemoryFree(pReq);
×
UNCOV
2986
    TAOS_RETURN(code);
×
2987
  }
2988

2989
  TAOS_RETURN(code);
6,740✔
2990
}
2991

2992
static void *mndBuildAlterVnodeElectBaselineReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId,
40,440✔
2993
                                          int32_t *pContLen, int32_t ms) {
2994
  SAlterVnodeElectBaselineReq alterReq = {
40,440✔
2995
      .vgId = pVgroup->vgId,
40,440✔
2996
      .electBaseLine = ms,
2997
  };
2998

2999
  int32_t contLen = tSerializeSAlterVnodeReplicaReq(NULL, 0, &alterReq);
40,440✔
3000
  if (contLen < 0) {
40,440✔
3001
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
3002
    return NULL;
×
3003
  }
3004

3005
  void *pReq = taosMemoryMalloc(contLen);
40,440✔
3006
  if (pReq == NULL) {
40,440✔
UNCOV
3007
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
3008
    return NULL;
×
3009
  }
3010

3011
  if (tSerializeSAlterVnodeReplicaReq(pReq, contLen, &alterReq) < 0) {
40,440✔
UNCOV
3012
    mError("vgId:%d, failed to serialize alter vnode req,since %s", alterReq.vgId, terrstr());
×
UNCOV
3013
    taosMemoryFree(pReq);
×
UNCOV
3014
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
3015
    return NULL;
×
3016
  }
3017
  *pContLen = contLen;
40,440✔
3018
  return pReq;
40,440✔
3019
}
3020

3021
static int32_t mndAddAlterVnodeElectionBaselineActionToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId, int32_t ms) {
40,440✔
3022
  int32_t    code = 0;
40,440✔
3023
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
40,440✔
3024
  if (pDnode == NULL) {
40,440✔
UNCOV
3025
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3026
    if (terrno != 0) code = terrno;
×
3027
    TAOS_RETURN(code);
×
3028
  }
3029

3030
  STransAction action = {0};
40,440✔
3031
  action.epSet = mndGetDnodeEpset(pDnode);
40,440✔
3032
  mndReleaseDnode(pMnode, pDnode);
40,440✔
3033

3034
  int32_t contLen = 0;
40,440✔
3035
  void   *pReq = mndBuildAlterVnodeElectBaselineReq(pMnode, pDb, pVgroup, dnodeId, &contLen, ms);
40,440✔
3036
  if (pReq == NULL) {
40,440✔
3037
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3038
    if (terrno != 0) code = terrno;
×
3039
    TAOS_RETURN(code);
×
3040
  }
3041

3042
  action.pCont = pReq;
40,440✔
3043
  action.contLen = contLen;
40,440✔
3044
  action.msgType = TDMT_VND_ALTER_ELECTBASELINE;
40,440✔
3045
  action.groupId = pVgroup->vgId;
40,440✔
3046

3047
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
40,440✔
UNCOV
3048
    taosMemoryFree(pReq);
×
UNCOV
3049
    TAOS_RETURN(code);
×
3050
  }
3051

3052
  TAOS_RETURN(code);
40,440✔
3053
}
3054

3055
static int32_t mndAddAlterVgroupElectionBaselineActionToTrans(SMnode *pMnode, SVgObj *pVgroup, STrans *pTrans, int32_t index){
13,480✔
3056
  int32_t code = 0;
13,480✔
3057
  SSdb   *pSdb = pMnode->pSdb;
13,480✔
3058

3059
  int32_t vgid = pVgroup->vgId;
13,480✔
3060
  int8_t  replica = pVgroup->replica;
13,480✔
3061

3062
  if (pVgroup->replica <= 1) {
13,480✔
3063
    mInfo("trans:%d, vgid:%d no need to balance, replica:%d", pTrans->id, vgid, replica);
×
3064
    return -1;
×
3065
  }
3066

3067
  for(int32_t i = 0; i < 3; i++){
53,920✔
3068
    if(i == index%3){
40,440✔
3069
      mInfo("trans:%d, balance leader to dnode:%d", pTrans->id, pVgroup->vnodeGid[i].dnodeId);
6,740✔
3070
      TAOS_CHECK_RETURN(mndAddAlterVnodeElectionBaselineActionToTrans(pMnode, pTrans, NULL, pVgroup,
6,740✔
3071
                                                                      pVgroup->vnodeGid[i].dnodeId, 1500));
3072
    }
3073
    else{
3074
    TAOS_CHECK_RETURN(
33,700✔
3075
        mndAddAlterVnodeElectionBaselineActionToTrans(pMnode, pTrans, NULL, pVgroup, pVgroup->vnodeGid[i].dnodeId, 5000));
3076
    }
3077
  }
3078
  return code; 
13,480✔
3079
}
3080

3081
int32_t mndAddVgroupBalanceToTrans(SMnode *pMnode, SVgObj *pVgroup, STrans *pTrans, int32_t index) {
7,313✔
3082
  int32_t code = 0;
7,313✔
3083
  SSdb   *pSdb = pMnode->pSdb;
7,313✔
3084

3085
  int32_t vgid = pVgroup->vgId;
7,313✔
3086
  int8_t  replica = pVgroup->replica;
7,313✔
3087

3088
  if (pVgroup->replica <= 1) {
7,313✔
3089
    mInfo("trans:%d, vgid:%d no need to balance, replica:%d", pTrans->id, vgid, replica);
8✔
3090
    return -1;
8✔
3091
  }
3092

3093
  int32_t dnodeId = 0;
7,305✔
3094

3095
  for (int i = 0; i < replica; i++) {
18,200✔
3096
    if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_LEADER) {
17,635✔
3097
      dnodeId = pVgroup->vnodeGid[i].dnodeId;
6,740✔
3098
      break;
6,740✔
3099
    }
3100
  }
3101

3102
  bool       exist = false;
7,305✔
3103
  bool       online = false;
7,305✔
3104
  int64_t    curMs = taosGetTimestampMs();
7,305✔
3105
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
7,305✔
3106
  if (pDnode != NULL) {
7,305✔
3107
    exist = true;
6,740✔
3108
    online = mndIsDnodeOnline(pDnode, curMs);
6,740✔
3109
    mndReleaseDnode(pMnode, pDnode);
6,740✔
3110
  }
3111

3112
  if (exist && online) {
14,045✔
3113
    mInfo("trans:%d, vgid:%d force drop leader from dnode:%d", pTrans->id, vgid, dnodeId);    
6,740✔
3114
    TAOS_CHECK_RETURN(mndAddAlterVgroupElectionBaselineActionToTrans(pMnode, pVgroup, pTrans, index));
6,740✔
3115

3116
    if ((code = mndAddBalanceVgroupLeaderAction(pMnode, pTrans, pVgroup, dnodeId)) != 0) {
6,740✔
UNCOV
3117
      mError("trans:%d, vgid:%d failed to be balanced to dnode:%d", pTrans->id, vgid, dnodeId);
×
UNCOV
3118
      TAOS_RETURN(code);
×
3119
    }
3120

3121
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, NULL, pVgroup));
6,740✔
3122

3123
    TAOS_CHECK_RETURN(mndAddAlterVgroupElectionBaselineActionToTrans(pMnode, pVgroup, pTrans, -1));
6,740✔
3124

3125
    SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName);
6,740✔
3126
    if (pDb == NULL) {
6,740✔
UNCOV
3127
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3128
      if (terrno != 0) code = terrno;
×
UNCOV
3129
      mError("trans:%d, vgid:%d failed to be balanced to dnode:%d, because db not exist", pTrans->id, vgid, dnodeId);
×
UNCOV
3130
      TAOS_RETURN(code);
×
3131
    }
3132

3133
    mndReleaseDb(pMnode, pDb);
6,740✔
3134
  } else {
3135
    mInfo("trans:%d, vgid:%d cant be balanced to dnode:%d, exist:%d, online:%d", pTrans->id, vgid, dnodeId, exist,
565✔
3136
          online);
3137
  }
3138

3139
  TAOS_RETURN(code);
7,305✔
3140
}
3141

3142
extern int32_t mndProcessVgroupBalanceLeaderMsgImp(SRpcMsg *pReq);
3143

3144
int32_t mndProcessVgroupBalanceLeaderMsg(SRpcMsg *pReq) { return mndProcessVgroupBalanceLeaderMsgImp(pReq); }
2,848✔
3145

3146
#ifndef TD_ENTERPRISE
3147
int32_t mndProcessVgroupBalanceLeaderMsgImp(SRpcMsg *pReq) { return 0; }
3148
#endif
3149

3150
static int32_t mndCheckDnodeMemory(SMnode *pMnode, SDbObj *pOldDb, SDbObj *pNewDb, SVgObj *pOldVgroup,
207,657✔
3151
                                   SVgObj *pNewVgroup, SArray *pArray) {
3152
  for (int32_t i = 0; i < (int32_t)taosArrayGetSize(pArray); ++i) {
604,462✔
3153
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
396,805✔
3154
    bool       inVgroup = false;
396,805✔
3155
    int64_t    oldMemUsed = 0;
396,805✔
3156
    int64_t    newMemUsed = 0;
396,805✔
3157
    mDebug("db:%s, vgId:%d, check dnode:%d, avail:%" PRId64 " used:%" PRId64, pNewVgroup->dbName, pNewVgroup->vgId,
396,805✔
3158
           pDnode->id, pDnode->memAvail, pDnode->memUsed);
3159
    for (int32_t j = 0; j < pOldVgroup->replica; ++j) {
1,114,514✔
3160
      SVnodeGid *pVgId = &pOldVgroup->vnodeGid[j];
717,709✔
3161
      if (pDnode->id == pVgId->dnodeId) {
717,709✔
3162
        oldMemUsed = mndGetVgroupMemory(pMnode, pOldDb, pOldVgroup);
314,625✔
3163
        inVgroup = true;
314,625✔
3164
      }
3165
    }
3166
    for (int32_t j = 0; j < pNewVgroup->replica; ++j) {
1,114,514✔
3167
      SVnodeGid *pVgId = &pNewVgroup->vnodeGid[j];
717,709✔
3168
      if (pDnode->id == pVgId->dnodeId) {
717,709✔
3169
        newMemUsed = mndGetVgroupMemory(pMnode, pNewDb, pNewVgroup);
314,625✔
3170
        inVgroup = true;
314,625✔
3171
      }
3172
    }
3173

3174
    mDebug("db:%s, vgId:%d, memory in dnode:%d, oldUsed:%" PRId64 ", newUsed:%" PRId64, pNewVgroup->dbName,
396,805✔
3175
           pNewVgroup->vgId, pDnode->id, oldMemUsed, newMemUsed);
3176

3177
    pDnode->memUsed = pDnode->memUsed - oldMemUsed + newMemUsed;
396,805✔
3178
    if (pDnode->memAvail - pDnode->memUsed <= 0) {
396,805✔
UNCOV
3179
      mError("db:%s, vgId:%d, no enough memory in dnode:%d, avail:%" PRId64 " used:%" PRId64, pNewVgroup->dbName,
×
3180
             pNewVgroup->vgId, pDnode->id, pDnode->memAvail, pDnode->memUsed);
UNCOV
3181
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE);
×
3182
    } else if (inVgroup) {
396,805✔
3183
      mInfo("db:%s, vgId:%d, memory in dnode:%d, avail:%" PRId64 " used:%" PRId64, pNewVgroup->dbName, pNewVgroup->vgId,
314,625✔
3184
            pDnode->id, pDnode->memAvail, pDnode->memUsed);
3185
    } else {
3186
    }
3187
  }
3188
  return 0;
207,657✔
3189
}
3190

3191
int32_t mndBuildAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pOldDb, SDbObj *pNewDb, SVgObj *pVgroup,
243,306✔
3192
                                  SArray *pArray, SVgObj *pNewVgroup) {
3193
  int32_t code = 0;
243,306✔
3194
  memcpy(pNewVgroup, pVgroup, sizeof(SVgObj));
243,306✔
3195

3196
  if (pVgroup->replica <= 0 || pVgroup->replica == pNewDb->cfg.replications) {
243,306✔
3197
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfigAction(pMnode, pTrans, pNewDb, pVgroup));
207,657✔
3198
    TAOS_CHECK_RETURN(mndCheckDnodeMemory(pMnode, pOldDb, pNewDb, pNewVgroup, pVgroup, pArray));
207,657✔
3199
    return 0;
207,657✔
3200
  }
3201

3202
  // mndTransSetGroupParallel(pTrans);
3203

3204
  if (pNewDb->cfg.replications == 3) {
35,649✔
3205
    mInfo("trans:%d, db:%s, vgId:%d, will add 2 vnodes, vn:0 dnode:%d", pTrans->id, pVgroup->dbName, pVgroup->vgId,
29,576✔
3206
          pVgroup->vnodeGid[0].dnodeId);
3207

3208
    // add second
3209
    if (pNewVgroup->replica == 1) {
29,576✔
3210
      TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, pNewVgroup, pArray));
29,576✔
3211
    }
3212

3213
    // learner stage
3214
    pNewVgroup->vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
28,839✔
3215
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
28,839✔
3216
    TAOS_CHECK_RETURN(
28,839✔
3217
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3218

3219
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &pNewVgroup->vnodeGid[1]));
28,839✔
3220

3221
    // follower stage
3222
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
28,839✔
3223
    TAOS_CHECK_RETURN(mndAddAlterVnodeTypeAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
28,839✔
3224
    TAOS_CHECK_RETURN(
28,839✔
3225
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3226

3227
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
28,839✔
3228

3229
    // add third
3230
    if (pNewVgroup->replica == 2) {
28,839✔
3231
      TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, pNewVgroup, pArray));
28,839✔
3232
    }
3233

3234
    pNewVgroup->vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
28,670✔
3235
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
28,670✔
3236
    pNewVgroup->vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_VOTER;
28,670✔
3237
    TAOS_CHECK_RETURN(
28,670✔
3238
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3239
    TAOS_CHECK_RETURN(
28,670✔
3240
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
3241
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &pNewVgroup->vnodeGid[2]));
28,670✔
3242

3243
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
28,670✔
3244
  } else if (pNewDb->cfg.replications == 1) {
6,073✔
3245
    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,595✔
3246
          pVgroup->dbName, pVgroup->vgId, pVgroup->vnodeGid[0].dnodeId, pVgroup->vnodeGid[1].dnodeId,
3247
          pVgroup->vnodeGid[2].dnodeId);
3248

3249
    SVnodeGid del1 = {0};
4,595✔
3250
    SVnodeGid del2 = {0};
4,595✔
3251
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroup(pMnode, pTrans, pNewVgroup, pArray, &del1));
4,595✔
3252
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &del1, true));
4,595✔
3253
    TAOS_CHECK_RETURN(
4,595✔
3254
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3255
    TAOS_CHECK_RETURN(
4,595✔
3256
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
3257
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
4,595✔
3258

3259
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroup(pMnode, pTrans, pNewVgroup, pArray, &del2));
4,595✔
3260
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &del2, true));
4,595✔
3261
    TAOS_CHECK_RETURN(
4,595✔
3262
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3263
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
4,595✔
3264
  } else if (pNewDb->cfg.replications == 2) {
1,478✔
3265
    mInfo("trans:%d, db:%s, vgId:%d, will add 1 vnode, vn:0 dnode:%d", pTrans->id, pVgroup->dbName, pVgroup->vgId,
1,478✔
3266
          pVgroup->vnodeGid[0].dnodeId);
3267

3268
    // add second
3269
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, pNewVgroup, pArray));
1,478✔
3270

3271
    // learner stage
3272
    pNewVgroup->vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
1,478✔
3273
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
1,478✔
3274
    TAOS_CHECK_RETURN(
1,478✔
3275
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3276

3277
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &pNewVgroup->vnodeGid[1]));
1,478✔
3278

3279
    // follower stage
3280
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
1,478✔
3281
    TAOS_CHECK_RETURN(mndAddAlterVnodeTypeAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
1,478✔
3282
    TAOS_CHECK_RETURN(
1,478✔
3283
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3284

3285
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
1,478✔
3286
  } else {
UNCOV
3287
    return -1;
×
3288
  }
3289

3290
  mndSortVnodeGid(pNewVgroup);
34,743✔
3291

3292
  {
3293
    SSdbRaw *pVgRaw = mndVgroupActionEncode(pNewVgroup);
34,743✔
3294
    if (pVgRaw == NULL) {
34,743✔
UNCOV
3295
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3296
      if (terrno != 0) code = terrno;
×
UNCOV
3297
      TAOS_RETURN(code);
×
3298
    }
3299
    if ((code = mndTransAppendCommitlog(pTrans, pVgRaw)) != 0) {
34,743✔
UNCOV
3300
      sdbFreeRaw(pVgRaw);
×
UNCOV
3301
      TAOS_RETURN(code);
×
3302
    }
3303
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
34,743✔
3304
    if (code != 0) {
34,743✔
UNCOV
3305
      mError("vgId:%d, failed to set raw status since %s at line:%d", pNewVgroup->vgId, tstrerror(code), __LINE__);
×
UNCOV
3306
      TAOS_RETURN(code);
×
3307
    }
3308
  }
3309

3310
  TAOS_RETURN(code);
34,743✔
3311
}
3312

UNCOV
3313
int32_t mndBuildRaftAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pOldDb, SDbObj *pNewDb, SVgObj *pVgroup,
×
3314
                                      SArray *pArray) {
UNCOV
3315
  int32_t code = 0;
×
UNCOV
3316
  SVgObj  newVgroup = {0};
×
UNCOV
3317
  memcpy(&newVgroup, pVgroup, sizeof(SVgObj));
×
3318

UNCOV
3319
  if (pVgroup->replica <= 0 || pVgroup->replica == pNewDb->cfg.replications) {
×
3320
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfigAction(pMnode, pTrans, pNewDb, pVgroup));
×
3321
    TAOS_CHECK_RETURN(mndCheckDnodeMemory(pMnode, pOldDb, pNewDb, &newVgroup, pVgroup, pArray));
×
3322
    return 0;
×
3323
  }
3324

3325
  mndTransSetSerial(pTrans);
×
3326

UNCOV
3327
  mInfo("trans:%d, vgId:%d, alter vgroup, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id, pVgroup->vgId,
×
3328
        pVgroup->syncConfChangeVer, pVgroup->version, pVgroup->replica);
3329

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

3334
    // add second
UNCOV
3335
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVgroup, pArray));
×
3336
    // add third
UNCOV
3337
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVgroup, pArray));
×
3338

3339
    // add learner stage
3340
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3341
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3342
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
UNCOV
3343
    TAOS_CHECK_RETURN(
×
3344
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3345
    mInfo("trans:%d, vgId:%d, add change config, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id,
×
3346
          pVgroup->vgId, newVgroup.syncConfChangeVer, pVgroup->version, pVgroup->replica);
3347
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &newVgroup.vnodeGid[1]));
×
UNCOV
3348
    mInfo("trans:%d, vgId:%d, create vnode, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id, pVgroup->vgId,
×
3349
          newVgroup.syncConfChangeVer, pVgroup->version, pVgroup->replica);
3350
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &newVgroup.vnodeGid[2]));
×
UNCOV
3351
    mInfo("trans:%d, vgId:%d, create vnode, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id, pVgroup->vgId,
×
3352
          newVgroup.syncConfChangeVer, pVgroup->version, pVgroup->replica);
3353

3354
    // check learner
3355
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3356
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3357
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3358
    TAOS_CHECK_RETURN(
×
3359
        mndAddCheckLearnerCatchupAction(pMnode, pTrans, pNewDb, &newVgroup, newVgroup.vnodeGid[1].dnodeId));
3360
    TAOS_CHECK_RETURN(
×
3361
        mndAddCheckLearnerCatchupAction(pMnode, pTrans, pNewDb, &newVgroup, newVgroup.vnodeGid[2].dnodeId));
3362

3363
    // change raft type
UNCOV
3364
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3365
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3366
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3367
    TAOS_CHECK_RETURN(
×
3368
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3369

3370
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
3371

3372
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3373
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3374
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3375
    TAOS_CHECK_RETURN(
×
3376
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3377

UNCOV
3378
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
3379

3380
    SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
×
3381
    if (pVgRaw == NULL) {
×
3382
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3383
      if (terrno != 0) code = terrno;
×
UNCOV
3384
      TAOS_RETURN(code);
×
3385
    }
UNCOV
3386
    if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
×
UNCOV
3387
      sdbFreeRaw(pVgRaw);
×
UNCOV
3388
      TAOS_RETURN(code);
×
3389
    }
3390
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
3391
    if (code != 0) {
×
3392
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
3393
             __LINE__);
UNCOV
3394
      TAOS_RETURN(code);
×
3395
    }
UNCOV
3396
  } else if (newVgroup.replica == 3 && pNewDb->cfg.replications == 1) {
×
3397
    mInfo("db:%s, vgId:%d, will remove 2 vnodes, vn:0 dnode:%d vn:1 dnode:%d vn:2 dnode:%d", pVgroup->dbName,
×
3398
          pVgroup->vgId, pVgroup->vnodeGid[0].dnodeId, pVgroup->vnodeGid[1].dnodeId, pVgroup->vnodeGid[2].dnodeId);
3399

3400
    SVnodeGid del1 = {0};
×
UNCOV
3401
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroupWithoutSave(pMnode, pTrans, &newVgroup, pArray, &del1));
×
3402

3403
    TAOS_CHECK_RETURN(
×
3404
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3405

3406
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
3407

3408
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &del1, true));
×
3409

UNCOV
3410
    SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
×
3411
    if (pVgRaw == NULL) {
×
3412
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3413
      if (terrno != 0) code = terrno;
×
UNCOV
3414
      TAOS_RETURN(code);
×
3415
    }
3416
    if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
×
3417
      sdbFreeRaw(pVgRaw);
×
UNCOV
3418
      TAOS_RETURN(code);
×
3419
    }
UNCOV
3420
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
3421
    if (code != 0) {
×
3422
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
3423
             __LINE__);
UNCOV
3424
      TAOS_RETURN(code);
×
3425
    }
3426

UNCOV
3427
    SVnodeGid del2 = {0};
×
3428
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroupWithoutSave(pMnode, pTrans, &newVgroup, pArray, &del2));
×
3429

UNCOV
3430
    TAOS_CHECK_RETURN(
×
3431
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3432

3433
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
3434

3435
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &del2, true));
×
3436

3437
    pVgRaw = mndVgroupActionEncode(&newVgroup);
×
3438
    if (pVgRaw == NULL) {
×
3439
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3440
      if (terrno != 0) code = terrno;
×
3441
      TAOS_RETURN(code);
×
3442
    }
3443
    if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
×
UNCOV
3444
      sdbFreeRaw(pVgRaw);
×
3445
      TAOS_RETURN(code);
×
3446
    }
3447
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
UNCOV
3448
    if (code != 0) {
×
3449
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
3450
             __LINE__);
UNCOV
3451
      TAOS_RETURN(code);
×
3452
    }
3453
  } else {
UNCOV
3454
    return -1;
×
3455
  }
3456

UNCOV
3457
  mndSortVnodeGid(&newVgroup);
×
3458

3459
  {
3460
    SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
×
UNCOV
3461
    if (pVgRaw == NULL) {
×
3462
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3463
      if (terrno != 0) code = terrno;
×
3464
      TAOS_RETURN(code);
×
3465
    }
3466
    if ((code = mndTransAppendCommitlog(pTrans, pVgRaw)) != 0) {
×
UNCOV
3467
      sdbFreeRaw(pVgRaw);
×
3468
      TAOS_RETURN(code);
×
3469
    }
3470
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
UNCOV
3471
    if (code != 0) {
×
3472
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
3473
             __LINE__);
3474
      TAOS_RETURN(code);
×
3475
    }
3476
  }
3477

UNCOV
3478
  TAOS_RETURN(code);
×
3479
}
3480

3481
int32_t mndBuildRestoreAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *db, SVgObj *pVgroup, SDnodeObj *pDnode,
6,170✔
3482
                                         SDnodeObj *pAnotherDnode) {
3483
  int32_t code = 0;
6,170✔
3484
  SVgObj  newVgroup = {0};
6,170✔
3485
  memcpy(&newVgroup, pVgroup, sizeof(SVgObj));
6,170✔
3486

3487
  mInfo("trans:%d, db:%s, vgId:%d, restore vnodes, vn:0 dnode:%d", pTrans->id, pVgroup->dbName, pVgroup->vgId,
6,170✔
3488
        pVgroup->vnodeGid[0].dnodeId);
3489

3490
  if (newVgroup.replica == 1) {
6,170✔
3491
    int selected = 0;
×
3492
    for (int i = 0; i < newVgroup.replica; i++) {
×
3493
      newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3494
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
3495
        selected = i;
×
3496
      }
3497
    }
UNCOV
3498
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, db, &newVgroup, &newVgroup.vnodeGid[selected]));
×
3499
  } else if (newVgroup.replica == 2) {
6,170✔
UNCOV
3500
    for (int i = 0; i < newVgroup.replica; i++) {
×
UNCOV
3501
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
UNCOV
3502
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3503
      } else {
UNCOV
3504
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3505
      }
3506
    }
UNCOV
3507
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pAnotherDnode));
×
3508

UNCOV
3509
    for (int i = 0; i < newVgroup.replica; i++) {
×
UNCOV
3510
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
UNCOV
3511
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3512
      } else {
UNCOV
3513
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3514
      }
3515
    }
3516
    TAOS_CHECK_RETURN(mndRestoreAddCreateVnodeAction(pMnode, pTrans, db, &newVgroup, pDnode));
×
3517

3518
    for (int i = 0; i < newVgroup.replica; i++) {
×
3519
      newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3520
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
3521
      }
3522
    }
3523
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pDnode));
×
UNCOV
3524
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pAnotherDnode));
×
3525
  } else if (newVgroup.replica == 3) {
6,170✔
3526
    for (int i = 0; i < newVgroup.replica; i++) {
24,680✔
3527
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
18,510✔
3528
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_LEARNER;
6,170✔
3529
      } else {
3530
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
12,340✔
3531
      }
3532
    }
3533
    TAOS_CHECK_RETURN(mndRestoreAddCreateVnodeAction(pMnode, pTrans, db, &newVgroup, pDnode));
6,170✔
3534

3535
    for (int i = 0; i < newVgroup.replica; i++) {
24,680✔
3536
      newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
18,510✔
3537
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
18,510✔
3538
      }
3539
    }
3540
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pDnode));
6,170✔
3541
  }
3542
  SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
6,170✔
3543
  if (pVgRaw == NULL) {
6,170✔
3544
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3545
    if (terrno != 0) code = terrno;
×
UNCOV
3546
    TAOS_RETURN(code);
×
3547
  }
3548
  if ((code = mndTransAppendCommitlog(pTrans, pVgRaw)) != 0) {
6,170✔
3549
    sdbFreeRaw(pVgRaw);
×
UNCOV
3550
    TAOS_RETURN(code);
×
3551
  }
3552
  code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
6,170✔
3553
  if (code != 0) {
6,170✔
UNCOV
3554
    mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code), __LINE__);
×
UNCOV
3555
    TAOS_RETURN(code);
×
3556
  }
3557

3558
  TAOS_RETURN(code);
6,170✔
3559
}
3560

UNCOV
3561
static int32_t mndAddAdjustVnodeHashRangeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) {
×
UNCOV
3562
  return 0;
×
3563
}
3564

3565
typedef int32_t (*FpTransActionCb)(STrans *pTrans, SSdbRaw *pRaw);
3566

3567
static int32_t mndAddVgStatusAction(STrans *pTrans, SVgObj *pVg, ESdbStatus vgStatus, ETrnStage stage) {
59,461✔
3568
  int32_t         code = 0;
59,461✔
3569
  FpTransActionCb appendActionCb = (stage == TRN_STAGE_COMMIT_ACTION) ? mndTransAppendCommitlog : mndTransAppendRedolog;
59,461✔
3570
  SSdbRaw        *pRaw = mndVgroupActionEncode(pVg);
59,461✔
3571
  if (pRaw == NULL) {
59,461✔
UNCOV
3572
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3573
    if (terrno != 0) code = terrno;
×
3574
    goto _err;
×
3575
  }
3576
  if ((code = appendActionCb(pTrans, pRaw)) != 0) goto _err;
59,461✔
3577
  code = sdbSetRawStatus(pRaw, vgStatus);
59,461✔
3578
  if (code != 0) {
59,461✔
3579
    mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", pVg->vgId, tstrerror(code), __LINE__);
×
3580
    goto _err;
×
3581
  }
3582
  pRaw = NULL;
59,461✔
3583
  TAOS_RETURN(code);
59,461✔
UNCOV
3584
_err:
×
UNCOV
3585
  sdbFreeRaw(pRaw);
×
3586
  TAOS_RETURN(code);
×
3587
}
3588

3589
static int32_t mndAddDbStatusAction(STrans *pTrans, SDbObj *pDb, ESdbStatus dbStatus, ETrnStage stage) {
23,617✔
3590
  int32_t         code = 0;
23,617✔
3591
  FpTransActionCb appendActionCb = (stage == TRN_STAGE_COMMIT_ACTION) ? mndTransAppendCommitlog : mndTransAppendRedolog;
23,617✔
3592
  SSdbRaw        *pRaw = mndDbActionEncode(pDb);
23,617✔
3593
  if (pRaw == NULL) {
23,617✔
UNCOV
3594
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3595
    if (terrno != 0) code = terrno;
×
UNCOV
3596
    goto _err;
×
3597
  }
3598
  if ((code = appendActionCb(pTrans, pRaw)) != 0) goto _err;
23,617✔
3599
  code = sdbSetRawStatus(pRaw, dbStatus);
23,617✔
3600
  if (code != 0) {
23,617✔
UNCOV
3601
    mError("db:%s, failed to set raw status to ready, error:%s, line:%d", pDb->name, tstrerror(code), __LINE__);
×
UNCOV
3602
    goto _err;
×
3603
  }
3604
  pRaw = NULL;
23,617✔
3605
  TAOS_RETURN(code);
23,617✔
UNCOV
3606
_err:
×
UNCOV
3607
  sdbFreeRaw(pRaw);
×
UNCOV
3608
  TAOS_RETURN(code);
×
3609
}
3610

3611
int32_t mndSplitVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SVgObj *pVgroup) {
12,953✔
3612
  int32_t code = -1;
12,953✔
3613
  STrans *pTrans = NULL;
12,953✔
3614
  SDbObj  dbObj = {0};
12,953✔
3615
  SArray *pArray = mndBuildDnodesArray(pMnode, 0, NULL);
12,953✔
3616

3617
#if defined(USE_SHARED_STORAGE)
3618
  if (tsSsEnabled) {
12,953✔
3619
    code = TSDB_CODE_OPS_NOT_SUPPORT;
×
3620
    mError("vgId:%d, db:%s, shared storage exists, split vgroup not allowed", pVgroup->vgId, pVgroup->dbName);
×
3621
    goto _OVER;
×
3622
  }
3623
#endif
3624

3625
  /*
3626
    if (pDb->cfg.withArbitrator) {
3627
      code = TSDB_CODE_OPS_NOT_SUPPORT;
3628
      mError("vgId:%d, db:%s, with arbitrator, split vgroup not allowed", pVgroup->vgId, pVgroup->dbName);
3629
      goto _OVER;
3630
    }
3631
  */
3632

3633
  pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB, pReq, "split-vgroup");
12,953✔
3634
  if (pTrans == NULL) {
12,953✔
UNCOV
3635
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3636
    if (terrno != 0) code = terrno;
×
UNCOV
3637
    goto _OVER;
×
3638
  }
3639
  mndTransSetSerial(pTrans);
12,953✔
3640
  mInfo("trans:%d, used to split vgroup, vgId:%d", pTrans->id, pVgroup->vgId);
12,953✔
3641

3642
  mndTransSetDbName(pTrans, pDb->name, NULL);
12,953✔
3643
  TAOS_CHECK_GOTO(mndTransCheckConflictWithCompact(pMnode, pTrans), NULL, _OVER);
12,953✔
3644
  TAOS_CHECK_GOTO(mndTransCheckConflictWithRetention(pMnode, pTrans), NULL, _OVER);
11,959✔
3645

3646
  SVgObj newVg1 = {0};
11,959✔
3647
  memcpy(&newVg1, pVgroup, sizeof(SVgObj));
11,959✔
3648
  mInfo("vgId:%d, vgroup info before split, replica:%d hashBegin:%u hashEnd:%u", newVg1.vgId, newVg1.replica,
11,959✔
3649
        newVg1.hashBegin, newVg1.hashEnd);
3650
  for (int32_t i = 0; i < newVg1.replica; ++i) {
35,017✔
3651
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg1.vgId, i, newVg1.vnodeGid[i].dnodeId);
23,058✔
3652
  }
3653

3654
  if (newVg1.replica == 1) {
11,959✔
3655
    TAOS_CHECK_GOTO(mndAddVnodeToVgroup(pMnode, pTrans, &newVg1, pArray), NULL, _OVER);
6,040✔
3656

3657
    newVg1.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
6,029✔
3658
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[0].dnodeId), NULL,
6,029✔
3659
                    _OVER);
3660
    TAOS_CHECK_GOTO(mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg1, &newVg1.vnodeGid[1]), NULL, _OVER);
6,029✔
3661

3662
    newVg1.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
6,029✔
3663
    TAOS_CHECK_GOTO(mndAddAlterVnodeTypeAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[1].dnodeId), NULL, _OVER);
6,029✔
3664
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[0].dnodeId), NULL,
6,029✔
3665
                    _OVER);
3666

3667
    TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg1), NULL, _OVER);
6,029✔
3668
  } else if (newVg1.replica == 3) {
5,919✔
3669
    SVnodeGid del1 = {0};
5,180✔
3670
    TAOS_CHECK_GOTO(mndRemoveVnodeFromVgroup(pMnode, pTrans, &newVg1, pArray, &del1), NULL, _OVER);
5,180✔
3671
    TAOS_CHECK_GOTO(mndAddDropVnodeAction(pMnode, pTrans, pDb, &newVg1, &del1, true), NULL, _OVER);
5,125✔
3672
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[0].dnodeId), NULL,
5,125✔
3673
                    _OVER);
3674
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[1].dnodeId), NULL,
5,125✔
3675
                    _OVER);
3676
  } else {
3677
    // goto _OVER;
3678
  }
3679

3680
  for (int32_t i = 0; i < newVg1.replica; ++i) {
35,679✔
3681
    TAOS_CHECK_GOTO(mndAddDisableVnodeWriteAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[i].dnodeId), NULL,
23,786✔
3682
                    _OVER);
3683
  }
3684
  TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg1), NULL, _OVER);
11,893✔
3685

3686
  SVgObj newVg2 = {0};
11,893✔
3687
  memcpy(&newVg2, &newVg1, sizeof(SVgObj));
11,893✔
3688
  newVg1.replica = 1;
11,893✔
3689
  newVg1.hashEnd = newVg1.hashBegin / 2 + newVg1.hashEnd / 2;
11,893✔
3690
  memset(&newVg1.vnodeGid[1], 0, sizeof(SVnodeGid));
11,893✔
3691

3692
  newVg2.replica = 1;
11,893✔
3693
  newVg2.hashBegin = newVg1.hashEnd + 1;
11,893✔
3694
  memcpy(&newVg2.vnodeGid[0], &newVg2.vnodeGid[1], sizeof(SVnodeGid));
11,893✔
3695
  memset(&newVg2.vnodeGid[1], 0, sizeof(SVnodeGid));
11,893✔
3696

3697
  mInfo("vgId:%d, vgroup info after split, replica:%d hashrange:[%u, %u] vnode:0 dnode:%d", newVg1.vgId, newVg1.replica,
11,893✔
3698
        newVg1.hashBegin, newVg1.hashEnd, newVg1.vnodeGid[0].dnodeId);
3699
  for (int32_t i = 0; i < newVg1.replica; ++i) {
23,786✔
3700
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg1.vgId, i, newVg1.vnodeGid[i].dnodeId);
11,893✔
3701
  }
3702
  mInfo("vgId:%d, vgroup info after split, replica:%d hashrange:[%u, %u] vnode:0 dnode:%d", newVg2.vgId, newVg2.replica,
11,893✔
3703
        newVg2.hashBegin, newVg2.hashEnd, newVg2.vnodeGid[0].dnodeId);
3704
  for (int32_t i = 0; i < newVg1.replica; ++i) {
23,786✔
3705
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg2.vgId, i, newVg2.vnodeGid[i].dnodeId);
11,893✔
3706
  }
3707

3708
  // alter vgId and hash range
3709
  int32_t maxVgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP);
11,893✔
3710
  int32_t srcVgId = newVg1.vgId;
11,893✔
3711
  newVg1.vgId = maxVgId;
11,893✔
3712
  TAOS_CHECK_GOTO(mndAddNewVgPrepareAction(pMnode, pTrans, &newVg1), NULL, _OVER);
11,893✔
3713
  TAOS_CHECK_GOTO(mndAddAlterVnodeHashRangeAction(pMnode, pTrans, srcVgId, &newVg1), NULL, _OVER);
11,893✔
3714

3715
  maxVgId++;
11,893✔
3716
  srcVgId = newVg2.vgId;
11,893✔
3717
  newVg2.vgId = maxVgId;
11,893✔
3718
  TAOS_CHECK_GOTO(mndAddNewVgPrepareAction(pMnode, pTrans, &newVg2), NULL, _OVER);
11,893✔
3719
  TAOS_CHECK_GOTO(mndAddAlterVnodeHashRangeAction(pMnode, pTrans, srcVgId, &newVg2), NULL, _OVER);
11,893✔
3720

3721
  TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg1), NULL, _OVER);
11,893✔
3722
  TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg2), NULL, _OVER);
11,893✔
3723

3724
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg1, SDB_STATUS_READY, TRN_STAGE_REDO_ACTION), NULL, _OVER);
11,893✔
3725
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg2, SDB_STATUS_READY, TRN_STAGE_REDO_ACTION), NULL, _OVER);
11,893✔
3726
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, pVgroup, SDB_STATUS_DROPPED, TRN_STAGE_REDO_ACTION), NULL, _OVER);
11,893✔
3727

3728
  // update db status
3729
  memcpy(&dbObj, pDb, sizeof(SDbObj));
11,893✔
3730
  if (dbObj.cfg.pRetensions != NULL) {
11,893✔
UNCOV
3731
    dbObj.cfg.pRetensions = taosArrayDup(pDb->cfg.pRetensions, NULL);
×
UNCOV
3732
    if (dbObj.cfg.pRetensions == NULL) {
×
UNCOV
3733
      code = terrno;
×
UNCOV
3734
      goto _OVER;
×
3735
    }
3736
  }
3737
  dbObj.vgVersion++;
11,893✔
3738
  dbObj.updateTime = taosGetTimestampMs();
11,893✔
3739
  dbObj.cfg.numOfVgroups++;
11,893✔
3740
  TAOS_CHECK_GOTO(mndAddDbStatusAction(pTrans, &dbObj, SDB_STATUS_READY, TRN_STAGE_REDO_ACTION), NULL, _OVER);
11,893✔
3741

3742
  // adjust vgroup replica
3743
  if (pDb->cfg.replications != newVg1.replica) {
11,893✔
3744
    SVgObj tmpGroup = {0};
5,864✔
3745
    TAOS_CHECK_GOTO(mndBuildAlterVgroupAction(pMnode, pTrans, pDb, pDb, &newVg1, pArray, &tmpGroup), NULL, _OVER);
5,864✔
3746
  } else {
3747
    TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg1, SDB_STATUS_READY, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
6,029✔
3748
  }
3749

3750
  if (pDb->cfg.replications != newVg2.replica) {
11,806✔
3751
    SVgObj tmpGroup = {0};
5,777✔
3752
    TAOS_CHECK_GOTO(mndBuildAlterVgroupAction(pMnode, pTrans, pDb, pDb, &newVg2, pArray, &tmpGroup), NULL, _OVER);
5,777✔
3753
  } else {
3754
    TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg2, SDB_STATUS_READY, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
6,029✔
3755
  }
3756

3757
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, pVgroup, SDB_STATUS_DROPPED, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
11,724✔
3758

3759
  // commit db status
3760
  dbObj.vgVersion++;
11,724✔
3761
  dbObj.updateTime = taosGetTimestampMs();
11,724✔
3762
  TAOS_CHECK_GOTO(mndAddDbStatusAction(pTrans, &dbObj, SDB_STATUS_READY, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
11,724✔
3763

3764
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
11,724✔
3765
  code = 0;
11,724✔
3766

3767
_OVER:
12,953✔
3768
  taosArrayDestroy(pArray);
12,953✔
3769
  mndTransDrop(pTrans);
12,953✔
3770
  taosArrayDestroy(dbObj.cfg.pRetensions);
12,953✔
3771
  TAOS_RETURN(code);
12,953✔
3772
}
3773

3774
extern int32_t mndProcessSplitVgroupMsgImp(SRpcMsg *pReq);
3775

3776
static int32_t mndProcessSplitVgroupMsg(SRpcMsg *pReq) { return mndProcessSplitVgroupMsgImp(pReq); }
13,705✔
3777

3778
#ifndef TD_ENTERPRISE
3779
int32_t mndProcessSplitVgroupMsgImp(SRpcMsg *pReq) { return 0; }
3780
#endif
3781

3782
static int32_t mndSetBalanceVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
15,365✔
3783
                                              SDnodeObj *pSrc, SDnodeObj *pDst) {
3784
  int32_t code = 0;
15,365✔
3785
  SVgObj  newVg = {0};
15,365✔
3786
  memcpy(&newVg, pVgroup, sizeof(SVgObj));
15,365✔
3787
  mInfo("vgId:%d, vgroup info before balance, replica:%d", newVg.vgId, newVg.replica);
15,365✔
3788
  for (int32_t i = 0; i < newVg.replica; ++i) {
45,222✔
3789
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
29,857✔
3790
  }
3791

3792
  TAOS_CHECK_RETURN(mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pDst->id));
15,365✔
3793
  TAOS_CHECK_RETURN(mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pSrc->id));
15,365✔
3794

3795
  {
3796
    SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
15,365✔
3797
    if (pRaw == NULL) {
15,365✔
UNCOV
3798
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3799
      if (terrno != 0) code = terrno;
×
UNCOV
3800
      TAOS_RETURN(code);
×
3801
    }
3802
    if ((code = mndTransAppendCommitlog(pTrans, pRaw)) != 0) {
15,365✔
UNCOV
3803
      sdbFreeRaw(pRaw);
×
UNCOV
3804
      TAOS_RETURN(code);
×
3805
    }
3806
    code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
15,365✔
3807
    if (code != 0) {
15,365✔
UNCOV
3808
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
UNCOV
3809
      TAOS_RETURN(code);
×
3810
    }
3811
  }
3812

3813
  mInfo("vgId:%d, vgroup info after balance, replica:%d", newVg.vgId, newVg.replica);
15,365✔
3814
  for (int32_t i = 0; i < newVg.replica; ++i) {
45,222✔
3815
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
29,857✔
3816
  }
3817
  TAOS_RETURN(code);
15,365✔
3818
}
3819

3820
static int32_t mndBalanceVgroupBetweenDnode(SMnode *pMnode, STrans *pTrans, SDnodeObj *pSrc, SDnodeObj *pDst,
15,365✔
3821
                                            SHashObj *pBalancedVgroups) {
3822
  void   *pIter = NULL;
15,365✔
3823
  int32_t code = -1;
15,365✔
3824
  SSdb   *pSdb = pMnode->pSdb;
15,365✔
3825

3826
  while (1) {
9,455✔
3827
    SVgObj *pVgroup = NULL;
24,820✔
3828
    pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
24,820✔
3829
    if (pIter == NULL) break;
24,820✔
3830
    if (taosHashGet(pBalancedVgroups, &pVgroup->vgId, sizeof(int32_t)) != NULL) {
24,820✔
3831
      sdbRelease(pSdb, pVgroup);
8,717✔
3832
      continue;
8,717✔
3833
    }
3834

3835
    bool existInSrc = false;
16,103✔
3836
    bool existInDst = false;
16,103✔
3837
    for (int32_t i = 0; i < pVgroup->replica; ++i) {
46,698✔
3838
      SVnodeGid *pGid = &pVgroup->vnodeGid[i];
30,595✔
3839
      if (pGid->dnodeId == pSrc->id) existInSrc = true;
30,595✔
3840
      if (pGid->dnodeId == pDst->id) existInDst = true;
30,595✔
3841
    }
3842

3843
    if (!existInSrc || existInDst) {
16,103✔
3844
      sdbRelease(pSdb, pVgroup);
738✔
3845
      continue;
738✔
3846
    }
3847

3848
    SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName);
15,365✔
3849
    if (pDb == NULL) {
15,365✔
UNCOV
3850
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3851
      if (terrno != 0) code = terrno;
×
UNCOV
3852
      mError("vgId:%d, balance vgroup can't find db obj dbName:%s", pVgroup->vgId, pVgroup->dbName);
×
UNCOV
3853
      goto _OUT;
×
3854
    }
3855

3856
    if (pDb->cfg.withArbitrator) {
15,365✔
UNCOV
3857
      mInfo("vgId:%d, db:%s, with arbitrator, balance vgroup not allowed", pVgroup->vgId, pVgroup->dbName);
×
UNCOV
3858
      goto _OUT;
×
3859
    }
3860

3861
    code = mndSetBalanceVgroupInfoToTrans(pMnode, pTrans, pDb, pVgroup, pSrc, pDst);
15,365✔
3862
    if (code == 0) {
15,365✔
3863
      code = taosHashPut(pBalancedVgroups, &pVgroup->vgId, sizeof(int32_t), &pVgroup->vgId, sizeof(int32_t));
15,365✔
3864
    }
3865

3866
  _OUT:
15,365✔
3867
    mndReleaseDb(pMnode, pDb);
15,365✔
3868
    sdbRelease(pSdb, pVgroup);
15,365✔
3869
    sdbCancelFetch(pSdb, pIter);
15,365✔
3870
    break;
15,365✔
3871
  }
3872

3873
  return code;
15,365✔
3874
}
3875

3876
static int32_t mndBalanceVgroup(SMnode *pMnode, SRpcMsg *pReq, SArray *pArray) {
12,549✔
3877
  int32_t   code = -1;
12,549✔
3878
  int32_t   numOfVgroups = 0;
12,549✔
3879
  STrans   *pTrans = NULL;
12,549✔
3880
  SHashObj *pBalancedVgroups = NULL;
12,549✔
3881

3882
  pBalancedVgroups = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
12,549✔
3883
  if (pBalancedVgroups == NULL) goto _OVER;
12,549✔
3884

3885
  pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_GLOBAL, pReq, "balance-vgroup");
12,549✔
3886
  if (pTrans == NULL) {
12,549✔
UNCOV
3887
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3888
    if (terrno != 0) code = terrno;
×
UNCOV
3889
    goto _OVER;
×
3890
  }
3891
  mndTransSetSerial(pTrans);
12,549✔
3892
  mInfo("trans:%d, used to balance vgroup", pTrans->id);
12,549✔
3893
  TAOS_CHECK_GOTO(mndTransCheckConflict(pMnode, pTrans), NULL, _OVER);
12,549✔
3894
  TAOS_CHECK_GOTO(mndTransCheckConflictWithCompact(pMnode, pTrans), NULL, _OVER);
9,819✔
3895
  TAOS_CHECK_GOTO(mndTransCheckConflictWithRetention(pMnode, pTrans), NULL, _OVER);
9,546✔
3896

3897
  while (1) {
15,365✔
3898
    taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
24,911✔
3899
    for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
107,491✔
3900
      SDnodeObj *pDnode = taosArrayGet(pArray, i);
82,580✔
3901
      mInfo("dnode:%d, equivalent vnodes:%d others:%d support:%d, score:%f", pDnode->id, pDnode->numOfVnodes,
82,580✔
3902
            pDnode->numOfSupportVnodes, pDnode->numOfOtherNodes, mndGetDnodeScore(pDnode, 0, 1));
3903
    }
3904

3905
    SDnodeObj *pSrc = taosArrayGet(pArray, taosArrayGetSize(pArray) - 1);
24,911✔
3906
    SDnodeObj *pDst = taosArrayGet(pArray, 0);
24,911✔
3907

3908
    float srcScore = mndGetDnodeScore(pSrc, -1, 1);
24,911✔
3909
    float dstScore = mndGetDnodeScore(pDst, 1, 1);
24,911✔
3910
    mInfo("trans:%d, after balance, src dnode:%d score:%f, dst dnode:%d score:%f", pTrans->id, pSrc->id, dstScore,
24,911✔
3911
          pDst->id, dstScore);
3912

3913
    if (srcScore > dstScore - 0.000001) {
24,911✔
3914
      code = mndBalanceVgroupBetweenDnode(pMnode, pTrans, pSrc, pDst, pBalancedVgroups);
15,365✔
3915
      if (code == 0) {
15,365✔
3916
        pSrc->numOfVnodes--;
15,365✔
3917
        pDst->numOfVnodes++;
15,365✔
3918
        numOfVgroups++;
15,365✔
3919
        continue;
15,365✔
3920
      } else {
UNCOV
3921
        mInfo("trans:%d, no vgroup need to balance from dnode:%d to dnode:%d", pTrans->id, pSrc->id, pDst->id);
×
UNCOV
3922
        break;
×
3923
      }
3924
    } else {
3925
      mInfo("trans:%d, no vgroup need to balance any more", pTrans->id);
9,546✔
3926
      break;
9,546✔
3927
    }
3928
  }
3929

3930
  if (numOfVgroups <= 0) {
9,546✔
UNCOV
3931
    mInfo("no need to balance vgroup");
×
UNCOV
3932
    code = 0;
×
3933
  } else {
3934
    mInfo("start to balance vgroup, numOfVgroups:%d", numOfVgroups);
9,546✔
3935
    if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER;
9,546✔
3936
    code = TSDB_CODE_ACTION_IN_PROGRESS;
9,546✔
3937
  }
3938

3939
_OVER:
12,549✔
3940
  taosHashCleanup(pBalancedVgroups);
12,549✔
3941
  mndTransDrop(pTrans);
12,549✔
3942
  TAOS_RETURN(code);
12,549✔
3943
}
3944

3945
static int32_t mndProcessBalanceVgroupMsg(SRpcMsg *pReq) {
14,392✔
3946
  SMnode *pMnode = pReq->info.node;
14,392✔
3947
  int32_t code = -1;
14,392✔
3948
  SArray *pArray = NULL;
14,392✔
3949
  void   *pIter = NULL;
14,392✔
3950
  int64_t curMs = taosGetTimestampMs();
14,392✔
3951

3952
  SBalanceVgroupReq req = {0};
14,392✔
3953
  if (tDeserializeSBalanceVgroupReq(pReq->pCont, pReq->contLen, &req) != 0) {
14,392✔
UNCOV
3954
    code = TSDB_CODE_INVALID_MSG;
×
UNCOV
3955
    goto _OVER;
×
3956
  }
3957

3958
  mInfo("start to balance vgroup");
14,392✔
3959
  if ((code = mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_BALANCE_VGROUP)) != 0) {
14,392✔
3960
    goto _OVER;
355✔
3961
  }
3962

3963
  if (sdbGetSize(pMnode->pSdb, SDB_MOUNT) > 0) {
14,037✔
UNCOV
3964
    code = TSDB_CODE_MND_MOUNT_NOT_EMPTY;
×
UNCOV
3965
    goto _OVER;
×
3966
  }
3967

3968
  while (1) {
42,749✔
3969
    SDnodeObj *pDnode = NULL;
56,786✔
3970
    pIter = sdbFetch(pMnode->pSdb, SDB_DNODE, pIter, (void **)&pDnode);
56,786✔
3971
    if (pIter == NULL) break;
56,786✔
3972
    if (!mndIsDnodeOnline(pDnode, curMs)) {
44,237✔
3973
      sdbCancelFetch(pMnode->pSdb, pIter);
1,488✔
3974
      code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
1,488✔
3975
      mError("failed to balance vgroup since %s, dnode:%d", terrstr(), pDnode->id);
1,488✔
3976
      sdbRelease(pMnode->pSdb, pDnode);
1,488✔
3977
      goto _OVER;
1,488✔
3978
    }
3979

3980
    sdbRelease(pMnode->pSdb, pDnode);
42,749✔
3981
  }
3982

3983
  pArray = mndBuildDnodesArray(pMnode, 0, NULL);
12,549✔
3984
  if (pArray == NULL) {
12,549✔
UNCOV
3985
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3986
    if (terrno != 0) code = terrno;
×
UNCOV
3987
    goto _OVER;
×
3988
  }
3989

3990
  if (taosArrayGetSize(pArray) < 2) {
12,549✔
UNCOV
3991
    mInfo("no need to balance vgroup since dnode num less than 2");
×
UNCOV
3992
    code = 0;
×
3993
  } else {
3994
    code = mndBalanceVgroup(pMnode, pReq, pArray);
12,549✔
3995
  }
3996

3997
  auditRecord(pReq, pMnode->clusterId, "balanceVgroup", "", "", req.sql, req.sqlLen);
12,549✔
3998

3999
_OVER:
14,392✔
4000
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
14,392✔
4001
    mError("failed to balance vgroup since %s", tstrerror(code));
4,846✔
4002
  }
4003

4004
  taosArrayDestroy(pArray);
14,392✔
4005
  tFreeSBalanceVgroupReq(&req);
14,392✔
4006
  TAOS_RETURN(code);
14,392✔
4007
}
4008

4009
bool mndVgroupInDb(SVgObj *pVgroup, int64_t dbUid) { return !pVgroup->isTsma && pVgroup->dbUid == dbUid; }
91,059,728✔
4010

4011
bool mndVgroupInDnode(SVgObj *pVgroup, int32_t dnodeId) {
9,872✔
4012
  for (int i = 0; i < pVgroup->replica; i++) {
24,676✔
4013
    if (pVgroup->vnodeGid[i].dnodeId == dnodeId) return true;
20,974✔
4014
  }
4015
  return false;
3,702✔
4016
}
4017

4018
static void *mndBuildCompactVnodeReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen, int64_t compactTs,
129,346✔
4019
                                     STimeWindow tw, bool metaOnly, bool force, ETsdbOpType type,
4020
                                     ETriggerType triggerType) {
4021
  SCompactVnodeReq compactReq = {0};
129,346✔
4022
  compactReq.dbUid = pDb->uid;
129,346✔
4023
  compactReq.compactStartTime = compactTs;
129,346✔
4024
  compactReq.tw = tw;
129,346✔
4025
  compactReq.metaOnly = metaOnly;
129,346✔
4026
  compactReq.force = force;
129,346✔
4027
  compactReq.optrType = type;
129,346✔
4028
  compactReq.triggerType = triggerType;
129,346✔
4029
  tstrncpy(compactReq.db, pDb->name, TSDB_DB_FNAME_LEN);
129,346✔
4030

4031
  mInfo("vgId:%d, build compact vnode config req", pVgroup->vgId);
129,346✔
4032
  int32_t contLen = tSerializeSCompactVnodeReq(NULL, 0, &compactReq);
129,346✔
4033
  if (contLen < 0) {
129,346✔
UNCOV
4034
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
4035
    return NULL;
×
4036
  }
4037
  contLen += sizeof(SMsgHead);
129,346✔
4038

4039
  void *pReq = taosMemoryMalloc(contLen);
129,346✔
4040
  if (pReq == NULL) {
129,346✔
UNCOV
4041
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
4042
    return NULL;
×
4043
  }
4044

4045
  SMsgHead *pHead = pReq;
129,346✔
4046
  pHead->contLen = htonl(contLen);
129,346✔
4047
  pHead->vgId = htonl(pVgroup->vgId);
129,346✔
4048

4049
  if (tSerializeSCompactVnodeReq((char *)pReq + sizeof(SMsgHead), contLen, &compactReq) < 0) {
129,346✔
UNCOV
4050
    taosMemoryFree(pReq);
×
UNCOV
4051
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
4052
    return NULL;
×
4053
  }
4054
  *pContLen = contLen;
129,346✔
4055
  return pReq;
129,346✔
4056
}
4057

4058
static int32_t mndAddCompactVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int64_t compactTs,
63,205✔
4059
                                        STimeWindow tw, bool metaOnly, bool force, ETsdbOpType type,
4060
                                        ETriggerType triggerType) {
4061
  int32_t      code = 0;
63,205✔
4062
  STransAction action = {0};
63,205✔
4063
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
63,205✔
4064

4065
  int32_t contLen = 0;
63,205✔
4066
  void   *pReq =
4067
      mndBuildCompactVnodeReq(pMnode, pDb, pVgroup, &contLen, compactTs, tw, metaOnly, force, type, triggerType);
63,205✔
4068
  if (pReq == NULL) {
63,205✔
UNCOV
4069
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
4070
    if (terrno != 0) code = terrno;
×
UNCOV
4071
    TAOS_RETURN(code);
×
4072
  }
4073

4074
  action.pCont = pReq;
63,205✔
4075
  action.contLen = contLen;
63,205✔
4076
  action.msgType = TDMT_VND_COMPACT;
63,205✔
4077

4078
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
63,205✔
UNCOV
4079
    taosMemoryFree(pReq);
×
UNCOV
4080
    TAOS_RETURN(code);
×
4081
  }
4082

4083
  TAOS_RETURN(code);
63,205✔
4084
}
4085

4086
int32_t mndBuildCompactVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int64_t compactTs,
63,205✔
4087
                                    STimeWindow tw, bool metaOnly, bool force, ETsdbOpType type,
4088
                                    ETriggerType triggerType) {
4089
  TAOS_CHECK_RETURN(
63,205✔
4090
      mndAddCompactVnodeAction(pMnode, pTrans, pDb, pVgroup, compactTs, tw, metaOnly, force, type, triggerType));
4091
  return 0;
63,205✔
4092
}
4093

4094
int32_t mndBuildTrimVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int64_t startTs,
66,141✔
4095
                                 STimeWindow tw, ETsdbOpType type, ETriggerType triggerType) {
4096
  int32_t      code = 0;
66,141✔
4097
  STransAction action = {0};
66,141✔
4098
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
66,141✔
4099

4100
  int32_t contLen = 0;
66,141✔
4101
  // reuse SCompactVnodeReq as SVTrimDbReq
4102
  void *pReq = mndBuildCompactVnodeReq(pMnode, pDb, pVgroup, &contLen, startTs, tw, false, false, type, triggerType);
66,141✔
4103
  if (pReq == NULL) {
66,141✔
4104
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
4105
    if (terrno != 0) code = terrno;
×
UNCOV
4106
    TAOS_RETURN(code);
×
4107
  }
4108

4109
  action.pCont = pReq;
66,141✔
4110
  action.contLen = contLen;
66,141✔
4111
  action.msgType = TDMT_VND_TRIM;
66,141✔
4112

4113
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
66,141✔
UNCOV
4114
    taosMemoryFree(pReq);
×
UNCOV
4115
    TAOS_RETURN(code);
×
4116
  }
4117

4118
  TAOS_RETURN(code);
66,141✔
4119
}
4120

4121
static int32_t mndProcessSetVgroupKeepVersionReq(SRpcMsg *pReq) {
1,194✔
4122
  SMnode *pMnode = pReq->info.node;
1,194✔
4123
  int32_t code = TSDB_CODE_SUCCESS;
1,194✔
4124
  STrans *pTrans = NULL;
1,194✔
4125
  SVgObj *pVgroup = NULL;
1,194✔
4126

4127
  SMndSetVgroupKeepVersionReq req = {0};
1,194✔
4128
  if (tDeserializeSMndSetVgroupKeepVersionReq(pReq->pCont, pReq->contLen, &req) != 0) {
1,194✔
4129
    code = TSDB_CODE_INVALID_MSG;
×
4130
    goto _OVER;
×
4131
  }
4132

4133
  mInfo("start to set vgroup keep version, vgId:%d, keepVersion:%" PRId64, req.vgId, req.keepVersion);
1,194✔
4134

4135
  // Check permission
4136
  if ((code = mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB)) != 0) {
1,194✔
UNCOV
4137
    goto _OVER;
×
4138
  }
4139

4140
  // Get vgroup
4141
  pVgroup = mndAcquireVgroup(pMnode, req.vgId);
1,194✔
4142
  if (pVgroup == NULL) {
1,194✔
UNCOV
4143
    code = TSDB_CODE_MND_VGROUP_NOT_EXIST;
×
UNCOV
4144
    mError("vgId:%d not exist, failed to set keep version", req.vgId);
×
UNCOV
4145
    goto _OVER;
×
4146
  }
4147

4148
  // Create transaction
4149
  pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, pReq, "set-vgroup-keep-version");
1,194✔
4150
  if (pTrans == NULL) {
1,194✔
UNCOV
4151
    code = terrno != 0 ? terrno : TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
4152
    mndReleaseVgroup(pMnode, pVgroup);
×
UNCOV
4153
    goto _OVER;
×
4154
  }
4155

4156
  mndTransSetSerial(pTrans);
1,194✔
4157
  mInfo("trans:%d, used to set vgroup keep version, vgId:%d keepVersion:%" PRId64, pTrans->id, req.vgId,
1,194✔
4158
        req.keepVersion);
4159

4160
  // Update SVgObj's keepVersion in mnode
4161
  SVgObj newVgroup = {0};
1,194✔
4162
  memcpy(&newVgroup, pVgroup, sizeof(SVgObj));
1,194✔
4163
  newVgroup.keepVersion = req.keepVersion;
1,194✔
4164
  newVgroup.keepVersionTime = taosGetTimestampMs();
1,194✔
4165

4166
  // Add prepare log for SDB vgroup update (execute in PREPARE stage, before redo actions)
4167
  SSdbRaw *pCommitRaw = mndVgroupActionEncode(&newVgroup);
1,194✔
4168
  if (pCommitRaw == NULL) {
1,194✔
4169
    code = TSDB_CODE_OUT_OF_MEMORY;
×
4170
    mndReleaseVgroup(pMnode, pVgroup);
×
UNCOV
4171
    goto _OVER;
×
4172
  }
4173
  if (mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
1,194✔
UNCOV
4174
    code = terrno;
×
UNCOV
4175
    sdbFreeRaw(pCommitRaw);
×
4176
    mndReleaseVgroup(pMnode, pVgroup);
×
4177
    goto _OVER;
×
4178
  }
4179
  if ((code = sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY)) != 0) {
1,194✔
UNCOV
4180
    mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", pVgroup->vgId, tstrerror(code), __LINE__);
×
UNCOV
4181
    sdbFreeRaw(pCommitRaw);
×
UNCOV
4182
    mndReleaseVgroup(pMnode, pVgroup);
×
UNCOV
4183
    goto _OVER;
×
4184
  }
4185

4186
  // Prepare message for vnodes
4187
  SVndSetKeepVersionReq vndReq = {.keepVersion = req.keepVersion};
1,194✔
4188
  int32_t               reqLen = tSerializeSVndSetKeepVersionReq(NULL, 0, &vndReq);
1,194✔
4189
  int32_t               contLen = reqLen + sizeof(SMsgHead);
1,194✔
4190

4191
  // Send to all replicas of the vgroup
4192
  for (int32_t i = 0; i < pVgroup->replica; ++i) {
4,776✔
4193
    SMsgHead *pHead = taosMemoryMalloc(contLen);
3,582✔
4194
    if (pHead == NULL) {
3,582✔
4195
      code = TSDB_CODE_OUT_OF_MEMORY;
×
4196
      mndReleaseVgroup(pMnode, pVgroup);
×
UNCOV
4197
      goto _OVER;
×
4198
    }
4199

4200
    pHead->contLen = htonl(contLen);
3,582✔
4201
    pHead->vgId = htonl(pVgroup->vgId);
3,582✔
4202

4203
    if (tSerializeSVndSetKeepVersionReq((char *)pHead + sizeof(SMsgHead), reqLen, &vndReq) < 0) {
3,582✔
UNCOV
4204
      taosMemoryFree(pHead);
×
4205
      code = TSDB_CODE_OUT_OF_MEMORY;
×
4206
      mndReleaseVgroup(pMnode, pVgroup);
×
4207
      goto _OVER;
×
4208
    }
4209

4210
    // Get dnode and add action to transaction
4211
    SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgroup->vnodeGid[i].dnodeId);
3,582✔
4212
    if (pDnode == NULL) {
3,582✔
UNCOV
4213
      taosMemoryFree(pHead);
×
UNCOV
4214
      code = TSDB_CODE_MND_DNODE_NOT_EXIST;
×
UNCOV
4215
      mndReleaseVgroup(pMnode, pVgroup);
×
UNCOV
4216
      goto _OVER;
×
4217
    }
4218

4219
    STransAction action = {0};
3,582✔
4220
    action.epSet = mndGetDnodeEpset(pDnode);
3,582✔
4221
    mndReleaseDnode(pMnode, pDnode);
3,582✔
4222
    action.pCont = pHead;
3,582✔
4223
    action.contLen = contLen;
3,582✔
4224
    action.msgType = TDMT_VND_SET_KEEP_VERSION;
3,582✔
4225
    action.acceptableCode = TSDB_CODE_VND_STOPPED;
3,582✔
4226

4227
    if (mndTransAppendRedoAction(pTrans, &action) != 0) {
3,582✔
UNCOV
4228
      taosMemoryFree(pHead);
×
4229
      code = terrno;
×
4230
      mndReleaseVgroup(pMnode, pVgroup);
×
4231
      goto _OVER;
×
4232
    }
4233
  }
4234

4235
  mndReleaseVgroup(pMnode, pVgroup);
1,194✔
4236

4237
  // Prepare and execute transaction
4238
  if ((code = mndTransPrepare(pMnode, pTrans)) != 0) {
1,194✔
4239
    goto _OVER;
×
4240
  }
4241

4242
  code = TSDB_CODE_ACTION_IN_PROGRESS;
1,194✔
4243

4244
_OVER:
1,194✔
4245
  if (pTrans != NULL) mndTransDrop(pTrans);
1,194✔
4246

4247
  return code;
1,194✔
4248
}
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