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

taosdata / TDengine / #4988

16 Mar 2026 12:26PM UTC coverage: 75.821% (+1.9%) from 73.883%
#4988

push

travis-ci

web-flow
feat: support secure delete option. (#34591)

274 of 464 new or added lines in 29 files covered. (59.05%)

4404 existing lines in 23 files now uncovered.

337108 of 444611 relevant lines covered (75.82%)

146708292.94 hits per line

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

67.92
/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_COMPAT_MOUNT_KEEP_VER 2
34
#define VGROUP_VER_NUMBER                VGROUP_VER_COMPAT_MOUNT_KEEP_VER
35
#define VGROUP_RESERVE_SIZE              60
36
// since 3.3.6.32/3.3.8.6 mountId + keepVersion + keepVersionTime + VGROUP_RESERVE_SIZE = 4 + 8 + 8 + 60 = 80
37
#define DLEN_AFTER_SYNC_CONF_CHANGE_VER 80
38

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

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

49
static int32_t mndProcessRedistributeVgroupMsg(SRpcMsg *pReq);
50
static int32_t mndProcessSplitVgroupMsg(SRpcMsg *pReq);
51
static int32_t mndProcessBalanceVgroupMsg(SRpcMsg *pReq);
52
static int32_t mndProcessVgroupBalanceLeaderMsg(SRpcMsg *pReq);
53
static int32_t mndProcessSetVgroupKeepVersionReq(SRpcMsg *pReq);
54

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

67
  mndSetMsgHandle(pMnode, TDMT_DND_CREATE_VNODE_RSP, mndTransProcessRsp);
917,496✔
68
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_REPLICA_RSP, mndTransProcessRsp);
917,496✔
69
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_CONFIG_RSP, mndTransProcessRsp);
917,496✔
70
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_CONFIRM_RSP, mndTransProcessRsp);
917,496✔
71
  mndSetMsgHandle(pMnode, TDMT_VND_SET_KEEP_VERSION_RSP, mndTransProcessRsp);
917,496✔
72
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_HASHRANGE_RSP, mndTransProcessRsp);
917,496✔
73
  mndSetMsgHandle(pMnode, TDMT_DND_DROP_VNODE_RSP, mndTransProcessRsp);
917,496✔
74
  mndSetMsgHandle(pMnode, TDMT_VND_COMPACT_RSP, mndTransProcessRsp);
917,496✔
75
  mndSetMsgHandle(pMnode, TDMT_VND_SCAN_RSP, mndTransProcessRsp);
917,496✔
76
  mndSetMsgHandle(pMnode, TDMT_VND_DISABLE_WRITE_RSP, mndTransProcessRsp);
917,496✔
77
  mndSetMsgHandle(pMnode, TDMT_SYNC_FORCE_FOLLOWER_RSP, mndTransProcessRsp);
917,496✔
78
  mndSetMsgHandle(pMnode, TDMT_VND_ALTER_ELECTBASELINE_RSP, mndTransProcessRsp);
917,496✔
79
  
80
  mndSetMsgHandle(pMnode, TDMT_DND_ALTER_VNODE_TYPE_RSP, mndTransProcessRsp);
917,496✔
81
  mndSetMsgHandle(pMnode, TDMT_DND_CHECK_VNODE_LEARNER_CATCHUP_RSP, mndTransProcessRsp);
917,496✔
82
  mndSetMsgHandle(pMnode, TDMT_SYNC_CONFIG_CHANGE_RSP, mndTransProcessRsp);
917,496✔
83

84
  mndSetMsgHandle(pMnode, TDMT_MND_REDISTRIBUTE_VGROUP, mndProcessRedistributeVgroupMsg);
917,496✔
85
  mndSetMsgHandle(pMnode, TDMT_MND_SPLIT_VGROUP, mndProcessSplitVgroupMsg);
917,496✔
86
  // mndSetMsgHandle(pMnode, TDMT_MND_BALANCE_VGROUP, mndProcessVgroupBalanceLeaderMsg);
87
  mndSetMsgHandle(pMnode, TDMT_MND_BALANCE_VGROUP, mndProcessBalanceVgroupMsg);
917,496✔
88
  mndSetMsgHandle(pMnode, TDMT_MND_BALANCE_VGROUP_LEADER, mndProcessVgroupBalanceLeaderMsg);
917,496✔
89
  mndSetMsgHandle(pMnode, TDMT_MND_SET_VGROUP_KEEP_VERSION, mndProcessSetVgroupKeepVersionReq);
917,496✔
90

91
  mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_VGROUP, mndRetrieveVgroups);
917,496✔
92
  mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_VGROUP, mndCancelGetNextVgroup);
917,496✔
93
  mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_VNODES, mndRetrieveVnodes);
917,496✔
94
  mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_VNODES, mndCancelGetNextVnode);
917,496✔
95

96
  return sdbSetTable(pMnode->pSdb, table);
917,496✔
97
}
98

99
void mndCleanupVgroup(SMnode *pMnode) {}
917,358✔
100

101
SSdbRaw *mndVgroupActionEncode(SVgObj *pVgroup) {
23,783,090✔
102
  int32_t code = 0;
23,783,090✔
103
  int32_t lino = 0;
23,783,090✔
104
  terrno = TSDB_CODE_OUT_OF_MEMORY;
23,783,090✔
105

106
  SSdbRaw *pRaw = sdbAllocRaw(SDB_VGROUP, VGROUP_VER_NUMBER, sizeof(SVgObj) + VGROUP_RESERVE_SIZE);
23,783,090✔
107
  if (pRaw == NULL) goto _OVER;
23,783,090✔
108

109
  int32_t dataPos = 0;
23,783,090✔
110
  SDB_SET_INT32(pRaw, dataPos, pVgroup->vgId, _OVER)
23,783,090✔
111
  SDB_SET_INT64(pRaw, dataPos, pVgroup->createdTime, _OVER)
23,783,090✔
112
  SDB_SET_INT64(pRaw, dataPos, pVgroup->updateTime, _OVER)
23,783,090✔
113
  SDB_SET_INT32(pRaw, dataPos, pVgroup->version, _OVER)
23,783,090✔
114
  SDB_SET_INT32(pRaw, dataPos, pVgroup->hashBegin, _OVER)
23,783,090✔
115
  SDB_SET_INT32(pRaw, dataPos, pVgroup->hashEnd, _OVER)
23,783,090✔
116
  SDB_SET_BINARY(pRaw, dataPos, pVgroup->dbName, TSDB_DB_FNAME_LEN, _OVER)
23,783,090✔
117
  SDB_SET_INT64(pRaw, dataPos, pVgroup->dbUid, _OVER)
23,783,090✔
118
  SDB_SET_INT8(pRaw, dataPos, pVgroup->isTsma, _OVER)
23,783,090✔
119
  SDB_SET_INT8(pRaw, dataPos, pVgroup->replica, _OVER)
23,783,090✔
120
  for (int8_t i = 0; i < pVgroup->replica; ++i) {
51,525,842✔
121
    SVnodeGid *pVgid = &pVgroup->vnodeGid[i];
27,742,752✔
122
    SDB_SET_INT32(pRaw, dataPos, pVgid->dnodeId, _OVER)
27,742,752✔
123
  }
124
  SDB_SET_INT32(pRaw, dataPos, pVgroup->syncConfChangeVer, _OVER)
23,783,090✔
125
  SDB_SET_INT32(pRaw, dataPos, pVgroup->mountVgId, _OVER)
23,783,090✔
126
  SDB_SET_INT64(pRaw, dataPos, pVgroup->keepVersion, _OVER)
23,783,090✔
127
  SDB_SET_INT64(pRaw, dataPos, pVgroup->keepVersionTime, _OVER)
23,783,090✔
128
  SDB_SET_RESERVE(pRaw, dataPos, VGROUP_RESERVE_SIZE, _OVER)
23,783,090✔
129
  SDB_SET_DATALEN(pRaw, dataPos, _OVER)
23,783,090✔
130

131
  terrno = 0;
23,783,090✔
132

133
_OVER:
23,783,090✔
134
  if (terrno != 0) {
23,783,090✔
135
    mError("vgId:%d, failed to encode to raw:%p since %s", pVgroup->vgId, pRaw, terrstr());
×
136
    sdbFreeRaw(pRaw);
×
137
    return NULL;
×
138
  }
139

140
  mTrace("vgId:%d, encode to raw:%p, row:%p", pVgroup->vgId, pRaw, pVgroup);
23,783,090✔
141
  return pRaw;
23,783,090✔
142
}
143

144
SSdbRow *mndVgroupActionDecode(SSdbRaw *pRaw) {
21,434,948✔
145
  int32_t code = 0;
21,434,948✔
146
  int32_t lino = 0;
21,434,948✔
147
  terrno = TSDB_CODE_OUT_OF_MEMORY;
21,434,948✔
148
  SSdbRow *pRow = NULL;
21,434,948✔
149
  SVgObj  *pVgroup = NULL;
21,434,948✔
150

151
  int8_t sver = 0;
21,434,948✔
152
  if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto _OVER;
21,434,948✔
153

154
  if (sver < 1 || sver > VGROUP_VER_NUMBER) {
21,434,948✔
155
    terrno = TSDB_CODE_SDB_INVALID_DATA_VER;
×
156
    goto _OVER;
×
157
  }
158

159
  pRow = sdbAllocRow(sizeof(SVgObj));
21,434,948✔
160
  if (pRow == NULL) goto _OVER;
21,434,948✔
161

162
  pVgroup = sdbGetRowObj(pRow);
21,434,948✔
163
  if (pVgroup == NULL) goto _OVER;
21,434,948✔
164

165
  int32_t dataPos = 0;
21,434,948✔
166
  SDB_GET_INT32(pRaw, dataPos, &pVgroup->vgId, _OVER)
21,434,948✔
167
  SDB_GET_INT64(pRaw, dataPos, &pVgroup->createdTime, _OVER)
21,434,948✔
168
  SDB_GET_INT64(pRaw, dataPos, &pVgroup->updateTime, _OVER)
21,434,948✔
169
  SDB_GET_INT32(pRaw, dataPos, &pVgroup->version, _OVER)
21,434,948✔
170
  SDB_GET_INT32(pRaw, dataPos, &pVgroup->hashBegin, _OVER)
21,434,948✔
171
  SDB_GET_INT32(pRaw, dataPos, &pVgroup->hashEnd, _OVER)
21,434,948✔
172
  SDB_GET_BINARY(pRaw, dataPos, pVgroup->dbName, TSDB_DB_FNAME_LEN, _OVER)
21,434,948✔
173
  SDB_GET_INT64(pRaw, dataPos, &pVgroup->dbUid, _OVER)
21,434,948✔
174
  SDB_GET_INT8(pRaw, dataPos, &pVgroup->isTsma, _OVER)
21,434,948✔
175
  SDB_GET_INT8(pRaw, dataPos, &pVgroup->replica, _OVER)
21,434,948✔
176
  for (int8_t i = 0; i < pVgroup->replica; ++i) {
46,768,934✔
177
    SVnodeGid *pVgid = &pVgroup->vnodeGid[i];
25,333,986✔
178
    SDB_GET_INT32(pRaw, dataPos, &pVgid->dnodeId, _OVER)
25,333,986✔
179
    if (pVgroup->replica == 1) {
25,333,986✔
180
      pVgid->syncState = TAOS_SYNC_STATE_LEADER;
19,399,340✔
181
    }
182
    pVgid->snapSeq = -1;
25,333,986✔
183
  }
184
  if (dataPos + 2 * sizeof(int32_t) + VGROUP_RESERVE_SIZE <= pRaw->dataLen) {
21,434,948✔
185
    SDB_GET_INT32(pRaw, dataPos, &pVgroup->syncConfChangeVer, _OVER)
21,434,948✔
186
  }
187

188
  int32_t dlenAfterSyncConfChangeVer = pRaw->dataLen - dataPos;
21,434,948✔
189
  if (dataPos + sizeof(int32_t) + VGROUP_RESERVE_SIZE <= pRaw->dataLen) {
21,434,948✔
190
    SDB_GET_INT32(pRaw, dataPos, &pVgroup->mountVgId, _OVER)
21,434,948✔
191
  }
192
  if (dataPos + sizeof(int64_t) + VGROUP_RESERVE_SIZE <= pRaw->dataLen) {
21,434,948✔
193
    SDB_GET_INT64(pRaw, dataPos, &pVgroup->keepVersion, _OVER)
21,434,948✔
194
  }
195
  if (dataPos + sizeof(int64_t) + VGROUP_RESERVE_SIZE <= pRaw->dataLen) {
21,434,948✔
196
    SDB_GET_INT64(pRaw, dataPos, &pVgroup->keepVersionTime, _OVER)
21,434,948✔
197
  }
198
  if (dataPos + VGROUP_RESERVE_SIZE <= pRaw->dataLen) {
21,434,948✔
199
    SDB_GET_RESERVE(pRaw, dataPos, VGROUP_RESERVE_SIZE, _OVER)
21,434,948✔
200
  }
201

202
  if (sver < VGROUP_VER_COMPAT_MOUNT_KEEP_VER) {
21,434,948✔
203
    if (dlenAfterSyncConfChangeVer == DLEN_AFTER_SYNC_CONF_CHANGE_VER) {
×
204
      pVgroup->mountVgId = 0;
×
205
    }
206
    pVgroup->keepVersion = -1;
×
207
    pVgroup->keepVersionTime = 0;
×
208
  }
209

210
  terrno = 0;
21,434,948✔
211

212
_OVER:
21,434,948✔
213
  if (terrno != 0) {
21,434,948✔
214
    mError("vgId:%d, failed to decode from raw:%p since %s", pVgroup == NULL ? 0 : pVgroup->vgId, pRaw, terrstr());
×
215
    taosMemoryFreeClear(pRow);
×
216
    return NULL;
×
217
  }
218

219
  mTrace("vgId:%d, decode from raw:%p, row:%p", pVgroup->vgId, pRaw, pVgroup);
21,434,948✔
220
  return pRow;
21,434,948✔
221
}
222

223
static int32_t mndNewVgActionValidate(SMnode *pMnode, STrans *pTrans, SSdbRaw *pRaw) {
5,634,774✔
224
  SSdb    *pSdb = pMnode->pSdb;
5,634,774✔
225
  SSdbRow *pRow = NULL;
5,634,774✔
226
  SVgObj  *pVgroup = NULL;
5,634,774✔
227
  int      code = -1;
5,634,774✔
228

229
  pRow = mndVgroupActionDecode(pRaw);
5,634,774✔
230
  if (pRow == NULL) {
5,634,774✔
231
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
232
    if (terrno != 0) code = terrno;
×
233
    goto _OVER;
×
234
  }
235
  pVgroup = sdbGetRowObj(pRow);
5,634,774✔
236
  if (pVgroup == NULL) {
5,634,774✔
237
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
238
    if (terrno != 0) code = terrno;
×
239
    goto _OVER;
×
240
  }
241

242
  int32_t maxVgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP);
5,634,774✔
243
  if (maxVgId > pVgroup->vgId) {
5,634,774✔
244
    mError("trans:%d, vgroup id %d already in use. maxVgId:%d", pTrans->id, pVgroup->vgId, maxVgId);
×
245
    goto _OVER;
×
246
  }
247

248
  code = 0;
5,634,774✔
249
_OVER:
5,634,774✔
250
  if (pVgroup) mndVgroupActionDelete(pSdb, pVgroup);
5,634,774✔
251
  taosMemoryFreeClear(pRow);
5,634,774✔
252
  TAOS_RETURN(code);
5,634,774✔
253
}
254

255
static int32_t mndVgroupActionInsert(SSdb *pSdb, SVgObj *pVgroup) {
6,310,936✔
256
  mTrace("vgId:%d, perform insert action, row:%p", pVgroup->vgId, pVgroup);
6,310,936✔
257
  return 0;
6,310,936✔
258
}
259

260
static int32_t mndVgroupActionDelete(SSdb *pSdb, SVgObj *pVgroup) {
21,411,396✔
261
  mTrace("vgId:%d, perform delete action, row:%p", pVgroup->vgId, pVgroup);
21,411,396✔
262
  return 0;
21,411,396✔
263
}
264

265
static int32_t mndVgroupActionUpdate(SSdb *pSdb, SVgObj *pOld, SVgObj *pNew) {
6,480,606✔
266
  mTrace("vgId:%d, perform update action, old row:%p new row:%p", pOld->vgId, pOld, pNew);
6,480,606✔
267
  pOld->updateTime = pNew->updateTime;
6,480,606✔
268
  pOld->version = pNew->version;
6,480,606✔
269
  pOld->hashBegin = pNew->hashBegin;
6,480,606✔
270
  pOld->hashEnd = pNew->hashEnd;
6,480,606✔
271
  pOld->replica = pNew->replica;
6,480,606✔
272
  pOld->isTsma = pNew->isTsma;
6,480,606✔
273
  pOld->keepVersion = pNew->keepVersion;
6,480,606✔
274
  pOld->keepVersionTime = pNew->keepVersionTime;
6,480,606✔
275
  for (int32_t i = 0; i < pNew->replica; ++i) {
14,977,154✔
276
    SVnodeGid *pNewGid = &pNew->vnodeGid[i];
8,496,548✔
277
    for (int32_t j = 0; j < pOld->replica; ++j) {
23,170,844✔
278
      SVnodeGid *pOldGid = &pOld->vnodeGid[j];
14,674,296✔
279
      if (pNewGid->dnodeId == pOldGid->dnodeId) {
14,674,296✔
280
        pNewGid->syncState = pOldGid->syncState;
8,021,932✔
281
        pNewGid->syncRestore = pOldGid->syncRestore;
8,021,932✔
282
        pNewGid->syncCanRead = pOldGid->syncCanRead;
8,021,932✔
283
        pNewGid->syncAppliedIndex = pOldGid->syncAppliedIndex;
8,021,932✔
284
        pNewGid->syncCommitIndex = pOldGid->syncCommitIndex;
8,021,932✔
285
        pNewGid->bufferSegmentUsed = pOldGid->bufferSegmentUsed;
8,021,932✔
286
        pNewGid->bufferSegmentSize = pOldGid->bufferSegmentSize;
8,021,932✔
287
        pNewGid->learnerProgress = pOldGid->learnerProgress;
8,021,932✔
288
        pNewGid->snapSeq = pOldGid->snapSeq;
8,021,932✔
289
        pNewGid->syncTotalIndex = pOldGid->syncTotalIndex;
8,021,932✔
290
      }
291
    }
292
  }
293
  pNew->numOfTables = pOld->numOfTables;
6,480,606✔
294
  pNew->numOfTimeSeries = pOld->numOfTimeSeries;
6,480,606✔
295
  pNew->totalStorage = pOld->totalStorage;
6,480,606✔
296
  pNew->compStorage = pOld->compStorage;
6,480,606✔
297
  pNew->pointsWritten = pOld->pointsWritten;
6,480,606✔
298
  pNew->compact = pOld->compact;
6,480,606✔
299
  memcpy(pOld->vnodeGid, pNew->vnodeGid, (TSDB_MAX_REPLICA + TSDB_MAX_LEARNER_REPLICA) * sizeof(SVnodeGid));
6,480,606✔
300
  pOld->syncConfChangeVer = pNew->syncConfChangeVer;
6,480,606✔
301
  tstrncpy(pOld->dbName, pNew->dbName, TSDB_DB_FNAME_LEN);
6,480,606✔
302
  return 0;
6,480,606✔
303
}
304

305
SVgObj *mndAcquireVgroup(SMnode *pMnode, int32_t vgId) {
285,194,662✔
306
  SSdb   *pSdb = pMnode->pSdb;
285,194,662✔
307
  SVgObj *pVgroup = sdbAcquire(pSdb, SDB_VGROUP, &vgId);
285,194,662✔
308
  if (pVgroup == NULL && terrno == TSDB_CODE_SDB_OBJ_NOT_THERE) {
285,194,662✔
309
    terrno = TSDB_CODE_MND_VGROUP_NOT_EXIST;
2,213,152✔
310
  }
311
  return pVgroup;
285,194,662✔
312
}
313

314
void mndReleaseVgroup(SMnode *pMnode, SVgObj *pVgroup) {
283,461,416✔
315
  SSdb *pSdb = pMnode->pSdb;
283,461,416✔
316
  sdbRelease(pSdb, pVgroup);
283,461,416✔
317
}
283,461,416✔
318

319
void *mndBuildCreateVnodeReq(SMnode *pMnode, SDnodeObj *pDnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen) {
6,212,776✔
320
  SCreateVnodeReq createReq = {0};
6,212,776✔
321
  createReq.vgId = pVgroup->vgId;
6,212,776✔
322
  memcpy(createReq.db, pDb->name, TSDB_DB_FNAME_LEN);
6,212,776✔
323
  createReq.dbUid = pDb->uid;
6,212,776✔
324
  createReq.vgVersion = pVgroup->version;
6,212,776✔
325
  createReq.numOfStables = pDb->cfg.numOfStables;
6,212,776✔
326
  createReq.buffer = pDb->cfg.buffer;
6,212,776✔
327
  createReq.pageSize = pDb->cfg.pageSize;
6,212,776✔
328
  createReq.pages = pDb->cfg.pages;
6,212,776✔
329
  createReq.cacheLastSize = pDb->cfg.cacheLastSize;
6,212,776✔
330
  createReq.daysPerFile = pDb->cfg.daysPerFile;
6,212,776✔
331
  createReq.daysToKeep0 = pDb->cfg.daysToKeep0;
6,212,776✔
332
  createReq.daysToKeep1 = pDb->cfg.daysToKeep1;
6,212,776✔
333
  createReq.daysToKeep2 = pDb->cfg.daysToKeep2;
6,212,776✔
334
  createReq.keepTimeOffset = pDb->cfg.keepTimeOffset;
6,212,776✔
335
  createReq.ssChunkSize = pDb->cfg.ssChunkSize;
6,212,776✔
336
  createReq.ssKeepLocal = pDb->cfg.ssKeepLocal;
6,212,776✔
337
  createReq.ssCompact = pDb->cfg.ssCompact;
6,212,776✔
338
  createReq.minRows = pDb->cfg.minRows;
6,212,776✔
339
  createReq.maxRows = pDb->cfg.maxRows;
6,212,776✔
340
  createReq.walFsyncPeriod = pDb->cfg.walFsyncPeriod;
6,212,776✔
341
  createReq.walLevel = pDb->cfg.walLevel;
6,212,776✔
342
  createReq.precision = pDb->cfg.precision;
6,212,776✔
343
  createReq.compression = pDb->cfg.compression;
6,212,776✔
344
  createReq.strict = pDb->cfg.strict;
6,212,776✔
345
  createReq.cacheLast = pDb->cfg.cacheLast;
6,212,776✔
346
  createReq.replica = 0;
6,212,776✔
347
  createReq.learnerReplica = 0;
6,212,776✔
348
  createReq.selfIndex = -1;
6,212,776✔
349
  createReq.learnerSelfIndex = -1;
6,212,776✔
350
  createReq.hashBegin = pVgroup->hashBegin;
6,212,776✔
351
  createReq.hashEnd = pVgroup->hashEnd;
6,212,776✔
352
  createReq.hashMethod = pDb->cfg.hashMethod;
6,212,776✔
353
  createReq.numOfRetensions = pDb->cfg.numOfRetensions;
6,212,776✔
354
  createReq.pRetensions = pDb->cfg.pRetensions;
6,212,776✔
355
  createReq.isTsma = pVgroup->isTsma;
6,212,776✔
356
  createReq.pTsma = pVgroup->pTsma;
6,212,776✔
357
  createReq.walRetentionPeriod = pDb->cfg.walRetentionPeriod;
6,212,776✔
358
  createReq.walRetentionSize = pDb->cfg.walRetentionSize;
6,212,776✔
359
  createReq.walRollPeriod = pDb->cfg.walRollPeriod;
6,212,776✔
360
  createReq.walSegmentSize = pDb->cfg.walSegmentSize;
6,212,776✔
361
  createReq.sstTrigger = pDb->cfg.sstTrigger;
6,212,776✔
362
  createReq.hashPrefix = pDb->cfg.hashPrefix;
6,212,776✔
363
  createReq.hashSuffix = pDb->cfg.hashSuffix;
6,212,776✔
364
  createReq.tsdbPageSize = pDb->cfg.tsdbPageSize;
6,212,776✔
365
  createReq.changeVersion = ++(pVgroup->syncConfChangeVer);
6,212,776✔
366
  // createReq.encryptAlgorithm = pDb->cfg.encryptAlgorithm;
367
  memset(createReq.encryptAlgrName, 0, TSDB_ENCRYPT_ALGR_NAME_LEN);
6,212,776✔
368
  if (pDb->cfg.encryptAlgorithm > 0) {
6,212,776✔
369
    mndGetEncryptOsslAlgrNameById(pMnode, pDb->cfg.encryptAlgorithm, createReq.encryptAlgrName);
8,988✔
370
  }
371
  createReq.isAudit = pDb->cfg.isAudit ? 1 : 0;
6,212,776✔
372
  createReq.allowDrop = pDb->cfg.allowDrop;
6,212,776✔
373
  createReq.secureDelete = pDb->cfg.secureDelete;
6,212,776✔
374
  int32_t code = 0;
6,212,776✔
375

376
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
14,679,656✔
377
    SReplica *pReplica = NULL;
8,466,880✔
378

379
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
8,466,880✔
380
      pReplica = &createReq.replicas[createReq.replica];
8,244,116✔
381
    } else {
382
      pReplica = &createReq.learnerReplicas[createReq.learnerReplica];
222,764✔
383
    }
384

385
    SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
8,466,880✔
386
    SDnodeObj *pVgidDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
8,466,880✔
387
    if (pVgidDnode == NULL) {
8,466,880✔
UNCOV
388
      return NULL;
×
389
    }
390

391
    pReplica->id = pVgidDnode->id;
8,466,880✔
392
    pReplica->port = pVgidDnode->port;
8,466,880✔
393
    memcpy(pReplica->fqdn, pVgidDnode->fqdn, TSDB_FQDN_LEN);
8,466,880✔
394
    mndReleaseDnode(pMnode, pVgidDnode);
8,466,880✔
395

396
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
8,466,880✔
397
      if (pDnode->id == pVgid->dnodeId) {
8,244,116✔
398
        createReq.selfIndex = createReq.replica;
5,990,012✔
399
      }
400
    } else {
401
      if (pDnode->id == pVgid->dnodeId) {
222,764✔
402
        createReq.learnerSelfIndex = createReq.learnerReplica;
222,764✔
403
      }
404
    }
405

406
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
8,466,880✔
407
      createReq.replica++;
8,244,116✔
408
    } else {
409
      createReq.learnerReplica++;
222,764✔
410
    }
411
  }
412

413
  if (createReq.selfIndex == -1 && createReq.learnerSelfIndex == -1) {
6,212,776✔
UNCOV
414
    terrno = TSDB_CODE_APP_ERROR;
×
415
    return NULL;
×
416
  }
417

418
  createReq.changeVersion = pVgroup->syncConfChangeVer;
6,212,776✔
419

420
  mInfo(
6,212,776✔
421
      "vgId:%d, build create vnode req, replica:%d selfIndex:%d learnerReplica:%d learnerSelfIndex:%d strict:%d "
422
      "changeVersion:%d",
423
      createReq.vgId, createReq.replica, createReq.selfIndex, createReq.learnerReplica, createReq.learnerSelfIndex,
424
      createReq.strict, createReq.changeVersion);
425
  for (int32_t i = 0; i < createReq.replica; ++i) {
14,456,892✔
426
    mInfo("vgId:%d, replica:%d ep:%s:%u", createReq.vgId, i, createReq.replicas[i].fqdn, createReq.replicas[i].port);
8,244,116✔
427
  }
428
  for (int32_t i = 0; i < createReq.learnerReplica; ++i) {
6,435,540✔
429
    mInfo("vgId:%d, replica:%d ep:%s:%u", createReq.vgId, i, createReq.learnerReplicas[i].fqdn,
222,764✔
430
          createReq.learnerReplicas[i].port);
431
  }
432

433
  int32_t contLen = tSerializeSCreateVnodeReq(NULL, 0, &createReq);
6,212,776✔
434
  if (contLen < 0) {
6,212,776✔
UNCOV
435
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
436
    return NULL;
×
437
  }
438

439
  void *pReq = taosMemoryMalloc(contLen);
6,212,776✔
440
  if (pReq == NULL) {
6,212,776✔
UNCOV
441
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
442
    return NULL;
×
443
  }
444

445
  code = tSerializeSCreateVnodeReq(pReq, contLen, &createReq);
6,212,776✔
446
  if (code < 0) {
6,212,776✔
UNCOV
447
    terrno = TSDB_CODE_APP_ERROR;
×
448
    taosMemoryFree(pReq);
×
449
    mError("vgId:%d, failed to serialize create vnode req,since %s", createReq.vgId, terrstr());
×
450
    return NULL;
×
451
  }
452
  *pContLen = contLen;
6,212,776✔
453
  return pReq;
6,212,776✔
454
}
455

456
static void *mndBuildAlterVnodeConfigReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen) {
414,606✔
457
  SAlterVnodeConfigReq alterReq = {0};
414,606✔
458
  alterReq.vgVersion = pVgroup->version;
414,606✔
459
  alterReq.buffer = pDb->cfg.buffer;
414,606✔
460
  alterReq.pageSize = pDb->cfg.pageSize;
414,606✔
461
  alterReq.pages = pDb->cfg.pages;
414,606✔
462
  alterReq.cacheLastSize = pDb->cfg.cacheLastSize;
414,606✔
463
  alterReq.daysPerFile = pDb->cfg.daysPerFile;
414,606✔
464
  alterReq.daysToKeep0 = pDb->cfg.daysToKeep0;
414,606✔
465
  alterReq.daysToKeep1 = pDb->cfg.daysToKeep1;
414,606✔
466
  alterReq.daysToKeep2 = pDb->cfg.daysToKeep2;
414,606✔
467
  alterReq.keepTimeOffset = pDb->cfg.keepTimeOffset;
414,606✔
468
  alterReq.walFsyncPeriod = pDb->cfg.walFsyncPeriod;
414,606✔
469
  alterReq.walLevel = pDb->cfg.walLevel;
414,606✔
470
  alterReq.strict = pDb->cfg.strict;
414,606✔
471
  alterReq.cacheLast = pDb->cfg.cacheLast;
414,606✔
472
  alterReq.sttTrigger = pDb->cfg.sstTrigger;
414,606✔
473
  alterReq.minRows = pDb->cfg.minRows;
414,606✔
474
  alterReq.walRetentionPeriod = pDb->cfg.walRetentionPeriod;
414,606✔
475
  alterReq.walRetentionSize = pDb->cfg.walRetentionSize;
414,606✔
476
  alterReq.ssKeepLocal = pDb->cfg.ssKeepLocal;
414,606✔
477
  alterReq.ssCompact = pDb->cfg.ssCompact;
414,606✔
478
  alterReq.allowDrop = (int8_t)pDb->cfg.allowDrop;
414,606✔
479
  alterReq.secureDelete = pDb->cfg.secureDelete;
414,606✔
480

481
  mInfo("vgId:%d, build alter vnode config req", pVgroup->vgId);
414,606✔
482
  int32_t contLen = tSerializeSAlterVnodeConfigReq(NULL, 0, &alterReq);
414,606✔
483
  if (contLen < 0) {
414,606✔
UNCOV
484
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
485
    return NULL;
×
486
  }
487
  contLen += sizeof(SMsgHead);
414,606✔
488

489
  void *pReq = taosMemoryMalloc(contLen);
414,606✔
490
  if (pReq == NULL) {
414,606✔
UNCOV
491
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
492
    return NULL;
×
493
  }
494

495
  SMsgHead *pHead = pReq;
414,606✔
496
  pHead->contLen = htonl(contLen);
414,606✔
497
  pHead->vgId = htonl(pVgroup->vgId);
414,606✔
498

499
  if (tSerializeSAlterVnodeConfigReq((char *)pReq + sizeof(SMsgHead), contLen, &alterReq) < 0) {
414,606✔
UNCOV
500
    taosMemoryFree(pReq);
×
UNCOV
501
    mError("vgId:%d, failed to serialize alter vnode config req,since %s", pVgroup->vgId, terrstr());
×
502
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
503
    return NULL;
×
504
  }
505
  *pContLen = contLen;
414,606✔
506
  return pReq;
414,606✔
507
}
508

509
static void *mndBuildAlterVnodeReplicaReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId,
1,691,108✔
510
                                          int32_t *pContLen) {
511
  SAlterVnodeReplicaReq alterReq = {
3,382,216✔
512
      .vgId = pVgroup->vgId,
1,691,108✔
513
      .strict = pDb->cfg.strict,
1,691,108✔
514
      .replica = 0,
515
      .learnerReplica = 0,
516
      .selfIndex = -1,
517
      .learnerSelfIndex = -1,
518
      .changeVersion = ++(pVgroup->syncConfChangeVer),
3,382,216✔
519
  };
520

521
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
6,926,612✔
522
    SReplica *pReplica = NULL;
5,235,504✔
523

524
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
5,235,504✔
525
      pReplica = &alterReq.replicas[alterReq.replica];
4,824,284✔
526
      alterReq.replica++;
4,824,284✔
527
    } else {
528
      pReplica = &alterReq.learnerReplicas[alterReq.learnerReplica];
411,220✔
529
      alterReq.learnerReplica++;
411,220✔
530
    }
531

532
    SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
5,235,504✔
533
    SDnodeObj *pVgidDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
5,235,504✔
534
    if (pVgidDnode == NULL) return NULL;
5,235,504✔
535

536
    pReplica->id = pVgidDnode->id;
5,235,504✔
537
    pReplica->port = pVgidDnode->port;
5,235,504✔
538
    memcpy(pReplica->fqdn, pVgidDnode->fqdn, TSDB_FQDN_LEN);
5,235,504✔
539
    mndReleaseDnode(pMnode, pVgidDnode);
5,235,504✔
540

541
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
5,235,504✔
542
      if (dnodeId == pVgid->dnodeId) {
4,824,284✔
543
        alterReq.selfIndex = v;
1,691,108✔
544
      }
545
    } else {
546
      if (dnodeId == pVgid->dnodeId) {
411,220✔
UNCOV
547
        alterReq.learnerSelfIndex = v;
×
548
      }
549
    }
550
  }
551

552
  mInfo(
1,691,108✔
553
      "vgId:%d, build alter vnode req, replica:%d selfIndex:%d learnerReplica:%d learnerSelfIndex:%d strict:%d "
554
      "changeVersion:%d",
555
      alterReq.vgId, alterReq.replica, alterReq.selfIndex, alterReq.learnerReplica, alterReq.learnerSelfIndex,
556
      alterReq.strict, alterReq.changeVersion);
557
  for (int32_t i = 0; i < alterReq.replica; ++i) {
6,515,392✔
558
    mInfo("vgId:%d, replica:%d ep:%s:%u", alterReq.vgId, i, alterReq.replicas[i].fqdn, alterReq.replicas[i].port);
4,824,284✔
559
  }
560
  for (int32_t i = 0; i < alterReq.learnerReplica; ++i) {
2,102,328✔
561
    mInfo("vgId:%d, learnerReplica:%d ep:%s:%u", alterReq.vgId, i, alterReq.learnerReplicas[i].fqdn,
411,220✔
562
          alterReq.learnerReplicas[i].port);
563
  }
564

565
  if (alterReq.selfIndex == -1 && alterReq.learnerSelfIndex == -1) {
1,691,108✔
UNCOV
566
    terrno = TSDB_CODE_APP_ERROR;
×
UNCOV
567
    return NULL;
×
568
  }
569

570
  int32_t contLen = tSerializeSAlterVnodeReplicaReq(NULL, 0, &alterReq);
1,691,108✔
571
  if (contLen < 0) {
1,691,108✔
UNCOV
572
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
573
    return NULL;
×
574
  }
575

576
  void *pReq = taosMemoryMalloc(contLen);
1,691,108✔
577
  if (pReq == NULL) {
1,691,108✔
UNCOV
578
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
579
    return NULL;
×
580
  }
581

582
  if (tSerializeSAlterVnodeReplicaReq(pReq, contLen, &alterReq) < 0) {
1,691,108✔
UNCOV
583
    mError("vgId:%d, failed to serialize alter vnode req,since %s", alterReq.vgId, terrstr());
×
UNCOV
584
    taosMemoryFree(pReq);
×
585
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
586
    return NULL;
×
587
  }
588
  *pContLen = contLen;
1,691,108✔
589
  return pReq;
1,691,108✔
590
}
591

UNCOV
592
static void *mndBuildCheckLearnCatchupReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId,
×
593
                                          int32_t *pContLen) {
594
  SCheckLearnCatchupReq req = {
×
UNCOV
595
      .vgId = pVgroup->vgId,
×
596
      .strict = pDb->cfg.strict,
×
597
      .replica = 0,
598
      .learnerReplica = 0,
599
      .selfIndex = -1,
600
      .learnerSelfIndex = -1,
601
  };
602

UNCOV
603
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
×
UNCOV
604
    SReplica *pReplica = NULL;
×
605

606
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
×
UNCOV
607
      pReplica = &req.replicas[req.replica];
×
608
      req.replica++;
×
609
    } else {
610
      pReplica = &req.learnerReplicas[req.learnerReplica];
×
UNCOV
611
      req.learnerReplica++;
×
612
    }
613

UNCOV
614
    SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
×
UNCOV
615
    SDnodeObj *pVgidDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
×
616
    if (pVgidDnode == NULL) return NULL;
×
617

618
    pReplica->id = pVgidDnode->id;
×
UNCOV
619
    pReplica->port = pVgidDnode->port;
×
620
    memcpy(pReplica->fqdn, pVgidDnode->fqdn, TSDB_FQDN_LEN);
×
621
    mndReleaseDnode(pMnode, pVgidDnode);
×
622

623
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
×
UNCOV
624
      if (dnodeId == pVgid->dnodeId) {
×
625
        req.selfIndex = v;
×
626
      }
627
    } else {
UNCOV
628
      if (dnodeId == pVgid->dnodeId) {
×
UNCOV
629
        req.learnerSelfIndex = v;
×
630
      }
631
    }
632
  }
633

UNCOV
634
  mInfo("vgId:%d, build alter vnode req, replica:%d selfIndex:%d learnerReplica:%d learnerSelfIndex:%d strict:%d",
×
635
        req.vgId, req.replica, req.selfIndex, req.learnerReplica, req.learnerSelfIndex, req.strict);
636
  for (int32_t i = 0; i < req.replica; ++i) {
×
UNCOV
637
    mInfo("vgId:%d, replica:%d ep:%s:%u", req.vgId, i, req.replicas[i].fqdn, req.replicas[i].port);
×
638
  }
639
  for (int32_t i = 0; i < req.learnerReplica; ++i) {
×
UNCOV
640
    mInfo("vgId:%d, learnerReplica:%d ep:%s:%u", req.vgId, i, req.learnerReplicas[i].fqdn, req.learnerReplicas[i].port);
×
641
  }
642

UNCOV
643
  if (req.selfIndex == -1 && req.learnerSelfIndex == -1) {
×
UNCOV
644
    terrno = TSDB_CODE_APP_ERROR;
×
645
    return NULL;
×
646
  }
647

UNCOV
648
  int32_t contLen = tSerializeSAlterVnodeReplicaReq(NULL, 0, &req);
×
UNCOV
649
  if (contLen < 0) {
×
650
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
651
    return NULL;
×
652
  }
653

UNCOV
654
  void *pReq = taosMemoryMalloc(contLen);
×
UNCOV
655
  if (pReq == NULL) {
×
656
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
657
    return NULL;
×
658
  }
659

UNCOV
660
  if (tSerializeSAlterVnodeReplicaReq(pReq, contLen, &req) < 0) {
×
UNCOV
661
    mError("vgId:%d, failed to serialize alter vnode req,since %s", req.vgId, terrstr());
×
662
    taosMemoryFree(pReq);
×
663
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
664
    return NULL;
×
665
  }
666
  *pContLen = contLen;
×
UNCOV
667
  return pReq;
×
668
}
669

670
static void *mndBuildDisableVnodeWriteReq(SMnode *pMnode, SDbObj *pDb, int32_t vgId, int32_t *pContLen) {
68,016✔
671
  SDisableVnodeWriteReq disableReq = {
68,016✔
672
      .vgId = vgId,
673
      .disable = 1,
674
  };
675

676
  mInfo("vgId:%d, build disable vnode write req", vgId);
68,016✔
677
  int32_t contLen = tSerializeSDisableVnodeWriteReq(NULL, 0, &disableReq);
68,016✔
678
  if (contLen < 0) {
68,016✔
UNCOV
679
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
680
    return NULL;
×
681
  }
682

683
  void *pReq = taosMemoryMalloc(contLen);
68,016✔
684
  if (pReq == NULL) {
68,016✔
UNCOV
685
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
686
    return NULL;
×
687
  }
688

689
  if (tSerializeSDisableVnodeWriteReq(pReq, contLen, &disableReq) < 0) {
68,016✔
UNCOV
690
    mError("vgId:%d, failed to serialize disable vnode write req,since %s", vgId, terrstr());
×
UNCOV
691
    taosMemoryFree(pReq);
×
692
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
693
    return NULL;
×
694
  }
695
  *pContLen = contLen;
68,016✔
696
  return pReq;
68,016✔
697
}
698

699
static void *mndBuildAlterVnodeHashRangeReq(SMnode *pMnode, int32_t srcVgId, SVgObj *pVgroup, int32_t *pContLen) {
68,016✔
700
  SAlterVnodeHashRangeReq alterReq = {
136,032✔
701
      .srcVgId = srcVgId,
702
      .dstVgId = pVgroup->vgId,
68,016✔
703
      .hashBegin = pVgroup->hashBegin,
68,016✔
704
      .hashEnd = pVgroup->hashEnd,
68,016✔
705
      .changeVersion = ++(pVgroup->syncConfChangeVer),
136,032✔
706
  };
707

708
  mInfo("vgId:%d, build alter vnode hashrange req, dstVgId:%d, hashrange:[%u, %u]", srcVgId, pVgroup->vgId,
68,016✔
709
        pVgroup->hashBegin, pVgroup->hashEnd);
710
  int32_t contLen = tSerializeSAlterVnodeHashRangeReq(NULL, 0, &alterReq);
68,016✔
711
  if (contLen < 0) {
68,016✔
UNCOV
712
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
713
    return NULL;
×
714
  }
715

716
  void *pReq = taosMemoryMalloc(contLen);
68,016✔
717
  if (pReq == NULL) {
68,016✔
UNCOV
718
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
719
    return NULL;
×
720
  }
721

722
  if (tSerializeSAlterVnodeHashRangeReq(pReq, contLen, &alterReq) < 0) {
68,016✔
UNCOV
723
    mError("vgId:%d, failed to serialize alter vnode hashrange req,since %s", srcVgId, terrstr());
×
UNCOV
724
    taosMemoryFree(pReq);
×
725
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
726
    return NULL;
×
727
  }
728
  *pContLen = contLen;
68,016✔
729
  return pReq;
68,016✔
730
}
731

732
void *mndBuildDropVnodeReq(SMnode *pMnode, SDnodeObj *pDnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen) {
9,159,916✔
733
  SDropVnodeReq dropReq = {0};
9,159,916✔
734
  dropReq.dnodeId = pDnode->id;
9,159,916✔
735
  dropReq.vgId = pVgroup->vgId;
9,159,916✔
736
  memcpy(dropReq.db, pDb->name, TSDB_DB_FNAME_LEN);
9,159,916✔
737
  dropReq.dbUid = pDb->uid;
9,159,916✔
738

739
  mInfo("vgId:%d, build drop vnode req", dropReq.vgId);
9,159,916✔
740
  int32_t contLen = tSerializeSDropVnodeReq(NULL, 0, &dropReq);
9,159,916✔
741
  if (contLen < 0) {
9,159,916✔
UNCOV
742
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
743
    return NULL;
×
744
  }
745

746
  void *pReq = taosMemoryMalloc(contLen);
9,159,916✔
747
  if (pReq == NULL) {
9,159,916✔
UNCOV
748
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
749
    return NULL;
×
750
  }
751

752
  if (tSerializeSDropVnodeReq(pReq, contLen, &dropReq) < 0) {
9,159,916✔
UNCOV
753
    mError("vgId:%d, failed to serialize drop vnode req,since %s", dropReq.vgId, terrstr());
×
UNCOV
754
    taosMemoryFree(pReq);
×
755
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
756
    return NULL;
×
757
  }
758
  *pContLen = contLen;
9,159,916✔
759
  return pReq;
9,159,916✔
760
}
761

762
static bool mndResetDnodesArrayFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
4,071,302✔
763
  SDnodeObj *pDnode = pObj;
4,071,302✔
764
  pDnode->numOfVnodes = 0;
4,071,302✔
765
  pDnode->numOfOtherNodes = 0;
4,071,302✔
766
  return true;
4,071,302✔
767
}
768

769
static bool mndBuildDnodesArrayFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
4,071,302✔
770
  SDnodeObj *pDnode = pObj;
4,071,302✔
771
  SArray    *pArray = p1;
4,071,302✔
772
  int32_t    exceptDnodeId = *(int32_t *)p2;
4,071,302✔
773
  SArray    *dnodeList = p3;
4,071,302✔
774

775
  if (exceptDnodeId == pDnode->id) {
4,071,302✔
776
    return true;
15,232✔
777
  }
778

779
  if (dnodeList != NULL) {
4,056,070✔
780
    int32_t dnodeListSize = taosArrayGetSize(dnodeList);
145,158✔
781
    if (dnodeListSize > 0) {
145,158✔
782
      bool inDnodeList = false;
145,158✔
783
      for (int32_t index = 0; index < dnodeListSize; ++index) {
473,024✔
784
        int32_t dnodeId = *(int32_t *)taosArrayGet(dnodeList, index);
327,866✔
785
        if (pDnode->id == dnodeId) {
327,866✔
786
          inDnodeList = true;
67,054✔
787
        }
788
      }
789
      if (!inDnodeList) {
145,158✔
790
        return true;
78,104✔
791
      }
792
    } else {
UNCOV
793
      return true;  // TS-6191
×
794
    }
795
  }
796

797
  int64_t curMs = taosGetTimestampMs();
3,977,966✔
798
  bool    online = mndIsDnodeOnline(pDnode, curMs);
3,977,966✔
799
  bool    isMnode = mndIsMnode(pMnode, pDnode->id);
3,977,966✔
800
  pDnode->numOfVnodes = mndGetVnodesNum(pMnode, pDnode->id);
3,977,966✔
801
  pDnode->memUsed = mndGetVnodesMemory(pMnode, pDnode->id);
3,977,966✔
802

803
  mInfo("dnode:%d, vnodes:%d supportVnodes:%d isMnode:%d online:%d memory avail:%" PRId64 " used:%" PRId64, pDnode->id,
3,977,966✔
804
        pDnode->numOfVnodes, pDnode->numOfSupportVnodes, isMnode, online, pDnode->memAvail, pDnode->memUsed);
805

806
  if (isMnode) {
3,977,966✔
807
    pDnode->numOfOtherNodes++;
2,850,654✔
808
  }
809

810
  if (online && pDnode->numOfSupportVnodes > 0) {
3,977,966✔
811
    if (taosArrayPush(pArray, pDnode) == NULL) return false;
3,877,670✔
812
  }
813
  return true;
3,977,966✔
814
}
815

UNCOV
816
static bool isDnodeInList(SArray *dnodeList, int32_t dnodeId) {
×
UNCOV
817
  int32_t dnodeListSize = taosArrayGetSize(dnodeList);
×
818
  for (int32_t i = 0; i < dnodeListSize; ++i) {
×
819
    int32_t id = *(int32_t *)TARRAY_GET_ELEM(dnodeList, i);
×
820
    if (id == dnodeId) {
×
821
      return true;
×
822
    }
823
  }
UNCOV
824
  return false;
×
825
}
826

827
#ifdef TD_ENTERPRISE
UNCOV
828
static float mndGetDnodeScore1(SDnodeObj *pDnode, int32_t additionDnodes, float ratio) {
×
UNCOV
829
  float totalDnodes = pDnode->numOfVnodes + (float)pDnode->numOfOtherNodes * ratio + additionDnodes;
×
830
  float result = totalDnodes / pDnode->numOfSupportVnodes;
×
831
  return pDnode->numOfVnodes > 0 ? -result : result;
×
832
}
833

UNCOV
834
static int32_t mndCompareDnodeVnodes1(SDnodeObj *pDnode1, SDnodeObj *pDnode2) {
×
UNCOV
835
  float d1Score = mndGetDnodeScore1(pDnode1, 0, 0.9);
×
836
  float d2Score = mndGetDnodeScore1(pDnode2, 0, 0.9);
×
837
  if (d1Score == d2Score) {
×
838
    if (pDnode1->id == pDnode2->id) {
×
839
      return 0;
×
840
    }
841
    return pDnode1->id > pDnode2->id ? 1 : -1;
×
842
  }
843
  return d1Score > d2Score ? 1 : -1;
×
844
}
845

UNCOV
846
static bool mndBuildDnodesListFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
×
UNCOV
847
  SDnodeObj *pDnode = pObj;
×
848
  SArray    *pArray = p1;
×
849

850
  bool isMnode = mndIsMnode(pMnode, pDnode->id);
×
UNCOV
851
  pDnode->numOfVnodes = mndGetVnodesNum(pMnode, pDnode->id);
×
852

853
  if (isMnode) {
×
UNCOV
854
    pDnode->numOfOtherNodes++;
×
855
  }
856

UNCOV
857
  if (pDnode->numOfSupportVnodes > 0) {
×
UNCOV
858
    if (taosArrayPush(pArray, pDnode) == NULL) return false;
×
859
  }
860
  return true;
×
861
}
862

863
// TS-6191
864
static int32_t mndBuildNodesCheckDualReplica(SMnode *pMnode, int32_t nDnodes, SArray *dnodeList, SArray **ppDnodeList) {
2,774,500✔
865
  int32_t code = 0;
2,774,500✔
866
  if (!grantCheckDualReplicaDnodes(pMnode)) {
2,774,500✔
867
    TAOS_RETURN(code);
2,774,500✔
868
  }
UNCOV
869
  SSdb   *pSdb = pMnode->pSdb;
×
UNCOV
870
  SArray *pArray = taosArrayInit(nDnodes, sizeof(SDnodeObj));
×
871
  if (pArray == NULL) {
×
872
    TAOS_RETURN(code = terrno);
×
873
  }
874
  *ppDnodeList = pArray;
×
875

876
  sdbTraverse(pSdb, SDB_DNODE, mndResetDnodesArrayFp, NULL, NULL, NULL);
×
UNCOV
877
  sdbTraverse(pSdb, SDB_DNODE, mndBuildDnodesListFp, pArray, NULL, NULL);
×
878

879
  int32_t arrSize = taosArrayGetSize(pArray);
×
UNCOV
880
  if (arrSize <= 0) {
×
881
    TAOS_RETURN(code);
×
882
  }
883
  if (arrSize > 1) taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes1);
×
884

885
  int32_t dnodeListSize = taosArrayGetSize(dnodeList);
×
UNCOV
886
  if (dnodeListSize <= 0) {
×
887
    if (arrSize > 2) taosArrayRemoveBatch(pArray, 2, arrSize - 2, NULL);
×
888
  } else {
889
    int32_t nDnodesWithVnodes = 0;
×
UNCOV
890
    for (int32_t i = 0; i < arrSize; ++i) {
×
891
      SDnodeObj *pDnode = TARRAY_GET_ELEM(pArray, i);
×
892
      if (pDnode->numOfVnodes <= 0) {
×
893
        break;
×
894
      }
895
      ++nDnodesWithVnodes;
×
896
    }
897
    int32_t dnodeId = -1;
×
UNCOV
898
    if (nDnodesWithVnodes == 1) {
×
899
      dnodeId = ((SDnodeObj *)TARRAY_GET_ELEM(pArray, 0))->id;
×
900
    } else if (nDnodesWithVnodes >= 2) {
×
901
      // must select the dnodes from the 1st 2 dnodes
902
      taosArrayRemoveBatch(pArray, 2, arrSize - 2, NULL);
×
903
    }
904
    for (int32_t i = 0; i < TARRAY_SIZE(pArray);) {
×
UNCOV
905
      SDnodeObj *pDnode = taosArrayGet(pArray, i);
×
906
      if (!isDnodeInList(dnodeList, pDnode->id)) {
×
907
        taosArrayRemove(pArray, i);
×
908
        continue;
×
909
      }
910
      ++i;
×
911
    }
912
    if (nDnodesWithVnodes == 1) {
×
UNCOV
913
      SDnodeObj *pDnode = taosArrayGet(pArray, 0);
×
914
      if (pDnode && (pDnode->id != dnodeId)) {  // the first dnode is not in dnodeList, remove the last element
×
915
        taosArrayRemove(pArray, taosArrayGetSize(pArray) - 1);
×
916
      }
917
    }
918
  }
919

UNCOV
920
  TAOS_RETURN(code);
×
921
}
922
#endif
923

924
SArray *mndBuildDnodesArray(SMnode *pMnode, int32_t exceptDnodeId, SArray *dnodeList) {
2,774,500✔
925
  SSdb   *pSdb = pMnode->pSdb;
2,774,500✔
926
  int32_t numOfDnodes = mndGetDnodeSize(pMnode);
2,774,500✔
927
  SArray *tDnodeList = NULL;
2,774,500✔
928
  SArray *pDnodeList = NULL;
2,774,500✔
929

930
  SArray *pArray = taosArrayInit(numOfDnodes, sizeof(SDnodeObj));
2,774,500✔
931
  if (pArray == NULL) {
2,774,500✔
UNCOV
932
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
933
    return NULL;
×
934
  }
935
  if (taosArrayGetSize(dnodeList) > 0) {
2,774,500✔
936
    tDnodeList = dnodeList;
29,772✔
937
  }
938
#ifdef TD_ENTERPRISE
939
  if (0 != mndBuildNodesCheckDualReplica(pMnode, numOfDnodes, tDnodeList, &pDnodeList)) {
2,774,500✔
UNCOV
940
    taosArrayDestroy(pArray);
×
UNCOV
941
    return NULL;
×
942
  }
943
#endif
944
  sdbTraverse(pSdb, SDB_DNODE, mndResetDnodesArrayFp, NULL, NULL, NULL);
2,774,500✔
945
  sdbTraverse(pSdb, SDB_DNODE, mndBuildDnodesArrayFp, pArray, &exceptDnodeId, pDnodeList ? pDnodeList : tDnodeList);
2,774,500✔
946

947
  mDebug("build %d dnodes array", (int32_t)taosArrayGetSize(pArray));
2,774,500✔
948
  for (int32_t i = 0; i < (int32_t)taosArrayGetSize(pArray); ++i) {
6,652,170✔
949
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
3,877,670✔
950
    mDebug("dnode:%d, vnodes:%d others:%d", pDnode->id, pDnode->numOfVnodes, pDnode->numOfOtherNodes);
3,877,670✔
951
  }
952
  taosArrayDestroy(pDnodeList);
2,774,500✔
953
  return pArray;
2,774,500✔
954
}
955

UNCOV
956
static int32_t mndCompareDnodeId(int32_t *dnode1Id, int32_t *dnode2Id) {
×
UNCOV
957
  if (*dnode1Id == *dnode2Id) {
×
958
    return 0;
×
959
  }
960
  return *dnode1Id > *dnode2Id ? 1 : -1;
×
961
}
962

963
static float mndGetDnodeScore(SDnodeObj *pDnode, int32_t additionDnodes, float ratio) {
19,817,328✔
964
  float totalDnodes = pDnode->numOfVnodes + (float)pDnode->numOfOtherNodes * ratio + additionDnodes;
19,817,328✔
965
  return totalDnodes / pDnode->numOfSupportVnodes;
19,817,328✔
966
}
967

968
static int32_t mndCompareDnodeVnodes(SDnodeObj *pDnode1, SDnodeObj *pDnode2) {
6,168,994✔
969
  float d1Score = mndGetDnodeScore(pDnode1, 0, 0.9);
6,168,994✔
970
  float d2Score = mndGetDnodeScore(pDnode2, 0, 0.9);
6,168,994✔
971
  if (d1Score == d2Score) {
6,168,994✔
972
    return 0;
2,042,434✔
973
  }
974
  return d1Score > d2Score ? 1 : -1;
4,126,560✔
975
}
976

977
void mndSortVnodeGid(SVgObj *pVgroup) {
5,415,458✔
978
  for (int32_t i = 0; i < pVgroup->replica; ++i) {
11,504,940✔
979
    for (int32_t j = 0; j < pVgroup->replica - 1 - i; ++j) {
7,092,614✔
980
      if (pVgroup->vnodeGid[j].dnodeId > pVgroup->vnodeGid[j + 1].dnodeId) {
1,003,132✔
981
        TSWAP(pVgroup->vnodeGid[j], pVgroup->vnodeGid[j + 1]);
461,628✔
982
      }
983
    }
984
  }
985
}
5,415,458✔
986

987
static int32_t mndGetAvailableDnode(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, SArray *pArray) {
5,357,972✔
988
  mDebug("start to sort %d dnodes", (int32_t)taosArrayGetSize(pArray));
5,357,972✔
989
  taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
5,357,972✔
990
  for (int32_t i = 0; i < (int32_t)taosArrayGetSize(pArray); ++i) {
12,711,864✔
991
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
7,353,892✔
992
    mDebug("dnode:%d, score:%f", pDnode->id, mndGetDnodeScore(pDnode, 0, 0.9));
7,353,892✔
993
  }
994

995
  int32_t size = taosArrayGetSize(pArray);
5,357,972✔
996
  if (size < pVgroup->replica) {
5,357,972✔
997
    mError("db:%s, vgId:%d, no enough online dnodes:%d to alloc %d replica", pVgroup->dbName, pVgroup->vgId, size,
10,850✔
998
           pVgroup->replica);
999
    TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_DNODES);
10,850✔
1000
  }
1001

1002
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
11,248,008✔
1003
    SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
5,900,886✔
1004
    SDnodeObj *pDnode = taosArrayGet(pArray, v);
5,900,886✔
1005
    if (pDnode == NULL) {
5,900,886✔
UNCOV
1006
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_DNODES);
×
1007
    }
1008
    if (pDnode->numOfVnodes >= pDnode->numOfSupportVnodes) {
5,900,886✔
UNCOV
1009
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_VNODES);
×
1010
    }
1011

1012
    int64_t vgMem = mndGetVgroupMemory(pMnode, pDb, pVgroup);
5,900,886✔
1013
    if (pDnode->memAvail - vgMem - pDnode->memUsed <= 0) {
5,900,886✔
UNCOV
1014
      mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d, avail:%" PRId64 " used:%" PRId64,
×
1015
             pVgroup->dbName, pVgroup->vgId, vgMem, pDnode->id, pDnode->memAvail, pDnode->memUsed);
1016
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE);
×
1017
    } else {
1018
      pDnode->memUsed += vgMem;
5,900,886✔
1019
    }
1020

1021
    pVgid->dnodeId = pDnode->id;
5,900,886✔
1022
    if (pVgroup->replica == 1) {
5,900,886✔
1023
      pVgid->syncState = TAOS_SYNC_STATE_LEADER;
5,063,792✔
1024
    } else {
1025
      pVgid->syncState = TAOS_SYNC_STATE_FOLLOWER;
837,094✔
1026
    }
1027

1028
    mInfo("db:%s, vgId:%d, vn:%d is alloced, memory:%" PRId64 ", dnode:%d avail:%" PRId64 " used:%" PRId64,
5,900,886✔
1029
          pVgroup->dbName, pVgroup->vgId, v, vgMem, pVgid->dnodeId, pDnode->memAvail, pDnode->memUsed);
1030
    pDnode->numOfVnodes++;
5,900,886✔
1031
  }
1032

1033
  mndSortVnodeGid(pVgroup);
5,347,122✔
1034
  return 0;
5,347,122✔
1035
}
1036

UNCOV
1037
int32_t mndAllocSmaVgroup(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup) {
×
UNCOV
1038
  int32_t code = 0;
×
1039
  SArray *pArray = mndBuildDnodesArray(pMnode, 0, NULL);
×
1040
  if (pArray == NULL) {
×
1041
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1042
    if (terrno != 0) code = terrno;
×
1043
    TAOS_RETURN(code);
×
1044
  }
1045

UNCOV
1046
  pVgroup->vgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP);
×
UNCOV
1047
  pVgroup->isTsma = 1;
×
1048
  pVgroup->createdTime = taosGetTimestampMs();
×
1049
  pVgroup->updateTime = pVgroup->createdTime;
×
1050
  pVgroup->version = 1;
×
1051
  memcpy(pVgroup->dbName, pDb->name, TSDB_DB_FNAME_LEN);
×
1052
  pVgroup->dbUid = pDb->uid;
×
1053
  pVgroup->replica = 1;
×
1054
  pVgroup->keepVersion = -1;  // default: WAL keep version disabled
×
1055
  pVgroup->keepVersionTime = 0;
×
1056

1057
  if (mndGetAvailableDnode(pMnode, pDb, pVgroup, pArray) != 0) return -1;
×
UNCOV
1058
  taosArrayDestroy(pArray);
×
1059

1060
  mInfo("db:%s, sma vgId:%d is alloced", pDb->name, pVgroup->vgId);
×
UNCOV
1061
  return 0;
×
1062
}
1063

1064
int32_t mndAllocVgroup(SMnode *pMnode, SDbObj *pDb, SVgObj **ppVgroups, SArray *dnodeList) {
2,524,706✔
1065
  int32_t code = -1;
2,524,706✔
1066
  SArray *pArray = NULL;
2,524,706✔
1067
  SVgObj *pVgroups = NULL;
2,524,706✔
1068

1069
  pVgroups = taosMemoryCalloc(pDb->cfg.numOfVgroups, sizeof(SVgObj));
2,524,706✔
1070
  if (pVgroups == NULL) {
2,524,706✔
UNCOV
1071
    code = terrno;
×
UNCOV
1072
    goto _OVER;
×
1073
  }
1074

1075
  pArray = mndBuildDnodesArray(pMnode, 0, dnodeList);
2,524,706✔
1076
  if (pArray == NULL) {
2,524,706✔
UNCOV
1077
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1078
    if (terrno != 0) code = terrno;
×
1079
    goto _OVER;
×
1080
  }
1081

1082
  mInfo("db:%s, total %d dnodes used to create %d vgroups (%d vnodes)", pDb->name, (int32_t)taosArrayGetSize(pArray),
2,524,706✔
1083
        pDb->cfg.numOfVgroups, pDb->cfg.numOfVgroups * pDb->cfg.replications);
1084

1085
  int32_t  allocedVgroups = 0;
2,524,706✔
1086
  int32_t  maxVgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP);
2,524,706✔
1087
  uint32_t hashMin = 0;
2,524,706✔
1088
  uint32_t hashMax = UINT32_MAX;
2,524,706✔
1089
  uint32_t hashInterval = (hashMax - hashMin) / pDb->cfg.numOfVgroups;
2,524,706✔
1090

1091
  if (maxVgId < 2) maxVgId = 2;
2,524,706✔
1092

1093
  for (uint32_t v = 0; v < pDb->cfg.numOfVgroups; v++) {
7,871,828✔
1094
    SVgObj *pVgroup = &pVgroups[v];
5,357,972✔
1095
    pVgroup->vgId = maxVgId++;
5,357,972✔
1096
    pVgroup->createdTime = taosGetTimestampMs();
5,357,972✔
1097
    pVgroup->updateTime = pVgroups->createdTime;
5,357,972✔
1098
    pVgroup->version = 1;
5,357,972✔
1099
    pVgroup->hashBegin = hashMin + hashInterval * v;
5,357,972✔
1100
    if (v == pDb->cfg.numOfVgroups - 1) {
5,357,972✔
1101
      pVgroup->hashEnd = hashMax;
2,519,816✔
1102
    } else {
1103
      pVgroup->hashEnd = hashMin + hashInterval * (v + 1) - 1;
2,838,156✔
1104
    }
1105

1106
    memcpy(pVgroup->dbName, pDb->name, TSDB_DB_FNAME_LEN);
5,357,972✔
1107
    pVgroup->dbUid = pDb->uid;
5,357,972✔
1108
    pVgroup->replica = pDb->cfg.replications;
5,357,972✔
1109
    pVgroup->keepVersion = -1;  // default: WAL keep version disabled
5,357,972✔
1110
    pVgroup->keepVersionTime = 0;
5,357,972✔
1111

1112
    if ((code = mndGetAvailableDnode(pMnode, pDb, pVgroup, pArray)) != 0) {
5,357,972✔
1113
      goto _OVER;
10,850✔
1114
    }
1115

1116
    allocedVgroups++;
5,347,122✔
1117
  }
1118

1119
  *ppVgroups = pVgroups;
2,513,856✔
1120
  code = 0;
2,513,856✔
1121

1122
  mInfo("db:%s, total %d vgroups is alloced, replica:%d", pDb->name, pDb->cfg.numOfVgroups, pDb->cfg.replications);
2,513,856✔
1123

UNCOV
1124
_OVER:
×
1125
  if (code != 0) taosMemoryFree(pVgroups);
2,524,706✔
1126
  taosArrayDestroy(pArray);
2,524,706✔
1127
  TAOS_RETURN(code);
2,524,706✔
1128
}
1129

1130
SEpSet mndGetVgroupEpset(SMnode *pMnode, const SVgObj *pVgroup) {
62,771,776✔
1131
  SEpSet epset = {0};
62,771,776✔
1132

1133
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
139,631,076✔
1134
    const SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
76,859,300✔
1135
    SDnodeObj       *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
76,859,300✔
1136
    if (pDnode == NULL) continue;
76,859,300✔
1137

1138
    if (pVgid->syncState == TAOS_SYNC_STATE_LEADER || pVgid->syncState == TAOS_SYNC_STATE_ASSIGNED_LEADER) {
76,829,700✔
1139
      epset.inUse = epset.numOfEps;
61,888,780✔
1140
    }
1141

1142
    if (addEpIntoEpSet(&epset, pDnode->fqdn, pDnode->port) != 0) {
76,829,700✔
UNCOV
1143
      mWarn("vgId:%d, failed to add ep:%s:%d into epset", pVgroup->vgId, pDnode->fqdn, pDnode->port);
×
1144
    }
1145
    mndReleaseDnode(pMnode, pDnode);
76,829,700✔
1146
  }
1147
  epsetSort(&epset);
62,771,776✔
1148

1149
  return epset;
62,771,776✔
1150
}
1151

1152
SEpSet mndGetVgroupEpsetById(SMnode *pMnode, int32_t vgId) {
1,257,184✔
1153
  SEpSet epset = {0};
1,257,184✔
1154

1155
  SVgObj *pVgroup = mndAcquireVgroup(pMnode, vgId);
1,257,184✔
1156
  if (!pVgroup) return epset;
1,257,184✔
1157

1158
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
2,642,574✔
1159
    const SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
1,385,390✔
1160
    SDnodeObj       *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
1,385,390✔
1161
    if (pDnode == NULL) continue;
1,385,390✔
1162

1163
    if (pVgid->syncState == TAOS_SYNC_STATE_LEADER || pVgid->syncState == TAOS_SYNC_STATE_ASSIGNED_LEADER) {
1,385,390✔
1164
      epset.inUse = epset.numOfEps;
1,198,156✔
1165
    }
1166

1167
    if (addEpIntoEpSet(&epset, pDnode->fqdn, pDnode->port) != 0) {
1,385,390✔
UNCOV
1168
      mWarn("vgId:%d, failed to add ep:%s:%d into epset", pVgroup->vgId, pDnode->fqdn, pDnode->port);
×
1169
    }
1170
    mndReleaseDnode(pMnode, pDnode);
1,385,390✔
1171
  }
1172

1173
  mndReleaseVgroup(pMnode, pVgroup);
1,257,184✔
1174
  return epset;
1,257,184✔
1175
}
1176

1177
static int32_t mndRetrieveVgroups(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
560,178✔
1178
  SMnode   *pMnode = pReq->info.node;
560,178✔
1179
  SSdb     *pSdb = pMnode->pSdb;
560,178✔
1180
  int32_t   numOfRows = 0;
560,178✔
1181
  SVgObj   *pVgroup = NULL;
560,178✔
1182
  SDbObj   *pVgDb = NULL;
560,178✔
1183
  int32_t   cols = 0;
560,178✔
1184
  int64_t   curMs = taosGetTimestampMs();
560,178✔
1185
  int32_t   code = 0, lino = 0;
560,178✔
1186
  SDbObj   *pDb = NULL;
560,178✔
1187
  SUserObj *pUser = NULL;
560,178✔
1188
  SDbObj   *pIterDb = NULL;
560,178✔
1189
  char      objFName[TSDB_OBJ_FNAME_LEN + 1] = {0};
560,178✔
1190
  bool      showAll = false, showIter = false;
560,178✔
1191
  int64_t   dbUid = 0;
560,178✔
1192

1193
  MND_SHOW_CHECK_OBJ_PRIVILEGE_ALL(RPC_MSG_USER(pReq), RPC_MSG_TOKEN(pReq), PRIV_SHOW_VGROUPS, PRIV_OBJ_DB, 0, _OVER);
560,178✔
1194

1195
  if (strlen(pShow->db) > 0) {
560,178✔
1196
    pDb = mndAcquireDb(pMnode, pShow->db);
488,732✔
1197
    if (pDb == NULL) {
488,732✔
UNCOV
1198
      goto _OVER;
×
1199
    }
1200
  }
1201

1202
  while (numOfRows < rows) {
2,938,696✔
1203
    pShow->pIter = sdbFetch(pSdb, SDB_VGROUP, pShow->pIter, (void **)&pVgroup);
2,938,696✔
1204
    if (pShow->pIter == NULL) break;
2,938,696✔
1205

1206
    if (pDb != NULL && pVgroup->dbUid != pDb->uid) {
2,378,518✔
1207
      sdbRelease(pSdb, pVgroup);
699,958✔
1208
      continue;
699,958✔
1209
    }
1210

1211
    MND_SHOW_CHECK_DB_PRIVILEGE(pDb, pVgroup->dbName, pVgroup, RPC_MSG_TOKEN(pReq), MND_OPER_SHOW_VGROUPS, _OVER);
1,678,560✔
1212

1213
    cols = 0;
1,675,648✔
1214
    SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,675,648✔
1215
    COL_DATA_SET_VAL_GOTO((const char *)&pVgroup->vgId, false, pVgroup, pShow->pIter, _OVER);
1,675,648✔
1216

1217
    SName name = {0};
1,675,648✔
1218
    char  db[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
1,675,648✔
1219
    code = tNameFromString(&name, pVgroup->dbName, T_NAME_ACCT | T_NAME_DB);
1,675,648✔
1220
    if (code != 0) {
1,675,648✔
UNCOV
1221
      mError("vgId:%d, failed to set dbName, since %s", pVgroup->vgId, tstrerror(code));
×
UNCOV
1222
      sdbRelease(pSdb, pVgroup);
×
1223
      // sdbCancelFetch(pSdb, pShow->pIter);
1224
      goto _OVER;
×
1225
    }
1226
    (void)tNameGetDbName(&name, varDataVal(db));
1,675,648✔
1227
    varDataSetLen(db, strlen(varDataVal(db)));
1,675,648✔
1228

1229
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,675,648✔
1230
    COL_DATA_SET_VAL_GOTO((const char *)db, false, pVgroup, pShow->pIter, _OVER);
1,675,648✔
1231

1232
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,675,648✔
1233
    COL_DATA_SET_VAL_GOTO((const char *)&pVgroup->numOfTables, false, pVgroup, pShow->pIter, _OVER);
1,675,648✔
1234

1235
    bool isReady = false;
1,675,648✔
1236
    bool isLeaderRestored = false;
1,675,648✔
1237
    bool hasFollowerRestored = false;
1,675,648✔
1238
    ESyncState leaderState = TAOS_SYNC_STATE_OFFLINE;
1,675,648✔
1239
    // default 3 replica, add 1 replica if move vnode
1240
    for (int32_t i = 0; i < 4; ++i) {
8,378,240✔
1241
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
6,702,592✔
1242
      if (i < pVgroup->replica) {
6,702,592✔
1243
        int16_t dnodeId = (int16_t)pVgroup->vnodeGid[i].dnodeId;
3,520,012✔
1244
        COL_DATA_SET_VAL_GOTO((const char *)&dnodeId, false, pVgroup, pShow->pIter, _OVER);
3,520,012✔
1245

1246
        bool       exist = false;
3,520,012✔
1247
        bool       online = false;
3,520,012✔
1248
        SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgroup->vnodeGid[i].dnodeId);
3,520,012✔
1249
        if (pDnode != NULL) {
3,520,012✔
1250
          exist = true;
3,520,012✔
1251
          online = mndIsDnodeOnline(pDnode, curMs);
3,520,012✔
1252
          mndReleaseDnode(pMnode, pDnode);
3,520,012✔
1253
        }
1254

1255
        char buf1[20] = {0};
3,520,012✔
1256
        char role[20] = "offline";
3,520,012✔
1257
        if (!exist) {
3,520,012✔
UNCOV
1258
          tstrncpy(role, "dropping", sizeof(role));
×
1259
        } else if (online) {
3,520,012✔
1260
          if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_LEADER ||
3,468,188✔
1261
              pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_ASSIGNED_LEADER) {
2,202,934✔
1262
            if (pVgroup->vnodeGid[i].syncRestore) {
1,265,254✔
1263
              isLeaderRestored = true;
1,094,492✔
1264
            }
1265
          } else if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_FOLLOWER) {
2,202,934✔
1266
            if (pVgroup->vnodeGid[i].syncRestore) {
1,782,030✔
1267
              hasFollowerRestored = true;
952,206✔
1268
            }
1269
          }
1270
          if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_LEADER ||
3,468,188✔
1271
              pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_ASSIGNED_LEADER)
2,202,934✔
1272
            leaderState = pVgroup->vnodeGid[i].syncState;
1,265,254✔
1273
          snprintf(role, sizeof(role), "%s", syncStr(pVgroup->vnodeGid[i].syncState));
3,468,188✔
1274
        }
1275
        STR_WITH_MAXSIZE_TO_VARSTR(buf1, role, pShow->pMeta->pSchemas[cols].bytes);
3,520,012✔
1276

1277
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
3,520,012✔
1278
        COL_DATA_SET_VAL_GOTO((const char *)buf1, false, pVgroup, pShow->pIter, _OVER);
3,520,012✔
1279

1280
        char applyStr[TSDB_SYNC_APPLY_COMMIT_LEN + 1] = {0};
3,520,012✔
1281
        char buf[TSDB_SYNC_APPLY_COMMIT_LEN + VARSTR_HEADER_SIZE + 1] = {0};
3,520,012✔
1282

1283
        if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_LEARNER &&
3,520,012✔
1284
            (pVgroup->vnodeGid[i].snapSeq > 0 && pVgroup->vnodeGid[i].snapSeq < SYNC_SNAPSHOT_SEQ_END)) {
79,038✔
UNCOV
1285
          if (pDb != NULL) {
×
UNCOV
1286
            mInfo("db:%s, learner progress:%d", pDb->name, pVgroup->vnodeGid[i].learnerProgress);
×
1287
          } else {
1288
            mInfo("db:null, learner progress:%d", pVgroup->vnodeGid[i].learnerProgress);
×
1289
          }
1290

UNCOV
1291
          snprintf(applyStr, sizeof(applyStr), "%" PRId64 "/%" PRId64 "/%" PRId64 "(snap:%d)(learner:%d)",
×
UNCOV
1292
                   pVgroup->vnodeGid[i].syncAppliedIndex, pVgroup->vnodeGid[i].syncCommitIndex,
×
1293
                   pVgroup->vnodeGid[i].syncTotalIndex, pVgroup->vnodeGid[i].snapSeq,
×
1294
                   pVgroup->vnodeGid[i].learnerProgress);
×
1295
        } else if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_LEARNER) {
3,520,012✔
1296
          if (pDb != NULL) {
79,038✔
1297
            mInfo("db:%s, learner progress:%d", pDb->name, pVgroup->vnodeGid[i].learnerProgress);
75,318✔
1298
          } else {
1299
            mInfo("db:null, learner progress:%d", pVgroup->vnodeGid[i].learnerProgress);
3,720✔
1300
          }
1301

1302
          snprintf(applyStr, sizeof(applyStr), "%" PRId64 "/%" PRId64 "/%" PRId64 "(learner:%d)",
316,152✔
1303
                   pVgroup->vnodeGid[i].syncAppliedIndex, pVgroup->vnodeGid[i].syncCommitIndex,
158,076✔
1304
                   pVgroup->vnodeGid[i].syncTotalIndex, pVgroup->vnodeGid[i].learnerProgress);
158,076✔
1305
        } else if (pVgroup->vnodeGid[i].snapSeq > 0 && pVgroup->vnodeGid[i].snapSeq < SYNC_SNAPSHOT_SEQ_END) {
3,440,974✔
1306
          snprintf(applyStr, sizeof(applyStr), "%" PRId64 "/%" PRId64 "(snap:%d)",
2,340✔
1307
                   pVgroup->vnodeGid[i].syncAppliedIndex, pVgroup->vnodeGid[i].syncCommitIndex,
1,560✔
1308
                   pVgroup->vnodeGid[i].snapSeq);
780✔
1309
        } else {
1310
          snprintf(applyStr, sizeof(applyStr), "%" PRId64 "/%" PRId64, pVgroup->vnodeGid[i].syncAppliedIndex,
3,440,194✔
1311
                   pVgroup->vnodeGid[i].syncCommitIndex);
3,440,194✔
1312
        }
1313

1314
        STR_WITH_MAXSIZE_TO_VARSTR(buf, applyStr, pShow->pMeta->pSchemas[cols].bytes);
3,520,012✔
1315

1316
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
3,520,012✔
1317
        COL_DATA_SET_VAL_GOTO((const char *)&buf, false, pVgroup, pShow->pIter, _OVER);
3,520,012✔
1318
      } else {
1319
        colDataSetNULL(pColInfo, numOfRows);
3,182,580✔
1320
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
3,182,580✔
1321
        colDataSetNULL(pColInfo, numOfRows);
3,182,580✔
1322
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
3,182,580✔
1323
        colDataSetNULL(pColInfo, numOfRows);
3,182,580✔
1324
      }
1325
    }
1326

1327
    if (pVgroup->replica >= 3) {
1,675,648✔
1328
      if (isLeaderRestored && hasFollowerRestored) isReady = true;
727,770✔
1329
    } else if (pVgroup->replica == 2) {
947,878✔
1330
      if (leaderState == TAOS_SYNC_STATE_LEADER) {
388,824✔
1331
        if (isLeaderRestored && hasFollowerRestored) isReady = true;
188,216✔
1332
      } else if (leaderState == TAOS_SYNC_STATE_ASSIGNED_LEADER) {
200,608✔
UNCOV
1333
        if (isLeaderRestored) isReady = true;
×
1334
      }
1335
    } else {
1336
      if (isLeaderRestored) isReady = true;
559,054✔
1337
    }
1338
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,675,648✔
1339
    COL_DATA_SET_VAL_GOTO((const char *)&isReady, false, pVgroup, pShow->pIter, _OVER);
1,675,648✔
1340

1341
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,675,648✔
1342
    int64_t cacheUsage = (int64_t)pVgroup->cacheUsage;
1,675,648✔
1343
    COL_DATA_SET_VAL_GOTO((const char *)&cacheUsage, false, pVgroup, pShow->pIter, _OVER);
1,675,648✔
1344

1345
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,675,648✔
1346
    COL_DATA_SET_VAL_GOTO((const char *)&pVgroup->numOfCachedTables, false, pVgroup, pShow->pIter, _OVER);
1,675,648✔
1347

1348
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,675,648✔
1349
    COL_DATA_SET_VAL_GOTO((const char *)&pVgroup->isTsma, false, pVgroup, pShow->pIter, _OVER);
1,675,648✔
1350

1351
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,675,648✔
1352
    COL_DATA_SET_VAL_GOTO((const char *)&pVgroup->mountVgId, false, pVgroup, pShow->pIter, _OVER);
1,675,648✔
1353

1354
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,675,648✔
1355
    COL_DATA_SET_VAL_GOTO((const char *)&pVgroup->keepVersion, false, pVgroup, pShow->pIter, _OVER);
1,675,648✔
1356

1357
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,675,648✔
1358
    COL_DATA_SET_VAL_GOTO((const char *)&pVgroup->keepVersionTime, false, pVgroup, pShow->pIter, _OVER);
1,675,648✔
1359

1360
    numOfRows++;
1,675,648✔
1361
    sdbRelease(pSdb, pVgroup);
1,675,648✔
1362
  }
1363
_OVER:
560,178✔
1364
  if (pUser) mndReleaseUser(pMnode, pUser);
560,178✔
1365
  if (pDb != NULL) {
560,178✔
1366
    mndReleaseDb(pMnode, pDb);
488,732✔
1367
  }
1368
  if (code != 0) {
560,178✔
UNCOV
1369
    mError("failed to retrieve vgroup info at line %d since %s", lino, tstrerror(code));
×
UNCOV
1370
    TAOS_RETURN(code);
×
1371
  }
1372

1373
  pShow->numOfRows += numOfRows;
560,178✔
1374
  return numOfRows;
560,178✔
1375
}
1376

UNCOV
1377
static void mndCancelGetNextVgroup(SMnode *pMnode, void *pIter) {
×
UNCOV
1378
  SSdb *pSdb = pMnode->pSdb;
×
1379
  sdbCancelFetchByType(pSdb, pIter, SDB_VGROUP);
×
1380
}
×
1381

1382
static bool mndGetVnodesNumFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
21,097,006✔
1383
  SVgObj  *pVgroup = pObj;
21,097,006✔
1384
  int32_t  dnodeId = *(int32_t *)p1;
21,097,006✔
1385
  int32_t *pNumOfVnodes = (int32_t *)p2;
21,097,006✔
1386

1387
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
55,795,076✔
1388
    if (pVgroup->vnodeGid[v].dnodeId == dnodeId) {
34,698,070✔
1389
      (*pNumOfVnodes)++;
13,659,198✔
1390
    }
1391
  }
1392

1393
  return true;
21,097,006✔
1394
}
1395

1396
int32_t mndGetVnodesNum(SMnode *pMnode, int32_t dnodeId) {
8,134,554✔
1397
  int32_t numOfVnodes = 0;
8,134,554✔
1398
  sdbTraverse(pMnode->pSdb, SDB_VGROUP, mndGetVnodesNumFp, &dnodeId, &numOfVnodes, NULL);
8,134,554✔
1399
  return numOfVnodes;
8,134,554✔
1400
}
1401

1402
int64_t mndGetVgroupMemory(SMnode *pMnode, SDbObj *pDbInput, SVgObj *pVgroup) {
17,196,848✔
1403
  SDbObj *pDb = pDbInput;
17,196,848✔
1404
  if (pDbInput == NULL) {
17,196,848✔
1405
    pDb = mndAcquireDb(pMnode, pVgroup->dbName);
9,965,406✔
1406
  }
1407

1408
  int64_t vgroupMemroy = 0;
17,196,848✔
1409
  if (pDb != NULL) {
17,196,848✔
1410
    int64_t buffer = (int64_t)pDb->cfg.buffer * 1024 * 1024;
17,196,848✔
1411
    int64_t cache = (int64_t)pDb->cfg.pages * pDb->cfg.pageSize * 1024;
17,196,848✔
1412
    vgroupMemroy = buffer + cache;
17,196,848✔
1413
    int64_t cacheLast = (int64_t)pDb->cfg.cacheLastSize * 1024 * 1024;
17,196,848✔
1414
    if (pDb->cfg.cacheLast > 0) {
17,196,848✔
1415
      vgroupMemroy += cacheLast;
2,125,914✔
1416
    }
1417
    mDebug("db:%s, vgroup:%d, buffer:%" PRId64 " cache:%" PRId64 " cacheLast:%" PRId64, pDb->name, pVgroup->vgId,
17,196,848✔
1418
           buffer, cache, cacheLast);
1419
  }
1420

1421
  if (pDbInput == NULL) {
17,196,848✔
1422
    mndReleaseDb(pMnode, pDb);
9,965,406✔
1423
  }
1424
  return vgroupMemroy;
17,196,848✔
1425
}
1426

1427
static bool mndGetVnodeMemroyFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
13,760,680✔
1428
  SVgObj  *pVgroup = pObj;
13,760,680✔
1429
  int32_t  dnodeId = *(int32_t *)p1;
13,760,680✔
1430
  int64_t *pVnodeMemory = (int64_t *)p2;
13,760,680✔
1431

1432
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
32,083,376✔
1433
    if (pVgroup->vnodeGid[v].dnodeId == dnodeId) {
18,322,696✔
1434
      *pVnodeMemory += mndGetVgroupMemory(pMnode, NULL, pVgroup);
9,655,500✔
1435
    }
1436
  }
1437

1438
  return true;
13,760,680✔
1439
}
1440

1441
int64_t mndGetVnodesMemory(SMnode *pMnode, int32_t dnodeId) {
3,978,586✔
1442
  int64_t vnodeMemory = 0;
3,978,586✔
1443
  sdbTraverse(pMnode->pSdb, SDB_VGROUP, mndGetVnodeMemroyFp, &dnodeId, &vnodeMemory, NULL);
3,978,586✔
1444
  return vnodeMemory;
3,978,586✔
1445
}
1446

1447
void calculateRstoreFinishTime(double rate, int64_t applyCount, char *restoreStr, size_t restoreStrSize) {
7,248✔
1448
  if (rate == 0) {
7,248✔
1449
    snprintf(restoreStr, restoreStrSize, "0:0:0");
7,248✔
1450
    return;
7,248✔
1451
  }
1452

UNCOV
1453
  int64_t costTime = applyCount / rate;
×
UNCOV
1454
  int64_t totalSeconds = costTime / 1000;
×
1455
  int64_t hours = totalSeconds / 3600;
×
1456
  totalSeconds %= 3600;
×
1457
  int64_t minutes = totalSeconds / 60;
×
1458
  int64_t seconds = totalSeconds % 60;
×
1459
  snprintf(restoreStr, restoreStrSize, "%" PRId64 ":%" PRId64 ":%" PRId64, hours, minutes, seconds);
×
1460
}
1461

1462
static int32_t mndRetrieveVnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
111,730✔
1463
  SMnode   *pMnode = pReq->info.node;
111,730✔
1464
  SSdb     *pSdb = pMnode->pSdb;
111,730✔
1465
  int32_t   numOfRows = 0;
111,730✔
1466
  SVgObj   *pVgroup = NULL;
111,730✔
1467
  SDbObj   *pVgDb = NULL;
111,730✔
1468
  int32_t   cols = 0;
111,730✔
1469
  int64_t   curMs = taosGetTimestampMs();
111,730✔
1470
  int32_t   code = 0, lino = 0;
111,730✔
1471
  SUserObj *pUser = NULL;
111,730✔
1472
  SDbObj   *pDb = NULL, *pIterDb = NULL;
111,730✔
1473
  char      objFName[TSDB_OBJ_FNAME_LEN + 1] = {0};
111,730✔
1474
  bool      showAll = false, showIter = false;
111,730✔
1475
  int64_t   dbUid = 0;
111,730✔
1476

1477
  MND_SHOW_CHECK_OBJ_PRIVILEGE_ALL(RPC_MSG_USER(pReq), RPC_MSG_TOKEN(pReq), PRIV_SHOW_VNODES, PRIV_OBJ_DB, 0, _OVER);
111,730✔
1478

1479
  while (numOfRows < rows - TSDB_MAX_REPLICA) {
347,296✔
1480
    pShow->pIter = sdbFetch(pSdb, SDB_VGROUP, pShow->pIter, (void **)&pVgroup);
347,296✔
1481
    if (pShow->pIter == NULL) break;
347,296✔
1482

1483
    MND_SHOW_CHECK_DB_PRIVILEGE(pDb, pVgroup->dbName, pVgroup, RPC_MSG_TOKEN(pReq), MND_OPER_SHOW_VNODES, _OVER);
235,566✔
1484

1485
    for (int32_t i = 0; i < pVgroup->replica && numOfRows < rows; ++i) {
604,710✔
1486
      SVnodeGid       *pGid = &pVgroup->vnodeGid[i];
369,144✔
1487
      SColumnInfoData *pColInfo = NULL;
369,144✔
1488
      cols = 0;
369,144✔
1489

1490
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
369,144✔
1491
      COL_DATA_SET_VAL_GOTO((const char *)&pGid->dnodeId, false, pVgroup, pShow->pIter, _OVER);
369,144✔
1492
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
369,144✔
1493
      COL_DATA_SET_VAL_GOTO((const char *)&pVgroup->vgId, false, pVgroup, pShow->pIter, _OVER);
369,144✔
1494

1495
      // db_name
1496
      const char *dbname = mndGetDbStr(pVgroup->dbName);
369,144✔
1497
      char        b1[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
369,144✔
1498
      if (dbname != NULL) {
369,144✔
1499
        STR_WITH_MAXSIZE_TO_VARSTR(b1, dbname, TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE);
369,144✔
1500
      } else {
UNCOV
1501
        STR_WITH_MAXSIZE_TO_VARSTR(b1, "NULL", TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE);
×
1502
      }
1503
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
369,144✔
1504
      COL_DATA_SET_VAL_GOTO((const char *)b1, false, pVgroup, pShow->pIter, _OVER);
369,144✔
1505

1506
      // dnode is online?
1507
      SDnodeObj *pDnode = mndAcquireDnode(pMnode, pGid->dnodeId);
369,144✔
1508
      if (pDnode == NULL) {
369,144✔
UNCOV
1509
        mError("failed to acquire dnode. dnodeId:%d", pGid->dnodeId);
×
UNCOV
1510
        break;
×
1511
      }
1512
      bool isDnodeOnline = mndIsDnodeOnline(pDnode, curMs);
369,144✔
1513
      sdbRelease(pSdb, pDnode);
369,144✔
1514

1515
      char       buf[20] = {0};
369,144✔
1516
      ESyncState syncState = (isDnodeOnline) ? pGid->syncState : TAOS_SYNC_STATE_OFFLINE;
369,144✔
1517
      STR_TO_VARSTR(buf, syncStr(syncState));
369,144✔
1518
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
369,144✔
1519
      COL_DATA_SET_VAL_GOTO((const char *)buf, false, pVgroup, pShow->pIter, _OVER);
369,144✔
1520

1521
      int64_t roleTimeMs = (isDnodeOnline) ? pGid->roleTimeMs : 0;
369,144✔
1522
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
369,144✔
1523
      COL_DATA_SET_VAL_GOTO((const char *)&roleTimeMs, false, pVgroup, pShow->pIter, _OVER);
369,144✔
1524

1525
      int64_t startTimeMs = (isDnodeOnline) ? pGid->startTimeMs : 0;
369,144✔
1526
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
369,144✔
1527
      COL_DATA_SET_VAL_GOTO((const char *)&startTimeMs, false, pVgroup, pShow->pIter, _OVER);
369,144✔
1528

1529
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
369,144✔
1530
      COL_DATA_SET_VAL_GOTO((const char *)&pGid->syncRestore, false, pVgroup, pShow->pIter, _OVER);
369,144✔
1531

1532
      int64_t unappliedCount = pGid->syncCommitIndex - pGid->syncAppliedIndex;
369,144✔
1533
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
369,144✔
1534
      char restoreStr[20] = {0};
369,144✔
1535
      if (unappliedCount > 0) {
369,144✔
1536
        calculateRstoreFinishTime(pGid->appliedRate, unappliedCount, restoreStr, sizeof(restoreStr));
7,248✔
1537
      }
1538
      STR_TO_VARSTR(buf, restoreStr);
369,144✔
1539
      COL_DATA_SET_VAL_GOTO((const char *)&buf, false, pVgroup, pShow->pIter, _OVER);
369,144✔
1540

1541
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
369,144✔
1542
      COL_DATA_SET_VAL_GOTO((const char *)&unappliedCount, false, pVgroup, pShow->pIter, _OVER);
369,144✔
1543

1544
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
369,144✔
1545
      COL_DATA_SET_VAL_GOTO((const char *)&pGid->bufferSegmentUsed, false, pVgroup, pShow->pIter, _OVER);
369,144✔
1546

1547
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
369,144✔
1548
      COL_DATA_SET_VAL_GOTO((const char *)&pGid->bufferSegmentSize, false, pVgroup, pShow->pIter, _OVER);
369,144✔
1549

1550
      numOfRows++;
369,144✔
1551
    }
1552
    sdbRelease(pSdb, pVgroup);
235,566✔
1553
  }
1554
_OVER:
111,730✔
1555
  if (pUser) mndReleaseUser(pMnode, pUser);
111,730✔
1556
  if (pDb) mndReleaseDb(pMnode, pDb);
111,730✔
1557
  if (code != 0) {
111,730✔
UNCOV
1558
    mError("failed to retrieve vnode info at line %d since %s", lino, tstrerror(code));
×
UNCOV
1559
    return code;
×
1560
  }
1561
  pShow->numOfRows += numOfRows;
111,730✔
1562
  return numOfRows;
111,730✔
1563
}
1564

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

1570
static int32_t mndAddVnodeToVgroup(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup, SArray *pArray) {
175,092✔
1571
  int32_t code = 0;
175,092✔
1572
  taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
175,092✔
1573
  for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
699,682✔
1574
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
524,590✔
1575
    mInfo("trans:%d, dnode:%d, equivalent vnodes:%d others:%d", pTrans->id, pDnode->id, pDnode->numOfVnodes,
524,590✔
1576
          pDnode->numOfOtherNodes);
1577
  }
1578

1579
  SVnodeGid *pVgid = &pVgroup->vnodeGid[pVgroup->replica];
175,092✔
1580
  for (int32_t d = 0; d < taosArrayGetSize(pArray); ++d) {
218,296✔
1581
    SDnodeObj *pDnode = taosArrayGet(pArray, d);
211,484✔
1582

1583
    bool used = false;
211,484✔
1584
    for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
497,596✔
1585
      if (pDnode->id == pVgroup->vnodeGid[vn].dnodeId) {
329,316✔
1586
        used = true;
43,204✔
1587
        break;
43,204✔
1588
      }
1589
    }
1590
    if (used) continue;
211,484✔
1591

1592
    if (pDnode == NULL) {
168,280✔
UNCOV
1593
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_DNODES);
×
1594
    }
1595
    if (pDnode->numOfVnodes >= pDnode->numOfSupportVnodes) {
168,280✔
UNCOV
1596
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_VNODES);
×
1597
    }
1598

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

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

1614
    pVgroup->replica++;
168,280✔
1615
    pDnode->numOfVnodes++;
168,280✔
1616

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

1635
  code = TSDB_CODE_MND_NO_ENOUGH_DNODES;
6,812✔
1636
  mError("trans:%d, db:%s, failed to add vnode to vgId:%d since %s", pTrans->id, pVgroup->dbName, pVgroup->vgId,
6,812✔
1637
         tstrerror(code));
1638
  TAOS_RETURN(code);
6,812✔
1639
}
1640

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

1650
  int32_t code = -1;
35,020✔
1651
  for (int32_t d = taosArrayGetSize(pArray) - 1; d >= 0; --d) {
40,692✔
1652
    SDnodeObj *pDnode = taosArrayGet(pArray, d);
39,512✔
1653

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

1673
_OVER:
1,180✔
1674
  if (code != 0) {
35,020✔
1675
    code = TSDB_CODE_APP_ERROR;
1,180✔
1676
    mError("trans:%d, db:%s, failed to remove vnode from vgId:%d since %s", pTrans->id, pVgroup->dbName, pVgroup->vgId,
1,180✔
1677
           tstrerror(code));
1678
    TAOS_RETURN(code);
1,180✔
1679
  }
1680

1681
  for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
94,770✔
1682
    SVnodeGid *pVgid = &pVgroup->vnodeGid[vn];
60,930✔
1683
    mInfo("trans:%d, db:%s, vgId:%d, vn:%d dnode:%d is reserved", pTrans->id, pVgroup->dbName, pVgroup->vgId, vn,
60,930✔
1684
          pVgid->dnodeId);
1685
  }
1686

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

1703
  TAOS_RETURN(code);
33,840✔
1704
}
1705

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

UNCOV
1714
  int32_t code = -1;
×
UNCOV
1715
  for (int32_t d = taosArrayGetSize(pArray) - 1; d >= 0; --d) {
×
1716
    SDnodeObj *pDnode = taosArrayGet(pArray, d);
×
1717

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

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

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

UNCOV
1748
  TAOS_RETURN(code);
×
1749
}
1750

1751
int32_t mndAddCreateVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, SVnodeGid *pVgid) {
6,208,096✔
1752
  int32_t      code = 0;
6,208,096✔
1753
  STransAction action = {0};
6,208,096✔
1754

1755
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
6,208,096✔
1756
  if (pDnode == NULL) return -1;
6,208,096✔
1757
  action.epSet = mndGetDnodeEpset(pDnode);
6,208,096✔
1758
  mndReleaseDnode(pMnode, pDnode);
6,208,096✔
1759

1760
  int32_t contLen = 0;
6,208,096✔
1761
  void   *pReq = mndBuildCreateVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen);
6,208,096✔
1762
  if (pReq == NULL) return -1;
6,208,096✔
1763

1764
  action.pCont = pReq;
6,208,096✔
1765
  action.contLen = contLen;
6,208,096✔
1766
  action.msgType = TDMT_DND_CREATE_VNODE;
6,208,096✔
1767
  action.acceptableCode = TSDB_CODE_VND_ALREADY_EXIST;
6,208,096✔
1768
  action.groupId = pVgroup->vgId;
6,208,096✔
1769

1770
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
6,208,096✔
UNCOV
1771
    taosMemoryFree(pReq);
×
UNCOV
1772
    TAOS_RETURN(code);
×
1773
  }
1774

1775
  TAOS_RETURN(code);
6,208,096✔
1776
}
1777

1778
int32_t mndRestoreAddCreateVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
4,680✔
1779
                                       SDnodeObj *pDnode) {
1780
  int32_t      code = 0;
4,680✔
1781
  STransAction action = {0};
4,680✔
1782

1783
  action.epSet = mndGetDnodeEpset(pDnode);
4,680✔
1784

1785
  int32_t contLen = 0;
4,680✔
1786
  void   *pReq = mndBuildCreateVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen);
4,680✔
1787
  if (pReq == NULL) {
4,680✔
UNCOV
1788
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1789
    if (terrno != 0) code = terrno;
×
1790
    TAOS_RETURN(code);
×
1791
  }
1792

1793
  action.pCont = pReq;
4,680✔
1794
  action.contLen = contLen;
4,680✔
1795
  action.msgType = TDMT_DND_CREATE_VNODE;
4,680✔
1796
  action.acceptableCode = TSDB_CODE_VND_ALREADY_EXIST;
4,680✔
1797
  action.groupId = pVgroup->vgId;
4,680✔
1798

1799
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
4,680✔
UNCOV
1800
    taosMemoryFree(pReq);
×
UNCOV
1801
    TAOS_RETURN(code);
×
1802
  }
1803

1804
  TAOS_RETURN(code);
4,680✔
1805
}
1806

1807
int32_t mndAddAlterVnodeConfirmAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) {
600,940✔
1808
  int32_t      code = 0;
600,940✔
1809
  STransAction action = {0};
600,940✔
1810
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
600,940✔
1811

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

1819
  pHead->contLen = htonl(contLen);
600,940✔
1820
  pHead->vgId = htonl(pVgroup->vgId);
600,940✔
1821

1822
  action.pCont = pHead;
600,940✔
1823
  action.contLen = contLen;
600,940✔
1824
  action.msgType = TDMT_VND_ALTER_CONFIRM;
600,940✔
1825
  // incorrect redirect result will cause this erro
1826
  action.retryCode = TSDB_CODE_VND_INVALID_VGROUP_ID;
600,940✔
1827
  action.groupId = pVgroup->vgId;
600,940✔
1828

1829
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
600,940✔
UNCOV
1830
    taosMemoryFree(pHead);
×
UNCOV
1831
    TAOS_RETURN(code);
×
1832
  }
1833

1834
  TAOS_RETURN(code);
600,940✔
1835
}
1836

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

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

UNCOV
1851
  int32_t totallen = contLen + sizeof(SMsgHead);
×
1852

1853
  SMsgHead *pHead = taosMemoryMalloc(totallen);
×
UNCOV
1854
  if (pHead == NULL) {
×
1855
    taosMemoryFree(pReq);
×
1856
    TAOS_RETURN(terrno);
×
1857
  }
1858

UNCOV
1859
  pHead->contLen = htonl(totallen);
×
UNCOV
1860
  pHead->vgId = htonl(pNewVgroup->vgId);
×
1861

1862
  memcpy((void *)(pHead + 1), pReq, contLen);
×
UNCOV
1863
  taosMemoryFree(pReq);
×
1864

1865
  action.pCont = pHead;
×
UNCOV
1866
  action.contLen = totallen;
×
1867
  action.msgType = TDMT_SYNC_CONFIG_CHANGE;
×
1868

1869
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
×
UNCOV
1870
    taosMemoryFree(pHead);
×
1871
    TAOS_RETURN(code);
×
1872
  }
1873

UNCOV
1874
  TAOS_RETURN(code);
×
1875
}
1876

1877
static int32_t mndAddAlterVnodeHashRangeAction(SMnode *pMnode, STrans *pTrans, int32_t srcVgId, SVgObj *pVgroup) {
68,016✔
1878
  int32_t      code = 0;
68,016✔
1879
  STransAction action = {0};
68,016✔
1880
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
68,016✔
1881

1882
  int32_t contLen = 0;
68,016✔
1883
  void   *pReq = mndBuildAlterVnodeHashRangeReq(pMnode, srcVgId, pVgroup, &contLen);
68,016✔
1884
  if (pReq == NULL) {
68,016✔
UNCOV
1885
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1886
    if (terrno != 0) code = terrno;
×
1887
    TAOS_RETURN(code);
×
1888
  }
1889

1890
  action.pCont = pReq;
68,016✔
1891
  action.contLen = contLen;
68,016✔
1892
  action.msgType = TDMT_VND_ALTER_HASHRANGE;
68,016✔
1893
  action.acceptableCode = TSDB_CODE_VND_ALREADY_EXIST;
68,016✔
1894

1895
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
68,016✔
UNCOV
1896
    taosMemoryFree(pReq);
×
UNCOV
1897
    TAOS_RETURN(code);
×
1898
  }
1899

1900
  mInfo("trans:%d, add alter vnode hash range action for from vgId:%d to vgId:%d", pTrans->id, srcVgId, pVgroup->vgId);
68,016✔
1901
  TAOS_RETURN(code);
68,016✔
1902
}
1903

1904
int32_t mndAddAlterVnodeConfigAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) {
414,606✔
1905
  int32_t      code = 0;
414,606✔
1906
  STransAction action = {0};
414,606✔
1907
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
414,606✔
1908

1909
  int32_t contLen = 0;
414,606✔
1910
  void   *pReq = mndBuildAlterVnodeConfigReq(pMnode, pDb, pVgroup, &contLen);
414,606✔
1911
  if (pReq == NULL) {
414,606✔
UNCOV
1912
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1913
    if (terrno != 0) code = terrno;
×
1914
    TAOS_RETURN(code);
×
1915
  }
1916

1917
  action.pCont = pReq;
414,606✔
1918
  action.contLen = contLen;
414,606✔
1919
  action.msgType = TDMT_VND_ALTER_CONFIG;
414,606✔
1920
  action.groupId = pVgroup->vgId;
414,606✔
1921

1922
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
414,606✔
UNCOV
1923
    taosMemoryFree(pReq);
×
UNCOV
1924
    TAOS_RETURN(code);
×
1925
  }
1926

1927
  TAOS_RETURN(code);
414,606✔
1928
}
1929

1930
int32_t mndAddNewVgPrepareAction(SMnode *pMnode, STrans *pTrans, SVgObj *pVg) {
5,417,618✔
1931
  int32_t  code = 0;
5,417,618✔
1932
  SSdbRaw *pRaw = mndVgroupActionEncode(pVg);
5,417,618✔
1933
  if (pRaw == NULL) {
5,417,618✔
UNCOV
1934
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1935
    if (terrno != 0) code = terrno;
×
1936
    goto _err;
×
1937
  }
1938

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

UNCOV
1950
_err:
×
UNCOV
1951
  sdbFreeRaw(pRaw);
×
1952
  TAOS_RETURN(code);
×
1953
}
1954

1955
int32_t mndAddAlterVnodeReplicaAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId) {
1,468,344✔
1956
  int32_t    code = 0;
1,468,344✔
1957
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
1,468,344✔
1958
  if (pDnode == NULL) {
1,468,344✔
UNCOV
1959
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1960
    if (terrno != 0) code = terrno;
×
1961
    TAOS_RETURN(code);
×
1962
  }
1963

1964
  STransAction action = {0};
1,468,344✔
1965
  action.epSet = mndGetDnodeEpset(pDnode);
1,468,344✔
1966
  mndReleaseDnode(pMnode, pDnode);
1,468,344✔
1967

1968
  int32_t contLen = 0;
1,468,344✔
1969
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pVgroup, dnodeId, &contLen);
1,468,344✔
1970
  if (pReq == NULL) {
1,468,344✔
UNCOV
1971
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1972
    if (terrno != 0) code = terrno;
×
1973
    TAOS_RETURN(code);
×
1974
  }
1975

1976
  action.pCont = pReq;
1,468,344✔
1977
  action.contLen = contLen;
1,468,344✔
1978
  action.msgType = TDMT_VND_ALTER_REPLICA;
1,468,344✔
1979
  action.groupId = pVgroup->vgId;
1,468,344✔
1980

1981
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
1,468,344✔
UNCOV
1982
    taosMemoryFree(pReq);
×
UNCOV
1983
    TAOS_RETURN(code);
×
1984
  }
1985

1986
  TAOS_RETURN(code);
1,468,344✔
1987
}
1988

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

UNCOV
1998
  STransAction action = {0};
×
UNCOV
1999
  action.epSet = mndGetDnodeEpset(pDnode);
×
2000
  mndReleaseDnode(pMnode, pDnode);
×
2001

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

UNCOV
2010
  action.pCont = pReq;
×
UNCOV
2011
  action.contLen = contLen;
×
2012
  action.msgType = TDMT_DND_CHECK_VNODE_LEARNER_CATCHUP;
×
2013
  action.acceptableCode = TSDB_CODE_VND_ALREADY_IS_VOTER;
×
2014
  action.retryCode = TSDB_CODE_VND_NOT_CATCH_UP;
×
2015

2016
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
×
UNCOV
2017
    taosMemoryFree(pReq);
×
2018
    TAOS_RETURN(code);
×
2019
  }
2020

UNCOV
2021
  TAOS_RETURN(code);
×
2022
}
2023

2024
int32_t mndAddAlterVnodeTypeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId) {
218,084✔
2025
  int32_t    code = 0;
218,084✔
2026
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
218,084✔
2027
  if (pDnode == NULL) {
218,084✔
UNCOV
2028
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2029
    if (terrno != 0) code = terrno;
×
2030
    TAOS_RETURN(code);
×
2031
  }
2032

2033
  STransAction action = {0};
218,084✔
2034
  action.epSet = mndGetDnodeEpset(pDnode);
218,084✔
2035
  mndReleaseDnode(pMnode, pDnode);
218,084✔
2036

2037
  int32_t contLen = 0;
218,084✔
2038
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pVgroup, dnodeId, &contLen);
218,084✔
2039
  if (pReq == NULL) {
218,084✔
UNCOV
2040
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2041
    if (terrno != 0) code = terrno;
×
2042
    TAOS_RETURN(code);
×
2043
  }
2044

2045
  action.pCont = pReq;
218,084✔
2046
  action.contLen = contLen;
218,084✔
2047
  action.msgType = TDMT_DND_ALTER_VNODE_TYPE;
218,084✔
2048
  action.acceptableCode = TSDB_CODE_VND_ALREADY_IS_VOTER;
218,084✔
2049
  action.retryCode = TSDB_CODE_VND_NOT_CATCH_UP;
218,084✔
2050
  action.groupId = pVgroup->vgId;
218,084✔
2051

2052
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
218,084✔
UNCOV
2053
    taosMemoryFree(pReq);
×
UNCOV
2054
    TAOS_RETURN(code);
×
2055
  }
2056

2057
  TAOS_RETURN(code);
218,084✔
2058
}
2059

2060
int32_t mndRestoreAddAlterVnodeTypeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
4,680✔
2061
                                          SDnodeObj *pDnode) {
2062
  int32_t      code = 0;
4,680✔
2063
  STransAction action = {0};
4,680✔
2064
  action.epSet = mndGetDnodeEpset(pDnode);
4,680✔
2065

2066
  int32_t contLen = 0;
4,680✔
2067
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pVgroup, pDnode->id, &contLen);
4,680✔
2068
  if (pReq == NULL) {
4,680✔
UNCOV
2069
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2070
    if (terrno != 0) code = terrno;
×
2071
    TAOS_RETURN(code);
×
2072
  }
2073

2074
  action.pCont = pReq;
4,680✔
2075
  action.contLen = contLen;
4,680✔
2076
  action.msgType = TDMT_DND_ALTER_VNODE_TYPE;
4,680✔
2077
  action.acceptableCode = TSDB_CODE_VND_ALREADY_IS_VOTER;
4,680✔
2078
  action.retryCode = TSDB_CODE_VND_NOT_CATCH_UP;
4,680✔
2079
  action.groupId = pVgroup->vgId;
4,680✔
2080

2081
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
4,680✔
UNCOV
2082
    taosMemoryFree(pReq);
×
UNCOV
2083
    TAOS_RETURN(code);
×
2084
  }
2085

2086
  TAOS_RETURN(code);
4,680✔
2087
}
2088

2089
static int32_t mndAddDisableVnodeWriteAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
68,016✔
2090
                                             int32_t dnodeId) {
2091
  int32_t    code = 0;
68,016✔
2092
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
68,016✔
2093
  if (pDnode == NULL) {
68,016✔
UNCOV
2094
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2095
    if (terrno != 0) code = terrno;
×
2096
    TAOS_RETURN(code);
×
2097
  }
2098

2099
  STransAction action = {0};
68,016✔
2100
  action.epSet = mndGetDnodeEpset(pDnode);
68,016✔
2101
  mndReleaseDnode(pMnode, pDnode);
68,016✔
2102

2103
  int32_t contLen = 0;
68,016✔
2104
  void   *pReq = mndBuildDisableVnodeWriteReq(pMnode, pDb, pVgroup->vgId, &contLen);
68,016✔
2105
  if (pReq == NULL) {
68,016✔
UNCOV
2106
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2107
    if (terrno != 0) code = terrno;
×
2108
    TAOS_RETURN(code);
×
2109
  }
2110

2111
  action.pCont = pReq;
68,016✔
2112
  action.contLen = contLen;
68,016✔
2113
  action.msgType = TDMT_VND_DISABLE_WRITE;
68,016✔
2114

2115
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
68,016✔
UNCOV
2116
    taosMemoryFree(pReq);
×
UNCOV
2117
    TAOS_RETURN(code);
×
2118
  }
2119

2120
  TAOS_RETURN(code);
68,016✔
2121
}
2122

2123
int32_t mndAddDropVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, SVnodeGid *pVgid,
9,159,916✔
2124
                              bool isRedo) {
2125
  int32_t      code = 0;
9,159,916✔
2126
  STransAction action = {0};
9,159,916✔
2127

2128
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
9,159,916✔
2129
  if (pDnode == NULL) {
9,159,916✔
UNCOV
2130
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2131
    if (terrno != 0) code = terrno;
×
2132
    TAOS_RETURN(code);
×
2133
  }
2134
  action.epSet = mndGetDnodeEpset(pDnode);
9,159,916✔
2135
  mndReleaseDnode(pMnode, pDnode);
9,159,916✔
2136

2137
  int32_t contLen = 0;
9,159,916✔
2138
  void   *pReq = mndBuildDropVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen);
9,159,916✔
2139
  if (pReq == NULL) {
9,159,916✔
UNCOV
2140
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2141
    if (terrno != 0) code = terrno;
×
2142
    TAOS_RETURN(code);
×
2143
  }
2144

2145
  action.pCont = pReq;
9,159,916✔
2146
  action.contLen = contLen;
9,159,916✔
2147
  action.msgType = TDMT_DND_DROP_VNODE;
9,159,916✔
2148
  action.acceptableCode = TSDB_CODE_VND_NOT_EXIST;
9,159,916✔
2149
  action.groupId = pVgroup->vgId;
9,159,916✔
2150

2151
  if (isRedo) {
9,159,916✔
2152
    if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
3,259,030✔
UNCOV
2153
      taosMemoryFree(pReq);
×
UNCOV
2154
      TAOS_RETURN(code);
×
2155
    }
2156
  } else {
2157
    if ((code = mndTransAppendUndoAction(pTrans, &action)) != 0) {
5,900,886✔
UNCOV
2158
      taosMemoryFree(pReq);
×
UNCOV
2159
      TAOS_RETURN(code);
×
2160
    }
2161
  }
2162

2163
  TAOS_RETURN(code);
9,159,916✔
2164
}
2165

2166
int32_t mndSetMoveVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t vnIndex,
30,452✔
2167
                                    SArray *pArray, bool force, bool unsafe) {
2168
  int32_t code = 0;
30,452✔
2169
  SVgObj  newVg = {0};
30,452✔
2170
  memcpy(&newVg, pVgroup, sizeof(SVgObj));
30,452✔
2171

2172
  mInfo("vgId:%d, trans:%d, vgroup info before move, replica:%d", newVg.vgId, pTrans->id, newVg.replica);
30,452✔
2173
  for (int32_t i = 0; i < newVg.replica; ++i) {
98,232✔
2174
    mInfo("vgId:%d, trans:%d, vnode:%d dnode:%d", newVg.vgId, pTrans->id, i, newVg.vnodeGid[i].dnodeId);
67,780✔
2175
  }
2176

2177
  if (!force) {
30,452✔
2178
#if 1
2179
    {
2180
#else
2181
    if (newVg.replica == 1) {
2182
#endif
2183
      mInfo("vgId:%d, trans:%d, will add 1 vnode, replca:%d", pVgroup->vgId, pTrans->id, newVg.replica);
30,452✔
2184
      TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVg, pArray));
30,452✔
2185
      for (int32_t i = 0; i < newVg.replica - 1; ++i) {
98,232✔
2186
        TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg, newVg.vnodeGid[i].dnodeId));
67,780✔
2187
      }
2188
      TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg, &newVg.vnodeGid[newVg.replica - 1]));
30,452✔
2189
      TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg));
30,452✔
2190

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

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

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

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

2281
    if (newVg.replica == 1) {
×
UNCOV
2282
      if (force && !unsafe) {
×
2283
        TAOS_RETURN(TSDB_CODE_VND_META_DATA_UNSAFE_DELETE);
×
2284
      }
2285

UNCOV
2286
      SSdb *pSdb = pMnode->pSdb;
×
UNCOV
2287
      void *pIter = NULL;
×
2288

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

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

UNCOV
2302
        sdbRelease(pSdb, pStb);
×
2303
      }
2304

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

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

2327
  mInfo("vgId:%d, vgroup info after move, replica:%d", newVg.vgId, newVg.replica);
30,452✔
2328
  for (int32_t i = 0; i < newVg.replica; ++i) {
98,232✔
2329
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
67,780✔
2330
  }
2331
  TAOS_RETURN(code);
30,452✔
2332
}
2333

2334
int32_t mndSetMoveVgroupsInfoToTrans(SMnode *pMnode, STrans *pTrans, int32_t delDnodeId, bool force, bool unsafe) {
15,232✔
2335
  int32_t code = 0;
15,232✔
2336
  SArray *pArray = mndBuildDnodesArray(pMnode, delDnodeId, NULL);
15,232✔
2337
  if (pArray == NULL) {
15,232✔
UNCOV
2338
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2339
    if (terrno != 0) code = terrno;
×
2340
    TAOS_RETURN(code);
×
2341
  }
2342

2343
  void *pIter = NULL;
15,232✔
2344
  while (1) {
45,342✔
2345
    SVgObj *pVgroup = NULL;
60,574✔
2346
    pIter = sdbFetch(pMnode->pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
60,574✔
2347
    if (pIter == NULL) break;
60,574✔
2348

2349
    int32_t vnIndex = -1;
45,342✔
2350
    for (int32_t i = 0; i < pVgroup->replica; ++i) {
90,498✔
2351
      if (pVgroup->vnodeGid[i].dnodeId == delDnodeId) {
75,608✔
2352
        vnIndex = i;
30,452✔
2353
        break;
30,452✔
2354
      }
2355
    }
2356

2357
    code = 0;
45,342✔
2358
    if (vnIndex != -1) {
45,342✔
2359
      mInfo("vgId:%d, trans:%d, vnode:%d will be removed from dnode:%d, force:%d", pVgroup->vgId, pTrans->id, vnIndex,
30,452✔
2360
            delDnodeId, force);
2361
      SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName);
30,452✔
2362
      code = mndSetMoveVgroupInfoToTrans(pMnode, pTrans, pDb, pVgroup, vnIndex, pArray, force, unsafe);
30,452✔
2363
      mndReleaseDb(pMnode, pDb);
30,452✔
2364
    }
2365

2366
    sdbRelease(pMnode->pSdb, pVgroup);
45,342✔
2367

2368
    if (code != 0) {
45,342✔
UNCOV
2369
      sdbCancelFetch(pMnode->pSdb, pIter);
×
UNCOV
2370
      break;
×
2371
    }
2372
  }
2373

2374
  taosArrayDestroy(pArray);
15,232✔
2375
  TAOS_RETURN(code);
15,232✔
2376
}
2377

2378
static int32_t mndAddIncVgroupReplicaToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
138,930✔
2379
                                             int32_t newDnodeId) {
2380
  int32_t code = 0;
138,930✔
2381
  mInfo("vgId:%d, will add 1 vnode, replica:%d dnode:%d", pVgroup->vgId, pVgroup->replica, newDnodeId);
138,930✔
2382

2383
  // assoc dnode
2384
  SVnodeGid *pGid = &pVgroup->vnodeGid[pVgroup->replica];
138,930✔
2385
  pVgroup->replica++;
138,930✔
2386
  pGid->dnodeId = newDnodeId;
138,930✔
2387
  pGid->syncState = TAOS_SYNC_STATE_OFFLINE;
138,930✔
2388
  pGid->nodeRole = TAOS_SYNC_ROLE_LEARNER;
138,930✔
2389

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

2406
  // learner
2407
  for (int32_t i = 0; i < pVgroup->replica - 1; ++i) {
470,996✔
2408
    TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, pVgroup, pVgroup->vnodeGid[i].dnodeId));
332,066✔
2409
  }
2410
  TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pDb, pVgroup, pGid));
138,930✔
2411

2412
  // voter
2413
  pGid->nodeRole = TAOS_SYNC_ROLE_VOTER;
138,930✔
2414
  TAOS_CHECK_RETURN(mndAddAlterVnodeTypeAction(pMnode, pTrans, pDb, pVgroup, pGid->dnodeId));
138,930✔
2415
  for (int32_t i = 0; i < pVgroup->replica - 1; ++i) {
470,996✔
2416
    TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, pVgroup, pVgroup->vnodeGid[i].dnodeId));
332,066✔
2417
  }
2418

2419
  // confirm
2420
  TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, pVgroup));
138,930✔
2421

2422
  TAOS_RETURN(code);
138,930✔
2423
}
2424

2425
static int32_t mndAddDecVgroupReplicaFromTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
138,930✔
2426
                                               int32_t delDnodeId) {
2427
  int32_t code = 0;
138,930✔
2428
  mInfo("vgId:%d, will remove 1 vnode, replica:%d dnode:%d", pVgroup->vgId, pVgroup->replica, delDnodeId);
138,930✔
2429

2430
  SVnodeGid *pGid = NULL;
138,930✔
2431
  SVnodeGid  delGid = {0};
138,930✔
2432
  for (int32_t i = 0; i < pVgroup->replica; ++i) {
236,628✔
2433
    if (pVgroup->vnodeGid[i].dnodeId == delDnodeId) {
236,628✔
2434
      pGid = &pVgroup->vnodeGid[i];
138,930✔
2435
      break;
138,930✔
2436
    }
2437
  }
2438

2439
  if (pGid == NULL) return 0;
138,930✔
2440

2441
  pVgroup->replica--;
138,930✔
2442
  memcpy(&delGid, pGid, sizeof(SVnodeGid));
138,930✔
2443
  memcpy(pGid, &pVgroup->vnodeGid[pVgroup->replica], sizeof(SVnodeGid));
138,930✔
2444
  memset(&pVgroup->vnodeGid[pVgroup->replica], 0, sizeof(SVnodeGid));
138,930✔
2445

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

2462
  TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pDb, pVgroup, &delGid, true));
138,930✔
2463
  for (int32_t i = 0; i < pVgroup->replica; ++i) {
470,996✔
2464
    TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, pVgroup, pVgroup->vnodeGid[i].dnodeId));
332,066✔
2465
  }
2466
  TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, pVgroup));
138,930✔
2467

2468
  TAOS_RETURN(code);
138,930✔
2469
}
2470

2471
static int32_t mndRedistributeVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SVgObj *pVgroup, SDnodeObj *pNew1,
77,452✔
2472
                                     SDnodeObj *pOld1, SDnodeObj *pNew2, SDnodeObj *pOld2, SDnodeObj *pNew3,
2473
                                     SDnodeObj *pOld3) {
2474
  int32_t code = -1;
77,452✔
2475
  STrans *pTrans = NULL;
77,452✔
2476

2477
  pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_GLOBAL, pReq, "red-vgroup");
77,452✔
2478
  if (pTrans == NULL) {
77,452✔
UNCOV
2479
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2480
    if (terrno != 0) code = terrno;
×
2481
    goto _OVER;
×
2482
  }
2483

2484
  mndTransSetDbName(pTrans, pVgroup->dbName, NULL);
77,452✔
2485
  TAOS_CHECK_GOTO(mndTransCheckConflictWithCompact(pMnode, pTrans), NULL, _OVER);
77,452✔
2486
  TAOS_CHECK_GOTO(mndTransCheckConflictWithRetention(pMnode, pTrans), NULL, _OVER);
77,288✔
2487

2488
  mndTransSetSerial(pTrans);
77,288✔
2489
  mInfo("trans:%d, used to redistribute vgroup, vgId:%d", pTrans->id, pVgroup->vgId);
77,288✔
2490

2491
  SVgObj newVg = {0};
77,288✔
2492
  memcpy(&newVg, pVgroup, sizeof(SVgObj));
77,288✔
2493
  mInfo("vgId:%d, vgroup info before redistribute, replica:%d", newVg.vgId, newVg.replica);
77,288✔
2494
  for (int32_t i = 0; i < newVg.replica; ++i) {
260,428✔
2495
    mInfo("vgId:%d, vnode:%d dnode:%d role:%s", newVg.vgId, i, newVg.vnodeGid[i].dnodeId,
183,140✔
2496
          syncStr(newVg.vnodeGid[i].syncState));
2497
  }
2498

2499
  if (pNew1 != NULL && pOld1 != NULL) {
77,288✔
2500
    int32_t numOfVnodes = mndGetVnodesNum(pMnode, pNew1->id);
77,288✔
2501
    if (numOfVnodes >= pNew1->numOfSupportVnodes) {
77,288✔
2502
      mError("vgId:%d, no enough vnodes in dnode:%d, numOfVnodes:%d support:%d", newVg.vgId, pNew1->id, numOfVnodes,
1,438✔
2503
             pNew1->numOfSupportVnodes);
2504
      code = TSDB_CODE_MND_NO_ENOUGH_VNODES;
1,438✔
2505
      goto _OVER;
1,438✔
2506
    }
2507

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

2518
    TAOS_CHECK_GOTO(mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pNew1->id), NULL, _OVER);
75,850✔
2519
    TAOS_CHECK_GOTO(mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pOld1->id), NULL, _OVER);
75,850✔
2520
  }
2521

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

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

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

2582
  mInfo("vgId:%d, vgroup info after redistribute, replica:%d", newVg.vgId, newVg.replica);
75,850✔
2583
  for (int32_t i = 0; i < newVg.replica; ++i) {
254,676✔
2584
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
178,826✔
2585
  }
2586

2587
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
75,850✔
2588
  code = 0;
74,210✔
2589

2590
_OVER:
77,452✔
2591
  mndTransDrop(pTrans);
77,452✔
2592
  mndReleaseDb(pMnode, pDb);
77,452✔
2593
  TAOS_RETURN(code);
77,452✔
2594
}
2595

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

2614
  SRedistributeVgroupReq req = {0};
95,140✔
2615
  if (tDeserializeSRedistributeVgroupReq(pReq->pCont, pReq->contLen, &req) != 0) {
95,140✔
UNCOV
2616
    code = TSDB_CODE_INVALID_MSG;
×
UNCOV
2617
    goto _OVER;
×
2618
  }
2619

2620
  mInfo("vgId:%d, start to redistribute vgroup to dnode %d:%d:%d", req.vgId, req.dnodeId1, req.dnodeId2, req.dnodeId3);
95,140✔
2621
  if ((code = mndCheckOperPrivilege(pMnode, RPC_MSG_USER(pReq), RPC_MSG_TOKEN(pReq), MND_OPER_REDISTRIBUTE_VGROUP)) != 0) {
95,140✔
UNCOV
2622
    goto _OVER;
×
2623
  }
2624

2625
  pVgroup = mndAcquireVgroup(pMnode, req.vgId);
95,140✔
2626
  if (pVgroup == NULL) {
95,140✔
2627
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
4,314✔
2628
    if (terrno != 0) code = terrno;
4,314✔
2629
    goto _OVER;
4,314✔
2630
  }
2631
  if (pVgroup->mountVgId) {
90,826✔
UNCOV
2632
    code = TSDB_CODE_MND_MOUNT_OBJ_NOT_SUPPORT;
×
UNCOV
2633
    goto _OVER;
×
2634
  }
2635
  pDb = mndAcquireDb(pMnode, pVgroup->dbName);
90,826✔
2636
  if (pDb == NULL) {
90,826✔
UNCOV
2637
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2638
    if (terrno != 0) code = terrno;
×
2639
    goto _OVER;
×
2640
  }
2641

2642
  if (pVgroup->replica == 1) {
90,826✔
2643
    if (req.dnodeId1 <= 0 || req.dnodeId2 > 0 || req.dnodeId3 > 0) {
23,070✔
UNCOV
2644
      code = TSDB_CODE_MND_INVALID_REPLICA;
×
UNCOV
2645
      goto _OVER;
×
2646
    }
2647

2648
    if (req.dnodeId1 == pVgroup->vnodeGid[0].dnodeId) {
23,070✔
2649
      // terrno = TSDB_CODE_MND_VGROUP_UN_CHANGED;
UNCOV
2650
      code = 0;
×
UNCOV
2651
      goto _OVER;
×
2652
    }
2653

2654
    pNew1 = mndAcquireDnode(pMnode, req.dnodeId1);
23,070✔
2655
    if (pNew1 == NULL) {
23,070✔
UNCOV
2656
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2657
      if (terrno != 0) code = terrno;
×
2658
      goto _OVER;
×
2659
    }
2660
    if (!mndIsDnodeOnline(pNew1, curMs)) {
23,070✔
UNCOV
2661
      code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2662
      goto _OVER;
×
2663
    }
2664

2665
    pOld1 = mndAcquireDnode(pMnode, pVgroup->vnodeGid[0].dnodeId);
23,070✔
2666
    if (pOld1 == NULL) {
23,070✔
UNCOV
2667
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2668
      if (terrno != 0) code = terrno;
×
2669
      goto _OVER;
×
2670
    }
2671
    if (!mndIsDnodeOnline(pOld1, curMs)) {
23,070✔
UNCOV
2672
      code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2673
      goto _OVER;
×
2674
    }
2675

2676
    code = mndRedistributeVgroup(pMnode, pReq, pDb, pVgroup, pNew1, pOld1, NULL, NULL, NULL, NULL);
23,070✔
2677

2678
  } else if (pVgroup->replica == 3) {
67,756✔
2679
    if (req.dnodeId1 <= 0 || req.dnodeId2 <= 0 || req.dnodeId3 <= 0) {
64,844✔
2680
      code = TSDB_CODE_MND_INVALID_REPLICA;
5,752✔
2681
      goto _OVER;
5,752✔
2682
    }
2683

2684
    if (req.dnodeId1 == req.dnodeId2 || req.dnodeId1 == req.dnodeId3 || req.dnodeId2 == req.dnodeId3) {
59,092✔
2685
      code = TSDB_CODE_MND_INVALID_REPLICA;
1,438✔
2686
      goto _OVER;
1,438✔
2687
    }
2688

2689
    if (req.dnodeId1 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId1 != pVgroup->vnodeGid[1].dnodeId &&
57,654✔
2690
        req.dnodeId1 != pVgroup->vnodeGid[2].dnodeId) {
27,616✔
2691
      newDnodeId[++newIndex] = req.dnodeId1;
24,768✔
2692
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
24,768✔
2693
    }
2694

2695
    if (req.dnodeId2 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[1].dnodeId &&
57,654✔
2696
        req.dnodeId2 != pVgroup->vnodeGid[2].dnodeId) {
38,642✔
2697
      newDnodeId[++newIndex] = req.dnodeId2;
28,678✔
2698
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
28,678✔
2699
    }
2700

2701
    if (req.dnodeId3 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId3 != pVgroup->vnodeGid[1].dnodeId &&
57,654✔
2702
        req.dnodeId3 != pVgroup->vnodeGid[2].dnodeId) {
46,294✔
2703
      newDnodeId[++newIndex] = req.dnodeId3;
37,336✔
2704
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
37,336✔
2705
    }
2706

2707
    if (req.dnodeId1 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[0].dnodeId &&
57,654✔
2708
        req.dnodeId3 != pVgroup->vnodeGid[0].dnodeId) {
37,450✔
2709
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[0].dnodeId;
33,232✔
2710
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
33,232✔
2711
    }
2712

2713
    if (req.dnodeId1 != pVgroup->vnodeGid[1].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[1].dnodeId &&
57,654✔
2714
        req.dnodeId3 != pVgroup->vnodeGid[1].dnodeId) {
28,808✔
2715
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[1].dnodeId;
21,666✔
2716
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
21,666✔
2717
    }
2718

2719
    if (req.dnodeId1 != pVgroup->vnodeGid[2].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[2].dnodeId &&
57,654✔
2720
        req.dnodeId3 != pVgroup->vnodeGid[2].dnodeId) {
44,842✔
2721
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[2].dnodeId;
35,884✔
2722
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
35,884✔
2723
    }
2724

2725
    if (newDnodeId[0] != 0) {
57,654✔
2726
      pNew1 = mndAcquireDnode(pMnode, newDnodeId[0]);
55,858✔
2727
      if (pNew1 == NULL) {
55,858✔
UNCOV
2728
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2729
        if (terrno != 0) code = terrno;
×
2730
        goto _OVER;
×
2731
      }
2732
      if (!mndIsDnodeOnline(pNew1, curMs)) {
55,858✔
2733
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
2,032✔
2734
        goto _OVER;
2,032✔
2735
      }
2736
    }
2737

2738
    if (newDnodeId[1] != 0) {
55,622✔
2739
      pNew2 = mndAcquireDnode(pMnode, newDnodeId[1]);
22,292✔
2740
      if (pNew2 == NULL) {
22,292✔
UNCOV
2741
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2742
        if (terrno != 0) code = terrno;
×
2743
        goto _OVER;
×
2744
      }
2745
      if (!mndIsDnodeOnline(pNew2, curMs)) {
22,292✔
UNCOV
2746
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2747
        goto _OVER;
×
2748
      }
2749
    }
2750

2751
    if (newDnodeId[2] != 0) {
55,622✔
2752
      pNew3 = mndAcquireDnode(pMnode, newDnodeId[2]);
11,444✔
2753
      if (pNew3 == NULL) {
11,444✔
UNCOV
2754
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2755
        if (terrno != 0) code = terrno;
×
2756
        goto _OVER;
×
2757
      }
2758
      if (!mndIsDnodeOnline(pNew3, curMs)) {
11,444✔
UNCOV
2759
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2760
        goto _OVER;
×
2761
      }
2762
    }
2763

2764
    if (oldDnodeId[0] != 0) {
55,622✔
2765
      pOld1 = mndAcquireDnode(pMnode, oldDnodeId[0]);
53,826✔
2766
      if (pOld1 == NULL) {
53,826✔
UNCOV
2767
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2768
        if (terrno != 0) code = terrno;
×
2769
        goto _OVER;
×
2770
      }
2771
      if (!mndIsDnodeOnline(pOld1, curMs)) {
53,826✔
2772
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
2,356✔
2773
        goto _OVER;
2,356✔
2774
      }
2775
    }
2776

2777
    if (oldDnodeId[1] != 0) {
53,266✔
2778
      pOld2 = mndAcquireDnode(pMnode, oldDnodeId[1]);
19,936✔
2779
      if (pOld2 == NULL) {
19,936✔
UNCOV
2780
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2781
        if (terrno != 0) code = terrno;
×
2782
        goto _OVER;
×
2783
      }
2784
      if (!mndIsDnodeOnline(pOld2, curMs)) {
19,936✔
UNCOV
2785
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2786
        goto _OVER;
×
2787
      }
2788
    }
2789

2790
    if (oldDnodeId[2] != 0) {
53,266✔
2791
      pOld3 = mndAcquireDnode(pMnode, oldDnodeId[2]);
9,088✔
2792
      if (pOld3 == NULL) {
9,088✔
UNCOV
2793
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2794
        if (terrno != 0) code = terrno;
×
2795
        goto _OVER;
×
2796
      }
2797
      if (!mndIsDnodeOnline(pOld3, curMs)) {
9,088✔
UNCOV
2798
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2799
        goto _OVER;
×
2800
      }
2801
    }
2802

2803
    if (pNew1 == NULL && pOld1 == NULL && pNew2 == NULL && pOld2 == NULL && pNew3 == NULL && pOld3 == NULL) {
53,266✔
2804
      // terrno = TSDB_CODE_MND_VGROUP_UN_CHANGED;
2805
      code = 0;
1,796✔
2806
      goto _OVER;
1,796✔
2807
    }
2808

2809
    code = mndRedistributeVgroup(pMnode, pReq, pDb, pVgroup, pNew1, pOld1, pNew2, pOld2, pNew3, pOld3);
51,470✔
2810

2811
  } else if (pVgroup->replica == 2) {
2,912✔
2812
    if (req.dnodeId1 <= 0 || req.dnodeId2 <= 0) {
2,912✔
UNCOV
2813
      code = TSDB_CODE_MND_INVALID_REPLICA;
×
UNCOV
2814
      goto _OVER;
×
2815
    }
2816

2817
    if (req.dnodeId1 == req.dnodeId2) {
2,912✔
UNCOV
2818
      code = TSDB_CODE_MND_INVALID_REPLICA;
×
UNCOV
2819
      goto _OVER;
×
2820
    }
2821

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

2827
    if (req.dnodeId2 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[1].dnodeId) {
2,912✔
2828
      newDnodeId[++newIndex] = req.dnodeId2;
2,912✔
2829
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
2,912✔
2830
    }
2831

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

2837
    if (req.dnodeId1 != pVgroup->vnodeGid[1].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[1].dnodeId) {
2,912✔
2838
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[1].dnodeId;
2,912✔
2839
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
2,912✔
2840
    }
2841

2842
    if (newDnodeId[0] != 0) {
2,912✔
2843
      pNew1 = mndAcquireDnode(pMnode, newDnodeId[0]);
2,912✔
2844
      if (pNew1 == NULL) {
2,912✔
UNCOV
2845
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2846
        if (terrno != 0) code = terrno;
×
2847
        goto _OVER;
×
2848
      }
2849
      if (!mndIsDnodeOnline(pNew1, curMs)) {
2,912✔
UNCOV
2850
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2851
        goto _OVER;
×
2852
      }
2853
    }
2854

2855
    if (newDnodeId[1] != 0) {
2,912✔
2856
      pNew2 = mndAcquireDnode(pMnode, newDnodeId[1]);
2,912✔
2857
      if (pNew2 == NULL) {
2,912✔
UNCOV
2858
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2859
        if (terrno != 0) code = terrno;
×
2860
        goto _OVER;
×
2861
      }
2862
      if (!mndIsDnodeOnline(pNew2, curMs)) {
2,912✔
UNCOV
2863
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2864
        goto _OVER;
×
2865
      }
2866
    }
2867

2868
    if (oldDnodeId[0] != 0) {
2,912✔
2869
      pOld1 = mndAcquireDnode(pMnode, oldDnodeId[0]);
2,912✔
2870
      if (pOld1 == NULL) {
2,912✔
UNCOV
2871
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2872
        if (terrno != 0) code = terrno;
×
2873
        goto _OVER;
×
2874
      }
2875
      if (!mndIsDnodeOnline(pOld1, curMs)) {
2,912✔
UNCOV
2876
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2877
        goto _OVER;
×
2878
      }
2879
    }
2880

2881
    if (oldDnodeId[1] != 0) {
2,912✔
2882
      pOld2 = mndAcquireDnode(pMnode, oldDnodeId[1]);
2,912✔
2883
      if (pOld2 == NULL) {
2,912✔
UNCOV
2884
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2885
        if (terrno != 0) code = terrno;
×
2886
        goto _OVER;
×
2887
      }
2888
      if (!mndIsDnodeOnline(pOld2, curMs)) {
2,912✔
UNCOV
2889
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
UNCOV
2890
        goto _OVER;
×
2891
      }
2892
    }
2893

2894
    if (pNew1 == NULL && pOld1 == NULL && pNew2 == NULL && pOld2 == NULL) {
2,912✔
2895
      // terrno = TSDB_CODE_MND_VGROUP_UN_CHANGED;
UNCOV
2896
      code = 0;
×
UNCOV
2897
      goto _OVER;
×
2898
    }
2899

2900
    code = mndRedistributeVgroup(pMnode, pReq, pDb, pVgroup, pNew1, pOld1, pNew2, pOld2, NULL, NULL);
2,912✔
2901
  } else {
UNCOV
2902
    code = TSDB_CODE_MND_REQ_REJECTED;
×
UNCOV
2903
    goto _OVER;
×
2904
  }
2905

2906
  if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
77,452✔
2907

2908
  if (tsAuditLevel >= AUDIT_LEVEL_CLUSTER) {
77,452✔
2909
    char obj[33] = {0};
77,452✔
2910
    (void)tsnprintf(obj, sizeof(obj), "%d", req.vgId);
77,452✔
2911

2912
    int64_t tse = taosGetTimestampMs();
77,452✔
2913
    double  duration = (double)(tse - tss);
77,452✔
2914
    duration = duration / 1000;
77,452✔
2915
    auditRecord(pReq, pMnode->clusterId, "RedistributeVgroup", "", obj, req.sql, req.sqlLen, duration, 0);
77,452✔
2916
  }
2917
_OVER:
95,140✔
2918
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
95,140✔
2919
    mError("vgId:%d, failed to redistribute to dnode %d:%d:%d since %s", req.vgId, req.dnodeId1, req.dnodeId2,
19,134✔
2920
           req.dnodeId3, tstrerror(code));
2921
  }
2922

2923
  mndReleaseDnode(pMnode, pNew1);
95,140✔
2924
  mndReleaseDnode(pMnode, pNew2);
95,140✔
2925
  mndReleaseDnode(pMnode, pNew3);
95,140✔
2926
  mndReleaseDnode(pMnode, pOld1);
95,140✔
2927
  mndReleaseDnode(pMnode, pOld2);
95,140✔
2928
  mndReleaseDnode(pMnode, pOld3);
95,140✔
2929
  mndReleaseVgroup(pMnode, pVgroup);
95,140✔
2930
  mndReleaseDb(pMnode, pDb);
95,140✔
2931
  tFreeSRedistributeVgroupReq(&req);
95,140✔
2932

2933
  TAOS_RETURN(code);
95,140✔
2934
}
2935

2936
static void *mndBuildSForceBecomeFollowerReq(SMnode *pMnode, SVgObj *pVgroup, int32_t dnodeId, int32_t *pContLen) {
8,824✔
2937
  SForceBecomeFollowerReq balanceReq = {
8,824✔
2938
      .vgId = pVgroup->vgId,
8,824✔
2939
  };
2940

2941
  int32_t contLen = tSerializeSForceBecomeFollowerReq(NULL, 0, &balanceReq);
8,824✔
2942
  if (contLen < 0) {
8,824✔
UNCOV
2943
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
2944
    return NULL;
×
2945
  }
2946
  contLen += sizeof(SMsgHead);
8,824✔
2947

2948
  void *pReq = taosMemoryMalloc(contLen);
8,824✔
2949
  if (pReq == NULL) {
8,824✔
UNCOV
2950
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
2951
    return NULL;
×
2952
  }
2953

2954
  SMsgHead *pHead = pReq;
8,824✔
2955
  pHead->contLen = htonl(contLen);
8,824✔
2956
  pHead->vgId = htonl(pVgroup->vgId);
8,824✔
2957

2958
  if (tSerializeSForceBecomeFollowerReq((char *)pReq + sizeof(SMsgHead), contLen, &balanceReq) < 0) {
8,824✔
UNCOV
2959
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
2960
    taosMemoryFree(pReq);
×
2961
    return NULL;
×
2962
  }
2963
  *pContLen = contLen;
8,824✔
2964
  return pReq;
8,824✔
2965
}
2966

2967
int32_t mndAddBalanceVgroupLeaderAction(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup, int32_t dnodeId) {
8,824✔
2968
  int32_t    code = 0;
8,824✔
2969
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
8,824✔
2970
  if (pDnode == NULL) {
8,824✔
UNCOV
2971
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2972
    if (terrno != 0) code = terrno;
×
2973
    TAOS_RETURN(code);
×
2974
  }
2975

2976
  STransAction action = {0};
8,824✔
2977
  action.epSet = mndGetDnodeEpset(pDnode);
8,824✔
2978
  mndReleaseDnode(pMnode, pDnode);
8,824✔
2979

2980
  int32_t contLen = 0;
8,824✔
2981
  void   *pReq = mndBuildSForceBecomeFollowerReq(pMnode, pVgroup, dnodeId, &contLen);
8,824✔
2982
  if (pReq == NULL) {
8,824✔
UNCOV
2983
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2984
    if (terrno != 0) code = terrno;
×
2985
    TAOS_RETURN(code);
×
2986
  }
2987

2988
  action.pCont = pReq;
8,824✔
2989
  action.contLen = contLen;
8,824✔
2990
  action.msgType = TDMT_SYNC_FORCE_FOLLOWER;
8,824✔
2991

2992
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
8,824✔
UNCOV
2993
    taosMemoryFree(pReq);
×
UNCOV
2994
    TAOS_RETURN(code);
×
2995
  }
2996

2997
  TAOS_RETURN(code);
8,824✔
2998
}
2999

3000
static void *mndBuildAlterVnodeElectBaselineReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId,
52,944✔
3001
                                          int32_t *pContLen, int32_t ms) {
3002
  SAlterVnodeElectBaselineReq alterReq = {
52,944✔
3003
      .vgId = pVgroup->vgId,
52,944✔
3004
      .electBaseLine = ms,
3005
  };
3006

3007
  int32_t contLen = tSerializeSAlterVnodeReplicaReq(NULL, 0, &alterReq);
52,944✔
3008
  if (contLen < 0) {
52,944✔
UNCOV
3009
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
3010
    return NULL;
×
3011
  }
3012

3013
  void *pReq = taosMemoryMalloc(contLen);
52,944✔
3014
  if (pReq == NULL) {
52,944✔
UNCOV
3015
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
3016
    return NULL;
×
3017
  }
3018

3019
  if (tSerializeSAlterVnodeReplicaReq(pReq, contLen, &alterReq) < 0) {
52,944✔
UNCOV
3020
    mError("vgId:%d, failed to serialize alter vnode req,since %s", alterReq.vgId, terrstr());
×
UNCOV
3021
    taosMemoryFree(pReq);
×
3022
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
3023
    return NULL;
×
3024
  }
3025
  *pContLen = contLen;
52,944✔
3026
  return pReq;
52,944✔
3027
}
3028

3029
static int32_t mndAddAlterVnodeElectionBaselineActionToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId, int32_t ms) {
52,944✔
3030
  int32_t    code = 0;
52,944✔
3031
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
52,944✔
3032
  if (pDnode == NULL) {
52,944✔
UNCOV
3033
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3034
    if (terrno != 0) code = terrno;
×
3035
    TAOS_RETURN(code);
×
3036
  }
3037

3038
  STransAction action = {0};
52,944✔
3039
  action.epSet = mndGetDnodeEpset(pDnode);
52,944✔
3040
  mndReleaseDnode(pMnode, pDnode);
52,944✔
3041

3042
  int32_t contLen = 0;
52,944✔
3043
  void   *pReq = mndBuildAlterVnodeElectBaselineReq(pMnode, pDb, pVgroup, dnodeId, &contLen, ms);
52,944✔
3044
  if (pReq == NULL) {
52,944✔
UNCOV
3045
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3046
    if (terrno != 0) code = terrno;
×
3047
    TAOS_RETURN(code);
×
3048
  }
3049

3050
  action.pCont = pReq;
52,944✔
3051
  action.contLen = contLen;
52,944✔
3052
  action.msgType = TDMT_VND_ALTER_ELECTBASELINE;
52,944✔
3053
  action.groupId = pVgroup->vgId;
52,944✔
3054

3055
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
52,944✔
UNCOV
3056
    taosMemoryFree(pReq);
×
UNCOV
3057
    TAOS_RETURN(code);
×
3058
  }
3059

3060
  TAOS_RETURN(code);
52,944✔
3061
}
3062

3063
static int32_t mndAddAlterVgroupElectionBaselineActionToTrans(SMnode *pMnode, SVgObj *pVgroup, STrans *pTrans, int32_t index){
17,648✔
3064
  int32_t code = 0;
17,648✔
3065
  SSdb   *pSdb = pMnode->pSdb;
17,648✔
3066

3067
  int32_t vgid = pVgroup->vgId;
17,648✔
3068
  int8_t  replica = pVgroup->replica;
17,648✔
3069

3070
  if (pVgroup->replica <= 1) {
17,648✔
UNCOV
3071
    mInfo("trans:%d, vgid:%d no need to balance, replica:%d", pTrans->id, vgid, replica);
×
UNCOV
3072
    return -1;
×
3073
  }
3074

3075
  for(int32_t i = 0; i < 3; i++){
70,592✔
3076
    if(i == index%3){
52,944✔
3077
      mInfo("trans:%d, balance leader to dnode:%d", pTrans->id, pVgroup->vnodeGid[i].dnodeId);
8,824✔
3078
      TAOS_CHECK_RETURN(mndAddAlterVnodeElectionBaselineActionToTrans(pMnode, pTrans, NULL, pVgroup,
8,824✔
3079
                                                                      pVgroup->vnodeGid[i].dnodeId, 1500));
3080
    }
3081
    else{
3082
    TAOS_CHECK_RETURN(
44,120✔
3083
        mndAddAlterVnodeElectionBaselineActionToTrans(pMnode, pTrans, NULL, pVgroup, pVgroup->vnodeGid[i].dnodeId, 5000));
3084
    }
3085
  }
3086
  return code; 
17,648✔
3087
}
3088

3089
int32_t mndAddVgroupBalanceToTrans(SMnode *pMnode, SVgObj *pVgroup, STrans *pTrans, int32_t index) {
10,472✔
3090
  int32_t code = 0;
10,472✔
3091
  SSdb   *pSdb = pMnode->pSdb;
10,472✔
3092

3093
  int32_t vgid = pVgroup->vgId;
10,472✔
3094
  int8_t  replica = pVgroup->replica;
10,472✔
3095

3096
  if (pVgroup->replica <= 1) {
10,472✔
3097
    mInfo("trans:%d, vgid:%d no need to balance, replica:%d", pTrans->id, vgid, replica);
594✔
3098
    return -1;
594✔
3099
  }
3100

3101
  int32_t dnodeId = 0;
9,878✔
3102

3103
  for (int i = 0; i < replica; i++) {
24,574✔
3104
    if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_LEADER) {
23,520✔
3105
      dnodeId = pVgroup->vnodeGid[i].dnodeId;
8,824✔
3106
      break;
8,824✔
3107
    }
3108
  }
3109

3110
  bool       exist = false;
9,878✔
3111
  bool       online = false;
9,878✔
3112
  int64_t    curMs = taosGetTimestampMs();
9,878✔
3113
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
9,878✔
3114
  if (pDnode != NULL) {
9,878✔
3115
    exist = true;
8,824✔
3116
    online = mndIsDnodeOnline(pDnode, curMs);
8,824✔
3117
    mndReleaseDnode(pMnode, pDnode);
8,824✔
3118
  }
3119

3120
  if (exist && online) {
18,702✔
3121
    mInfo("trans:%d, vgid:%d force drop leader from dnode:%d", pTrans->id, vgid, dnodeId);    
8,824✔
3122
    TAOS_CHECK_RETURN(mndAddAlterVgroupElectionBaselineActionToTrans(pMnode, pVgroup, pTrans, index));
8,824✔
3123

3124
    if ((code = mndAddBalanceVgroupLeaderAction(pMnode, pTrans, pVgroup, dnodeId)) != 0) {
8,824✔
UNCOV
3125
      mError("trans:%d, vgid:%d failed to be balanced to dnode:%d", pTrans->id, vgid, dnodeId);
×
UNCOV
3126
      TAOS_RETURN(code);
×
3127
    }
3128

3129
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, NULL, pVgroup));
8,824✔
3130

3131
    TAOS_CHECK_RETURN(mndAddAlterVgroupElectionBaselineActionToTrans(pMnode, pVgroup, pTrans, -1));
8,824✔
3132

3133
    SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName);
8,824✔
3134
    if (pDb == NULL) {
8,824✔
UNCOV
3135
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3136
      if (terrno != 0) code = terrno;
×
3137
      mError("trans:%d, vgid:%d failed to be balanced to dnode:%d, because db not exist", pTrans->id, vgid, dnodeId);
×
3138
      TAOS_RETURN(code);
×
3139
    }
3140

3141
    mndReleaseDb(pMnode, pDb);
8,824✔
3142
  } else {
3143
    mInfo("trans:%d, vgid:%d cant be balanced to dnode:%d, exist:%d, online:%d", pTrans->id, vgid, dnodeId, exist,
1,054✔
3144
          online);
3145
  }
3146

3147
  TAOS_RETURN(code);
9,878✔
3148
}
3149

3150
extern int32_t mndProcessVgroupBalanceLeaderMsgImp(SRpcMsg *pReq);
3151

3152
int32_t mndProcessVgroupBalanceLeaderMsg(SRpcMsg *pReq) { return mndProcessVgroupBalanceLeaderMsgImp(pReq); }
4,756✔
3153

3154
#ifndef TD_ENTERPRISE
3155
int32_t mndProcessVgroupBalanceLeaderMsgImp(SRpcMsg *pReq) { return 0; }
3156
#endif
3157

3158
static int32_t mndCheckDnodeMemory(SMnode *pMnode, SDbObj *pOldDb, SDbObj *pNewDb, SVgObj *pOldVgroup,
414,606✔
3159
                                   SVgObj *pNewVgroup, SArray *pArray) {
3160
  for (int32_t i = 0; i < (int32_t)taosArrayGetSize(pArray); ++i) {
1,258,552✔
3161
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
843,946✔
3162
    bool       inVgroup = false;
843,946✔
3163
    int64_t    oldMemUsed = 0;
843,946✔
3164
    int64_t    newMemUsed = 0;
843,946✔
3165
    mDebug("db:%s, vgId:%d, check dnode:%d, avail:%" PRId64 " used:%" PRId64, pNewVgroup->dbName, pNewVgroup->vgId,
843,946✔
3166
           pDnode->id, pDnode->memAvail, pDnode->memUsed);
3167
    for (int32_t j = 0; j < pOldVgroup->replica; ++j) {
2,436,188✔
3168
      SVnodeGid *pVgId = &pOldVgroup->vnodeGid[j];
1,592,242✔
3169
      if (pDnode->id == pVgId->dnodeId) {
1,592,242✔
3170
        oldMemUsed = mndGetVgroupMemory(pMnode, pOldDb, pOldVgroup);
664,038✔
3171
        inVgroup = true;
664,038✔
3172
      }
3173
    }
3174
    for (int32_t j = 0; j < pNewVgroup->replica; ++j) {
2,436,188✔
3175
      SVnodeGid *pVgId = &pNewVgroup->vnodeGid[j];
1,592,242✔
3176
      if (pDnode->id == pVgId->dnodeId) {
1,592,242✔
3177
        newMemUsed = mndGetVgroupMemory(pMnode, pNewDb, pNewVgroup);
664,038✔
3178
        inVgroup = true;
664,038✔
3179
      }
3180
    }
3181

3182
    mDebug("db:%s, vgId:%d, memory in dnode:%d, oldUsed:%" PRId64 ", newUsed:%" PRId64, pNewVgroup->dbName,
843,946✔
3183
           pNewVgroup->vgId, pDnode->id, oldMemUsed, newMemUsed);
3184

3185
    pDnode->memUsed = pDnode->memUsed - oldMemUsed + newMemUsed;
843,946✔
3186
    if (pDnode->memAvail - pDnode->memUsed <= 0) {
843,946✔
UNCOV
3187
      mError("db:%s, vgId:%d, no enough memory in dnode:%d, avail:%" PRId64 " used:%" PRId64, pNewVgroup->dbName,
×
3188
             pNewVgroup->vgId, pDnode->id, pDnode->memAvail, pDnode->memUsed);
3189
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE);
×
3190
    } else if (inVgroup) {
843,946✔
3191
      mInfo("db:%s, vgId:%d, memory in dnode:%d, avail:%" PRId64 " used:%" PRId64, pNewVgroup->dbName, pNewVgroup->vgId,
664,038✔
3192
            pDnode->id, pDnode->memAvail, pDnode->memUsed);
3193
    } else {
3194
    }
3195
  }
3196
  return 0;
414,606✔
3197
}
3198

3199
int32_t mndBuildAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pOldDb, SDbObj *pNewDb, SVgObj *pVgroup,
489,754✔
3200
                                  SArray *pArray, SVgObj *pNewVgroup) {
3201
  int32_t code = 0;
489,754✔
3202
  memcpy(pNewVgroup, pVgroup, sizeof(SVgObj));
489,754✔
3203

3204
  if (pVgroup->replica <= 0 || pVgroup->replica == pNewDb->cfg.replications) {
489,754✔
3205
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfigAction(pMnode, pTrans, pNewDb, pVgroup));
414,606✔
3206
    TAOS_CHECK_RETURN(mndCheckDnodeMemory(pMnode, pOldDb, pNewDb, pNewVgroup, pVgroup, pArray));
414,606✔
3207
    return 0;
414,606✔
3208
  }
3209

3210
  // mndTransSetGroupParallel(pTrans);
3211

3212
  if (pNewDb->cfg.replications == 3) {
75,148✔
3213
    mInfo("trans:%d, db:%s, vgId:%d, will add 2 vnodes, vn:0 dnode:%d", pTrans->id, pVgroup->dbName, pVgroup->vgId,
65,486✔
3214
          pVgroup->vnodeGid[0].dnodeId);
3215

3216
    // add second
3217
    if (pNewVgroup->replica == 1) {
65,486✔
3218
      TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, pNewVgroup, pArray));
65,486✔
3219
    }
3220

3221
    // learner stage
3222
    pNewVgroup->vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
64,030✔
3223
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
64,030✔
3224
    TAOS_CHECK_RETURN(
64,030✔
3225
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3226

3227
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &pNewVgroup->vnodeGid[1]));
64,030✔
3228

3229
    // follower stage
3230
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
64,030✔
3231
    TAOS_CHECK_RETURN(mndAddAlterVnodeTypeAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
64,030✔
3232
    TAOS_CHECK_RETURN(
64,030✔
3233
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3234

3235
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
64,030✔
3236

3237
    // add third
3238
    if (pNewVgroup->replica == 2) {
64,030✔
3239
      TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, pNewVgroup, pArray));
64,030✔
3240
    }
3241

3242
    pNewVgroup->vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
58,674✔
3243
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
58,674✔
3244
    pNewVgroup->vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_VOTER;
58,674✔
3245
    TAOS_CHECK_RETURN(
58,674✔
3246
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3247
    TAOS_CHECK_RETURN(
58,674✔
3248
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
3249
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &pNewVgroup->vnodeGid[2]));
58,674✔
3250

3251
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
58,674✔
3252
  } else if (pNewDb->cfg.replications == 1) {
9,662✔
3253
    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,
6,750✔
3254
          pVgroup->dbName, pVgroup->vgId, pVgroup->vnodeGid[0].dnodeId, pVgroup->vnodeGid[1].dnodeId,
3255
          pVgroup->vnodeGid[2].dnodeId);
3256

3257
    SVnodeGid del1 = {0};
6,750✔
3258
    SVnodeGid del2 = {0};
6,750✔
3259
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroup(pMnode, pTrans, pNewVgroup, pArray, &del1));
6,750✔
3260
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &del1, true));
6,750✔
3261
    TAOS_CHECK_RETURN(
6,750✔
3262
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3263
    TAOS_CHECK_RETURN(
6,750✔
3264
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
3265
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
6,750✔
3266

3267
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroup(pMnode, pTrans, pNewVgroup, pArray, &del2));
6,750✔
3268
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &del2, true));
6,750✔
3269
    TAOS_CHECK_RETURN(
6,750✔
3270
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3271
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
6,750✔
3272
  } else if (pNewDb->cfg.replications == 2) {
2,912✔
3273
    mInfo("trans:%d, db:%s, vgId:%d, will add 1 vnode, vn:0 dnode:%d", pTrans->id, pVgroup->dbName, pVgroup->vgId,
2,912✔
3274
          pVgroup->vnodeGid[0].dnodeId);
3275

3276
    // add second
3277
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, pNewVgroup, pArray));
2,912✔
3278

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

3285
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &pNewVgroup->vnodeGid[1]));
2,912✔
3286

3287
    // follower stage
3288
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
2,912✔
3289
    TAOS_CHECK_RETURN(mndAddAlterVnodeTypeAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
2,912✔
3290
    TAOS_CHECK_RETURN(
2,912✔
3291
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
3292

3293
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
2,912✔
3294
  } else {
UNCOV
3295
    return -1;
×
3296
  }
3297

3298
  mndSortVnodeGid(pNewVgroup);
68,336✔
3299

3300
  {
3301
    SSdbRaw *pVgRaw = mndVgroupActionEncode(pNewVgroup);
68,336✔
3302
    if (pVgRaw == NULL) {
68,336✔
UNCOV
3303
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3304
      if (terrno != 0) code = terrno;
×
3305
      TAOS_RETURN(code);
×
3306
    }
3307
    if ((code = mndTransAppendCommitlog(pTrans, pVgRaw)) != 0) {
68,336✔
UNCOV
3308
      sdbFreeRaw(pVgRaw);
×
UNCOV
3309
      TAOS_RETURN(code);
×
3310
    }
3311
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
68,336✔
3312
    if (code != 0) {
68,336✔
UNCOV
3313
      mError("vgId:%d, failed to set raw status since %s at line:%d", pNewVgroup->vgId, tstrerror(code), __LINE__);
×
UNCOV
3314
      TAOS_RETURN(code);
×
3315
    }
3316
  }
3317

3318
  TAOS_RETURN(code);
68,336✔
3319
}
3320

UNCOV
3321
int32_t mndBuildRaftAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pOldDb, SDbObj *pNewDb, SVgObj *pVgroup,
×
3322
                                      SArray *pArray) {
3323
  int32_t code = 0;
×
UNCOV
3324
  SVgObj  newVgroup = {0};
×
3325
  memcpy(&newVgroup, pVgroup, sizeof(SVgObj));
×
3326

3327
  if (pVgroup->replica <= 0 || pVgroup->replica == pNewDb->cfg.replications) {
×
UNCOV
3328
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfigAction(pMnode, pTrans, pNewDb, pVgroup));
×
3329
    TAOS_CHECK_RETURN(mndCheckDnodeMemory(pMnode, pOldDb, pNewDb, &newVgroup, pVgroup, pArray));
×
3330
    return 0;
×
3331
  }
3332

UNCOV
3333
  mndTransSetSerial(pTrans);
×
3334

3335
  mInfo("trans:%d, vgId:%d, alter vgroup, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id, pVgroup->vgId,
×
3336
        pVgroup->syncConfChangeVer, pVgroup->version, pVgroup->replica);
3337

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

3342
    // add second
UNCOV
3343
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVgroup, pArray));
×
3344
    // add third
3345
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVgroup, pArray));
×
3346

3347
    // add learner stage
UNCOV
3348
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3349
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3350
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3351
    TAOS_CHECK_RETURN(
×
3352
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3353
    mInfo("trans:%d, vgId:%d, add change config, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id,
×
3354
          pVgroup->vgId, newVgroup.syncConfChangeVer, pVgroup->version, pVgroup->replica);
3355
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &newVgroup.vnodeGid[1]));
×
UNCOV
3356
    mInfo("trans:%d, vgId:%d, create vnode, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id, pVgroup->vgId,
×
3357
          newVgroup.syncConfChangeVer, pVgroup->version, pVgroup->replica);
3358
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &newVgroup.vnodeGid[2]));
×
UNCOV
3359
    mInfo("trans:%d, vgId:%d, create vnode, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id, pVgroup->vgId,
×
3360
          newVgroup.syncConfChangeVer, pVgroup->version, pVgroup->replica);
3361

3362
    // check learner
UNCOV
3363
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3364
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3365
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3366
    TAOS_CHECK_RETURN(
×
3367
        mndAddCheckLearnerCatchupAction(pMnode, pTrans, pNewDb, &newVgroup, newVgroup.vnodeGid[1].dnodeId));
3368
    TAOS_CHECK_RETURN(
×
3369
        mndAddCheckLearnerCatchupAction(pMnode, pTrans, pNewDb, &newVgroup, newVgroup.vnodeGid[2].dnodeId));
3370

3371
    // change raft type
UNCOV
3372
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3373
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3374
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
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
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
UNCOV
3381
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3382
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3383
    TAOS_CHECK_RETURN(
×
3384
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3385

UNCOV
3386
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
3387

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

UNCOV
3408
    SVnodeGid del1 = {0};
×
UNCOV
3409
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroupWithoutSave(pMnode, pTrans, &newVgroup, pArray, &del1));
×
3410

3411
    TAOS_CHECK_RETURN(
×
3412
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3413

UNCOV
3414
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
3415

3416
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &del1, true));
×
3417

3418
    SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
×
UNCOV
3419
    if (pVgRaw == NULL) {
×
3420
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3421
      if (terrno != 0) code = terrno;
×
3422
      TAOS_RETURN(code);
×
3423
    }
3424
    if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
×
UNCOV
3425
      sdbFreeRaw(pVgRaw);
×
3426
      TAOS_RETURN(code);
×
3427
    }
3428
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
UNCOV
3429
    if (code != 0) {
×
3430
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
3431
             __LINE__);
3432
      TAOS_RETURN(code);
×
3433
    }
3434

UNCOV
3435
    SVnodeGid del2 = {0};
×
UNCOV
3436
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroupWithoutSave(pMnode, pTrans, &newVgroup, pArray, &del2));
×
3437

3438
    TAOS_CHECK_RETURN(
×
3439
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
3440

UNCOV
3441
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
3442

3443
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &del2, true));
×
3444

3445
    pVgRaw = mndVgroupActionEncode(&newVgroup);
×
UNCOV
3446
    if (pVgRaw == NULL) {
×
3447
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3448
      if (terrno != 0) code = terrno;
×
3449
      TAOS_RETURN(code);
×
3450
    }
3451
    if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
×
UNCOV
3452
      sdbFreeRaw(pVgRaw);
×
3453
      TAOS_RETURN(code);
×
3454
    }
3455
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
UNCOV
3456
    if (code != 0) {
×
3457
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
3458
             __LINE__);
3459
      TAOS_RETURN(code);
×
3460
    }
3461
  } else {
UNCOV
3462
    return -1;
×
3463
  }
3464

UNCOV
3465
  mndSortVnodeGid(&newVgroup);
×
3466

3467
  {
UNCOV
3468
    SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
×
UNCOV
3469
    if (pVgRaw == NULL) {
×
3470
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3471
      if (terrno != 0) code = terrno;
×
3472
      TAOS_RETURN(code);
×
3473
    }
3474
    if ((code = mndTransAppendCommitlog(pTrans, pVgRaw)) != 0) {
×
UNCOV
3475
      sdbFreeRaw(pVgRaw);
×
3476
      TAOS_RETURN(code);
×
3477
    }
3478
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
UNCOV
3479
    if (code != 0) {
×
3480
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
3481
             __LINE__);
3482
      TAOS_RETURN(code);
×
3483
    }
3484
  }
3485

UNCOV
3486
  TAOS_RETURN(code);
×
3487
}
3488

3489
int32_t mndBuildRestoreAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *db, SVgObj *pVgroup, SDnodeObj *pDnode,
4,680✔
3490
                                         SDnodeObj *pAnotherDnode) {
3491
  int32_t code = 0;
4,680✔
3492
  SVgObj  newVgroup = {0};
4,680✔
3493
  memcpy(&newVgroup, pVgroup, sizeof(SVgObj));
4,680✔
3494

3495
  mInfo("trans:%d, db:%s, vgId:%d, restore vnodes, vn:0 dnode:%d", pTrans->id, pVgroup->dbName, pVgroup->vgId,
4,680✔
3496
        pVgroup->vnodeGid[0].dnodeId);
3497

3498
  if (newVgroup.replica == 1) {
4,680✔
UNCOV
3499
    int selected = 0;
×
UNCOV
3500
    for (int i = 0; i < newVgroup.replica; i++) {
×
3501
      newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3502
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
3503
        selected = i;
×
3504
      }
3505
    }
UNCOV
3506
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, db, &newVgroup, &newVgroup.vnodeGid[selected]));
×
3507
  } else if (newVgroup.replica == 2) {
4,680✔
3508
    for (int i = 0; i < newVgroup.replica; i++) {
×
UNCOV
3509
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
3510
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3511
      } else {
3512
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3513
      }
3514
    }
UNCOV
3515
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pAnotherDnode));
×
3516

3517
    for (int i = 0; i < newVgroup.replica; i++) {
×
UNCOV
3518
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
3519
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3520
      } else {
3521
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3522
      }
3523
    }
UNCOV
3524
    TAOS_CHECK_RETURN(mndRestoreAddCreateVnodeAction(pMnode, pTrans, db, &newVgroup, pDnode));
×
3525

3526
    for (int i = 0; i < newVgroup.replica; i++) {
×
UNCOV
3527
      newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3528
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
3529
      }
3530
    }
UNCOV
3531
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pDnode));
×
UNCOV
3532
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pAnotherDnode));
×
3533
  } else if (newVgroup.replica == 3) {
4,680✔
3534
    for (int i = 0; i < newVgroup.replica; i++) {
18,720✔
3535
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
14,040✔
3536
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_LEARNER;
4,680✔
3537
      } else {
3538
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
9,360✔
3539
      }
3540
    }
3541
    TAOS_CHECK_RETURN(mndRestoreAddCreateVnodeAction(pMnode, pTrans, db, &newVgroup, pDnode));
4,680✔
3542

3543
    for (int i = 0; i < newVgroup.replica; i++) {
18,720✔
3544
      newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
14,040✔
3545
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
14,040✔
3546
      }
3547
    }
3548
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pDnode));
4,680✔
3549
  }
3550
  SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
4,680✔
3551
  if (pVgRaw == NULL) {
4,680✔
UNCOV
3552
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3553
    if (terrno != 0) code = terrno;
×
3554
    TAOS_RETURN(code);
×
3555
  }
3556
  if ((code = mndTransAppendCommitlog(pTrans, pVgRaw)) != 0) {
4,680✔
UNCOV
3557
    sdbFreeRaw(pVgRaw);
×
UNCOV
3558
    TAOS_RETURN(code);
×
3559
  }
3560
  code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
4,680✔
3561
  if (code != 0) {
4,680✔
UNCOV
3562
    mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code), __LINE__);
×
UNCOV
3563
    TAOS_RETURN(code);
×
3564
  }
3565

3566
  TAOS_RETURN(code);
4,680✔
3567
}
3568

UNCOV
3569
static int32_t mndAddAdjustVnodeHashRangeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) {
×
UNCOV
3570
  return 0;
×
3571
}
3572

3573
typedef int32_t (*FpTransActionCb)(STrans *pTrans, SSdbRaw *pRaw);
3574

3575
static int32_t mndAddVgStatusAction(STrans *pTrans, SVgObj *pVg, ESdbStatus vgStatus, ETrnStage stage) {
155,100✔
3576
  int32_t         code = 0;
155,100✔
3577
  FpTransActionCb appendActionCb = (stage == TRN_STAGE_COMMIT_ACTION) ? mndTransAppendCommitlog : mndTransAppendRedolog;
155,100✔
3578
  SSdbRaw        *pRaw = mndVgroupActionEncode(pVg);
155,100✔
3579
  if (pRaw == NULL) {
155,100✔
UNCOV
3580
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3581
    if (terrno != 0) code = terrno;
×
3582
    goto _err;
×
3583
  }
3584
  if ((code = appendActionCb(pTrans, pRaw)) != 0) goto _err;
155,100✔
3585
  code = sdbSetRawStatus(pRaw, vgStatus);
155,100✔
3586
  if (code != 0) {
155,100✔
UNCOV
3587
    mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", pVg->vgId, tstrerror(code), __LINE__);
×
UNCOV
3588
    goto _err;
×
3589
  }
3590
  pRaw = NULL;
155,100✔
3591
  TAOS_RETURN(code);
155,100✔
UNCOV
3592
_err:
×
UNCOV
3593
  sdbFreeRaw(pRaw);
×
3594
  TAOS_RETURN(code);
×
3595
}
3596

3597
static int32_t mndAddDbStatusAction(STrans *pTrans, SDbObj *pDb, ESdbStatus dbStatus, ETrnStage stage) {
62,660✔
3598
  int32_t         code = 0;
62,660✔
3599
  FpTransActionCb appendActionCb = (stage == TRN_STAGE_COMMIT_ACTION) ? mndTransAppendCommitlog : mndTransAppendRedolog;
62,660✔
3600
  SSdbRaw        *pRaw = mndDbActionEncode(pDb);
62,660✔
3601
  if (pRaw == NULL) {
62,660✔
UNCOV
3602
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3603
    if (terrno != 0) code = terrno;
×
3604
    goto _err;
×
3605
  }
3606
  if ((code = appendActionCb(pTrans, pRaw)) != 0) goto _err;
62,660✔
3607
  code = sdbSetRawStatus(pRaw, dbStatus);
62,660✔
3608
  if (code != 0) {
62,660✔
UNCOV
3609
    mError("db:%s, failed to set raw status to ready, error:%s, line:%d", pDb->name, tstrerror(code), __LINE__);
×
UNCOV
3610
    goto _err;
×
3611
  }
3612
  pRaw = NULL;
62,660✔
3613
  TAOS_RETURN(code);
62,660✔
UNCOV
3614
_err:
×
UNCOV
3615
  sdbFreeRaw(pRaw);
×
3616
  TAOS_RETURN(code);
×
3617
}
3618

3619
int32_t mndSplitVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SVgObj *pVgroup) {
35,352✔
3620
  int32_t code = -1;
35,352✔
3621
  STrans *pTrans = NULL;
35,352✔
3622
  SDbObj  dbObj = {0};
35,352✔
3623
  SArray *pArray = mndBuildDnodesArray(pMnode, 0, NULL);
35,352✔
3624

3625
#if defined(USE_SHARED_STORAGE)
3626
  if (tsSsEnabled) {
35,352✔
UNCOV
3627
    code = TSDB_CODE_OPS_NOT_SUPPORT;
×
UNCOV
3628
    mError("vgId:%d, db:%s, shared storage exists, split vgroup not allowed", pVgroup->vgId, pVgroup->dbName);
×
3629
    goto _OVER;
×
3630
  }
3631
#endif
3632

3633
  /*
3634
    if (pDb->cfg.withArbitrator) {
3635
      code = TSDB_CODE_OPS_NOT_SUPPORT;
3636
      mError("vgId:%d, db:%s, with arbitrator, split vgroup not allowed", pVgroup->vgId, pVgroup->dbName);
3637
      goto _OVER;
3638
    }
3639
  */
3640

3641
  pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB, pReq, "split-vgroup");
35,352✔
3642
  if (pTrans == NULL) {
35,352✔
UNCOV
3643
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3644
    if (terrno != 0) code = terrno;
×
3645
    goto _OVER;
×
3646
  }
3647
  mndTransSetSerial(pTrans);
35,352✔
3648
  mInfo("trans:%d, used to split vgroup, vgId:%d", pTrans->id, pVgroup->vgId);
35,352✔
3649

3650
  mndTransSetDbName(pTrans, pDb->name, NULL);
35,352✔
3651
  TAOS_CHECK_GOTO(mndTransCheckConflictWithCompact(pMnode, pTrans), NULL, _OVER);
35,352✔
3652
  TAOS_CHECK_GOTO(mndTransCheckConflictWithRetention(pMnode, pTrans), NULL, _OVER);
35,188✔
3653

3654
  SVgObj newVg1 = {0};
35,188✔
3655
  memcpy(&newVg1, pVgroup, sizeof(SVgObj));
35,188✔
3656
  mInfo("vgId:%d, vgroup info before split, replica:%d hashBegin:%u hashEnd:%u", newVg1.vgId, newVg1.replica,
35,188✔
3657
        newVg1.hashBegin, newVg1.hashEnd);
3658
  for (int32_t i = 0; i < newVg1.replica; ++i) {
114,872✔
3659
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg1.vgId, i, newVg1.vnodeGid[i].dnodeId);
79,684✔
3660
  }
3661

3662
  if (newVg1.replica == 1) {
35,188✔
3663
    TAOS_CHECK_GOTO(mndAddVnodeToVgroup(pMnode, pTrans, &newVg1, pArray), NULL, _OVER);
12,212✔
3664

3665
    newVg1.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
12,212✔
3666
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[0].dnodeId), NULL,
12,212✔
3667
                    _OVER);
3668
    TAOS_CHECK_GOTO(mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg1, &newVg1.vnodeGid[1]), NULL, _OVER);
12,212✔
3669

3670
    newVg1.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
12,212✔
3671
    TAOS_CHECK_GOTO(mndAddAlterVnodeTypeAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[1].dnodeId), NULL, _OVER);
12,212✔
3672
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[0].dnodeId), NULL,
12,212✔
3673
                    _OVER);
3674

3675
    TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg1), NULL, _OVER);
12,212✔
3676
  } else if (newVg1.replica == 3) {
22,976✔
3677
    SVnodeGid del1 = {0};
21,520✔
3678
    TAOS_CHECK_GOTO(mndRemoveVnodeFromVgroup(pMnode, pTrans, &newVg1, pArray, &del1), NULL, _OVER);
21,520✔
3679
    TAOS_CHECK_GOTO(mndAddDropVnodeAction(pMnode, pTrans, pDb, &newVg1, &del1, true), NULL, _OVER);
20,340✔
3680
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[0].dnodeId), NULL,
20,340✔
3681
                    _OVER);
3682
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[1].dnodeId), NULL,
20,340✔
3683
                    _OVER);
3684
  } else {
3685
    // goto _OVER;
3686
  }
3687

3688
  for (int32_t i = 0; i < newVg1.replica; ++i) {
102,024✔
3689
    TAOS_CHECK_GOTO(mndAddDisableVnodeWriteAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[i].dnodeId), NULL,
68,016✔
3690
                    _OVER);
3691
  }
3692
  TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg1), NULL, _OVER);
34,008✔
3693

3694
  SVgObj newVg2 = {0};
34,008✔
3695
  memcpy(&newVg2, &newVg1, sizeof(SVgObj));
34,008✔
3696
  newVg1.replica = 1;
34,008✔
3697
  newVg1.hashEnd = newVg1.hashBegin / 2 + newVg1.hashEnd / 2;
34,008✔
3698
  memset(&newVg1.vnodeGid[1], 0, sizeof(SVnodeGid));
34,008✔
3699

3700
  newVg2.replica = 1;
34,008✔
3701
  newVg2.hashBegin = newVg1.hashEnd + 1;
34,008✔
3702
  memcpy(&newVg2.vnodeGid[0], &newVg2.vnodeGid[1], sizeof(SVnodeGid));
34,008✔
3703
  memset(&newVg2.vnodeGid[1], 0, sizeof(SVnodeGid));
34,008✔
3704

3705
  mInfo("vgId:%d, vgroup info after split, replica:%d hashrange:[%u, %u] vnode:0 dnode:%d", newVg1.vgId, newVg1.replica,
34,008✔
3706
        newVg1.hashBegin, newVg1.hashEnd, newVg1.vnodeGid[0].dnodeId);
3707
  for (int32_t i = 0; i < newVg1.replica; ++i) {
68,016✔
3708
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg1.vgId, i, newVg1.vnodeGid[i].dnodeId);
34,008✔
3709
  }
3710
  mInfo("vgId:%d, vgroup info after split, replica:%d hashrange:[%u, %u] vnode:0 dnode:%d", newVg2.vgId, newVg2.replica,
34,008✔
3711
        newVg2.hashBegin, newVg2.hashEnd, newVg2.vnodeGid[0].dnodeId);
3712
  for (int32_t i = 0; i < newVg1.replica; ++i) {
68,016✔
3713
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg2.vgId, i, newVg2.vnodeGid[i].dnodeId);
34,008✔
3714
  }
3715

3716
  // alter vgId and hash range
3717
  int32_t maxVgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP);
34,008✔
3718
  int32_t srcVgId = newVg1.vgId;
34,008✔
3719
  newVg1.vgId = maxVgId;
34,008✔
3720
  TAOS_CHECK_GOTO(mndAddNewVgPrepareAction(pMnode, pTrans, &newVg1), NULL, _OVER);
34,008✔
3721
  TAOS_CHECK_GOTO(mndAddAlterVnodeHashRangeAction(pMnode, pTrans, srcVgId, &newVg1), NULL, _OVER);
34,008✔
3722

3723
  maxVgId++;
34,008✔
3724
  srcVgId = newVg2.vgId;
34,008✔
3725
  newVg2.vgId = maxVgId;
34,008✔
3726
  TAOS_CHECK_GOTO(mndAddNewVgPrepareAction(pMnode, pTrans, &newVg2), NULL, _OVER);
34,008✔
3727
  TAOS_CHECK_GOTO(mndAddAlterVnodeHashRangeAction(pMnode, pTrans, srcVgId, &newVg2), NULL, _OVER);
34,008✔
3728

3729
  TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg1), NULL, _OVER);
34,008✔
3730
  TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg2), NULL, _OVER);
34,008✔
3731

3732
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg1, SDB_STATUS_READY, TRN_STAGE_REDO_ACTION), NULL, _OVER);
34,008✔
3733
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg2, SDB_STATUS_READY, TRN_STAGE_REDO_ACTION), NULL, _OVER);
34,008✔
3734
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, pVgroup, SDB_STATUS_DROPPED, TRN_STAGE_REDO_ACTION), NULL, _OVER);
34,008✔
3735

3736
  // update db status
3737
  memcpy(&dbObj, pDb, sizeof(SDbObj));
34,008✔
3738
  if (dbObj.cfg.pRetensions != NULL) {
34,008✔
UNCOV
3739
    dbObj.cfg.pRetensions = taosArrayDup(pDb->cfg.pRetensions, NULL);
×
UNCOV
3740
    if (dbObj.cfg.pRetensions == NULL) {
×
3741
      code = terrno;
×
3742
      goto _OVER;
×
3743
    }
3744
  }
3745
  dbObj.vgVersion++;
34,008✔
3746
  dbObj.updateTime = taosGetTimestampMs();
34,008✔
3747
  dbObj.cfg.numOfVgroups++;
34,008✔
3748
  TAOS_CHECK_GOTO(mndAddDbStatusAction(pTrans, &dbObj, SDB_STATUS_READY, TRN_STAGE_REDO_ACTION), NULL, _OVER);
34,008✔
3749

3750
  // adjust vgroup replica
3751
  if (pDb->cfg.replications != newVg1.replica) {
34,008✔
3752
    SVgObj tmpGroup = {0};
21,796✔
3753
    TAOS_CHECK_GOTO(mndBuildAlterVgroupAction(pMnode, pTrans, pDb, pDb, &newVg1, pArray, &tmpGroup), NULL, _OVER);
21,796✔
3754
  } else {
3755
    TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg1, SDB_STATUS_READY, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
12,212✔
3756
  }
3757

3758
  if (pDb->cfg.replications != newVg2.replica) {
30,424✔
3759
    SVgObj tmpGroup = {0};
18,212✔
3760
    TAOS_CHECK_GOTO(mndBuildAlterVgroupAction(pMnode, pTrans, pDb, pDb, &newVg2, pArray, &tmpGroup), NULL, _OVER);
18,212✔
3761
  } else {
3762
    TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg2, SDB_STATUS_READY, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
12,212✔
3763
  }
3764

3765
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, pVgroup, SDB_STATUS_DROPPED, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
28,652✔
3766

3767
  // commit db status
3768
  dbObj.vgVersion++;
28,652✔
3769
  dbObj.updateTime = taosGetTimestampMs();
28,652✔
3770
  TAOS_CHECK_GOTO(mndAddDbStatusAction(pTrans, &dbObj, SDB_STATUS_READY, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
28,652✔
3771

3772
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
28,652✔
3773
  code = 0;
28,652✔
3774

3775
_OVER:
35,352✔
3776
  taosArrayDestroy(pArray);
35,352✔
3777
  mndTransDrop(pTrans);
35,352✔
3778
  taosArrayDestroy(dbObj.cfg.pRetensions);
35,352✔
3779
  TAOS_RETURN(code);
35,352✔
3780
}
3781

3782
extern int32_t mndProcessSplitVgroupMsgImp(SRpcMsg *pReq);
3783

3784
static int32_t mndProcessSplitVgroupMsg(SRpcMsg *pReq) { return mndProcessSplitVgroupMsgImp(pReq); }
36,192✔
3785

3786
#ifndef TD_ENTERPRISE
3787
int32_t mndProcessSplitVgroupMsgImp(SRpcMsg *pReq) { return 0; }
3788
#endif
3789

3790
static int32_t mndSetBalanceVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
31,144✔
3791
                                              SDnodeObj *pSrc, SDnodeObj *pDst) {
3792
  int32_t code = 0;
31,144✔
3793
  SVgObj  newVg = {0};
31,144✔
3794
  memcpy(&newVg, pVgroup, sizeof(SVgObj));
31,144✔
3795
  mInfo("vgId:%d, vgroup info before balance, replica:%d", newVg.vgId, newVg.replica);
31,144✔
3796
  for (int32_t i = 0; i < newVg.replica; ++i) {
91,488✔
3797
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
60,344✔
3798
  }
3799

3800
  TAOS_CHECK_RETURN(mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pDst->id));
31,144✔
3801
  TAOS_CHECK_RETURN(mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pSrc->id));
31,144✔
3802

3803
  {
3804
    SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
31,144✔
3805
    if (pRaw == NULL) {
31,144✔
UNCOV
3806
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3807
      if (terrno != 0) code = terrno;
×
3808
      TAOS_RETURN(code);
×
3809
    }
3810
    if ((code = mndTransAppendCommitlog(pTrans, pRaw)) != 0) {
31,144✔
UNCOV
3811
      sdbFreeRaw(pRaw);
×
UNCOV
3812
      TAOS_RETURN(code);
×
3813
    }
3814
    code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
31,144✔
3815
    if (code != 0) {
31,144✔
UNCOV
3816
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
UNCOV
3817
      TAOS_RETURN(code);
×
3818
    }
3819
  }
3820

3821
  mInfo("vgId:%d, vgroup info after balance, replica:%d", newVg.vgId, newVg.replica);
31,144✔
3822
  for (int32_t i = 0; i < newVg.replica; ++i) {
91,488✔
3823
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
60,344✔
3824
  }
3825
  TAOS_RETURN(code);
31,144✔
3826
}
3827

3828
static int32_t mndBalanceVgroupBetweenDnode(SMnode *pMnode, STrans *pTrans, SDnodeObj *pSrc, SDnodeObj *pDst,
31,144✔
3829
                                            SHashObj *pBalancedVgroups) {
3830
  void   *pIter = NULL;
31,144✔
3831
  int32_t code = -1;
31,144✔
3832
  SSdb   *pSdb = pMnode->pSdb;
31,144✔
3833

3834
  while (1) {
19,198✔
3835
    SVgObj *pVgroup = NULL;
50,342✔
3836
    pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
50,342✔
3837
    if (pIter == NULL) break;
50,342✔
3838
    if (taosHashGet(pBalancedVgroups, &pVgroup->vgId, sizeof(int32_t)) != NULL) {
50,342✔
3839
      sdbRelease(pSdb, pVgroup);
17,542✔
3840
      continue;
17,542✔
3841
    }
3842

3843
    bool existInSrc = false;
32,800✔
3844
    bool existInDst = false;
32,800✔
3845
    for (int32_t i = 0; i < pVgroup->replica; ++i) {
94,800✔
3846
      SVnodeGid *pGid = &pVgroup->vnodeGid[i];
62,000✔
3847
      if (pGid->dnodeId == pSrc->id) existInSrc = true;
62,000✔
3848
      if (pGid->dnodeId == pDst->id) existInDst = true;
62,000✔
3849
    }
3850

3851
    if (!existInSrc || existInDst) {
32,800✔
3852
      sdbRelease(pSdb, pVgroup);
1,656✔
3853
      continue;
1,656✔
3854
    }
3855

3856
    SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName);
31,144✔
3857
    if (pDb == NULL) {
31,144✔
UNCOV
3858
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3859
      if (terrno != 0) code = terrno;
×
3860
      mError("vgId:%d, balance vgroup can't find db obj dbName:%s", pVgroup->vgId, pVgroup->dbName);
×
3861
      goto _OUT;
×
3862
    }
3863

3864
    if (pDb->cfg.withArbitrator) {
31,144✔
UNCOV
3865
      mInfo("vgId:%d, db:%s, with arbitrator, balance vgroup not allowed", pVgroup->vgId, pVgroup->dbName);
×
UNCOV
3866
      goto _OUT;
×
3867
    }
3868

3869
    code = mndSetBalanceVgroupInfoToTrans(pMnode, pTrans, pDb, pVgroup, pSrc, pDst);
31,144✔
3870
    if (code == 0) {
31,144✔
3871
      code = taosHashPut(pBalancedVgroups, &pVgroup->vgId, sizeof(int32_t), &pVgroup->vgId, sizeof(int32_t));
31,144✔
3872
    }
3873

3874
  _OUT:
31,144✔
3875
    mndReleaseDb(pMnode, pDb);
31,144✔
3876
    sdbRelease(pSdb, pVgroup);
31,144✔
3877
    sdbCancelFetch(pSdb, pIter);
31,144✔
3878
    break;
31,144✔
3879
  }
3880

3881
  return code;
31,144✔
3882
}
3883

3884
static int32_t mndBalanceVgroup(SMnode *pMnode, SRpcMsg *pReq, SArray *pArray) {
20,758✔
3885
  int32_t   code = -1;
20,758✔
3886
  int32_t   numOfVgroups = 0;
20,758✔
3887
  STrans   *pTrans = NULL;
20,758✔
3888
  SHashObj *pBalancedVgroups = NULL;
20,758✔
3889

3890
  pBalancedVgroups = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
20,758✔
3891
  if (pBalancedVgroups == NULL) goto _OVER;
20,758✔
3892

3893
  pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_GLOBAL, pReq, "balance-vgroup");
20,758✔
3894
  if (pTrans == NULL) {
20,758✔
UNCOV
3895
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3896
    if (terrno != 0) code = terrno;
×
3897
    goto _OVER;
×
3898
  }
3899
  mndTransSetSerial(pTrans);
20,758✔
3900
  mInfo("trans:%d, used to balance vgroup", pTrans->id);
20,758✔
3901
  TAOS_CHECK_GOTO(mndTransCheckConflict(pMnode, pTrans), NULL, _OVER);
20,758✔
3902
  TAOS_CHECK_GOTO(mndTransCheckConflictWithCompact(pMnode, pTrans), NULL, _OVER);
19,610✔
3903
  TAOS_CHECK_GOTO(mndTransCheckConflictWithRetention(pMnode, pTrans), NULL, _OVER);
19,446✔
3904

3905
  while (1) {
31,144✔
3906
    taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
50,590✔
3907
    for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
218,158✔
3908
      SDnodeObj *pDnode = taosArrayGet(pArray, i);
167,568✔
3909
      mInfo("dnode:%d, equivalent vnodes:%d others:%d support:%d, score:%f", pDnode->id, pDnode->numOfVnodes,
167,568✔
3910
            pDnode->numOfSupportVnodes, pDnode->numOfOtherNodes, mndGetDnodeScore(pDnode, 0, 1));
3911
    }
3912

3913
    SDnodeObj *pSrc = taosArrayGet(pArray, taosArrayGetSize(pArray) - 1);
50,590✔
3914
    SDnodeObj *pDst = taosArrayGet(pArray, 0);
50,590✔
3915

3916
    float srcScore = mndGetDnodeScore(pSrc, -1, 1);
50,590✔
3917
    float dstScore = mndGetDnodeScore(pDst, 1, 1);
50,590✔
3918
    mInfo("trans:%d, after balance, src dnode:%d score:%f, dst dnode:%d score:%f", pTrans->id, pSrc->id, dstScore,
50,590✔
3919
          pDst->id, dstScore);
3920

3921
    if (srcScore > dstScore - 0.000001) {
50,590✔
3922
      code = mndBalanceVgroupBetweenDnode(pMnode, pTrans, pSrc, pDst, pBalancedVgroups);
31,144✔
3923
      if (code == 0) {
31,144✔
3924
        pSrc->numOfVnodes--;
31,144✔
3925
        pDst->numOfVnodes++;
31,144✔
3926
        numOfVgroups++;
31,144✔
3927
        continue;
31,144✔
3928
      } else {
UNCOV
3929
        mInfo("trans:%d, no vgroup need to balance from dnode:%d to dnode:%d", pTrans->id, pSrc->id, pDst->id);
×
UNCOV
3930
        break;
×
3931
      }
3932
    } else {
3933
      mInfo("trans:%d, no vgroup need to balance any more", pTrans->id);
19,446✔
3934
      break;
19,446✔
3935
    }
3936
  }
3937

3938
  if (numOfVgroups <= 0) {
19,446✔
UNCOV
3939
    mInfo("no need to balance vgroup");
×
UNCOV
3940
    code = 0;
×
3941
  } else {
3942
    mInfo("start to balance vgroup, numOfVgroups:%d", numOfVgroups);
19,446✔
3943
    if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER;
19,446✔
3944
    code = TSDB_CODE_ACTION_IN_PROGRESS;
19,446✔
3945
  }
3946

3947
_OVER:
20,758✔
3948
  taosHashCleanup(pBalancedVgroups);
20,758✔
3949
  mndTransDrop(pTrans);
20,758✔
3950
  TAOS_RETURN(code);
20,758✔
3951
}
3952

3953
static int32_t mndProcessBalanceVgroupMsg(SRpcMsg *pReq) {
23,766✔
3954
  SMnode *pMnode = pReq->info.node;
23,766✔
3955
  int32_t code = -1;
23,766✔
3956
  SArray *pArray = NULL;
23,766✔
3957
  void   *pIter = NULL;
23,766✔
3958
  int64_t curMs = taosGetTimestampMs();
23,766✔
3959
  int64_t tss = taosGetTimestampMs();
23,766✔
3960

3961
  SBalanceVgroupReq req = {0};
23,766✔
3962
  if (tDeserializeSBalanceVgroupReq(pReq->pCont, pReq->contLen, &req) != 0) {
23,766✔
UNCOV
3963
    code = TSDB_CODE_INVALID_MSG;
×
UNCOV
3964
    goto _OVER;
×
3965
  }
3966

3967
  mInfo("start to balance vgroup");
23,766✔
3968
  if ((code = mndCheckOperPrivilege(pMnode, RPC_MSG_USER(pReq), RPC_MSG_TOKEN(pReq), MND_OPER_BALANCE_VGROUP)) != 0) {
23,766✔
UNCOV
3969
    goto _OVER;
×
3970
  }
3971

3972
  if (sdbGetSize(pMnode->pSdb, SDB_MOUNT) > 0) {
23,766✔
UNCOV
3973
    code = TSDB_CODE_MND_MOUNT_NOT_EMPTY;
×
UNCOV
3974
    goto _OVER;
×
3975
  }
3976

3977
  while (1) {
72,554✔
3978
    SDnodeObj *pDnode = NULL;
96,320✔
3979
    pIter = sdbFetch(pMnode->pSdb, SDB_DNODE, pIter, (void **)&pDnode);
96,320✔
3980
    if (pIter == NULL) break;
96,320✔
3981
    if (!mndIsDnodeOnline(pDnode, curMs)) {
75,562✔
3982
      sdbCancelFetch(pMnode->pSdb, pIter);
3,008✔
3983
      code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
3,008✔
3984
      mError("failed to balance vgroup since %s, dnode:%d", terrstr(), pDnode->id);
3,008✔
3985
      sdbRelease(pMnode->pSdb, pDnode);
3,008✔
3986
      goto _OVER;
3,008✔
3987
    }
3988

3989
    sdbRelease(pMnode->pSdb, pDnode);
72,554✔
3990
  }
3991

3992
  pArray = mndBuildDnodesArray(pMnode, 0, NULL);
20,758✔
3993
  if (pArray == NULL) {
20,758✔
UNCOV
3994
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
3995
    if (terrno != 0) code = terrno;
×
3996
    goto _OVER;
×
3997
  }
3998

3999
  if (taosArrayGetSize(pArray) < 2) {
20,758✔
UNCOV
4000
    mInfo("no need to balance vgroup since dnode num less than 2");
×
UNCOV
4001
    code = 0;
×
4002
  } else {
4003
    code = mndBalanceVgroup(pMnode, pReq, pArray);
20,758✔
4004
  }
4005

4006
  if (tsAuditLevel >= AUDIT_LEVEL_CLUSTER) {
20,758✔
4007
    int64_t tse = taosGetTimestampMs();
20,758✔
4008
    double  duration = (double)(tse - tss);
20,758✔
4009
    duration = duration / 1000;
20,758✔
4010
    auditRecord(pReq, pMnode->clusterId, "balanceVgroup", "", "", req.sql, req.sqlLen, duration, 0);
20,758✔
4011
  }
4012

4013
_OVER:
23,766✔
4014
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
23,766✔
4015
    mError("failed to balance vgroup since %s", tstrerror(code));
4,320✔
4016
  }
4017

4018
  taosArrayDestroy(pArray);
23,766✔
4019
  tFreeSBalanceVgroupReq(&req);
23,766✔
4020
  TAOS_RETURN(code);
23,766✔
4021
}
4022

4023
bool mndVgroupInDb(SVgObj *pVgroup, int64_t dbUid) { return !pVgroup->isTsma && pVgroup->dbUid == dbUid; }
248,243,520✔
4024

4025
bool mndVgroupInDnode(SVgObj *pVgroup, int32_t dnodeId) {
7,488✔
4026
  for (int i = 0; i < pVgroup->replica; i++) {
18,712✔
4027
    if (pVgroup->vnodeGid[i].dnodeId == dnodeId) return true;
15,904✔
4028
  }
4029
  return false;
2,808✔
4030
}
4031

4032
static void *mndBuildCompactVnodeReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen, int64_t compactTs,
275,194✔
4033
                                     STimeWindow tw, bool metaOnly, bool force, ETsdbOpType type,
4034
                                     ETriggerType triggerType) {
4035
  SCompactVnodeReq compactReq = {0};
275,194✔
4036
  compactReq.dbUid = pDb->uid;
275,194✔
4037
  compactReq.compactStartTime = compactTs;
275,194✔
4038
  compactReq.tw = tw;
275,194✔
4039
  compactReq.metaOnly = metaOnly;
275,194✔
4040
  compactReq.force = force;
275,194✔
4041
  compactReq.optrType = type;
275,194✔
4042
  compactReq.triggerType = triggerType;
275,194✔
4043
  tstrncpy(compactReq.db, pDb->name, TSDB_DB_FNAME_LEN);
275,194✔
4044

4045
  mInfo("vgId:%d, build compact vnode config req", pVgroup->vgId);
275,194✔
4046
  int32_t contLen = tSerializeSCompactVnodeReq(NULL, 0, &compactReq);
275,194✔
4047
  if (contLen < 0) {
275,194✔
UNCOV
4048
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
4049
    return NULL;
×
4050
  }
4051
  contLen += sizeof(SMsgHead);
275,194✔
4052

4053
  void *pReq = taosMemoryMalloc(contLen);
275,194✔
4054
  if (pReq == NULL) {
275,194✔
UNCOV
4055
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
4056
    return NULL;
×
4057
  }
4058

4059
  SMsgHead *pHead = pReq;
275,194✔
4060
  pHead->contLen = htonl(contLen);
275,194✔
4061
  pHead->vgId = htonl(pVgroup->vgId);
275,194✔
4062

4063
  if (tSerializeSCompactVnodeReq((char *)pReq + sizeof(SMsgHead), contLen, &compactReq) < 0) {
275,194✔
UNCOV
4064
    taosMemoryFree(pReq);
×
UNCOV
4065
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
4066
    return NULL;
×
4067
  }
4068
  *pContLen = contLen;
275,194✔
4069
  return pReq;
275,194✔
4070
}
4071

4072
static int32_t mndAddCompactVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int64_t compactTs,
119,670✔
4073
                                        STimeWindow tw, bool metaOnly, bool force, ETsdbOpType type,
4074
                                        ETriggerType triggerType) {
4075
  int32_t      code = 0;
119,670✔
4076
  STransAction action = {0};
119,670✔
4077
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
119,670✔
4078

4079
  int32_t contLen = 0;
119,670✔
4080
  void   *pReq =
4081
      mndBuildCompactVnodeReq(pMnode, pDb, pVgroup, &contLen, compactTs, tw, metaOnly, force, type, triggerType);
119,670✔
4082
  if (pReq == NULL) {
119,670✔
UNCOV
4083
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
4084
    if (terrno != 0) code = terrno;
×
4085
    TAOS_RETURN(code);
×
4086
  }
4087

4088
  action.pCont = pReq;
119,670✔
4089
  action.contLen = contLen;
119,670✔
4090
  action.msgType = TDMT_VND_COMPACT;
119,670✔
4091

4092
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
119,670✔
UNCOV
4093
    taosMemoryFree(pReq);
×
UNCOV
4094
    TAOS_RETURN(code);
×
4095
  }
4096

4097
  TAOS_RETURN(code);
119,670✔
4098
}
4099

4100
int32_t mndBuildCompactVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int64_t compactTs,
119,670✔
4101
                                    STimeWindow tw, bool metaOnly, bool force, ETsdbOpType type,
4102
                                    ETriggerType triggerType) {
4103
  TAOS_CHECK_RETURN(
119,670✔
4104
      mndAddCompactVnodeAction(pMnode, pTrans, pDb, pVgroup, compactTs, tw, metaOnly, force, type, triggerType));
4105
  return 0;
119,670✔
4106
}
4107

4108
int32_t mndBuildTrimVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int64_t startTs,
155,524✔
4109
                                 STimeWindow tw, ETsdbOpType type, ETriggerType triggerType) {
4110
  int32_t      code = 0;
155,524✔
4111
  STransAction action = {0};
155,524✔
4112
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
155,524✔
4113

4114
  int32_t contLen = 0;
155,524✔
4115
  // reuse SCompactVnodeReq as SVTrimDbReq
4116
  void *pReq = mndBuildCompactVnodeReq(pMnode, pDb, pVgroup, &contLen, startTs, tw, false, false, type, triggerType);
155,524✔
4117
  if (pReq == NULL) {
155,524✔
UNCOV
4118
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
4119
    if (terrno != 0) code = terrno;
×
4120
    TAOS_RETURN(code);
×
4121
  }
4122

4123
  action.pCont = pReq;
155,524✔
4124
  action.contLen = contLen;
155,524✔
4125
  action.msgType = TDMT_VND_TRIM;
155,524✔
4126

4127
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
155,524✔
UNCOV
4128
    taosMemoryFree(pReq);
×
UNCOV
4129
    TAOS_RETURN(code);
×
4130
  }
4131

4132
  TAOS_RETURN(code);
155,524✔
4133
}
4134

4135
static int32_t mndProcessSetVgroupKeepVersionReq(SRpcMsg *pReq) {
2,280✔
4136
  SMnode *pMnode = pReq->info.node;
2,280✔
4137
  int32_t code = TSDB_CODE_SUCCESS;
2,280✔
4138
  STrans *pTrans = NULL;
2,280✔
4139
  SVgObj *pVgroup = NULL;
2,280✔
4140

4141
  SMndSetVgroupKeepVersionReq req = {0};
2,280✔
4142
  if (tDeserializeSMndSetVgroupKeepVersionReq(pReq->pCont, pReq->contLen, &req) != 0) {
2,280✔
UNCOV
4143
    code = TSDB_CODE_INVALID_MSG;
×
UNCOV
4144
    goto _OVER;
×
4145
  }
4146

4147
  mInfo("start to set vgroup keep version, vgId:%d, keepVersion:%" PRId64, req.vgId, req.keepVersion);
2,280✔
4148

4149
  // Check permission
4150
  if ((code = mndCheckOperPrivilege(pMnode, RPC_MSG_USER(pReq), RPC_MSG_TOKEN(pReq), MND_OPER_WRITE_DB)) != 0) {
2,280✔
UNCOV
4151
    goto _OVER;
×
4152
  }
4153

4154
  // Get vgroup
4155
  pVgroup = mndAcquireVgroup(pMnode, req.vgId);
2,280✔
4156
  if (pVgroup == NULL) {
2,280✔
UNCOV
4157
    code = TSDB_CODE_MND_VGROUP_NOT_EXIST;
×
UNCOV
4158
    mError("vgId:%d not exist, failed to set keep version", req.vgId);
×
4159
    goto _OVER;
×
4160
  }
4161

4162
  // Create transaction
4163
  pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, pReq, "set-vgroup-keep-version");
2,280✔
4164
  if (pTrans == NULL) {
2,280✔
UNCOV
4165
    code = terrno != 0 ? terrno : TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
4166
    mndReleaseVgroup(pMnode, pVgroup);
×
4167
    goto _OVER;
×
4168
  }
4169

4170
  mndTransSetSerial(pTrans);
2,280✔
4171
  mInfo("trans:%d, used to set vgroup keep version, vgId:%d keepVersion:%" PRId64, pTrans->id, req.vgId,
2,280✔
4172
        req.keepVersion);
4173

4174
  // Update SVgObj's keepVersion in mnode
4175
  SVgObj newVgroup = {0};
2,280✔
4176
  memcpy(&newVgroup, pVgroup, sizeof(SVgObj));
2,280✔
4177
  newVgroup.keepVersion = req.keepVersion;
2,280✔
4178
  newVgroup.keepVersionTime = taosGetTimestampMs();
2,280✔
4179

4180
  // Add prepare log for SDB vgroup update (execute in PREPARE stage, before redo actions)
4181
  SSdbRaw *pCommitRaw = mndVgroupActionEncode(&newVgroup);
2,280✔
4182
  if (pCommitRaw == NULL) {
2,280✔
UNCOV
4183
    code = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
4184
    mndReleaseVgroup(pMnode, pVgroup);
×
4185
    goto _OVER;
×
4186
  }
4187
  if (mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
2,280✔
UNCOV
4188
    code = terrno;
×
UNCOV
4189
    sdbFreeRaw(pCommitRaw);
×
4190
    mndReleaseVgroup(pMnode, pVgroup);
×
4191
    goto _OVER;
×
4192
  }
4193
  if ((code = sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY)) != 0) {
2,280✔
UNCOV
4194
    mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", pVgroup->vgId, tstrerror(code), __LINE__);
×
UNCOV
4195
    sdbFreeRaw(pCommitRaw);
×
4196
    mndReleaseVgroup(pMnode, pVgroup);
×
4197
    goto _OVER;
×
4198
  }
4199

4200
  // Prepare message for vnodes
4201
  SVndSetKeepVersionReq vndReq = {.keepVersion = req.keepVersion};
2,280✔
4202
  int32_t               reqLen = tSerializeSVndSetKeepVersionReq(NULL, 0, &vndReq);
2,280✔
4203
  int32_t               contLen = reqLen + sizeof(SMsgHead);
2,280✔
4204

4205
  // Send to all replicas of the vgroup
4206
  for (int32_t i = 0; i < pVgroup->replica; ++i) {
9,120✔
4207
    SMsgHead *pHead = taosMemoryMalloc(contLen);
6,840✔
4208
    if (pHead == NULL) {
6,840✔
UNCOV
4209
      code = TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
4210
      mndReleaseVgroup(pMnode, pVgroup);
×
4211
      goto _OVER;
×
4212
    }
4213

4214
    pHead->contLen = htonl(contLen);
6,840✔
4215
    pHead->vgId = htonl(pVgroup->vgId);
6,840✔
4216

4217
    if (tSerializeSVndSetKeepVersionReq((char *)pHead + sizeof(SMsgHead), reqLen, &vndReq) < 0) {
6,840✔
UNCOV
4218
      taosMemoryFree(pHead);
×
UNCOV
4219
      code = TSDB_CODE_OUT_OF_MEMORY;
×
4220
      mndReleaseVgroup(pMnode, pVgroup);
×
4221
      goto _OVER;
×
4222
    }
4223

4224
    // Get dnode and add action to transaction
4225
    SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgroup->vnodeGid[i].dnodeId);
6,840✔
4226
    if (pDnode == NULL) {
6,840✔
UNCOV
4227
      taosMemoryFree(pHead);
×
UNCOV
4228
      code = TSDB_CODE_MND_DNODE_NOT_EXIST;
×
4229
      mndReleaseVgroup(pMnode, pVgroup);
×
4230
      goto _OVER;
×
4231
    }
4232

4233
    STransAction action = {0};
6,840✔
4234
    action.epSet = mndGetDnodeEpset(pDnode);
6,840✔
4235
    mndReleaseDnode(pMnode, pDnode);
6,840✔
4236
    action.pCont = pHead;
6,840✔
4237
    action.contLen = contLen;
6,840✔
4238
    action.msgType = TDMT_VND_SET_KEEP_VERSION;
6,840✔
4239
    action.acceptableCode = TSDB_CODE_VND_STOPPED;
6,840✔
4240

4241
    if (mndTransAppendRedoAction(pTrans, &action) != 0) {
6,840✔
UNCOV
4242
      taosMemoryFree(pHead);
×
UNCOV
4243
      code = terrno;
×
4244
      mndReleaseVgroup(pMnode, pVgroup);
×
4245
      goto _OVER;
×
4246
    }
4247
  }
4248

4249
  mndReleaseVgroup(pMnode, pVgroup);
2,280✔
4250

4251
  // Prepare and execute transaction
4252
  if ((code = mndTransPrepare(pMnode, pTrans)) != 0) {
2,280✔
UNCOV
4253
    goto _OVER;
×
4254
  }
4255

4256
  code = TSDB_CODE_ACTION_IN_PROGRESS;
2,280✔
4257

4258
_OVER:
2,280✔
4259
  if (pTrans != NULL) mndTransDrop(pTrans);
2,280✔
4260

4261
  return code;
2,280✔
4262
}
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