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

taosdata / TDengine / #5005

26 Mar 2026 12:51PM UTC coverage: 72.152% (-0.2%) from 72.338%
#5005

push

travis-ci

web-flow
merge: from main to 3.0 branch #34951

512 of 851 new or added lines in 47 files covered. (60.16%)

6189 existing lines in 147 files now uncovered.

253282 of 351039 relevant lines covered (72.15%)

132156710.33 hits per line

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

50.77
/source/dnode/mnode/impl/src/mndXnode.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 <stdio.h>
18
#include "mndDef.h"
19
#include "tdatablock.h"
20
#include "types.h"
21
#include <curl/curl.h>
22
#ifndef WINDOWS
23
#include <openssl/bio.h>
24
#include <openssl/buffer.h>
25
#include <openssl/err.h>
26
#include <openssl/evp.h>
27
#include <openssl/hmac.h>
28
#else
29
#include "tsha.h"
30
#include "tbase64.h"
31
#endif
32
#include "audit.h"
33
#include "mndDnode.h"
34
#include "mndPrivilege.h"
35
#include "mndShow.h"
36
#include "mndTrans.h"
37
#include "mndUser.h"
38
#include "mndXnode.h"
39
#include "sdb.h"
40
#include "taoserror.h"
41
#include "tjson.h"
42
#include "xnode.h"
43

44
#define TSDB_XNODE_RESERVE_SIZE 64
45
#ifdef WINDOWS
46
#define XNODED_PIPE_SOCKET_URL "http://localhost:6051"
47
#else
48
#define XNODED_PIPE_SOCKET_URL "http://localhost"
49
#endif
50
typedef enum {
51
  HTTP_TYPE_GET = 0,
52
  HTTP_TYPE_POST,
53
  HTTP_TYPE_DELETE,
54
} EHttpType;
55
typedef struct {
56
  char   *data;
57
  int64_t dataLen;
58
} SCurlResp;
59

60
const int32_t defaultTimeout = 1000;
61

62
/** xnodes systable actions */
63
SSdbRaw *mndXnodeActionEncode(SXnodeObj *pObj);
64
SSdbRow *mndXnodeActionDecode(SSdbRaw *pRaw);
65
int32_t  mndXnodeActionInsert(SSdb *pSdb, SXnodeObj *pObj);
66
int32_t  mndXnodeActionUpdate(SSdb *pSdb, SXnodeObj *pOld, SXnodeObj *pNew);
67
int32_t  mndXnodeActionDelete(SSdb *pSdb, SXnodeObj *pObj);
68

69
/** @section xnodes request handlers */
70
static int32_t mndProcessCreateXnodeReq(SRpcMsg *pReq);
71
static int32_t mndProcessUpdateXnodeReq(SRpcMsg *pReq);
72
static int32_t mndProcessDropXnodeReq(SRpcMsg *pReq);
73
static int32_t mndProcessDrainXnodeReq(SRpcMsg *pReq);
74
static int32_t mndRetrieveXnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows);
75
static void    mndCancelGetNextXnode(SMnode *pMnode, void *pIter);
76

77
/** @section xnode task handlers */
78
SSdbRaw *mndXnodeTaskActionEncode(SXnodeTaskObj *pObj);
79
SSdbRow *mndXnodeTaskActionDecode(SSdbRaw *pRaw);
80
int32_t  mndXnodeTaskActionInsert(SSdb *pSdb, SXnodeTaskObj *pObj);
81
int32_t  mndXnodeTaskActionUpdate(SSdb *pSdb, SXnodeTaskObj *pOld, SXnodeTaskObj *pNew);
82
int32_t  mndXnodeTaskActionDelete(SSdb *pSdb, SXnodeTaskObj *pObj);
83

84
static int32_t mndProcessCreateXnodeTaskReq(SRpcMsg *pReq);
85
static int32_t mndProcessStartXnodeTaskReq(SRpcMsg *pReq);
86
static int32_t mndProcessStopXnodeTaskReq(SRpcMsg *pReq);
87
static int32_t mndProcessUpdateXnodeTaskReq(SRpcMsg *pReq);
88
static int32_t mndProcessDropXnodeTaskReq(SRpcMsg *pReq);
89
static int32_t mndRetrieveXnodeTasks(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows);
90
static void    mndCancelGetNextXnodeTask(SMnode *pMnode, void *pIter);
91

92
/** @section xnode task job handlers */
93
SSdbRaw *mndXnodeJobActionEncode(SXnodeJobObj *pObj);
94
SSdbRow *mndXnodeJobActionDecode(SSdbRaw *pRaw);
95
int32_t  mndXnodeJobActionInsert(SSdb *pSdb, SXnodeJobObj *pObj);
96
int32_t  mndXnodeJobActionUpdate(SSdb *pSdb, SXnodeJobObj *pOld, SXnodeJobObj *pNew);
97
int32_t  mndXnodeJobActionDelete(SSdb *pSdb, SXnodeJobObj *pObj);
98

99
static int32_t mndProcessCreateXnodeJobReq(SRpcMsg *pReq);
100
static int32_t mndProcessUpdateXnodeJobReq(SRpcMsg *pReq);
101
static int32_t mndProcessRebalanceXnodeJobReq(SRpcMsg *pReq);
102
static int32_t mndProcessRebalanceXnodeJobsWhereReq(SRpcMsg *pReq);
103
static int32_t mndProcessDropXnodeJobReq(SRpcMsg *pReq);
104
static int32_t mndRetrieveXnodeJobs(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows);
105
static void    mndCancelGetNextXnodeJob(SMnode *pMnode, void *pIter);
106

107
/** @section xnode user pass handlers */
108
SSdbRaw *mndXnodeUserPassActionEncode(SXnodeUserPassObj *pObj);
109
SSdbRow *mndXnodeUserPassActionDecode(SSdbRaw *pRaw);
110
int32_t  mndXnodeUserPassActionInsert(SSdb *pSdb, SXnodeUserPassObj *pObj);
111
int32_t  mndXnodeUserPassActionUpdate(SSdb *pSdb, SXnodeUserPassObj *pOld, SXnodeUserPassObj *pNew);
112
int32_t  mndXnodeUserPassActionDelete(SSdb *pSdb, SXnodeUserPassObj *pObj);
113

114
/** @section xnode agent handlers */
115
SSdbRaw *mndXnodeAgentActionEncode(SXnodeAgentObj *pObj);
116
SSdbRow *mndXnodeAgentActionDecode(SSdbRaw *pRaw);
117
int32_t  mndXnodeAgentActionInsert(SSdb *pSdb, SXnodeAgentObj *pObj);
118
int32_t  mndXnodeAgentActionUpdate(SSdb *pSdb, SXnodeAgentObj *pOld, SXnodeAgentObj *pNew);
119
int32_t  mndXnodeAgentActionDelete(SSdb *pSdb, SXnodeAgentObj *pObj);
120

121
static int32_t mndProcessCreateXnodeAgentReq(SRpcMsg *pReq);
122
static int32_t mndProcessUpdateXnodeAgentReq(SRpcMsg *pReq);
123
static int32_t mndProcessDropXnodeAgentReq(SRpcMsg *pReq);
124
static int32_t mndRetrieveXnodeAgents(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows);
125
static void    mndCancelGetNextXnodeAgent(SMnode *pMnode, void *pIter);
126

127
/** @section xnoded mgmt */
128
void mndStartXnoded(SMnode *pMnode, const char *user, const char *pass, const char *token);
129
void mndRestartXnoded(SMnode *pMnode);
130

131
/** @section others */
132
static int32_t mndGetXnodeStatus(SXnodeObj *pObj, char *status, int32_t statusLen);
133
SXnodeTaskObj *mndAcquireXnodeTask(SMnode *pMnode, int32_t tid);
134
SJson         *mndSendReqRetJson(const char *url, EHttpType type, int64_t timeout, const char *buf, int64_t bufLen);
135
static int32_t mndSetDropXnodeJobInfoToTrans(STrans *pTrans, SXnodeJobObj *pObj, bool force);
136
void           mndReleaseXnodeJob(SMnode *pMnode, SXnodeJobObj *pObj);
137
static int32_t mndValidateXnodePermissions(SMnode *pMnode, SRpcMsg *pReq, EOperType oper);
138
static int32_t mndXnodeCheckTaskObjPrivilege(SMnode *pMnode, const char *user, SXnodeTaskObj *pTask, EPrivType priv);
139

140
int32_t mndInitXnode(SMnode *pMnode) {
453,094✔
141
  SSdbTable table = {
453,094✔
142
      .sdbType = SDB_XNODE,
143
      .keyType = SDB_KEY_INT32,
144
      .encodeFp = (SdbEncodeFp)mndXnodeActionEncode,
145
      .decodeFp = (SdbDecodeFp)mndXnodeActionDecode,
146
      .insertFp = (SdbInsertFp)mndXnodeActionInsert,
147
      .updateFp = (SdbUpdateFp)mndXnodeActionUpdate,
148
      .deleteFp = (SdbDeleteFp)mndXnodeActionDelete,
149
  };
150

151
  int32_t code = sdbSetTable(pMnode->pSdb, table);
453,094✔
152
  if (code != 0) {
453,094✔
UNCOV
153
    return code;
×
154
  }
155

156
  SSdbTable tasks = {
453,094✔
157
      .sdbType = SDB_XNODE_TASK,
158
      .keyType = SDB_KEY_INT32,
159
      .encodeFp = (SdbEncodeFp)mndXnodeTaskActionEncode,
160
      .decodeFp = (SdbDecodeFp)mndXnodeTaskActionDecode,
161
      .insertFp = (SdbInsertFp)mndXnodeTaskActionInsert,
162
      .updateFp = (SdbUpdateFp)mndXnodeTaskActionUpdate,
163
      .deleteFp = (SdbDeleteFp)mndXnodeTaskActionDelete,
164
  };
165

166
  code = sdbSetTable(pMnode->pSdb, tasks);
453,094✔
167
  if (code != 0) {
453,094✔
UNCOV
168
    return code;
×
169
  }
170

171
  SSdbTable jobs = {
453,094✔
172
      .sdbType = SDB_XNODE_JOB,
173
      .keyType = SDB_KEY_INT32,
174
      .encodeFp = (SdbEncodeFp)mndXnodeJobActionEncode,
175
      .decodeFp = (SdbDecodeFp)mndXnodeJobActionDecode,
176
      .insertFp = (SdbInsertFp)mndXnodeJobActionInsert,
177
      .updateFp = (SdbUpdateFp)mndXnodeJobActionUpdate,
178
      .deleteFp = (SdbDeleteFp)mndXnodeJobActionDelete,
179
  };
180

181
  code = sdbSetTable(pMnode->pSdb, jobs);
453,094✔
182
  if (code != 0) {
453,094✔
UNCOV
183
    return code;
×
184
  }
185

186
  SSdbTable agents = {
453,094✔
187
      .sdbType = SDB_XNODE_AGENT,
188
      .keyType = SDB_KEY_INT32,
189
      .encodeFp = (SdbEncodeFp)mndXnodeAgentActionEncode,
190
      .decodeFp = (SdbDecodeFp)mndXnodeAgentActionDecode,
191
      .insertFp = (SdbInsertFp)mndXnodeAgentActionInsert,
192
      .updateFp = (SdbUpdateFp)mndXnodeAgentActionUpdate,
193
      .deleteFp = (SdbDeleteFp)mndXnodeAgentActionDelete,
194
  };
195

196
  code = sdbSetTable(pMnode->pSdb, agents);
453,094✔
197
  if (code != 0) {
453,094✔
UNCOV
198
    return code;
×
199
  }
200

201
  SSdbTable userPass = {
453,094✔
202
      .sdbType = SDB_XNODE_USER_PASS,
203
      .keyType = SDB_KEY_INT32,
204
      .encodeFp = (SdbEncodeFp)mndXnodeUserPassActionEncode,
205
      .decodeFp = (SdbDecodeFp)mndXnodeUserPassActionDecode,
206
      .insertFp = (SdbInsertFp)mndXnodeUserPassActionInsert,
207
      .updateFp = (SdbUpdateFp)mndXnodeUserPassActionUpdate,
208
      .deleteFp = (SdbDeleteFp)mndXnodeUserPassActionDelete,
209
  };
210

211
  code = sdbSetTable(pMnode->pSdb, userPass);
453,094✔
212
  if (code != 0) {
453,094✔
UNCOV
213
    return code;
×
214
  }
215

216
  mndSetMsgHandle(pMnode, TDMT_MND_CREATE_XNODE, mndProcessCreateXnodeReq);
453,094✔
217
  mndSetMsgHandle(pMnode, TDMT_MND_UPDATE_XNODE, mndProcessUpdateXnodeReq);
453,094✔
218
  mndSetMsgHandle(pMnode, TDMT_MND_DROP_XNODE, mndProcessDropXnodeReq);
453,094✔
219
  mndSetMsgHandle(pMnode, TDMT_MND_DRAIN_XNODE, mndProcessDrainXnodeReq);
453,094✔
220
  mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_XNODES, mndRetrieveXnodes);
453,094✔
221
  mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_XNODES, mndCancelGetNextXnode);
453,094✔
222

223
  mndSetMsgHandle(pMnode, TDMT_MND_CREATE_XNODE_TASK, mndProcessCreateXnodeTaskReq);
453,094✔
224
  mndSetMsgHandle(pMnode, TDMT_MND_START_XNODE_TASK, mndProcessStartXnodeTaskReq);
453,094✔
225
  mndSetMsgHandle(pMnode, TDMT_MND_STOP_XNODE_TASK, mndProcessStopXnodeTaskReq);
453,094✔
226
  mndSetMsgHandle(pMnode, TDMT_MND_UPDATE_XNODE_TASK, mndProcessUpdateXnodeTaskReq);
453,094✔
227
  mndSetMsgHandle(pMnode, TDMT_MND_DROP_XNODE_TASK, mndProcessDropXnodeTaskReq);
453,094✔
228
  mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_XNODE_TASKS, mndRetrieveXnodeTasks);
453,094✔
229
  mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_XNODE_TASKS, mndCancelGetNextXnodeTask);
453,094✔
230

231
  mndSetMsgHandle(pMnode, TDMT_MND_CREATE_XNODE_JOB, mndProcessCreateXnodeJobReq);
453,094✔
232
  mndSetMsgHandle(pMnode, TDMT_MND_UPDATE_XNODE_JOB, mndProcessUpdateXnodeJobReq);
453,094✔
233
  mndSetMsgHandle(pMnode, TDMT_MND_REBALANCE_XNODE_JOB, mndProcessRebalanceXnodeJobReq);
453,094✔
234
  mndSetMsgHandle(pMnode, TDMT_MND_REBALANCE_XNODE_JOBS_WHERE, mndProcessRebalanceXnodeJobsWhereReq);
453,094✔
235
  mndSetMsgHandle(pMnode, TDMT_MND_DROP_XNODE_JOB, mndProcessDropXnodeJobReq);
453,094✔
236
  mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_XNODE_JOBS, mndRetrieveXnodeJobs);
453,094✔
237
  mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_XNODE_JOBS, mndCancelGetNextXnodeJob);
453,094✔
238

239
  mndSetMsgHandle(pMnode, TDMT_MND_CREATE_XNODE_AGENT, mndProcessCreateXnodeAgentReq);
453,094✔
240
  mndSetMsgHandle(pMnode, TDMT_MND_UPDATE_XNODE_AGENT, mndProcessUpdateXnodeAgentReq);
453,094✔
241
  mndSetMsgHandle(pMnode, TDMT_MND_DROP_XNODE_AGENT, mndProcessDropXnodeAgentReq);
453,094✔
242
  mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_XNODE_AGENTS, mndRetrieveXnodeAgents);
453,094✔
243
  mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_XNODE_AGENTS, mndCancelGetNextXnodeAgent);
453,094✔
244

245
  return 0;
453,094✔
246
}
247

248
/** tools section **/
249

250
int32_t xnodeCheckPasswordFmt(const char *pwd) {
120✔
251
  if (tsEnableAdvancedSecurity == 0 && strcmp(pwd, "taosdata") == 0) {
120✔
UNCOV
252
    return 0;
×
253
  }
254

255
  if (tsEnableStrongPassword == 0) {
120✔
256
    for (char c = *pwd; c != 0; c = *(++pwd)) {
×
UNCOV
257
      if (c == ' ' || c == '\'' || c == '\"' || c == '`' || c == '\\') {
×
UNCOV
258
        return TSDB_CODE_MND_INVALID_PASS_FORMAT;
×
259
      }
260
    }
UNCOV
261
    return 0;
×
262
  }
263

264
  int32_t len = strlen(pwd);
120✔
265
  if (len < TSDB_PASSWORD_MIN_LEN) {
120✔
UNCOV
266
    return TSDB_CODE_PAR_PASSWD_TOO_SHORT_OR_EMPTY;
×
267
  }
268

269
  if (len > TSDB_PASSWORD_MAX_LEN) {
120✔
UNCOV
270
    return TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG;
×
271
  }
272

273
  if (taosIsComplexString(pwd)) {
120✔
274
    return 0;
120✔
275
  }
276

UNCOV
277
  return TSDB_CODE_MND_INVALID_PASS_FORMAT;
×
278
}
279

280
static void swapFields(int32_t *newLen, char **ppNewStr, int32_t *oldLen, char **ppOldStr) {
18,360✔
281
  if (*newLen > 0) {
18,360✔
282
    int32_t tempLen = *newLen;
14,640✔
283
    *newLen = *oldLen;
14,640✔
284
    *oldLen = tempLen;
14,640✔
285

286
    char *tempStr = *ppNewStr;
14,640✔
287
    *ppNewStr = *ppOldStr;
14,640✔
288
    *ppOldStr = tempStr;
14,640✔
289
  }
290
}
18,360✔
291

292
/** xnode section **/
293

294
void mndCleanupXnode(SMnode *pMnode) {}
453,032✔
295

296
SXnodeObj *mndAcquireXnode(SMnode *pMnode, int32_t xnodeId) {
840✔
297
  SXnodeObj *pObj = sdbAcquire(pMnode->pSdb, SDB_XNODE, &xnodeId);
840✔
298
  if (pObj == NULL && terrno == TSDB_CODE_SDB_OBJ_NOT_THERE) {
840✔
299
    terrno = TSDB_CODE_MND_XNODE_NOT_EXIST;
600✔
300
  }
301
  return pObj;
840✔
302
}
303

304
void mndReleaseXnode(SMnode *pMnode, SXnodeObj *pObj) {
5,040✔
305
  SSdb *pSdb = pMnode->pSdb;
5,040✔
306
  sdbRelease(pSdb, pObj);
5,040✔
307
}
5,040✔
308

309
SSdbRaw *mndXnodeActionEncode(SXnodeObj *pObj) {
12,090✔
310
  int32_t code = 0;
12,090✔
311
  int32_t lino = 0;
12,090✔
312
  terrno = TSDB_CODE_OUT_OF_MEMORY;
12,090✔
313

314
  if (NULL == pObj) {
12,090✔
315
    terrno = TSDB_CODE_INVALID_PARA;
195✔
316
    return NULL;
195✔
317
  }
318

319
  int32_t rawDataLen = sizeof(SXnodeObj) + TSDB_XNODE_RESERVE_SIZE + pObj->urlLen + pObj->statusLen;
11,895✔
320

321
  SSdbRaw *pRaw = sdbAllocRaw(SDB_XNODE, TSDB_XNODE_VER_NUMBER, rawDataLen);
11,895✔
322
  if (pRaw == NULL) goto _OVER;
11,895✔
323

324
  int32_t dataPos = 0;
11,895✔
325
  SDB_SET_INT32(pRaw, dataPos, pObj->id, _OVER)
11,895✔
326
  SDB_SET_INT32(pRaw, dataPos, pObj->urlLen, _OVER)
11,895✔
327
  SDB_SET_BINARY(pRaw, dataPos, pObj->url, pObj->urlLen, _OVER)
11,895✔
328
  SDB_SET_INT32(pRaw, dataPos, pObj->statusLen, _OVER)
11,895✔
329
  SDB_SET_BINARY(pRaw, dataPos, pObj->status, pObj->statusLen, _OVER)
11,895✔
330
  SDB_SET_INT64(pRaw, dataPos, pObj->createTime, _OVER)
11,895✔
331
  SDB_SET_INT64(pRaw, dataPos, pObj->updateTime, _OVER)
11,895✔
332

333
  SDB_SET_RESERVE(pRaw, dataPos, TSDB_XNODE_RESERVE_SIZE, _OVER)
11,895✔
334

335
  terrno = 0;
11,895✔
336

337
_OVER:
11,895✔
338
  if (terrno != 0) {
11,895✔
339
    mError("xnode:%d, failed to encode to raw:%p since %s", pObj->id, pRaw, terrstr());
×
UNCOV
340
    sdbFreeRaw(pRaw);
×
UNCOV
341
    return NULL;
×
342
  }
343

344
  mTrace("xnode:%d, encode to raw:%p, row:%p", pObj->id, pRaw, pObj);
11,895✔
345
  return pRaw;
11,895✔
346
}
347

348
SSdbRow *mndXnodeActionDecode(SSdbRaw *pRaw) {
9,690✔
349
  int32_t code = 0;
9,690✔
350
  int32_t lino = 0;
9,690✔
351
  terrno = TSDB_CODE_OUT_OF_MEMORY;
9,690✔
352
  SSdbRow   *pRow = NULL;
9,690✔
353
  SXnodeObj *pObj = NULL;
9,690✔
354

355
  if (NULL == pRaw) {
9,690✔
356
    terrno = TSDB_CODE_INVALID_PARA;
195✔
357
    return NULL;
195✔
358
  }
359

360
  int8_t sver = 0;
9,495✔
361
  if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto _OVER;
9,495✔
362

363
  if (sver != TSDB_XNODE_VER_NUMBER) {
9,495✔
UNCOV
364
    terrno = TSDB_CODE_SDB_INVALID_DATA_VER;
×
UNCOV
365
    goto _OVER;
×
366
  }
367

368
  pRow = sdbAllocRow(sizeof(SXnodeObj));
9,495✔
369
  if (pRow == NULL) goto _OVER;
9,495✔
370

371
  pObj = sdbGetRowObj(pRow);
9,495✔
372
  if (pObj == NULL) goto _OVER;
9,495✔
373

374
  int32_t dataPos = 0;
9,495✔
375
  SDB_GET_INT32(pRaw, dataPos, &pObj->id, _OVER)
9,495✔
376
  SDB_GET_INT32(pRaw, dataPos, &pObj->urlLen, _OVER)
9,495✔
377
  if (pObj->urlLen > 0) {
9,495✔
378
    pObj->url = taosMemoryCalloc(1, pObj->urlLen + 1);
9,060✔
379
    if (pObj->url == NULL) goto _OVER;
9,060✔
380
    SDB_GET_BINARY(pRaw, dataPos, pObj->url, pObj->urlLen, _OVER)
9,060✔
381
  } else {
382
    pObj->url = NULL;
435✔
383
  }
384
  SDB_GET_INT32(pRaw, dataPos, &pObj->statusLen, _OVER)
9,495✔
385
  if (pObj->statusLen > 0) {
9,495✔
386
    pObj->status = taosMemoryCalloc(1, pObj->statusLen + 1);
3,060✔
387
    if (pObj->status == NULL) goto _OVER;
3,060✔
388
    SDB_GET_BINARY(pRaw, dataPos, pObj->status, pObj->statusLen, _OVER)
3,060✔
389
  } else {
390
    pObj->status = NULL;
6,435✔
391
  }
392
  SDB_GET_INT64(pRaw, dataPos, &pObj->createTime, _OVER)
9,495✔
393
  SDB_GET_INT64(pRaw, dataPos, &pObj->updateTime, _OVER)
9,495✔
394

395
  SDB_GET_RESERVE(pRaw, dataPos, TSDB_XNODE_RESERVE_SIZE, _OVER)
9,495✔
396

397
  terrno = 0;
9,495✔
398

399
_OVER:
9,495✔
400
  if (terrno != 0) {
9,495✔
401
    mError("xnode:%d, failed to decode from raw:%p since %s", pObj == NULL ? 0 : pObj->id, pRaw, terrstr());
×
UNCOV
402
    if (pObj != NULL) {
×
403
      taosMemoryFreeClear(pObj->url);
×
404
    }
UNCOV
405
    taosMemoryFreeClear(pRow);
×
UNCOV
406
    return NULL;
×
407
  }
408

409
  mTrace("xnode:%d, decode from raw:%p, row:%p", pObj->id, pRaw, pObj);
9,495✔
410
  return pRow;
9,495✔
411
}
412

413
static void mndFreeXnode(SXnodeObj *pObj) {
8,880✔
414
  if (pObj == NULL) return;
8,880✔
415
  if (pObj->url != NULL) {
8,880✔
416
    taosMemoryFreeClear(pObj->url);
8,640✔
417
  }
418
  if (pObj->status != NULL) {
8,880✔
419
    taosMemoryFreeClear(pObj->status);
720✔
420
  }
421
}
422

423
int32_t mndXnodeActionInsert(SSdb *pSdb, SXnodeObj *pObj) {
1,920✔
424
  mDebug("xnode:%d, perform insert action, row:%p", pObj->id, pObj);
1,920✔
425
  return 0;
1,920✔
426
}
427

428
int32_t mndXnodeActionDelete(SSdb *pSdb, SXnodeObj *pObj) {
6,960✔
429
  mDebug("xnode:%d, perform delete action, row:%p", pObj->id, pObj);
6,960✔
430
  mndFreeXnode(pObj);
6,960✔
431
  return 0;
6,960✔
432
}
433

434
int32_t mndXnodeActionUpdate(SSdb *pSdb, SXnodeObj *pOld, SXnodeObj *pNew) {
3,600✔
435
  mDebug("xnode:%d, perform update action, old row:%p new row:%p", pOld->id, pOld, pNew);
3,600✔
436

437
  taosWLockLatch(&pOld->lock);
3,600✔
438
  swapFields(&pNew->statusLen, &pNew->status, &pOld->statusLen, &pOld->status);
3,600✔
439
  if (pNew->updateTime > pOld->updateTime) {
3,600✔
440
    pOld->updateTime = pNew->updateTime;
240✔
441
  }
442
  taosWUnLockLatch(&pOld->lock);
3,600✔
443
  return 0;
3,600✔
444
}
445

446
void mndReleaseXnodeUserPass(SMnode *pMnode, SXnodeUserPassObj *pObj) {
840✔
447
  SSdb *pSdb = pMnode->pSdb;
840✔
448
  sdbRelease(pSdb, pObj);
840✔
449
}
840✔
450

451
SXnodeUserPassObj *mndAcquireFirstXnodeUserPass(SMnode *pMnode) {
418,963✔
452
  SSdb *pSdb = pMnode->pSdb;
418,963✔
453

454
  void *pIter = NULL;
418,963✔
UNCOV
455
  while (1) {
×
456
    SXnodeUserPassObj *pObj = NULL;
418,963✔
457
    pIter = sdbFetch(pSdb, SDB_XNODE_USER_PASS, pIter, (void **)&pObj);
418,963✔
458
    if (pIter == NULL) break;
418,963✔
459

460
    if (pObj != NULL) {
840✔
461
      sdbCancelFetch(pSdb, pIter);
840✔
462
      return pObj;
840✔
463
    }
464

UNCOV
465
    sdbRelease(pSdb, pObj);
×
466
  }
467
  terrno = TSDB_CODE_MND_XNODE_USER_PASS_NOT_EXIST;
418,123✔
468
  return NULL;
418,123✔
469
}
470

471
static int32_t mndSetCreateXnodeUserPassRedoLogs(STrans *pTrans, SXnodeUserPassObj *pObj) {
240✔
472
  int32_t  code = 0;
240✔
473
  SSdbRaw *pRedoRaw = mndXnodeUserPassActionEncode(pObj);
240✔
474
  if (pRedoRaw == NULL) {
240✔
475
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
476
    if (terrno != 0) code = terrno;
×
UNCOV
477
    TAOS_RETURN(code);
×
478
  }
479
  TAOS_CHECK_RETURN(mndTransAppendRedolog(pTrans, pRedoRaw));
240✔
480
  TAOS_CHECK_RETURN(sdbSetRawStatus(pRedoRaw, SDB_STATUS_CREATING));
240✔
481
  TAOS_RETURN(code);
240✔
482
}
483

484
static int32_t mndSetCreateXnodeUserPassCommitLogs(STrans *pTrans, SXnodeUserPassObj *pObj) {
1,080✔
485
  int32_t  code = 0;
1,080✔
486
  SSdbRaw *pCommitRaw = mndXnodeUserPassActionEncode(pObj);
1,080✔
487
  if (pCommitRaw == NULL) {
1,080✔
488
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
489
    if (terrno != 0) code = terrno;
×
UNCOV
490
    TAOS_RETURN(code);
×
491
  }
492
  TAOS_CHECK_RETURN(mndTransAppendCommitlog(pTrans, pCommitRaw));
1,080✔
493
  TAOS_CHECK_RETURN(sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY));
1,080✔
494
  TAOS_RETURN(code);
1,080✔
495
}
496

497
static int32_t mndSetCreateXnodeRedoLogs(STrans *pTrans, SXnodeObj *pObj) {
1,920✔
498
  int32_t  code = 0;
1,920✔
499
  SSdbRaw *pRedoRaw = mndXnodeActionEncode(pObj);
1,920✔
500
  if (pRedoRaw == NULL) {
1,920✔
501
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
502
    if (terrno != 0) code = terrno;
×
UNCOV
503
    TAOS_RETURN(code);
×
504
  }
505
  TAOS_CHECK_RETURN(mndTransAppendRedolog(pTrans, pRedoRaw));
1,920✔
506
  TAOS_CHECK_RETURN(sdbSetRawStatus(pRedoRaw, SDB_STATUS_CREATING));
1,920✔
507
  TAOS_RETURN(code);
1,920✔
508
}
509

510
static int32_t mndSetCreateXnodeUndoLogs(STrans *pTrans, SXnodeObj *pObj) {
1,920✔
511
  int32_t  code = 0;
1,920✔
512
  SSdbRaw *pUndoRaw = mndXnodeActionEncode(pObj);
1,920✔
513
  if (pUndoRaw == NULL) {
1,920✔
514
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
515
    if (terrno != 0) code = terrno;
×
UNCOV
516
    TAOS_RETURN(code);
×
517
  }
518
  TAOS_CHECK_RETURN(mndTransAppendUndolog(pTrans, pUndoRaw));
1,920✔
519
  TAOS_CHECK_RETURN(sdbSetRawStatus(pUndoRaw, SDB_STATUS_DROPPED));
1,920✔
520
  TAOS_RETURN(code);
1,920✔
521
}
522

523
static int32_t mndSetCreateXnodeCommitLogs(STrans *pTrans, SXnodeObj *pObj) {
2,160✔
524
  int32_t  code = 0;
2,160✔
525
  SSdbRaw *pCommitRaw = mndXnodeActionEncode(pObj);
2,160✔
526
  if (pCommitRaw == NULL) {
2,160✔
527
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
528
    if (terrno != 0) code = terrno;
×
UNCOV
529
    TAOS_RETURN(code);
×
530
  }
531
  TAOS_CHECK_RETURN(mndTransAppendCommitlog(pTrans, pCommitRaw));
2,160✔
532
  TAOS_CHECK_RETURN(sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY));
2,160✔
533
  TAOS_RETURN(code);
2,160✔
534
}
535

536
static int32_t mndCreateXnode(SMnode *pMnode, SRpcMsg *pReq, SMCreateXnodeReq *pCreate) {
1,920✔
537
  int32_t code = 0, lino = 0;
1,920✔
538
  STrans *pTrans = NULL;
1,920✔
539

540
  SXnodeObj xnodeObj = {0};
1,920✔
541
  xnodeObj.id = sdbGetMaxId(pMnode->pSdb, SDB_XNODE);
1,920✔
542

543
  xnodeObj.urlLen = pCreate->urlLen;
1,920✔
544
  if (xnodeObj.urlLen > TSDB_XNODE_URL_LEN) {
1,920✔
545
    code = TSDB_CODE_MND_XNODE_TOO_LONG_URL;
×
UNCOV
546
    lino = __LINE__;
×
UNCOV
547
    goto _OVER;
×
548
  }
549
  xnodeObj.url = taosMemoryCalloc(1, pCreate->urlLen);
1,920✔
550
  if (xnodeObj.url == NULL) goto _OVER;
1,920✔
551
  (void)memcpy(xnodeObj.url, pCreate->url, pCreate->urlLen);
1,920✔
552

553
  xnodeObj.createTime = taosGetTimestampMs();
1,920✔
554
  xnodeObj.updateTime = xnodeObj.createTime;
1,920✔
555
  mInfo("create xnode, xnode.id:%d, xnode.url: %s, xnode.time:%" PRId64, xnodeObj.id, xnodeObj.url,
1,920✔
556
        xnodeObj.createTime);
557

558
  pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq, "create-xnode");
1,920✔
559
  if (pTrans == NULL) {
1,920✔
560
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
561
    if (terrno != 0) code = terrno;
×
562
    mInfo("failed to create transaction for xnode:%s, code:0x%x:%s", pCreate->url, code, tstrerror(code));
×
UNCOV
563
    lino = __LINE__;
×
UNCOV
564
    goto _OVER;
×
565
  }
566
  mndTransSetSerial(pTrans);
1,920✔
567

568
  mInfo("trans:%d, used to create xnode:%s as xnode:%d", pTrans->id, pCreate->url, xnodeObj.id);
1,920✔
569

570
  TAOS_CHECK_GOTO(mndSetCreateXnodeRedoLogs(pTrans, &xnodeObj), NULL, _OVER);
1,920✔
571
  TAOS_CHECK_GOTO(mndSetCreateXnodeUndoLogs(pTrans, &xnodeObj), NULL, _OVER);
1,920✔
572
  TAOS_CHECK_GOTO(mndSetCreateXnodeCommitLogs(pTrans, &xnodeObj), NULL, _OVER);
1,920✔
573
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
1,920✔
574
  code = TSDB_CODE_ACTION_IN_PROGRESS;
1,920✔
575

576
_OVER:
1,920✔
577
  if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_ACTION_IN_PROGRESS) {
1,920✔
UNCOV
578
    mError("xnode:failed create xnode since %s, line:%d", tstrerror(code), lino);
×
579
  }
580
  mndFreeXnode(&xnodeObj);
1,920✔
581
  mndTransDrop(pTrans);
1,920✔
582
  TAOS_RETURN(code);
1,920✔
583
}
584

585
static SXnodeObj *mndAcquireXnodeByURL(SMnode *pMnode, char *url) {
6,000✔
586
  SSdb *pSdb = pMnode->pSdb;
6,000✔
587

588
  void *pIter = NULL;
6,000✔
589
  while (1) {
8,640✔
590
    SXnodeObj *pXnode = NULL;
14,640✔
591
    pIter = sdbFetch(pSdb, SDB_XNODE, pIter, (void **)&pXnode);
14,640✔
592
    if (pIter == NULL) break;
14,640✔
593

594
    if (strcasecmp(url, pXnode->url) == 0) {
12,360✔
595
      sdbCancelFetch(pSdb, pIter);
3,720✔
596
      return pXnode;
3,720✔
597
    }
598

599
    sdbRelease(pSdb, pXnode);
8,640✔
600
  }
601

602
  mError("xnode:%s, not found", url);
2,280✔
603
  terrno = TSDB_CODE_MND_XNODE_NOT_EXIST;
2,280✔
604
  return NULL;
2,280✔
605
}
606

607
static int32_t mndStoreXnodeUserPassToken(SMnode *pMnode, SRpcMsg *pReq, SMCreateXnodeReq *pCreate) {
240✔
608
  int32_t code = 0, lino = 0;
240✔
609
  STrans *pTrans = NULL;
240✔
610

611
  SXnodeUserPassObj upObj = {0};
240✔
612
  upObj.id = sdbGetMaxId(pMnode->pSdb, SDB_XNODE_USER_PASS);
240✔
613

614
  if (pCreate->user) {
240✔
615
    upObj.userLen = pCreate->userLen;
120✔
616
    if (upObj.userLen > TSDB_USER_LEN) {
120✔
617
      code = TSDB_CODE_MND_USER_NOT_AVAILABLE;
×
UNCOV
618
      lino = __LINE__;
×
UNCOV
619
      goto _OVER;
×
620
    }
621
    upObj.user = taosMemoryCalloc(1, pCreate->userLen);
120✔
622
    if (upObj.user == NULL) goto _OVER;
120✔
623
    (void)memcpy(upObj.user, pCreate->user, pCreate->userLen);
120✔
624
  }
625
  if (pCreate->pass) {
240✔
626
    upObj.passLen = pCreate->passLen;
120✔
627
    if (upObj.passLen > TSDB_USER_PASSWORD_LONGLEN) {
120✔
628
      code = TSDB_CODE_MND_INVALID_PASS_FORMAT;
×
UNCOV
629
      lino = __LINE__;
×
UNCOV
630
      goto _OVER;
×
631
    }
632
    upObj.pass = taosMemoryCalloc(1, pCreate->passLen);
120✔
633
    if (upObj.pass == NULL) goto _OVER;
120✔
634
    (void)memcpy(upObj.pass, pCreate->pass, pCreate->passLen);
120✔
635
  }
636

637
  if (pCreate->token.ptr) {
240✔
638
    upObj.tokenLen = pCreate->token.len + 1;
120✔
639
    upObj.token = taosMemoryCalloc(1, upObj.tokenLen);
120✔
640
    if (upObj.token == NULL) goto _OVER;
120✔
641
    (void)memcpy(upObj.token, pCreate->token.ptr, pCreate->token.len);
120✔
642
  }
643

644
  pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq, "create-userpass");
240✔
645
  if (pTrans == NULL) {
240✔
646
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
647
    if (terrno != 0) code = terrno;
×
648
    mInfo("failed to create transaction for xnode:%s, code:0x%x:%s", pCreate->url, code, tstrerror(code));
×
UNCOV
649
    lino = __LINE__;
×
UNCOV
650
    goto _OVER;
×
651
  }
652
  mndTransSetSerial(pTrans);
240✔
653

654
  mInfo("trans:%d, used to create xnode:%s as xnode:%d", pTrans->id, pCreate->url, upObj.id);
240✔
655

656
  TAOS_CHECK_GOTO(mndSetCreateXnodeUserPassRedoLogs(pTrans, &upObj), NULL, _OVER);
240✔
657
  TAOS_CHECK_GOTO(mndSetCreateXnodeUserPassCommitLogs(pTrans, &upObj), NULL, _OVER);
240✔
658
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
240✔
659
  code = TSDB_CODE_ACTION_IN_PROGRESS;
240✔
660

661
_OVER:
240✔
662
  if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_ACTION_IN_PROGRESS) {
240✔
UNCOV
663
    mError("xnode failed to store userpass since %s, line:%d", tstrerror(code), lino);
×
664
  }
665
  taosMemoryFreeClear(upObj.user);
240✔
666
  taosMemoryFreeClear(upObj.pass);
240✔
667
  taosMemoryFreeClear(upObj.token);
240✔
668
  mndTransDrop(pTrans);
240✔
669
  TAOS_RETURN(code);
240✔
670
}
671

672
#ifndef TD_ENTERPRISE
673

674
int32_t mndXnodeCreateDefaultToken(SRpcMsg* pReq, char** ppToken) {
675
  return TSDB_CODE_OPS_NOT_SUPPORT;
676
}
677

678
#endif
679

680
static int32_t httpCreateXnode(SXnodeObj *pObj) {
1,920✔
681
  int32_t code = 0;
1,920✔
682
  SJson  *pJson = NULL;
1,920✔
683
  SJson  *postContent = NULL;
1,920✔
684
  char   *pContStr = NULL;
1,920✔
685

686
  char xnodeUrl[TSDB_XNODE_URL_LEN + 1] = {0};
1,920✔
687
  snprintf(xnodeUrl, TSDB_XNODE_URL_LEN + 1, "%s/xnode", XNODED_PIPE_SOCKET_URL);
1,920✔
688
  postContent = tjsonCreateObject();
1,920✔
689
  if (postContent == NULL) {
1,920✔
UNCOV
690
    code = terrno;
×
UNCOV
691
    goto _OVER;
×
692
  }
693
  TAOS_CHECK_GOTO(tjsonAddDoubleToObject(postContent, "id", (double)pObj->id), NULL, _OVER);
1,920✔
694
  TAOS_CHECK_GOTO(tjsonAddStringToObject(postContent, "url", pObj->url), NULL, _OVER);
1,920✔
695
  pContStr = tjsonToUnformattedString(postContent);
1,920✔
696
  if (pContStr == NULL) {
1,920✔
UNCOV
697
    code = terrno;
×
UNCOV
698
    goto _OVER;
×
699
  }
700
  pJson = mndSendReqRetJson(xnodeUrl, HTTP_TYPE_POST, defaultTimeout, pContStr, strlen(pContStr));
1,920✔
701

702
_OVER:
1,920✔
703
  if (postContent != NULL) {
1,920✔
704
    tjsonDelete(postContent);
1,920✔
705
  }
706
  if (pContStr != NULL) {
1,920✔
707
    taosMemFree(pContStr);
1,920✔
708
  }
709
  if (pJson != NULL) {
1,920✔
UNCOV
710
    tjsonDelete(pJson);
×
711
  }
712
  TAOS_RETURN(code);
1,920✔
713
}
714

715
static int32_t mndProcessCreateXnodeReq(SRpcMsg *pReq) {
2,400✔
716
  SMnode          *pMnode = pReq->info.node;
2,400✔
717
  int32_t          code = 0, lino = 0;
2,400✔
718
  SXnodeObj       *pObj = NULL;
2,400✔
719
  SMCreateXnodeReq createReq = {0};
2,400✔
720
  char            *pToken = NULL;
2,400✔
721
  bool             isSuperUser = false;
2,400✔
722

723
  code = mndValidateXnodePermissions(pMnode, pReq, MND_OPER_CREATE_XNODE);
2,400✔
724
  if (code != TSDB_CODE_SUCCESS) {
2,400✔
725
    mError("failed check permission for create xnode, code:%s", tstrerror(code));
120✔
726
    goto _OVER;
120✔
727
  }
728
  TAOS_CHECK_GOTO(tDeserializeSMCreateXnodeReq(pReq->pCont, pReq->contLen, &createReq), &lino, _OVER);
2,280✔
729
  mDebug("xnode:%s, start to create", createReq.url);
2,280✔
730

731
  pObj = mndAcquireXnodeByURL(pMnode, createReq.url);
2,280✔
732
  if (pObj != NULL) {
2,280✔
733
    code = TSDB_CODE_MND_XNODE_ALREADY_EXIST;
360✔
734
    goto _OVER;
360✔
735
  }
736

737
  int32_t numOfRows = sdbGetSize(pMnode->pSdb, SDB_XNODE_USER_PASS);
1,920✔
738
  if (numOfRows <= 0) {
1,920✔
739
    if (createReq.token.ptr != NULL) {
240✔
UNCOV
740
      (void)mndCreateXnode(pMnode, NULL, &createReq);
×
UNCOV
741
      code = mndStoreXnodeUserPassToken(pMnode, pReq, &createReq);
×
UNCOV
742
      if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
×
UNCOV
743
        lino = __LINE__;
×
744
        goto _OVER;
×
745
      }
UNCOV
746
      mndStartXnoded(pMnode, NULL, NULL, createReq.token.ptr);
×
747
    } else if (createReq.user != NULL) {
240✔
748
      TAOS_CHECK_GOTO(xnodeCheckPasswordFmt(createReq.pass), &lino, _OVER);
120✔
749
      (void)mndCreateXnode(pMnode, NULL, &createReq);
120✔
750
      code = mndStoreXnodeUserPassToken(pMnode, pReq, &createReq);
120✔
751
      if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
120✔
UNCOV
752
        lino = __LINE__;
×
UNCOV
753
        goto _OVER;
×
754
      }
755
      mndStartXnoded(pMnode, createReq.user, createReq.pass, NULL);
120✔
756
    } else {
757
      code = mndXnodeCreateDefaultToken(pReq, &pToken);
120✔
758
      if (code == TSDB_CODE_MND_TOKEN_ALREADY_EXIST) {
120✔
UNCOV
759
        code = 0;
×
760
      }
761
      if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
120✔
UNCOV
762
        lino = __LINE__;
×
UNCOV
763
        goto _OVER;
×
764
      }
765
      (void)mndCreateXnode(pMnode, NULL, &createReq);
120✔
766
      createReq.token = xCreateCowStr(strlen(pToken), pToken, false);
120✔
767
      (void)mndStoreXnodeUserPassToken(pMnode, NULL, &createReq);
120✔
768
      mndStartXnoded(pMnode, NULL, NULL, createReq.token.ptr);
120✔
769
    }
770
  } else {
771
    code = mndCreateXnode(pMnode, pReq, &createReq);
1,680✔
772
    if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
1,680✔
773
      lino = __LINE__;
×
774
      goto _OVER;
×
775
    }
776
  }
777

778
  taosMsleep(defaultTimeout);
1,920✔
779
  pObj = mndAcquireXnodeByURL(pMnode, createReq.url);
1,920✔
780
  if (pObj == NULL) {
1,920✔
UNCOV
781
    code = TSDB_CODE_MND_XNODE_NOT_EXIST;
×
UNCOV
782
    goto _OVER;
×
783
  }
784
  // send request
785
  (void)httpCreateXnode(pObj);
1,920✔
786

787
_OVER:
2,400✔
788
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
2,400✔
789
    mError("xnode:%s, failed to create since %s, line:%d", createReq.url, tstrerror(code), lino);
480✔
790
  }
791
  taosMemoryFreeClear(pToken);
2,400✔
792
  mndReleaseXnode(pMnode, pObj);
2,400✔
793
  tFreeSMCreateXnodeReq(&createReq);
2,400✔
794
  TAOS_RETURN(code);
2,400✔
795
}
796

797
static int32_t mndUpdateXnode(SMnode *pMnode, SXnodeObj *pXnode, SRpcMsg *pReq) {
×
798
  mInfo("xnode:%d, start to update", pXnode->id);
×
799
  int32_t   code = -1;
×
800
  STrans   *pTrans = NULL;
×
801
  SXnodeObj xnodeObj = {0};
×
UNCOV
802
  xnodeObj.id = pXnode->id;
×
803
  xnodeObj.updateTime = taosGetTimestampMs();
×
804

805
  pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq, "update-xnode");
×
806
  if (pTrans == NULL) {
×
807
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
808
    if (terrno != 0) code = terrno;
×
809
    goto _OVER;
×
810
  }
811
  mInfo("trans:%d, used to update xnode:%d", pTrans->id, xnodeObj.id);
×
812

UNCOV
813
  TAOS_CHECK_GOTO(mndSetCreateXnodeCommitLogs(pTrans, &xnodeObj), NULL, _OVER);
×
UNCOV
814
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
×
UNCOV
815
  code = 0;
×
816

UNCOV
817
_OVER:
×
UNCOV
818
  mndFreeXnode(&xnodeObj);
×
UNCOV
819
  mndTransDrop(pTrans);
×
UNCOV
820
  TAOS_RETURN(code);
×
821
}
822

823
static int32_t mndUpdateXnodeUserPassToken(SMnode *pMnode, SRpcMsg *pReq, SMUpdateXnodeReq *pUpdate) {
840✔
824
  int32_t           code = 0, lino = 0;
840✔
825
  STrans           *pTrans = NULL;
840✔
826
  SXnodeUserPassObj upObj = {0};
840✔
827
  upObj.id = pUpdate->id;
840✔
828
  upObj.updateTime = taosGetTimestampMs();
840✔
829

830
  if (pUpdate->user.ptr != NULL) {
840✔
831
    upObj.userLen = pUpdate->user.len + 1;
600✔
832
    upObj.user = taosMemoryCalloc(1, upObj.userLen);
600✔
833
    if (upObj.user == NULL) goto _OVER;
600✔
834
    (void)memcpy(upObj.user, pUpdate->user.ptr, pUpdate->user.len);
600✔
835
  }
836
  if (pUpdate->pass.ptr != NULL) {
840✔
837
    upObj.passLen = pUpdate->pass.len + 1;
600✔
838
    upObj.pass = taosMemoryCalloc(1, upObj.passLen);
600✔
839
    if (upObj.pass == NULL) goto _OVER;
600✔
840
    (void)memcpy(upObj.pass, pUpdate->pass.ptr, pUpdate->pass.len);
600✔
841
  }
842
  if (pUpdate->token.ptr != NULL) {
840✔
843
    upObj.tokenLen = pUpdate->token.len + 1;
240✔
844
    upObj.token = taosMemoryCalloc(1, upObj.tokenLen);
240✔
845
    if (upObj.token == NULL) goto _OVER;
240✔
846
    (void)memcpy(upObj.token, pUpdate->token.ptr, pUpdate->token.len);
240✔
847
  }
848

849
  pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq, "update-xnode-userpass");
840✔
850
  if (pTrans == NULL) {
840✔
UNCOV
851
    code = terrno;
×
UNCOV
852
    lino = __LINE__;
×
UNCOV
853
    goto _OVER;
×
854
  }
855
  mDebug("trans:%d, used to update xnode userpass or token:%d", pTrans->id, upObj.id);
840✔
856

857
  TAOS_CHECK_GOTO(mndSetCreateXnodeUserPassCommitLogs(pTrans, &upObj), NULL, _OVER);
840✔
858
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
840✔
859
  code = TSDB_CODE_ACTION_IN_PROGRESS;
840✔
860

861
_OVER:
840✔
862
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
840✔
UNCOV
863
    mError("xnode:failed to update xnode %d since %s, line:%d", upObj.id, tstrerror(code), lino);
×
864
  }
865
  taosMemoryFreeClear(upObj.user);
840✔
866
  taosMemoryFreeClear(upObj.pass);
840✔
867
  taosMemoryFreeClear(upObj.token);
840✔
868
  mndTransDrop(pTrans);
840✔
869
  TAOS_RETURN(code);
840✔
870
}
871

872
static int32_t mndProcessUpdateXnodeReq(SRpcMsg *pReq) {
840✔
873
  SMnode          *pMnode = pReq->info.node;
840✔
874
  int32_t          code = 0;
840✔
875
  SXnodeObj       *pObj = NULL;
840✔
876
  SMUpdateXnodeReq updateReq = {0};
840✔
877
  bool             isSuperUser = false;
840✔
878

879
  code = mndValidateXnodePermissions(pMnode, pReq, MND_OPER_UPDATE_XNODE);
840✔
880
  if (code != TSDB_CODE_SUCCESS) {
840✔
881
    mError("failed check permission for update xnode, code:%s", tstrerror(code));
×
UNCOV
882
    goto _OVER;
×
883
  }
884
  TAOS_CHECK_GOTO(tDeserializeSMUpdateXnodeReq(pReq->pCont, pReq->contLen, &updateReq), NULL, _OVER);
840✔
885

886
  if (updateReq.token.ptr != NULL || (updateReq.user.ptr != NULL && updateReq.pass.ptr != NULL)) {
840✔
887
    code = mndUpdateXnodeUserPassToken(pMnode, pReq, &updateReq);
840✔
888
    if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
840✔
UNCOV
889
      goto _OVER;
×
890
    }
891
    mndRestartXnoded(pMnode);
840✔
892
  }
893

894
_OVER:
840✔
895
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
840✔
UNCOV
896
    mError("xnode:%d, failed to update since %s", updateReq.id, tstrerror(code));
×
897
  }
898
  mndReleaseXnode(pMnode, pObj);
840✔
899
  tFreeSMUpdateXnodeReq(&updateReq);
840✔
900
  TAOS_RETURN(code);
840✔
901
}
902

903
static int32_t mndSetDropXnodeRedoLogs(STrans *pTrans, SXnodeObj *pObj) {
1,440✔
904
  int32_t  code = 0;
1,440✔
905
  SSdbRaw *pRedoRaw = mndXnodeActionEncode(pObj);
1,440✔
906
  if (pRedoRaw == NULL) {
1,440✔
907
    code = terrno;
×
UNCOV
908
    TAOS_RETURN(code);
×
909
  }
910

911
  TAOS_CHECK_RETURN(mndTransAppendRedolog(pTrans, pRedoRaw));
1,440✔
912
  TAOS_CHECK_RETURN(sdbSetRawStatus(pRedoRaw, SDB_STATUS_DROPPING));
1,440✔
913
  TAOS_RETURN(code);
1,440✔
914
}
915

916
static int32_t mndSetDropXnodeCommitLogs(STrans *pTrans, SXnodeObj *pObj) {
1,440✔
917
  int32_t  code = 0;
1,440✔
918
  SSdbRaw *pCommitRaw = mndXnodeActionEncode(pObj);
1,440✔
919
  if (pCommitRaw == NULL) {
1,440✔
UNCOV
920
    code = terrno;
×
UNCOV
921
    TAOS_RETURN(code);
×
922
  }
923

924
  TAOS_CHECK_RETURN(mndTransAppendCommitlog(pTrans, pCommitRaw));
1,440✔
925
  TAOS_CHECK_RETURN(sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED));
1,440✔
926
  TAOS_RETURN(code);
1,440✔
927
}
928

929
static int32_t mndSetDropXnodeInfoToTrans(SMnode *pMnode, STrans *pTrans, SXnodeObj *pObj, bool force) {
1,440✔
930
  if (pObj == NULL) return 0;
1,440✔
931
  TAOS_CHECK_RETURN(mndSetDropXnodeRedoLogs(pTrans, pObj));
1,440✔
932
  TAOS_CHECK_RETURN(mndSetDropXnodeCommitLogs(pTrans, pObj));
1,440✔
933
  return 0;
1,440✔
934
}
935

936
static int32_t mndDropXnode(SMnode *pMnode, SRpcMsg *pReq, SXnodeObj *pObj) {
1,440✔
937
  int32_t code = 0;
1,440✔
938
  int32_t lino = 0;
1,440✔
939

940
  STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, pReq, "drop-xnode");
1,440✔
941
  TSDB_CHECK_NULL(pTrans, code, lino, _OVER, terrno);
1,440✔
942

943
  mndTransSetSerial(pTrans);
1,440✔
944
  mDebug("trans:%d, to drop xnode:%d", pTrans->id, pObj->id);
1,440✔
945

946
  code = mndSetDropXnodeInfoToTrans(pMnode, pTrans, pObj, false);
1,440✔
947
  TSDB_CHECK_CODE(code, lino, _OVER);
1,440✔
948

949
  code = mndTransPrepare(pMnode, pTrans);
1,440✔
950

951
_OVER:
1,440✔
952
  mndTransDrop(pTrans);
1,440✔
953
  TAOS_RETURN(code);
1,440✔
954
}
955

956
static int32_t mndDrainXnode(SMnode *pMnode, SRpcMsg *pReq, SXnodeObj *pObj) {
240✔
957
  int32_t code = 0;
240✔
958
  int32_t lino = 0;
240✔
959

960
  SXnodeObj xnodeObj = {0};
240✔
961
  xnodeObj.id = pObj->id;
240✔
962
  xnodeObj.status = "drain";
240✔
963
  xnodeObj.statusLen = strlen(xnodeObj.status) + 1;
240✔
964
  xnodeObj.updateTime = taosGetTimestampMs();
240✔
965

966
  STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, pReq, "drain-xnode");
240✔
967
  TSDB_CHECK_NULL(pTrans, code, lino, _OVER, terrno);
240✔
968

969
  mndTransSetSerial(pTrans);
240✔
970
  mDebug("trans:%d, to drain xnode:%d", pTrans->id, xnodeObj.id);
240✔
971

972
  TAOS_CHECK_GOTO(mndSetCreateXnodeCommitLogs(pTrans, &xnodeObj), NULL, _OVER);
240✔
973
  code = mndTransPrepare(pMnode, pTrans);
240✔
974

975
_OVER:
240✔
976
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
240✔
UNCOV
977
    mError("xnode:%d, failed to drain since %s", xnodeObj.id, tstrerror(code));
×
978
  }
979
  mndTransDrop(pTrans);
240✔
980
  TAOS_RETURN(code);
240✔
981
}
982

983
static int32_t mndProcessDropXnodeReq(SRpcMsg *pReq) {
2,280✔
984
  SMnode        *pMnode = pReq->info.node;
2,280✔
985
  int32_t        code = -1;
2,280✔
986
  SXnodeObj     *pObj = NULL;
2,280✔
987
  SMDropXnodeReq dropReq = {0};
2,280✔
988
  SJson         *pJson = NULL;
2,280✔
989
  bool           isSuperUser = false;
2,280✔
990

991
  code = mndValidateXnodePermissions(pMnode, pReq, MND_OPER_DROP_XNODE);
2,280✔
992
  if (code != TSDB_CODE_SUCCESS) {
2,280✔
UNCOV
993
    mError("failed check permission for drop xnode, code:%s", tstrerror(code));
×
UNCOV
994
    goto _OVER;
×
995
  }
996
  TAOS_CHECK_GOTO(tDeserializeSMDropXnodeReq(pReq->pCont, pReq->contLen, &dropReq), NULL, _OVER);
2,280✔
997
  mDebug("xnode:%d, start to drop", dropReq.xnodeId);
2,280✔
998

999
  if (dropReq.xnodeId <= 0 && (dropReq.url == NULL || strlen(dropReq.url) <= 0)) {
2,280✔
UNCOV
1000
    code = TSDB_CODE_MND_XNODE_INVALID_MSG;
×
UNCOV
1001
    goto _OVER;
×
1002
  }
1003

1004
  if (dropReq.url != NULL && strlen(dropReq.url) > 0) {
2,280✔
1005
    pObj = mndAcquireXnodeByURL(pMnode, dropReq.url);
1,800✔
1006
    if (pObj == NULL) {
1,800✔
1007
      code = terrno;
360✔
1008
      goto _OVER;
360✔
1009
    }
1010
  } else {
1011
    pObj = mndAcquireXnode(pMnode, dropReq.xnodeId);
480✔
1012
    if (pObj == NULL) {
480✔
1013
      code = terrno;
480✔
1014
      goto _OVER;
480✔
1015
    }
1016
  }
1017

1018
  // send request
1019
  char xnodeUrl[TSDB_XNODE_URL_LEN] = {0};
1,440✔
1020
  snprintf(xnodeUrl, TSDB_XNODE_URL_LEN, "%s/xnode/%d?force=%s", XNODED_PIPE_SOCKET_URL, pObj->id,
1,440✔
1021
           dropReq.force ? "true" : "false");
1,440✔
1022
  pJson = mndSendReqRetJson(xnodeUrl, HTTP_TYPE_DELETE, defaultTimeout, NULL, 0);
1,440✔
1023

1024
  code = mndDropXnode(pMnode, pReq, pObj);
1,440✔
1025
  if (code == 0) {
1,440✔
1026
    code = TSDB_CODE_ACTION_IN_PROGRESS;
1,440✔
1027
  }
1028

1029
_OVER:
2,280✔
1030
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
2,280✔
1031
    mError("xnode:%d, failed to drop since %s", dropReq.xnodeId, tstrerror(code));
840✔
1032
  }
1033
  if (pJson != NULL) {
2,280✔
UNCOV
1034
    tjsonDelete(pJson);
×
1035
  }
1036
  if (pObj != NULL) {
2,280✔
1037
    mndReleaseXnode(pMnode, pObj);
1,440✔
1038
  }
1039
  tFreeSMDropXnodeReq(&dropReq);
2,280✔
1040
  TAOS_RETURN(code);
2,280✔
1041
}
1042

1043
static int32_t mndProcessDrainXnodeReq(SRpcMsg *pReq) {
360✔
1044
  SMnode         *pMnode = pReq->info.node;
360✔
1045
  int32_t         code = 0;
360✔
1046
  SXnodeObj      *pObj = NULL;
360✔
1047
  SMDrainXnodeReq drainReq = {0};
360✔
1048
  SJson          *pJson = NULL;
360✔
1049
  SJson          *postContent = NULL;
360✔
1050
  char           *pContStr = NULL;
360✔
1051
  bool            isSuperUser = false;
360✔
1052

1053
  code = mndValidateXnodePermissions(pMnode, pReq, MND_OPER_DRAIN_XNODE);
360✔
1054
  if (code != TSDB_CODE_SUCCESS) {
360✔
UNCOV
1055
    mError("failed check permission for drain xnode, code:%s", tstrerror(code));
×
UNCOV
1056
    goto _OVER;
×
1057
  }
1058
  TAOS_CHECK_GOTO(tDeserializeSMDrainXnodeReq(pReq->pCont, pReq->contLen, &drainReq), NULL, _OVER);
360✔
1059
  mDebug("xnode:%d, start to drain", drainReq.xnodeId);
360✔
1060

1061
  if (drainReq.xnodeId <= 0) {
360✔
UNCOV
1062
    code = TSDB_CODE_MND_XNODE_INVALID_MSG;
×
UNCOV
1063
    goto _OVER;
×
1064
  }
1065

1066
  pObj = mndAcquireXnode(pMnode, drainReq.xnodeId);
360✔
1067
  if (pObj == NULL) {
360✔
1068
    code = TSDB_CODE_MND_XNODE_NOT_EXIST;
120✔
1069
    goto _OVER;
120✔
1070
  }
1071

1072
  // send request
1073
  char xnodeUrl[TSDB_XNODE_URL_LEN + 1] = {0};
240✔
1074
  snprintf(xnodeUrl, TSDB_XNODE_URL_LEN + 1, "%s/xnode/drain/%d", XNODED_PIPE_SOCKET_URL, pObj->id);
240✔
1075
  postContent = tjsonCreateObject();
240✔
1076
  if (postContent == NULL) {
240✔
UNCOV
1077
    code = terrno;
×
UNCOV
1078
    goto _OVER;
×
1079
  }
1080
  TAOS_CHECK_GOTO(tjsonAddStringToObject(postContent, "xnode", pObj->url), NULL, _OVER);
240✔
1081
  pContStr = tjsonToString(postContent);
240✔
1082
  if (pContStr == NULL) {
240✔
UNCOV
1083
    code = terrno;
×
UNCOV
1084
    goto _OVER;
×
1085
  }
1086
  pJson = mndSendReqRetJson(xnodeUrl, HTTP_TYPE_POST, defaultTimeout, pContStr, strlen(pContStr));
240✔
1087

1088
  code = mndDrainXnode(pMnode, pReq, pObj);
240✔
1089
  if (code == 0) {
240✔
1090
    code = TSDB_CODE_ACTION_IN_PROGRESS;
240✔
1091
    goto _OVER;
240✔
1092
  }
1093

1094
_OVER:
360✔
1095
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
360✔
1096
    mError("xnode:%d, failed to drain since %s", drainReq.xnodeId, tstrerror(code));
120✔
1097
  }
1098

1099
  if (postContent != NULL) {
360✔
1100
    tjsonDelete(postContent);
240✔
1101
  }
1102
  if (pContStr != NULL) {
360✔
1103
    taosMemoryFree(pContStr);
240✔
1104
  }
1105
  if (pJson != NULL) {
360✔
UNCOV
1106
    tjsonDelete(pJson);
×
1107
  }
1108
  mndReleaseXnode(pMnode, pObj);
360✔
1109
  tFreeSMDrainXnodeReq(&drainReq);
360✔
1110
  TAOS_RETURN(code);
360✔
1111
}
1112

1113
static int32_t mndRetrieveXnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
2,404✔
1114
  SMnode    *pMnode = pReq->info.node;
2,404✔
1115
  SSdb      *pSdb = pMnode->pSdb;
2,404✔
1116
  int32_t    numOfRows = 0;
2,404✔
1117
  int32_t    cols = 0;
2,404✔
1118
  SXnodeObj *pObj = NULL;
2,404✔
1119
  char       buf[TSDB_XNODE_URL_LEN + VARSTR_HEADER_SIZE] = {0};
2,404✔
1120
  char       status[TSDB_XNODE_STATUS_LEN] = {0};
2,404✔
1121
  int32_t    code = 0;
2,404✔
1122
  mDebug("show.type:%d, %s:%d: retrieve xnodes with rows: %d", pShow->type, __FILE__, __LINE__, rows);
2,404✔
1123

1124
  while (numOfRows < rows) {
5,644✔
1125
    pShow->pIter = sdbFetch(pSdb, SDB_XNODE, pShow->pIter, (void **)&pObj);
5,644✔
1126
    if (pShow->pIter == NULL) break;
5,644✔
1127

1128
    cols = 0;
3,240✔
1129
    SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
3,240✔
1130
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->id, false);
3,240✔
1131
    if (code != 0) goto _end;
3,240✔
1132

1133
    STR_WITH_MAXSIZE_TO_VARSTR(buf, pObj->url, pShow->pMeta->pSchemas[cols].bytes);
3,240✔
1134
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
3,240✔
1135
    code = colDataSetVal(pColInfo, numOfRows, (const char *)buf, false);
3,240✔
1136
    if (code != 0) goto _end;
3,240✔
1137

1138
    if (mndGetXnodeStatus(pObj, status, TSDB_XNODE_STATUS_LEN) == 0) {
3,240✔
UNCOV
1139
      STR_TO_VARSTR(buf, status);
×
1140
    } else {
1141
      mDebug("xnode:%d, status request err: %s", pObj->id, tstrerror(terrno));
3,240✔
1142
      STR_TO_VARSTR(buf, "offline");
3,240✔
1143
    }
1144
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
3,240✔
1145
    code = colDataSetVal(pColInfo, numOfRows, buf, false);
3,240✔
1146
    if (code != 0) goto _end;
3,240✔
1147

1148
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
3,240✔
1149
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->createTime, false);
3,240✔
1150
    if (code != 0) goto _end;
3,240✔
1151

1152
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
3,240✔
1153
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->updateTime, false);
3,240✔
1154
    if (code != 0) goto _end;
3,240✔
1155

1156
    numOfRows++;
3,240✔
1157
    sdbRelease(pSdb, pObj);
3,240✔
1158
  }
1159

1160
_end:
2,404✔
1161
  if (code != 0) sdbRelease(pSdb, pObj);
2,404✔
1162

1163
  pShow->numOfRows += numOfRows;
2,404✔
1164
  return numOfRows;
2,404✔
1165
}
1166

UNCOV
1167
static void mndCancelGetNextXnode(SMnode *pMnode, void *pIter) {
×
UNCOV
1168
  SSdb *pSdb = pMnode->pSdb;
×
UNCOV
1169
  sdbCancelFetchByType(pSdb, pIter, SDB_XNODE);
×
UNCOV
1170
}
×
1171

1172
/** xnode task section **/
1173

1174
static SXnodeTaskObj *mndAcquireXnodeTaskById(SMnode *pMnode, int32_t tid) {
10,560✔
1175
  SSdb *pSdb = pMnode->pSdb;
10,560✔
1176

1177
  void *pIter = NULL;
10,560✔
1178
  while (1) {
×
1179
    SXnodeTaskObj *pTask = NULL;
10,560✔
1180
    pIter = sdbFetch(pSdb, SDB_XNODE_TASK, pIter, (void **)&pTask);
10,560✔
1181
    if (pIter == NULL) break;
10,560✔
1182

1183
    if (pTask->id == tid) {
×
UNCOV
1184
      sdbCancelFetch(pSdb, pIter);
×
UNCOV
1185
      return pTask;
×
1186
    }
1187

UNCOV
1188
    sdbRelease(pSdb, pTask);
×
1189
  }
1190

1191
  mDebug("xnode task:%d, not found", tid);
10,560✔
1192
  terrno = TSDB_CODE_MND_XNODE_TASK_NOT_EXIST;
10,560✔
1193
  return NULL;
10,560✔
1194
}
1195
static SXnodeTaskObj *mndAcquireXnodeTaskByName(SMnode *pMnode, const char *name) {
7,800✔
1196
  SSdb *pSdb = pMnode->pSdb;
7,800✔
1197

1198
  void *pIter = NULL;
7,800✔
1199
  while (1) {
×
1200
    SXnodeTaskObj *pTask = NULL;
7,800✔
1201
    pIter = sdbFetch(pSdb, SDB_XNODE_TASK, pIter, (void **)&pTask);
7,800✔
1202
    if (pIter == NULL) break;
7,800✔
1203
    if (pTask->name == NULL) {
×
UNCOV
1204
      continue;
×
1205
    }
1206

UNCOV
1207
    if (strcasecmp(name, pTask->name) == 0) {
×
UNCOV
1208
      sdbCancelFetch(pSdb, pIter);
×
UNCOV
1209
      return pTask;
×
1210
    }
1211

UNCOV
1212
    sdbRelease(pSdb, pTask);
×
1213
  }
1214

1215
  mDebug("xnode task:%s, not found", name);
7,800✔
1216
  terrno = TSDB_CODE_MND_XNODE_TASK_NOT_EXIST;
7,800✔
1217
  return NULL;
7,800✔
1218
}
1219

UNCOV
1220
static void mndFreeXnodeTask(SXnodeTaskObj *pObj) {
×
UNCOV
1221
  taosMemoryFreeClear(pObj->name);
×
UNCOV
1222
  taosMemoryFreeClear(pObj->sourceDsn);
×
UNCOV
1223
  taosMemoryFreeClear(pObj->sinkDsn);
×
UNCOV
1224
  taosMemoryFreeClear(pObj->parser);
×
UNCOV
1225
  taosMemoryFreeClear(pObj->reason);
×
UNCOV
1226
  taosMemoryFreeClear(pObj->status);
×
UNCOV
1227
  taosMemoryFreeClear(pObj->createdBy);
×
UNCOV
1228
  taosMemoryFreeClear(pObj->labels);
×
UNCOV
1229
}
×
1230

1231
SSdbRaw *mndXnodeTaskActionEncode(SXnodeTaskObj *pObj) {
585✔
1232
  int32_t code = 0;
585✔
1233
  int32_t lino = 0;
585✔
1234
  terrno = TSDB_CODE_OUT_OF_MEMORY;
585✔
1235
  if (NULL == pObj) {
585✔
1236
    terrno = TSDB_CODE_INVALID_PARA;
195✔
1237
    return NULL;
195✔
1238
  }
1239

1240
  int32_t totalStrLen = pObj->nameLen + pObj->sourceDsnLen + pObj->sinkDsnLen + pObj->parserLen + pObj->reasonLen +
390✔
1241
                        pObj->statusLen + pObj->createdByLen + pObj->labelsLen;
390✔
1242
  int32_t rawDataLen = sizeof(SXnodeTaskObj) + TSDB_XNODE_RESERVE_SIZE + totalStrLen;
390✔
1243

1244
  SSdbRaw *pRaw = sdbAllocRaw(SDB_XNODE_TASK, TSDB_XNODE_VER_NUMBER, rawDataLen);
390✔
1245
  if (pRaw == NULL) goto _OVER;
390✔
1246

1247
  int32_t dataPos = 0;
390✔
1248
  SDB_SET_INT32(pRaw, dataPos, pObj->id, _OVER)
390✔
1249
  SDB_SET_INT64(pRaw, dataPos, pObj->createTime, _OVER)
390✔
1250
  SDB_SET_INT64(pRaw, dataPos, pObj->updateTime, _OVER)
390✔
1251
  SDB_SET_INT32(pRaw, dataPos, pObj->statusLen, _OVER)
390✔
1252
  SDB_SET_BINARY(pRaw, dataPos, pObj->status, pObj->statusLen, _OVER)
390✔
1253
  SDB_SET_INT32(pRaw, dataPos, pObj->via, _OVER)
390✔
1254
  SDB_SET_INT32(pRaw, dataPos, pObj->xnodeId, _OVER)
390✔
1255
  SDB_SET_INT32(pRaw, dataPos, pObj->nameLen, _OVER)
390✔
1256
  SDB_SET_BINARY(pRaw, dataPos, pObj->name, pObj->nameLen, _OVER)
390✔
1257
  SDB_SET_INT32(pRaw, dataPos, pObj->sourceType, _OVER)
390✔
1258
  SDB_SET_INT32(pRaw, dataPos, pObj->sourceDsnLen, _OVER)
390✔
1259
  SDB_SET_BINARY(pRaw, dataPos, pObj->sourceDsn, pObj->sourceDsnLen, _OVER)
390✔
1260
  SDB_SET_INT32(pRaw, dataPos, pObj->sinkType, _OVER)
390✔
1261
  SDB_SET_INT32(pRaw, dataPos, pObj->sinkDsnLen, _OVER)
390✔
1262
  SDB_SET_BINARY(pRaw, dataPos, pObj->sinkDsn, pObj->sinkDsnLen, _OVER)
390✔
1263
  SDB_SET_INT32(pRaw, dataPos, pObj->parserLen, _OVER)
390✔
1264
  SDB_SET_BINARY(pRaw, dataPos, pObj->parser, pObj->parserLen, _OVER)
390✔
1265
  SDB_SET_INT32(pRaw, dataPos, pObj->reasonLen, _OVER)
390✔
1266
  SDB_SET_BINARY(pRaw, dataPos, pObj->reason, pObj->reasonLen, _OVER)
390✔
1267
  SDB_SET_INT32(pRaw, dataPos, pObj->createdByLen, _OVER)
390✔
1268
  SDB_SET_BINARY(pRaw, dataPos, pObj->createdBy, pObj->createdByLen, _OVER)
390✔
1269
  SDB_SET_INT32(pRaw, dataPos, pObj->labelsLen, _OVER)
390✔
1270
  SDB_SET_BINARY(pRaw, dataPos, pObj->labels, pObj->labelsLen, _OVER)
390✔
1271

1272
  SDB_SET_RESERVE(pRaw, dataPos, TSDB_XNODE_RESERVE_SIZE, _OVER)
390✔
1273

1274
  terrno = 0;
390✔
1275

1276
_OVER:
390✔
1277
  if (terrno != 0) {
390✔
1278
    mError("xnode task:%d, failed to encode to raw:%p since %s", pObj->id, pRaw, terrstr());
×
UNCOV
1279
    sdbFreeRaw(pRaw);
×
UNCOV
1280
    return NULL;
×
1281
  }
1282

1283
  mTrace("xnode task:%d, encode to raw:%p, row:%p", pObj->id, pRaw, pObj);
390✔
1284
  return pRaw;
390✔
1285
}
1286

1287
SSdbRow *mndXnodeTaskActionDecode(SSdbRaw *pRaw) {
585✔
1288
  int32_t code = 0;
585✔
1289
  int32_t lino = 0;
585✔
1290
  terrno = TSDB_CODE_OUT_OF_MEMORY;
585✔
1291
  SSdbRow       *pRow = NULL;
585✔
1292
  SXnodeTaskObj *pObj = NULL;
585✔
1293

1294
  if (NULL == pRaw) {
585✔
1295
    terrno = TSDB_CODE_INVALID_PARA;
195✔
1296
    return NULL;
195✔
1297
  }
1298

1299
  int8_t sver = 0;
390✔
1300
  if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto _OVER;
390✔
1301

1302
  if (sver != TSDB_XNODE_VER_NUMBER) {
390✔
UNCOV
1303
    terrno = TSDB_CODE_SDB_INVALID_DATA_VER;
×
UNCOV
1304
    goto _OVER;
×
1305
  }
1306

1307
  pRow = sdbAllocRow(sizeof(SXnodeTaskObj));
390✔
1308
  if (pRow == NULL) goto _OVER;
390✔
1309

1310
  pObj = sdbGetRowObj(pRow);
390✔
1311
  if (pObj == NULL) goto _OVER;
390✔
1312

1313
  int32_t dataPos = 0;
390✔
1314
  SDB_GET_INT32(pRaw, dataPos, &pObj->id, _OVER)
390✔
1315
  SDB_GET_INT64(pRaw, dataPos, &pObj->createTime, _OVER)
390✔
1316
  SDB_GET_INT64(pRaw, dataPos, &pObj->updateTime, _OVER)
390✔
1317
  SDB_GET_INT32(pRaw, dataPos, &pObj->statusLen, _OVER)
390✔
1318
  if (pObj->statusLen > 0) {
390✔
1319
    pObj->status = taosMemoryCalloc(pObj->statusLen + 1, 1);
390✔
1320
    if (pObj->status == NULL) goto _OVER;
390✔
1321
    SDB_GET_BINARY(pRaw, dataPos, pObj->status, pObj->statusLen, _OVER)
390✔
1322
  }
1323

1324
  SDB_GET_INT32(pRaw, dataPos, &pObj->via, _OVER)
390✔
1325
  SDB_GET_INT32(pRaw, dataPos, &pObj->xnodeId, _OVER)
390✔
1326

1327
  SDB_GET_INT32(pRaw, dataPos, &pObj->nameLen, _OVER)
390✔
1328
  if (pObj->nameLen > 0) {
390✔
1329
    pObj->name = taosMemoryCalloc(pObj->nameLen + 1, 1);
390✔
1330
    if (pObj->name == NULL) goto _OVER;
390✔
1331
    SDB_GET_BINARY(pRaw, dataPos, pObj->name, pObj->nameLen, _OVER)
390✔
1332
  }
1333

1334
  SDB_GET_INT32(pRaw, dataPos, &pObj->sourceType, _OVER)
390✔
1335
  SDB_GET_INT32(pRaw, dataPos, &pObj->sourceDsnLen, _OVER)
390✔
1336
  if (pObj->sourceDsnLen > 0) {
390✔
1337
    pObj->sourceDsn = taosMemoryCalloc(pObj->sourceDsnLen + 1, 1);
390✔
1338
    if (pObj->sourceDsn == NULL) goto _OVER;
390✔
1339
    SDB_GET_BINARY(pRaw, dataPos, pObj->sourceDsn, pObj->sourceDsnLen, _OVER)
390✔
1340
  }
1341

1342
  SDB_GET_INT32(pRaw, dataPos, &pObj->sinkType, _OVER)
390✔
1343
  SDB_GET_INT32(pRaw, dataPos, &pObj->sinkDsnLen, _OVER)
390✔
1344
  if (pObj->sinkDsnLen > 0) {
390✔
1345
    pObj->sinkDsn = taosMemoryCalloc(pObj->sinkDsnLen + 1, 1);
390✔
1346
    if (pObj->sinkDsn == NULL) goto _OVER;
390✔
1347
    SDB_GET_BINARY(pRaw, dataPos, pObj->sinkDsn, pObj->sinkDsnLen, _OVER)
390✔
1348
  }
1349

1350
  SDB_GET_INT32(pRaw, dataPos, &pObj->parserLen, _OVER)
390✔
1351
  if (pObj->parserLen > 0) {
390✔
1352
    pObj->parser = taosMemoryCalloc(pObj->parserLen + 1, 1);
195✔
1353
    if (pObj->parser == NULL) goto _OVER;
195✔
1354
    SDB_GET_BINARY(pRaw, dataPos, pObj->parser, pObj->parserLen, _OVER)
195✔
1355
  }
1356

1357
  SDB_GET_INT32(pRaw, dataPos, &pObj->reasonLen, _OVER)
390✔
1358
  if (pObj->reasonLen > 0) {
390✔
1359
    pObj->reason = taosMemoryCalloc(pObj->reasonLen + 1, 1);
195✔
1360
    if (pObj->reason == NULL) goto _OVER;
195✔
1361
    SDB_GET_BINARY(pRaw, dataPos, pObj->reason, pObj->reasonLen, _OVER)
195✔
1362
  }
1363

1364
  SDB_GET_INT32(pRaw, dataPos, &pObj->createdByLen, _OVER)
390✔
1365
  if (pObj->createdByLen > 0) {
390✔
UNCOV
1366
    pObj->createdBy = taosMemoryCalloc(pObj->createdByLen + 1, 1);
×
1367
    if (pObj->createdBy == NULL) goto _OVER;
×
1368
    SDB_GET_BINARY(pRaw, dataPos, pObj->createdBy, pObj->createdByLen, _OVER)
×
1369
  }
1370

1371
  SDB_GET_INT32(pRaw, dataPos, &pObj->labelsLen, _OVER)
390✔
1372
  if (pObj->labelsLen > 0) {
390✔
UNCOV
1373
    pObj->labels = taosMemoryCalloc(pObj->labelsLen + 1, 1);
×
UNCOV
1374
    if (pObj->labels == NULL) goto _OVER;
×
1375
    SDB_GET_BINARY(pRaw, dataPos, pObj->labels, pObj->labelsLen, _OVER)
×
1376
  }
1377

1378
  SDB_GET_RESERVE(pRaw, dataPos, TSDB_XNODE_RESERVE_SIZE, _OVER)
390✔
1379

1380
  terrno = 0;
390✔
1381

1382
_OVER:
390✔
1383
  if (terrno != 0) {
390✔
UNCOV
1384
    mError("xnode task:%d, failed to decode from raw:%p since %s", pObj == NULL ? 0 : pObj->id, pRaw, terrstr());
×
UNCOV
1385
    if (pObj != NULL) {
×
1386
      taosMemoryFreeClear(pObj->name);
×
1387
      taosMemoryFreeClear(pObj->sourceDsn);
×
UNCOV
1388
      taosMemoryFreeClear(pObj->sinkDsn);
×
1389
      taosMemoryFreeClear(pObj->parser);
×
1390
      taosMemoryFreeClear(pObj->reason);
×
1391
      taosMemoryFreeClear(pObj->status);
×
1392
    }
1393
    taosMemoryFreeClear(pRow);
×
1394
    return NULL;
×
1395
  }
1396

1397
  mTrace("xnode:%d, decode from raw:%p, row:%p", pObj->id, pRaw, pObj);
390✔
1398
  return pRow;
390✔
1399
}
1400

UNCOV
1401
int32_t mndXnodeTaskActionInsert(SSdb *pSdb, SXnodeTaskObj *pObj) {
×
1402
  mDebug("xtask:%d, perform insert action, row:%p", pObj->id, pObj);
×
1403
  return 0;
×
1404
}
1405

1406
int32_t mndXnodeTaskActionDelete(SSdb *pSdb, SXnodeTaskObj *pObj) {
×
1407
  mDebug("xtask:%d, perform delete action, row:%p", pObj->id, pObj);
×
1408
  mndFreeXnodeTask(pObj);
×
1409
  return 0;
×
1410
}
1411

1412
int32_t mndXnodeTaskActionUpdate(SSdb *pSdb, SXnodeTaskObj *pOld, SXnodeTaskObj *pNew) {
×
UNCOV
1413
  mDebug("xtask:%d, perform update action, old row:%p new row:%p", pOld->id, pOld, pNew);
×
1414

1415
  taosWLockLatch(&pOld->lock);
×
1416
  pOld->via = pNew->via;
×
UNCOV
1417
  pOld->xnodeId = pNew->xnodeId;
×
UNCOV
1418
  swapFields(&pNew->statusLen, &pNew->status, &pOld->statusLen, &pOld->status);
×
1419
  swapFields(&pNew->nameLen, &pNew->name, &pOld->nameLen, &pOld->name);
×
1420
  swapFields(&pNew->sourceDsnLen, &pNew->sourceDsn, &pOld->sourceDsnLen, &pOld->sourceDsn);
×
1421
  swapFields(&pNew->sinkDsnLen, &pNew->sinkDsn, &pOld->sinkDsnLen, &pOld->sinkDsn);
×
1422
  swapFields(&pNew->parserLen, &pNew->parser, &pOld->parserLen, &pOld->parser);
×
1423
  swapFields(&pNew->reasonLen, &pNew->reason, &pOld->reasonLen, &pOld->reason);
×
1424
  swapFields(&pNew->labelsLen, &pNew->labels, &pOld->labelsLen, &pOld->labels);
×
1425
  if (pNew->updateTime > pOld->updateTime) {
×
UNCOV
1426
    pOld->updateTime = pNew->updateTime;
×
1427
  }
1428
  taosWUnLockLatch(&pOld->lock);
×
1429
  return 0;
×
1430
}
1431

1432
static int32_t mndSetCreateXnodeTaskRedoLogs(STrans *pTrans, SXnodeTaskObj *pObj) {
×
1433
  int32_t  code = 0;
×
1434
  SSdbRaw *pRedoRaw = mndXnodeTaskActionEncode(pObj);
×
1435
  if (pRedoRaw == NULL) {
×
1436
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
1437
    if (terrno != 0) code = terrno;
×
1438
    TAOS_RETURN(code);
×
1439
  }
1440
  TAOS_CHECK_RETURN(mndTransAppendRedolog(pTrans, pRedoRaw));
×
1441
  TAOS_CHECK_RETURN(sdbSetRawStatus(pRedoRaw, SDB_STATUS_CREATING));
×
1442
  TAOS_RETURN(code);
×
1443
}
1444

UNCOV
1445
static int32_t mndSetCreateXnodeTaskUndoLogs(STrans *pTrans, SXnodeTaskObj *pObj) {
×
UNCOV
1446
  int32_t  code = 0;
×
UNCOV
1447
  SSdbRaw *pUndoRaw = mndXnodeTaskActionEncode(pObj);
×
UNCOV
1448
  if (pUndoRaw == NULL) {
×
UNCOV
1449
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1450
    if (terrno != 0) code = terrno;
×
UNCOV
1451
    TAOS_RETURN(code);
×
1452
  }
UNCOV
1453
  TAOS_CHECK_RETURN(mndTransAppendUndolog(pTrans, pUndoRaw));
×
UNCOV
1454
  TAOS_CHECK_RETURN(sdbSetRawStatus(pUndoRaw, SDB_STATUS_DROPPED));
×
UNCOV
1455
  TAOS_RETURN(code);
×
1456
}
1457

UNCOV
1458
static int32_t mndSetCreateXnodeTaskCommitLogs(STrans *pTrans, SXnodeTaskObj *pObj) {
×
UNCOV
1459
  int32_t  code = 0;
×
1460
  SSdbRaw *pCommitRaw = mndXnodeTaskActionEncode(pObj);
×
1461
  if (pCommitRaw == NULL) {
×
1462
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1463
    if (terrno != 0) code = terrno;
×
1464
    TAOS_RETURN(code);
×
1465
  }
1466
  TAOS_CHECK_RETURN(mndTransAppendCommitlog(pTrans, pCommitRaw));
×
1467
  TAOS_CHECK_RETURN(sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY));
×
1468
  TAOS_RETURN(code);
×
1469
}
1470
void mndReleaseXnodeTask(SMnode *pMnode, SXnodeTaskObj *pObj) {
11,280✔
1471
  SSdb *pSdb = pMnode->pSdb;
11,280✔
1472
  sdbRelease(pSdb, pObj);
11,280✔
1473
}
11,280✔
1474

1475
static const char *getXTaskOptionByName(xTaskOptions *pOptions, const char *name) {
5,040✔
1476
  if (pOptions == NULL || name == NULL) return NULL;
5,040✔
1477
  for (int32_t i = 0; i < pOptions->optionsNum; ++i) {
10,800✔
1478
    CowStr option = pOptions->options[i];
7,680✔
1479
    if (option.ptr != NULL && strncasecmp(option.ptr, name, strlen(name)) == 0 && option.ptr[strlen(name)] == '=') {
7,680✔
1480
      return option.ptr + strlen(name) + 1;
1,920✔
1481
    }
1482
  }
1483
  return NULL;
3,120✔
1484
}
1485

1486
static int32_t mndCreateXnodeTask(SMnode *pMnode, SRpcMsg *pReq, SMCreateXnodeTaskReq *pCreate) {
×
UNCOV
1487
  int32_t code = -1;
×
1488
  STrans *pTrans = NULL;
×
1489

1490
  SXnodeTaskObj xnodeObj = {0};
×
1491
  xnodeObj.id = sdbGetMaxId(pMnode->pSdb, SDB_XNODE_TASK);
×
1492
  xnodeObj.createTime = taosGetTimestampMs();
×
UNCOV
1493
  xnodeObj.updateTime = xnodeObj.createTime;
×
UNCOV
1494
  xnodeObj.via = pCreate->options.via;
×
1495
  xnodeObj.xnodeId = pCreate->xnodeId;
×
1496

1497
  xnodeObj.nameLen = pCreate->name.len + 1;
×
1498
  xnodeObj.name = taosMemoryCalloc(1, xnodeObj.nameLen);
×
1499
  if (xnodeObj.name == NULL) goto _OVER;
×
1500
  (void)memcpy(xnodeObj.name, pCreate->name.ptr, pCreate->name.len);
×
1501

UNCOV
1502
  xnodeObj.sourceType = pCreate->source.type;
×
1503
  xnodeObj.sourceDsnLen = pCreate->source.cstr.len + 1;
×
1504
  xnodeObj.sourceDsn = taosMemoryCalloc(1, xnodeObj.sourceDsnLen);
×
1505
  if (xnodeObj.sourceDsn == NULL) goto _OVER;
×
1506
  (void)memcpy(xnodeObj.sourceDsn, pCreate->source.cstr.ptr, pCreate->source.cstr.len);
×
1507

1508
  xnodeObj.sinkType = pCreate->sink.type;
×
1509
  xnodeObj.sinkDsnLen = pCreate->sink.cstr.len + 1;
×
1510
  xnodeObj.sinkDsn = taosMemoryCalloc(1, xnodeObj.sinkDsnLen);
×
1511
  if (xnodeObj.sinkDsn == NULL) goto _OVER;
×
1512
  (void)memcpy(xnodeObj.sinkDsn, pCreate->sink.cstr.ptr, pCreate->sink.cstr.len);
×
1513

UNCOV
1514
  xnodeObj.parserLen = pCreate->options.parser.len + 1;
×
UNCOV
1515
  if (pCreate->options.parser.ptr != NULL) {
×
1516
    xnodeObj.parser = taosMemoryCalloc(1, xnodeObj.parserLen);
×
1517
    if (xnodeObj.parser == NULL) goto _OVER;
×
1518
    (void)memcpy(xnodeObj.parser, pCreate->options.parser.ptr, pCreate->options.parser.len);
×
1519
  }
1520

UNCOV
1521
  const char *status = getXTaskOptionByName(&pCreate->options, "status");
×
1522
  if (status != NULL) {
×
1523
    xnodeObj.statusLen = strlen(status) + 1;
×
UNCOV
1524
    xnodeObj.status = taosMemoryCalloc(1, xnodeObj.statusLen);
×
1525
    if (xnodeObj.status == NULL) goto _OVER;
×
UNCOV
1526
    (void)memcpy(xnodeObj.status, status, xnodeObj.statusLen - 1);
×
1527
  }
1528

1529
  xnodeObj.createdByLen = strlen(pReq->info.conn.user) + 1;
×
1530
  xnodeObj.createdBy = taosMemoryCalloc(1, xnodeObj.createdByLen);
×
1531
  if (xnodeObj.createdBy == NULL) goto _OVER;
×
1532
  (void)memcpy(xnodeObj.createdBy, pReq->info.conn.user, xnodeObj.createdByLen - 1);
×
1533

1534
  const char *labels = getXTaskOptionByName(&pCreate->options, "labels");
×
UNCOV
1535
  if (labels != NULL) {
×
1536
    xnodeObj.labelsLen = strlen(labels) + 1;
×
1537
    xnodeObj.labels = taosMemoryCalloc(1, xnodeObj.labelsLen);
×
1538
    if (xnodeObj.labels == NULL) goto _OVER;
×
1539
    (void)memcpy(xnodeObj.labels, labels, xnodeObj.labelsLen - 1);
×
1540
  }
1541

UNCOV
1542
  pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq, "create-xnode-task");
×
UNCOV
1543
  if (pTrans == NULL) {
×
UNCOV
1544
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
1545
    if (terrno != 0) {
×
UNCOV
1546
      code = terrno;
×
1547
    }
UNCOV
1548
    mError("failed to create transaction for xnode-task:%s, code:0x%x:%s", pCreate->name.ptr, code, tstrerror(code));
×
UNCOV
1549
    goto _OVER;
×
1550
  }
UNCOV
1551
  mndTransSetSerial(pTrans);
×
1552

UNCOV
1553
  mDebug("trans:%d, used to create xnode task:%s as task:%d", pTrans->id, pCreate->name.ptr, xnodeObj.id);
×
1554

UNCOV
1555
  TAOS_CHECK_GOTO(mndSetCreateXnodeTaskRedoLogs(pTrans, &xnodeObj), NULL, _OVER);
×
UNCOV
1556
  TAOS_CHECK_GOTO(mndSetCreateXnodeTaskUndoLogs(pTrans, &xnodeObj), NULL, _OVER);
×
1557
  TAOS_CHECK_GOTO(mndSetCreateXnodeTaskCommitLogs(pTrans, &xnodeObj), NULL, _OVER);
×
1558
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
×
1559

UNCOV
1560
  code = 0;
×
1561

1562
_OVER:
×
1563
  mndFreeXnodeTask(&xnodeObj);
×
UNCOV
1564
  mndTransDrop(pTrans);
×
UNCOV
1565
  TAOS_RETURN(code);
×
1566
}
1567

1568
// Helper function to parse and validate the request
1569
static int32_t mndValidateCreateXnodeTaskReq(SRpcMsg *pReq, SMCreateXnodeTaskReq *pCreateReq) {
3,960✔
1570
  int32_t code = 0;
3,960✔
1571
  SJson  *pJson = NULL;
3,960✔
1572
  SJson  *postContent = NULL;
3,960✔
1573
  char   *srcDsn = NULL;
3,960✔
1574
  char   *sinkDsn = NULL;
3,960✔
1575
  char   *parser = NULL;
3,960✔
1576
  char   *pContStr = NULL;
3,960✔
1577

1578
  // from, to, parser check
1579
  char xnodeUrl[TSDB_XNODE_URL_LEN] = {0};
3,960✔
1580
  snprintf(xnodeUrl, TSDB_XNODE_URL_LEN, "%s/task/check", XNODED_PIPE_SOCKET_URL);
3,960✔
1581
  postContent = tjsonCreateObject();
3,960✔
1582
  if (postContent == NULL) {
3,960✔
UNCOV
1583
    code = terrno;
×
1584
    goto _OVER;
×
1585
  }
1586
  srcDsn = taosStrndupi(pCreateReq->source.cstr.ptr, (int64_t)pCreateReq->source.cstr.len);
3,960✔
1587
  if (srcDsn == NULL) {
3,960✔
UNCOV
1588
    code = terrno;
×
UNCOV
1589
    goto _OVER;
×
1590
  }
1591
  TAOS_CHECK_GOTO(tjsonAddStringToObject(postContent, "from", srcDsn), NULL, _OVER);
3,960✔
1592

1593
  sinkDsn = taosStrndupi(pCreateReq->sink.cstr.ptr, (int64_t)pCreateReq->sink.cstr.len);
3,960✔
1594
  if (sinkDsn == NULL) {
3,960✔
UNCOV
1595
    code = terrno;
×
UNCOV
1596
    goto _OVER;
×
1597
  }
1598
  TAOS_CHECK_GOTO(tjsonAddStringToObject(postContent, "to", sinkDsn), NULL, _OVER);
3,960✔
1599

1600
  if (pCreateReq->options.parser.len > 0 && pCreateReq->options.parser.ptr != NULL) {
3,960✔
1601
    parser = taosStrndupi(pCreateReq->options.parser.ptr, (int64_t)pCreateReq->options.parser.len);
2,520✔
1602
    if (parser == NULL) {
2,520✔
UNCOV
1603
      code = terrno;
×
UNCOV
1604
      goto _OVER;
×
1605
    }
1606
    TAOS_CHECK_GOTO(tjsonAddStringToObject(postContent, "parser", parser), NULL, _OVER);
2,520✔
1607
  }
1608

1609
  if (pCreateReq->xnodeId > 0) {
3,960✔
1610
    TAOS_CHECK_GOTO(tjsonAddDoubleToObject(postContent, "xnode_id", (double)pCreateReq->xnodeId), NULL, _OVER);
×
1611
  }
1612

1613
  if (pCreateReq->options.via > 0) {
3,960✔
1614
    TAOS_CHECK_GOTO(tjsonAddDoubleToObject(postContent, "via", (double)pCreateReq->options.via), NULL, _OVER);
360✔
1615
  }
1616

1617
  const char *labels = getXTaskOptionByName(&pCreateReq->options, "labels");
3,960✔
1618
  if (labels != NULL) {
3,960✔
1619
    TAOS_CHECK_GOTO(tjsonAddStringToObject(postContent, "labels", labels), NULL, _OVER);
1,560✔
1620
  }
1621

1622
  TAOS_CHECK_GOTO(tjsonAddStringToObject(postContent, "created_by", pReq->info.conn.user), NULL, _OVER);
3,960✔
1623

1624
  pContStr = tjsonToUnformattedString(postContent);
3,960✔
1625
  if (pContStr == NULL) {
3,960✔
1626
    code = terrno;
×
UNCOV
1627
    goto _OVER;
×
1628
  }
1629

1630
  pJson = mndSendReqRetJson(xnodeUrl, HTTP_TYPE_POST, 60000, pContStr, strlen(pContStr));
3,960✔
1631
  if (pJson == NULL) {
3,960✔
1632
    code = terrno;
3,960✔
1633
    goto _OVER;
3,960✔
1634
  }
UNCOV
1635
  SJson *errorJson = tjsonGetObjectItem(pJson, "__inner_error");
×
UNCOV
1636
  if (errorJson != NULL) {
×
UNCOV
1637
    code = TSDB_CODE_MND_XNODE_HTTP_CODE_ERROR;
×
UNCOV
1638
    char* pValueString = ((cJSON*)errorJson)->valuestring;
×
UNCOV
1639
    if (NULL == pValueString) {
×
UNCOV
1640
      mError("should not failed to get __inner_error message, task name:%s", pCreateReq->name.ptr);
×
UNCOV
1641
      goto _OVER;
×
1642
    }
1643
    //handle response
UNCOV
1644
    int32_t contLen = strlen(pValueString) + strlen(tstrerror(code)) + 32;
×
UNCOV
1645
    void *pRsp = rpcMallocCont(contLen);
×
UNCOV
1646
    if (pRsp == NULL) {
×
UNCOV
1647
      TAOS_CHECK_GOTO(terrno, NULL, _OVER);
×
1648
    }
1649
    pReq->info.rspLen = contLen;
×
1650
    pReq->info.rsp = pRsp;
×
UNCOV
1651
    snprintf(pReq->info.rsp, contLen, "%s, since: %s", tstrerror(code), pValueString);
×
UNCOV
1652
    goto _OVER;
×
1653
  }
1654

1655
  // todo: only4test
1656
  // (void)mndSendReqRetJson(xnodeUrl, HTTP_TYPE_POST, 60000, pContStr, strlen(pContStr));
1657
  // code = TSDB_CODE_SUCCESS;
1658

1659
_OVER:
3,960✔
1660
  if (srcDsn != NULL) taosMemoryFreeClear(srcDsn);
3,960✔
1661
  if (sinkDsn != NULL) taosMemoryFreeClear(sinkDsn);
3,960✔
1662
  if (parser != NULL) taosMemoryFreeClear(parser);
3,960✔
1663
  if (pContStr != NULL) taosMemoryFreeClear(pContStr);
3,960✔
1664
  if (postContent != NULL) tjsonDelete(postContent);
3,960✔
1665
  if (pJson != NULL) tjsonDelete(pJson);
3,960✔
1666

1667
  TAOS_RETURN(code);
3,960✔
1668
}
1669

1670
// Helper function to check if xnode task already exists
1671
static int32_t mndCheckXnodeTaskExists(SMnode *pMnode, const char *name) {
3,960✔
1672
  SXnodeTaskObj *pObj = mndAcquireXnodeTaskByName(pMnode, name);
3,960✔
1673
  if (pObj != NULL) {
3,960✔
UNCOV
1674
    mError("xnode task:%s already exists", name);
×
UNCOV
1675
    mndReleaseXnodeTask(pMnode, pObj);
×
UNCOV
1676
    return TSDB_CODE_MND_XNODE_TASK_ALREADY_EXIST;
×
1677
  }
1678
  return TSDB_CODE_SUCCESS;
3,960✔
1679
}
1680

1681
// Helper function to handle the creation result
UNCOV
1682
static int32_t mndHandleCreateXnodeTaskResult(int32_t createCode) {
×
UNCOV
1683
  if (createCode == 0) {
×
UNCOV
1684
    return TSDB_CODE_ACTION_IN_PROGRESS;
×
1685
  }
UNCOV
1686
  return createCode;
×
1687
}
1688

1689
static int32_t mndProcessCreateXnodeTaskReq(SRpcMsg *pReq) {
3,960✔
1690
  mDebug("xnode create task request received, contLen:%d\n", pReq->contLen);
3,960✔
1691
  SMnode              *pMnode = pReq->info.node;
3,960✔
1692
  int32_t              code = 0;
3,960✔
1693
  SMCreateXnodeTaskReq createReq = {0};
3,960✔
1694

1695
  // Step 1: Validate permissions
1696
  code = mndValidateXnodePermissions(pMnode, pReq, MND_OPER_CREATE_XNODE_TASK);
3,960✔
1697
  if (code != TSDB_CODE_SUCCESS) {
3,960✔
UNCOV
1698
    mError("failed check permission for create xnode task, code:%s", tstrerror(code));
×
UNCOV
1699
    goto _OVER;
×
1700
  }
1701

1702
  code = tDeserializeSMCreateXnodeTaskReq(pReq->pCont, pReq->contLen, &createReq);
3,960✔
1703
  if (code != 0) {
3,960✔
UNCOV
1704
    mError("failed to deserialize create xnode task request, code:%s", tstrerror(code));
×
UNCOV
1705
    TAOS_RETURN(code);
×
1706
  }
1707

1708
  // Step 2: Check if task already exists
1709
  TAOS_CHECK_GOTO(mndCheckXnodeTaskExists(pMnode, createReq.name.ptr), NULL, _OVER);
3,960✔
1710

1711
  // Step 3: Parse and validate request
1712
  TAOS_CHECK_GOTO(mndValidateCreateXnodeTaskReq(pReq, &createReq), NULL, _OVER);
3,960✔
1713

1714
  // Step 4: Create the xnode task
1715
  TAOS_CHECK_GOTO(mndCreateXnodeTask(pMnode, pReq, &createReq), NULL, _OVER);
×
1716
  TAOS_CHECK_GOTO(mndHandleCreateXnodeTaskResult(code), NULL, _OVER);
×
1717

1718
_OVER:
3,960✔
1719
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
3,960✔
1720
    mError("xnode task:%s, failed to create since %s", createReq.name.ptr ? createReq.name.ptr : "unknown",
3,960✔
1721
           tstrerror(code));
1722
  }
1723
  tFreeSMCreateXnodeTaskReq(&createReq);
3,960✔
1724
  TAOS_RETURN(code);
3,960✔
1725
}
1726

1727
static int32_t httpStartXnodeTask(SXnodeTaskObj *pObj) {
×
1728
  int32_t code = 0;
×
1729
  struct {
1730
    char   xnodeUrl[TSDB_XNODE_URL_LEN + 1];
1731
    SJson *postContent;
1732
    SJson *pJson;
1733
    char  *pContStr;
1734
    char  *srcDsn;
1735
    char  *sinkDsn;
1736
    char  *parser;
1737
  } req = {0};
×
1738

1739
  snprintf(req.xnodeUrl, TSDB_XNODE_URL_LEN + 1, "%s/task/%d", XNODED_PIPE_SOCKET_URL, pObj->id);
×
UNCOV
1740
  req.postContent = tjsonCreateObject();
×
UNCOV
1741
  if (req.postContent == NULL) {
×
1742
    code = terrno;
×
1743
    goto _OVER;
×
1744
  }
UNCOV
1745
  req.srcDsn = taosStrndupi(pObj->sourceDsn, (int64_t)pObj->sourceDsnLen);
×
1746
  if (req.srcDsn == NULL) {
×
1747
    code = terrno;
×
UNCOV
1748
    goto _OVER;
×
1749
  }
1750
  TAOS_CHECK_GOTO(tjsonAddStringToObject(req.postContent, "from", req.srcDsn), NULL, _OVER);
×
1751

UNCOV
1752
  req.sinkDsn = taosStrndupi(pObj->sinkDsn, (int64_t)pObj->sinkDsnLen);
×
UNCOV
1753
  if (req.sinkDsn == NULL) {
×
1754
    code = terrno;
×
1755
    goto _OVER;
×
1756
  }
UNCOV
1757
  TAOS_CHECK_GOTO(tjsonAddStringToObject(req.postContent, "to", req.sinkDsn), NULL, _OVER);
×
1758

1759
  if (pObj->parserLen > 0) {
×
1760
    req.parser = taosStrndupi(pObj->parser, (int64_t)pObj->parserLen);
×
1761
    if (req.parser == NULL) {
×
UNCOV
1762
      code = terrno;
×
1763
      goto _OVER;
×
1764
    }
UNCOV
1765
    TAOS_CHECK_GOTO(tjsonAddStringToObject(req.postContent, "parser", req.parser), NULL, _OVER);
×
1766
  }
1767

1768
  if (pObj->xnodeId > 0) {
×
1769
    TAOS_CHECK_GOTO(tjsonAddDoubleToObject(req.postContent, "xnode_id", (double)pObj->xnodeId), NULL, _OVER);
×
1770
  }
1771

1772
  if (pObj->via > 0) {
×
1773
    TAOS_CHECK_GOTO(tjsonAddDoubleToObject(req.postContent, "via", (double)pObj->via), NULL, _OVER);
×
1774
  }
1775

UNCOV
1776
  if (pObj->createdBy != NULL) {
×
UNCOV
1777
    TAOS_CHECK_GOTO(tjsonAddStringToObject(req.postContent, "created_by", pObj->createdBy), NULL, _OVER);
×
1778
  }
1779

UNCOV
1780
  if (pObj->labels != NULL) {
×
UNCOV
1781
    TAOS_CHECK_GOTO(tjsonAddStringToObject(req.postContent, "labels", pObj->labels), NULL, _OVER);
×
1782
  }
1783

UNCOV
1784
  req.pContStr = tjsonToUnformattedString(req.postContent);
×
1785
  if (req.pContStr == NULL) {
×
1786
    code = terrno;
×
UNCOV
1787
    goto _OVER;
×
1788
  }
UNCOV
1789
  mDebug("start xnode post content:%s", req.pContStr);
×
UNCOV
1790
  req.pJson = mndSendReqRetJson(req.xnodeUrl, HTTP_TYPE_POST, defaultTimeout, req.pContStr, strlen(req.pContStr));
×
1791

1792
_OVER:
×
1793
  if (req.pContStr != NULL) taosMemoryFreeClear(req.pContStr);
×
UNCOV
1794
  if (req.postContent != NULL) tjsonDelete(req.postContent);
×
UNCOV
1795
  if (req.pJson != NULL) tjsonDelete(req.pJson);
×
UNCOV
1796
  if (req.srcDsn != NULL) taosMemoryFreeClear(req.srcDsn);
×
1797
  if (req.sinkDsn != NULL) taosMemoryFreeClear(req.sinkDsn);
×
UNCOV
1798
  if (req.parser != NULL) taosMemoryFreeClear(req.parser);
×
UNCOV
1799
  TAOS_RETURN(code);
×
1800
}
1801

1802
static int32_t mndProcessStartXnodeTaskReq(SRpcMsg *pReq) {
120✔
1803
  SMnode             *pMnode = pReq->info.node;
120✔
1804
  int32_t             code = 0;
120✔
1805
  SXnodeTaskObj      *pObj = NULL;
120✔
1806
  SMStartXnodeTaskReq startReq = {0};
120✔
1807
  SXnodeTaskObj      *pObjClone = NULL;
120✔
1808

1809
  code = mndValidateXnodePermissions(pMnode, pReq, MND_OPER_START_XNODE_TASK);
120✔
1810
  if (code != TSDB_CODE_SUCCESS) {
120✔
UNCOV
1811
    mError("failed check permission for start xnode task, code:%s", tstrerror(code));
×
UNCOV
1812
    goto _OVER;
×
1813
  }
1814
  TAOS_CHECK_GOTO(tDeserializeSMStartXnodeTaskReq(pReq->pCont, pReq->contLen, &startReq), NULL, _OVER);
120✔
1815
  mDebug("xnode start xnode task with tid:%d", startReq.tid);
120✔
1816

1817
  if (startReq.tid <= 0 && (startReq.name.len <= 0 || startReq.name.ptr == NULL)) {
120✔
1818
    code = TSDB_CODE_MND_XNODE_INVALID_MSG;
×
UNCOV
1819
    goto _OVER;
×
1820
  }
1821

1822
  if (startReq.tid > 0) {
120✔
UNCOV
1823
    pObj = mndAcquireXnodeTask(pMnode, startReq.tid);
×
1824
  } else {
1825
    pObj = mndAcquireXnodeTaskByName(pMnode, startReq.name.ptr);
120✔
1826
  }
1827
  if (pObj == NULL) {
120✔
1828
    code = terrno;
120✔
1829
    goto _OVER;
120✔
1830
  }
NEW
1831
  code = mndXnodeCheckTaskObjPrivilege(pMnode, pReq->info.conn.user, pObj, PRIV_CM_ALTER);
×
UNCOV
1832
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
1833
    mError("user:%s has no privilege on xnode task:%d", pReq->info.conn.user, pObj->id);
×
UNCOV
1834
    goto _OVER;
×
1835
  }
1836
  (void)httpStartXnodeTask(pObj);
×
1837

1838
_OVER:
120✔
1839
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
120✔
1840
    mError("xnode task:%d, failed to start since %s", startReq.tid, tstrerror(code));
120✔
1841
  }
1842
  tFreeSMStartXnodeTaskReq(&startReq);
120✔
1843
  if (pObj != NULL) {
120✔
1844
    mndReleaseXnodeTask(pMnode, pObj);
×
1845
  }
1846
  if (pObjClone != NULL) {
120✔
UNCOV
1847
    mndFreeXnodeTask(pObjClone);
×
1848
    taosMemFree(pObjClone);
×
1849
  }
1850
  TAOS_RETURN(code);
120✔
1851
}
1852

1853
static int32_t mndProcessStopXnodeTaskReq(SRpcMsg *pReq) {
120✔
1854
  SMnode            *pMnode = pReq->info.node;
120✔
1855
  int32_t            code = -1;
120✔
1856
  SXnodeTaskObj     *pObj = NULL;
120✔
1857
  SMStopXnodeTaskReq stopReq = {0};
120✔
1858
  SJson             *pJson = NULL;
120✔
1859

1860
  code = mndValidateXnodePermissions(pMnode, pReq, MND_OPER_STOP_XNODE_TASK);
120✔
1861
  if (code != TSDB_CODE_SUCCESS) {
120✔
UNCOV
1862
    mError("failed check permission for stop xnode task, code:%s", tstrerror(code));
×
1863
    goto _OVER;
×
1864
  }
1865
  TAOS_CHECK_GOTO(tDeserializeSMStopXnodeTaskReq(pReq->pCont, pReq->contLen, &stopReq), NULL, _OVER);
120✔
1866
  mDebug("Stop xnode task with tid:%d", stopReq.tid);
120✔
1867

1868
  if (stopReq.tid <= 0 && (stopReq.name.len <= 0 || stopReq.name.ptr == NULL)) {
120✔
UNCOV
1869
    code = TSDB_CODE_MND_XNODE_INVALID_MSG;
×
UNCOV
1870
    goto _OVER;
×
1871
  }
1872

1873
  if (stopReq.tid > 0) {
120✔
UNCOV
1874
    pObj = mndAcquireXnodeTask(pMnode, stopReq.tid);
×
1875
  } else {
1876
    pObj = mndAcquireXnodeTaskByName(pMnode, stopReq.name.ptr);
120✔
1877
  }
1878
  if (pObj == NULL) {
120✔
1879
    code = terrno;
120✔
1880
    goto _OVER;
120✔
1881
  }
NEW
1882
  code = mndXnodeCheckTaskObjPrivilege(pMnode, pReq->info.conn.user, pObj, PRIV_CM_ALTER);
×
1883
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
1884
    mError("user:%s has no privilege on xnode task:%d", pReq->info.conn.user, pObj->id);
×
UNCOV
1885
    goto _OVER;
×
1886
  }
1887

1888
  // send request
UNCOV
1889
  char xnodeUrl[TSDB_XNODE_URL_LEN + 1] = {0};
×
UNCOV
1890
  snprintf(xnodeUrl, TSDB_XNODE_URL_LEN + 1, "%s/task/%d", XNODED_PIPE_SOCKET_URL, pObj->id);
×
UNCOV
1891
  pJson = mndSendReqRetJson(xnodeUrl, HTTP_TYPE_DELETE, defaultTimeout, NULL, 0);
×
1892

1893
_OVER:
120✔
1894
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
120✔
1895
    mError("xnode task:%d, failed to stop since %s", stopReq.tid, tstrerror(code));
120✔
1896
  }
1897
  if (pJson != NULL) {
120✔
1898
    tjsonDelete(pJson);
×
1899
  }
1900
  tFreeSMStopXnodeTaskReq(&stopReq);
120✔
1901
  TAOS_RETURN(code);
120✔
1902
}
1903

1904
static int32_t mndUpdateXnodeTask(SMnode *pMnode, SRpcMsg *pReq, const SXnodeTaskObj *pOld,
×
1905
                                  SMUpdateXnodeTaskReq *pUpdate) {
UNCOV
1906
  mDebug("xnode task:%d, start to update", pUpdate->tid);
×
1907
  int32_t      code = -1;
×
1908
  STrans       *pTrans = NULL;
×
UNCOV
1909
  SXnodeTaskObj taskObj = *pOld;
×
1910
  struct {
1911
    bool status;
1912
    bool name;
1913
    bool source;
1914
    bool sink;
1915
    bool parser;
1916
    bool reason;
1917
    bool labels;
1918
  } isChange = {0};
×
1919

1920
  if (pUpdate->via > 0) {
×
1921
    taskObj.via = pUpdate->via;
×
1922
  }
1923
  if (pUpdate->xnodeId > 0) {
×
1924
    taskObj.xnodeId = pUpdate->xnodeId;
×
1925
  }
1926
  if (pUpdate->status.ptr != NULL) {
×
UNCOV
1927
    taskObj.statusLen = pUpdate->status.len + 1;
×
1928
    taskObj.status = taosMemoryCalloc(1, taskObj.statusLen);
×
1929
    if (taskObj.status == NULL) {
×
UNCOV
1930
      code = terrno;
×
1931
      goto _OVER;
×
1932
    }
1933
    (void)memcpy(taskObj.status, pUpdate->status.ptr, pUpdate->status.len);
×
1934
    isChange.status = true;
×
1935
  }
1936
  if (pUpdate->updateName.ptr != NULL) {
×
1937
    taskObj.nameLen = pUpdate->updateName.len + 1;
×
UNCOV
1938
    taskObj.name = taosMemoryCalloc(1, taskObj.nameLen);
×
1939
    if (taskObj.name == NULL) {
×
1940
      code = terrno;
×
UNCOV
1941
      goto _OVER;
×
1942
    }
1943
    (void)memcpy(taskObj.name, pUpdate->updateName.ptr, pUpdate->updateName.len);
×
1944
    isChange.name = true;
×
1945
  }
1946
  if (pUpdate->source.cstr.ptr != NULL) {
×
1947
    taskObj.sourceType = pUpdate->source.type;
×
UNCOV
1948
    taskObj.sourceDsnLen = pUpdate->source.cstr.len + 1;
×
1949
    taskObj.sourceDsn = taosMemoryCalloc(1, taskObj.sourceDsnLen);
×
1950
    if (taskObj.sourceDsn == NULL) {
×
UNCOV
1951
      code = terrno;
×
1952
      goto _OVER;
×
1953
    }
1954
    (void)memcpy(taskObj.sourceDsn, pUpdate->source.cstr.ptr, pUpdate->source.cstr.len);
×
1955
    isChange.source = true;
×
1956
  }
1957
  if (pUpdate->sink.cstr.ptr != NULL) {
×
UNCOV
1958
    taskObj.sinkType = pUpdate->sink.type;
×
1959
    taskObj.sinkDsnLen = pUpdate->sink.cstr.len + 1;
×
1960
    taskObj.sinkDsn = taosMemoryCalloc(1, taskObj.sinkDsnLen);
×
UNCOV
1961
    if (taskObj.sinkDsn == NULL) {
×
1962
      code = terrno;
×
1963
      goto _OVER;
×
1964
    }
1965
    (void)memcpy(taskObj.sinkDsn, pUpdate->sink.cstr.ptr, pUpdate->sink.cstr.len);
×
1966
    isChange.sink = true;
×
1967
  }
UNCOV
1968
  if (pUpdate->parser.ptr != NULL) {
×
1969
    taskObj.parserLen = pUpdate->parser.len + 1;
×
1970
    taskObj.parser = taosMemoryCalloc(1, taskObj.parserLen);
×
UNCOV
1971
    if (taskObj.parser == NULL) {
×
1972
      code = terrno;
×
UNCOV
1973
      goto _OVER;
×
1974
    }
1975
    (void)memcpy(taskObj.parser, pUpdate->parser.ptr, pUpdate->parser.len);
×
1976
    isChange.parser = true;
×
1977
  }
1978
  if (pUpdate->reason.ptr != NULL) {
×
UNCOV
1979
    taskObj.reasonLen = pUpdate->reason.len + 1;
×
1980
    taskObj.reason = taosMemoryCalloc(1, taskObj.reasonLen);
×
UNCOV
1981
    if (taskObj.reason == NULL) {
×
1982
      code = terrno;
×
1983
      goto _OVER;
×
1984
    }
UNCOV
1985
    (void)memcpy(taskObj.reason, pUpdate->reason.ptr, pUpdate->reason.len);
×
1986
    isChange.reason = true;
×
1987
  }
1988
  if (pUpdate->labels.ptr != NULL) {
×
UNCOV
1989
    taskObj.labelsLen = pUpdate->labels.len + 1;
×
1990
    taskObj.labels = taosMemoryCalloc(1, taskObj.labelsLen);
×
1991
    if (taskObj.labels == NULL) {
×
UNCOV
1992
      code = terrno;
×
1993
      goto _OVER;
×
1994
    }
UNCOV
1995
    (void)memcpy(taskObj.labels, pUpdate->labels.ptr, pUpdate->labels.len);
×
1996
    isChange.labels = true;
×
1997
  }
UNCOV
1998
  taskObj.updateTime = taosGetTimestampMs();
×
1999

2000
  pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq, "update-xnode-task");
×
UNCOV
2001
  if (pTrans == NULL) {
×
2002
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2003
    if (terrno != 0) code = terrno;
×
UNCOV
2004
    goto _OVER;
×
2005
  }
2006
  mInfo("trans:%d, used to update xnode task:%d", pTrans->id, taskObj.id);
×
2007

2008
  TAOS_CHECK_GOTO(mndSetCreateXnodeTaskCommitLogs(pTrans, &taskObj), NULL, _OVER);
×
2009
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
×
UNCOV
2010
  code = 0;
×
2011

UNCOV
2012
_OVER:
×
UNCOV
2013
  if (NULL != taskObj.name && isChange.name) {
×
UNCOV
2014
    taosMemoryFree(taskObj.name);
×
2015
  }
UNCOV
2016
  if (NULL != taskObj.status && isChange.status) {
×
UNCOV
2017
    taosMemoryFree(taskObj.status);
×
2018
  }
UNCOV
2019
  if (NULL != taskObj.sourceDsn && isChange.source) {
×
2020
    taosMemoryFree(taskObj.sourceDsn);
×
2021
  }
UNCOV
2022
  if (NULL != taskObj.sinkDsn && isChange.sink) {
×
UNCOV
2023
    taosMemoryFree(taskObj.sinkDsn);
×
2024
  }
UNCOV
2025
  if (NULL != taskObj.parser && isChange.parser) {
×
UNCOV
2026
    taosMemoryFree(taskObj.parser);
×
2027
  }
UNCOV
2028
  if (NULL != taskObj.reason && isChange.reason) {
×
UNCOV
2029
    taosMemoryFree(taskObj.reason);
×
2030
  }
UNCOV
2031
  if (NULL != taskObj.labels && isChange.labels) {
×
UNCOV
2032
    taosMemoryFree(taskObj.labels);
×
2033
  }
UNCOV
2034
  mndTransDrop(pTrans);
×
2035
  TAOS_RETURN(code);
×
2036
}
2037

2038
static int32_t mndProcessUpdateXnodeTaskReq(SRpcMsg *pReq) {
480✔
2039
  SMnode             *pMnode = pReq->info.node;
480✔
2040
  int32_t             code = -1;
480✔
2041
  SXnodeTaskObj       *pObj = NULL;
480✔
2042
  SMUpdateXnodeTaskReq updateReq = {0};
480✔
2043

2044
  code = mndValidateXnodePermissions(pMnode, pReq, MND_OPER_UPDATE_XNODE_TASK);
480✔
2045
  if (code != TSDB_CODE_SUCCESS) {
480✔
2046
    mError("failed check permission for update xnode task, code:%s", tstrerror(code));
×
UNCOV
2047
    goto _OVER;
×
2048
  }
2049

2050
  TAOS_CHECK_GOTO(tDeserializeSMUpdateXnodeTaskReq(pReq->pCont, pReq->contLen, &updateReq), NULL, _OVER);
480✔
2051

2052
  if (updateReq.tid > 0) {
480✔
2053
    pObj = mndAcquireXnodeTaskById(pMnode, updateReq.tid);
120✔
2054
  } else {
2055
    pObj = mndAcquireXnodeTaskByName(pMnode, updateReq.name.ptr);
360✔
2056
  }
2057
  if (pObj == NULL) {
480✔
2058
    code = terrno;
480✔
2059
    goto _OVER;
480✔
2060
  }
NEW
2061
  code = mndXnodeCheckTaskObjPrivilege(pMnode, pReq->info.conn.user, pObj, PRIV_CM_ALTER);
×
UNCOV
2062
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
2063
    mError("user:%s has no privilege on xnode task:%d", pReq->info.conn.user, pObj->id);
×
2064
    goto _OVER;
×
2065
  }
2066

2067
  if (updateReq.updateName.len > 0) {
×
UNCOV
2068
    SXnodeTaskObj *tmpObj = mndAcquireXnodeTaskByName(pMnode, updateReq.updateName.ptr);
×
2069
    if (tmpObj != NULL) {
×
UNCOV
2070
      mndReleaseXnodeTask(pMnode, tmpObj);
×
UNCOV
2071
      code = TSDB_CODE_MND_XNODE_NAME_DUPLICATE;
×
2072
      goto _OVER;
×
2073
    }
2074
  }
2075

2076
  code = mndUpdateXnodeTask(pMnode, pReq, pObj, &updateReq);
×
2077
  if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
×
2078

2079
_OVER:
480✔
2080
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
480✔
2081
    mError("xnode task:%d, failed to update since %s", updateReq.tid, tstrerror(code));
480✔
2082
  }
2083

2084
  mndReleaseXnodeTask(pMnode, pObj);
480✔
2085
  tFreeSMUpdateXnodeTaskReq(&updateReq);
480✔
2086
  TAOS_RETURN(code);
480✔
2087
  return 0;
2088
}
2089

2090
SXnodeTaskObj *mndAcquireXnodeTask(SMnode *pMnode, int32_t tid) {
×
2091
  SXnodeTaskObj *pObj = sdbAcquire(pMnode->pSdb, SDB_XNODE_TASK, &tid);
×
UNCOV
2092
  if (pObj == NULL && terrno == TSDB_CODE_SDB_OBJ_NOT_THERE) {
×
UNCOV
2093
    terrno = TSDB_CODE_MND_XNODE_TASK_NOT_EXIST;
×
2094
  }
2095
  return pObj;
×
2096
}
2097

2098
static int32_t mndSetDropXnodeTaskRedoLogs(STrans *pTrans, SXnodeTaskObj *pObj) {
×
2099
  int32_t  code = 0;
×
2100
  SSdbRaw *pRedoRaw = mndXnodeTaskActionEncode(pObj);
×
UNCOV
2101
  if (pRedoRaw == NULL) {
×
2102
    code = terrno;
×
2103
    return code;
×
2104
  }
2105

UNCOV
2106
  TAOS_CHECK_RETURN(mndTransAppendRedolog(pTrans, pRedoRaw));
×
2107
  TAOS_CHECK_RETURN(sdbSetRawStatus(pRedoRaw, SDB_STATUS_DROPPING));
×
2108

2109
  TAOS_RETURN(code);
×
2110
}
2111

2112
static int32_t mndSetDropXnodeTaskCommitLogs(STrans *pTrans, SXnodeTaskObj *pObj) {
×
2113
  int32_t  code = 0;
×
UNCOV
2114
  SSdbRaw *pCommitRaw = mndXnodeTaskActionEncode(pObj);
×
2115
  if (pCommitRaw == NULL) {
×
2116
    code = terrno;
×
UNCOV
2117
    return code;
×
2118
  }
2119

UNCOV
2120
  TAOS_CHECK_RETURN(mndTransAppendCommitlog(pTrans, pCommitRaw));
×
2121
  TAOS_CHECK_RETURN(sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED));
×
UNCOV
2122
  TAOS_RETURN(code);
×
2123
}
UNCOV
2124
static int32_t mndSetDropXnodeTaskInfoToTrans(SMnode *pMnode, STrans *pTrans, SXnodeTaskObj *pObj, bool force) {
×
2125
  if (pObj == NULL) {
×
2126
    return 0;
×
2127
  }
2128
  TAOS_CHECK_RETURN(mndSetDropXnodeTaskRedoLogs(pTrans, pObj));
×
2129
  TAOS_CHECK_RETURN(mndSetDropXnodeTaskCommitLogs(pTrans, pObj));
×
2130
  return 0;
×
2131
}
2132

2133
static int32_t mndDropXnodeTask(SMnode *pMnode, SRpcMsg *pReq, SXnodeTaskObj *pTask) {
×
2134
  int32_t code = 0;
×
UNCOV
2135
  int32_t lino = 0;
×
UNCOV
2136
  SArray *pArray = NULL;
×
2137

UNCOV
2138
  STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, pReq, "drop-xnode-task");
×
UNCOV
2139
  TSDB_CHECK_NULL(pTrans, code, lino, _OVER, terrno);
×
2140

UNCOV
2141
  mndTransSetSerial(pTrans);
×
UNCOV
2142
  mDebug("trans:%d, to drop xnode:%d", pTrans->id, pTask->id);
×
2143

UNCOV
2144
  code = mndSetDropXnodeTaskInfoToTrans(pMnode, pTrans, pTask, false);
×
UNCOV
2145
  mndReleaseXnodeTask(pMnode, pTask);
×
2146

2147
  TSDB_CHECK_CODE(code, lino, _OVER);
×
2148

UNCOV
2149
  code = mndTransPrepare(pMnode, pTrans);
×
2150

UNCOV
2151
_OVER:
×
UNCOV
2152
  if (pArray != NULL) {
×
2153
    for (int i = 0; i < pArray->size; i++) {
×
2154
      SXnodeJobObj *pJob = taosArrayGet(pArray, i);
×
UNCOV
2155
      if (pJob == NULL) continue;
×
UNCOV
2156
      mndReleaseXnodeJob(pMnode, pJob);
×
2157
    }
2158
  }
UNCOV
2159
  mndTransDrop(pTrans);
×
2160
  TAOS_RETURN(code);
×
2161
}
2162

2163
static int32_t mndProcessDropXnodeTaskReq(SRpcMsg *pReq) {
3,240✔
2164
  SMnode            *pMnode = pReq->info.node;
3,240✔
2165
  int32_t            code = -1;
3,240✔
2166
  SXnodeTaskObj     *pObj = NULL;
3,240✔
2167
  SMDropXnodeTaskReq dropReq = {0};
3,240✔
2168
  SJson             *pJson = NULL;
3,240✔
2169

2170
  code = mndValidateXnodePermissions(pMnode, pReq, MND_OPER_DROP_XNODE_TASK);
3,240✔
2171
  if (code != TSDB_CODE_SUCCESS) {
3,240✔
UNCOV
2172
    mError("failed check permission for drop xnode task, code:%s", tstrerror(code));
×
2173
    goto _OVER;
×
2174
  }
2175
  TAOS_CHECK_GOTO(tDeserializeSMDropXnodeTaskReq(pReq->pCont, pReq->contLen, &dropReq), NULL, _OVER);
3,240✔
2176
  mDebug("DropXnodeTask with tid:%d, start to drop", dropReq.id);
3,240✔
2177

2178
  if (dropReq.id <= 0 && (dropReq.name.len <= 0 || dropReq.name.ptr == NULL)) {
3,240✔
2179
    code = TSDB_CODE_MND_XNODE_INVALID_MSG;
×
UNCOV
2180
    goto _OVER;
×
2181
  }
2182

2183
  if (dropReq.name.len > 0 && dropReq.name.ptr != NULL) {
3,240✔
2184
    pObj = mndAcquireXnodeTaskByName(pMnode, dropReq.name.ptr);
3,240✔
2185
  } else {
UNCOV
2186
    pObj = mndAcquireXnodeTask(pMnode, dropReq.id);
×
2187
  }
2188
  if (pObj == NULL) {
3,240✔
2189
    code = terrno;
3,240✔
2190
    goto _OVER;
3,240✔
2191
  }
NEW
2192
  code = mndXnodeCheckTaskObjPrivilege(pMnode, pReq->info.conn.user, pObj, PRIV_CM_DROP);
×
UNCOV
2193
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
2194
    mError("user:%s has no privilege on xnode task:%d", pReq->info.conn.user, pObj->id);
×
UNCOV
2195
    goto _OVER;
×
2196
  }
2197

2198
  // send request to drop xnode task
UNCOV
2199
  char xnodeUrl[TSDB_XNODE_URL_LEN + 1] = {0};
×
UNCOV
2200
  snprintf(xnodeUrl, TSDB_XNODE_URL_LEN + 1, "%s/task/drop/%d", XNODED_PIPE_SOCKET_URL, pObj->id);
×
UNCOV
2201
  pJson = mndSendReqRetJson(xnodeUrl, HTTP_TYPE_DELETE, defaultTimeout, NULL, 0);
×
2202

UNCOV
2203
  code = mndDropXnodeTask(pMnode, pReq, pObj);
×
UNCOV
2204
  if (code == 0) {
×
UNCOV
2205
    code = TSDB_CODE_ACTION_IN_PROGRESS;
×
2206
  }
2207

2208
_OVER:
3,240✔
2209
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
3,240✔
2210
    mError("xnode task:%d, failed to drop since %s", dropReq.id, tstrerror(code));
3,240✔
2211
  }
2212
  if (pJson != NULL) {
3,240✔
2213
    tjsonDelete(pJson);
×
2214
  }
2215
  tFreeSMDropXnodeTaskReq(&dropReq);
3,240✔
2216
  TAOS_RETURN(code);
3,240✔
2217
}
2218
static int32_t mndRetrieveXnodeTasks(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
6,725✔
2219
  SMnode        *pMnode = pReq->info.node;
6,725✔
2220
  SSdb          *pSdb = pMnode->pSdb;
6,725✔
2221
  int32_t        numOfRows = 0;
6,725✔
2222
  int32_t        cols = 0;
6,725✔
2223
  SXnodeTaskObj *pObj = NULL;
6,725✔
UNCOV
2224
  char           buf[VARSTR_HEADER_SIZE +
×
2225
           TMAX(TSDB_XNODE_TASK_NAME_LEN,
6,725✔
2226
                          TMAX(TSDB_XNODE_TASK_SOURCE_LEN, TMAX(TSDB_XNODE_TASK_SINK_LEN, TSDB_XNODE_TASK_PARSER_LEN)))];
2227
  int32_t        code = 0;
6,725✔
2228
  SUserObj      *pOperUser = NULL;
6,725✔
2229
  mDebug("show.type:%d, %s:%d: retrieve xnode tasks with rows: %d", pShow->type, __FILE__, __LINE__, rows);
6,725✔
2230

2231
  TAOS_CHECK_GOTO(mndAcquireUser(pMnode, pReq->info.conn.user, &pOperUser), NULL, _end);
6,725✔
2232

2233
  while (numOfRows < rows) {
6,725✔
2234
    pShow->pIter = sdbFetch(pSdb, SDB_XNODE_TASK, pShow->pIter, (void **)&pObj);
6,725✔
2235
    if (pShow->pIter == NULL) break;
6,725✔
2236

2237
    if (!pOperUser->superUser) {
×
UNCOV
2238
      if (pObj->createdBy == NULL || pObj->createdByLen <= 0 ||
×
UNCOV
2239
          strncmp(pObj->createdBy, pReq->info.conn.user, TSDB_USER_LEN) != 0) {
×
2240

NEW
2241
        char taskIdStr[32] = {0};
×
NEW
2242
        snprintf(taskIdStr, sizeof(taskIdStr), "%d", pObj->id);
×
NEW
2243
        bool canShow = (0 == mndCheckObjPrivilegeRec(pMnode, pOperUser, PRIV_CM_SHOW,
×
NEW
2244
                 PRIV_OBJ_XTASK, 0, pOperUser->acctId, taskIdStr, NULL));
×
NEW
2245
        if (!canShow) {
×
NEW
2246
          sdbRelease(pSdb, pObj);
×
NEW
2247
          continue;
×
2248
        }
2249
      }
2250
    }
2251

UNCOV
2252
    cols = 0;
×
2253
    // id
2254
    SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
2255
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->id, false);
×
2256
    if (code != 0) goto _end;
×
2257

2258
    // name
UNCOV
2259
    buf[0] = 0;
×
UNCOV
2260
    STR_WITH_MAXSIZE_TO_VARSTR(buf, pObj->name, pShow->pMeta->pSchemas[cols].bytes);
×
2261
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
2262
    code = colDataSetVal(pColInfo, numOfRows, (const char *)buf, false);
×
2263
    if (code != 0) goto _end;
×
2264

2265
    // from
2266
    buf[0] = 0;
×
UNCOV
2267
    STR_WITH_MAXSIZE_TO_VARSTR(buf, pObj->sourceDsn, pShow->pMeta->pSchemas[cols].bytes);
×
2268
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
2269
    code = colDataSetVal(pColInfo, numOfRows, (const char *)buf, false);
×
UNCOV
2270
    if (code != 0) goto _end;
×
2271

2272
    // to
2273
    buf[0] = 0;
×
2274
    STR_WITH_MAXSIZE_TO_VARSTR(buf, pObj->sinkDsn, pShow->pMeta->pSchemas[cols].bytes);
×
2275
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
2276
    code = colDataSetVal(pColInfo, numOfRows, (const char *)buf, false);
×
UNCOV
2277
    if (code != 0) goto _end;
×
2278

2279
    // parser
UNCOV
2280
    if (pObj->parserLen > 0 && pObj->parser != NULL) {
×
UNCOV
2281
      buf[0] = 0;
×
UNCOV
2282
      STR_WITH_MAXSIZE_TO_VARSTR(buf, pObj->parser, pShow->pMeta->pSchemas[cols].bytes);
×
2283
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
2284
      code = colDataSetVal(pColInfo, numOfRows, (const char *)buf, false);
×
2285
      if (code != 0) goto _end;
×
2286
    } else {
UNCOV
2287
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
2288
      colDataSetNULL(pColInfo, numOfRows);
×
2289
    }
2290

2291
    // via
UNCOV
2292
    if (pObj->via != 0) {
×
2293
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
2294
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->via, false);
×
2295
      if (code != 0) goto _end;
×
2296
    } else {
2297
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
2298
      colDataSetNULL(pColInfo, numOfRows);
×
2299
    }
2300

2301
    // xnode_id
UNCOV
2302
    if (pObj->xnodeId != 0) {
×
UNCOV
2303
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
UNCOV
2304
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->xnodeId, false);
×
2305
      if (code != 0) goto _end;
×
2306
    } else {
2307
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
2308
      colDataSetNULL(pColInfo, numOfRows);
×
2309
    }
2310

2311
    // status
2312
    if (pObj->statusLen > 0) {
×
2313
      buf[0] = 0;
×
UNCOV
2314
      STR_WITH_MAXSIZE_TO_VARSTR(buf, pObj->status, pShow->pMeta->pSchemas[cols].bytes);
×
UNCOV
2315
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
UNCOV
2316
      code = colDataSetVal(pColInfo, numOfRows, (const char *)buf, false);
×
2317
      if (code != 0) goto _end;
×
2318
    } else {
2319
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
2320
      colDataSetNULL(pColInfo, numOfRows);
×
2321
    }
2322

2323
    // reason
2324
    if (pObj->reasonLen > 0) {
×
2325
      buf[0] = 0;
×
UNCOV
2326
      STR_WITH_MAXSIZE_TO_VARSTR(buf, pObj->reason, pShow->pMeta->pSchemas[cols].bytes);
×
UNCOV
2327
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
UNCOV
2328
      code = colDataSetVal(pColInfo, numOfRows, (const char *)buf, false);
×
2329
      if (code != 0) goto _end;
×
2330
    } else {
2331
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
2332
      colDataSetNULL(pColInfo, numOfRows);
×
2333
    }
2334

2335
    // create_by
2336
    if (pObj->createdByLen > 0) {
×
2337
      buf[0] = 0;
×
UNCOV
2338
      STR_WITH_MAXSIZE_TO_VARSTR(buf, pObj->createdBy, pShow->pMeta->pSchemas[cols].bytes);
×
UNCOV
2339
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
UNCOV
2340
      code = colDataSetVal(pColInfo, numOfRows, (const char *)buf, false);
×
2341
      if (code != 0) goto _end;
×
2342
    } else {
2343
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
UNCOV
2344
      colDataSetNULL(pColInfo, numOfRows);
×
2345
    }
2346

2347
    // labels
2348
    if (pObj->labelsLen > 0) {
×
UNCOV
2349
      buf[0] = 0;
×
2350
      STR_WITH_MAXSIZE_TO_VARSTR(buf, pObj->labels, pShow->pMeta->pSchemas[cols].bytes);
×
2351
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
UNCOV
2352
      code = colDataSetVal(pColInfo, numOfRows, (const char *)buf, false);
×
UNCOV
2353
      if (code != 0) goto _end;
×
2354
    } else {
UNCOV
2355
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
UNCOV
2356
      colDataSetNULL(pColInfo, numOfRows);
×
2357
    }
2358

2359
    // create_time
UNCOV
2360
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
UNCOV
2361
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->createTime, false);
×
2362
    if (code != 0) goto _end;
×
2363

2364
    // update_time
2365
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
UNCOV
2366
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->updateTime, false);
×
UNCOV
2367
    if (code != 0) goto _end;
×
2368

2369
    numOfRows++;
×
2370
    sdbRelease(pSdb, pObj);
×
2371
  }
2372

2373
_end:
6,725✔
2374
  if (code != 0 && pObj != NULL) sdbRelease(pSdb, pObj);
6,725✔
2375
  mndReleaseUser(pMnode, pOperUser);
6,725✔
2376

2377
  pShow->numOfRows += numOfRows;
6,725✔
2378
  return numOfRows;
6,725✔
2379
}
2380

2381
static void mndCancelGetNextXnodeTask(SMnode *pMnode, void *pIter) {
×
2382
  SSdb *pSdb = pMnode->pSdb;
×
2383
  sdbCancelFetchByType(pSdb, pIter, SDB_XNODE_TASK);
×
2384
}
×
2385

2386
/** xnode job section **/
2387

2388
static int32_t mndAcquireXnodeJobsByTaskId(SMnode *pMnode, int32_t tid, SArray **ppArray) {
×
2389
  int32_t code = 0;
×
2390
  SSdb   *pSdb = pMnode->pSdb;
×
2391

UNCOV
2392
  *ppArray = taosArrayInit(16, sizeof(SXnodeJobObj));
×
UNCOV
2393
  if (ppArray == NULL) {
×
UNCOV
2394
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2395
    if (terrno != 0) code = terrno;
×
UNCOV
2396
    goto _exit;
×
2397
  }
2398

2399
  int32_t idx = 0;
×
2400
  void   *pIter = NULL;
×
UNCOV
2401
  while (1) {
×
UNCOV
2402
    SXnodeJobObj *pJob = NULL;
×
UNCOV
2403
    pIter = sdbFetch(pSdb, SDB_XNODE_JOB, pIter, (void **)&pJob);
×
UNCOV
2404
    if (pIter == NULL) break;
×
2405

UNCOV
2406
    if (pJob->taskId == tid) {
×
UNCOV
2407
      if (NULL == taosArrayInsert(*ppArray, idx++, pJob)) {
×
UNCOV
2408
        code = terrno;
×
2409
        sdbRelease(pSdb, pJob);
×
2410
        goto _exit;
×
2411
      }
2412
    }
2413

UNCOV
2414
    sdbRelease(pSdb, pJob);
×
2415
  }
UNCOV
2416
  sdbCancelFetch(pSdb, pIter);
×
2417

UNCOV
2418
_exit:
×
2419
  TAOS_RETURN(code);
×
2420
}
2421

2422
static int32_t mndAcquireXnodeJobsAll(SMnode *pMnode, SArray **ppArray) {
20,400✔
2423
  int32_t code = 0;
20,400✔
2424
  SSdb   *pSdb = pMnode->pSdb;
20,400✔
2425

2426
  *ppArray = taosArrayInit(64, sizeof(SXnodeJobObj));
20,400✔
2427
  if (ppArray == NULL) {
20,400✔
UNCOV
2428
    code = terrno;
×
UNCOV
2429
    goto _exit;
×
2430
  }
2431

2432
  int32_t idx = 0;
20,400✔
2433
  void   *pIter = NULL;
20,400✔
UNCOV
2434
  while (1) {
×
2435
    SXnodeJobObj *pJob = NULL;
20,400✔
2436
    pIter = sdbFetch(pSdb, SDB_XNODE_JOB, pIter, (void **)&pJob);
20,400✔
2437
    if (pIter == NULL) break;
20,400✔
2438
    if (NULL == taosArrayInsert(*ppArray, idx++, pJob)) {
×
2439
      code = terrno;
×
UNCOV
2440
      goto _exit;
×
2441
    }
2442
    sdbRelease(pSdb, pJob);
×
2443
  }
2444
  sdbCancelFetch(pSdb, pIter);
20,400✔
2445

2446
_exit:
20,400✔
2447
  TAOS_RETURN(code);
20,400✔
2448
}
2449

UNCOV
2450
static void mndFreeXnodeJob(SXnodeJobObj *pObj) {
×
UNCOV
2451
  if (NULL == pObj) {
×
UNCOV
2452
    return;
×
2453
  }
UNCOV
2454
  if (NULL != pObj->config) {
×
UNCOV
2455
    taosMemoryFreeClear(pObj->config);
×
2456
  }
UNCOV
2457
  if (NULL != pObj->reason) {
×
UNCOV
2458
    taosMemoryFreeClear(pObj->reason);
×
2459
  }
UNCOV
2460
  if (NULL != pObj->status) {
×
UNCOV
2461
    taosMemoryFreeClear(pObj->status);
×
2462
  }
2463
}
2464

2465
SSdbRaw *mndXnodeJobActionEncode(SXnodeJobObj *pObj) {
585✔
2466
  int32_t code = 0;
585✔
2467
  int32_t lino = 0;
585✔
2468
  terrno = TSDB_CODE_OUT_OF_MEMORY;
585✔
2469

2470
  if (NULL == pObj) {
585✔
2471
    terrno = TSDB_CODE_INVALID_PARA;
195✔
2472
    return NULL;
195✔
2473
  }
2474

2475
  mDebug("xnode tid:%d, jid:%d, start to encode to raw, row:%p", pObj->taskId, pObj->id, pObj);
390✔
2476

2477
  int32_t rawDataLen =
390✔
2478
      sizeof(SXnodeJobObj) + TSDB_XNODE_RESERVE_SIZE + pObj->configLen + pObj->reasonLen + pObj->statusLen;
390✔
2479

2480
  SSdbRaw *pRaw = sdbAllocRaw(SDB_XNODE_JOB, TSDB_XNODE_VER_NUMBER, rawDataLen);
390✔
2481
  if (pRaw == NULL) goto _OVER;
390✔
2482

2483
  int32_t dataPos = 0;
390✔
2484
  SDB_SET_INT32(pRaw, dataPos, pObj->id, _OVER)
390✔
2485
  SDB_SET_INT32(pRaw, dataPos, pObj->taskId, _OVER)
390✔
2486
  SDB_SET_INT32(pRaw, dataPos, pObj->configLen, _OVER)
390✔
2487
  SDB_SET_BINARY(pRaw, dataPos, pObj->config, pObj->configLen, _OVER)
390✔
2488
  SDB_SET_INT32(pRaw, dataPos, pObj->via, _OVER)
390✔
2489
  SDB_SET_INT32(pRaw, dataPos, pObj->xnodeId, _OVER)
390✔
2490
  SDB_SET_INT32(pRaw, dataPos, pObj->statusLen, _OVER)
390✔
2491
  SDB_SET_BINARY(pRaw, dataPos, pObj->status, pObj->statusLen, _OVER)
390✔
2492
  SDB_SET_INT32(pRaw, dataPos, pObj->reasonLen, _OVER)
390✔
2493
  SDB_SET_BINARY(pRaw, dataPos, pObj->reason, pObj->reasonLen, _OVER)
390✔
2494
  SDB_SET_INT64(pRaw, dataPos, pObj->createTime, _OVER)
390✔
2495
  SDB_SET_INT64(pRaw, dataPos, pObj->updateTime, _OVER)
390✔
2496

2497
  SDB_SET_RESERVE(pRaw, dataPos, TSDB_XNODE_RESERVE_SIZE, _OVER)
390✔
2498

2499
  terrno = 0;
390✔
2500

2501
_OVER:
390✔
2502
  if (terrno != 0) {
390✔
UNCOV
2503
    mError("xnode tid:%d, jid:%d, failed to encode to raw:%p since %s", pObj->taskId, pObj->id, pRaw, terrstr());
×
UNCOV
2504
    sdbFreeRaw(pRaw);
×
UNCOV
2505
    return NULL;
×
2506
  }
2507

2508
  mTrace("xnode tid:%d, jid:%d, encode to raw:%p, row:%p", pObj->taskId, pObj->id, pRaw, pObj);
390✔
2509
  return pRaw;
390✔
2510
}
2511

2512
SSdbRow *mndXnodeJobActionDecode(SSdbRaw *pRaw) {
585✔
2513
  mInfo("xnode, start to decode from raw:%p", pRaw);
585✔
2514
  int32_t code = 0;
585✔
2515
  int32_t lino = 0;
585✔
2516
  terrno = TSDB_CODE_OUT_OF_MEMORY;
585✔
2517
  SSdbRow      *pRow = NULL;
585✔
2518
  SXnodeJobObj *pObj = NULL;
585✔
2519

2520
  if (NULL == pRaw) {
585✔
2521
    terrno = TSDB_CODE_INVALID_PARA;
195✔
2522
    return NULL;
195✔
2523
  }
2524

2525
  int8_t sver = 0;
390✔
2526
  if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto _OVER;
390✔
2527

2528
  if (sver != TSDB_XNODE_VER_NUMBER) {
390✔
UNCOV
2529
    terrno = TSDB_CODE_SDB_INVALID_DATA_VER;
×
UNCOV
2530
    goto _OVER;
×
2531
  }
2532

2533
  pRow = sdbAllocRow(sizeof(SXnodeJobObj));
390✔
2534
  if (pRow == NULL) goto _OVER;
390✔
2535

2536
  pObj = sdbGetRowObj(pRow);
390✔
2537
  if (pObj == NULL) goto _OVER;
390✔
2538

2539
  int32_t dataPos = 0;
390✔
2540
  SDB_GET_INT32(pRaw, dataPos, &pObj->id, _OVER)
390✔
2541
  SDB_GET_INT32(pRaw, dataPos, &pObj->taskId, _OVER)
390✔
2542

2543
  SDB_GET_INT32(pRaw, dataPos, &pObj->configLen, _OVER)
390✔
2544
  if (pObj->configLen > 0) {
390✔
2545
    pObj->config = taosMemoryCalloc(pObj->configLen, 1);
390✔
2546
    if (pObj->config == NULL) goto _OVER;
390✔
2547
    SDB_GET_BINARY(pRaw, dataPos, pObj->config, pObj->configLen, _OVER)
390✔
2548
  }
2549

2550
  SDB_GET_INT32(pRaw, dataPos, &pObj->via, _OVER)
390✔
2551
  SDB_GET_INT32(pRaw, dataPos, &pObj->xnodeId, _OVER)
390✔
2552
  SDB_GET_INT32(pRaw, dataPos, &pObj->statusLen, _OVER)
390✔
2553
  if (pObj->statusLen > 0) {
390✔
2554
    pObj->status = taosMemoryCalloc(pObj->statusLen, 1);
390✔
2555
    if (pObj->status == NULL) goto _OVER;
390✔
2556
    SDB_GET_BINARY(pRaw, dataPos, pObj->status, pObj->statusLen, _OVER)
390✔
2557
  }
2558

2559
  SDB_GET_INT32(pRaw, dataPos, &pObj->reasonLen, _OVER)
390✔
2560
  if (pObj->reasonLen > 0) {
390✔
2561
    pObj->reason = taosMemoryCalloc(pObj->reasonLen, 1);
195✔
2562
    if (pObj->reason == NULL) goto _OVER;
195✔
2563
    SDB_GET_BINARY(pRaw, dataPos, pObj->reason, pObj->reasonLen, _OVER)
195✔
2564
  }
2565

2566
  SDB_GET_INT64(pRaw, dataPos, &pObj->createTime, _OVER)
390✔
2567
  SDB_GET_INT64(pRaw, dataPos, &pObj->updateTime, _OVER)
390✔
2568

2569
  SDB_GET_RESERVE(pRaw, dataPos, TSDB_XNODE_RESERVE_SIZE, _OVER)
390✔
2570

2571
  terrno = 0;
390✔
2572

2573
_OVER:
390✔
2574
  if (terrno != 0) {
390✔
UNCOV
2575
    mError("xnode tid:%d, jid:%d, failed to decode from raw:%p since %s", pObj == NULL ? 0 : pObj->taskId,
×
2576
           pObj == NULL ? 0 : pObj->id, pRaw, terrstr());
2577
    if (pObj != NULL) {
×
2578
      taosMemoryFreeClear(pObj->config);
×
2579
      taosMemoryFreeClear(pObj->reason);
×
UNCOV
2580
      taosMemoryFreeClear(pObj->status);
×
2581
    }
2582
    taosMemoryFreeClear(pRow);
×
2583
    return NULL;
×
2584
  }
2585

2586
  mTrace("xnode:%d, decode from raw:%p, row:%p", pObj->id, pRaw, pObj);
390✔
2587
  return pRow;
390✔
2588
}
2589

2590
int32_t mndXnodeJobActionInsert(SSdb *pSdb, SXnodeJobObj *pObj) {
×
2591
  mInfo("xnode tid:%d, jid:%d, perform insert action, row:%p", pObj->taskId, pObj->id, pObj);
×
2592
  return 0;
×
2593
}
2594

2595
int32_t mndXnodeJobActionDelete(SSdb *pSdb, SXnodeJobObj *pObj) {
×
UNCOV
2596
  mDebug("xnode tid:%d, jid:%d, perform delete action, row:%p", pObj->taskId, pObj->id, pObj);
×
UNCOV
2597
  mndFreeXnodeJob(pObj);
×
UNCOV
2598
  return 0;
×
2599
}
2600

UNCOV
2601
int32_t mndXnodeJobActionUpdate(SSdb *pSdb, SXnodeJobObj *pOld, SXnodeJobObj *pNew) {
×
UNCOV
2602
  mDebug("xnode tid:%d, jid:%d, perform update action, old row:%p new row:%p", pOld->taskId, pOld->id, pOld, pNew);
×
2603

UNCOV
2604
  taosWLockLatch(&pOld->lock);
×
UNCOV
2605
  pOld->via = pNew->via;
×
UNCOV
2606
  pOld->xnodeId = pNew->xnodeId;
×
UNCOV
2607
  swapFields(&pNew->statusLen, &pNew->status, &pOld->statusLen, &pOld->status);
×
UNCOV
2608
  swapFields(&pNew->configLen, &pNew->config, &pOld->configLen, &pOld->config);
×
UNCOV
2609
  swapFields(&pNew->reasonLen, &pNew->reason, &pOld->reasonLen, &pOld->reason);
×
UNCOV
2610
  if (pNew->updateTime > pOld->updateTime) {
×
UNCOV
2611
    pOld->updateTime = pNew->updateTime;
×
2612
  }
UNCOV
2613
  taosWUnLockLatch(&pOld->lock);
×
UNCOV
2614
  return 0;
×
2615
}
2616

2617
/* xnode user pass actions */
2618
SSdbRaw *mndXnodeUserPassActionEncode(SXnodeUserPassObj *pObj) {
2,700✔
2619
  int32_t code = 0;
2,700✔
2620
  int32_t lino = 0;
2,700✔
2621
  terrno = TSDB_CODE_OUT_OF_MEMORY;
2,700✔
2622

2623
  if (NULL == pObj) {
2,700✔
2624
    terrno = TSDB_CODE_INVALID_PARA;
195✔
2625
    return NULL;
195✔
2626
  }
2627

2628
  int32_t rawDataLen =
2,505✔
2629
      sizeof(SXnodeUserPassObj) + TSDB_XNODE_RESERVE_SIZE + pObj->userLen + pObj->passLen + pObj->tokenLen;
2,505✔
2630

2631
  SSdbRaw *pRaw = sdbAllocRaw(SDB_XNODE_USER_PASS, TSDB_XNODE_VER_NUMBER, rawDataLen);
2,505✔
2632
  if (pRaw == NULL) goto _OVER;
2,505✔
2633

2634
  int32_t dataPos = 0;
2,505✔
2635
  SDB_SET_INT32(pRaw, dataPos, pObj->id, _OVER)
2,505✔
2636
  SDB_SET_INT32(pRaw, dataPos, pObj->userLen, _OVER)
2,505✔
2637
  SDB_SET_BINARY(pRaw, dataPos, pObj->user, pObj->userLen, _OVER)
2,505✔
2638
  SDB_SET_INT32(pRaw, dataPos, pObj->passLen, _OVER)
2,505✔
2639
  SDB_SET_BINARY(pRaw, dataPos, pObj->pass, pObj->passLen, _OVER)
2,505✔
2640
  SDB_SET_INT32(pRaw, dataPos, pObj->tokenLen, _OVER)
2,505✔
2641
  SDB_SET_BINARY(pRaw, dataPos, pObj->token, pObj->tokenLen, _OVER)
2,505✔
2642
  SDB_SET_INT64(pRaw, dataPos, pObj->createTime, _OVER)
2,505✔
2643
  SDB_SET_INT64(pRaw, dataPos, pObj->updateTime, _OVER)
2,505✔
2644

2645
  SDB_SET_RESERVE(pRaw, dataPos, TSDB_XNODE_RESERVE_SIZE, _OVER)
2,505✔
2646

2647
  terrno = 0;
2,505✔
2648

2649
_OVER:
2,505✔
2650
  if (terrno != 0) {
2,505✔
UNCOV
2651
    mError("xnode user pass:%d, failed to encode to raw:%p since %s", pObj->id, pRaw, terrstr());
×
UNCOV
2652
    sdbFreeRaw(pRaw);
×
UNCOV
2653
    return NULL;
×
2654
  }
2655

2656
  mTrace("xnode user pass:%d, encode to raw:%p, row:%p", pObj->id, pRaw, pObj);
2,505✔
2657
  return pRaw;
2,505✔
2658
}
2659
SSdbRow *mndXnodeUserPassActionDecode(SSdbRaw *pRaw) {
2,100✔
2660
  int32_t code = 0;
2,100✔
2661
  int32_t lino = 0;
2,100✔
2662
  terrno = TSDB_CODE_OUT_OF_MEMORY;
2,100✔
2663
  SSdbRow           *pRow = NULL;
2,100✔
2664
  SXnodeUserPassObj *pObj = NULL;
2,100✔
2665

2666
  if (NULL == pRaw) {
2,100✔
2667
    terrno = TSDB_CODE_INVALID_PARA;
195✔
2668
    return NULL;
195✔
2669
  }
2670

2671
  int8_t sver = 0;
1,905✔
2672
  if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto _OVER;
1,905✔
2673

2674
  if (sver != TSDB_XNODE_VER_NUMBER) {
1,905✔
UNCOV
2675
    terrno = TSDB_CODE_SDB_INVALID_DATA_VER;
×
UNCOV
2676
    goto _OVER;
×
2677
  }
2678

2679
  pRow = sdbAllocRow(sizeof(SXnodeUserPassObj));
1,905✔
2680
  if (pRow == NULL) goto _OVER;
1,905✔
2681

2682
  pObj = sdbGetRowObj(pRow);
1,905✔
2683
  if (pObj == NULL) goto _OVER;
1,905✔
2684

2685
  int32_t dataPos = 0;
1,905✔
2686
  SDB_GET_INT32(pRaw, dataPos, &pObj->id, _OVER)
1,905✔
2687
  SDB_GET_INT32(pRaw, dataPos, &pObj->userLen, _OVER)
1,905✔
2688
  if (pObj->userLen > 0) {
1,905✔
2689
    pObj->user = taosMemoryCalloc(1, pObj->userLen + 1);
1,230✔
2690
    if (pObj->user == NULL) goto _OVER;
1,230✔
2691
    SDB_GET_BINARY(pRaw, dataPos, pObj->user, pObj->userLen, _OVER)
1,230✔
2692
  }
2693
  SDB_GET_INT32(pRaw, dataPos, &pObj->passLen, _OVER)
1,905✔
2694
  if (pObj->passLen > 0) {
1,905✔
2695
    pObj->pass = taosMemoryCalloc(1, pObj->passLen + 1);
1,230✔
2696
    if (pObj->pass == NULL) goto _OVER;
1,230✔
2697
    SDB_GET_BINARY(pRaw, dataPos, pObj->pass, pObj->passLen, _OVER)
1,230✔
2698
  }
2699
  SDB_GET_INT32(pRaw, dataPos, &pObj->tokenLen, _OVER)
1,905✔
2700
  if (pObj->tokenLen > 0) {
1,905✔
2701
    pObj->token = taosMemoryCalloc(1, pObj->tokenLen + 1);
480✔
2702
    if (pObj->token == NULL) goto _OVER;
480✔
2703
    SDB_GET_BINARY(pRaw, dataPos, pObj->token, pObj->tokenLen, _OVER)
480✔
2704
  }
2705
  SDB_GET_INT64(pRaw, dataPos, &pObj->createTime, _OVER)
1,905✔
2706
  SDB_GET_INT64(pRaw, dataPos, &pObj->updateTime, _OVER)
1,905✔
2707

2708
  SDB_GET_RESERVE(pRaw, dataPos, TSDB_XNODE_RESERVE_SIZE, _OVER)
1,905✔
2709

2710
  terrno = 0;
1,905✔
2711

2712
_OVER:
1,905✔
2713
  if (terrno != 0) {
1,905✔
UNCOV
2714
    mError("xnode user pass:%d, failed to decode from raw:%p since %s", pObj == NULL ? 0 : pObj->id, pRaw, terrstr());
×
UNCOV
2715
    if (pObj != NULL) {
×
UNCOV
2716
      if (pObj->user != NULL) {
×
UNCOV
2717
        taosMemoryFreeClear(pObj->user);
×
2718
      }
UNCOV
2719
      if (pObj->pass != NULL) {
×
UNCOV
2720
        taosMemoryFreeClear(pObj->pass);
×
2721
      }
2722
    }
UNCOV
2723
    taosMemoryFreeClear(pRow);
×
UNCOV
2724
    return NULL;
×
2725
  }
2726

2727
  mTrace("xnode user pass:%d, decode from raw:%p, row:%p", pObj->id, pRaw, pObj);
1,905✔
2728
  return pRow;
1,905✔
2729
}
2730
int32_t mndXnodeUserPassActionInsert(SSdb *pSdb, SXnodeUserPassObj *pObj) {
360✔
2731
  mDebug("xnode user pass:%d, perform insert action, row:%p", pObj->id, pObj);
360✔
2732
  return 0;
360✔
2733
}
2734
int32_t mndXnodeUserPassActionUpdate(SSdb *pSdb, SXnodeUserPassObj *pOld, SXnodeUserPassObj *pNew) {
960✔
2735
  mDebug("xnode user pass:%d, perform update action, old row:%p new row:%p", pOld->id, pOld, pNew);
960✔
2736
  taosWLockLatch(&pOld->lock);
960✔
2737
  if (pNew->updateTime > pOld->updateTime) {
960✔
2738
    pOld->updateTime = pNew->updateTime;
720✔
2739
  }
2740
  char* tmp = NULL;
960✔
2741
  pOld->userLen = pNew->userLen;
960✔
2742
  tmp = pOld->user;
960✔
2743
  pOld->user = pNew->user;
960✔
2744
  pNew->user = tmp;
960✔
2745

2746
  pOld->passLen = pNew->passLen;
960✔
2747
  tmp = pOld->pass;
960✔
2748
  pOld->pass = pNew->pass;
960✔
2749
  pNew->pass = tmp;
960✔
2750

2751
  pOld->tokenLen = pNew->tokenLen;
960✔
2752
  tmp = pOld->token;
960✔
2753
  pOld->token = pNew->token;
960✔
2754
  pNew->token = tmp;
960✔
2755

2756
  // swapFields(&pNew->userLen, &pNew->user, &pOld->userLen, &pOld->user);
2757
  // swapFields(&pNew->passLen, &pNew->pass, &pOld->passLen, &pOld->pass);
2758
  // swapFields(&pNew->tokenLen, &pNew->token, &pOld->tokenLen, &pOld->token);
2759
  // SXnodeUserPassObj* tmp = pNew;
2760
  // pNew = pOld;
2761
  // pOld = tmp;
2762

2763
  taosWUnLockLatch(&pOld->lock);
960✔
2764
  return 0;
960✔
2765
}
2766
int32_t mndXnodeUserPassActionDelete(SSdb *pSdb, SXnodeUserPassObj *pObj) {
1,320✔
2767
  mDebug("xnode:%d, perform delete action, row:%p", pObj->id, pObj);
1,320✔
2768
  taosMemoryFreeClear(pObj->user);
1,320✔
2769
  taosMemoryFreeClear(pObj->pass);
1,320✔
2770
  taosMemoryFreeClear(pObj->token);
1,320✔
2771
  return 0;
1,320✔
2772
}
2773

2774
static int32_t mndSetCreateXnodeJobRedoLogs(STrans *pTrans, SXnodeJobObj *pObj) {
×
UNCOV
2775
  int32_t  code = 0;
×
2776
  SSdbRaw *pRedoRaw = mndXnodeJobActionEncode(pObj);
×
2777
  if (pRedoRaw == NULL) {
×
2778
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2779
    if (terrno != 0) code = terrno;
×
UNCOV
2780
    TAOS_RETURN(code);
×
2781
  }
2782
  TAOS_CHECK_RETURN(mndTransAppendRedolog(pTrans, pRedoRaw));
×
2783
  TAOS_CHECK_RETURN(sdbSetRawStatus(pRedoRaw, SDB_STATUS_CREATING));
×
2784
  TAOS_RETURN(code);
×
2785
}
2786

2787
static int32_t mndSetCreateXnodeJobUndoLogs(STrans *pTrans, SXnodeJobObj *pObj) {
×
UNCOV
2788
  int32_t  code = 0;
×
2789
  SSdbRaw *pUndoRaw = mndXnodeJobActionEncode(pObj);
×
2790
  if (pUndoRaw == NULL) {
×
2791
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2792
    if (terrno != 0) code = terrno;
×
UNCOV
2793
    TAOS_RETURN(code);
×
2794
  }
2795
  TAOS_CHECK_RETURN(mndTransAppendUndolog(pTrans, pUndoRaw));
×
2796
  TAOS_CHECK_RETURN(sdbSetRawStatus(pUndoRaw, SDB_STATUS_DROPPED));
×
UNCOV
2797
  TAOS_RETURN(code);
×
2798
}
2799

2800
static int32_t mndSetCreateXnodeJobCommitLogs(STrans *pTrans, SXnodeJobObj *pObj) {
×
UNCOV
2801
  int32_t  code = 0;
×
2802
  SSdbRaw *pCommitRaw = mndXnodeJobActionEncode(pObj);
×
2803
  if (pCommitRaw == NULL) {
×
2804
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
2805
    if (terrno != 0) code = terrno;
×
UNCOV
2806
    TAOS_RETURN(code);
×
2807
  }
2808
  TAOS_CHECK_RETURN(mndTransAppendCommitlog(pTrans, pCommitRaw));
×
2809
  TAOS_CHECK_RETURN(sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY));
×
UNCOV
2810
  TAOS_RETURN(code);
×
2811
}
2812

UNCOV
2813
static int32_t mndCreateXnodeJob(SMnode *pMnode, SRpcMsg *pReq, SMCreateXnodeJobReq *pCreate) {
×
2814
  int32_t code = -1;
×
2815
  STrans *pTrans = NULL;
×
2816

2817
  SXnodeJobObj jobObj = {0};
×
2818
  jobObj.id = sdbGetMaxId(pMnode->pSdb, SDB_XNODE_JOB);
×
UNCOV
2819
  jobObj.taskId = pCreate->tid;
×
2820

2821
  jobObj.configLen = pCreate->config.len + 1;
×
2822
  if (jobObj.configLen > TSDB_XNODE_TASK_JOB_CONFIG_LEN + 1) {
×
2823
    code = TSDB_CODE_MND_XNODE_TASK_JOB_CONFIG_TOO_LONG;
×
2824
    goto _OVER;
×
2825
  }
UNCOV
2826
  jobObj.config = taosMemoryCalloc(1, jobObj.configLen);
×
2827
  if (jobObj.config == NULL) goto _OVER;
×
2828
  (void)memcpy(jobObj.config, pCreate->config.ptr, pCreate->config.len);
×
2829

UNCOV
2830
  jobObj.via = pCreate->via;
×
UNCOV
2831
  jobObj.xnodeId = pCreate->xnodeId;
×
2832

2833
  if (pCreate->status.ptr != NULL) {
×
UNCOV
2834
    jobObj.statusLen = pCreate->status.len + 1;
×
2835
    jobObj.status = taosMemoryCalloc(1, jobObj.statusLen);
×
UNCOV
2836
    if (jobObj.status == NULL) goto _OVER;
×
UNCOV
2837
    (void)memmove(jobObj.status, pCreate->status.ptr, pCreate->status.len);
×
2838
  }
2839

2840
  if (jobObj.reason != NULL) {
×
2841
    jobObj.reasonLen = pCreate->reason.len + 1;
×
2842
    if (jobObj.reasonLen > TSDB_XNODE_TASK_REASON_LEN + 1) {
×
2843
      code = TSDB_CODE_MND_XNODE_TASK_REASON_TOO_LONG;
×
UNCOV
2844
      goto _OVER;
×
2845
    }
UNCOV
2846
    jobObj.reason = taosMemoryCalloc(1, jobObj.reasonLen);
×
2847
    if (jobObj.reason == NULL) goto _OVER;
×
UNCOV
2848
    (void)memcpy(jobObj.reason, pCreate->reason.ptr, pCreate->reason.len);
×
2849
  }
2850

2851
  jobObj.createTime = taosGetTimestampMs();
×
2852
  jobObj.updateTime = jobObj.createTime;
×
2853

2854
  mDebug("create xnode job, id:%d, tid:%d, config:%s, time:%" PRId64, jobObj.id, jobObj.taskId, jobObj.config,
×
2855
         jobObj.createTime);
2856

2857
  pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq, "create-xnode-job");
×
2858
  if (pTrans == NULL) {
×
2859
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
2860
    if (terrno != 0) code = terrno;
×
UNCOV
2861
    mInfo("failed to create transaction for xnode-job:%d, code:0x%x:%s", pCreate->tid, code, tstrerror(code));
×
2862
    goto _OVER;
×
2863
  }
2864
  mndTransSetSerial(pTrans);
×
2865

2866
  mInfo("trans:%d, used to create xnode job on %d as jid:%d", pTrans->id, pCreate->tid, jobObj.id);
×
2867

UNCOV
2868
  TAOS_CHECK_GOTO(mndSetCreateXnodeJobRedoLogs(pTrans, &jobObj), NULL, _OVER);
×
UNCOV
2869
  TAOS_CHECK_GOTO(mndSetCreateXnodeJobUndoLogs(pTrans, &jobObj), NULL, _OVER);
×
UNCOV
2870
  TAOS_CHECK_GOTO(mndSetCreateXnodeJobCommitLogs(pTrans, &jobObj), NULL, _OVER);
×
2871
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
×
2872

2873
  code = 0;
×
2874

2875
_OVER:
×
UNCOV
2876
  mndFreeXnodeJob(&jobObj);
×
2877
  mndTransDrop(pTrans);
×
2878
  TAOS_RETURN(code);
×
2879
}
2880

2881
static int32_t mndUpdateXnodeJob(SMnode *pMnode, SRpcMsg *pReq, SXnodeJobObj *pOld, SMUpdateXnodeJobReq *pUpdate) {
×
2882
  mInfo("xnode job:%d, start to update", pUpdate->jid);
×
2883
  int32_t      code = -1;
×
2884
  STrans      *pTrans = NULL;
×
2885
  SXnodeJobObj jobObj = *pOld;
×
2886
  struct {
2887
    bool status;
2888
    bool config;
2889
    bool reason;
2890
  } isChange = {0};
×
2891

2892
  jobObj.id = pUpdate->jid;
×
UNCOV
2893
  if (pUpdate->via > 0) {
×
2894
    jobObj.via = pUpdate->via;
×
2895
  }
2896
  if (pUpdate->xnodeId > 0) {
×
2897
    jobObj.xnodeId = pUpdate->xnodeId;
×
2898
  }
2899
  if (pUpdate->status.ptr != NULL) {
×
UNCOV
2900
    jobObj.statusLen = pUpdate->status.len + 1;
×
2901
    jobObj.status = taosMemoryCalloc(1, jobObj.statusLen);
×
UNCOV
2902
    if (jobObj.status == NULL) goto _OVER;
×
2903
    (void)memcpy(jobObj.status, pUpdate->status.ptr, pUpdate->status.len);
×
2904
    isChange.status = true;
×
2905
  }
2906
  if (pUpdate->config != NULL) {
×
UNCOV
2907
    jobObj.configLen = pUpdate->configLen + 1;
×
2908
    jobObj.config = taosMemoryCalloc(1, jobObj.configLen);
×
UNCOV
2909
    if (jobObj.config == NULL) goto _OVER;
×
2910
    (void)memcpy(jobObj.config, pUpdate->config, pUpdate->configLen);
×
2911
    isChange.config = true;
×
2912
  }
UNCOV
2913
  if (pUpdate->reason != NULL) {
×
2914
    jobObj.reasonLen = pUpdate->reasonLen + 1;
×
2915
    jobObj.reason = taosMemoryCalloc(1, jobObj.reasonLen);
×
2916
    if (jobObj.reason == NULL) goto _OVER;
×
UNCOV
2917
    (void)memcpy(jobObj.reason, pUpdate->reason, pUpdate->reasonLen);
×
2918
    isChange.reason = true;
×
2919
  }
UNCOV
2920
  jobObj.updateTime = taosGetTimestampMs();
×
2921

2922
  pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq, "update-xnode");
×
UNCOV
2923
  if (pTrans == NULL) {
×
2924
    code = terrno;
×
2925
    goto _OVER;
×
2926
  }
UNCOV
2927
  mInfo("trans:%d, used to update xnode job:%d", pTrans->id, jobObj.id);
×
2928

2929
  TAOS_CHECK_GOTO(mndSetCreateXnodeJobCommitLogs(pTrans, &jobObj), NULL, _OVER);
×
2930
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
×
2931
  code = 0;
×
2932

UNCOV
2933
_OVER:
×
UNCOV
2934
  if (NULL != jobObj.status && isChange.status) {
×
UNCOV
2935
    taosMemoryFree(jobObj.status);
×
2936
  }
UNCOV
2937
  if (NULL != jobObj.config && isChange.config) {
×
UNCOV
2938
    taosMemoryFree(jobObj.config);
×
2939
  }
UNCOV
2940
  if (NULL != jobObj.reason && isChange.reason) {
×
UNCOV
2941
    taosMemoryFree(jobObj.reason);
×
2942
  }
UNCOV
2943
  mndTransDrop(pTrans);
×
UNCOV
2944
  TAOS_RETURN(code);
×
2945
}
2946

2947
void mndReleaseXnodeTaskJob(SMnode *pMnode, SXnodeJobObj *pObj) {
×
2948
  SSdb *pSdb = pMnode->pSdb;
×
2949
  sdbRelease(pSdb, pObj);
×
2950
}
×
2951

2952
SXnodeJobObj *mndAcquireXnodeJob(SMnode *pMnode, int32_t jid) {
360✔
2953
  SXnodeJobObj *pObj = sdbAcquire(pMnode->pSdb, SDB_XNODE_JOB, &jid);
360✔
2954
  if (pObj == NULL && terrno == TSDB_CODE_SDB_OBJ_NOT_THERE) {
360✔
2955
    terrno = TSDB_CODE_MND_XNODE_JOB_NOT_EXIST;
360✔
2956
  }
2957
  return pObj;
360✔
2958
}
2959
void mndReleaseXnodeJob(SMnode *pMnode, SXnodeJobObj *pObj) {
360✔
2960
  SSdb *pSdb = pMnode->pSdb;
360✔
2961
  sdbRelease(pSdb, pObj);
360✔
2962
}
360✔
2963

2964
static int32_t mndSetDropXnodeJobRedoLogs(STrans *pTrans, SXnodeJobObj *pObj) {
×
UNCOV
2965
  int32_t  code = 0;
×
UNCOV
2966
  SSdbRaw *pRedoRaw = mndXnodeJobActionEncode(pObj);
×
2967
  if (pRedoRaw == NULL) {
×
2968
    code = terrno;
×
2969
    return code;
×
2970
  }
2971

2972
  TAOS_CHECK_RETURN(mndTransAppendRedolog(pTrans, pRedoRaw));
×
2973
  TAOS_CHECK_RETURN(sdbSetRawStatus(pRedoRaw, SDB_STATUS_DROPPING));
×
2974

2975
  return code;
×
2976
}
2977

UNCOV
2978
static int32_t mndSetDropXnodeJobCommitLogs(STrans *pTrans, SXnodeJobObj *pObj) {
×
UNCOV
2979
  int32_t  code = 0;
×
2980
  SSdbRaw *pCommitRaw = mndXnodeJobActionEncode(pObj);
×
2981
  if (pCommitRaw == NULL) {
×
2982
    code = terrno;
×
UNCOV
2983
    return code;
×
2984
  }
2985

UNCOV
2986
  TAOS_CHECK_RETURN(mndTransAppendCommitlog(pTrans, pCommitRaw));
×
2987
  TAOS_CHECK_RETURN(sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED));
×
2988
  TAOS_RETURN(code);
×
2989
}
2990
static int32_t mndSetDropXnodeJobInfoToTrans(STrans *pTrans, SXnodeJobObj *pObj, bool force) {
×
UNCOV
2991
  if (pObj == NULL) {
×
2992
    return 0;
×
2993
  }
2994
  TAOS_CHECK_RETURN(mndSetDropXnodeJobRedoLogs(pTrans, pObj));
×
UNCOV
2995
  TAOS_CHECK_RETURN(mndSetDropXnodeJobCommitLogs(pTrans, pObj));
×
2996
  return 0;
×
2997
}
2998

UNCOV
2999
static int32_t mndDropXnodeJob(SMnode *pMnode, SRpcMsg *pReq, SXnodeJobObj *pObj) {
×
UNCOV
3000
  int32_t code = 0;
×
UNCOV
3001
  int32_t lino = 0;
×
3002

UNCOV
3003
  STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, pReq, "drop-xnode-job");
×
UNCOV
3004
  TSDB_CHECK_NULL(pTrans, code, lino, _OVER, terrno);
×
3005

UNCOV
3006
  mndTransSetSerial(pTrans);
×
UNCOV
3007
  mInfo("trans:%d, to drop xnode:%d", pTrans->id, pObj->id);
×
3008

3009
  code = mndSetDropXnodeJobInfoToTrans(pTrans, pObj, false);
×
3010

UNCOV
3011
  TSDB_CHECK_CODE(code, lino, _OVER);
×
3012

UNCOV
3013
  code = mndTransPrepare(pMnode, pTrans);
×
3014

UNCOV
3015
_OVER:
×
UNCOV
3016
  mndTransDrop(pTrans);
×
UNCOV
3017
  return code;
×
3018
}
3019
static int32_t mndProcessCreateXnodeJobReq(SRpcMsg *pReq) {
10,440✔
3020
  mDebug("create xnode job req, content len:%d", pReq->contLen);
10,440✔
3021
  SMnode             *pMnode = pReq->info.node;
10,440✔
3022
  int32_t             code = -1;
10,440✔
3023
  SMCreateXnodeJobReq createReq = {0};
10,440✔
3024
  SXnodeTaskObj      *pTaskObj = NULL;
10,440✔
3025

3026
  code = mndValidateXnodePermissions(pMnode, pReq, MND_OPER_CREATE_XNODE_JOB);
10,440✔
3027
  if (code != TSDB_CODE_SUCCESS) {
10,440✔
3028
    mError("failed check permission for create xnode job, code:%s", tstrerror(code));
×
3029
    goto _OVER;
×
3030
  }
3031
  TAOS_CHECK_GOTO(tDeserializeSMCreateXnodeJobReq(pReq->pCont, pReq->contLen, &createReq), NULL, _OVER);
10,440✔
3032
  mDebug("xnode create job on xnode:%d", createReq.xnodeId);
10,440✔
3033

3034
  // task must exists
3035
  pTaskObj = mndAcquireXnodeTaskById(pMnode, createReq.tid);
10,440✔
3036
  if (pTaskObj == NULL) {
10,440✔
3037
    code = TSDB_CODE_MND_XNODE_TASK_NOT_EXIST;
10,440✔
3038
    goto _OVER;
10,440✔
3039
  }
3040
  // check task privilege
NEW
3041
  code = mndXnodeCheckTaskObjPrivilege(pMnode, pReq->info.conn.user, pTaskObj, PRIV_CM_ALTER);
×
UNCOV
3042
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
3043
    mError("user:%s has no privilege on xnode task:%d", pReq->info.conn.user, pTaskObj->id);
×
UNCOV
3044
    goto _OVER;
×
3045
  }
3046

UNCOV
3047
  code = mndCreateXnodeJob(pMnode, pReq, &createReq);
×
UNCOV
3048
  if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
×
3049

3050
_OVER:
10,440✔
3051
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
10,440✔
3052
    mError("xnode task job on task id:%d, failed to create since %s", createReq.tid, tstrerror(code));
10,440✔
3053
  }
3054

3055
  mndReleaseXnodeTask(pMnode, pTaskObj);
10,440✔
3056
  tFreeSMCreateXnodeJobReq(&createReq);
10,440✔
3057
  TAOS_RETURN(code);
10,440✔
3058
}
3059

3060
static int32_t mndProcessUpdateXnodeJobReq(SRpcMsg *pReq) {
120✔
3061
  SMnode             *pMnode = pReq->info.node;
120✔
3062
  int32_t             code = -1;
120✔
3063
  SXnodeJobObj       *pObj = NULL;
120✔
3064
  SXnodeTaskObj      *pTaskObj = NULL;
120✔
3065
  SMUpdateXnodeJobReq updateReq = {0};
120✔
3066

3067
  code = mndValidateXnodePermissions(pMnode, pReq, MND_OPER_UPDATE_XNODE_JOB);
120✔
3068
  if (code != TSDB_CODE_SUCCESS) {
120✔
UNCOV
3069
    mError("failed check permission for update xnode job, code:%s", tstrerror(code));
×
3070
    goto _OVER;
×
3071
  }
3072
  TAOS_CHECK_GOTO(tDeserializeSMUpdateXnodeJobReq(pReq->pCont, pReq->contLen, &updateReq), NULL, _OVER);
120✔
3073

3074
  pObj = mndAcquireXnodeJob(pMnode, updateReq.jid);
120✔
3075
  if (pObj == NULL) {
120✔
3076
    code = terrno;
120✔
3077
    goto _OVER;
120✔
3078
  }
NEW
3079
  pTaskObj = mndAcquireXnodeTaskById(pMnode, pObj->taskId);
×
NEW
3080
  if (pTaskObj != NULL) {
×
NEW
3081
    code = mndXnodeCheckTaskObjPrivilege(pMnode, pReq->info.conn.user, pTaskObj, PRIV_CM_ALTER);
×
NEW
3082
    if (code != TSDB_CODE_SUCCESS) {
×
NEW
3083
      mError("user:%s has no privilege on xnode task:%d", pReq->info.conn.user, pTaskObj->id);
×
NEW
3084
      goto _OVER;
×
3085
    }
3086
  }
3087

UNCOV
3088
  code = mndUpdateXnodeJob(pMnode, pReq, pObj, &updateReq);
×
UNCOV
3089
  if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
×
3090

3091
_OVER:
120✔
3092
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
120✔
3093
    mError("xnode task job on jid:%d, failed to update since %s", updateReq.jid, tstrerror(code));
120✔
3094
  }
3095
  mndReleaseXnodeTask(pMnode, pTaskObj);
120✔
3096
  mndReleaseXnodeJob(pMnode, pObj);
120✔
3097
  tFreeSMUpdateXnodeJobReq(&updateReq);
120✔
3098
  TAOS_RETURN(code);
120✔
3099

3100
  return 0;
3101
}
3102

3103
static int32_t mndProcessRebalanceXnodeJobReq(SRpcMsg *pReq) {
240✔
3104
  SMnode                *pMnode = pReq->info.node;
240✔
3105
  int32_t                code = -1;
240✔
3106
  SXnodeJobObj          *pObj = NULL;
240✔
3107
  SXnodeTaskObj         *pTaskObj      = NULL;
240✔
3108
  SMRebalanceXnodeJobReq rebalanceReq = {0};
240✔
3109
  SJson                 *pJson = NULL;
240✔
3110

3111
  code = mndValidateXnodePermissions(pMnode, pReq, MND_OPER_REBALANCE_XNODE_JOB);
240✔
3112
  if (code != TSDB_CODE_SUCCESS) {
240✔
UNCOV
3113
    mError("failed check permission for rebalance xnode job, code:%s", tstrerror(code));
×
UNCOV
3114
    goto _OVER;
×
3115
  }
3116
  TAOS_CHECK_GOTO(tDeserializeSMRebalanceXnodeJobReq(pReq->pCont, pReq->contLen, &rebalanceReq), NULL, _OVER);
240✔
3117
  mDebug("RebalanceXnodeJob with jid:%d, xnode_id:%d, start to rebalance", rebalanceReq.jid, rebalanceReq.xnodeId);
240✔
3118

3119
  if (rebalanceReq.jid <= 0) {
240✔
3120
    code = TSDB_CODE_INVALID_MSG;
×
UNCOV
3121
    goto _OVER;
×
3122
  }
3123

3124
  pObj = mndAcquireXnodeJob(pMnode, rebalanceReq.jid);
240✔
3125
  if (pObj == NULL) {
240✔
3126
    code = terrno;
240✔
3127
    goto _OVER;
240✔
3128
  }
NEW
3129
  pTaskObj = mndAcquireXnodeTaskById(pMnode, pObj->taskId);
×
NEW
3130
  if (pTaskObj != NULL) {
×
NEW
3131
    code = mndXnodeCheckTaskObjPrivilege(pMnode, pReq->info.conn.user, pTaskObj, PRIV_CM_ALTER);
×
NEW
3132
    if (code != TSDB_CODE_SUCCESS) {
×
NEW
3133
      mError("user:%s has no privilege on xnode task:%d", pReq->info.conn.user, pTaskObj->id);
×
NEW
3134
      goto _OVER;
×
3135
    }
3136
  }
3137

3138
  // send request
UNCOV
3139
  char xnodeUrl[TSDB_XNODE_URL_LEN + 1] = {0};
×
UNCOV
3140
  snprintf(xnodeUrl, TSDB_XNODE_URL_LEN + 1, "%s/rebalance/manual/%d/%d/%d", XNODED_PIPE_SOCKET_URL, pObj->taskId, pObj->id,
×
3141
           rebalanceReq.xnodeId);
UNCOV
3142
  pJson = mndSendReqRetJson(xnodeUrl, HTTP_TYPE_POST, defaultTimeout, NULL, 0);
×
3143

3144
_OVER:
240✔
3145
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
240✔
3146
    mError("xnode:%d, failed to rebalance xnode job since %s", rebalanceReq.jid, tstrerror(code));
240✔
3147
  }
3148
  if (pJson != NULL) {
240✔
UNCOV
3149
    tjsonDelete(pJson);
×
3150
  }
3151
  mndReleaseXnodeJob(pMnode, pObj);
240✔
3152
  mndReleaseXnodeTask(pMnode, pTaskObj);
240✔
3153
  tFreeSMRebalanceXnodeJobReq(&rebalanceReq);
240✔
3154
  TAOS_RETURN(code);
240✔
3155
}
3156

3157
typedef struct {
3158
  SValueNode nd;
3159
  bool       shouldFree;
3160
} SXndRefValueNode;
3161

UNCOV
3162
static void freeSXndRefValueNode(void *pNode) {
×
UNCOV
3163
  if (pNode == NULL) return;
×
3164

UNCOV
3165
  SXndRefValueNode *pRefNode = (SXndRefValueNode *)pNode;
×
UNCOV
3166
  if (pRefNode->shouldFree) {
×
3167
    taosMemoryFreeClear(pRefNode->nd.datum.p);
×
3168
  }
3169
}
3170

3171
typedef struct {
3172
  SArray   *stack;
3173
  SHashObj *pMap;
3174
  int32_t   code;
3175
} SXndWhereContext;
3176

3177
void freeSXndWhereContext(SXndWhereContext *pCtx) {
×
3178
  if (pCtx == NULL) return;
×
3179

UNCOV
3180
  if (pCtx->pMap != NULL) {
×
3181
    taosHashCleanup(pCtx->pMap);
×
3182
    pCtx->pMap = NULL;
×
3183
  }
UNCOV
3184
  if (pCtx->stack != NULL) {
×
UNCOV
3185
    for (int32_t i = 0; i < pCtx->stack->size; i++) {
×
3186
      SXndRefValueNode *pRefNode = (SXndRefValueNode *)taosArrayGet(pCtx->stack, i);
×
3187
      if (pRefNode != NULL) {
×
3188
        freeSXndRefValueNode(pRefNode);
×
3189
      }
3190
    }
3191
    taosArrayDestroy(pCtx->stack);
×
UNCOV
3192
    pCtx->stack = NULL;
×
3193
  }
3194
}
3195

3196
static SHashObj *convertJob2Map(const SXnodeJobObj *pJob) {
×
3197
  SHashObj *pMap = taosHashInit(256, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK);
×
3198
  if (pMap == NULL) {
×
3199
    return NULL;
×
3200
  }
UNCOV
3201
  taosHashSetFreeFp(pMap, freeSXndRefValueNode);
×
3202
  // id
3203
  SXndRefValueNode id = {0};
×
3204
  id.nd.node.type = QUERY_NODE_VALUE;
×
3205
  id.nd.node.resType.type = TSDB_DATA_TYPE_UBIGINT;
×
3206
  id.nd.datum.u = pJob->id;
×
3207
  int32_t code = taosHashPut(pMap, "id", strlen("id") + 1, &id, sizeof(SXndRefValueNode));
×
3208
  if (code != 0) {
×
UNCOV
3209
    taosHashCleanup(pMap);
×
3210
    return NULL;
×
3211
  }
3212
  // task id
3213
  SXndRefValueNode taskId = {0};
×
UNCOV
3214
  taskId.nd.node.type = QUERY_NODE_VALUE;
×
UNCOV
3215
  taskId.nd.node.resType.type = TSDB_DATA_TYPE_UBIGINT;
×
3216
  taskId.nd.datum.u = pJob->taskId;
×
3217
  if (pJob->taskId == 0) {
×
3218
    taskId.nd.isNull = true;
×
3219
  }
3220
  code = taosHashPut(pMap, "task_id", strlen("task_id") + 1, &taskId, sizeof(SXndRefValueNode));
×
3221
  if (code != 0) {
×
UNCOV
3222
    taosHashCleanup(pMap);
×
3223
    return NULL;
×
3224
  }
3225
  // via
3226
  SXndRefValueNode via = {0};
×
UNCOV
3227
  via.nd.node.type = QUERY_NODE_VALUE;
×
UNCOV
3228
  via.nd.node.resType.type = TSDB_DATA_TYPE_UBIGINT;
×
3229
  via.nd.datum.u = pJob->via;
×
3230
  if (pJob->via == 0) {
×
3231
    via.nd.isNull = true;
×
3232
  }
3233
  code = taosHashPut(pMap, "via", strlen("via") + 1, &via, sizeof(SXndRefValueNode));
×
3234
  if (code != 0) {
×
UNCOV
3235
    taosHashCleanup(pMap);
×
3236
    return NULL;
×
3237
  }
3238
  // xnode id
3239
  SXndRefValueNode xnodeId = {0};
×
UNCOV
3240
  xnodeId.nd.node.type = QUERY_NODE_VALUE;
×
UNCOV
3241
  xnodeId.nd.node.resType.type = TSDB_DATA_TYPE_UBIGINT;
×
3242
  xnodeId.nd.datum.u = pJob->xnodeId;
×
3243
  if (pJob->xnodeId == 0) {
×
3244
    xnodeId.nd.isNull = true;
×
3245
  }
3246
  code = taosHashPut(pMap, "xnode_id", strlen("xnode_id") + 1, &xnodeId, sizeof(SXndRefValueNode));
×
3247
  if (code != 0) {
×
3248
    taosHashCleanup(pMap);
×
UNCOV
3249
    return NULL;
×
3250
  }
3251
  // config
3252
  SXndRefValueNode config = {0};
×
3253
  config.nd.node.type = QUERY_NODE_VALUE;
×
UNCOV
3254
  if (pJob->configLen > 0) {
×
3255
    config.nd.node.resType.type = TSDB_DATA_TYPE_BINARY;
×
3256
    config.nd.datum.p = taosStrndupi(pJob->config, strlen(pJob->config) + 1);
×
3257
    config.shouldFree = true;
×
UNCOV
3258
    code = taosHashPut(pMap, "config", strlen("config") + 1, &config, sizeof(SXndRefValueNode));
×
3259
  } else {
3260
    config.nd.node.resType.type = TSDB_DATA_TYPE_BINARY;
×
3261
    config.nd.datum.p = NULL;
×
3262
    config.nd.isNull = true;
×
3263
    code = taosHashPut(pMap, "config", strlen("config") + 1, &config, sizeof(SXndRefValueNode));
×
3264
  }
3265
  if (code != 0) {
×
3266
    taosHashCleanup(pMap);
×
UNCOV
3267
    return NULL;
×
3268
  }
3269
  // status
3270
  SXndRefValueNode status = {0};
×
3271
  status.nd.node.type = QUERY_NODE_VALUE;
×
UNCOV
3272
  if (pJob->statusLen > 0) {
×
3273
    status.nd.node.resType.type = TSDB_DATA_TYPE_BINARY;
×
3274
    status.nd.datum.p = taosStrndupi(pJob->status, strlen(pJob->status) + 1);
×
3275
    status.shouldFree = true;
×
UNCOV
3276
    code = taosHashPut(pMap, "status", strlen("status") + 1, &status, sizeof(SXndRefValueNode));
×
3277
  } else {
3278
    status.nd.node.resType.type = TSDB_DATA_TYPE_BINARY;
×
3279
    status.nd.datum.p = NULL;
×
3280
    status.nd.isNull = true;
×
3281
    code = taosHashPut(pMap, "status", strlen("status") + 1, &status, sizeof(SXndRefValueNode));
×
3282
  }
3283
  if (code != 0) {
×
3284
    taosHashCleanup(pMap);
×
UNCOV
3285
    return NULL;
×
3286
  }
3287
  // reason
3288
  SXndRefValueNode reason = {0};
×
3289
  reason.nd.node.type = QUERY_NODE_VALUE;
×
UNCOV
3290
  if (pJob->reasonLen > 0) {
×
3291
    reason.nd.node.resType.type = TSDB_DATA_TYPE_BINARY;
×
3292
    reason.nd.datum.p = taosStrndupi(pJob->reason, strlen(pJob->reason) + 1);
×
3293
    reason.shouldFree = true;
×
UNCOV
3294
    code = taosHashPut(pMap, "reason", strlen("reason") + 1, &reason, sizeof(SXndRefValueNode));
×
3295
  } else {
3296
    reason.nd.node.resType.type = TSDB_DATA_TYPE_BINARY;
×
3297
    reason.nd.datum.p = NULL;
×
3298
    reason.nd.isNull = true;
×
3299
    code = taosHashPut(pMap, "reason", strlen("reason") + 1, &reason, sizeof(SXndRefValueNode));
×
3300
  }
3301
  if (code != 0) {
×
3302
    taosHashCleanup(pMap);
×
3303
    return NULL;
×
3304
  }
3305
  // create time
3306
  SXndRefValueNode createTime = {0};
×
UNCOV
3307
  createTime.nd.node.type = QUERY_NODE_VALUE;
×
UNCOV
3308
  createTime.nd.node.resType.type = TSDB_DATA_TYPE_BINARY;
×
3309
  createTime.nd.datum.p = taosMemoryCalloc(1, TD_TIME_STR_LEN);
×
3310
  createTime.nd.datum.p =
×
3311
      formatTimestampLocal(createTime.nd.datum.p, TD_TIME_STR_LEN, pJob->createTime, TSDB_TIME_PRECISION_MILLI);
×
3312
  createTime.shouldFree = true;
×
3313
  code = taosHashPut(pMap, "create_time", strlen("create_time") + 1, &createTime, sizeof(SXndRefValueNode));
×
3314
  if (code != 0) {
×
3315
    taosHashCleanup(pMap);
×
3316
    return NULL;
×
3317
  }
3318
  // update time
UNCOV
3319
  SXndRefValueNode updateTime = {0};
×
UNCOV
3320
  updateTime.nd.node.type = QUERY_NODE_VALUE;
×
UNCOV
3321
  updateTime.nd.node.resType.type = TSDB_DATA_TYPE_BINARY;
×
UNCOV
3322
  updateTime.nd.datum.p = taosMemoryCalloc(1, TD_TIME_STR_LEN);
×
UNCOV
3323
  updateTime.nd.datum.p =
×
UNCOV
3324
      formatTimestampLocal(updateTime.nd.datum.p, TD_TIME_STR_LEN, pJob->updateTime, TSDB_TIME_PRECISION_MILLI);
×
UNCOV
3325
  updateTime.shouldFree = true;
×
UNCOV
3326
  code = taosHashPut(pMap, "update_time", strlen("update_time") + 1, &updateTime, sizeof(SXndRefValueNode));
×
UNCOV
3327
  return pMap;
×
3328
}
3329

3330
typedef bool (*FOpCmp)(SValueNode *pval1, SValueNode *pval2);
3331

3332
#define XNODE_DEF_OP_FUNC(NAME, OP)                             \
3333
  static bool NAME(SValueNode *pval1, SValueNode *pval2) {      \
3334
    switch (pval1->node.resType.type) {                         \
3335
      case TSDB_DATA_TYPE_BOOL:                                 \
3336
        return pval1->datum.b OP pval2->datum.b;                \
3337
      case TSDB_DATA_TYPE_UBIGINT:                              \
3338
        return pval1->datum.u OP pval2->datum.u;                \
3339
      case TSDB_DATA_TYPE_BIGINT:                               \
3340
        return pval1->datum.i OP pval2->datum.i;                \
3341
      case TSDB_DATA_TYPE_FLOAT:                                \
3342
        return pval1->datum.d OP pval2->datum.d;                \
3343
      case TSDB_DATA_TYPE_BINARY: {                             \
3344
        if (pval1->datum.p == NULL || pval2->datum.p == NULL) { \
3345
          return pval1->datum.p OP pval2->datum.p;              \
3346
        }                                                       \
3347
        return strcmp(pval1->datum.p, pval2->datum.p) OP 0;     \
3348
      }                                                         \
3349
      default:                                                  \
3350
        return false;                                           \
3351
    }                                                           \
3352
  }
3353

3354
XNODE_DEF_OP_FUNC(op_greater_than, >)
×
3355
XNODE_DEF_OP_FUNC(op_greater_equal, >=)
×
UNCOV
3356
XNODE_DEF_OP_FUNC(op_lower_than, <)
×
3357
XNODE_DEF_OP_FUNC(op_lower_equal, <=)
×
3358
XNODE_DEF_OP_FUNC(op_equal, ==)
×
3359
XNODE_DEF_OP_FUNC(op_not_equal, !=)
×
3360

UNCOV
3361
static int32_t call_op_cmp(SXndWhereContext *pctx, FOpCmp opFn) {
×
3362
  int32_t     code = 0;
×
UNCOV
3363
  SValueNode *pval2 = (SValueNode *)taosArrayPop(pctx->stack);
×
UNCOV
3364
  SValueNode *pval1 = (SValueNode *)taosArrayPop(pctx->stack);
×
3365
  bool        ret = false;
×
3366

3367
  if (pval1->node.type != pval2->node.type) {
×
3368
    code = TSDB_CODE_MND_XNODE_WHERE_COL_TYPE_DIFF;
×
3369
    mError("xnode type not same, v1 type: %d, v2 type: %d", pval1->node.type, pval2->node.type);
×
3370
    goto _OVER;
×
3371
  } else {
3372
    mDebug("xnode type v1:%d, is null: %d, UB: %" PRIu64 ", v2 type: %d, is null: %d, UB: %" PRIu64, pval1->node.type,
×
3373
           pval1->isNull, pval1->datum.u, pval2->node.type, pval2->isNull, pval2->datum.u);
3374

UNCOV
3375
    ret = (*opFn)(pval1, pval2);
×
3376
  }
3377
  SXndRefValueNode pval = {0};
×
3378
  pval.nd.node.type = QUERY_NODE_VALUE;
×
3379
  pval.nd.node.resType.type = TSDB_DATA_TYPE_BOOL;
×
3380
  pval.nd.datum.b = ret;
×
UNCOV
3381
  if (NULL == taosArrayPush(pctx->stack, &pval)) {
×
UNCOV
3382
    mError("xnode evaluate walker array push error: %s", tstrerror(terrno));
×
UNCOV
3383
    code = terrno;
×
UNCOV
3384
    goto _OVER;
×
3385
  }
3386

UNCOV
3387
_OVER:
×
UNCOV
3388
  if (pval1 != NULL) freeSXndRefValueNode((SXndRefValueNode *)pval1);
×
UNCOV
3389
  if (pval2 != NULL) freeSXndRefValueNode((SXndRefValueNode *)pval2);
×
UNCOV
3390
  TAOS_RETURN(code);
×
3391
}
3392

3393
#define XND_WALKER_CHECK_GOTO(CMD, LABEL)    \
3394
  do {                                       \
3395
    pctx->code = (CMD);                      \
3396
    if ((pctx->code != TSDB_CODE_SUCCESS)) { \
3397
      goto LABEL;                            \
3398
    }                                        \
3399
  } while (0);
3400

3401
static EDealRes evaluateWaker(SNode *pNode, void *pWhereCtx) {
×
3402
  int32_t           code = 0;
×
UNCOV
3403
  SXndWhereContext *pctx = (SXndWhereContext *)pWhereCtx;
×
3404

3405
  if (nodeType(pNode) == QUERY_NODE_COLUMN) {
×
3406
    SColumnNode *colNode = (SColumnNode *)pNode;
×
3407
    SXndRefValueNode *pval =
UNCOV
3408
        (SXndRefValueNode *)taosHashGet(pctx->pMap, colNode->colName, strlen(colNode->colName) + 1);
×
3409
    if (pval == NULL) {
×
UNCOV
3410
      mError("xnode evaluateWhereCond hash get error: %s", tstrerror(terrno));
×
3411
      pctx->code = TSDB_CODE_MND_XNODE_WHERE_COL_NOT_EXIST;
×
3412
      return DEAL_RES_END;
×
3413
    }
3414
    if (NULL == taosArrayPush(pctx->stack, pval)) {
×
UNCOV
3415
      mError("xnode evaluate walker array push error: %s", tstrerror(terrno));
×
3416
      pctx->code = TSDB_CODE_FAILED;
×
3417
      return DEAL_RES_END;
×
3418
    }
UNCOV
3419
    return DEAL_RES_CONTINUE;
×
3420
  }
3421
  if (nodeType(pNode) == QUERY_NODE_VALUE) {
×
3422
    SValueNode *pval = (SValueNode *)pNode;
×
3423
    if (pval->node.resType.type == TSDB_DATA_TYPE_UBIGINT) {
×
UNCOV
3424
      pval->datum.u = taosStr2Int64(pval->literal, NULL, 10);
×
3425
    }
3426
    if (pval->node.resType.type == TSDB_DATA_TYPE_BINARY) {
×
UNCOV
3427
      if (pval->datum.p == NULL) {
×
3428
        pval->datum.p = taosStrndupi(pval->literal, strlen(pval->literal) + 1);
×
3429
      }
3430
    }
3431
    if (pval->node.resType.type == TSDB_DATA_TYPE_NULL) {
×
3432
      pval->isNull = true;
×
3433
      pval->datum.p = NULL;
×
3434
    }
UNCOV
3435
    if (pval->node.resType.type == TSDB_DATA_TYPE_BOOL) {
×
3436
      pval->datum.b = pval->literal[0] == 't' || pval->literal[0] == 'T';
×
3437
    }
UNCOV
3438
    SXndRefValueNode refVal = {0};
×
3439
    refVal.nd = *pval;
×
3440
    refVal.shouldFree = false;
×
3441
    if (NULL == taosArrayPush(pctx->stack, &refVal)) {
×
3442
      mError("xnode evaluate walker array push error: %s", tstrerror(terrno));
×
3443
      pctx->code = TSDB_CODE_FAILED;
×
3444
      return DEAL_RES_END;
×
3445
    }
3446
    return DEAL_RES_CONTINUE;
×
3447
  }
3448

UNCOV
3449
  if (nodeType(pNode) == QUERY_NODE_OPERATOR) {
×
3450
    SOperatorNode *opNode = (SOperatorNode *)pNode;
×
3451
    switch (opNode->opType) {
×
3452
      case OP_TYPE_GREATER_THAN: {
×
UNCOV
3453
        XND_WALKER_CHECK_GOTO(call_op_cmp(pctx, op_greater_than), _exit);
×
3454
        break;
×
3455
      }
3456
      case OP_TYPE_GREATER_EQUAL: {
×
UNCOV
3457
        XND_WALKER_CHECK_GOTO(call_op_cmp(pctx, op_greater_equal), _exit);
×
3458
        break;
×
3459
      }
3460
      case OP_TYPE_LOWER_THAN: {
×
UNCOV
3461
        XND_WALKER_CHECK_GOTO(call_op_cmp(pctx, op_lower_than), _exit);
×
3462
        break;
×
3463
      }
3464
      case OP_TYPE_LOWER_EQUAL: {
×
UNCOV
3465
        XND_WALKER_CHECK_GOTO(call_op_cmp(pctx, op_lower_equal), _exit);
×
3466
        break;
×
3467
      }
3468
      case OP_TYPE_EQUAL: {
×
UNCOV
3469
        XND_WALKER_CHECK_GOTO(call_op_cmp(pctx, op_equal), _exit);
×
3470
        break;
×
3471
      }
UNCOV
3472
      case OP_TYPE_NOT_EQUAL: {
×
3473
        XND_WALKER_CHECK_GOTO(call_op_cmp(pctx, op_not_equal), _exit);
×
3474
        break;
×
3475
      }
3476
      default:
×
3477
        pctx->code = TSDB_CODE_MND_XNODE_WHERE_OP_NOT_SUPPORT;
×
UNCOV
3478
        return DEAL_RES_CONTINUE;
×
3479
    }
3480
    return DEAL_RES_CONTINUE;
×
3481
  }
3482

UNCOV
3483
  if (nodeType(pNode) == QUERY_NODE_LOGIC_CONDITION) {
×
3484
    SLogicConditionNode *logicNode = (SLogicConditionNode *)pNode;
×
3485
    SXndRefValueNode     pval = {0};
×
3486
    pval.nd.node.type = QUERY_NODE_VALUE;
×
3487
    pval.nd.node.resType.type = TSDB_DATA_TYPE_BOOL;
×
3488

UNCOV
3489
    switch (logicNode->condType) {
×
UNCOV
3490
      case LOGIC_COND_TYPE_AND: {
×
3491
        SValueNode *pval2 = (SValueNode *)taosArrayPop(pctx->stack);
×
3492
        SValueNode *pval1 = (SValueNode *)taosArrayPop(pctx->stack);
×
3493

UNCOV
3494
        pval.nd.datum.b = pval1->datum.b && pval2->datum.b;
×
3495
        if (NULL == taosArrayPush(pctx->stack, &pval)) {
×
3496
          mError("xnode walker AND array push err: %s", tstrerror(terrno));
×
3497
          pctx->code = TSDB_CODE_FAILED;
×
UNCOV
3498
          return DEAL_RES_END;
×
3499
        }
3500

3501
        freeSXndRefValueNode((SXndRefValueNode *)pval1);
×
3502
        freeSXndRefValueNode((SXndRefValueNode *)pval2);
×
3503
        break;
×
3504
      }
UNCOV
3505
      case LOGIC_COND_TYPE_OR: {
×
3506
        SValueNode *pval2 = (SValueNode *)taosArrayPop(pctx->stack);
×
3507
        SValueNode *pval1 = (SValueNode *)taosArrayPop(pctx->stack);
×
3508

UNCOV
3509
        pval.nd.datum.b = pval1->datum.b || pval2->datum.b;
×
3510
        if (NULL == taosArrayPush(pctx->stack, &pval)) {
×
3511
          mError("xnode walker OR array push err: %s", tstrerror(terrno));
×
UNCOV
3512
          pctx->code = TSDB_CODE_FAILED;
×
3513
          return DEAL_RES_END;
×
3514
        }
3515

3516
        freeSXndRefValueNode((SXndRefValueNode *)pval1);
×
3517
        freeSXndRefValueNode((SXndRefValueNode *)pval2);
×
UNCOV
3518
        break;
×
3519
      }
3520
      case LOGIC_COND_TYPE_NOT: {
×
3521
        SValueNode *pval1 = (SValueNode *)taosArrayPop(pctx->stack);
×
3522

3523
        pval.nd.datum.b = !pval1->datum.b;
×
3524
        if (NULL == taosArrayPush(pctx->stack, &pval)) {
×
UNCOV
3525
          mError("xnode walker NOT array push err: %s", tstrerror(terrno));
×
3526
          pctx->code = TSDB_CODE_FAILED;
×
UNCOV
3527
          return DEAL_RES_END;
×
3528
        }
3529

UNCOV
3530
        freeSXndRefValueNode((SXndRefValueNode *)pval1);
×
3531
        break;
×
3532
      }
UNCOV
3533
      default:
×
UNCOV
3534
        break;
×
3535
    }
3536
    return DEAL_RES_CONTINUE;
×
3537
  }
3538

3539
  pctx->code = TSDB_CODE_MND_XNODE_INVALID_MSG;
×
3540

3541
_exit:
×
3542
  return DEAL_RES_END;
×
3543
}
3544

3545
static bool evaluateWhereCond(SNode *pWhere, SHashObj *pDataMap, int32_t *code) {
×
UNCOV
3546
  bool             ret = false;
×
UNCOV
3547
  SXndWhereContext ctx = {0};
×
3548

3549
  ctx.stack = taosArrayInit(64, sizeof(SXndRefValueNode));
×
3550
  if (ctx.stack == NULL) {
×
3551
    mError("xnode evaluateWhereCond error: %s", tstrerror(terrno));
×
3552
    *code = terrno;
×
UNCOV
3553
    goto _exit;
×
3554
  }
3555
  ctx.pMap = pDataMap;
×
3556

3557
  // walkexpr pnode
3558
  nodesWalkExprPostOrder(pWhere, evaluateWaker, &ctx);
×
UNCOV
3559
  if (ctx.code != TSDB_CODE_SUCCESS) {
×
3560
    *code = ctx.code;
×
3561
    mError("xnode walkExpr error: %s", tstrerror(ctx.code));
×
UNCOV
3562
    goto _exit;
×
3563
  }
3564
  SValueNode *pval = taosArrayGetLast(ctx.stack);
×
3565
  if (pval == NULL) {
×
UNCOV
3566
    *code = terrno;
×
UNCOV
3567
    mError("xnode evaluateWhereCond error: %s", tstrerror(terrno));
×
UNCOV
3568
    goto _exit;
×
3569
  }
UNCOV
3570
  mDebug("xnode ctx stack size:%lu, last nd type:%d, bool:%d", ctx.stack->size, pval->node.type, pval->datum.b);
×
UNCOV
3571
  ret = pval->datum.b;
×
3572

3573
_exit:
×
3574
  freeSXndWhereContext(&ctx);
×
UNCOV
3575
  return ret;
×
3576
}
3577

3578
static int32_t filterJobsByWhereCond(SNode *pWhere, SArray *pArray, SArray **ppResult) {
20,400✔
3579
  int32_t code = 0;
20,400✔
3580

3581
  *ppResult = taosArrayInit(64, sizeof(SXnodeJobObj));
20,400✔
3582
  if (*ppResult == NULL) {
20,400✔
UNCOV
3583
    code = terrno;
×
3584
    goto _exit;
×
3585
  }
3586
  for (int32_t i = 0; i < pArray->size; i++) {
20,400✔
3587
    SXnodeJobObj *pJob = taosArrayGet(pArray, i);
×
3588

UNCOV
3589
    SHashObj *pDataMap = NULL;
×
UNCOV
3590
    if ((pDataMap = convertJob2Map(pJob)) == NULL) {
×
3591
      mError("xnode evaluate convertJow2Map error: %s", tstrerror(terrno));
×
3592
      goto _exit;
×
3593
    }
UNCOV
3594
    if (evaluateWhereCond(pWhere, pDataMap, &code)) {
×
UNCOV
3595
      if (NULL == taosArrayPush(*ppResult, pJob)) {
×
UNCOV
3596
        mError("xnode filterJobsByWhereCond array push err: %s", tstrerror(terrno));
×
UNCOV
3597
        code = TSDB_CODE_FAILED;
×
UNCOV
3598
        goto _exit;
×
3599
      }
3600
    }
UNCOV
3601
    if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
3602
      goto _exit;
×
3603
    }
3604
  }
3605

3606
_exit:
20,400✔
3607
  TAOS_RETURN(code);
20,400✔
3608
}
3609

3610
#define XND_LOG_END(code, lino)                                                                 \
3611
  do {                                                                                          \
3612
    if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_ACTION_IN_PROGRESS) {                    \
3613
      mError("xnode:%s failed at line %d code: %d, since %s", __func__, lino, code, tstrerror(code)); \
3614
    }                                                                                           \
3615
  } while (0)
3616

3617
void httpRebalanceAuto(SArray *pResult) {
720✔
3618
  int32_t code = 0;
720✔
3619
  int32_t lino = 0;
720✔
3620
  SJson *pJsonArr = NULL;
720✔
3621
  char  *pContStr = NULL;
720✔
3622
  // convert pResult to [(tid, jid)*]
3623
  pJsonArr = tjsonCreateArray();
720✔
3624
  if (pJsonArr == NULL) {
720✔
3625
    code = terrno;
×
UNCOV
3626
    mError("xnode json array error: %s", tstrerror(code));
×
3627
    goto _OVER;
×
3628
  }
3629
  for (int32_t i = 0; i < pResult->size; i++) {
720✔
UNCOV
3630
    SXnodeJobObj *pJob = taosArrayGet(pResult, i);
×
UNCOV
3631
    SJson        *pJsonObj = tjsonCreateObject();
×
UNCOV
3632
    if (pJsonObj == NULL) {
×
UNCOV
3633
      code = terrno;
×
3634
      mError("xnode json object error: %s", tstrerror(code));
×
3635
      goto _OVER;
×
3636
    }
UNCOV
3637
    TAOS_CHECK_GOTO(tjsonAddDoubleToObject(pJsonObj, "tid", pJob->taskId), &lino, _OVER);
×
UNCOV
3638
    TAOS_CHECK_GOTO(tjsonAddDoubleToObject(pJsonObj, "jid", pJob->id), &lino, _OVER);
×
UNCOV
3639
    TAOS_CHECK_GOTO(tjsonAddItemToArray(pJsonArr, pJsonObj), &lino, _OVER);
×
3640
  }
3641

3642
  pContStr = tjsonToUnformattedString(pJsonArr);
720✔
3643
  if (pContStr == NULL) {
720✔
UNCOV
3644
    mError("xnode to json string error: %s", tstrerror(terrno));
×
UNCOV
3645
    goto _OVER;
×
3646
  }
3647
  char xnodeUrl[TSDB_XNODE_URL_LEN + 1] = {0};
720✔
3648
  snprintf(xnodeUrl, TSDB_XNODE_URL_LEN + 1, "%s/rebalance/auto", XNODED_PIPE_SOCKET_URL);
720✔
3649
  SJson* pJson = mndSendReqRetJson(xnodeUrl, HTTP_TYPE_POST, defaultTimeout, pContStr, strlen(pContStr));
720✔
3650
  if (pJson) {
720✔
UNCOV
3651
    tjsonDelete(pJson);
×
3652
  }
3653

3654
_OVER:
720✔
3655
  if (pJsonArr != NULL) tjsonDelete(pJsonArr);
720✔
3656
  if (pContStr != NULL) taosMemoryFree(pContStr);
720✔
3657
  XND_LOG_END(code, lino);
720✔
3658
  return;
720✔
3659
}
3660

3661
static int32_t mndProcessRebalanceXnodeJobsWhereReq(SRpcMsg *pReq) {
720✔
3662
  int32_t                      code = 0;
720✔
3663
  SMnode                      *pMnode = pReq->info.node;
720✔
3664
  SMRebalanceXnodeJobsWhereReq rebalanceReq = {0};
720✔
3665
  SNode                       *pWhere = NULL;
720✔
3666
  SArray                      *pArray = NULL;
720✔
3667
  SArray                      *pResult = NULL;
720✔
3668

3669
  code = mndValidateXnodePermissions(pMnode, pReq, MND_OPER_REBALANCE_XNODE_JOB);
720✔
3670
  if (code != TSDB_CODE_SUCCESS) {
720✔
3671
    mError("failed check permission for rebalance xnode jobs where, code:%s", tstrerror(code));
×
3672
    goto _OVER;
×
3673
  }
3674
  TAOS_CHECK_GOTO(tDeserializeSMRebalanceXnodeJobsWhereReq(pReq->pCont, pReq->contLen, &rebalanceReq), NULL, _OVER);
720✔
3675

3676
  TAOS_CHECK_GOTO(mndAcquireXnodeJobsAll(pMnode, &pArray), NULL, _OVER);
720✔
3677
  for (int32_t i = 0; i < pArray->size; i++) {
720✔
3678
    SXnodeJobObj *pJob = taosArrayGet(pArray, i);
×
NEW
3679
    SXnodeTaskObj *pTaskObj = NULL;
×
NEW
3680
    pTaskObj = mndAcquireXnodeTaskById(pMnode, pJob->taskId);
×
NEW
3681
    if (pTaskObj == NULL) {
×
NEW
3682
      continue;
×
3683
    }
NEW
3684
    code = mndXnodeCheckTaskObjPrivilege(pMnode, pReq->info.conn.user, pTaskObj, PRIV_CM_ALTER);
×
NEW
3685
    mndReleaseXnodeTask(pMnode, pTaskObj);
×
UNCOV
3686
    if (code == TSDB_CODE_SUCCESS) {
×
UNCOV
3687
      continue;
×
NEW
3688
    } else if (code == TSDB_CODE_MND_NO_RIGHTS) {
×
3689
      taosArrayRemove(pArray, i);
×
UNCOV
3690
      i--;
×
3691
    } else {
UNCOV
3692
      mError("user:%s rebalance where xnode job:%d, error:%s", pReq->info.conn.user, pJob->id, tstrerror(code));
×
UNCOV
3693
      goto _OVER;
×
3694
    }
3695
  }
3696
  if (NULL != rebalanceReq.ast.ptr) {
720✔
3697
    TAOS_CHECK_GOTO(nodesStringToNode(rebalanceReq.ast.ptr, &pWhere), NULL, _OVER);
720✔
3698
    TAOS_CHECK_GOTO(filterJobsByWhereCond(pWhere, pArray, &pResult), NULL, _OVER);
720✔
3699
    httpRebalanceAuto(pResult);
720✔
3700
  } else {
UNCOV
3701
    httpRebalanceAuto(pArray);
×
3702
  }
3703

3704
_OVER:
720✔
3705
  if (pWhere != NULL) {
720✔
3706
    nodesDestroyNode(pWhere);
720✔
3707
  }
3708
  if (pArray != NULL) {
720✔
3709
    taosArrayDestroy(pArray);
720✔
3710
  }
3711
  if (pResult != NULL) {
720✔
3712
    taosArrayDestroy(pResult);
720✔
3713
  }
3714
  tFreeSMRebalanceXnodeJobsWhereReq(&rebalanceReq);
720✔
3715
  TAOS_RETURN(code);
720✔
3716
}
3717

3718
static int32_t dropXnodeJobById(SMnode *pMnode, SRpcMsg *pReq, int32_t jid) {
×
NEW
3719
  int32_t        code = 0;
×
NEW
3720
  int32_t        lino = 0;
×
NEW
3721
  SXnodeJobObj  *pObj = NULL;
×
NEW
3722
  SXnodeTaskObj *pTaskObj = NULL;
×
3723

3724
  pObj = mndAcquireXnodeJob(pMnode, jid);
×
3725
  if (pObj == NULL) {
×
UNCOV
3726
    code = terrno;
×
3727
    lino = __LINE__;
×
3728
    goto _OVER;
×
3729
  }
NEW
3730
  pTaskObj = mndAcquireXnodeTaskById(pMnode, pObj->taskId);
×
NEW
3731
  if (pTaskObj != NULL) {
×
NEW
3732
    code = mndXnodeCheckTaskObjPrivilege(pMnode, pReq->info.conn.user, pTaskObj, PRIV_CM_DROP);
×
NEW
3733
    if (code != TSDB_CODE_SUCCESS) {
×
NEW
3734
      mError("user:%s has no privilege on xnode task:%d, job:%d", pReq->info.conn.user, pTaskObj->id, pObj->id);
×
NEW
3735
      goto _OVER;
×
3736
    }
3737
  }
3738
  code = mndDropXnodeJob(pMnode, pReq, pObj);
×
3739

3740
_OVER:
×
3741
  XND_LOG_END(code, lino);
×
NEW
3742
  mndReleaseXnodeTask(pMnode, pTaskObj);
×
3743
  mndReleaseXnodeJob(pMnode, pObj);
×
3744
  return code;
×
3745
}
3746

3747
static int32_t dropXnodeJobByWhereCond(SMnode *pMnode, SRpcMsg *pReq, SMDropXnodeJobReq *dropReq) {
19,680✔
3748
  int32_t       code = 0;
19,680✔
3749
  int32_t       lino = 0;
19,680✔
3750
  SXnodeJobObj *pObj = NULL;
19,680✔
3751
  SNode        *pWhere = NULL;
19,680✔
3752
  SArray       *pArray = NULL;
19,680✔
3753
  SArray       *pResult = NULL;
19,680✔
3754

3755
  if (NULL != dropReq->ast.ptr) {
19,680✔
3756
    TAOS_CHECK_GOTO(mndAcquireXnodeJobsAll(pMnode, &pArray), &lino, _OVER);
19,680✔
3757
    TAOS_CHECK_GOTO(nodesStringToNode(dropReq->ast.ptr, &pWhere), &lino, _OVER);
19,680✔
3758

3759
    for (int32_t i = 0; i < pArray->size; i++) {
19,680✔
NEW
3760
      SXnodeJobObj *pJob = taosArrayGet(pArray, i);
×
NEW
3761
      SXnodeTaskObj *pTaskObj = NULL;
×
NEW
3762
      pTaskObj = mndAcquireXnodeTaskById(pMnode, pJob->taskId);
×
NEW
3763
      if (pTaskObj == NULL) {
×
NEW
3764
        continue;
×
3765
      }
NEW
3766
      code = mndXnodeCheckTaskObjPrivilege(pMnode, pReq->info.conn.user, pTaskObj, PRIV_CM_DROP);
×
NEW
3767
      mndReleaseXnodeTask(pMnode, pTaskObj);
×
NEW
3768
      if (code == TSDB_CODE_SUCCESS) {
×
NEW
3769
        continue;
×
NEW
3770
      } else if (code == TSDB_CODE_MND_NO_RIGHTS) {
×
NEW
3771
        taosArrayRemove(pArray, i);
×
NEW
3772
        i--;
×
3773
      } else {
NEW
3774
        mError("user:%s rebalance where xnode job:%d, error:%s", pReq->info.conn.user, pJob->id, tstrerror(code));
×
NEW
3775
        goto _OVER;
×
3776
      }
3777
    }
3778
    TAOS_CHECK_GOTO(filterJobsByWhereCond(pWhere, pArray, &pResult), &lino, _OVER);
19,680✔
3779

3780
    for (int32_t i = 0; i < pResult->size; i++) {
19,680✔
3781
      pObj = taosArrayGet(pResult, i);
×
3782
      TAOS_CHECK_GOTO(mndDropXnodeJob(pMnode, NULL, pObj), &lino, _OVER);
×
3783
    }
3784
  }
3785

3786
_OVER:
19,680✔
3787
  XND_LOG_END(code, lino);
19,680✔
3788
  if (pResult != NULL) {
19,680✔
3789
    taosArrayDestroy(pResult);
19,680✔
3790
  }
3791
  if (pWhere != NULL) {
19,680✔
3792
    nodesDestroyNode(pWhere);
19,680✔
3793
  }
3794
  if (pArray != NULL) {
19,680✔
3795
    taosArrayDestroy(pArray);
19,680✔
3796
  }
3797
  return code;
19,680✔
3798
}
3799

3800
static int32_t mndProcessDropXnodeJobReq(SRpcMsg *pReq) {
19,680✔
3801
  mDebug("drop xnode job req, content len:%d", pReq->contLen);
19,680✔
3802
  SMnode           *pMnode = pReq->info.node;
19,680✔
3803
  int32_t           code = -1;
19,680✔
3804
  SMDropXnodeJobReq dropReq = {0};
19,680✔
3805

3806
  code = mndValidateXnodePermissions(pMnode, pReq, MND_OPER_DROP_XNODE_JOB);
19,680✔
3807
  if (code != TSDB_CODE_SUCCESS) {
19,680✔
UNCOV
3808
    mError("failed check permission for drop xnode jobs, code:%s", tstrerror(code));
×
UNCOV
3809
    goto _OVER;
×
3810
  }
3811
  TAOS_CHECK_GOTO(tDeserializeSMDropXnodeJobReq(pReq->pCont, pReq->contLen, &dropReq), NULL, _OVER);
19,680✔
3812
  mDebug("Xnode drop job with jid:%d", dropReq.jid);
19,680✔
3813

3814
  if (dropReq.jid <= 0 && dropReq.ast.ptr == NULL) {
19,680✔
UNCOV
3815
    code = TSDB_CODE_MND_XNODE_INVALID_MSG;
×
UNCOV
3816
    goto _OVER;
×
3817
  }
3818
  if (dropReq.jid > 0) {
19,680✔
UNCOV
3819
    code = dropXnodeJobById(pMnode, pReq, dropReq.jid);
×
UNCOV
3820
    if (code == 0) {
×
UNCOV
3821
      code = TSDB_CODE_ACTION_IN_PROGRESS;
×
3822
    } else {
UNCOV
3823
      goto _OVER;
×
3824
    }
3825
  } else {
3826
    TAOS_CHECK_GOTO(dropXnodeJobByWhereCond(pMnode, pReq, &dropReq), NULL, _OVER);
19,680✔
3827
  }
3828

3829
_OVER:
19,680✔
3830
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
19,680✔
3831
    mError("xnode:%d, failed to drop since %s", dropReq.jid, tstrerror(code));
×
3832
  }
3833
  tFreeSMDropXnodeJobReq(&dropReq);
19,680✔
3834
  TAOS_RETURN(code);
19,680✔
3835
}
3836

3837
/**
3838
 * @brief Mapping the columns of show xnode jobs
3839
 *
3840
 * See [xnodeTaskJobSchema] in systable.h.
3841
 *
3842
 *  {.name = "jid", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = false},
3843
    {.name = "tid", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = false},
3844
    {.name = "config", .bytes = TSDB_XNODE_NAME_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo =
3845
 false},
3846
    {.name = "status", .bytes = 10 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
3847
    // {.name = "reason", .bytes = 10 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
3848
    {.name = "create_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP, .sysInfo = false},
3849
    {.name = "update_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP, .sysInfo = false},
3850
 * @param pReq
3851
 * @param pShow
3852
 * @param pBlock
3853
 * @param rows
3854
 * @return int32_t
3855
 */
3856
static int32_t mndRetrieveXnodeJobs(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
4,561✔
3857
  SMnode       *pMnode = pReq->info.node;
4,561✔
3858
  SSdb         *pSdb = pMnode->pSdb;
4,561✔
3859
  int32_t       numOfRows = 0;
4,561✔
3860
  int32_t       cols = 0;
4,561✔
3861
  SXnodeJobObj *pObj = NULL;
4,561✔
3862
  char          buf[VARSTR_HEADER_SIZE + TMAX(TSDB_XNODE_TASK_JOB_CONFIG_LEN, TSDB_XNODE_TASK_REASON_LEN)];
4,561✔
3863
  char          status[64] = {0};
4,561✔
3864
  int32_t       code = 0;
4,561✔
3865
  SUserObj     *pOperUser = NULL;
4,561✔
3866
  mDebug("show.type:%d, %s:%d: retrieve xnode jobs with rows: %d", pShow->type, __FILE__, __LINE__, rows);
4,561✔
3867

3868
  TAOS_CHECK_GOTO(mndAcquireUser(pMnode, pReq->info.conn.user, &pOperUser), NULL, _end);
4,561✔
3869

3870
  while (numOfRows < rows) {
4,561✔
3871
    pShow->pIter = sdbFetch(pSdb, SDB_XNODE_JOB, pShow->pIter, (void **)&pObj);
4,561✔
3872
    if (pShow->pIter == NULL) break;
4,561✔
3873

UNCOV
3874
    if (!pOperUser->superUser) {
×
UNCOV
3875
      SXnodeTaskObj *pTask = mndAcquireXnodeTaskById(pMnode, pObj->taskId);
×
UNCOV
3876
      bool allowed = false;
×
UNCOV
3877
      if (pTask != NULL) {
×
NEW
3878
        allowed = (0 == mndXnodeCheckTaskObjPrivilege(pMnode, pReq->info.conn.user, pTask, PRIV_CM_SHOW));
×
UNCOV
3879
        mndReleaseXnodeTask(pMnode, pTask);
×
3880
      }
UNCOV
3881
      if (!allowed) {
×
UNCOV
3882
        sdbRelease(pSdb, pObj);
×
UNCOV
3883
        continue;
×
3884
      }
3885
    }
3886

3887
    cols = 0;
×
3888
    SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
3889
    // id
3890
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->id, false);
×
3891
    if (code != 0) goto _end;
×
3892
    // tid
UNCOV
3893
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
3894
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->taskId, false);
×
3895
    if (code != 0) goto _end;
×
3896

3897
    // config
UNCOV
3898
    buf[0] = 0;
×
UNCOV
3899
    STR_WITH_MAXSIZE_TO_VARSTR(buf, pObj->config, pShow->pMeta->pSchemas[cols].bytes);
×
3900
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
3901
    code = colDataSetVal(pColInfo, numOfRows, buf, false);
×
UNCOV
3902
    if (code != 0) goto _end;
×
3903

3904
    // via
UNCOV
3905
    if (pObj->via != 0) {
×
3906
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
3907
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->via, false);
×
3908
      if (code != 0) goto _end;
×
3909
    } else {
UNCOV
3910
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
3911
      colDataSetNULL(pColInfo, numOfRows);
×
3912
    }
3913

3914
    // xnode_id
3915
    if (pObj->xnodeId != 0) {
×
UNCOV
3916
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
UNCOV
3917
      code = colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->xnodeId, false);
×
3918
      if (code != 0) goto _end;
×
3919
    } else {
3920
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
3921
      colDataSetNULL(pColInfo, numOfRows);
×
3922
    }
3923

3924
    // status
UNCOV
3925
    if (pObj->statusLen > 0) {
×
UNCOV
3926
      buf[0] = 0;
×
UNCOV
3927
      STR_WITH_MAXSIZE_TO_VARSTR(buf, pObj->status, pShow->pMeta->pSchemas[cols].bytes);
×
3928
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
3929
      code = colDataSetVal(pColInfo, numOfRows, (const char *)buf, false);
×
3930
      if (code != 0) goto _end;
×
3931
    } else {
UNCOV
3932
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
3933
      colDataSetNULL(pColInfo, numOfRows);
×
3934
    }
3935

3936
    // reason
UNCOV
3937
    if (pObj->reasonLen > 0) {
×
3938
      buf[0] = 0;
×
3939
      STR_WITH_MAXSIZE_TO_VARSTR(buf, pObj->reason, pShow->pMeta->pSchemas[cols].bytes);
×
3940
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
3941
      code = colDataSetVal(pColInfo, numOfRows, (const char *)buf, false);
×
3942
      if (code != 0) goto _end;
×
3943
    } else {
UNCOV
3944
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
3945
      colDataSetNULL(pColInfo, numOfRows);
×
3946
    }
3947

3948
    // create_time
UNCOV
3949
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
3950
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->createTime, false);
×
3951
    if (code != 0) goto _end;
×
3952

3953
    // update_time
3954
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
3955
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->updateTime, false);
×
UNCOV
3956
    if (code != 0) goto _end;
×
3957

3958
    numOfRows++;
×
UNCOV
3959
    sdbRelease(pSdb, pObj);
×
3960
  }
3961

3962
_end:
4,561✔
3963
  if (code != 0) sdbRelease(pSdb, pObj);
4,561✔
3964
  mndReleaseUser(pMnode, pOperUser);
4,561✔
3965

3966
  pShow->numOfRows += numOfRows;
4,561✔
3967
  return numOfRows;
4,561✔
3968
}
3969
static void mndCancelGetNextXnodeJob(SMnode *pMnode, void *pIter) {
×
UNCOV
3970
  SSdb *pSdb = pMnode->pSdb;
×
3971
  sdbCancelFetchByType(pSdb, pIter, SDB_XNODE_JOB);
×
3972
}
×
3973

UNCOV
3974
static size_t taosCurlWriteData(char *pCont, size_t contLen, size_t nmemb, void *userdata) {
×
UNCOV
3975
  SCurlResp *pRsp = userdata;
×
UNCOV
3976
  if (contLen == 0 || nmemb == 0 || pCont == NULL) {
×
UNCOV
3977
    pRsp->dataLen = 0;
×
UNCOV
3978
    pRsp->data = NULL;
×
UNCOV
3979
    uError("curl response is received, len:%" PRId64, pRsp->dataLen);
×
UNCOV
3980
    return 0;
×
3981
  }
3982

3983
  int64_t newDataSize = (int64_t)contLen * nmemb;
×
3984
  int64_t size = pRsp->dataLen + newDataSize;
×
3985

UNCOV
3986
  if (pRsp->data == NULL) {
×
3987
    pRsp->data = taosMemoryMalloc(size + 1);
×
3988
    if (pRsp->data == NULL) {
×
3989
      uError("failed to prepare recv buffer for post rsp, len:%d, code:%s", (int32_t)size + 1, tstrerror(terrno));
×
3990
      return 0;  // return the recv length, if failed, return 0
×
3991
    }
3992
  } else {
3993
    char *p = taosMemoryRealloc(pRsp->data, size + 1);
×
UNCOV
3994
    if (p == NULL) {
×
UNCOV
3995
      uError("failed to prepare recv buffer for post rsp, len:%d, code:%s", (int32_t)size + 1, tstrerror(terrno));
×
3996
      return 0;  // return the recv length, if failed, return 0
×
3997
    }
3998

3999
    pRsp->data = p;
×
4000
  }
4001

4002
  if (pRsp->data != NULL) {
×
4003
    (void)memcpy(pRsp->data + pRsp->dataLen, pCont, newDataSize);
×
4004

UNCOV
4005
    pRsp->dataLen = size;
×
4006
    pRsp->data[size] = 0;
×
4007

4008
    uDebugL("curl response is received, len:%" PRId64 ", content:%s", size, pRsp->data);
×
4009
    return newDataSize;
×
4010
  } else {
UNCOV
4011
    pRsp->dataLen = 0;
×
4012
    uError("failed to malloc curl response");
×
UNCOV
4013
    return 0;
×
4014
  }
4015
}
4016

UNCOV
4017
static int32_t taosCurlGetRequest(const char *url, SCurlResp *pRsp, int32_t timeout, const char *socketPath) {
×
4018
  CURL   *curl = NULL;
×
4019
  int32_t code = 0;
×
UNCOV
4020
  int32_t lino = 0;
×
4021

4022
  curl = curl_easy_init();
×
UNCOV
4023
  if (curl == NULL) {
×
4024
    uError("failed to create curl handle");
×
4025
    return -1;
×
4026
  }
4027

4028
  #ifndef WINDOWS
UNCOV
4029
  TAOS_CHECK_GOTO(curl_easy_setopt(curl, CURLOPT_UNIX_SOCKET_PATH, socketPath), &lino, _OVER);
×
4030
  #endif
4031
  TAOS_CHECK_GOTO(curl_easy_setopt(curl, CURLOPT_URL, url), &lino, _OVER);
×
4032
  TAOS_CHECK_GOTO(curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, taosCurlWriteData), &lino, _OVER);
×
4033
  TAOS_CHECK_GOTO(curl_easy_setopt(curl, CURLOPT_WRITEDATA, pRsp), &lino, _OVER);
×
UNCOV
4034
  TAOS_CHECK_GOTO(curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, timeout), &lino, _OVER);
×
4035

4036
  uDebug("curl get request will sent, url:%s", url);
×
4037
  CURLcode curlCode = curl_easy_perform(curl);
×
4038
  if (curlCode != CURLE_OK) {
×
UNCOV
4039
    if (curlCode == CURLE_OPERATION_TIMEDOUT) {
×
UNCOV
4040
      mError("xnode failed to perform curl action, code:%d", curlCode);
×
UNCOV
4041
      code = TSDB_CODE_MND_XNODE_URL_RESP_TIMEOUT;
×
4042
      goto _OVER;
×
4043
    }
4044
    uError("failed to perform curl action, code:%d", curlCode);
×
4045
    code = TSDB_CODE_MND_XNODE_URL_CANT_ACCESS;
×
4046
    goto _OVER;
×
4047
  }
4048

4049
  long http_code = 0;
×
4050
  TAOS_CHECK_GOTO(curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code), &lino, _OVER);
×
4051
  if (http_code != 200) {
×
4052
    code = TSDB_CODE_MND_XNODE_HTTP_CODE_ERROR;
×
4053
  }
4054

4055
_OVER:
×
UNCOV
4056
  if (curl != NULL) curl_easy_cleanup(curl);
×
4057
  XND_LOG_END(code, lino);
×
4058
  return code;
×
4059
}
4060

UNCOV
4061
static int32_t taosCurlPostRequest(const char *url, SCurlResp *pRsp, const char *buf, int32_t bufLen, int32_t timeout,
×
4062
                                   const char *socketPath) {
4063
  struct curl_slist *headers = NULL;
×
4064
  CURL              *curl = NULL;
×
4065
  int32_t            code = 0;
×
UNCOV
4066
  int32_t            lino = 0;
×
4067

4068
  curl = curl_easy_init();
×
4069
  if (curl == NULL) {
×
4070
    mError("xnode failed to create curl handle");
×
4071
    return -1;
×
4072
  }
4073

4074
  headers = curl_slist_append(headers, "Content-Type:application/json;charset=UTF-8");
×
4075
  #ifndef WINDOWS
4076
  TAOS_CHECK_GOTO(curl_easy_setopt(curl, CURLOPT_UNIX_SOCKET_PATH, socketPath), &lino, _OVER);
×
4077
  #endif
4078
  TAOS_CHECK_GOTO(curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers), &lino, _OVER);
×
4079
  TAOS_CHECK_GOTO(curl_easy_setopt(curl, CURLOPT_URL, url), &lino, _OVER);
×
UNCOV
4080
  TAOS_CHECK_GOTO(curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, taosCurlWriteData), &lino, _OVER);
×
4081
  TAOS_CHECK_GOTO(curl_easy_setopt(curl, CURLOPT_WRITEDATA, pRsp), &lino, _OVER);
×
4082
  TAOS_CHECK_GOTO(curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, timeout), &lino, _OVER);
×
4083
  TAOS_CHECK_GOTO(curl_easy_setopt(curl, CURLOPT_POST, 1), &lino, _OVER);
×
4084
  TAOS_CHECK_GOTO(curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, bufLen), &lino, _OVER);
×
UNCOV
4085
  TAOS_CHECK_GOTO(curl_easy_setopt(curl, CURLOPT_POSTFIELDS, buf), &lino, _OVER);
×
UNCOV
4086
  TAOS_CHECK_GOTO(curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L), &lino, _OVER);
×
4087
  TAOS_CHECK_GOTO(curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L), &lino, _OVER);
×
4088

4089
  mDebug("xnode curl post request will sent, url:%s len:%d content:%s", url, bufLen, buf);
×
UNCOV
4090
  CURLcode curlCode = curl_easy_perform(curl);
×
4091

4092
  if (curlCode != CURLE_OK) {
×
4093
    if (curlCode == CURLE_OPERATION_TIMEDOUT) {
×
4094
      mError("xnode failed to perform curl action, code:%d", curlCode);
×
4095
      code = TSDB_CODE_MND_XNODE_URL_RESP_TIMEOUT;
×
4096
      goto _OVER;
×
4097
    }
4098
    uError("xnode failed to perform curl action, code:%d", curlCode);
×
4099
    code = TSDB_CODE_MND_XNODE_URL_CANT_ACCESS;
×
4100
    goto _OVER;
×
4101
  }
4102

4103
  long http_code = 0;
×
UNCOV
4104
  TAOS_CHECK_GOTO(curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code), &lino, _OVER);
×
4105
  if (http_code != 200) {
×
4106
    mError("xnode failed to perform curl action, http code:%ld", http_code);
×
4107
    code = TSDB_CODE_MND_XNODE_HTTP_CODE_ERROR;
×
4108
  }
4109

UNCOV
4110
_OVER:
×
4111
  if (curl != NULL) {
×
4112
    curl_slist_free_all(headers);
×
4113
    curl_easy_cleanup(curl);
×
4114
  }
UNCOV
4115
  XND_LOG_END(code, lino);
×
4116
  return code;
×
4117
}
4118

4119
static int32_t taosCurlDeleteRequest(const char *url, SCurlResp *pRsp, int32_t timeout, const char *socketPath) {
×
4120
  CURL   *curl = NULL;
×
UNCOV
4121
  int32_t code = 0;
×
UNCOV
4122
  int32_t lino = 0;
×
4123

4124
  curl = curl_easy_init();
×
4125
  if (curl == NULL) {
×
4126
    uError("xnode failed to create curl handle");
×
UNCOV
4127
    return -1;
×
4128
  }
4129

4130
  #ifndef WINDOWS
UNCOV
4131
  if (curl_easy_setopt(curl, CURLOPT_UNIX_SOCKET_PATH, socketPath)) goto _OVER;
×
4132
  #endif
4133
  if (curl_easy_setopt(curl, CURLOPT_URL, url) != 0) goto _OVER;
×
4134
  if (curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE") != 0) goto _OVER;
×
4135
  if (curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, taosCurlWriteData) != 0) goto _OVER;
×
UNCOV
4136
  if (curl_easy_setopt(curl, CURLOPT_WRITEDATA, pRsp) != 0) goto _OVER;
×
4137
  if (curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, timeout) != 0) goto _OVER;
×
4138

4139
  uDebug("xnode curl get request will sent, url:%s", url);
×
4140
  CURLcode curlCode = curl_easy_perform(curl);
×
UNCOV
4141
  if (curlCode != CURLE_OK) {
×
UNCOV
4142
    uError("xnode failed to perform curl action, curl code:%d", curlCode);
×
UNCOV
4143
    if (curlCode == CURLE_OPERATION_TIMEDOUT) {
×
4144
      code = TSDB_CODE_MND_XNODE_URL_RESP_TIMEOUT;
×
UNCOV
4145
      goto _OVER;
×
4146
    }
4147
    code = TSDB_CODE_MND_XNODE_URL_CANT_ACCESS;
×
4148
    goto _OVER;
×
4149
  }
4150

UNCOV
4151
  long http_code = 0;
×
4152
  TAOS_CHECK_GOTO(curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code), &lino, _OVER);
×
4153
  if (http_code != 200 && http_code != 204) {
×
4154
    uError("xnode curl request response http code:%ld", http_code);
×
4155
    code = TSDB_CODE_MND_XNODE_HTTP_CODE_ERROR;
×
4156
  }
4157

4158
_OVER:
×
UNCOV
4159
  if (curl != NULL) curl_easy_cleanup(curl);
×
4160
  XND_LOG_END(code, lino);
×
4161
  return code;
×
4162
}
4163

4164
SJson *mndSendReqRetJson(const char *url, EHttpType type, int64_t timeout, const char *buf, int64_t bufLen) {
16,080✔
4165
  SJson    *pJson = NULL;
16,080✔
4166
  SCurlResp curlRsp = {0};
16,080✔
4167
  char      socketPath[PATH_MAX] = {0};
16,080✔
4168

4169
  getXnodedPipeName(socketPath, sizeof(socketPath));
16,080✔
4170
  #ifndef WINDOWS
4171
  if (!taosCheckExistFile(socketPath)) {
16,080✔
4172
    uError("xnode failed to send request, socket path:%s not exist", socketPath);
16,080✔
4173
    terrno = TSDB_CODE_MND_XNODE_URL_CANT_ACCESS;
16,080✔
4174
    goto _EXIT;
16,080✔
4175
  }
4176
  #endif
UNCOV
4177
  if (type == HTTP_TYPE_GET) {
×
UNCOV
4178
    if ((terrno = taosCurlGetRequest(url, &curlRsp, timeout, socketPath)) != 0) {
×
UNCOV
4179
      goto _OVER;
×
4180
    }
UNCOV
4181
  } else if (type == HTTP_TYPE_POST) {
×
UNCOV
4182
    if ((terrno = taosCurlPostRequest(url, &curlRsp, buf, bufLen, timeout, socketPath)) != 0) {
×
UNCOV
4183
      goto _OVER;
×
4184
    }
UNCOV
4185
  } else if (type == HTTP_TYPE_DELETE) {
×
UNCOV
4186
    if ((terrno = taosCurlDeleteRequest(url, &curlRsp, timeout, socketPath)) != 0) {
×
UNCOV
4187
      goto _OVER;
×
4188
    }
4189
  } else {
4190
    uError("xnode invalid http type:%d", type);
×
4191
    terrno = TSDB_CODE_MND_XNODE_INVALID_MSG;
×
4192
    goto _EXIT;
×
4193
  }
4194

4195
_OVER:
×
4196
  if (terrno == TSDB_CODE_SUCCESS) {
×
UNCOV
4197
    if (curlRsp.data == NULL || curlRsp.dataLen == 0) {
×
4198
      pJson = tjsonCreateObject();
×
4199
      goto _EXIT;
×
4200
    }
UNCOV
4201
    pJson = tjsonParse(curlRsp.data);
×
UNCOV
4202
    if (pJson == NULL) {
×
4203
      terrno = TSDB_CODE_INVALID_JSON_FORMAT;
×
4204
      goto _EXIT;
×
4205
    }
UNCOV
4206
  } else if (terrno == TSDB_CODE_MND_XNODE_HTTP_CODE_ERROR) {
×
UNCOV
4207
    pJson = tjsonCreateObject();
×
4208
    char *buf = taosMemCalloc(1, curlRsp.dataLen + 1);
×
4209
    (void)memcpy(buf, curlRsp.data, curlRsp.dataLen);
×
4210
    if (tjsonAddStringToObject(pJson, "__inner_error", buf) != TSDB_CODE_SUCCESS) {
×
4211
      taosMemoryFreeClear(buf);
×
4212
      goto _EXIT;
×
4213
    }
4214
    taosMemoryFreeClear(buf);
×
4215
  }
4216

4217
_EXIT:
16,080✔
4218
  if (curlRsp.data != NULL) taosMemoryFreeClear(curlRsp.data);
16,080✔
4219
  if (terrno != TSDB_CODE_SUCCESS) {
16,080✔
4220
    mError("xnode failed to send request, url: %s, since:%s", url, tstrerror(terrno));
16,080✔
4221
  }
4222
  return pJson;
16,080✔
4223
}
4224

4225
static int32_t mndGetXnodeStatus(SXnodeObj *pObj, char *status, int32_t statusLen) {
3,240✔
4226
  int32_t code = 0;
3,240✔
4227
  SJson  *pJson = NULL;
3,240✔
4228

4229
  char xnodeUrl[TSDB_XNODE_URL_LEN + 1] = {0};
3,240✔
4230
  snprintf(xnodeUrl, TSDB_XNODE_URL_LEN + 1, "%s/xnode/%d", XNODED_PIPE_SOCKET_URL, pObj->id);
3,240✔
4231
  pJson = mndSendReqRetJson(xnodeUrl, HTTP_TYPE_GET, defaultTimeout, NULL, 0);
3,240✔
4232
  if (pJson == NULL) {
3,240✔
4233
    code = terrno;
3,240✔
4234
    goto _OVER;
3,240✔
4235
  }
4236

UNCOV
4237
  code = tjsonGetStringValue2(pJson, "status", status, statusLen);
×
UNCOV
4238
  if (code < 0) {
×
UNCOV
4239
    code = TSDB_CODE_INVALID_JSON_FORMAT;
×
UNCOV
4240
    goto _OVER;
×
4241
  }
UNCOV
4242
  if (strlen(status) == 0) {
×
UNCOV
4243
    code = TSDB_CODE_MND_XNODE_INVALID_MSG;
×
UNCOV
4244
    goto _OVER;
×
4245
  }
4246

4247
_OVER:
3,240✔
4248
  if (pJson != NULL) tjsonDelete(pJson);
3,240✔
4249
  TAOS_RETURN(code);
3,240✔
4250
}
4251

4252
/** xnode agent section **/
4253

4254
SSdbRaw *mndXnodeAgentActionEncode(SXnodeAgentObj *pObj) {
13,230✔
4255
  int32_t code = 0;
13,230✔
4256
  int32_t lino = 0;
13,230✔
4257
  terrno = TSDB_CODE_OUT_OF_MEMORY;
13,230✔
4258

4259
  if (NULL == pObj) {
13,230✔
UNCOV
4260
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
4261
    return NULL;
×
4262
  }
4263

4264
  int32_t rawDataLen =
13,230✔
4265
      sizeof(SXnodeAgentObj) + TSDB_XNODE_RESERVE_SIZE + pObj->nameLen + pObj->tokenLen + pObj->statusLen;
13,230✔
4266

4267
  SSdbRaw *pRaw = sdbAllocRaw(SDB_XNODE_AGENT, TSDB_XNODE_VER_NUMBER, rawDataLen);
13,230✔
4268
  if (pRaw == NULL) goto _OVER;
13,230✔
4269

4270
  int32_t dataPos = 0;
13,230✔
4271
  SDB_SET_INT32(pRaw, dataPos, pObj->id, _OVER)
13,230✔
4272
  SDB_SET_INT32(pRaw, dataPos, pObj->nameLen, _OVER)
13,230✔
4273
  SDB_SET_BINARY(pRaw, dataPos, pObj->name, pObj->nameLen, _OVER)
13,230✔
4274
  SDB_SET_INT32(pRaw, dataPos, pObj->tokenLen, _OVER)
13,230✔
4275
  SDB_SET_BINARY(pRaw, dataPos, pObj->token, pObj->tokenLen, _OVER)
13,230✔
4276
  SDB_SET_INT32(pRaw, dataPos, pObj->statusLen, _OVER)
13,230✔
4277
  SDB_SET_BINARY(pRaw, dataPos, pObj->status, pObj->statusLen, _OVER)
13,230✔
4278
  SDB_SET_INT64(pRaw, dataPos, pObj->createTime, _OVER)
13,230✔
4279
  SDB_SET_INT64(pRaw, dataPos, pObj->updateTime, _OVER)
13,230✔
4280

4281
  SDB_SET_RESERVE(pRaw, dataPos, TSDB_XNODE_RESERVE_SIZE, _OVER)
13,230✔
4282

4283
  terrno = 0;
13,230✔
4284

4285
_OVER:
13,230✔
4286
  if (terrno != 0) {
13,230✔
UNCOV
4287
    mError("xnode agent:%d, failed to encode to raw:%p since %s", pObj->id, pRaw, terrstr());
×
UNCOV
4288
    sdbFreeRaw(pRaw);
×
UNCOV
4289
    return NULL;
×
4290
  }
4291

4292
  mTrace("xnode agent:%d, encode to raw:%p, row:%p", pObj->id, pRaw, pObj);
13,230✔
4293
  return pRaw;
13,230✔
4294
}
4295

4296
SSdbRow *mndXnodeAgentActionDecode(SSdbRaw *pRaw) {
9,870✔
4297
  int32_t code = 0;
9,870✔
4298
  int32_t lino = 0;
9,870✔
4299
  terrno = TSDB_CODE_OUT_OF_MEMORY;
9,870✔
4300
  SSdbRow        *pRow = NULL;
9,870✔
4301
  SXnodeAgentObj *pObj = NULL;
9,870✔
4302

4303
  if (NULL == pRaw) {
9,870✔
UNCOV
4304
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
4305
    return NULL;
×
4306
  }
4307

4308
  int8_t sver = 0;
9,870✔
4309
  if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto _OVER;
9,870✔
4310

4311
  if (sver != TSDB_XNODE_VER_NUMBER) {
9,870✔
UNCOV
4312
    terrno = TSDB_CODE_SDB_INVALID_DATA_VER;
×
UNCOV
4313
    goto _OVER;
×
4314
  }
4315

4316
  pRow = sdbAllocRow(sizeof(SXnodeAgentObj));
9,870✔
4317
  if (pRow == NULL) goto _OVER;
9,870✔
4318

4319
  pObj = sdbGetRowObj(pRow);
9,870✔
4320
  if (pObj == NULL) goto _OVER;
9,870✔
4321

4322
  int32_t dataPos = 0;
9,870✔
4323
  SDB_GET_INT32(pRaw, dataPos, &pObj->id, _OVER)
9,870✔
4324
  SDB_GET_INT32(pRaw, dataPos, &pObj->nameLen, _OVER)
9,870✔
4325
  if (pObj->nameLen > 0) {
9,870✔
4326
    pObj->name = taosMemoryCalloc(pObj->nameLen, 1);
9,870✔
4327
    if (pObj->name == NULL) goto _OVER;
9,870✔
4328
    SDB_GET_BINARY(pRaw, dataPos, pObj->name, pObj->nameLen, _OVER)
9,870✔
4329
  } else {
UNCOV
4330
    pObj->name = NULL;
×
4331
  }
4332
  SDB_GET_INT32(pRaw, dataPos, &pObj->tokenLen, _OVER)
9,870✔
4333
  if (pObj->tokenLen > 0) {
9,870✔
4334
    pObj->token = taosMemoryCalloc(pObj->tokenLen, 1);
9,870✔
4335
    if (pObj->token == NULL) goto _OVER;
9,870✔
4336
    SDB_GET_BINARY(pRaw, dataPos, pObj->token, pObj->tokenLen, _OVER)
9,870✔
4337
  } else {
UNCOV
4338
    pObj->token = NULL;
×
4339
  }
4340
  SDB_GET_INT32(pRaw, dataPos, &pObj->statusLen, _OVER)
9,870✔
4341
  if (pObj->statusLen > 0) {
9,870✔
4342
    pObj->status = taosMemoryCalloc(pObj->statusLen, 1);
8,475✔
4343
    if (pObj->status == NULL) goto _OVER;
8,475✔
4344
    SDB_GET_BINARY(pRaw, dataPos, pObj->status, pObj->statusLen, _OVER)
8,475✔
4345
  } else {
4346
    pObj->status = NULL;
1,395✔
4347
  }
4348
  SDB_GET_INT64(pRaw, dataPos, &pObj->createTime, _OVER)
9,870✔
4349
  SDB_GET_INT64(pRaw, dataPos, &pObj->updateTime, _OVER)
9,870✔
4350

4351
  SDB_GET_RESERVE(pRaw, dataPos, TSDB_XNODE_RESERVE_SIZE, _OVER)
9,870✔
4352

4353
  terrno = 0;
9,870✔
4354

4355
_OVER:
9,870✔
4356
  if (terrno != 0) {
9,870✔
UNCOV
4357
    mError("xnode agent:%d, failed to decode from raw:%p since %s", pObj == NULL ? 0 : pObj->id, pRaw, terrstr());
×
UNCOV
4358
    if (pObj != NULL) {
×
UNCOV
4359
      taosMemoryFreeClear(pObj->name);
×
UNCOV
4360
      taosMemoryFreeClear(pObj->token);
×
UNCOV
4361
      taosMemoryFreeClear(pObj->status);
×
4362
    }
UNCOV
4363
    taosMemoryFreeClear(pRow);
×
UNCOV
4364
    return NULL;
×
4365
  }
4366

4367
  mTrace("xnode agent:%d, decode from raw:%p, row:%p", pObj->id, pRaw, pObj);
9,870✔
4368
  return pRow;
9,870✔
4369
}
4370

4371
int32_t mndXnodeAgentActionInsert(SSdb *pSdb, SXnodeAgentObj *pObj) {
2,280✔
4372
  mDebug("xnode agent:%d, perform insert action, row:%p", pObj->id, pObj);
2,280✔
4373
  return 0;
2,280✔
4374
}
4375

4376
int32_t mndXnodeAgentActionUpdate(SSdb *pSdb, SXnodeAgentObj *pOld, SXnodeAgentObj *pNew) {
4,920✔
4377
  mDebug("xnode agent:%d, perform update action, old row:%p new row:%p", pOld->id, pOld, pNew);
4,920✔
4378

4379
  taosWLockLatch(&pOld->lock);
4,920✔
4380
  swapFields(&pNew->nameLen, &pNew->name, &pOld->nameLen, &pOld->name);
4,920✔
4381
  swapFields(&pNew->tokenLen, &pNew->token, &pOld->tokenLen, &pOld->token);
4,920✔
4382
  swapFields(&pNew->statusLen, &pNew->status, &pOld->statusLen, &pOld->status);
4,920✔
4383
  if (pNew->updateTime > pOld->updateTime) {
4,920✔
4384
    pOld->updateTime = pNew->updateTime;
360✔
4385
  }
4386
  taosWUnLockLatch(&pOld->lock);
4,920✔
4387
  return 0;
4,920✔
4388
}
4389

4390
static void mndFreeXnodeAgent(SXnodeAgentObj *pObj) {
11,760✔
4391
  if (pObj == NULL) return;
11,760✔
4392
  if (pObj->name != NULL) {
11,760✔
4393
    taosMemoryFreeClear(pObj->name);
11,760✔
4394
  }
4395
  if (pObj->token != NULL) {
11,760✔
4396
    taosMemoryFreeClear(pObj->token);
11,760✔
4397
  }
4398
  if (pObj->status != NULL) {
11,760✔
4399
    taosMemoryFreeClear(pObj->status);
10,200✔
4400
  }
4401
}
4402

4403
int32_t mndXnodeAgentActionDelete(SSdb *pSdb, SXnodeAgentObj *pObj) {
9,480✔
4404
  mDebug("xnode agent:%d, perform delete action, row:%p", pObj->id, pObj);
9,480✔
4405
  mndFreeXnodeAgent(pObj);
9,480✔
4406
  return 0;
9,480✔
4407
}
4408

4409
static int32_t mndSetCreateXnodeAgentRedoLogs(STrans *pTrans, SXnodeAgentObj *pObj) {
2,280✔
4410
  int32_t  code = 0;
2,280✔
4411
  SSdbRaw *pRedoRaw = mndXnodeAgentActionEncode(pObj);
2,280✔
4412
  if (pRedoRaw == NULL) {
2,280✔
UNCOV
4413
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
4414
    if (terrno != 0) code = terrno;
×
UNCOV
4415
    TAOS_RETURN(code);
×
4416
  }
4417
  TAOS_CHECK_RETURN(mndTransAppendRedolog(pTrans, pRedoRaw));
2,280✔
4418
  TAOS_CHECK_RETURN(sdbSetRawStatus(pRedoRaw, SDB_STATUS_CREATING));
2,280✔
4419
  TAOS_RETURN(code);
2,280✔
4420
}
4421

4422
static int32_t mndSetCreateXnodeAgentUndoLogs(STrans *pTrans, SXnodeAgentObj *pObj) {
2,280✔
4423
  int32_t  code = 0;
2,280✔
4424
  SSdbRaw *pUndoRaw = mndXnodeAgentActionEncode(pObj);
2,280✔
4425
  if (pUndoRaw == NULL) {
2,280✔
4426
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
4427
    if (terrno != 0) code = terrno;
×
4428
    TAOS_RETURN(code);
×
4429
  }
4430
  TAOS_CHECK_RETURN(mndTransAppendUndolog(pTrans, pUndoRaw));
2,280✔
4431
  TAOS_CHECK_RETURN(sdbSetRawStatus(pUndoRaw, SDB_STATUS_DROPPED));
2,280✔
4432
  TAOS_RETURN(code);
2,280✔
4433
}
4434

4435
static int32_t mndSetCreateXnodeAgentCommitLogs(STrans *pTrans, SXnodeAgentObj *pObj) {
2,640✔
4436
  int32_t  code = 0;
2,640✔
4437
  SSdbRaw *pCommitRaw = mndXnodeAgentActionEncode(pObj);
2,640✔
4438
  if (pCommitRaw == NULL) {
2,640✔
4439
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
4440
    if (terrno != 0) code = terrno;
×
4441
    TAOS_RETURN(code);
×
4442
  }
4443
  TAOS_CHECK_RETURN(mndTransAppendCommitlog(pTrans, pCommitRaw));
2,640✔
4444
  TAOS_CHECK_RETURN(sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY));
2,640✔
4445
  TAOS_RETURN(code);
2,640✔
4446
}
4447

4448
void mndReleaseXnodeAgent(SMnode *pMnode, SXnodeAgentObj *pObj) {
2,760✔
4449
  SSdb *pSdb = pMnode->pSdb;
2,760✔
4450
  sdbRelease(pSdb, pObj);
2,760✔
4451
}
2,760✔
4452

NEW
4453
static int32_t mndXnodeCheckTaskObjPrivilege(SMnode *pMnode, const char *user, SXnodeTaskObj *pTask, EPrivType priv) {
×
NEW
4454
  if (pMnode == NULL || user == NULL || pTask == NULL) {
×
UNCOV
4455
    return TSDB_CODE_INVALID_PARA;
×
4456
  }
4457

NEW
4458
  SUserObj *curUser = NULL;
×
NEW
4459
  SUserObj *tUser = NULL;
×
NEW
4460
  int32_t code = mndAcquireUser(pMnode, user, &curUser);
×
UNCOV
4461
  if (code != 0) {
×
NEW
4462
    goto _OVER;
×
4463
  }
4464

NEW
4465
  code = mndAcquireUser(pMnode, pTask->createdBy, &tUser);
×
NEW
4466
  if (code != 0) {
×
NEW
4467
    goto _OVER;
×
4468
  }
4469

NEW
4470
  char objName[32] = {0};
×
NEW
4471
  snprintf(objName, sizeof(objName), "%d", pTask->id);
×
NEW
4472
  code = mndCheckObjPrivilegeRec(pMnode, curUser, priv, PRIV_OBJ_XTASK, tUser->uid, tUser->acctId, objName, NULL);
×
4473

NEW
4474
_OVER:
×
NEW
4475
  mndReleaseUser(pMnode, curUser);
×
NEW
4476
  mndReleaseUser(pMnode, tUser);
×
UNCOV
4477
  return code;
×
4478
}
4479

4480
static int32_t mndValidateXnodePermissions(SMnode *pMnode, SRpcMsg *pReq, EOperType oper) {
50,040✔
4481
  int32_t code = grantCheck(TSDB_GRANT_XNODE);
50,040✔
4482
  if (code != TSDB_CODE_SUCCESS) {
50,040✔
UNCOV
4483
    mError("failed to validate xnode permissions, code:%s, oper:%d", tstrerror(code), oper);
×
4484
    return code;
×
4485
  }
4486

4487
  EPrivType privType;
4488
  switch (oper) {
50,040✔
4489
    case MND_OPER_CREATE_XNODE:        privType = PRIV_NODE_CREATE; break;
2,400✔
4490
    case MND_OPER_UPDATE_XNODE:        privType = PRIV_NODE_ALTER; break;
840✔
4491
    case MND_OPER_DRAIN_XNODE:         privType = PRIV_NODE_ALTER; break;
360✔
4492
    case MND_OPER_DROP_XNODE:          privType = PRIV_NODE_DROP; break;
2,280✔
4493
    case MND_OPER_CREATE_XNODE_AGENT:  privType = PRIV_NODE_CREATE; break;
2,280✔
4494
    case MND_OPER_UPDATE_XNODE_AGENT:  privType = PRIV_NODE_ALTER; break;
360✔
4495
    case MND_OPER_DROP_XNODE_AGENT:    privType = PRIV_NODE_DROP; break;
2,400✔
4496

4497
    case MND_OPER_CREATE_XNODE_TASK:   privType = PRIV_XNODE_TASK_CREATE; break;
3,960✔
4498
    case MND_OPER_START_XNODE_TASK:    return code;
120✔
4499
    case MND_OPER_STOP_XNODE_TASK:     return code;
120✔
4500
    case MND_OPER_UPDATE_XNODE_TASK:   return code;
480✔
4501
    case MND_OPER_DROP_XNODE_TASK:     return code;
3,240✔
4502

4503
    case MND_OPER_CREATE_XNODE_JOB:    privType = PRIV_XNODE_TASK_CREATE; break;
10,440✔
4504
    case MND_OPER_UPDATE_XNODE_JOB:    return code;
120✔
4505
    case MND_OPER_REBALANCE_XNODE_JOB: return code;
960✔
4506
    case MND_OPER_DROP_XNODE_JOB:      return code;
19,680✔
NEW
4507
    default: return TSDB_CODE_MND_NO_RIGHTS;
×
4508
  }
4509

4510
  SUserObj *pUser = NULL;
25,320✔
4511
  code = mndAcquireUser(pMnode, pReq->info.conn.user, &pUser);
25,320✔
4512
  if (code != 0) return code;
25,320✔
4513

4514
  code = mndCheckSysObjPrivilege(pMnode, pUser, NULL, privType, 0, 0, NULL, NULL);
25,320✔
4515
  mndReleaseUser(pMnode, pUser);
25,320✔
4516
  return code;
25,320✔
4517
}
4518

UNCOV
4519
SXnodeAgentObj *mndAcquireXnodeAgentById(SMnode *pMnode, int32_t id) {
×
UNCOV
4520
  SXnodeAgentObj *pObj = sdbAcquire(pMnode->pSdb, SDB_XNODE_AGENT, &id);
×
UNCOV
4521
  if (pObj == NULL && terrno == TSDB_CODE_SDB_OBJ_NOT_THERE) {
×
UNCOV
4522
    terrno = TSDB_CODE_MND_XNODE_AGENT_NOT_EXIST;
×
4523
  }
4524
  return pObj;
×
4525
}
4526

4527
static SXnodeAgentObj *mndAcquireXnodeAgentByName(SMnode *pMnode, const char *name) {
5,040✔
4528
  SSdb *pSdb = pMnode->pSdb;
5,040✔
4529

4530
  void *pIter = NULL;
5,040✔
4531
  while (1) {
6,120✔
4532
    SXnodeAgentObj *pAgent = NULL;
11,160✔
4533
    pIter = sdbFetch(pSdb, SDB_XNODE_AGENT, pIter, (void **)&pAgent);
11,160✔
4534
    if (pIter == NULL) break;
11,160✔
4535
    if (pAgent->name == NULL) {
8,760✔
UNCOV
4536
      continue;
×
4537
    }
4538

4539
    if (strcasecmp(name, pAgent->name) == 0) {
8,760✔
4540
      sdbCancelFetch(pSdb, pIter);
2,640✔
4541
      return pAgent;
2,640✔
4542
    }
4543

4544
    sdbRelease(pSdb, pAgent);
6,120✔
4545
  }
4546

4547
  mDebug("xnode agent:%s, not found", name);
2,400✔
4548
  terrno = TSDB_CODE_MND_XNODE_AGENT_NOT_EXIST;
2,400✔
4549
  return NULL;
2,400✔
4550
}
4551

4552
static int32_t mndCheckXnodeAgentExists(SMnode *pMnode, const char *name) {
2,280✔
4553
  SXnodeAgentObj *pObj = mndAcquireXnodeAgentByName(pMnode, name);
2,280✔
4554
  if (pObj != NULL) {
2,280✔
UNCOV
4555
    mError("xnode agent:%s already exists", name);
×
UNCOV
4556
    mndReleaseXnodeAgent(pMnode, pObj);
×
UNCOV
4557
    return TSDB_CODE_MND_XNODE_AGENT_ALREADY_EXIST;
×
4558
  }
4559
  terrno = TSDB_CODE_SUCCESS;
2,280✔
4560
  return TSDB_CODE_SUCCESS;
2,280✔
4561
}
4562

4563
typedef struct {
4564
  int64_t sub;  // agent ID
4565
  int64_t iat;  // issued at time
4566
} agentTokenField;
4567

4568
const unsigned char MNDXNODE_DEFAULT_SECRET[] = {126, 222, 130, 137, 43,  122, 41,  173, 144, 146, 116,
4569
                                                 138, 153, 244, 251, 99,  50,  55,  140, 238, 218, 232,
4570
                                                 15,  161, 226, 54,  130, 40,  211, 234, 111, 171};
4571

4572
#ifndef WINDOWS
4573

UNCOV
4574
agentTokenField mndXnodeCreateAgentTokenField(long agent_id, time_t issued_at) {
×
UNCOV
4575
  agentTokenField field = {0};
×
UNCOV
4576
  field.sub = agent_id;
×
UNCOV
4577
  field.iat = issued_at;
×
UNCOV
4578
  return field;
×
4579
}
4580

4581
static char *mndXnodeBase64UrlEncodeOpenssl(const unsigned char *input, size_t input_len) {
8,010✔
4582
  __uint64_t code = 0;
8,010✔
4583
  int32_t lino = 0;
8,010✔
4584
  BIO     *bio = NULL, *b64 = NULL;
8,010✔
4585
  BUF_MEM *bufferPtr = NULL;
8,010✔
4586
  char    *base64_str = NULL;
8,010✔
4587

4588
  b64 = BIO_new(BIO_f_base64());
8,010✔
4589
  if (!b64) {
8,010✔
UNCOV
4590
    lino = __LINE__;
×
UNCOV
4591
    code = ERR_get_error();
×
UNCOV
4592
    goto _err;
×
4593
  }
4594

4595
  bio = BIO_new(BIO_s_mem());
8,010✔
4596
  if (!bio) {
8,010✔
4597
    lino = __LINE__;
×
UNCOV
4598
    code = ERR_get_error();
×
UNCOV
4599
    goto _err;
×
4600
  }
4601

4602
  // BIO chain:b64 → bio
4603
  bio = BIO_push(b64, bio);
8,010✔
4604
  if (!bio) {
8,010✔
UNCOV
4605
    lino = __LINE__;
×
UNCOV
4606
    code = ERR_get_error();
×
UNCOV
4607
    goto _err;
×
4608
  }
4609
  BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
8,010✔
4610

4611
  int32_t write_ret = BIO_write(bio, input, input_len);
8,010✔
4612
  if (write_ret <= 0 || (size_t)write_ret != input_len) {
8,010✔
UNCOV
4613
    lino = __LINE__;
×
UNCOV
4614
    code = ERR_get_error();
×
UNCOV
4615
    goto _err;
×
4616
  }
4617
  int32_t flush_ret = BIO_flush(bio);
8,010✔
4618
  if (flush_ret != 1) {
8,010✔
4619
    lino = __LINE__;
×
4620
    code = ERR_get_error();
×
UNCOV
4621
    goto _err;
×
4622
  }
4623
  int64_t ret = BIO_get_mem_ptr(bio, &bufferPtr);
8,010✔
4624
  if (ret <= 0) {
8,010✔
4625
    lino = __LINE__;
×
4626
    code = ERR_get_error();
×
UNCOV
4627
    goto _err;
×
4628
}
4629
  if (!bufferPtr || !bufferPtr->data || bufferPtr->length == 0) {
8,010✔
4630
    lino = __LINE__;
×
4631
    code = ERR_get_error();
×
4632
    goto _err;
×
4633
  }
4634
  base64_str = taosMemoryMalloc(bufferPtr->length + 1);
8,010✔
4635
  if (!base64_str) {
8,010✔
4636
    lino = __LINE__;
×
4637
    code = ERR_get_error();
×
UNCOV
4638
    goto _err;
×
4639
  }
4640
  memcpy(base64_str, bufferPtr->data, bufferPtr->length);
8,010✔
4641
  base64_str[bufferPtr->length] = '\0';
8,010✔
4642
  // url safe
4643
  for (size_t i = 0; i < bufferPtr->length; i++) {
327,630✔
4644
    if (base64_str[i] == '+') {
319,620✔
4645
      base64_str[i] = '-';
1,305✔
4646
    } else if (base64_str[i] == '/') {
318,315✔
4647
      base64_str[i] = '_';
1,680✔
4648
    }
4649
  }
4650
  // remove padding char '='
4651
  size_t len = strlen(base64_str);
8,010✔
4652
  while (len > 0 && base64_str[len - 1] == '=') {
11,955✔
4653
    base64_str[len - 1] = '\0';
3,945✔
4654
    len--;
3,945✔
4655
  }
4656
  goto _exit;
8,010✔
4657

UNCOV
4658
_err:
×
UNCOV
4659
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
4660
    mError("xnode agent: line: %d failed to encode base64 since %s", lino, ERR_error_string(code, NULL));
×
4661
  }
UNCOV
4662
  if (base64_str) {
×
4663
    taosMemoryFree(base64_str);
×
4664
    base64_str = NULL;
×
4665
  }
4666

4667
_exit:
6,840✔
4668
  if (bio) {
8,010✔
4669
    BIO_free_all(bio);  // will release b64 and bio
8,010✔
UNCOV
4670
  } else if (b64) {
×
UNCOV
4671
    int32_t ret = BIO_free(b64);
×
UNCOV
4672
    if (ret != 1) {
×
UNCOV
4673
      lino = __LINE__;
×
UNCOV
4674
      code = ERR_get_error();
×
4675
      mError("xnode agent: line: %d BIO failed to free since %s", lino, ERR_error_string(code, NULL));
×
4676
    }
4677
  }
4678

4679
  return base64_str;
8,010✔
4680
}
4681

4682
static char *mndXnodeCreateTokenHeader() {
2,670✔
4683
  int32_t code = 0, lino = 0;
2,670✔
4684
  cJSON  *headerJson = NULL;
2,670✔
4685
  char   *headerJsonStr = NULL;
2,670✔
4686
  char   *encoded = NULL;
2,670✔
4687

4688
  headerJson = tjsonCreateObject();
2,670✔
4689
  if (!headerJson) {
2,670✔
UNCOV
4690
    code = terrno;
×
UNCOV
4691
    goto _exit;
×
4692
  }
4693

4694
  TAOS_CHECK_EXIT(tjsonAddStringToObject(headerJson, "alg", "HS256"));
2,670✔
4695
  TAOS_CHECK_EXIT(tjsonAddStringToObject(headerJson, "typ", "JWT"));
2,670✔
4696

4697
  headerJsonStr = tjsonToUnformattedString(headerJson);
2,670✔
4698
  if (!headerJsonStr) {
2,670✔
UNCOV
4699
    code = terrno;
×
UNCOV
4700
    goto _exit;
×
4701
  }
4702
  encoded = mndXnodeBase64UrlEncodeOpenssl((const unsigned char *)headerJsonStr, strlen(headerJsonStr));
2,670✔
4703
  if (!encoded) {
2,670✔
4704
    code = terrno;
×
4705
    goto _exit;
×
4706
  }
4707

4708
_exit:
2,670✔
4709
  if (code != TSDB_CODE_SUCCESS) {
2,670✔
4710
    mError("xnode agent: line: %d failed to create header since %s", lino, tstrerror(code));
×
UNCOV
4711
    taosMemoryFree(encoded);
×
UNCOV
4712
    encoded = NULL;
×
4713
  }
4714

4715
  if (headerJsonStr) {
2,670✔
4716
    taosMemoryFree(headerJsonStr);
2,670✔
4717
  }
4718
  if (headerJson) {
2,670✔
4719
    tjsonDelete(headerJson);
2,670✔
4720
  }
4721

4722
  return encoded;
2,670✔
4723
}
4724

4725
static char *mndXnodeCreateTokenPayload(const agentTokenField *claims) {
2,670✔
4726
  int32_t code = 0, lino = 0;
2,670✔
4727
  cJSON  *payloadJson = NULL;
2,670✔
4728
  char   *payloadStr = NULL;
2,670✔
4729
  char   *encoded = NULL;
2,670✔
4730

4731
  if (!claims) {
2,670✔
UNCOV
4732
    code = TSDB_CODE_INVALID_PARA;
×
UNCOV
4733
    terrno = code;
×
UNCOV
4734
    return NULL;
×
4735
  }
4736

4737
  payloadJson = tjsonCreateObject();
2,670✔
4738
  if (!payloadJson) {
2,670✔
4739
    code = terrno;
×
UNCOV
4740
    goto _exit;
×
4741
  }
4742

4743
  TAOS_CHECK_EXIT(tjsonAddDoubleToObject(payloadJson, "iat", claims->iat));
2,670✔
4744
  TAOS_CHECK_EXIT(tjsonAddDoubleToObject(payloadJson, "sub", claims->sub));
2,670✔
4745

4746
  payloadStr = tjsonToUnformattedString(payloadJson);
2,670✔
4747
  if (!payloadStr) {
2,670✔
UNCOV
4748
    code = terrno;
×
UNCOV
4749
    goto _exit;
×
4750
  }
4751
  encoded = mndXnodeBase64UrlEncodeOpenssl((const unsigned char *)payloadStr, strlen(payloadStr));
2,670✔
4752
  if (!encoded) {
2,670✔
4753
    code = terrno;
×
4754
    goto _exit;
×
4755
  }
4756

4757
_exit:
2,670✔
4758
  if (code != TSDB_CODE_SUCCESS) {
2,670✔
4759
    mError("xnode agent line: %d failed to create payload since %s", lino, tstrerror(code));
×
UNCOV
4760
    taosMemoryFree(encoded);
×
UNCOV
4761
    encoded = NULL;
×
4762
  }
4763
  if (payloadStr) {
2,670✔
4764
    taosMemoryFree(payloadStr);
2,670✔
4765
  }
4766
  if (payloadJson) {
2,670✔
4767
    tjsonDelete(payloadJson);
2,670✔
4768
  }
4769
  return encoded;
2,670✔
4770
}
4771

4772
static char *mndXnodeCreateTokenSignature(const char *header_payload, const unsigned char *secret, size_t secret_len) {
2,670✔
4773
  int32_t       code = 0, lino = 0;
2,670✔
4774
  unsigned char hash[EVP_MAX_MD_SIZE] = {0};
2,670✔
4775
  unsigned int  hash_len = 0;
2,670✔
4776
  char         *encoded = NULL;
2,670✔
4777

4778
  // HMAC-SHA256
4779
  if (!HMAC(EVP_sha256(), secret, secret_len, (const unsigned char *)header_payload, strlen(header_payload), hash,
2,670✔
4780
            &hash_len)) {
UNCOV
4781
    code = terrno;
×
UNCOV
4782
    goto _exit;
×
4783
  }
4784

4785
  encoded = mndXnodeBase64UrlEncodeOpenssl(hash, hash_len);
2,670✔
4786
  if (!encoded) {
2,670✔
4787
    code = terrno;
×
UNCOV
4788
    goto _exit;
×
4789
  }
4790

4791
_exit:
2,670✔
4792
  if (code != TSDB_CODE_SUCCESS) {
2,670✔
4793
    mError("xnode agent line: %d failed create signature since %s", lino, tstrerror(code));
×
UNCOV
4794
    taosMemoryFree(encoded);
×
UNCOV
4795
    encoded = NULL;
×
4796
  }
4797
  return encoded;
2,670✔
4798
}
4799

4800
char *mndXnodeCreateAgentToken(const agentTokenField *claims, const unsigned char *secret, size_t secret_len) {
2,670✔
4801
  int32_t code = 0, lino = 0;
2,670✔
4802
  char   *header = NULL, *payload = NULL;
2,670✔
4803
  char   *headerPayload = NULL;
2,670✔
4804
  char   *signature = NULL;
2,670✔
4805
  char   *token = NULL;
2,670✔
4806

4807
  if (!claims) {
2,670✔
UNCOV
4808
    code = TSDB_CODE_INVALID_PARA;
×
UNCOV
4809
    goto _exit;
×
4810
  }
4811

4812
  if (!secret || secret_len == 0) {
2,670✔
4813
    secret = MNDXNODE_DEFAULT_SECRET;
×
4814
    secret_len = sizeof(MNDXNODE_DEFAULT_SECRET);
×
4815
  }
4816

4817
  header = mndXnodeCreateTokenHeader();
2,670✔
4818
  if (!header) {
2,670✔
4819
    code = terrno;
×
UNCOV
4820
    goto _exit;
×
4821
  }
4822

4823
  payload = mndXnodeCreateTokenPayload(claims);
2,670✔
4824
  if (!payload) {
2,670✔
4825
    code = terrno;
×
UNCOV
4826
    goto _exit;
×
4827
  }
4828

4829
  size_t header_payload_len = strlen(header) + strlen(payload) + 2;
2,670✔
4830
  headerPayload = taosMemoryMalloc(header_payload_len);
2,670✔
4831
  if (!headerPayload) {
2,670✔
UNCOV
4832
    code = terrno;
×
UNCOV
4833
    goto _exit;
×
4834
  }
4835
  snprintf(headerPayload, header_payload_len, "%s.%s", header, payload);
2,670✔
4836

4837
  signature = mndXnodeCreateTokenSignature(headerPayload, secret, secret_len);
2,670✔
4838
  if (!signature) {
2,670✔
UNCOV
4839
    code = terrno;
×
UNCOV
4840
    goto _exit;
×
4841
  }
4842

4843
  size_t token_len = strlen(headerPayload) + strlen(signature) + 2;
2,670✔
4844
  token = taosMemoryCalloc(1, token_len);
2,670✔
4845
  if (!token) {
2,670✔
UNCOV
4846
    code = terrno;
×
UNCOV
4847
    goto _exit;
×
4848
  }
4849

4850
  snprintf(token, token_len, "%s.%s", headerPayload, signature);
2,670✔
4851

4852
_exit:
2,670✔
4853
  if (code != TSDB_CODE_SUCCESS) {
2,670✔
UNCOV
4854
    mError("xnode agent line: %d failed create token since %s", lino, tstrerror(code));
×
UNCOV
4855
    taosMemoryFree(token);
×
UNCOV
4856
    token = NULL;
×
4857
  }
4858
  taosMemoryFree(signature);
2,670✔
4859
  taosMemoryFree(headerPayload);
2,670✔
4860
  taosMemoryFree(payload);
2,670✔
4861
  taosMemoryFree(header);
2,670✔
4862

4863
  return token;
2,670✔
4864
}
4865
#else
4866

4867
static int32_t mndXnodeHmacSha256Windows(const unsigned char *key, size_t key_len, const unsigned char *message,
4868
                                         size_t message_len, unsigned char *output) {
4869
  unsigned char k_pad[64];
4870
  unsigned char k_ipad[64];
4871
  unsigned char k_opad[64];
4872
  unsigned char inner_hash[SHA256_DIGEST_SIZE];
4873
  sha256_ctx    ctx;
4874

4875
  if (key_len > 64) {
4876
    sha256_init(&ctx);
4877
    sha256_update(&ctx, key, key_len);
4878
    sha256_final(&ctx, k_pad);
4879
    memset(k_pad + SHA256_DIGEST_SIZE, 0, 64 - SHA256_DIGEST_SIZE);
4880
  } else {
4881
    memcpy(k_pad, key, key_len);
4882
    memset(k_pad + key_len, 0, 64 - key_len);
4883
  }
4884

4885
  for (int i = 0; i < 64; i++) {
4886
    k_ipad[i] = k_pad[i] ^ 0x36;
4887
    k_opad[i] = k_pad[i] ^ 0x5c;
4888
  }
4889

4890
  sha256_init(&ctx);
4891
  sha256_update(&ctx, k_ipad, 64);
4892
  sha256_update(&ctx, message, message_len);
4893
  sha256_final(&ctx, inner_hash);
4894

4895
  sha256_init(&ctx);
4896
  sha256_update(&ctx, k_opad, 64);
4897
  sha256_update(&ctx, inner_hash, SHA256_DIGEST_SIZE);
4898
  sha256_final(&ctx, output);
4899

4900
  return 0;
4901
}
4902

4903
static char *mndXnodeBase64UrlEncodeWindows(const unsigned char *input, size_t input_len) {
4904
  char *base64_str = NULL;
4905

4906
  int32_t ret = base64_encode(input, input_len, &base64_str);
4907
  if (ret != 0 || !base64_str) {
4908
    return NULL;
4909
  }
4910

4911
  for (size_t i = 0; base64_str[i] != '\0'; i++) {
4912
    if (base64_str[i] == '+') {
4913
      base64_str[i] = '-';
4914
    } else if (base64_str[i] == '/') {
4915
      base64_str[i] = '_';
4916
    }
4917
  }
4918

4919
  size_t len = strlen(base64_str);
4920
  while (len > 0 && base64_str[len - 1] == '=') {
4921
    base64_str[len - 1] = '\0';
4922
    len--;
4923
  }
4924

4925
  return base64_str;
4926
}
4927

4928
static char *mndXnodeCreateTokenHeaderWindows() {
4929
  int32_t code = 0, lino = 0;
4930
  cJSON  *headerJson = NULL;
4931
  char   *headerJsonStr = NULL;
4932
  char   *encoded = NULL;
4933

4934
  headerJson = tjsonCreateObject();
4935
  if (!headerJson) {
4936
    code = terrno;
4937
    goto _exit;
4938
  }
4939

4940
  TAOS_CHECK_EXIT(tjsonAddStringToObject(headerJson, "alg", "HS256"));
4941
  TAOS_CHECK_EXIT(tjsonAddStringToObject(headerJson, "typ", "JWT"));
4942

4943
  headerJsonStr = tjsonToUnformattedString(headerJson);
4944
  if (!headerJsonStr) {
4945
    code = terrno;
4946
    goto _exit;
4947
  }
4948
  encoded = mndXnodeBase64UrlEncodeWindows((const unsigned char *)headerJsonStr, strlen(headerJsonStr));
4949
  if (!encoded) {
4950
    code = terrno;
4951
    goto _exit;
4952
  }
4953

4954
_exit:
4955
  if (code != TSDB_CODE_SUCCESS) {
4956
    mError("xnode agent: line: %d failed to create header since %s", lino, tstrerror(code));
4957
    taosMemoryFree(encoded);
4958
    encoded = NULL;
4959
  }
4960

4961
  if (headerJsonStr) {
4962
    taosMemoryFree(headerJsonStr);
4963
  }
4964
  if (headerJson) {
4965
    tjsonDelete(headerJson);
4966
  }
4967

4968
  return encoded;
4969
}
4970

4971
static char *mndXnodeCreateTokenPayloadWindows(const agentTokenField *claims) {
4972
  int32_t code = 0, lino = 0;
4973
  cJSON  *payloadJson = NULL;
4974
  char   *payloadStr = NULL;
4975
  char   *encoded = NULL;
4976

4977
  if (!claims) {
4978
    code = TSDB_CODE_INVALID_PARA;
4979
    terrno = code;
4980
    return NULL;
4981
  }
4982

4983
  payloadJson = tjsonCreateObject();
4984
  if (!payloadJson) {
4985
    code = terrno;
4986
    goto _exit;
4987
  }
4988

4989
  TAOS_CHECK_EXIT(tjsonAddDoubleToObject(payloadJson, "iat", claims->iat));
4990
  TAOS_CHECK_EXIT(tjsonAddDoubleToObject(payloadJson, "sub", claims->sub));
4991

4992
  payloadStr = tjsonToUnformattedString(payloadJson);
4993
  if (!payloadStr) {
4994
    code = terrno;
4995
    goto _exit;
4996
  }
4997
  encoded = mndXnodeBase64UrlEncodeWindows((const unsigned char *)payloadStr, strlen(payloadStr));
4998
  if (!encoded) {
4999
    code = terrno;
5000
    goto _exit;
5001
  }
5002

5003
_exit:
5004
  if (code != TSDB_CODE_SUCCESS) {
5005
    mError("xnode agent line: %d failed to create payload since %s", lino, tstrerror(code));
5006
    taosMemoryFree(encoded);
5007
    encoded = NULL;
5008
  }
5009
  if (payloadStr) {
5010
    taosMemoryFree(payloadStr);
5011
  }
5012
  if (payloadJson) {
5013
    tjsonDelete(payloadJson);
5014
  }
5015
  return encoded;
5016
}
5017

5018
static char *mndXnodeCreateTokenSignatureWindows(const char *header_payload, const unsigned char *secret,
5019
                                                  size_t secret_len) {
5020
  int32_t       code = 0, lino = 0;
5021
  unsigned char hash[SHA256_DIGEST_SIZE] = {0};
5022
  char         *encoded = NULL;
5023

5024
  int32_t ret = mndXnodeHmacSha256Windows(secret, secret_len, (const unsigned char *)header_payload,
5025
                                          strlen(header_payload), hash);
5026
  if (ret != 0) {
5027
    code = terrno;
5028
    goto _exit;
5029
  }
5030

5031
  encoded = mndXnodeBase64UrlEncodeWindows(hash, SHA256_DIGEST_SIZE);
5032
  if (!encoded) {
5033
    code = terrno;
5034
    goto _exit;
5035
  }
5036

5037
_exit:
5038
  if (code != TSDB_CODE_SUCCESS) {
5039
    mError("xnode agent line: %d failed create signature since %s", lino, tstrerror(code));
5040
    taosMemoryFree(encoded);
5041
    encoded = NULL;
5042
  }
5043
  return encoded;
5044
}
5045

5046
char *mndXnodeCreateAgentToken(const agentTokenField *claims, const unsigned char *secret, size_t secret_len) {
5047
  int32_t code = 0, lino = 0;
5048
  char   *header = NULL, *payload = NULL;
5049
  char   *headerPayload = NULL;
5050
  char   *signature = NULL;
5051
  char   *token = NULL;
5052

5053
  if (!claims) {
5054
    code = TSDB_CODE_INVALID_PARA;
5055
    goto _exit;
5056
  }
5057

5058
  if (!secret || secret_len == 0) {
5059
    secret = MNDXNODE_DEFAULT_SECRET;
5060
    secret_len = sizeof(MNDXNODE_DEFAULT_SECRET);
5061
  }
5062

5063
  header = mndXnodeCreateTokenHeaderWindows();
5064
  if (!header) {
5065
    code = terrno;
5066
    goto _exit;
5067
  }
5068

5069
  payload = mndXnodeCreateTokenPayloadWindows(claims);
5070
  if (!payload) {
5071
    code = terrno;
5072
    goto _exit;
5073
  }
5074

5075
  size_t header_payload_len = strlen(header) + strlen(payload) + 2;
5076
  headerPayload = taosMemoryMalloc(header_payload_len);
5077
  if (!headerPayload) {
5078
    code = terrno;
5079
    goto _exit;
5080
  }
5081
  snprintf(headerPayload, header_payload_len, "%s.%s", header, payload);
5082

5083
  signature = mndXnodeCreateTokenSignatureWindows(headerPayload, secret, secret_len);
5084
  if (!signature) {
5085
    code = terrno;
5086
    goto _exit;
5087
  }
5088

5089
  size_t token_len = strlen(headerPayload) + strlen(signature) + 2;
5090
  token = taosMemoryCalloc(1, token_len);
5091
  if (!token) {
5092
    code = terrno;
5093
    goto _exit;
5094
  }
5095

5096
  snprintf(token, token_len, "%s.%s", headerPayload, signature);
5097

5098
_exit:
5099
  if (code != TSDB_CODE_SUCCESS) {
5100
    mError("xnode agent line: %d failed create token since %s", lino, tstrerror(code));
5101
    taosMemoryFree(token);
5102
    token = NULL;
5103
  }
5104
  taosMemoryFree(signature);
5105
  taosMemoryFree(headerPayload);
5106
  taosMemoryFree(payload);
5107
  taosMemoryFree(header);
5108

5109
  return token;
5110
}
5111

5112
#endif
5113

5114
int32_t mndXnodeGenAgentToken(const SXnodeAgentObj *pAgent, char *pTokenBuf) {
2,280✔
5115
  int32_t code = 0, lino = 0;
2,280✔
5116

5117
  agentTokenField claims = {
2,280✔
5118
      .iat = pAgent->createTime,
2,280✔
5119
      .sub = pAgent->id,
2,280✔
5120
  };
5121
  // token be like:
5122
  // "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3Njc1OTc3NzIsInN1YiI6MTIzNDV9.i7HvYf_S-yWGEExDzQESPUwVX23Ok_7Fxo93aqgKrtw"
5123
  char *token = mndXnodeCreateAgentToken(&claims, MNDXNODE_DEFAULT_SECRET, sizeof(MNDXNODE_DEFAULT_SECRET));
2,280✔
5124
  if (!token) {
2,280✔
UNCOV
5125
    code = terrno;
×
UNCOV
5126
    lino = __LINE__;
×
UNCOV
5127
    goto _exit;
×
5128
  }
5129
  (void)memcpy(pTokenBuf, token, TMIN(strlen(token) + 1, TSDB_XNODE_AGENT_TOKEN_LEN));
2,280✔
5130

5131
_exit:
2,280✔
5132
  if (code != TSDB_CODE_SUCCESS) {
2,280✔
UNCOV
5133
    mError("xnode agent line: %d failed gen token since %s", lino, tstrerror(code));
×
5134
  }
5135
  taosMemoryFree(token);
2,280✔
5136
  TAOS_RETURN(code);
2,280✔
5137
}
5138

5139
static int32_t mndCreateXnodeAgent(SMnode *pMnode, SRpcMsg *pReq, SMCreateXnodeAgentReq *pCreate,
2,280✔
5140
                                   SXnodeAgentObj **ppObj) {
5141
  int32_t code = -1;
2,280✔
5142
  STrans *pTrans = NULL;
2,280✔
5143

5144
  if ((*ppObj) == NULL) {
2,280✔
5145
    *ppObj = taosMemoryCalloc(1, sizeof(SXnodeAgentObj));
2,280✔
5146
    if (*ppObj == NULL) {
2,280✔
UNCOV
5147
      code = terrno;
×
UNCOV
5148
      goto _OVER;
×
5149
    }
5150
  }
5151
  SXnodeAgentObj *pAgentObj = *ppObj;
2,280✔
5152

5153
  pAgentObj->id = sdbGetMaxId(pMnode->pSdb, SDB_XNODE_AGENT);
2,280✔
5154
  pAgentObj->createTime = taosGetTimestampMs();
2,280✔
5155
  pAgentObj->updateTime = pAgentObj->createTime;
2,280✔
5156

5157
  pAgentObj->nameLen = pCreate->name.len + 1;
2,280✔
5158
  pAgentObj->name = taosMemoryCalloc(1, pAgentObj->nameLen);
2,280✔
5159
  if (pAgentObj->name == NULL) goto _OVER;
2,280✔
5160
  (void)memcpy(pAgentObj->name, pCreate->name.ptr, pCreate->name.len);
2,280✔
5161

5162
  if (pCreate->status.ptr != NULL) {
2,280✔
5163
    pAgentObj->statusLen = pCreate->status.len + 1;
1,920✔
5164
    pAgentObj->status = taosMemoryCalloc(1, pAgentObj->statusLen);
1,920✔
5165
    if (pAgentObj->status == NULL) goto _OVER;
1,920✔
5166
    (void)memcpy(pAgentObj->status, pCreate->status.ptr, pCreate->status.len);
1,920✔
5167
  }
5168
  // gen token
5169
  char token[TSDB_XNODE_AGENT_TOKEN_LEN] = {0};
2,280✔
5170
  TAOS_CHECK_GOTO(mndXnodeGenAgentToken(pAgentObj, token), NULL, _OVER);
2,280✔
5171
  pAgentObj->tokenLen = strlen(token) + 1;
2,280✔
5172
  pAgentObj->token = taosMemoryCalloc(1, pAgentObj->tokenLen);
2,280✔
5173
  if (pAgentObj->token == NULL) goto _OVER;
2,280✔
5174
  (void)memcpy(pAgentObj->token, token, pAgentObj->tokenLen - 1);
2,280✔
5175

5176
  pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq, "create-xnode-agent");
2,280✔
5177
  if (pTrans == NULL) {
2,280✔
UNCOV
5178
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
5179
    if (terrno != 0) {
×
UNCOV
5180
      code = terrno;
×
5181
    }
UNCOV
5182
    mError("failed to create transaction for xnode-agent:%s, code:0x%x:%s", pCreate->name.ptr, code, tstrerror(code));
×
5183
    goto _OVER;
×
5184
  }
5185
  mndTransSetSerial(pTrans);
2,280✔
5186

5187
  mDebug("trans:%d, used to create xnode agent:%s as agent:%d", pTrans->id, pCreate->name.ptr, pAgentObj->id);
2,280✔
5188
  TAOS_CHECK_GOTO(mndSetCreateXnodeAgentRedoLogs(pTrans, pAgentObj), NULL, _OVER);
2,280✔
5189
  TAOS_CHECK_GOTO(mndSetCreateXnodeAgentUndoLogs(pTrans, pAgentObj), NULL, _OVER);
2,280✔
5190
  TAOS_CHECK_GOTO(mndSetCreateXnodeAgentCommitLogs(pTrans, pAgentObj), NULL, _OVER);
2,280✔
5191
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
2,280✔
5192

5193
  code = 0;
2,280✔
5194

5195
_OVER:
2,280✔
5196
  mndTransDrop(pTrans);
2,280✔
5197
  TAOS_RETURN(code);
2,280✔
5198
}
5199

5200
static int32_t httpCreateAgent(SXnodeAgentObj *pObj) {
2,280✔
5201
  int32_t code = 0;
2,280✔
5202
  SJson  *pJson = NULL;
2,280✔
5203
  SJson  *postContent = NULL;
2,280✔
5204
  char   *pContStr = NULL;
2,280✔
5205

5206
  char xnodeUrl[TSDB_XNODE_URL_LEN + 1] = {0};
2,280✔
5207
  snprintf(xnodeUrl, TSDB_XNODE_URL_LEN + 1, "%s/agent", XNODED_PIPE_SOCKET_URL);
2,280✔
5208
  postContent = tjsonCreateObject();
2,280✔
5209
  if (postContent == NULL) {
2,280✔
UNCOV
5210
    code = terrno;
×
UNCOV
5211
    goto _OVER;
×
5212
  }
5213
  TAOS_CHECK_GOTO(tjsonAddStringToObject(postContent, "token", pObj->token), NULL, _OVER);
2,280✔
5214
  pContStr = tjsonToUnformattedString(postContent);
2,280✔
5215
  if (pContStr == NULL) {
2,280✔
5216
    code = terrno;
×
UNCOV
5217
    goto _OVER;
×
5218
  }
5219
  pJson = mndSendReqRetJson(xnodeUrl, HTTP_TYPE_POST, defaultTimeout, pContStr, strlen(pContStr));
2,280✔
5220

5221
_OVER:
2,280✔
5222
  if (postContent != NULL) {
2,280✔
5223
    tjsonDelete(postContent);
2,280✔
5224
  }
5225
  if (pContStr != NULL) {
2,280✔
5226
    taosMemFree(pContStr);
2,280✔
5227
  }
5228
  if (pJson != NULL) {
2,280✔
UNCOV
5229
    tjsonDelete(pJson);
×
5230
  }
5231
  TAOS_RETURN(code);
2,280✔
5232
}
5233

5234
static int32_t mndProcessCreateXnodeAgentReq(SRpcMsg *pReq) {
2,280✔
5235
  SMnode               *pMnode = pReq->info.node;
2,280✔
5236
  int32_t               code = 0;
2,280✔
5237
  SXnodeAgentObj       *pObj = NULL;
2,280✔
5238
  SMCreateXnodeAgentReq createReq = {0};
2,280✔
5239

5240
  code = mndValidateXnodePermissions(pMnode, pReq, MND_OPER_CREATE_XNODE_AGENT);
2,280✔
5241
  if (code != TSDB_CODE_SUCCESS) {
2,280✔
UNCOV
5242
    mError("failed check permission for create xnode agent, code:%s", tstrerror(code));
×
UNCOV
5243
    goto _OVER;
×
5244
  }
5245

5246
  code = tDeserializeSMCreateXnodeAgentReq(pReq->pCont, pReq->contLen, &createReq);
2,280✔
5247
  if (code != 0) {
2,280✔
5248
    mError("failed to deserialize create xnode agent request, code:%s", tstrerror(code));
×
UNCOV
5249
    TAOS_RETURN(code);
×
5250
  }
5251

5252
  TAOS_CHECK_GOTO(mndCheckXnodeAgentExists(pMnode, createReq.name.ptr), NULL, _OVER);
2,280✔
5253

5254
  TAOS_CHECK_GOTO(mndCreateXnodeAgent(pMnode, pReq, &createReq, &pObj), NULL, _OVER);
2,280✔
5255
  code = TSDB_CODE_ACTION_IN_PROGRESS;
2,280✔
5256

5257
  (void)httpCreateAgent(pObj);
2,280✔
5258

5259
_OVER:
2,280✔
5260
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
2,280✔
UNCOV
5261
    mError("xnode agent:%s, failed to create since %s", createReq.name.ptr ? createReq.name.ptr : "unknown",
×
5262
           tstrerror(code));
5263
  }
5264
  if (pObj != NULL) {
2,280✔
5265
    mndFreeXnodeAgent(pObj);
2,280✔
5266
    taosMemoryFree(pObj);
2,280✔
5267
  }
5268
  tFreeSMCreateXnodeAgentReq(&createReq);
2,280✔
5269
  TAOS_RETURN(code);
2,280✔
5270
}
5271

5272
static int32_t mndUpdateXnodeAgent(SMnode *pMnode, SRpcMsg *pReq, const SXnodeAgentObj *pOld,
360✔
5273
                                   SMUpdateXnodeAgentReq *pUpdate) {
5274
  mDebug("xnode agent:%d, start to update", pUpdate->id);
360✔
5275
  int32_t        code = -1;
360✔
5276
  STrans        *pTrans = NULL;
360✔
5277
  struct {
5278
    bool status;
5279
    bool name;
5280
  } isChange = {0};
360✔
5281
  SXnodeAgentObj agentObjRef = *pOld;
360✔
5282

5283
  const char *status = getXTaskOptionByName(&pUpdate->options, "status");
360✔
5284
  if (status != NULL) {
360✔
5285
    isChange.status = true;
360✔
5286
    agentObjRef.statusLen = strlen(status) + 1;
360✔
5287
    agentObjRef.status = taosMemoryCalloc(1, agentObjRef.statusLen);
360✔
5288
    if (agentObjRef.status == NULL) goto _OVER;
360✔
5289
    (void)memcpy(agentObjRef.status, status, agentObjRef.statusLen);
360✔
5290
  }
5291
  const char *name = getXTaskOptionByName(&pUpdate->options, "name");
360✔
5292
  if (name != NULL) {
360✔
UNCOV
5293
    isChange.name = true;
×
UNCOV
5294
    agentObjRef.nameLen = strlen(name) + 1;
×
UNCOV
5295
    agentObjRef.name = taosMemoryCalloc(1, agentObjRef.nameLen);
×
UNCOV
5296
    if (agentObjRef.name == NULL) goto _OVER;
×
UNCOV
5297
    (void)memcpy(agentObjRef.name, name, agentObjRef.nameLen);
×
5298
  }
5299
  agentObjRef.updateTime = taosGetTimestampMs();
360✔
5300

5301
  pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq, "update-xnode-agent");
360✔
5302
  if (pTrans == NULL) {
360✔
UNCOV
5303
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
UNCOV
5304
    if (terrno != 0) code = terrno;
×
UNCOV
5305
    goto _OVER;
×
5306
  }
5307
  mInfo("trans:%d, used to update xnode agent:%d", pTrans->id, agentObjRef.id);
360✔
5308

5309
  TAOS_CHECK_GOTO(mndSetCreateXnodeAgentCommitLogs(pTrans, &agentObjRef), NULL, _OVER);
360✔
5310
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
360✔
5311
  code = 0;
360✔
5312

5313
_OVER:
360✔
5314
  if (isChange.status) {
360✔
5315
    taosMemoryFree(agentObjRef.status);
360✔
5316
  }
5317
  if (isChange.name) {
360✔
UNCOV
5318
    taosMemoryFree(agentObjRef.name);
×
5319
  }
5320
  mndTransDrop(pTrans);
360✔
5321
  TAOS_RETURN(code);
360✔
5322
}
5323

5324
static int32_t mndProcessUpdateXnodeAgentReq(SRpcMsg *pReq) {
360✔
5325
  SMnode               *pMnode = pReq->info.node;
360✔
5326
  int32_t               code = -1;
360✔
5327
  SXnodeAgentObj       *pObj = NULL;
360✔
5328
  SMUpdateXnodeAgentReq updateReq = {0};
360✔
5329

5330
  code = mndValidateXnodePermissions(pMnode, pReq, MND_OPER_UPDATE_XNODE_AGENT);
360✔
5331
  if (code != TSDB_CODE_SUCCESS) {
360✔
UNCOV
5332
    mError("failed check permission for update xnode agent, code:%s", tstrerror(code));
×
UNCOV
5333
    goto _OVER;
×
5334
  }
5335

5336
  TAOS_CHECK_GOTO(tDeserializeSMUpdateXnodeAgentReq(pReq->pCont, pReq->contLen, &updateReq), NULL, _OVER);
360✔
5337
  mDebug("xnode update agent request id:%d, nameLen:%d\n", updateReq.id, updateReq.name.len);
360✔
5338

5339
  if (updateReq.id <= 0 && (updateReq.name.len <= 0 || updateReq.name.ptr == NULL)) {
360✔
UNCOV
5340
    code = TSDB_CODE_MND_XNODE_INVALID_MSG;
×
UNCOV
5341
    goto _OVER;
×
5342
  }
5343

5344
  if (updateReq.id > 0) {
360✔
5345
    pObj = mndAcquireXnodeAgentById(pMnode, updateReq.id);
×
5346
  } else {
5347
    pObj = mndAcquireXnodeAgentByName(pMnode, updateReq.name.ptr);
360✔
5348
  }
5349
  if (pObj == NULL) {
360✔
5350
    code = terrno;
×
UNCOV
5351
    goto _OVER;
×
5352
  }
5353
  const char *nameRef = getXTaskOptionByName(&updateReq.options, "name");
360✔
5354
  if (nameRef != NULL) {
360✔
5355
    SXnodeAgentObj* tmpObj = mndAcquireXnodeAgentByName(pMnode, nameRef);
×
5356
    if (tmpObj != NULL) {
×
UNCOV
5357
      mndReleaseXnodeAgent(pMnode, tmpObj);
×
UNCOV
5358
      code = TSDB_CODE_MND_XNODE_NAME_DUPLICATE;
×
UNCOV
5359
      goto _OVER;
×
5360
    }
5361
  }
5362

5363
  code = mndUpdateXnodeAgent(pMnode, pReq, pObj, &updateReq);
360✔
5364
  if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
360✔
5365

5366
_OVER:
360✔
5367
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
360✔
UNCOV
5368
    mError("xnode agent:%d, failed to update since %s", updateReq.id, tstrerror(code));
×
5369
  }
5370

5371
  mndReleaseXnodeAgent(pMnode, pObj);
360✔
5372
  tFreeSMUpdateXnodeAgentReq(&updateReq);
360✔
5373
  TAOS_RETURN(code);
360✔
5374
}
5375

5376
static int32_t mndSetDropXnodeAgentRedoLogs(STrans *pTrans, SXnodeAgentObj *pObj) {
2,280✔
5377
  int32_t  code = 0;
2,280✔
5378
  SSdbRaw *pRedoRaw = mndXnodeAgentActionEncode(pObj);
2,280✔
5379
  if (pRedoRaw == NULL) {
2,280✔
UNCOV
5380
    code = terrno;
×
UNCOV
5381
    return code;
×
5382
  }
5383

5384
  TAOS_CHECK_RETURN(mndTransAppendRedolog(pTrans, pRedoRaw));
2,280✔
5385
  TAOS_CHECK_RETURN(sdbSetRawStatus(pRedoRaw, SDB_STATUS_DROPPING));
2,280✔
5386

5387
  TAOS_RETURN(code);
2,280✔
5388
}
5389

5390
static int32_t mndSetDropXnodeAgentCommitLogs(STrans *pTrans, SXnodeAgentObj *pObj) {
2,280✔
5391
  int32_t  code = 0;
2,280✔
5392
  SSdbRaw *pCommitRaw = mndXnodeAgentActionEncode(pObj);
2,280✔
5393
  if (pCommitRaw == NULL) {
2,280✔
UNCOV
5394
    code = terrno;
×
UNCOV
5395
    return code;
×
5396
  }
5397

5398
  TAOS_CHECK_RETURN(mndTransAppendCommitlog(pTrans, pCommitRaw));
2,280✔
5399
  TAOS_CHECK_RETURN(sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED));
2,280✔
5400
  TAOS_RETURN(code);
2,280✔
5401
}
5402

5403
static int32_t mndDropXnodeAgent(SMnode *pMnode, SRpcMsg *pReq, SXnodeAgentObj *pAgent) {
2,280✔
5404
  int32_t code = 0;
2,280✔
5405
  int32_t lino = 0;
2,280✔
5406

5407
  if (pAgent == NULL) {
2,280✔
UNCOV
5408
    mError("xnode agent fail to drop since pAgent is NULL");
×
UNCOV
5409
    code = TSDB_CODE_INVALID_PARA;
×
UNCOV
5410
    return code;
×
5411
  }
5412
  STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, pReq, "drop-xnode-agent");
2,280✔
5413
  TSDB_CHECK_NULL(pTrans, code, lino, _OVER, terrno);
2,280✔
5414
  mndTransSetSerial(pTrans);
2,280✔
5415
  mDebug("trans:%d, to drop xnode agent:%d", pTrans->id, pAgent->id);
2,280✔
5416

5417
  TAOS_CHECK_GOTO(mndSetDropXnodeAgentRedoLogs(pTrans, pAgent), NULL, _OVER);
2,280✔
5418
  TAOS_CHECK_GOTO(mndSetDropXnodeAgentCommitLogs(pTrans, pAgent), NULL, _OVER);
2,280✔
5419
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
2,280✔
5420

5421
_OVER:
2,280✔
5422
  mndTransDrop(pTrans);
2,280✔
5423
  TAOS_RETURN(code);
2,280✔
5424
}
5425

5426
static int32_t mndProcessDropXnodeAgentReq(SRpcMsg *pReq) {
2,400✔
5427
  SMnode             *pMnode = pReq->info.node;
2,400✔
5428
  int32_t             code = -1;
2,400✔
5429
  SXnodeAgentObj     *pObj = NULL;
2,400✔
5430
  SMDropXnodeAgentReq dropReq = {0};
2,400✔
5431

5432
  code = mndValidateXnodePermissions(pMnode, pReq, MND_OPER_DROP_XNODE_AGENT);
2,400✔
5433
  if (code != TSDB_CODE_SUCCESS) {
2,400✔
UNCOV
5434
    mError("failed check permission for drop xnode agent, code:%s", tstrerror(code));
×
UNCOV
5435
    goto _OVER;
×
5436
  }
5437
  TAOS_CHECK_GOTO(tDeserializeSMDropXnodeAgentReq(pReq->pCont, pReq->contLen, &dropReq), NULL, _OVER);
2,400✔
5438
  mDebug("xnode drop agent with id:%d, start to drop", dropReq.id);
2,400✔
5439

5440
  if (dropReq.id <= 0 && (dropReq.name.len <= 0 || dropReq.name.ptr == NULL)) {
2,400✔
UNCOV
5441
    code = TSDB_CODE_MND_XNODE_INVALID_MSG;
×
UNCOV
5442
    goto _OVER;
×
5443
  }
5444

5445
  if (dropReq.name.len > 0 && dropReq.name.ptr != NULL) {
2,400✔
5446
    pObj = mndAcquireXnodeAgentByName(pMnode, dropReq.name.ptr);
2,400✔
5447
  } else {
UNCOV
5448
    pObj = mndAcquireXnodeAgentById(pMnode, dropReq.id);
×
5449
  }
5450
  if (pObj == NULL) {
2,400✔
5451
    code = terrno;
120✔
5452
    goto _OVER;
120✔
5453
  }
5454

5455
  // send request to drop xnode task
5456
  char xnodeUrl[TSDB_XNODE_URL_LEN + 1] = {0};
2,280✔
5457
  snprintf(xnodeUrl, TSDB_XNODE_URL_LEN + 1, "%s/agent/%d", XNODED_PIPE_SOCKET_URL, pObj->id);
2,280✔
5458
  SJson *pJson = mndSendReqRetJson(xnodeUrl, HTTP_TYPE_DELETE, defaultTimeout, NULL, 0);
2,280✔
5459
  if (pJson) {
2,280✔
UNCOV
5460
    tjsonDelete(pJson);
×
5461
  }
5462

5463
  code = mndDropXnodeAgent(pMnode, pReq, pObj);
2,280✔
5464
  if (code == 0) {
2,280✔
5465
    code = TSDB_CODE_ACTION_IN_PROGRESS;
2,280✔
5466
  }
5467

5468
_OVER:
2,400✔
5469
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
2,400✔
5470
    mError("xnode task:%d, failed to drop since %s", dropReq.id, tstrerror(code));
120✔
5471
  }
5472
  mndReleaseXnodeAgent(pMnode, pObj);
2,400✔
5473
  tFreeSMDropXnodeAgentReq(&dropReq);
2,400✔
5474
  TAOS_RETURN(code);
2,400✔
5475
}
5476

5477
static int32_t mndRetrieveXnodeAgents(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
3,721✔
5478
  int32_t         code = 0;
3,721✔
5479
  SMnode         *pMnode = pReq->info.node;
3,721✔
5480
  SSdb           *pSdb = pMnode->pSdb;
3,721✔
5481
  int32_t         numOfRows = 0;
3,721✔
5482
  int32_t         cols = 0;
3,721✔
5483
  char            buf[VARSTR_HEADER_SIZE + TSDB_XNODE_AGENT_TOKEN_LEN];
3,721✔
5484
  SXnodeAgentObj *pObj = NULL;
3,721✔
5485

5486
  while (numOfRows < rows) {
10,681✔
5487
    pShow->pIter = sdbFetch(pSdb, SDB_XNODE_AGENT, pShow->pIter, (void **)&pObj);
10,681✔
5488
    if (pShow->pIter == NULL) break;
10,681✔
5489

5490
    cols = 0;
6,960✔
5491
    SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
6,960✔
5492
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->id, false);
6,960✔
5493
    if (code != 0) goto _end;
6,960✔
5494

5495
    STR_WITH_MAXSIZE_TO_VARSTR(buf, pObj->name, pShow->pMeta->pSchemas[cols].bytes);
6,960✔
5496
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
6,960✔
5497
    code = colDataSetVal(pColInfo, numOfRows, (const char *)buf, false);
6,960✔
5498
    if (code != 0) goto _end;
6,960✔
5499

5500
    if (pObj->tokenLen > 0) {
6,960✔
5501
      buf[0] = 0;
6,960✔
5502
      STR_WITH_MAXSIZE_TO_VARSTR(buf, pObj->token, pShow->pMeta->pSchemas[cols].bytes);
6,960✔
5503
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
6,960✔
5504
      code = colDataSetVal(pColInfo, numOfRows, (const char *)buf, false);
6,960✔
5505
      if (code != 0) goto _end;
6,960✔
5506
    } else {
UNCOV
5507
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
UNCOV
5508
      colDataSetNULL(pColInfo, numOfRows);
×
5509
    }
5510

5511
    if (pObj->statusLen > 0) {
6,960✔
5512
      buf[0] = 0;
5,400✔
5513
      STR_WITH_MAXSIZE_TO_VARSTR(buf, pObj->status, pShow->pMeta->pSchemas[cols].bytes);
5,400✔
5514
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
5,400✔
5515
      code = colDataSetVal(pColInfo, numOfRows, (const char *)buf, false);
5,400✔
5516
      if (code != 0) goto _end;
5,400✔
5517
    } else {
5518
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1,560✔
5519
      colDataSetNULL(pColInfo, numOfRows);
1,560✔
5520
    }
5521

5522
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
6,960✔
5523
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->createTime, false);
6,960✔
5524
    if (code != 0) goto _end;
6,960✔
5525

5526
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
6,960✔
5527
    code = colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->updateTime, false);
6,960✔
5528
    if (code != 0) goto _end;
6,960✔
5529

5530
    numOfRows++;
6,960✔
5531
    sdbRelease(pSdb, pObj);
6,960✔
5532
  }
5533

5534
_end:
3,721✔
5535
  if (code != 0) sdbRelease(pSdb, pObj);
3,721✔
5536

5537
  pShow->numOfRows += numOfRows;
3,721✔
5538
  return numOfRows;
3,721✔
5539
}
5540

UNCOV
5541
static void mndCancelGetNextXnodeAgent(SMnode *pMnode, void *pIter) {
×
UNCOV
5542
  SSdb *pSdb = pMnode->pSdb;
×
UNCOV
5543
  sdbCancelFetchByType(pSdb, pIter, SDB_XNODE_AGENT);
×
UNCOV
5544
}
×
5545

5546
/** xnoded mgmt section **/
5547

5548
void mndStartXnoded(SMnode *pMnode, const char *user, const char *pass, const char *token) {
1,080✔
5549
  int32_t   code = 0;
1,080✔
5550
  SXnodeOpt pOption = {0};
1,080✔
5551

5552
  if ((user == NULL || pass == NULL) && token == NULL) {
1,080✔
UNCOV
5553
    mError("xnode failed to start xnoded, dnode:%d", pMnode->selfDnodeId);
×
UNCOV
5554
    return;
×
5555
  }
5556

5557
  pOption.dnodeId = pMnode->selfDnodeId;
1,080✔
5558
  pOption.clusterId = pMnode->clusterId;
1,080✔
5559

5560
  SEpSet epset = mndGetDnodeEpsetById(pMnode, pMnode->selfDnodeId);
1,080✔
5561
  if (epset.numOfEps == 0) {
1,080✔
UNCOV
5562
    mError("xnode failed to start xnoded, dnode:%d", pMnode->selfDnodeId);
×
UNCOV
5563
    return;
×
5564
  }
5565
  pOption.ep = epset.eps[0];
1,080✔
5566
  // add user password
5567
  if (user != NULL && pass != NULL) {
1,080✔
5568
    pOption.upLen = strlen(user) + strlen(pass) + 1;
720✔
5569
    snprintf(pOption.userPass, XNODE_USER_PASS_LEN, "%s:%s", user, pass);
720✔
5570
  }
5571
  // add token
5572
  if (token != NULL) {
1,080✔
5573
    snprintf(pOption.token, sizeof(pOption.token), "%s", token);
360✔
5574
  }
5575
  if ((code = mndOpenXnd(&pOption)) != 0) {
1,080✔
5576
    mError("xnode failed to open xnd since %s, dnodeId:%d", tstrerror(code), pOption.dnodeId);
240✔
5577
    return;
240✔
5578
  }
5579
}
5580

5581
void mndXnodeHandleBecomeLeader(SMnode *pMnode) {
418,123✔
5582
  mInfo("mndxnode start to process mnode become leader");
418,123✔
5583
  SXnodeUserPassObj *pObj = mndAcquireFirstXnodeUserPass(pMnode);
418,123✔
5584
  if (pObj == NULL) {
418,123✔
5585
    mInfo("mndXnode become leader found no xnoded user pass");
418,123✔
5586
    return;
418,123✔
5587
  }
5588

UNCOV
5589
  mndStartXnoded(pMnode, pObj->user, pObj->pass, pObj->token);
×
UNCOV
5590
  mndReleaseXnodeUserPass(pMnode, pObj);
×
5591
}
5592

5593
void mndXnodeHandleBecomeNotLeader() {
58,709✔
5594
  mInfo("mndxnode handle mnode become not leader");
58,709✔
5595
  mndCloseXnd();
58,709✔
5596
}
58,709✔
5597

5598
void mndRestartXnoded(SMnode *pMnode) {
840✔
5599
  mInfo("mndxnode restart xnoded");
840✔
5600
  mndCloseXnd();
840✔
5601

5602
  taosMsleep(200);
840✔
5603
  SXnodeUserPassObj *pObj = mndAcquireFirstXnodeUserPass(pMnode);
840✔
5604
  if (pObj == NULL) {
840✔
UNCOV
5605
    mInfo("mndXnode restart found no xnoded user pass");
×
UNCOV
5606
    return;
×
5607
  }
5608
  mndStartXnoded(pMnode, pObj->user, pObj->pass, pObj->token);
840✔
5609
  mndReleaseXnodeUserPass(pMnode, pObj);
840✔
5610
  mInfo("mndxnode xnoded restarted");
840✔
5611
  return;
840✔
5612
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc