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

taosdata / TDengine / #3548

04 Dec 2024 01:03PM UTC coverage: 59.846% (-0.8%) from 60.691%
#3548

push

travis-ci

web-flow
Merge pull request #29033 from taosdata/fix/calculate-vnode-memory-used

fix/calculate-vnode-memory-used

118484 of 254183 branches covered (46.61%)

Branch coverage included in aggregate %.

199691 of 277471 relevant lines covered (71.97%)

18794141.86 hits per line

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

60.68
/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 "mndMnode.h"
23
#include "mndPrivilege.h"
24
#include "mndShow.h"
25
#include "mndStb.h"
26
#include "mndStream.h"
27
#include "mndTopic.h"
28
#include "mndTrans.h"
29
#include "mndUser.h"
30
#include "tmisce.h"
31

32
#define VGROUP_VER_NUMBER   1
33
#define VGROUP_RESERVE_SIZE 64
34

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

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

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

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

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

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

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

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

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

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

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

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

118
  terrno = 0;
38,731✔
119

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

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

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

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

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

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

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

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

174
  SDB_GET_RESERVE(pRaw, dataPos, VGROUP_RESERVE_SIZE, _OVER)
33,215!
175

176
  terrno = 0;
33,215✔
177

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

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

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

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

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

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

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

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

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

261
SVgObj *mndAcquireVgroup(SMnode *pMnode, int32_t vgId) {
1,039,817✔
262
  SSdb   *pSdb = pMnode->pSdb;
1,039,817✔
263
  SVgObj *pVgroup = sdbAcquire(pSdb, SDB_VGROUP, &vgId);
1,039,817✔
264
  if (pVgroup == NULL && terrno == TSDB_CODE_SDB_OBJ_NOT_THERE) {
1,039,821✔
265
    terrno = TSDB_CODE_MND_VGROUP_NOT_EXIST;
5,810✔
266
  }
267
  return pVgroup;
1,039,821✔
268
}
269

270
void mndReleaseVgroup(SMnode *pMnode, SVgObj *pVgroup) {
1,035,387✔
271
  SSdb *pSdb = pMnode->pSdb;
1,035,387✔
272
  sdbRelease(pSdb, pVgroup);
1,035,387✔
273
}
1,035,391✔
274

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

325
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
21,736✔
326
    SReplica *pReplica = NULL;
12,278✔
327

328
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
12,278✔
329
      pReplica = &createReq.replicas[createReq.replica];
12,080✔
330
    } else {
331
      pReplica = &createReq.learnerReplicas[createReq.learnerReplica];
198✔
332
    }
333

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

340
    pReplica->id = pVgidDnode->id;
12,278✔
341
    pReplica->port = pVgidDnode->port;
12,278✔
342
    memcpy(pReplica->fqdn, pVgidDnode->fqdn, TSDB_FQDN_LEN);
12,278✔
343
    mndReleaseDnode(pMnode, pVgidDnode);
12,278✔
344

345
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
12,278✔
346
      if (pDnode->id == pVgid->dnodeId) {
12,080✔
347
        createReq.selfIndex = createReq.replica;
9,260✔
348
      }
349
    } else {
350
      if (pDnode->id == pVgid->dnodeId) {
198!
351
        createReq.learnerSelfIndex = createReq.learnerReplica;
198✔
352
      }
353
    }
354

355
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
12,278✔
356
      createReq.replica++;
12,080✔
357
    } else {
358
      createReq.learnerReplica++;
198✔
359
    }
360
  }
361

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

367
  createReq.changeVersion = pVgroup->syncConfChangeVer;
9,458✔
368

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

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

388
  void *pReq = taosMemoryMalloc(contLen);
9,458✔
389
  if (pReq == NULL) {
9,458!
390
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
391
    return NULL;
×
392
  }
393

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

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

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

436
  void *pReq = taosMemoryMalloc(contLen);
429✔
437
  if (pReq == NULL) {
429!
438
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
439
    return NULL;
×
440
  }
441

442
  SMsgHead *pHead = pReq;
429✔
443
  pHead->contLen = htonl(contLen);
429✔
444
  pHead->vgId = htonl(pVgroup->vgId);
429✔
445

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

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

468
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
5,592✔
469
    SReplica *pReplica = NULL;
4,195✔
470

471
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
4,195✔
472
      pReplica = &alterReq.replicas[alterReq.replica];
3,863✔
473
      alterReq.replica++;
3,863✔
474
    } else {
475
      pReplica = &alterReq.learnerReplicas[alterReq.learnerReplica];
332✔
476
      alterReq.learnerReplica++;
332✔
477
    }
478

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

483
    pReplica->id = pVgidDnode->id;
4,195✔
484
    pReplica->port = pVgidDnode->port;
4,195✔
485
    memcpy(pReplica->fqdn, pVgidDnode->fqdn, TSDB_FQDN_LEN);
4,195✔
486
    mndReleaseDnode(pMnode, pVgidDnode);
4,195✔
487

488
    if (pVgroup->vnodeGid[v].nodeRole == TAOS_SYNC_ROLE_VOTER) {
4,195✔
489
      if (dnodeId == pVgid->dnodeId) {
3,863✔
490
        alterReq.selfIndex = v;
1,397✔
491
      }
492
    } else {
493
      if (dnodeId == pVgid->dnodeId) {
332!
494
        alterReq.learnerSelfIndex = v;
×
495
      }
496
    }
497
  }
498

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

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

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

523
  void *pReq = taosMemoryMalloc(contLen);
1,397✔
524
  if (pReq == NULL) {
1,397!
525
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
526
    return NULL;
×
527
  }
528

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

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

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

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

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

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

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

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

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

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

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

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

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

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

630
  void *pReq = taosMemoryMalloc(contLen);
60✔
631
  if (pReq == NULL) {
60!
632
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
633
    return NULL;
×
634
  }
635

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

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

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

663
  void *pReq = taosMemoryMalloc(contLen);
60✔
664
  if (pReq == NULL) {
60!
665
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
666
    return NULL;
×
667
  }
668

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

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

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

693
  void *pReq = taosMemoryMalloc(contLen);
13,643✔
694
  if (pReq == NULL) {
13,643!
695
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
696
    return NULL;
×
697
  }
698

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

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

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

722
  if (exceptDnodeId == pDnode->id) {
5,809✔
723
    return true;
16✔
724
  }
725

726
  if (dnodeList != NULL) {
5,793✔
727
    int32_t dnodeListSize = taosArrayGetSize(dnodeList);
5,291✔
728
    if (dnodeListSize > 0) {
5,291✔
729
      bool inDnodeList = false;
95✔
730
      for (int32_t index = 0; index < dnodeListSize; ++index) {
310✔
731
        int32_t dnodeId = *(int32_t *)taosArrayGet(dnodeList, index);
215✔
732
        if (pDnode->id == dnodeId) {
215✔
733
          inDnodeList = true;
43✔
734
        }
735
      }
736
      if (!inDnodeList) {
95✔
737
        return true;
52✔
738
      }
739
    }
740
  }
741

742
  int64_t curMs = taosGetTimestampMs();
5,741✔
743
  bool    online = mndIsDnodeOnline(pDnode, curMs);
5,741✔
744
  bool    isMnode = mndIsMnode(pMnode, pDnode->id);
5,741✔
745
  pDnode->numOfVnodes = mndGetVnodesNum(pMnode, pDnode->id);
5,741✔
746
  pDnode->memUsed = mndGetVnodesMemory(pMnode, pDnode->id);
5,741✔
747

748
  mInfo("dnode:%d, vnodes:%d supportVnodes:%d isMnode:%d online:%d memory avail:%" PRId64 " used:%" PRId64, pDnode->id,
5,741!
749
        pDnode->numOfVnodes, pDnode->numOfSupportVnodes, isMnode, online, pDnode->memAvail, pDnode->memUsed);
750

751
  if (isMnode) {
5,741✔
752
    pDnode->numOfOtherNodes++;
4,711✔
753
  }
754

755
  if (online && pDnode->numOfSupportVnodes > 0) {
5,741✔
756
    if (taosArrayPush(pArray, pDnode) == NULL) return false;
5,134!
757
  }
758
  return true;
5,741✔
759
}
760

761
SArray *mndBuildDnodesArray(SMnode *pMnode, int32_t exceptDnodeId, SArray *dnodeList) {
4,468✔
762
  SSdb   *pSdb = pMnode->pSdb;
4,468✔
763
  int32_t numOfDnodes = mndGetDnodeSize(pMnode);
4,468✔
764

765
  SArray *pArray = taosArrayInit(numOfDnodes, sizeof(SDnodeObj));
4,468✔
766
  if (pArray == NULL) {
4,468!
767
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
768
    return NULL;
×
769
  }
770

771
  sdbTraverse(pSdb, SDB_DNODE, mndResetDnodesArrayFp, NULL, NULL, NULL);
4,468✔
772
  sdbTraverse(pSdb, SDB_DNODE, mndBuildDnodesArrayFp, pArray, &exceptDnodeId, dnodeList);
4,468✔
773

774
  mDebug("build %d dnodes array", (int32_t)taosArrayGetSize(pArray));
4,468✔
775
  for (int32_t i = 0; i < (int32_t)taosArrayGetSize(pArray); ++i) {
9,602✔
776
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
5,134✔
777
    mDebug("dnode:%d, vnodes:%d others:%d", pDnode->id, pDnode->numOfVnodes, pDnode->numOfOtherNodes);
5,134✔
778
  }
779
  return pArray;
4,468✔
780
}
781

782
static int32_t mndCompareDnodeId(int32_t *dnode1Id, int32_t *dnode2Id) {
×
783
  if (*dnode1Id == *dnode2Id) {
×
784
    return 0;
×
785
  }
786
  return *dnode1Id > *dnode2Id ? 1 : -1;
×
787
}
788

789
static float mndGetDnodeScore(SDnodeObj *pDnode, int32_t additionDnodes, float ratio) {
18,013✔
790
  float totalDnodes = pDnode->numOfVnodes + (float)pDnode->numOfOtherNodes * ratio + additionDnodes;
18,013✔
791
  return totalDnodes / pDnode->numOfSupportVnodes;
18,013✔
792
}
793

794
static int32_t mndCompareDnodeVnodes(SDnodeObj *pDnode1, SDnodeObj *pDnode2) {
4,414✔
795
  float d1Score = mndGetDnodeScore(pDnode1, 0, 0.9);
4,414✔
796
  float d2Score = mndGetDnodeScore(pDnode2, 0, 0.9);
4,414✔
797
  if (d1Score == d2Score) {
4,414✔
798
    return 0;
1,666✔
799
  }
800
  return d1Score > d2Score ? 1 : -1;
2,748✔
801
}
802

803
void mndSortVnodeGid(SVgObj *pVgroup) {
8,474✔
804
  for (int32_t i = 0; i < pVgroup->replica; ++i) {
17,830✔
805
    for (int32_t j = 0; j < pVgroup->replica - 1 - i; ++j) {
10,676✔
806
      if (pVgroup->vnodeGid[j].dnodeId > pVgroup->vnodeGid[j + 1].dnodeId) {
1,320✔
807
        TSWAP(pVgroup->vnodeGid[j], pVgroup->vnodeGid[j + 1]);
444✔
808
      }
809
    }
810
  }
811
}
8,474✔
812

813
static int32_t mndGetAvailableDnode(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, SArray *pArray) {
8,877✔
814
  mDebug("start to sort %d dnodes", (int32_t)taosArrayGetSize(pArray));
8,877✔
815
  taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
8,877✔
816
  for (int32_t i = 0; i < (int32_t)taosArrayGetSize(pArray); ++i) {
19,801✔
817
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
10,924✔
818
    mDebug("dnode:%d, score:%f", pDnode->id, mndGetDnodeScore(pDnode, 0, 0.9));
10,924✔
819
  }
820

821
  int32_t size = taosArrayGetSize(pArray);
8,877✔
822
  if (size < pVgroup->replica) {
8,877✔
823
    mError("db:%s, vgId:%d, no enough online dnodes:%d to alloc %d replica", pVgroup->dbName, pVgroup->vgId, size,
451!
824
           pVgroup->replica);
825
    TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_DNODES);
451✔
826
  }
827

828
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
17,646✔
829
    SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
9,220✔
830
    SDnodeObj *pDnode = taosArrayGet(pArray, v);
9,220✔
831
    if (pDnode == NULL) {
9,220!
832
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_DNODES);
×
833
    }
834
    if (pDnode->numOfVnodes >= pDnode->numOfSupportVnodes) {
9,220!
835
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_VNODES);
×
836
    }
837

838
    int64_t vgMem = mndGetVgroupMemory(pMnode, pDb, pVgroup);
9,220✔
839
    if (pDnode->memAvail - vgMem - pDnode->memUsed <= 0) {
9,220!
840
      mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d, avail:%" PRId64 " used:%" PRId64,
×
841
             pVgroup->dbName, pVgroup->vgId, vgMem, pDnode->id, pDnode->memAvail, pDnode->memUsed);
842
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE);
×
843
    } else {
844
      pDnode->memUsed += vgMem;
9,220✔
845
    }
846

847
    pVgid->dnodeId = pDnode->id;
9,220✔
848
    if (pVgroup->replica == 1) {
9,220✔
849
      pVgid->syncState = TAOS_SYNC_STATE_LEADER;
8,026✔
850
    } else {
851
      pVgid->syncState = TAOS_SYNC_STATE_FOLLOWER;
1,194✔
852
    }
853

854
    mInfo("db:%s, vgId:%d, vn:%d is alloced, memory:%" PRId64 ", dnode:%d avail:%" PRId64 " used:%" PRId64,
9,220!
855
          pVgroup->dbName, pVgroup->vgId, v, vgMem, pVgid->dnodeId, pDnode->memAvail, pDnode->memUsed);
856
    pDnode->numOfVnodes++;
9,220✔
857
  }
858

859
  mndSortVnodeGid(pVgroup);
8,426✔
860
  return 0;
8,426✔
861
}
862

863
int32_t mndAllocSmaVgroup(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup) {
29✔
864
  int32_t code = 0;
29✔
865
  SArray *pArray = mndBuildDnodesArray(pMnode, 0, NULL);
29✔
866
  if (pArray == NULL) {
29!
867
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
868
    if (terrno != 0) code = terrno;
×
869
    TAOS_RETURN(code);
×
870
  }
871

872
  pVgroup->vgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP);
29✔
873
  pVgroup->isTsma = 1;
29✔
874
  pVgroup->createdTime = taosGetTimestampMs();
29✔
875
  pVgroup->updateTime = pVgroup->createdTime;
29✔
876
  pVgroup->version = 1;
29✔
877
  memcpy(pVgroup->dbName, pDb->name, TSDB_DB_FNAME_LEN);
29✔
878
  pVgroup->dbUid = pDb->uid;
29✔
879
  pVgroup->replica = 1;
29✔
880

881
  if (mndGetAvailableDnode(pMnode, pDb, pVgroup, pArray) != 0) return -1;
29!
882
  taosArrayDestroy(pArray);
29✔
883

884
  mInfo("db:%s, sma vgId:%d is alloced", pDb->name, pVgroup->vgId);
29!
885
  return 0;
29✔
886
}
887

888
int32_t mndAllocVgroup(SMnode *pMnode, SDbObj *pDb, SVgObj **ppVgroups, SArray *dnodeList) {
4,196✔
889
  int32_t code = -1;
4,196✔
890
  SArray *pArray = NULL;
4,196✔
891
  SVgObj *pVgroups = NULL;
4,196✔
892

893
  pVgroups = taosMemoryCalloc(pDb->cfg.numOfVgroups, sizeof(SVgObj));
4,196✔
894
  if (pVgroups == NULL) {
4,196!
895
    code = terrno;
×
896
    goto _OVER;
×
897
  }
898

899
  pArray = mndBuildDnodesArray(pMnode, 0, dnodeList);
4,196✔
900
  if (pArray == NULL) {
4,196!
901
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
902
    if (terrno != 0) code = terrno;
×
903
    goto _OVER;
×
904
  }
905

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

909
  int32_t  allocedVgroups = 0;
4,196✔
910
  int32_t  maxVgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP);
4,196✔
911
  uint32_t hashMin = 0;
4,196✔
912
  uint32_t hashMax = UINT32_MAX;
4,196✔
913
  uint32_t hashInterval = (hashMax - hashMin) / pDb->cfg.numOfVgroups;
4,196✔
914

915
  if (maxVgId < 2) maxVgId = 2;
4,196✔
916

917
  for (uint32_t v = 0; v < pDb->cfg.numOfVgroups; v++) {
12,593✔
918
    SVgObj *pVgroup = &pVgroups[v];
8,848✔
919
    pVgroup->vgId = maxVgId++;
8,848✔
920
    pVgroup->createdTime = taosGetTimestampMs();
8,848✔
921
    pVgroup->updateTime = pVgroups->createdTime;
8,848✔
922
    pVgroup->version = 1;
8,848✔
923
    pVgroup->hashBegin = hashMin + hashInterval * v;
8,848✔
924
    if (v == pDb->cfg.numOfVgroups - 1) {
8,848✔
925
      pVgroup->hashEnd = hashMax;
3,838✔
926
    } else {
927
      pVgroup->hashEnd = hashMin + hashInterval * (v + 1) - 1;
5,010✔
928
    }
929

930
    memcpy(pVgroup->dbName, pDb->name, TSDB_DB_FNAME_LEN);
8,848✔
931
    pVgroup->dbUid = pDb->uid;
8,848✔
932
    pVgroup->replica = pDb->cfg.replications;
8,848✔
933

934
    if ((code = mndGetAvailableDnode(pMnode, pDb, pVgroup, pArray)) != 0) {
8,848✔
935
      goto _OVER;
451✔
936
    }
937

938
    allocedVgroups++;
8,397✔
939
  }
940

941
  *ppVgroups = pVgroups;
3,745✔
942
  code = 0;
3,745✔
943

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

946
_OVER:
×
947
  if (code != 0) taosMemoryFree(pVgroups);
4,196✔
948
  taosArrayDestroy(pArray);
4,196✔
949
  TAOS_RETURN(code);
4,196✔
950
}
951

952
SEpSet mndGetVgroupEpset(SMnode *pMnode, const SVgObj *pVgroup) {
451,004✔
953
  SEpSet epset = {0};
451,004✔
954

955
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
923,848✔
956
    const SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
472,844✔
957
    SDnodeObj       *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
472,844✔
958
    if (pDnode == NULL) continue;
472,844✔
959

960
    if (pVgid->syncState == TAOS_SYNC_STATE_LEADER || pVgid->syncState == TAOS_SYNC_STATE_ASSIGNED_LEADER) {
472,683!
961
      epset.inUse = epset.numOfEps;
449,379✔
962
    }
963

964
    if (addEpIntoEpSet(&epset, pDnode->fqdn, pDnode->port) != 0) {
472,683!
965
      mWarn("vgId:%d, failed to add ep:%s:%d into epset", pVgroup->vgId, pDnode->fqdn, pDnode->port);
×
966
    }
967
    mndReleaseDnode(pMnode, pDnode);
472,683✔
968
  }
969
  epsetSort(&epset);
451,004✔
970

971
  return epset;
451,004✔
972
}
973

974
SEpSet mndGetVgroupEpsetById(SMnode *pMnode, int32_t vgId) {
×
975
  SEpSet epset = {0};
×
976

977
  SVgObj *pVgroup = mndAcquireVgroup(pMnode, vgId);
×
978
  if (!pVgroup) return epset;
×
979

980
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
×
981
    const SVnodeGid *pVgid = &pVgroup->vnodeGid[v];
×
982
    SDnodeObj       *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
×
983
    if (pDnode == NULL) continue;
×
984

985
    if (pVgid->syncState == TAOS_SYNC_STATE_LEADER || pVgid->syncState == TAOS_SYNC_STATE_ASSIGNED_LEADER) {
×
986
      epset.inUse = epset.numOfEps;
×
987
    }
988

989
    if (addEpIntoEpSet(&epset, pDnode->fqdn, pDnode->port) != 0) {
×
990
      mWarn("vgId:%d, failed to add ep:%s:%d into epset", pVgroup->vgId, pDnode->fqdn, pDnode->port);
×
991
    }
992
    mndReleaseDnode(pMnode, pDnode);
×
993
  }
994

995
  mndReleaseVgroup(pMnode, pVgroup);
×
996
  return epset;
×
997
}
998

999
static int32_t mndRetrieveVgroups(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
10,622✔
1000
  SMnode *pMnode = pReq->info.node;
10,622✔
1001
  SSdb   *pSdb = pMnode->pSdb;
10,622✔
1002
  int32_t numOfRows = 0;
10,622✔
1003
  SVgObj *pVgroup = NULL;
10,622✔
1004
  int32_t cols = 0;
10,622✔
1005
  int64_t curMs = taosGetTimestampMs();
10,625✔
1006
  int32_t code = 0;
10,625✔
1007

1008
  SDbObj *pDb = NULL;
10,625✔
1009
  if (strlen(pShow->db) > 0) {
10,625✔
1010
    pDb = mndAcquireDb(pMnode, pShow->db);
517✔
1011
    if (pDb == NULL) {
517!
1012
      return 0;
×
1013
    }
1014
  }
1015

1016
  while (numOfRows < rows) {
506,137!
1017
    pShow->pIter = sdbFetch(pSdb, SDB_VGROUP, pShow->pIter, (void **)&pVgroup);
506,159✔
1018
    if (pShow->pIter == NULL) break;
505,800✔
1019

1020
    if (pDb != NULL && pVgroup->dbUid != pDb->uid) {
495,171✔
1021
      sdbRelease(pSdb, pVgroup);
75✔
1022
      continue;
75✔
1023
    }
1024

1025
    cols = 0;
495,096✔
1026
    SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
495,096✔
1027
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->vgId, false);
494,463✔
1028
    if (code != 0) {
493,457!
1029
      mError("vgId:%d, failed to set vgId, since %s", pVgroup->vgId, tstrerror(code));
×
1030
      return code;
×
1031
    }
1032

1033
    SName name = {0};
493,457✔
1034
    char  db[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
493,457✔
1035
    code = tNameFromString(&name, pVgroup->dbName, T_NAME_ACCT | T_NAME_DB);
493,457✔
1036
    if (code != 0) {
494,649!
1037
      mError("vgId:%d, failed to set dbName, since %s", pVgroup->vgId, tstrerror(code));
×
1038
      return code;
×
1039
    }
1040
    (void)tNameGetDbName(&name, varDataVal(db));
494,649✔
1041
    varDataSetLen(db, strlen(varDataVal(db)));
494,667✔
1042

1043
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
494,667✔
1044
    code = colDataSetVal(pColInfo, numOfRows, (const char *)db, false);
494,154✔
1045
    if (code != 0) {
492,064!
1046
      mError("vgId:%d, failed to set dbName, since %s", pVgroup->vgId, tstrerror(code));
×
1047
      return code;
×
1048
    }
1049

1050
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
492,064✔
1051
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->numOfTables, false);
491,530✔
1052
    if (code != 0) {
490,541!
1053
      mError("vgId:%d, failed to set numOfTables, since %s", pVgroup->vgId, tstrerror(code));
×
1054
      return code;
×
1055
    }
1056

1057
    // default 3 replica, add 1 replica if move vnode
1058
    for (int32_t i = 0; i < 4; ++i) {
2,433,312✔
1059
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,912,974✔
1060
      if (i < pVgroup->replica) {
1,906,676✔
1061
        int16_t dnodeId = (int16_t)pVgroup->vnodeGid[i].dnodeId;
452,206✔
1062
        code = colDataSetVal(pColInfo, numOfRows, (const char *)&dnodeId, false);
452,206✔
1063
        if (code != 0) {
490,767!
1064
          mError("vgId:%d, failed to set dnodeId, since %s", pVgroup->vgId, tstrerror(code));
×
1065
          return code;
×
1066
        }
1067

1068
        bool       exist = false;
490,767✔
1069
        bool       online = false;
490,767✔
1070
        SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgroup->vnodeGid[i].dnodeId);
490,767✔
1071
        if (pDnode != NULL) {
495,937!
1072
          exist = true;
495,946✔
1073
          online = mndIsDnodeOnline(pDnode, curMs);
495,946✔
1074
          mndReleaseDnode(pMnode, pDnode);
495,496✔
1075
        }
1076

1077
        char buf1[20] = {0};
496,704✔
1078
        char role[20] = "offline";
496,704✔
1079
        if (!exist) {
496,704!
1080
          strcpy(role, "dropping");
×
1081
        } else if (online) {
496,704✔
1082
          char *star = "";
496,566✔
1083
          if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_LEADER ||
496,566✔
1084
              pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_ASSIGNED_LEADER) {
1,262!
1085
            if (!pVgroup->vnodeGid[i].syncRestore && !pVgroup->vnodeGid[i].syncCanRead) {
495,304!
1086
              star = "**";
279✔
1087
            } else if (!pVgroup->vnodeGid[i].syncRestore && pVgroup->vnodeGid[i].syncCanRead) {
495,025!
1088
              star = "*";
×
1089
            } else {
1090
            }
1091
          }
1092
          snprintf(role, sizeof(role), "%s%s", syncStr(pVgroup->vnodeGid[i].syncState), star);
496,566✔
1093
          /*
1094
          mInfo("db:%s, learner progress:%d", pDb->name, pVgroup->vnodeGid[i].learnerProgress);
1095

1096
          if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_LEARNER) {
1097
            if(pVgroup->vnodeGid[i].learnerProgress < 0){
1098
              snprintf(role, sizeof(role), "%s-",
1099
                syncStr(pVgroup->vnodeGid[i].syncState));
1100

1101
            }
1102
            else if(pVgroup->vnodeGid[i].learnerProgress >= 100){
1103
              snprintf(role, sizeof(role), "%s--",
1104
                syncStr(pVgroup->vnodeGid[i].syncState));
1105
            }
1106
            else{
1107
              snprintf(role, sizeof(role), "%s%d",
1108
                syncStr(pVgroup->vnodeGid[i].syncState), pVgroup->vnodeGid[i].learnerProgress);
1109
            }
1110
          }
1111
          else{
1112
            snprintf(role, sizeof(role), "%s%s", syncStr(pVgroup->vnodeGid[i].syncState), star);
1113
          }
1114
          */
1115
        } else {
1116
        }
1117
        STR_WITH_MAXSIZE_TO_VARSTR(buf1, role, pShow->pMeta->pSchemas[cols].bytes);
496,665✔
1118

1119
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
496,665✔
1120
        code = colDataSetVal(pColInfo, numOfRows, (const char *)buf1, false);
495,684✔
1121
        if (code != 0) {
493,429!
1122
          mError("vgId:%d, failed to set role, since %s", pVgroup->vgId, tstrerror(code));
×
1123
          return code;
×
1124
        }
1125
      } else {
1126
        colDataSetNULL(pColInfo, numOfRows);
1,454,470✔
1127
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,454,470✔
1128
        colDataSetNULL(pColInfo, numOfRows);
1,449,342!
1129
      }
1130
    }
1131

1132
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
520,338✔
1133
    int32_t cacheUsage = (int32_t)pVgroup->cacheUsage;
488,008✔
1134
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&cacheUsage, false);
488,008✔
1135
    if (code != 0) {
490,964!
1136
      mError("vgId:%d, failed to set cacheUsage, since %s", pVgroup->vgId, tstrerror(code));
×
1137
      return code;
×
1138
    }
1139

1140
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
490,964✔
1141
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->numOfCachedTables, false);
490,058✔
1142
    if (code != 0) {
489,052!
1143
      mError("vgId:%d, failed to set numOfCachedTables, since %s", pVgroup->vgId, tstrerror(code));
×
1144
      return code;
×
1145
    }
1146

1147
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
489,052✔
1148
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->isTsma, false);
488,188✔
1149
    if (code != 0) {
487,528!
1150
      mError("vgId:%d, failed to set isTsma, since %s", pVgroup->vgId, tstrerror(code));
×
1151
      return code;
×
1152
    }
1153
    numOfRows++;
487,528✔
1154
    sdbRelease(pSdb, pVgroup);
487,528✔
1155
  }
1156

1157
  if (pDb != NULL) {
10,607✔
1158
    mndReleaseDb(pMnode, pDb);
517✔
1159
  }
1160

1161
  pShow->numOfRows += numOfRows;
10,629✔
1162
  return numOfRows;
10,629✔
1163
}
1164

1165
static void mndCancelGetNextVgroup(SMnode *pMnode, void *pIter) {
×
1166
  SSdb *pSdb = pMnode->pSdb;
×
1167
  sdbCancelFetchByType(pSdb, pIter, SDB_VGROUP);
×
1168
}
×
1169

1170
static bool mndGetVnodesNumFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
334,033✔
1171
  SVgObj  *pVgroup = pObj;
334,033✔
1172
  int32_t  dnodeId = *(int32_t *)p1;
334,033✔
1173
  int32_t *pNumOfVnodes = (int32_t *)p2;
334,033✔
1174

1175
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
679,641✔
1176
    if (pVgroup->vnodeGid[v].dnodeId == dnodeId) {
345,608✔
1177
      (*pNumOfVnodes)++;
326,935✔
1178
    }
1179
  }
1180

1181
  return true;
334,033✔
1182
}
1183

1184
int32_t mndGetVnodesNum(SMnode *pMnode, int32_t dnodeId) {
15,292✔
1185
  int32_t numOfVnodes = 0;
15,292✔
1186
  sdbTraverse(pMnode->pSdb, SDB_VGROUP, mndGetVnodesNumFp, &dnodeId, &numOfVnodes, NULL);
15,292✔
1187
  return numOfVnodes;
15,315✔
1188
}
1189

1190
int64_t mndGetVgroupMemory(SMnode *pMnode, SDbObj *pDbInput, SVgObj *pVgroup) {
33,598✔
1191
  SDbObj *pDb = pDbInput;
33,598✔
1192
  if (pDbInput == NULL) {
33,598✔
1193
    pDb = mndAcquireDb(pMnode, pVgroup->dbName);
23,104✔
1194
  }
1195

1196
  int64_t vgroupMemroy = 0;
33,598✔
1197
  if (pDb != NULL) {
33,598✔
1198
    int64_t buffer = (int64_t)pDb->cfg.buffer * 1024 * 1024;
33,592✔
1199
    int64_t cache = (int64_t)pDb->cfg.pages * pDb->cfg.pageSize * 1024;
33,592✔
1200
    vgroupMemroy = buffer + cache;
33,592✔
1201
    int64_t cacheLast = (int64_t)pDb->cfg.cacheLastSize * 1024 * 1024;
33,592✔
1202
    if (pDb->cfg.cacheLast > 0) {
33,592✔
1203
      vgroupMemroy += cacheLast;
9,481✔
1204
    }
1205
    mDebug("db:%s, vgroup:%d, buffer:%" PRId64 " cache:%" PRId64 " cacheLast:%" PRId64, pDb->name, pVgroup->vgId,
33,592✔
1206
           buffer, cache, cacheLast);
1207
  }
1208

1209
  if (pDbInput == NULL) {
33,598✔
1210
    mndReleaseDb(pMnode, pDb);
23,104✔
1211
  }
1212
  return vgroupMemroy;
33,598✔
1213
}
1214

1215
static bool mndGetVnodeMemroyFp(SMnode *pMnode, void *pObj, void *p1, void *p2, void *p3) {
26,281✔
1216
  SVgObj  *pVgroup = pObj;
26,281✔
1217
  int32_t  dnodeId = *(int32_t *)p1;
26,281✔
1218
  int64_t *pVnodeMemory = (int64_t *)p2;
26,281✔
1219

1220
  for (int32_t v = 0; v < pVgroup->replica; ++v) {
58,544✔
1221
    if (pVgroup->vnodeGid[v].dnodeId == dnodeId) {
32,263✔
1222
      *pVnodeMemory += mndGetVgroupMemory(pMnode, NULL, pVgroup);
22,835✔
1223
    }
1224
  }
1225

1226
  return true;
26,281✔
1227
}
1228

1229
int64_t mndGetVnodesMemory(SMnode *pMnode, int32_t dnodeId) {
5,741✔
1230
  int64_t vnodeMemory = 0;
5,741✔
1231
  sdbTraverse(pMnode->pSdb, SDB_VGROUP, mndGetVnodeMemroyFp, &dnodeId, &vnodeMemory, NULL);
5,741✔
1232
  return vnodeMemory;
5,741✔
1233
}
1234

1235
static int32_t mndRetrieveVnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
5,174✔
1236
  SMnode *pMnode = pReq->info.node;
5,174✔
1237
  SSdb   *pSdb = pMnode->pSdb;
5,174✔
1238
  int32_t numOfRows = 0;
5,174✔
1239
  SVgObj *pVgroup = NULL;
5,174✔
1240
  int32_t cols = 0;
5,174✔
1241
  int64_t curMs = taosGetTimestampMs();
5,174✔
1242
  int32_t code = 0;
5,174✔
1243

1244
  while (numOfRows < rows - TSDB_MAX_REPLICA) {
252,473!
1245
    pShow->pIter = sdbFetch(pSdb, SDB_VGROUP, pShow->pIter, (void **)&pVgroup);
252,473✔
1246
    if (pShow->pIter == NULL) break;
252,296✔
1247

1248
    for (int32_t i = 0; i < pVgroup->replica && numOfRows < rows; ++i) {
494,568!
1249
      SVnodeGid       *pGid = &pVgroup->vnodeGid[i];
247,291✔
1250
      SColumnInfoData *pColInfo = NULL;
247,291✔
1251
      cols = 0;
247,291✔
1252

1253
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
247,291✔
1254
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&pGid->dnodeId, false);
247,159✔
1255
      if (code != 0) {
246,794!
1256
        mError("vgId:%d, failed to set dnodeId, since %s", pVgroup->vgId, tstrerror(code));
×
1257
        return code;
×
1258
      }
1259
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
246,794✔
1260
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->vgId, false);
246,685✔
1261
      if (code != 0) {
246,340!
1262
        mError("vgId:%d, failed to set vgId, since %s", pVgroup->vgId, tstrerror(code));
×
1263
        return code;
×
1264
      }
1265

1266
      // db_name
1267
      const char *dbname = mndGetDbStr(pVgroup->dbName);
246,340✔
1268
      char        b1[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
246,366✔
1269
      if (dbname != NULL) {
246,366!
1270
        STR_WITH_MAXSIZE_TO_VARSTR(b1, dbname, TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE);
246,847✔
1271
      } else {
1272
        STR_WITH_MAXSIZE_TO_VARSTR(b1, "NULL", TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE);
×
1273
      }
1274
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
246,366✔
1275
      code = colDataSetVal(pColInfo, numOfRows, (const char *)b1, false);
246,583✔
1276
      if (code != 0) {
246,331!
1277
        mError("vgId:%d, failed to set dbName, since %s", pVgroup->vgId, tstrerror(code));
×
1278
        return code;
×
1279
      }
1280

1281
      // dnode is online?
1282
      SDnodeObj *pDnode = mndAcquireDnode(pMnode, pGid->dnodeId);
246,331✔
1283
      if (pDnode == NULL) {
247,210!
1284
        mError("failed to acquire dnode. dnodeId:%d", pGid->dnodeId);
×
1285
        break;
×
1286
      }
1287
      bool isDnodeOnline = mndIsDnodeOnline(pDnode, curMs);
247,210✔
1288

1289
      char       buf[20] = {0};
246,971✔
1290
      ESyncState syncState = (isDnodeOnline) ? pGid->syncState : TAOS_SYNC_STATE_OFFLINE;
246,971✔
1291
      STR_TO_VARSTR(buf, syncStr(syncState));
246,971✔
1292
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
246,691✔
1293
      code = colDataSetVal(pColInfo, numOfRows, (const char *)buf, false);
246,362✔
1294
      if (code != 0) {
245,554!
1295
        mError("vgId:%d, failed to set syncState, since %s", pVgroup->vgId, tstrerror(code));
×
1296
        return code;
×
1297
      }
1298

1299
      int64_t roleTimeMs = (isDnodeOnline) ? pGid->roleTimeMs : 0;
245,554✔
1300
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
245,554✔
1301
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&roleTimeMs, false);
245,363✔
1302
      if (code != 0) {
244,947!
1303
        mError("vgId:%d, failed to set roleTimeMs, since %s", pVgroup->vgId, tstrerror(code));
×
1304
        return code;
×
1305
      }
1306

1307
      int64_t startTimeMs = (isDnodeOnline) ? pGid->startTimeMs : 0;
244,947✔
1308
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
244,947✔
1309
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&startTimeMs, false);
244,818✔
1310
      if (code != 0) {
244,485!
1311
        mError("vgId:%d, failed to set startTimeMs, since %s", pVgroup->vgId, tstrerror(code));
×
1312
        return code;
×
1313
      }
1314

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

1322
      numOfRows++;
244,195✔
1323
      sdbRelease(pSdb, pDnode);
244,195✔
1324
    }
1325

1326
    sdbRelease(pSdb, pVgroup);
247,277✔
1327
  }
1328

1329
  pShow->numOfRows += numOfRows;
5,177✔
1330
  return numOfRows;
5,177✔
1331
}
1332

1333
static void mndCancelGetNextVnode(SMnode *pMnode, void *pIter) {
×
1334
  SSdb *pSdb = pMnode->pSdb;
×
1335
  sdbCancelFetchByType(pSdb, pIter, SDB_VGROUP);
×
1336
}
×
1337

1338
static int32_t mndAddVnodeToVgroup(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup, SArray *pArray) {
150✔
1339
  int32_t code = 0;
150✔
1340
  taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
150✔
1341
  for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
589✔
1342
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
439✔
1343
    mInfo("dnode:%d, equivalent vnodes:%d others:%d", pDnode->id, pDnode->numOfVnodes, pDnode->numOfOtherNodes);
439!
1344
  }
1345

1346
  SVnodeGid *pVgid = &pVgroup->vnodeGid[pVgroup->replica];
150✔
1347
  for (int32_t d = 0; d < taosArrayGetSize(pArray); ++d) {
188✔
1348
    SDnodeObj *pDnode = taosArrayGet(pArray, d);
177✔
1349

1350
    bool used = false;
177✔
1351
    for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
413✔
1352
      if (pDnode->id == pVgroup->vnodeGid[vn].dnodeId) {
274✔
1353
        used = true;
38✔
1354
        break;
38✔
1355
      }
1356
    }
1357
    if (used) continue;
177✔
1358

1359
    if (pDnode == NULL) {
139!
1360
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_DNODES);
×
1361
    }
1362
    if (pDnode->numOfVnodes >= pDnode->numOfSupportVnodes) {
139!
1363
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_VNODES);
×
1364
    }
1365

1366
    int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
139✔
1367
    if (pDnode->memAvail - vgMem - pDnode->memUsed <= 0) {
139!
1368
      mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
×
1369
             pVgroup->dbName, pVgroup->vgId, vgMem, pDnode->id, pDnode->memAvail, pDnode->memUsed);
1370
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE);
×
1371
    } else {
1372
      pDnode->memUsed += vgMem;
139✔
1373
    }
1374

1375
    pVgid->dnodeId = pDnode->id;
139✔
1376
    pVgid->syncState = TAOS_SYNC_STATE_OFFLINE;
139✔
1377
    mInfo("db:%s, vgId:%d, vn:%d is added, memory:%" PRId64 ", dnode:%d avail:%" PRId64 " used:%" PRId64,
139!
1378
          pVgroup->dbName, pVgroup->vgId, pVgroup->replica, vgMem, pVgid->dnodeId, pDnode->memAvail, pDnode->memUsed);
1379

1380
    pVgroup->replica++;
139✔
1381
    pDnode->numOfVnodes++;
139✔
1382

1383
    SSdbRaw *pVgRaw = mndVgroupActionEncode(pVgroup);
139✔
1384
    if (pVgRaw == NULL) {
139!
1385
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1386
      if (terrno != 0) code = terrno;
×
1387
      TAOS_RETURN(code);
×
1388
    }
1389
    if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
139!
1390
      sdbFreeRaw(pVgRaw);
×
1391
      TAOS_RETURN(code);
×
1392
    }
1393
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
139✔
1394
    if (code != 0) {
139!
1395
      mError("vgId:%d, failed to set raw status since %s at line:%d", pVgroup->vgId, tstrerror(code), __LINE__);
×
1396
    }
1397
    TAOS_RETURN(code);
139✔
1398
  }
1399

1400
  code = TSDB_CODE_MND_NO_ENOUGH_DNODES;
11✔
1401
  mError("db:%s, failed to add vnode to vgId:%d since %s", pVgroup->dbName, pVgroup->vgId, tstrerror(code));
11!
1402
  TAOS_RETURN(code);
11✔
1403
}
1404

1405
static int32_t mndRemoveVnodeFromVgroup(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup, SArray *pArray,
29✔
1406
                                        SVnodeGid *pDelVgid) {
1407
  taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
29✔
1408
  for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
130✔
1409
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
101✔
1410
    mInfo("dnode:%d, equivalent vnodes:%d others:%d", pDnode->id, pDnode->numOfVnodes, pDnode->numOfOtherNodes);
101!
1411
  }
1412

1413
  int32_t code = -1;
29✔
1414
  for (int32_t d = taosArrayGetSize(pArray) - 1; d >= 0; --d) {
41!
1415
    SDnodeObj *pDnode = taosArrayGet(pArray, d);
41✔
1416

1417
    for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
99✔
1418
      SVnodeGid *pVgid = &pVgroup->vnodeGid[vn];
87✔
1419
      if (pVgid->dnodeId == pDnode->id) {
87✔
1420
        int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
29✔
1421
        pDnode->memUsed -= vgMem;
29✔
1422
        mInfo("db:%s, vgId:%d, vn:%d is removed, memory:%" PRId64 ", dnode:%d avail:%" PRId64 " used:%" PRId64,
29!
1423
              pVgroup->dbName, pVgroup->vgId, vn, vgMem, pVgid->dnodeId, pDnode->memAvail, pDnode->memUsed);
1424
        pDnode->numOfVnodes--;
29✔
1425
        pVgroup->replica--;
29✔
1426
        *pDelVgid = *pVgid;
29✔
1427
        *pVgid = pVgroup->vnodeGid[pVgroup->replica];
29✔
1428
        memset(&pVgroup->vnodeGid[pVgroup->replica], 0, sizeof(SVnodeGid));
29✔
1429
        code = 0;
29✔
1430
        goto _OVER;
29✔
1431
      }
1432
    }
1433
  }
1434

1435
_OVER:
×
1436
  if (code != 0) {
29!
1437
    code = TSDB_CODE_APP_ERROR;
×
1438
    mError("db:%s, failed to remove vnode from vgId:%d since %s", pVgroup->dbName, pVgroup->vgId, tstrerror(code));
×
1439
    TAOS_RETURN(code);
×
1440
  }
1441

1442
  for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
83✔
1443
    SVnodeGid *pVgid = &pVgroup->vnodeGid[vn];
54✔
1444
    mInfo("db:%s, vgId:%d, vn:%d dnode:%d is reserved", pVgroup->dbName, pVgroup->vgId, vn, pVgid->dnodeId);
54!
1445
  }
1446

1447
  SSdbRaw *pVgRaw = mndVgroupActionEncode(pVgroup);
29✔
1448
  if (pVgRaw == NULL) {
29!
1449
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1450
    if (terrno != 0) code = terrno;
×
1451
    TAOS_RETURN(code);
×
1452
  }
1453
  if (mndTransAppendRedolog(pTrans, pVgRaw) != 0) {
29!
1454
    sdbFreeRaw(pVgRaw);
×
1455
    TAOS_RETURN(code);
×
1456
  }
1457
  code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
29✔
1458
  if (code != 0) {
29!
1459
    mError("vgId:%d, failed to set raw status since %s at line:%d", pVgroup->vgId, tstrerror(code), __LINE__);
×
1460
  }
1461

1462
  TAOS_RETURN(code);
29✔
1463
}
1464

1465
static int32_t mndRemoveVnodeFromVgroupWithoutSave(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup, SArray *pArray,
×
1466
                                                   SVnodeGid *pDelVgid) {
1467
  taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
×
1468
  for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
×
1469
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
×
1470
    mInfo("dnode:%d, equivalent vnodes:%d others:%d", pDnode->id, pDnode->numOfVnodes, pDnode->numOfOtherNodes);
×
1471
  }
1472

1473
  int32_t code = -1;
×
1474
  for (int32_t d = taosArrayGetSize(pArray) - 1; d >= 0; --d) {
×
1475
    SDnodeObj *pDnode = taosArrayGet(pArray, d);
×
1476

1477
    for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
×
1478
      SVnodeGid *pVgid = &pVgroup->vnodeGid[vn];
×
1479
      if (pVgid->dnodeId == pDnode->id) {
×
1480
        int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
×
1481
        pDnode->memUsed -= vgMem;
×
1482
        mInfo("db:%s, vgId:%d, vn:%d is removed, memory:%" PRId64 ", dnode:%d avail:%" PRId64 " used:%" PRId64,
×
1483
              pVgroup->dbName, pVgroup->vgId, vn, vgMem, pVgid->dnodeId, pDnode->memAvail, pDnode->memUsed);
1484
        pDnode->numOfVnodes--;
×
1485
        pVgroup->replica--;
×
1486
        *pDelVgid = *pVgid;
×
1487
        *pVgid = pVgroup->vnodeGid[pVgroup->replica];
×
1488
        memset(&pVgroup->vnodeGid[pVgroup->replica], 0, sizeof(SVnodeGid));
×
1489
        code = 0;
×
1490
        goto _OVER;
×
1491
      }
1492
    }
1493
  }
1494

1495
_OVER:
×
1496
  if (code != 0) {
×
1497
    code = TSDB_CODE_APP_ERROR;
×
1498
    mError("db:%s, failed to remove vnode from vgId:%d since %s", pVgroup->dbName, pVgroup->vgId, tstrerror(code));
×
1499
    TAOS_RETURN(code);
×
1500
  }
1501

1502
  for (int32_t vn = 0; vn < pVgroup->replica; ++vn) {
×
1503
    SVnodeGid *pVgid = &pVgroup->vnodeGid[vn];
×
1504
    mInfo("db:%s, vgId:%d, vn:%d dnode:%d is reserved", pVgroup->dbName, pVgroup->vgId, vn, pVgid->dnodeId);
×
1505
  }
1506

1507
  TAOS_RETURN(code);
×
1508
}
1509

1510
int32_t mndAddCreateVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, SVnodeGid *pVgid) {
9,419✔
1511
  int32_t      code = 0;
9,419✔
1512
  STransAction action = {0};
9,419✔
1513

1514
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
9,419✔
1515
  if (pDnode == NULL) return -1;
9,419!
1516
  action.epSet = mndGetDnodeEpset(pDnode);
9,419✔
1517
  mndReleaseDnode(pMnode, pDnode);
9,419✔
1518

1519
  int32_t contLen = 0;
9,419✔
1520
  void   *pReq = mndBuildCreateVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen);
9,419✔
1521
  if (pReq == NULL) return -1;
9,419!
1522

1523
  action.pCont = pReq;
9,419✔
1524
  action.contLen = contLen;
9,419✔
1525
  action.msgType = TDMT_DND_CREATE_VNODE;
9,419✔
1526
  action.acceptableCode = TSDB_CODE_VND_ALREADY_EXIST;
9,419✔
1527

1528
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
9,419!
1529
    taosMemoryFree(pReq);
×
1530
    TAOS_RETURN(code);
×
1531
  }
1532

1533
  TAOS_RETURN(code);
9,419✔
1534
}
1535

1536
int32_t mndRestoreAddCreateVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
10✔
1537
                                       SDnodeObj *pDnode) {
1538
  int32_t      code = 0;
10✔
1539
  STransAction action = {0};
10✔
1540

1541
  action.epSet = mndGetDnodeEpset(pDnode);
10✔
1542

1543
  int32_t contLen = 0;
10✔
1544
  void   *pReq = mndBuildCreateVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen);
10✔
1545
  if (pReq == NULL) {
10!
1546
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1547
    if (terrno != 0) code = terrno;
×
1548
    TAOS_RETURN(code);
×
1549
  }
1550

1551
  action.pCont = pReq;
10✔
1552
  action.contLen = contLen;
10✔
1553
  action.msgType = TDMT_DND_CREATE_VNODE;
10✔
1554
  action.acceptableCode = TSDB_CODE_VND_ALREADY_EXIST;
10✔
1555

1556
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
10!
1557
    taosMemoryFree(pReq);
×
1558
    TAOS_RETURN(code);
×
1559
  }
1560

1561
  TAOS_RETURN(code);
10✔
1562
}
1563

1564
int32_t mndAddAlterVnodeConfirmAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) {
515✔
1565
  int32_t      code = 0;
515✔
1566
  STransAction action = {0};
515✔
1567
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
515✔
1568

1569
  mInfo("vgId:%d, build alter vnode confirm req", pVgroup->vgId);
515!
1570
  int32_t   contLen = sizeof(SMsgHead);
515✔
1571
  SMsgHead *pHead = taosMemoryMalloc(contLen);
515✔
1572
  if (pHead == NULL) {
515!
1573
    TAOS_RETURN(terrno);
×
1574
  }
1575

1576
  pHead->contLen = htonl(contLen);
515✔
1577
  pHead->vgId = htonl(pVgroup->vgId);
515✔
1578

1579
  action.pCont = pHead;
515✔
1580
  action.contLen = contLen;
515✔
1581
  action.msgType = TDMT_VND_ALTER_CONFIRM;
515✔
1582
  // incorrect redirect result will cause this erro
1583
  action.retryCode = TSDB_CODE_VND_INVALID_VGROUP_ID;
515✔
1584

1585
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
515!
1586
    taosMemoryFree(pHead);
×
1587
    TAOS_RETURN(code);
×
1588
  }
1589

1590
  TAOS_RETURN(code);
515✔
1591
}
1592

1593
int32_t mndAddChangeConfigAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pOldVgroup, SVgObj *pNewVgroup,
×
1594
                                 int32_t dnodeId) {
1595
  int32_t      code = 0;
×
1596
  STransAction action = {0};
×
1597
  action.epSet = mndGetVgroupEpset(pMnode, pNewVgroup);
×
1598

1599
  int32_t contLen = 0;
×
1600
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pNewVgroup, dnodeId, &contLen);
×
1601
  if (pReq == NULL) {
×
1602
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1603
    if (terrno != 0) code = terrno;
×
1604
    TAOS_RETURN(code);
×
1605
  }
1606

1607
  int32_t totallen = contLen + sizeof(SMsgHead);
×
1608

1609
  SMsgHead *pHead = taosMemoryMalloc(totallen);
×
1610
  if (pHead == NULL) {
×
1611
    taosMemoryFree(pReq);
×
1612
    TAOS_RETURN(terrno);
×
1613
  }
1614

1615
  pHead->contLen = htonl(totallen);
×
1616
  pHead->vgId = htonl(pNewVgroup->vgId);
×
1617

1618
  memcpy((void *)(pHead + 1), pReq, contLen);
×
1619
  taosMemoryFree(pReq);
×
1620

1621
  action.pCont = pHead;
×
1622
  action.contLen = totallen;
×
1623
  action.msgType = TDMT_SYNC_CONFIG_CHANGE;
×
1624

1625
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
×
1626
    taosMemoryFree(pHead);
×
1627
    TAOS_RETURN(code);
×
1628
  }
1629

1630
  TAOS_RETURN(code);
×
1631
}
1632

1633
static int32_t mndAddAlterVnodeHashRangeAction(SMnode *pMnode, STrans *pTrans, int32_t srcVgId, SVgObj *pVgroup) {
60✔
1634
  int32_t      code = 0;
60✔
1635
  STransAction action = {0};
60✔
1636
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
60✔
1637

1638
  int32_t contLen = 0;
60✔
1639
  void   *pReq = mndBuildAlterVnodeHashRangeReq(pMnode, srcVgId, pVgroup, &contLen);
60✔
1640
  if (pReq == NULL) {
60!
1641
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1642
    if (terrno != 0) code = terrno;
×
1643
    TAOS_RETURN(code);
×
1644
  }
1645

1646
  action.pCont = pReq;
60✔
1647
  action.contLen = contLen;
60✔
1648
  action.msgType = TDMT_VND_ALTER_HASHRANGE;
60✔
1649
  action.acceptableCode = TSDB_CODE_VND_ALREADY_EXIST;
60✔
1650

1651
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
60!
1652
    taosMemoryFree(pReq);
×
1653
    TAOS_RETURN(code);
×
1654
  }
1655

1656
  mInfo("trans:%d, add alter vnode hash range action for from vgId:%d to vgId:%d", pTrans->id, srcVgId, pVgroup->vgId);
60!
1657
  TAOS_RETURN(code);
60✔
1658
}
1659

1660
int32_t mndAddAlterVnodeConfigAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) {
429✔
1661
  int32_t      code = 0;
429✔
1662
  STransAction action = {0};
429✔
1663
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
429✔
1664

1665
  int32_t contLen = 0;
429✔
1666
  void   *pReq = mndBuildAlterVnodeConfigReq(pMnode, pDb, pVgroup, &contLen);
429✔
1667
  if (pReq == NULL) {
429!
1668
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1669
    if (terrno != 0) code = terrno;
×
1670
    TAOS_RETURN(code);
×
1671
  }
1672

1673
  action.pCont = pReq;
429✔
1674
  action.contLen = contLen;
429✔
1675
  action.msgType = TDMT_VND_ALTER_CONFIG;
429✔
1676

1677
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
429!
1678
    taosMemoryFree(pReq);
×
1679
    TAOS_RETURN(code);
×
1680
  }
1681

1682
  TAOS_RETURN(code);
429✔
1683
}
1684

1685
int32_t mndAddNewVgPrepareAction(SMnode *pMnode, STrans *pTrans, SVgObj *pVg) {
8,470✔
1686
  int32_t  code = 0;
8,470✔
1687
  SSdbRaw *pRaw = mndVgroupActionEncode(pVg);
8,470✔
1688
  if (pRaw == NULL) {
8,470!
1689
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1690
    if (terrno != 0) code = terrno;
×
1691
    goto _err;
×
1692
  }
1693

1694
  TAOS_CHECK_GOTO(mndTransAppendPrepareLog(pTrans, pRaw), NULL, _err);
8,470!
1695
  if (sdbSetRawStatus(pRaw, SDB_STATUS_CREATING) != 0) {
8,470!
1696
    mError("vgId:%d, failed to set raw status at line:%d", pVg->vgId, __LINE__);
×
1697
  }
1698
  if (code != 0) {
8,470!
1699
    mError("vgId:%d, failed to set raw status since %s at line:%d", pVg->vgId, tstrerror(code), __LINE__);
×
1700
    TAOS_RETURN(code);
×
1701
  }
1702
  pRaw = NULL;
8,470✔
1703
  TAOS_RETURN(code);
8,470✔
1704

1705
_err:
×
1706
  sdbFreeRaw(pRaw);
×
1707
  TAOS_RETURN(code);
×
1708
}
1709

1710
int32_t mndAddAlterVnodeReplicaAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId) {
1,199✔
1711
  int32_t    code = 0;
1,199✔
1712
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
1,199✔
1713
  if (pDnode == NULL) {
1,199!
1714
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1715
    if (terrno != 0) code = terrno;
×
1716
    TAOS_RETURN(code);
×
1717
  }
1718

1719
  STransAction action = {0};
1,199✔
1720
  action.epSet = mndGetDnodeEpset(pDnode);
1,199✔
1721
  mndReleaseDnode(pMnode, pDnode);
1,199✔
1722

1723
  int32_t contLen = 0;
1,199✔
1724
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pVgroup, dnodeId, &contLen);
1,199✔
1725
  if (pReq == NULL) {
1,199!
1726
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1727
    if (terrno != 0) code = terrno;
×
1728
    TAOS_RETURN(code);
×
1729
  }
1730

1731
  action.pCont = pReq;
1,199✔
1732
  action.contLen = contLen;
1,199✔
1733
  action.msgType = TDMT_VND_ALTER_REPLICA;
1,199✔
1734

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

1740
  TAOS_RETURN(code);
1,199✔
1741
}
1742

1743
int32_t mndAddCheckLearnerCatchupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId) {
×
1744
  int32_t    code = 0;
×
1745
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
×
1746
  if (pDnode == NULL) {
×
1747
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1748
    if (terrno != 0) code = terrno;
×
1749
    TAOS_RETURN(code);
×
1750
  }
1751

1752
  STransAction action = {0};
×
1753
  action.epSet = mndGetDnodeEpset(pDnode);
×
1754
  mndReleaseDnode(pMnode, pDnode);
×
1755

1756
  int32_t contLen = 0;
×
1757
  void   *pReq = mndBuildCheckLearnCatchupReq(pMnode, pDb, pVgroup, dnodeId, &contLen);
×
1758
  if (pReq == NULL) {
×
1759
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1760
    if (terrno != 0) code = terrno;
×
1761
    TAOS_RETURN(code);
×
1762
  }
1763

1764
  action.pCont = pReq;
×
1765
  action.contLen = contLen;
×
1766
  action.msgType = TDMT_DND_CHECK_VNODE_LEARNER_CATCHUP;
×
1767
  action.acceptableCode = TSDB_CODE_VND_ALREADY_IS_VOTER;
×
1768
  action.retryCode = TSDB_CODE_VND_NOT_CATCH_UP;
×
1769

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

1775
  TAOS_RETURN(code);
×
1776
}
1777

1778
int32_t mndAddAlterVnodeTypeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t dnodeId) {
188✔
1779
  int32_t    code = 0;
188✔
1780
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
188✔
1781
  if (pDnode == NULL) {
188!
1782
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1783
    if (terrno != 0) code = terrno;
×
1784
    TAOS_RETURN(code);
×
1785
  }
1786

1787
  STransAction action = {0};
188✔
1788
  action.epSet = mndGetDnodeEpset(pDnode);
188✔
1789
  mndReleaseDnode(pMnode, pDnode);
188✔
1790

1791
  int32_t contLen = 0;
188✔
1792
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pVgroup, dnodeId, &contLen);
188✔
1793
  if (pReq == NULL) {
188!
1794
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1795
    if (terrno != 0) code = terrno;
×
1796
    TAOS_RETURN(code);
×
1797
  }
1798

1799
  action.pCont = pReq;
188✔
1800
  action.contLen = contLen;
188✔
1801
  action.msgType = TDMT_DND_ALTER_VNODE_TYPE;
188✔
1802
  action.acceptableCode = TSDB_CODE_VND_ALREADY_IS_VOTER;
188✔
1803
  action.retryCode = TSDB_CODE_VND_NOT_CATCH_UP;
188✔
1804

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

1810
  TAOS_RETURN(code);
188✔
1811
}
1812

1813
int32_t mndRestoreAddAlterVnodeTypeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
10✔
1814
                                          SDnodeObj *pDnode) {
1815
  int32_t      code = 0;
10✔
1816
  STransAction action = {0};
10✔
1817
  action.epSet = mndGetDnodeEpset(pDnode);
10✔
1818

1819
  int32_t contLen = 0;
10✔
1820
  void   *pReq = mndBuildAlterVnodeReplicaReq(pMnode, pDb, pVgroup, pDnode->id, &contLen);
10✔
1821
  if (pReq == NULL) {
10!
1822
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1823
    if (terrno != 0) code = terrno;
×
1824
    TAOS_RETURN(code);
×
1825
  }
1826

1827
  action.pCont = pReq;
10✔
1828
  action.contLen = contLen;
10✔
1829
  action.msgType = TDMT_DND_ALTER_VNODE_TYPE;
10✔
1830
  action.acceptableCode = TSDB_CODE_VND_ALREADY_IS_VOTER;
10✔
1831
  action.retryCode = TSDB_CODE_VND_NOT_CATCH_UP;
10✔
1832

1833
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
10!
1834
    taosMemoryFree(pReq);
×
1835
    TAOS_RETURN(code);
×
1836
  }
1837

1838
  TAOS_RETURN(code);
10✔
1839
}
1840

1841
static int32_t mndAddDisableVnodeWriteAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
60✔
1842
                                             int32_t dnodeId) {
1843
  int32_t    code = 0;
60✔
1844
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
60✔
1845
  if (pDnode == NULL) {
60!
1846
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1847
    if (terrno != 0) code = terrno;
×
1848
    TAOS_RETURN(code);
×
1849
  }
1850

1851
  STransAction action = {0};
60✔
1852
  action.epSet = mndGetDnodeEpset(pDnode);
60✔
1853
  mndReleaseDnode(pMnode, pDnode);
60✔
1854

1855
  int32_t contLen = 0;
60✔
1856
  void   *pReq = mndBuildDisableVnodeWriteReq(pMnode, pDb, pVgroup->vgId, &contLen);
60✔
1857
  if (pReq == NULL) {
60!
1858
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1859
    if (terrno != 0) code = terrno;
×
1860
    TAOS_RETURN(code);
×
1861
  }
1862

1863
  action.pCont = pReq;
60✔
1864
  action.contLen = contLen;
60✔
1865
  action.msgType = TDMT_VND_DISABLE_WRITE;
60✔
1866

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

1872
  TAOS_RETURN(code);
60✔
1873
}
1874

1875
int32_t mndAddDropVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, SVnodeGid *pVgid,
13,628✔
1876
                              bool isRedo) {
1877
  int32_t      code = 0;
13,628✔
1878
  STransAction action = {0};
13,628✔
1879

1880
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId);
13,628✔
1881
  if (pDnode == NULL) {
13,628!
1882
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1883
    if (terrno != 0) code = terrno;
×
1884
    TAOS_RETURN(code);
×
1885
  }
1886
  action.epSet = mndGetDnodeEpset(pDnode);
13,628✔
1887
  mndReleaseDnode(pMnode, pDnode);
13,628✔
1888

1889
  int32_t contLen = 0;
13,628✔
1890
  void   *pReq = mndBuildDropVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen);
13,628✔
1891
  if (pReq == NULL) {
13,628!
1892
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1893
    if (terrno != 0) code = terrno;
×
1894
    TAOS_RETURN(code);
×
1895
  }
1896

1897
  action.pCont = pReq;
13,628✔
1898
  action.contLen = contLen;
13,628✔
1899
  action.msgType = TDMT_DND_DROP_VNODE;
13,628✔
1900
  action.acceptableCode = TSDB_CODE_VND_NOT_EXIST;
13,628✔
1901

1902
  if (isRedo) {
13,628✔
1903
    if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
4,473!
1904
      taosMemoryFree(pReq);
×
1905
      TAOS_RETURN(code);
×
1906
    }
1907
  } else {
1908
    if ((code = mndTransAppendUndoAction(pTrans, &action)) != 0) {
9,155!
1909
      taosMemoryFree(pReq);
×
1910
      TAOS_RETURN(code);
×
1911
    }
1912
  }
1913

1914
  TAOS_RETURN(code);
13,628✔
1915
}
1916

1917
int32_t mndSetMoveVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int32_t vnIndex,
33✔
1918
                                    SArray *pArray, bool force, bool unsafe) {
1919
  int32_t code = 0;
33✔
1920
  SVgObj  newVg = {0};
33✔
1921
  memcpy(&newVg, pVgroup, sizeof(SVgObj));
33✔
1922

1923
  mInfo("vgId:%d, vgroup info before move, replica:%d", newVg.vgId, newVg.replica);
33!
1924
  for (int32_t i = 0; i < newVg.replica; ++i) {
102✔
1925
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
69!
1926
  }
1927

1928
  if (!force) {
33✔
1929
#if 1
1930
    {
1931
#else
1932
    if (newVg.replica == 1) {
1933
#endif
1934
      mInfo("vgId:%d, will add 1 vnode, replca:%d", pVgroup->vgId, newVg.replica);
29!
1935
      TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVg, pArray));
29✔
1936
      for (int32_t i = 0; i < newVg.replica - 1; ++i) {
88✔
1937
        TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg, newVg.vnodeGid[i].dnodeId));
60!
1938
      }
1939
      TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg, &newVg.vnodeGid[newVg.replica - 1]));
28!
1940
      TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg));
28!
1941

1942
      mInfo("vgId:%d, will remove 1 vnode, replca:2", pVgroup->vgId);
28!
1943
      newVg.replica--;
28✔
1944
      SVnodeGid del = newVg.vnodeGid[vnIndex];
28✔
1945
      newVg.vnodeGid[vnIndex] = newVg.vnodeGid[newVg.replica];
28✔
1946
      memset(&newVg.vnodeGid[newVg.replica], 0, sizeof(SVnodeGid));
28✔
1947
      {
1948
        SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
28✔
1949
        if (pRaw == NULL) {
28!
1950
          code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1951
          if (terrno != 0) code = terrno;
×
1952
          TAOS_RETURN(code);
×
1953
        }
1954
        if ((code = mndTransAppendRedolog(pTrans, pRaw)) != 0) {
28!
1955
          sdbFreeRaw(pRaw);
×
1956
          TAOS_RETURN(code);
×
1957
        }
1958
        code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
28✔
1959
        if (code != 0) {
28!
1960
          mError("vgId:%d, failed to set raw status since %s at line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
1961
          return code;
×
1962
        }
1963
      }
1964

1965
      TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pDb, &newVg, &del, true));
28!
1966
      for (int32_t i = 0; i < newVg.replica; ++i) {
88✔
1967
        TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg, newVg.vnodeGid[i].dnodeId));
60!
1968
      }
1969
      TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg));
28!
1970
#if 1
1971
    }
1972
#else
1973
    } else {  // new replica == 3
1974
      mInfo("vgId:%d, will add 1 vnode, replca:3", pVgroup->vgId);
1975
      if (mndAddVnodeToVgroup(pMnode, pTrans, &newVg, pArray) != 0) return -1;
1976
      mInfo("vgId:%d, will remove 1 vnode, replca:4", pVgroup->vgId);
1977
      newVg.replica--;
1978
      SVnodeGid del = newVg.vnodeGid[vnIndex];
1979
      newVg.vnodeGid[vnIndex] = newVg.vnodeGid[newVg.replica];
1980
      memset(&newVg.vnodeGid[newVg.replica], 0, sizeof(SVnodeGid));
1981
      {
1982
        SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
1983
        if (pRaw == NULL) return -1;
1984
        if (mndTransAppendRedolog(pTrans, pRaw) != 0) {
1985
          sdbFreeRaw(pRaw);
1986
          return -1;
1987
        }
1988
      }
1989

1990
      if (mndAddDropVnodeAction(pMnode, pTrans, pDb, &newVg, &del, true) != 0) return -1;
1991
      for (int32_t i = 0; i < newVg.replica; ++i) {
1992
        if (i == vnIndex) continue;
1993
        if (mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg, newVg.vnodeGid[i].dnodeId) != 0) return -1;
1994
      }
1995
      if (mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg, &newVg.vnodeGid[vnIndex]) != 0) return -1;
1996
      if (mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg) != 0) return -1;
1997
    }
1998
#endif
1999
  } else {
2000
    mInfo("vgId:%d, will add 1 vnode and force remove 1 vnode", pVgroup->vgId);
4!
2001
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVg, pArray));
4!
2002
    newVg.replica--;
4✔
2003
    // SVnodeGid del = newVg.vnodeGid[vnIndex];
2004
    newVg.vnodeGid[vnIndex] = newVg.vnodeGid[newVg.replica];
4✔
2005
    memset(&newVg.vnodeGid[newVg.replica], 0, sizeof(SVnodeGid));
4✔
2006
    {
2007
      SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
4✔
2008
      if (pRaw == NULL) {
4!
2009
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2010
        if (terrno != 0) code = terrno;
×
2011
        TAOS_RETURN(code);
×
2012
      }
2013
      if ((code = mndTransAppendRedolog(pTrans, pRaw)) != 0) {
4!
2014
        sdbFreeRaw(pRaw);
×
2015
        TAOS_RETURN(code);
×
2016
      }
2017
      code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
4✔
2018
      if (code != 0) {
4!
2019
        mError("vgId:%d, failed to set raw status since %s at line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
2020
        return code;
×
2021
      }
2022
    }
2023

2024
    for (int32_t i = 0; i < newVg.replica; ++i) {
12✔
2025
      if (i != vnIndex) {
8✔
2026
        TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg, newVg.vnodeGid[i].dnodeId));
4!
2027
      }
2028
    }
2029
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg, &newVg.vnodeGid[vnIndex]));
4!
2030
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg));
4!
2031

2032
    if (newVg.replica == 1) {
4✔
2033
      if (force && !unsafe) {
2!
2034
        TAOS_RETURN(TSDB_CODE_VND_META_DATA_UNSAFE_DELETE);
1✔
2035
      }
2036

2037
      SSdb *pSdb = pMnode->pSdb;
1✔
2038
      void *pIter = NULL;
1✔
2039

2040
      while (1) {
3✔
2041
        SStbObj *pStb = NULL;
4✔
2042
        pIter = sdbFetch(pSdb, SDB_STB, pIter, (void **)&pStb);
4✔
2043
        if (pIter == NULL) break;
4✔
2044

2045
        if (strcmp(pStb->db, pDb->name) == 0) {
3✔
2046
          if ((code = mndSetForceDropCreateStbRedoActions(pMnode, pTrans, &newVg, pStb)) != 0) {
2!
2047
            sdbCancelFetch(pSdb, pIter);
×
2048
            sdbRelease(pSdb, pStb);
×
2049
            TAOS_RETURN(code);
×
2050
          }
2051
        }
2052

2053
        sdbRelease(pSdb, pStb);
3✔
2054
      }
2055

2056
      mInfo("vgId:%d, all data is dropped since replica=1", pVgroup->vgId);
1!
2057
    }
2058
  }
2059

2060
  {
2061
    SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
31✔
2062
    if (pRaw == NULL) {
31!
2063
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2064
      if (terrno != 0) code = terrno;
×
2065
      TAOS_RETURN(code);
×
2066
    }
2067
    if ((code = mndTransAppendCommitlog(pTrans, pRaw)) != 0) {
31!
2068
      sdbFreeRaw(pRaw);
×
2069
      TAOS_RETURN(code);
×
2070
    }
2071
    code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
31✔
2072
    if (code != 0) {
31!
2073
      mError("vgId:%d, failed to set raw status since %s at line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
2074
      return code;
×
2075
    }
2076
  }
2077

2078
  mInfo("vgId:%d, vgroup info after move, replica:%d", newVg.vgId, newVg.replica);
31!
2079
  for (int32_t i = 0; i < newVg.replica; ++i) {
98✔
2080
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
67!
2081
  }
2082
  TAOS_RETURN(code);
31✔
2083
}
2084

2085
int32_t mndSetMoveVgroupsInfoToTrans(SMnode *pMnode, STrans *pTrans, int32_t delDnodeId, bool force, bool unsafe) {
16✔
2086
  int32_t code = 0;
16✔
2087
  SArray *pArray = mndBuildDnodesArray(pMnode, delDnodeId, NULL);
16✔
2088
  if (pArray == NULL) {
16!
2089
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2090
    if (terrno != 0) code = terrno;
×
2091
    TAOS_RETURN(code);
×
2092
  }
2093

2094
  void *pIter = NULL;
16✔
2095
  while (1) {
44✔
2096
    SVgObj *pVgroup = NULL;
60✔
2097
    pIter = sdbFetch(pMnode->pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
60✔
2098
    if (pIter == NULL) break;
60✔
2099

2100
    int32_t vnIndex = -1;
46✔
2101
    for (int32_t i = 0; i < pVgroup->replica; ++i) {
81✔
2102
      if (pVgroup->vnodeGid[i].dnodeId == delDnodeId) {
68✔
2103
        vnIndex = i;
33✔
2104
        break;
33✔
2105
      }
2106
    }
2107

2108
    code = 0;
46✔
2109
    if (vnIndex != -1) {
46✔
2110
      mInfo("vgId:%d, vnode:%d will be removed from dnode:%d, force:%d", pVgroup->vgId, vnIndex, delDnodeId, force);
33!
2111
      SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName);
33✔
2112
      code = mndSetMoveVgroupInfoToTrans(pMnode, pTrans, pDb, pVgroup, vnIndex, pArray, force, unsafe);
33✔
2113
      mndReleaseDb(pMnode, pDb);
33✔
2114
    }
2115

2116
    sdbRelease(pMnode->pSdb, pVgroup);
46✔
2117

2118
    if (code != 0) {
46✔
2119
      sdbCancelFetch(pMnode->pSdb, pIter);
2✔
2120
      break;
2✔
2121
    }
2122
  }
2123

2124
  taosArrayDestroy(pArray);
16✔
2125
  TAOS_RETURN(code);
16✔
2126
}
2127

2128
static int32_t mndAddIncVgroupReplicaToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
125✔
2129
                                             int32_t newDnodeId) {
2130
  int32_t code = 0;
125✔
2131
  mInfo("vgId:%d, will add 1 vnode, replica:%d dnode:%d", pVgroup->vgId, pVgroup->replica, newDnodeId);
125!
2132

2133
  // assoc dnode
2134
  SVnodeGid *pGid = &pVgroup->vnodeGid[pVgroup->replica];
125✔
2135
  pVgroup->replica++;
125✔
2136
  pGid->dnodeId = newDnodeId;
125✔
2137
  pGid->syncState = TAOS_SYNC_STATE_OFFLINE;
125✔
2138
  pGid->nodeRole = TAOS_SYNC_ROLE_LEARNER;
125✔
2139

2140
  SSdbRaw *pVgRaw = mndVgroupActionEncode(pVgroup);
125✔
2141
  if (pVgRaw == NULL) {
125!
2142
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2143
    if (terrno != 0) code = terrno;
×
2144
    TAOS_RETURN(code);
×
2145
  }
2146
  if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
125!
2147
    sdbFreeRaw(pVgRaw);
×
2148
    TAOS_RETURN(code);
×
2149
  }
2150
  code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
125✔
2151
  if (code != 0) {
125!
2152
    mError("vgId:%d, failed to set raw status since %s at line:%d", pVgroup->vgId, tstrerror(code), __LINE__);
×
2153
    TAOS_RETURN(code);
×
2154
  }
2155

2156
  // learner
2157
  for (int32_t i = 0; i < pVgroup->replica - 1; ++i) {
394✔
2158
    TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, pVgroup, pVgroup->vnodeGid[i].dnodeId));
269!
2159
  }
2160
  TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pDb, pVgroup, pGid));
125!
2161

2162
  // voter
2163
  pGid->nodeRole = TAOS_SYNC_ROLE_VOTER;
125✔
2164
  TAOS_CHECK_RETURN(mndAddAlterVnodeTypeAction(pMnode, pTrans, pDb, pVgroup, pGid->dnodeId));
125!
2165
  for (int32_t i = 0; i < pVgroup->replica - 1; ++i) {
394✔
2166
    TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, pVgroup, pVgroup->vnodeGid[i].dnodeId));
269!
2167
  }
2168

2169
  // confirm
2170
  TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, pVgroup));
125!
2171

2172
  TAOS_RETURN(code);
125✔
2173
}
2174

2175
static int32_t mndAddDecVgroupReplicaFromTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
125✔
2176
                                               int32_t delDnodeId) {
2177
  int32_t code = 0;
125✔
2178
  mInfo("vgId:%d, will remove 1 vnode, replica:%d dnode:%d", pVgroup->vgId, pVgroup->replica, delDnodeId);
125!
2179

2180
  SVnodeGid *pGid = NULL;
125✔
2181
  SVnodeGid  delGid = {0};
125✔
2182
  for (int32_t i = 0; i < pVgroup->replica; ++i) {
201!
2183
    if (pVgroup->vnodeGid[i].dnodeId == delDnodeId) {
201✔
2184
      pGid = &pVgroup->vnodeGid[i];
125✔
2185
      break;
125✔
2186
    }
2187
  }
2188

2189
  if (pGid == NULL) return 0;
125!
2190

2191
  pVgroup->replica--;
125✔
2192
  memcpy(&delGid, pGid, sizeof(SVnodeGid));
125✔
2193
  memcpy(pGid, &pVgroup->vnodeGid[pVgroup->replica], sizeof(SVnodeGid));
125✔
2194
  memset(&pVgroup->vnodeGid[pVgroup->replica], 0, sizeof(SVnodeGid));
125✔
2195

2196
  SSdbRaw *pVgRaw = mndVgroupActionEncode(pVgroup);
125✔
2197
  if (pVgRaw == NULL) {
125!
2198
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2199
    if (terrno != 0) code = terrno;
×
2200
    TAOS_RETURN(code);
×
2201
  }
2202
  if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
125!
2203
    sdbFreeRaw(pVgRaw);
×
2204
    TAOS_RETURN(code);
×
2205
  }
2206
  code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
125✔
2207
  if (code != 0) {
125!
2208
    mError("vgId:%d, failed to set raw status since %s at line:%d", pVgroup->vgId, tstrerror(code), __LINE__);
×
2209
    TAOS_RETURN(code);
×
2210
  }
2211

2212
  TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pDb, pVgroup, &delGid, true));
125!
2213
  for (int32_t i = 0; i < pVgroup->replica; ++i) {
394✔
2214
    TAOS_CHECK_RETURN(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, pVgroup, pVgroup->vnodeGid[i].dnodeId));
269!
2215
  }
2216
  TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, pVgroup));
125!
2217

2218
  TAOS_RETURN(code);
125✔
2219
}
2220

2221
static int32_t mndRedistributeVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SVgObj *pVgroup, SDnodeObj *pNew1,
79✔
2222
                                     SDnodeObj *pOld1, SDnodeObj *pNew2, SDnodeObj *pOld2, SDnodeObj *pNew3,
2223
                                     SDnodeObj *pOld3) {
2224
  int32_t code = -1;
79✔
2225
  STrans *pTrans = NULL;
79✔
2226

2227
  pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_GLOBAL, pReq, "red-vgroup");
79✔
2228
  if (pTrans == NULL) {
79!
2229
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2230
    if (terrno != 0) code = terrno;
×
2231
    goto _OVER;
×
2232
  }
2233

2234
  mndTransSetDbName(pTrans, pVgroup->dbName, NULL);
79✔
2235
  TAOS_CHECK_GOTO(mndTransCheckConflictWithCompact(pMnode, pTrans), NULL, _OVER);
79✔
2236

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

2240
  SVgObj newVg = {0};
78✔
2241
  memcpy(&newVg, pVgroup, sizeof(SVgObj));
78✔
2242
  mInfo("vgId:%d, vgroup info before redistribute, replica:%d", newVg.vgId, newVg.replica);
78!
2243
  for (int32_t i = 0; i < newVg.replica; ++i) {
234✔
2244
    mInfo("vgId:%d, vnode:%d dnode:%d role:%s", newVg.vgId, i, newVg.vnodeGid[i].dnodeId,
156!
2245
          syncStr(newVg.vnodeGid[i].syncState));
2246
  }
2247

2248
  if (pNew1 != NULL && pOld1 != NULL) {
78!
2249
    int32_t numOfVnodes = mndGetVnodesNum(pMnode, pNew1->id);
78✔
2250
    if (numOfVnodes >= pNew1->numOfSupportVnodes) {
78✔
2251
      mError("vgId:%d, no enough vnodes in dnode:%d, numOfVnodes:%d support:%d", newVg.vgId, pNew1->id, numOfVnodes,
1!
2252
             pNew1->numOfSupportVnodes);
2253
      code = TSDB_CODE_MND_NO_ENOUGH_VNODES;
1✔
2254
      goto _OVER;
1✔
2255
    }
2256

2257
    int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
77✔
2258
    if (pNew1->memAvail - vgMem - pNew1->memUsed <= 0) {
77!
2259
      mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
×
2260
             pVgroup->dbName, pVgroup->vgId, vgMem, pNew1->id, pNew1->memAvail, pNew1->memUsed);
2261
      code = TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE;
×
2262
      goto _OVER;
×
2263
    } else {
2264
      pNew1->memUsed += vgMem;
77✔
2265
    }
2266

2267
    TAOS_CHECK_GOTO(mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pNew1->id), NULL, _OVER);
77!
2268
    TAOS_CHECK_GOTO(mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pOld1->id), NULL, _OVER);
77!
2269
  }
2270

2271
  if (pNew2 != NULL && pOld2 != NULL) {
77!
2272
    int32_t numOfVnodes = mndGetVnodesNum(pMnode, pNew2->id);
16✔
2273
    if (numOfVnodes >= pNew2->numOfSupportVnodes) {
16!
2274
      mError("vgId:%d, no enough vnodes in dnode:%d, numOfVnodes:%d support:%d", newVg.vgId, pNew2->id, numOfVnodes,
×
2275
             pNew2->numOfSupportVnodes);
2276
      code = TSDB_CODE_MND_NO_ENOUGH_VNODES;
×
2277
      goto _OVER;
×
2278
    }
2279
    int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
16✔
2280
    if (pNew2->memAvail - vgMem - pNew2->memUsed <= 0) {
16!
2281
      mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
×
2282
             pVgroup->dbName, pVgroup->vgId, vgMem, pNew2->id, pNew2->memAvail, pNew2->memUsed);
2283
      code = TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE;
×
2284
      goto _OVER;
×
2285
    } else {
2286
      pNew2->memUsed += vgMem;
16✔
2287
    }
2288
    TAOS_CHECK_GOTO(mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pNew2->id), NULL, _OVER);
16!
2289
    TAOS_CHECK_GOTO(mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pOld2->id), NULL, _OVER);
16!
2290
  }
2291

2292
  if (pNew3 != NULL && pOld3 != NULL) {
77!
2293
    int32_t numOfVnodes = mndGetVnodesNum(pMnode, pNew3->id);
8✔
2294
    if (numOfVnodes >= pNew3->numOfSupportVnodes) {
8!
2295
      mError("vgId:%d, no enough vnodes in dnode:%d, numOfVnodes:%d support:%d", newVg.vgId, pNew3->id, numOfVnodes,
×
2296
             pNew3->numOfSupportVnodes);
2297
      code = TSDB_CODE_MND_NO_ENOUGH_VNODES;
×
2298
      goto _OVER;
×
2299
    }
2300
    int64_t vgMem = mndGetVgroupMemory(pMnode, NULL, pVgroup);
8✔
2301
    if (pNew3->memAvail - vgMem - pNew3->memUsed <= 0) {
8!
2302
      mError("db:%s, vgId:%d, no enough memory:%" PRId64 " in dnode:%d avail:%" PRId64 " used:%" PRId64,
×
2303
             pVgroup->dbName, pVgroup->vgId, vgMem, pNew3->id, pNew3->memAvail, pNew3->memUsed);
2304
      code = TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE;
×
2305
      goto _OVER;
×
2306
    } else {
2307
      pNew3->memUsed += vgMem;
8✔
2308
    }
2309
    TAOS_CHECK_GOTO(mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pNew3->id), NULL, _OVER);
8!
2310
    TAOS_CHECK_GOTO(mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pOld3->id), NULL, _OVER);
8!
2311
  }
2312

2313
  {
2314
    SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
77✔
2315
    if (pRaw == NULL) {
77!
2316
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2317
      if (terrno != 0) code = terrno;
×
2318
      goto _OVER;
×
2319
    }
2320
    if ((code = mndTransAppendCommitlog(pTrans, pRaw)) != 0) {
77!
2321
      sdbFreeRaw(pRaw);
×
2322
      goto _OVER;
×
2323
    }
2324
    code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
77✔
2325
    if (code != 0) {
77!
2326
      mError("vgId:%d, failed to set raw status since %s at line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
2327
      goto _OVER;
×
2328
    }
2329
  }
2330

2331
  mInfo("vgId:%d, vgroup info after redistribute, replica:%d", newVg.vgId, newVg.replica);
77!
2332
  for (int32_t i = 0; i < newVg.replica; ++i) {
230✔
2333
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
153!
2334
  }
2335

2336
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
77!
2337
  code = 0;
77✔
2338

2339
_OVER:
79✔
2340
  mndTransDrop(pTrans);
79✔
2341
  mndReleaseDb(pMnode, pDb);
79✔
2342
  TAOS_RETURN(code);
79✔
2343
}
2344

2345
static int32_t mndProcessRedistributeVgroupMsg(SRpcMsg *pReq) {
94✔
2346
  SMnode    *pMnode = pReq->info.node;
94✔
2347
  SDnodeObj *pNew1 = NULL;
94✔
2348
  SDnodeObj *pNew2 = NULL;
94✔
2349
  SDnodeObj *pNew3 = NULL;
94✔
2350
  SDnodeObj *pOld1 = NULL;
94✔
2351
  SDnodeObj *pOld2 = NULL;
94✔
2352
  SDnodeObj *pOld3 = NULL;
94✔
2353
  SVgObj    *pVgroup = NULL;
94✔
2354
  SDbObj    *pDb = NULL;
94✔
2355
  int32_t    code = -1;
94✔
2356
  int64_t    curMs = taosGetTimestampMs();
94✔
2357
  int32_t    newDnodeId[3] = {0};
94✔
2358
  int32_t    oldDnodeId[3] = {0};
94✔
2359
  int32_t    newIndex = -1;
94✔
2360
  int32_t    oldIndex = -1;
94✔
2361

2362
  SRedistributeVgroupReq req = {0};
94✔
2363
  if (tDeserializeSRedistributeVgroupReq(pReq->pCont, pReq->contLen, &req) != 0) {
94!
2364
    code = TSDB_CODE_INVALID_MSG;
×
2365
    goto _OVER;
×
2366
  }
2367

2368
  mInfo("vgId:%d, start to redistribute vgroup to dnode %d:%d:%d", req.vgId, req.dnodeId1, req.dnodeId2, req.dnodeId3);
94!
2369
  if ((code = mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_REDISTRIBUTE_VGROUP)) != 0) {
94✔
2370
    goto _OVER;
1✔
2371
  }
2372

2373
  pVgroup = mndAcquireVgroup(pMnode, req.vgId);
93✔
2374
  if (pVgroup == NULL) {
93✔
2375
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
3✔
2376
    if (terrno != 0) code = terrno;
3!
2377
    goto _OVER;
3✔
2378
  }
2379

2380
  pDb = mndAcquireDb(pMnode, pVgroup->dbName);
90✔
2381
  if (pDb == NULL) {
90!
2382
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2383
    if (terrno != 0) code = terrno;
×
2384
    goto _OVER;
×
2385
  }
2386

2387
  if (pVgroup->replica == 1) {
90✔
2388
    if (req.dnodeId1 <= 0 || req.dnodeId2 > 0 || req.dnodeId3 > 0) {
43!
2389
      code = TSDB_CODE_MND_INVALID_REPLICA;
×
2390
      goto _OVER;
×
2391
    }
2392

2393
    if (req.dnodeId1 == pVgroup->vnodeGid[0].dnodeId) {
43✔
2394
      // terrno = TSDB_CODE_MND_VGROUP_UN_CHANGED;
2395
      code = 0;
1✔
2396
      goto _OVER;
1✔
2397
    }
2398

2399
    pNew1 = mndAcquireDnode(pMnode, req.dnodeId1);
42✔
2400
    if (pNew1 == NULL) {
42!
2401
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2402
      if (terrno != 0) code = terrno;
×
2403
      goto _OVER;
×
2404
    }
2405
    if (!mndIsDnodeOnline(pNew1, curMs)) {
42!
2406
      code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
2407
      goto _OVER;
×
2408
    }
2409

2410
    pOld1 = mndAcquireDnode(pMnode, pVgroup->vnodeGid[0].dnodeId);
42✔
2411
    if (pOld1 == NULL) {
42!
2412
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2413
      if (terrno != 0) code = terrno;
×
2414
      goto _OVER;
×
2415
    }
2416
    if (!mndIsDnodeOnline(pOld1, curMs)) {
42✔
2417
      code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
2✔
2418
      goto _OVER;
2✔
2419
    }
2420

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

2423
  } else if (pVgroup->replica == 3) {
47!
2424
    if (req.dnodeId1 <= 0 || req.dnodeId2 <= 0 || req.dnodeId3 <= 0) {
47!
2425
      code = TSDB_CODE_MND_INVALID_REPLICA;
4✔
2426
      goto _OVER;
4✔
2427
    }
2428

2429
    if (req.dnodeId1 == req.dnodeId2 || req.dnodeId1 == req.dnodeId3 || req.dnodeId2 == req.dnodeId3) {
43!
2430
      code = TSDB_CODE_MND_INVALID_REPLICA;
1✔
2431
      goto _OVER;
1✔
2432
    }
2433

2434
    if (req.dnodeId1 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId1 != pVgroup->vnodeGid[1].dnodeId &&
42✔
2435
        req.dnodeId1 != pVgroup->vnodeGid[2].dnodeId) {
22✔
2436
      newDnodeId[++newIndex] = req.dnodeId1;
18✔
2437
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
18!
2438
    }
2439

2440
    if (req.dnodeId2 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[1].dnodeId &&
42✔
2441
        req.dnodeId2 != pVgroup->vnodeGid[2].dnodeId) {
28✔
2442
      newDnodeId[++newIndex] = req.dnodeId2;
21✔
2443
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
21!
2444
    }
2445

2446
    if (req.dnodeId3 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId3 != pVgroup->vnodeGid[1].dnodeId &&
42✔
2447
        req.dnodeId3 != pVgroup->vnodeGid[2].dnodeId) {
32✔
2448
      newDnodeId[++newIndex] = req.dnodeId3;
28✔
2449
      mInfo("vgId:%d, dnode:%d will be added, index:%d", pVgroup->vgId, newDnodeId[newIndex], newIndex);
28!
2450
    }
2451

2452
    if (req.dnodeId1 != pVgroup->vnodeGid[0].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[0].dnodeId &&
42✔
2453
        req.dnodeId3 != pVgroup->vnodeGid[0].dnodeId) {
28✔
2454
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[0].dnodeId;
22✔
2455
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
22!
2456
    }
2457

2458
    if (req.dnodeId1 != pVgroup->vnodeGid[1].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[1].dnodeId &&
42✔
2459
        req.dnodeId3 != pVgroup->vnodeGid[1].dnodeId) {
22✔
2460
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[1].dnodeId;
18✔
2461
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
18!
2462
    }
2463

2464
    if (req.dnodeId1 != pVgroup->vnodeGid[2].dnodeId && req.dnodeId2 != pVgroup->vnodeGid[2].dnodeId &&
42✔
2465
        req.dnodeId3 != pVgroup->vnodeGid[2].dnodeId) {
31✔
2466
      oldDnodeId[++oldIndex] = pVgroup->vnodeGid[2].dnodeId;
27✔
2467
      mInfo("vgId:%d, dnode:%d will be removed, index:%d", pVgroup->vgId, oldDnodeId[oldIndex], oldIndex);
27!
2468
    }
2469

2470
    if (newDnodeId[0] != 0) {
42✔
2471
      pNew1 = mndAcquireDnode(pMnode, newDnodeId[0]);
41✔
2472
      if (pNew1 == NULL) {
41!
2473
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2474
        if (terrno != 0) code = terrno;
×
2475
        goto _OVER;
×
2476
      }
2477
      if (!mndIsDnodeOnline(pNew1, curMs)) {
41✔
2478
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
1✔
2479
        goto _OVER;
1✔
2480
      }
2481
    }
2482

2483
    if (newDnodeId[1] != 0) {
41✔
2484
      pNew2 = mndAcquireDnode(pMnode, newDnodeId[1]);
17✔
2485
      if (pNew2 == NULL) {
17!
2486
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2487
        if (terrno != 0) code = terrno;
×
2488
        goto _OVER;
×
2489
      }
2490
      if (!mndIsDnodeOnline(pNew2, curMs)) {
17!
2491
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
2492
        goto _OVER;
×
2493
      }
2494
    }
2495

2496
    if (newDnodeId[2] != 0) {
41✔
2497
      pNew3 = mndAcquireDnode(pMnode, newDnodeId[2]);
9✔
2498
      if (pNew3 == NULL) {
9!
2499
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2500
        if (terrno != 0) code = terrno;
×
2501
        goto _OVER;
×
2502
      }
2503
      if (!mndIsDnodeOnline(pNew3, curMs)) {
9!
2504
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
2505
        goto _OVER;
×
2506
      }
2507
    }
2508

2509
    if (oldDnodeId[0] != 0) {
41✔
2510
      pOld1 = mndAcquireDnode(pMnode, oldDnodeId[0]);
40✔
2511
      if (pOld1 == NULL) {
40!
2512
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2513
        if (terrno != 0) code = terrno;
×
2514
        goto _OVER;
×
2515
      }
2516
      if (!mndIsDnodeOnline(pOld1, curMs)) {
40✔
2517
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
1✔
2518
        goto _OVER;
1✔
2519
      }
2520
    }
2521

2522
    if (oldDnodeId[1] != 0) {
40✔
2523
      pOld2 = mndAcquireDnode(pMnode, oldDnodeId[1]);
16✔
2524
      if (pOld2 == NULL) {
16!
2525
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2526
        if (terrno != 0) code = terrno;
×
2527
        goto _OVER;
×
2528
      }
2529
      if (!mndIsDnodeOnline(pOld2, curMs)) {
16!
2530
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
2531
        goto _OVER;
×
2532
      }
2533
    }
2534

2535
    if (oldDnodeId[2] != 0) {
40✔
2536
      pOld3 = mndAcquireDnode(pMnode, oldDnodeId[2]);
8✔
2537
      if (pOld3 == NULL) {
8!
2538
        code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2539
        if (terrno != 0) code = terrno;
×
2540
        goto _OVER;
×
2541
      }
2542
      if (!mndIsDnodeOnline(pOld3, curMs)) {
8!
2543
        code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
×
2544
        goto _OVER;
×
2545
      }
2546
    }
2547

2548
    if (pNew1 == NULL && pOld1 == NULL && pNew2 == NULL && pOld2 == NULL && pNew3 == NULL && pOld3 == NULL) {
40!
2549
      // terrno = TSDB_CODE_MND_VGROUP_UN_CHANGED;
2550
      code = 0;
1✔
2551
      goto _OVER;
1✔
2552
    }
2553

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

2556
  } else {
2557
    code = TSDB_CODE_MND_REQ_REJECTED;
×
2558
    goto _OVER;
×
2559
  }
2560

2561
  if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
79✔
2562

2563
  char obj[33] = {0};
79✔
2564
  sprintf(obj, "%d", req.vgId);
79✔
2565

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

2568
_OVER:
94✔
2569
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
94✔
2570
    mError("vgId:%d, failed to redistribute to dnode %d:%d:%d since %s", req.vgId, req.dnodeId1, req.dnodeId2,
15!
2571
           req.dnodeId3, tstrerror(code));
2572
  }
2573

2574
  mndReleaseDnode(pMnode, pNew1);
94✔
2575
  mndReleaseDnode(pMnode, pNew2);
94✔
2576
  mndReleaseDnode(pMnode, pNew3);
94✔
2577
  mndReleaseDnode(pMnode, pOld1);
94✔
2578
  mndReleaseDnode(pMnode, pOld2);
94✔
2579
  mndReleaseDnode(pMnode, pOld3);
94✔
2580
  mndReleaseVgroup(pMnode, pVgroup);
94✔
2581
  mndReleaseDb(pMnode, pDb);
94✔
2582
  tFreeSRedistributeVgroupReq(&req);
94✔
2583

2584
  TAOS_RETURN(code);
94✔
2585
}
2586

2587
static void *mndBuildSForceBecomeFollowerReq(SMnode *pMnode, SVgObj *pVgroup, int32_t dnodeId, int32_t *pContLen) {
2✔
2588
  SForceBecomeFollowerReq balanceReq = {
2✔
2589
      .vgId = pVgroup->vgId,
2✔
2590
  };
2591

2592
  int32_t contLen = tSerializeSForceBecomeFollowerReq(NULL, 0, &balanceReq);
2✔
2593
  if (contLen < 0) {
2!
2594
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
2595
    return NULL;
×
2596
  }
2597
  contLen += sizeof(SMsgHead);
2✔
2598

2599
  void *pReq = taosMemoryMalloc(contLen);
2✔
2600
  if (pReq == NULL) {
2!
2601
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
2602
    return NULL;
×
2603
  }
2604

2605
  SMsgHead *pHead = pReq;
2✔
2606
  pHead->contLen = htonl(contLen);
2✔
2607
  pHead->vgId = htonl(pVgroup->vgId);
2✔
2608

2609
  if (tSerializeSForceBecomeFollowerReq((char *)pReq + sizeof(SMsgHead), contLen, &balanceReq) < 0) {
2!
2610
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
2611
    taosMemoryFree(pReq);
×
2612
    return NULL;
×
2613
  }
2614
  *pContLen = contLen;
2✔
2615
  return pReq;
2✔
2616
}
2617

2618
int32_t mndAddBalanceVgroupLeaderAction(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup, int32_t dnodeId) {
2✔
2619
  int32_t    code = 0;
2✔
2620
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
2✔
2621
  if (pDnode == NULL) {
2!
2622
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2623
    if (terrno != 0) code = terrno;
×
2624
    TAOS_RETURN(code);
×
2625
  }
2626

2627
  STransAction action = {0};
2✔
2628
  action.epSet = mndGetDnodeEpset(pDnode);
2✔
2629
  mndReleaseDnode(pMnode, pDnode);
2✔
2630

2631
  int32_t contLen = 0;
2✔
2632
  void   *pReq = mndBuildSForceBecomeFollowerReq(pMnode, pVgroup, dnodeId, &contLen);
2✔
2633
  if (pReq == NULL) {
2!
2634
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2635
    if (terrno != 0) code = terrno;
×
2636
    TAOS_RETURN(code);
×
2637
  }
2638

2639
  action.pCont = pReq;
2✔
2640
  action.contLen = contLen;
2✔
2641
  action.msgType = TDMT_SYNC_FORCE_FOLLOWER;
2✔
2642

2643
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
2!
2644
    taosMemoryFree(pReq);
×
2645
    TAOS_RETURN(code);
×
2646
  }
2647

2648
  TAOS_RETURN(code);
2✔
2649
}
2650

2651
int32_t mndAddVgroupBalanceToTrans(SMnode *pMnode, SVgObj *pVgroup, STrans *pTrans) {
4✔
2652
  int32_t code = 0;
4✔
2653
  SSdb   *pSdb = pMnode->pSdb;
4✔
2654

2655
  int32_t vgid = pVgroup->vgId;
4✔
2656
  int8_t  replica = pVgroup->replica;
4✔
2657

2658
  if (pVgroup->replica <= 1) {
4✔
2659
    mInfo("trans:%d, vgid:%d no need to balance, replica:%d", pTrans->id, vgid, replica);
1!
2660
    return -1;
1✔
2661
  }
2662

2663
  int32_t dnodeId = 0;
3✔
2664

2665
  for (int i = 0; i < replica; i++) {
7✔
2666
    if (pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_LEADER) {
6✔
2667
      dnodeId = pVgroup->vnodeGid[i].dnodeId;
2✔
2668
      break;
2✔
2669
    }
2670
  }
2671

2672
  bool       exist = false;
3✔
2673
  bool       online = false;
3✔
2674
  int64_t    curMs = taosGetTimestampMs();
3✔
2675
  SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId);
3✔
2676
  if (pDnode != NULL) {
3✔
2677
    exist = true;
2✔
2678
    online = mndIsDnodeOnline(pDnode, curMs);
2✔
2679
    mndReleaseDnode(pMnode, pDnode);
2✔
2680
  }
2681

2682
  if (exist && online) {
5!
2683
    mInfo("trans:%d, vgid:%d leader to dnode:%d", pTrans->id, vgid, dnodeId);
2!
2684

2685
    if ((code = mndAddBalanceVgroupLeaderAction(pMnode, pTrans, pVgroup, dnodeId)) != 0) {
2!
2686
      mError("trans:%d, vgid:%d failed to be balanced to dnode:%d", pTrans->id, vgid, dnodeId);
×
2687
      TAOS_RETURN(code);
×
2688
    }
2689

2690
    SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName);
2✔
2691
    if (pDb == NULL) {
2!
2692
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2693
      if (terrno != 0) code = terrno;
×
2694
      mError("trans:%d, vgid:%d failed to be balanced to dnode:%d, because db not exist", pTrans->id, vgid, dnodeId);
×
2695
      TAOS_RETURN(code);
×
2696
    }
2697

2698
    mndReleaseDb(pMnode, pDb);
2✔
2699
  } else {
2700
    mInfo("trans:%d, vgid:%d cant be balanced to dnode:%d, exist:%d, online:%d", pTrans->id, vgid, dnodeId, exist,
1!
2701
          online);
2702
  }
2703

2704
  TAOS_RETURN(code);
3✔
2705
}
2706

2707
extern int32_t mndProcessVgroupBalanceLeaderMsgImp(SRpcMsg *pReq);
2708

2709
int32_t mndProcessVgroupBalanceLeaderMsg(SRpcMsg *pReq) { return mndProcessVgroupBalanceLeaderMsgImp(pReq); }
4✔
2710

2711
#ifndef TD_ENTERPRISE
2712
int32_t mndProcessVgroupBalanceLeaderMsgImp(SRpcMsg *pReq) { return 0; }
2713
#endif
2714

2715
static int32_t mndCheckDnodeMemory(SMnode *pMnode, SDbObj *pOldDb, SDbObj *pNewDb, SVgObj *pOldVgroup,
429✔
2716
                                   SVgObj *pNewVgroup, SArray *pArray) {
2717
  for (int32_t i = 0; i < (int32_t)taosArrayGetSize(pArray); ++i) {
1,096✔
2718
    SDnodeObj *pDnode = taosArrayGet(pArray, i);
667✔
2719
    bool       inVgroup = false;
667✔
2720
    int64_t    oldMemUsed = 0;
667✔
2721
    int64_t    newMemUsed = 0;
667✔
2722
    mDebug("db:%s, vgId:%d, check dnode:%d, avail:%" PRId64 " used:%" PRId64, pNewVgroup->dbName, pNewVgroup->vgId,
667✔
2723
           pDnode->id, pDnode->memAvail, pDnode->memUsed);
2724
    for (int32_t j = 0; j < pOldVgroup->replica; ++j) {
1,958✔
2725
      SVnodeGid *pVgId = &pOldVgroup->vnodeGid[j];
1,291✔
2726
      if (pDnode->id == pVgId->dnodeId) {
1,291✔
2727
        oldMemUsed = mndGetVgroupMemory(pMnode, pOldDb, pOldVgroup);
637✔
2728
        inVgroup = true;
637✔
2729
      }
2730
    }
2731
    for (int32_t j = 0; j < pNewVgroup->replica; ++j) {
1,958✔
2732
      SVnodeGid *pVgId = &pNewVgroup->vnodeGid[j];
1,291✔
2733
      if (pDnode->id == pVgId->dnodeId) {
1,291✔
2734
        newMemUsed = mndGetVgroupMemory(pMnode, pNewDb, pNewVgroup);
637✔
2735
        inVgroup = true;
637✔
2736
      }
2737
    }
2738

2739
    mDebug("db:%s, vgId:%d, memory in dnode:%d, oldUsed:%" PRId64 ", newUsed:%" PRId64, pNewVgroup->dbName,
667✔
2740
           pNewVgroup->vgId, pDnode->id, oldMemUsed, newMemUsed);
2741

2742
    pDnode->memUsed = pDnode->memUsed - oldMemUsed + newMemUsed;
667✔
2743
    if (pDnode->memAvail - pDnode->memUsed <= 0) {
667!
2744
      mError("db:%s, vgId:%d, no enough memory in dnode:%d, avail:%" PRId64 " used:%" PRId64, pNewVgroup->dbName,
×
2745
             pNewVgroup->vgId, pDnode->id, pDnode->memAvail, pDnode->memUsed);
2746
      TAOS_RETURN(TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE);
×
2747
    } else if (inVgroup) {
667✔
2748
      mInfo("db:%s, vgId:%d, memory in dnode:%d, avail:%" PRId64 " used:%" PRId64, pNewVgroup->dbName, pNewVgroup->vgId,
637!
2749
            pDnode->id, pDnode->memAvail, pDnode->memUsed);
2750
    } else {
2751
    }
2752
  }
2753
  return 0;
429✔
2754
}
2755

2756
int32_t mndBuildAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pOldDb, SDbObj *pNewDb, SVgObj *pVgroup,
487✔
2757
                                  SArray *pArray, SVgObj *pNewVgroup) {
2758
  int32_t code = 0;
487✔
2759
  memcpy(pNewVgroup, pVgroup, sizeof(SVgObj));
487✔
2760

2761
  if (pVgroup->replica <= 0 || pVgroup->replica == pNewDb->cfg.replications) {
487!
2762
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfigAction(pMnode, pTrans, pNewDb, pVgroup));
429!
2763
    TAOS_CHECK_RETURN(mndCheckDnodeMemory(pMnode, pOldDb, pNewDb, pNewVgroup, pVgroup, pArray));
429!
2764
    return 0;
429✔
2765
  }
2766

2767
  mndTransSetSerial(pTrans);
58✔
2768

2769
  if (pNewVgroup->replica == 1 && pNewDb->cfg.replications == 3) {
58!
2770
    mInfo("db:%s, vgId:%d, will add 2 vnodes, vn:0 dnode:%d", pVgroup->dbName, pVgroup->vgId,
54!
2771
          pVgroup->vnodeGid[0].dnodeId);
2772

2773
    // add second
2774
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, pNewVgroup, pArray));
54!
2775

2776
    // learner stage
2777
    pNewVgroup->vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
54✔
2778
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
54✔
2779
    TAOS_CHECK_RETURN(
54!
2780
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
2781

2782
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &pNewVgroup->vnodeGid[1]));
54!
2783

2784
    // follower stage
2785
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
54✔
2786
    TAOS_CHECK_RETURN(mndAddAlterVnodeTypeAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
54!
2787
    TAOS_CHECK_RETURN(
54!
2788
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
2789

2790
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
54!
2791

2792
    // add third
2793
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, pNewVgroup, pArray));
54✔
2794

2795
    pNewVgroup->vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
44✔
2796
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
44✔
2797
    pNewVgroup->vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_VOTER;
44✔
2798
    TAOS_CHECK_RETURN(
44!
2799
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
2800
    TAOS_CHECK_RETURN(
44!
2801
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
2802
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &pNewVgroup->vnodeGid[2]));
44!
2803

2804
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
44!
2805
  } else if (pNewVgroup->replica == 3 && pNewDb->cfg.replications == 1) {
8!
2806
    mInfo("db:%s, vgId:%d, will remove 2 vnodes, vn:0 dnode:%d vn:1 dnode:%d vn:2 dnode:%d", pVgroup->dbName,
4!
2807
          pVgroup->vgId, pVgroup->vnodeGid[0].dnodeId, pVgroup->vnodeGid[1].dnodeId, pVgroup->vnodeGid[2].dnodeId);
2808

2809
    SVnodeGid del1 = {0};
4✔
2810
    SVnodeGid del2 = {0};
4✔
2811
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroup(pMnode, pTrans, pNewVgroup, pArray, &del1));
4!
2812
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &del1, true));
4!
2813
    TAOS_CHECK_RETURN(
4!
2814
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
2815
    TAOS_CHECK_RETURN(
4!
2816
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
2817
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
4!
2818

2819
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroup(pMnode, pTrans, pNewVgroup, pArray, &del2));
4!
2820
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, pNewVgroup, &del2, true));
4!
2821
    TAOS_CHECK_RETURN(
4!
2822
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
2823
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
4!
2824
  } else if (pNewVgroup->replica == 1 && pNewDb->cfg.replications == 2) {
×
2825
    mInfo("db:%s, vgId:%d, will add 1 vnode, vn:0 dnode:%d", pVgroup->dbName, pVgroup->vgId,
×
2826
          pVgroup->vnodeGid[0].dnodeId);
2827

2828
    // add second
2829
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, pNewVgroup, pArray));
×
2830

2831
    // learner stage
2832
    pNewVgroup->vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
2833
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
2834
    TAOS_CHECK_RETURN(
×
2835
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
2836

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

2839
    // follower stage
2840
    pNewVgroup->vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
2841
    TAOS_CHECK_RETURN(mndAddAlterVnodeTypeAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[1].dnodeId));
×
2842
    TAOS_CHECK_RETURN(
×
2843
        mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, pNewVgroup, pNewVgroup->vnodeGid[0].dnodeId));
2844

2845
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, pNewVgroup));
×
2846
  } else {
2847
    return -1;
×
2848
  }
2849

2850
  mndSortVnodeGid(pNewVgroup);
48✔
2851

2852
  {
2853
    SSdbRaw *pVgRaw = mndVgroupActionEncode(pNewVgroup);
48✔
2854
    if (pVgRaw == NULL) {
48!
2855
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2856
      if (terrno != 0) code = terrno;
×
2857
      TAOS_RETURN(code);
×
2858
    }
2859
    if ((code = mndTransAppendCommitlog(pTrans, pVgRaw)) != 0) {
48!
2860
      sdbFreeRaw(pVgRaw);
×
2861
      TAOS_RETURN(code);
×
2862
    }
2863
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
48✔
2864
    if (code != 0) {
48!
2865
      mError("vgId:%d, failed to set raw status since %s at line:%d", pNewVgroup->vgId, tstrerror(code), __LINE__);
×
2866
      TAOS_RETURN(code);
×
2867
    }
2868
  }
2869

2870
  TAOS_RETURN(code);
48✔
2871
}
2872

2873
int32_t mndBuildRaftAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pOldDb, SDbObj *pNewDb, SVgObj *pVgroup,
×
2874
                                      SArray *pArray) {
2875
  int32_t code = 0;
×
2876
  SVgObj  newVgroup = {0};
×
2877
  memcpy(&newVgroup, pVgroup, sizeof(SVgObj));
×
2878

2879
  if (pVgroup->replica <= 0 || pVgroup->replica == pNewDb->cfg.replications) {
×
2880
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfigAction(pMnode, pTrans, pNewDb, pVgroup));
×
2881
    TAOS_CHECK_RETURN(mndCheckDnodeMemory(pMnode, pOldDb, pNewDb, &newVgroup, pVgroup, pArray));
×
2882
    return 0;
×
2883
  }
2884

2885
  mndTransSetSerial(pTrans);
×
2886

2887
  mInfo("trans:%d, vgId:%d, alter vgroup, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id, pVgroup->vgId,
×
2888
        pVgroup->syncConfChangeVer, pVgroup->version, pVgroup->replica);
2889

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

2894
    // add second
2895
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVgroup, pArray));
×
2896
    // add third
2897
    TAOS_CHECK_RETURN(mndAddVnodeToVgroup(pMnode, pTrans, &newVgroup, pArray));
×
2898

2899
    // add learner stage
2900
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
2901
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
2902
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
2903
    TAOS_CHECK_RETURN(
×
2904
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
2905
    mInfo("trans:%d, vgId:%d, add change config, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id,
×
2906
          pVgroup->vgId, newVgroup.syncConfChangeVer, pVgroup->version, pVgroup->replica);
2907
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &newVgroup.vnodeGid[1]));
×
2908
    mInfo("trans:%d, vgId:%d, create vnode, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id, pVgroup->vgId,
×
2909
          newVgroup.syncConfChangeVer, pVgroup->version, pVgroup->replica);
2910
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &newVgroup.vnodeGid[2]));
×
2911
    mInfo("trans:%d, vgId:%d, create vnode, syncConfChangeVer:%d, version:%d, replica:%d", pTrans->id, pVgroup->vgId,
×
2912
          newVgroup.syncConfChangeVer, pVgroup->version, pVgroup->replica);
2913

2914
    // check learner
2915
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
2916
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
2917
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
2918
    TAOS_CHECK_RETURN(
×
2919
        mndAddCheckLearnerCatchupAction(pMnode, pTrans, pNewDb, &newVgroup, newVgroup.vnodeGid[1].dnodeId));
2920
    TAOS_CHECK_RETURN(
×
2921
        mndAddCheckLearnerCatchupAction(pMnode, pTrans, pNewDb, &newVgroup, newVgroup.vnodeGid[2].dnodeId));
2922

2923
    // change raft type
2924
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
2925
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
2926
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
2927
    TAOS_CHECK_RETURN(
×
2928
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
2929

2930
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
2931

2932
    newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
2933
    newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
2934
    newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
2935
    TAOS_CHECK_RETURN(
×
2936
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
2937

2938
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
2939

2940
    SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
×
2941
    if (pVgRaw == NULL) {
×
2942
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2943
      if (terrno != 0) code = terrno;
×
2944
      TAOS_RETURN(code);
×
2945
    }
2946
    if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
×
2947
      sdbFreeRaw(pVgRaw);
×
2948
      TAOS_RETURN(code);
×
2949
    }
2950
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
2951
    if (code != 0) {
×
2952
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
2953
             __LINE__);
2954
      TAOS_RETURN(code);
×
2955
    }
2956
  } else if (newVgroup.replica == 3 && pNewDb->cfg.replications == 1) {
×
2957
    mInfo("db:%s, vgId:%d, will remove 2 vnodes, vn:0 dnode:%d vn:1 dnode:%d vn:2 dnode:%d", pVgroup->dbName,
×
2958
          pVgroup->vgId, pVgroup->vnodeGid[0].dnodeId, pVgroup->vnodeGid[1].dnodeId, pVgroup->vnodeGid[2].dnodeId);
2959

2960
    SVnodeGid del1 = {0};
×
2961
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroupWithoutSave(pMnode, pTrans, &newVgroup, pArray, &del1));
×
2962

2963
    TAOS_CHECK_RETURN(
×
2964
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
2965

2966
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
2967

2968
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &del1, true));
×
2969

2970
    SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
×
2971
    if (pVgRaw == NULL) {
×
2972
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2973
      if (terrno != 0) code = terrno;
×
2974
      TAOS_RETURN(code);
×
2975
    }
2976
    if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
×
2977
      sdbFreeRaw(pVgRaw);
×
2978
      TAOS_RETURN(code);
×
2979
    }
2980
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
2981
    if (code != 0) {
×
2982
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
2983
             __LINE__);
2984
      TAOS_RETURN(code);
×
2985
    }
2986

2987
    SVnodeGid del2 = {0};
×
2988
    TAOS_CHECK_RETURN(mndRemoveVnodeFromVgroupWithoutSave(pMnode, pTrans, &newVgroup, pArray, &del2));
×
2989

2990
    TAOS_CHECK_RETURN(
×
2991
        mndAddChangeConfigAction(pMnode, pTrans, pNewDb, pVgroup, &newVgroup, newVgroup.vnodeGid[0].dnodeId));
2992

2993
    TAOS_CHECK_RETURN(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup));
×
2994

2995
    TAOS_CHECK_RETURN(mndAddDropVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &del2, true));
×
2996

2997
    pVgRaw = mndVgroupActionEncode(&newVgroup);
×
2998
    if (pVgRaw == NULL) {
×
2999
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3000
      if (terrno != 0) code = terrno;
×
3001
      TAOS_RETURN(code);
×
3002
    }
3003
    if ((code = mndTransAppendRedolog(pTrans, pVgRaw)) != 0) {
×
3004
      sdbFreeRaw(pVgRaw);
×
3005
      TAOS_RETURN(code);
×
3006
    }
3007
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
3008
    if (code != 0) {
×
3009
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
3010
             __LINE__);
3011
      TAOS_RETURN(code);
×
3012
    }
3013
  } else {
3014
    return -1;
×
3015
  }
3016

3017
  mndSortVnodeGid(&newVgroup);
×
3018

3019
  {
3020
    SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
×
3021
    if (pVgRaw == NULL) {
×
3022
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3023
      if (terrno != 0) code = terrno;
×
3024
      TAOS_RETURN(code);
×
3025
    }
3026
    if ((code = mndTransAppendCommitlog(pTrans, pVgRaw)) != 0) {
×
3027
      sdbFreeRaw(pVgRaw);
×
3028
      TAOS_RETURN(code);
×
3029
    }
3030
    code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
×
3031
    if (code != 0) {
×
3032
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code),
×
3033
             __LINE__);
3034
      TAOS_RETURN(code);
×
3035
    }
3036
  }
3037

3038
  TAOS_RETURN(code);
×
3039
}
3040

3041
int32_t mndBuildRestoreAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *db, SVgObj *pVgroup, SDnodeObj *pDnode,
10✔
3042
                                         SDnodeObj *pAnotherDnode) {
3043
  int32_t code = 0;
10✔
3044
  SVgObj  newVgroup = {0};
10✔
3045
  memcpy(&newVgroup, pVgroup, sizeof(SVgObj));
10✔
3046

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

3049
  if (newVgroup.replica == 1) {
10!
3050
    int selected = 0;
×
3051
    for (int i = 0; i < newVgroup.replica; i++) {
×
3052
      newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3053
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
3054
        selected = i;
×
3055
      }
3056
    }
3057
    TAOS_CHECK_RETURN(mndAddCreateVnodeAction(pMnode, pTrans, db, &newVgroup, &newVgroup.vnodeGid[selected]));
×
3058
  } else if (newVgroup.replica == 2) {
10!
3059
    for (int i = 0; i < newVgroup.replica; i++) {
×
3060
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
3061
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3062
      } else {
3063
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3064
      }
3065
    }
3066
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pAnotherDnode));
×
3067

3068
    for (int i = 0; i < newVgroup.replica; i++) {
×
3069
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
3070
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_LEARNER;
×
3071
      } else {
3072
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3073
      }
3074
    }
3075
    TAOS_CHECK_RETURN(mndRestoreAddCreateVnodeAction(pMnode, pTrans, db, &newVgroup, pDnode));
×
3076

3077
    for (int i = 0; i < newVgroup.replica; i++) {
×
3078
      newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
×
3079
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
×
3080
      }
3081
    }
3082
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pDnode));
×
3083
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pAnotherDnode));
×
3084
  } else if (newVgroup.replica == 3) {
10!
3085
    for (int i = 0; i < newVgroup.replica; i++) {
40✔
3086
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
30✔
3087
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_LEARNER;
10✔
3088
      } else {
3089
        newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
20✔
3090
      }
3091
    }
3092
    TAOS_CHECK_RETURN(mndRestoreAddCreateVnodeAction(pMnode, pTrans, db, &newVgroup, pDnode));
10!
3093

3094
    for (int i = 0; i < newVgroup.replica; i++) {
40✔
3095
      newVgroup.vnodeGid[i].nodeRole = TAOS_SYNC_ROLE_VOTER;
30✔
3096
      if (newVgroup.vnodeGid[i].dnodeId == pDnode->id) {
30✔
3097
      }
3098
    }
3099
    TAOS_CHECK_RETURN(mndRestoreAddAlterVnodeTypeAction(pMnode, pTrans, db, &newVgroup, pDnode));
10!
3100
  }
3101
  SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup);
10✔
3102
  if (pVgRaw == NULL) {
10!
3103
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3104
    if (terrno != 0) code = terrno;
×
3105
    TAOS_RETURN(code);
×
3106
  }
3107
  if ((code = mndTransAppendCommitlog(pTrans, pVgRaw)) != 0) {
10!
3108
    sdbFreeRaw(pVgRaw);
×
3109
    TAOS_RETURN(code);
×
3110
  }
3111
  code = sdbSetRawStatus(pVgRaw, SDB_STATUS_READY);
10✔
3112
  if (code != 0) {
10!
3113
    mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVgroup.vgId, tstrerror(code), __LINE__);
×
3114
    TAOS_RETURN(code);
×
3115
  }
3116

3117
  TAOS_RETURN(code);
10✔
3118
}
3119

3120
static int32_t mndAddAdjustVnodeHashRangeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) {
×
3121
  return 0;
×
3122
}
3123

3124
typedef int32_t (*FpTransActionCb)(STrans *pTrans, SSdbRaw *pRaw);
3125

3126
static int32_t mndAddVgStatusAction(STrans *pTrans, SVgObj *pVg, ESdbStatus vgStatus, ETrnStage stage) {
128✔
3127
  int32_t         code = 0;
128✔
3128
  FpTransActionCb appendActionCb = (stage == TRN_STAGE_COMMIT_ACTION) ? mndTransAppendCommitlog : mndTransAppendRedolog;
128✔
3129
  SSdbRaw        *pRaw = mndVgroupActionEncode(pVg);
128✔
3130
  if (pRaw == NULL) {
128!
3131
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3132
    if (terrno != 0) code = terrno;
×
3133
    goto _err;
×
3134
  }
3135
  if ((code = appendActionCb(pTrans, pRaw)) != 0) goto _err;
128!
3136
  code = sdbSetRawStatus(pRaw, vgStatus);
128✔
3137
  if (code != 0) {
128!
3138
    mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", pVg->vgId, tstrerror(code), __LINE__);
×
3139
    goto _err;
×
3140
  }
3141
  pRaw = NULL;
128✔
3142
  TAOS_RETURN(code);
128✔
3143
_err:
×
3144
  sdbFreeRaw(pRaw);
×
3145
  TAOS_RETURN(code);
×
3146
}
3147

3148
static int32_t mndAddDbStatusAction(STrans *pTrans, SDbObj *pDb, ESdbStatus dbStatus, ETrnStage stage) {
50✔
3149
  int32_t         code = 0;
50✔
3150
  FpTransActionCb appendActionCb = (stage == TRN_STAGE_COMMIT_ACTION) ? mndTransAppendCommitlog : mndTransAppendRedolog;
50✔
3151
  SSdbRaw        *pRaw = mndDbActionEncode(pDb);
50✔
3152
  if (pRaw == NULL) {
50!
3153
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3154
    if (terrno != 0) code = terrno;
×
3155
    goto _err;
×
3156
  }
3157
  if ((code = appendActionCb(pTrans, pRaw)) != 0) goto _err;
50!
3158
  code = sdbSetRawStatus(pRaw, dbStatus);
50✔
3159
  if (code != 0) {
50!
3160
    mError("db:%s, failed to set raw status to ready, error:%s, line:%d", pDb->name, tstrerror(code), __LINE__);
×
3161
    goto _err;
×
3162
  }
3163
  pRaw = NULL;
50✔
3164
  TAOS_RETURN(code);
50✔
3165
_err:
×
3166
  sdbFreeRaw(pRaw);
×
3167
  TAOS_RETURN(code);
×
3168
}
3169

3170
int32_t mndSplitVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SVgObj *pVgroup) {
31✔
3171
  int32_t code = -1;
31✔
3172
  STrans *pTrans = NULL;
31✔
3173
  SDbObj  dbObj = {0};
31✔
3174
  SArray *pArray = mndBuildDnodesArray(pMnode, 0, NULL);
31✔
3175

3176
  int32_t numOfStreams = 0;
31✔
3177
  if ((code = mndGetNumOfStreams(pMnode, pDb->name, &numOfStreams)) != 0) {
31!
3178
    goto _OVER;
×
3179
  }
3180
  if (numOfStreams > 0) {
31!
3181
    code = TSDB_CODE_MND_STREAM_MUST_BE_DELETED;
×
3182
    goto _OVER;
×
3183
  }
3184

3185
#if defined(USE_S3)
3186
  extern int8_t tsS3Enabled;
3187
  if (tsS3Enabled) {
31!
3188
    code = TSDB_CODE_OPS_NOT_SUPPORT;
×
3189
    mError("vgId:%d, db:%s, s3 exists, split vgroup not allowed", pVgroup->vgId, pVgroup->dbName);
×
3190
    goto _OVER;
×
3191
  }
3192
#endif
3193

3194
  if (pDb->cfg.withArbitrator) {
31!
3195
    code = TSDB_CODE_OPS_NOT_SUPPORT;
×
3196
    mError("vgId:%d, db:%s, with arbitrator, split vgroup not allowed", pVgroup->vgId, pVgroup->dbName);
×
3197
    goto _OVER;
×
3198
  }
3199

3200
  pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB, pReq, "split-vgroup");
31✔
3201
  if (pTrans == NULL) {
31!
3202
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3203
    if (terrno != 0) code = terrno;
×
3204
    goto _OVER;
×
3205
  }
3206
  mndTransSetSerial(pTrans);
31✔
3207
  mInfo("trans:%d, used to split vgroup, vgId:%d", pTrans->id, pVgroup->vgId);
31!
3208

3209
  mndTransSetDbName(pTrans, pDb->name, NULL);
31✔
3210
  TAOS_CHECK_GOTO(mndTransCheckConflictWithCompact(pMnode, pTrans), NULL, _OVER);
31✔
3211

3212
  SVgObj newVg1 = {0};
30✔
3213
  memcpy(&newVg1, pVgroup, sizeof(SVgObj));
30✔
3214
  mInfo("vgId:%d, vgroup info before split, replica:%d hashBegin:%u hashEnd:%u", newVg1.vgId, newVg1.replica,
30!
3215
        newVg1.hashBegin, newVg1.hashEnd);
3216
  for (int32_t i = 0; i < newVg1.replica; ++i) {
102✔
3217
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg1.vgId, i, newVg1.vnodeGid[i].dnodeId);
72!
3218
  }
3219

3220
  if (newVg1.replica == 1) {
30✔
3221
    TAOS_CHECK_GOTO(mndAddVnodeToVgroup(pMnode, pTrans, &newVg1, pArray), NULL, _OVER);
9!
3222

3223
    newVg1.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
9✔
3224
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[0].dnodeId), NULL,
9!
3225
                    _OVER);
3226
    TAOS_CHECK_GOTO(mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg1, &newVg1.vnodeGid[1]), NULL, _OVER);
9!
3227

3228
    newVg1.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
9✔
3229
    TAOS_CHECK_GOTO(mndAddAlterVnodeTypeAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[1].dnodeId), NULL, _OVER);
9!
3230
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[0].dnodeId), NULL,
9!
3231
                    _OVER);
3232

3233
    TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg1), NULL, _OVER);
9!
3234
  } else if (newVg1.replica == 3) {
21!
3235
    SVnodeGid del1 = {0};
21✔
3236
    TAOS_CHECK_GOTO(mndRemoveVnodeFromVgroup(pMnode, pTrans, &newVg1, pArray, &del1), NULL, _OVER);
21!
3237
    TAOS_CHECK_GOTO(mndAddDropVnodeAction(pMnode, pTrans, pDb, &newVg1, &del1, true), NULL, _OVER);
21!
3238
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[0].dnodeId), NULL,
21!
3239
                    _OVER);
3240
    TAOS_CHECK_GOTO(mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[1].dnodeId), NULL,
21!
3241
                    _OVER);
3242
  } else {
3243
    goto _OVER;
×
3244
  }
3245

3246
  for (int32_t i = 0; i < newVg1.replica; ++i) {
90✔
3247
    TAOS_CHECK_GOTO(mndAddDisableVnodeWriteAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[i].dnodeId), NULL,
60!
3248
                    _OVER);
3249
  }
3250
  TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg1), NULL, _OVER);
30!
3251

3252
  SVgObj newVg2 = {0};
30✔
3253
  memcpy(&newVg2, &newVg1, sizeof(SVgObj));
30✔
3254
  newVg1.replica = 1;
30✔
3255
  newVg1.hashEnd = newVg1.hashBegin / 2 + newVg1.hashEnd / 2;
30✔
3256
  memset(&newVg1.vnodeGid[1], 0, sizeof(SVnodeGid));
30✔
3257

3258
  newVg2.replica = 1;
30✔
3259
  newVg2.hashBegin = newVg1.hashEnd + 1;
30✔
3260
  memcpy(&newVg2.vnodeGid[0], &newVg2.vnodeGid[1], sizeof(SVnodeGid));
30✔
3261
  memset(&newVg2.vnodeGid[1], 0, sizeof(SVnodeGid));
30✔
3262

3263
  mInfo("vgId:%d, vgroup info after split, replica:%d hashrange:[%u, %u] vnode:0 dnode:%d", newVg1.vgId, newVg1.replica,
30!
3264
        newVg1.hashBegin, newVg1.hashEnd, newVg1.vnodeGid[0].dnodeId);
3265
  for (int32_t i = 0; i < newVg1.replica; ++i) {
60✔
3266
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg1.vgId, i, newVg1.vnodeGid[i].dnodeId);
30!
3267
  }
3268
  mInfo("vgId:%d, vgroup info after split, replica:%d hashrange:[%u, %u] vnode:0 dnode:%d", newVg2.vgId, newVg2.replica,
30!
3269
        newVg2.hashBegin, newVg2.hashEnd, newVg2.vnodeGid[0].dnodeId);
3270
  for (int32_t i = 0; i < newVg1.replica; ++i) {
60✔
3271
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg2.vgId, i, newVg2.vnodeGid[i].dnodeId);
30!
3272
  }
3273

3274
  // alter vgId and hash range
3275
  int32_t maxVgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP);
30✔
3276
  int32_t srcVgId = newVg1.vgId;
30✔
3277
  newVg1.vgId = maxVgId;
30✔
3278
  TAOS_CHECK_GOTO(mndAddNewVgPrepareAction(pMnode, pTrans, &newVg1), NULL, _OVER);
30!
3279
  TAOS_CHECK_GOTO(mndAddAlterVnodeHashRangeAction(pMnode, pTrans, srcVgId, &newVg1), NULL, _OVER);
30!
3280

3281
  maxVgId++;
30✔
3282
  srcVgId = newVg2.vgId;
30✔
3283
  newVg2.vgId = maxVgId;
30✔
3284
  TAOS_CHECK_GOTO(mndAddNewVgPrepareAction(pMnode, pTrans, &newVg2), NULL, _OVER);
30!
3285
  TAOS_CHECK_GOTO(mndAddAlterVnodeHashRangeAction(pMnode, pTrans, srcVgId, &newVg2), NULL, _OVER);
30!
3286

3287
  TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg1), NULL, _OVER);
30!
3288
  TAOS_CHECK_GOTO(mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg2), NULL, _OVER);
30!
3289

3290
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg1, SDB_STATUS_READY, TRN_STAGE_REDO_ACTION), NULL, _OVER);
30!
3291
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg2, SDB_STATUS_READY, TRN_STAGE_REDO_ACTION), NULL, _OVER);
30!
3292
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, pVgroup, SDB_STATUS_DROPPED, TRN_STAGE_REDO_ACTION), NULL, _OVER);
30!
3293

3294
  // update db status
3295
  memcpy(&dbObj, pDb, sizeof(SDbObj));
30✔
3296
  if (dbObj.cfg.pRetensions != NULL) {
30!
3297
    dbObj.cfg.pRetensions = taosArrayDup(pDb->cfg.pRetensions, NULL);
×
3298
    if (dbObj.cfg.pRetensions == NULL) {
×
3299
      code = terrno;
×
3300
      goto _OVER;
×
3301
    }
3302
  }
3303
  dbObj.vgVersion++;
30✔
3304
  dbObj.updateTime = taosGetTimestampMs();
30✔
3305
  dbObj.cfg.numOfVgroups++;
30✔
3306
  TAOS_CHECK_GOTO(mndAddDbStatusAction(pTrans, &dbObj, SDB_STATUS_READY, TRN_STAGE_REDO_ACTION), NULL, _OVER);
30!
3307

3308
  // adjust vgroup replica
3309
  if (pDb->cfg.replications != newVg1.replica) {
30✔
3310
    SVgObj tmpGroup = {0};
21✔
3311
    TAOS_CHECK_GOTO(mndBuildAlterVgroupAction(pMnode, pTrans, pDb, pDb, &newVg1, pArray, &tmpGroup), NULL, _OVER);
21!
3312
  } else {
3313
    TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg1, SDB_STATUS_READY, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
9!
3314
  }
3315

3316
  if (pDb->cfg.replications != newVg2.replica) {
30✔
3317
    SVgObj tmpGroup = {0};
21✔
3318
    TAOS_CHECK_GOTO(mndBuildAlterVgroupAction(pMnode, pTrans, pDb, pDb, &newVg2, pArray, &tmpGroup), NULL, _OVER);
21✔
3319
  } else {
3320
    TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, &newVg2, SDB_STATUS_READY, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
9!
3321
  }
3322

3323
  TAOS_CHECK_GOTO(mndAddVgStatusAction(pTrans, pVgroup, SDB_STATUS_DROPPED, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
20!
3324

3325
  // commit db status
3326
  dbObj.vgVersion++;
20✔
3327
  dbObj.updateTime = taosGetTimestampMs();
20✔
3328
  TAOS_CHECK_GOTO(mndAddDbStatusAction(pTrans, &dbObj, SDB_STATUS_READY, TRN_STAGE_COMMIT_ACTION), NULL, _OVER);
20!
3329

3330
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
20!
3331
  code = 0;
20✔
3332

3333
_OVER:
31✔
3334
  taosArrayDestroy(pArray);
31✔
3335
  mndTransDrop(pTrans);
31✔
3336
  taosArrayDestroy(dbObj.cfg.pRetensions);
31✔
3337
  TAOS_RETURN(code);
31✔
3338
}
3339

3340
extern int32_t mndProcessSplitVgroupMsgImp(SRpcMsg *pReq);
3341

3342
static int32_t mndProcessSplitVgroupMsg(SRpcMsg *pReq) { return mndProcessSplitVgroupMsgImp(pReq); }
31✔
3343

3344
#ifndef TD_ENTERPRISE
3345
int32_t mndProcessSplitVgroupMsgImp(SRpcMsg *pReq) { return 0; }
3346
#endif
3347

3348
static int32_t mndSetBalanceVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
24✔
3349
                                              SDnodeObj *pSrc, SDnodeObj *pDst) {
3350
  int32_t code = 0;
24✔
3351
  SVgObj  newVg = {0};
24✔
3352
  memcpy(&newVg, pVgroup, sizeof(SVgObj));
24✔
3353
  mInfo("vgId:%d, vgroup info before balance, replica:%d", newVg.vgId, newVg.replica);
24!
3354
  for (int32_t i = 0; i < newVg.replica; ++i) {
68✔
3355
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
44!
3356
  }
3357

3358
  TAOS_CHECK_RETURN(mndAddIncVgroupReplicaToTrans(pMnode, pTrans, pDb, &newVg, pDst->id));
24!
3359
  TAOS_CHECK_RETURN(mndAddDecVgroupReplicaFromTrans(pMnode, pTrans, pDb, &newVg, pSrc->id));
24!
3360

3361
  {
3362
    SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
24✔
3363
    if (pRaw == NULL) {
24!
3364
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3365
      if (terrno != 0) code = terrno;
×
3366
      TAOS_RETURN(code);
×
3367
    }
3368
    if ((code = mndTransAppendCommitlog(pTrans, pRaw)) != 0) {
24!
3369
      sdbFreeRaw(pRaw);
×
3370
      TAOS_RETURN(code);
×
3371
    }
3372
    code = sdbSetRawStatus(pRaw, SDB_STATUS_READY);
24✔
3373
    if (code != 0) {
24!
3374
      mError("vgId:%d, failed to set raw status to ready, error:%s, line:%d", newVg.vgId, tstrerror(code), __LINE__);
×
3375
      TAOS_RETURN(code);
×
3376
    }
3377
  }
3378

3379
  mInfo("vgId:%d, vgroup info after balance, replica:%d", newVg.vgId, newVg.replica);
24!
3380
  for (int32_t i = 0; i < newVg.replica; ++i) {
68✔
3381
    mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
44!
3382
  }
3383
  TAOS_RETURN(code);
24✔
3384
}
3385

3386
static int32_t mndBalanceVgroupBetweenDnode(SMnode *pMnode, STrans *pTrans, SDnodeObj *pSrc, SDnodeObj *pDst,
24✔
3387
                                            SHashObj *pBalancedVgroups) {
3388
  void   *pIter = NULL;
24✔
3389
  int32_t code = -1;
24✔
3390
  SSdb   *pSdb = pMnode->pSdb;
24✔
3391

3392
  while (1) {
16✔
3393
    SVgObj *pVgroup = NULL;
40✔
3394
    pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup);
40✔
3395
    if (pIter == NULL) break;
40!
3396
    if (taosHashGet(pBalancedVgroups, &pVgroup->vgId, sizeof(int32_t)) != NULL) {
40✔
3397
      sdbRelease(pSdb, pVgroup);
15✔
3398
      continue;
16✔
3399
    }
3400

3401
    bool existInSrc = false;
25✔
3402
    bool existInDst = false;
25✔
3403
    for (int32_t i = 0; i < pVgroup->replica; ++i) {
70✔
3404
      SVnodeGid *pGid = &pVgroup->vnodeGid[i];
45✔
3405
      if (pGid->dnodeId == pSrc->id) existInSrc = true;
45✔
3406
      if (pGid->dnodeId == pDst->id) existInDst = true;
45!
3407
    }
3408

3409
    if (!existInSrc || existInDst) {
25!
3410
      sdbRelease(pSdb, pVgroup);
1✔
3411
      continue;
1✔
3412
    }
3413

3414
    SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName);
24✔
3415
    if (pDb == NULL) {
24!
3416
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3417
      if (terrno != 0) code = terrno;
×
3418
      mError("vgId:%d, balance vgroup can't find db obj dbName:%s", pVgroup->vgId, pVgroup->dbName);
×
3419
      goto _OUT;
×
3420
    }
3421

3422
    if (pDb->cfg.withArbitrator) {
24!
3423
      mInfo("vgId:%d, db:%s, with arbitrator, balance vgroup not allowed", pVgroup->vgId, pVgroup->dbName);
×
3424
      goto _OUT;
×
3425
    }
3426

3427
    code = mndSetBalanceVgroupInfoToTrans(pMnode, pTrans, pDb, pVgroup, pSrc, pDst);
24✔
3428
    if (code == 0) {
24!
3429
      code = taosHashPut(pBalancedVgroups, &pVgroup->vgId, sizeof(int32_t), &pVgroup->vgId, sizeof(int32_t));
24✔
3430
    }
3431

3432
  _OUT:
×
3433
    mndReleaseDb(pMnode, pDb);
24✔
3434
    sdbRelease(pSdb, pVgroup);
24✔
3435
    sdbCancelFetch(pSdb, pIter);
24✔
3436
    break;
24✔
3437
  }
3438

3439
  return code;
24✔
3440
}
3441

3442
static int32_t mndBalanceVgroup(SMnode *pMnode, SRpcMsg *pReq, SArray *pArray) {
16✔
3443
  int32_t   code = -1;
16✔
3444
  int32_t   numOfVgroups = 0;
16✔
3445
  STrans   *pTrans = NULL;
16✔
3446
  SHashObj *pBalancedVgroups = NULL;
16✔
3447

3448
  pBalancedVgroups = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
16✔
3449
  if (pBalancedVgroups == NULL) goto _OVER;
16!
3450

3451
  pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_GLOBAL, pReq, "balance-vgroup");
16✔
3452
  if (pTrans == NULL) {
16!
3453
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3454
    if (terrno != 0) code = terrno;
×
3455
    goto _OVER;
×
3456
  }
3457
  mndTransSetSerial(pTrans);
16✔
3458
  mInfo("trans:%d, used to balance vgroup", pTrans->id);
16!
3459
  TAOS_CHECK_GOTO(mndTransCheckConflict(pMnode, pTrans), NULL, _OVER);
16!
3460
  TAOS_CHECK_GOTO(mndTransCheckConflictWithCompact(pMnode, pTrans), NULL, _OVER);
16✔
3461

3462
  while (1) {
24✔
3463
    taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
39✔
3464
    for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
169✔
3465
      SDnodeObj *pDnode = taosArrayGet(pArray, i);
130✔
3466
      mInfo("dnode:%d, equivalent vnodes:%d others:%d support:%d, score:%f", pDnode->id, pDnode->numOfVnodes,
130!
3467
            pDnode->numOfSupportVnodes, pDnode->numOfOtherNodes, mndGetDnodeScore(pDnode, 0, 1));
3468
    }
3469

3470
    SDnodeObj *pSrc = taosArrayGet(pArray, taosArrayGetSize(pArray) - 1);
39✔
3471
    SDnodeObj *pDst = taosArrayGet(pArray, 0);
39✔
3472

3473
    float srcScore = mndGetDnodeScore(pSrc, -1, 1);
39✔
3474
    float dstScore = mndGetDnodeScore(pDst, 1, 1);
39✔
3475
    mInfo("trans:%d, after balance, src dnode:%d score:%f, dst dnode:%d score:%f", pTrans->id, pSrc->id, dstScore,
39!
3476
          pDst->id, dstScore);
3477

3478
    if (srcScore > dstScore - 0.000001) {
39✔
3479
      code = mndBalanceVgroupBetweenDnode(pMnode, pTrans, pSrc, pDst, pBalancedVgroups);
24✔
3480
      if (code == 0) {
24!
3481
        pSrc->numOfVnodes--;
24✔
3482
        pDst->numOfVnodes++;
24✔
3483
        numOfVgroups++;
24✔
3484
        continue;
24✔
3485
      } else {
3486
        mInfo("trans:%d, no vgroup need to balance from dnode:%d to dnode:%d", pTrans->id, pSrc->id, pDst->id);
×
3487
        break;
×
3488
      }
3489
    } else {
3490
      mInfo("trans:%d, no vgroup need to balance any more", pTrans->id);
15!
3491
      break;
15✔
3492
    }
3493
  }
3494

3495
  if (numOfVgroups <= 0) {
15✔
3496
    mInfo("no need to balance vgroup");
1!
3497
    code = 0;
1✔
3498
  } else {
3499
    mInfo("start to balance vgroup, numOfVgroups:%d", numOfVgroups);
14!
3500
    if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER;
14!
3501
    code = TSDB_CODE_ACTION_IN_PROGRESS;
14✔
3502
  }
3503

3504
_OVER:
16✔
3505
  taosHashCleanup(pBalancedVgroups);
16✔
3506
  mndTransDrop(pTrans);
16✔
3507
  TAOS_RETURN(code);
16✔
3508
}
3509

3510
static int32_t mndProcessBalanceVgroupMsg(SRpcMsg *pReq) {
20✔
3511
  SMnode *pMnode = pReq->info.node;
20✔
3512
  int32_t code = -1;
20✔
3513
  SArray *pArray = NULL;
20✔
3514
  void   *pIter = NULL;
20✔
3515
  int64_t curMs = taosGetTimestampMs();
20✔
3516

3517
  SBalanceVgroupReq req = {0};
20✔
3518
  if (tDeserializeSBalanceVgroupReq(pReq->pCont, pReq->contLen, &req) != 0) {
20!
3519
    code = TSDB_CODE_INVALID_MSG;
×
3520
    goto _OVER;
×
3521
  }
3522

3523
  mInfo("start to balance vgroup");
20!
3524
  if ((code = mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_BALANCE_VGROUP)) != 0) {
20✔
3525
    goto _OVER;
1✔
3526
  }
3527

3528
  while (1) {
56✔
3529
    SDnodeObj *pDnode = NULL;
75✔
3530
    pIter = sdbFetch(pMnode->pSdb, SDB_DNODE, pIter, (void **)&pDnode);
75✔
3531
    if (pIter == NULL) break;
75✔
3532
    if (!mndIsDnodeOnline(pDnode, curMs)) {
58✔
3533
      sdbCancelFetch(pMnode->pSdb, pIter);
2✔
3534
      code = TSDB_CODE_MND_HAS_OFFLINE_DNODE;
2✔
3535
      mError("failed to balance vgroup since %s, dnode:%d", terrstr(), pDnode->id);
2!
3536
      sdbRelease(pMnode->pSdb, pDnode);
2✔
3537
      goto _OVER;
2✔
3538
    }
3539

3540
    sdbRelease(pMnode->pSdb, pDnode);
56✔
3541
  }
3542

3543
  pArray = mndBuildDnodesArray(pMnode, 0, NULL);
17✔
3544
  if (pArray == NULL) {
17!
3545
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3546
    if (terrno != 0) code = terrno;
×
3547
    goto _OVER;
×
3548
  }
3549

3550
  if (taosArrayGetSize(pArray) < 2) {
17✔
3551
    mInfo("no need to balance vgroup since dnode num less than 2");
1!
3552
    code = 0;
1✔
3553
  } else {
3554
    code = mndBalanceVgroup(pMnode, pReq, pArray);
16✔
3555
  }
3556

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

3559
_OVER:
20✔
3560
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
20✔
3561
    mError("failed to balance vgroup since %s", tstrerror(code));
4!
3562
  }
3563

3564
  taosArrayDestroy(pArray);
20✔
3565
  tFreeSBalanceVgroupReq(&req);
20✔
3566
  TAOS_RETURN(code);
20✔
3567
}
3568

3569
bool mndVgroupInDb(SVgObj *pVgroup, int64_t dbUid) { return !pVgroup->isTsma && pVgroup->dbUid == dbUid; }
73,705,839✔
3570

3571
bool mndVgroupInDnode(SVgObj *pVgroup, int32_t dnodeId) {
16✔
3572
  for (int i = 0; i < pVgroup->replica; i++) {
42✔
3573
    if (pVgroup->vnodeGid[i].dnodeId == dnodeId) return true;
36✔
3574
  }
3575
  return false;
6✔
3576
}
3577

3578
static void *mndBuildCompactVnodeReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen, int64_t compactTs,
28✔
3579
                                     STimeWindow tw) {
3580
  SCompactVnodeReq compactReq = {0};
28✔
3581
  compactReq.dbUid = pDb->uid;
28✔
3582
  compactReq.compactStartTime = compactTs;
28✔
3583
  compactReq.tw = tw;
28✔
3584
  tstrncpy(compactReq.db, pDb->name, TSDB_DB_FNAME_LEN);
28✔
3585

3586
  mInfo("vgId:%d, build compact vnode config req", pVgroup->vgId);
28!
3587
  int32_t contLen = tSerializeSCompactVnodeReq(NULL, 0, &compactReq);
28✔
3588
  if (contLen < 0) {
28!
3589
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
3590
    return NULL;
×
3591
  }
3592
  contLen += sizeof(SMsgHead);
28✔
3593

3594
  void *pReq = taosMemoryMalloc(contLen);
28✔
3595
  if (pReq == NULL) {
28!
3596
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
3597
    return NULL;
×
3598
  }
3599

3600
  SMsgHead *pHead = pReq;
28✔
3601
  pHead->contLen = htonl(contLen);
28✔
3602
  pHead->vgId = htonl(pVgroup->vgId);
28✔
3603

3604
  if (tSerializeSCompactVnodeReq((char *)pReq + sizeof(SMsgHead), contLen, &compactReq) < 0) {
28!
3605
    taosMemoryFree(pReq);
×
3606
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
3607
    return NULL;
×
3608
  }
3609
  *pContLen = contLen;
28✔
3610
  return pReq;
28✔
3611
}
3612

3613
static int32_t mndAddCompactVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int64_t compactTs,
28✔
3614
                                        STimeWindow tw) {
3615
  int32_t      code = 0;
28✔
3616
  STransAction action = {0};
28✔
3617
  action.epSet = mndGetVgroupEpset(pMnode, pVgroup);
28✔
3618

3619
  int32_t contLen = 0;
28✔
3620
  void   *pReq = mndBuildCompactVnodeReq(pMnode, pDb, pVgroup, &contLen, compactTs, tw);
28✔
3621
  if (pReq == NULL) {
28!
3622
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
3623
    if (terrno != 0) code = terrno;
×
3624
    TAOS_RETURN(code);
×
3625
  }
3626

3627
  action.pCont = pReq;
28✔
3628
  action.contLen = contLen;
28✔
3629
  action.msgType = TDMT_VND_COMPACT;
28✔
3630

3631
  if ((code = mndTransAppendRedoAction(pTrans, &action)) != 0) {
28!
3632
    taosMemoryFree(pReq);
×
3633
    TAOS_RETURN(code);
×
3634
  }
3635

3636
  TAOS_RETURN(code);
28✔
3637
}
3638

3639
int32_t mndBuildCompactVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int64_t compactTs,
28✔
3640
                                    STimeWindow tw) {
3641
  TAOS_CHECK_RETURN(mndAddCompactVnodeAction(pMnode, pTrans, pDb, pVgroup, compactTs, tw));
28!
3642
  return 0;
28✔
3643
}
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

© 2025 Coveralls, Inc