mndStream.c 47.9 KB
Newer Older
L
Liu Jicong 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include "mndStream.h"
#include "mndDb.h"
#include "mndDnode.h"
#include "mndMnode.h"
L
Liu Jicong 已提交
20
#include "mndPrivilege.h"
L
Liu Jicong 已提交
21
#include "mndScheduler.h"
L
Liu Jicong 已提交
22 23
#include "mndShow.h"
#include "mndStb.h"
L
Liu Jicong 已提交
24
#include "mndTopic.h"
L
Liu Jicong 已提交
25 26 27
#include "mndTrans.h"
#include "mndUser.h"
#include "mndVgroup.h"
L
Liu Jicong 已提交
28
#include "parser.h"
L
Liu Jicong 已提交
29 30
#include "tname.h"

31
#define MND_STREAM_VER_NUMBER   2
L
Liu Jicong 已提交
32 33
#define MND_STREAM_RESERVE_SIZE 64

34
#define MND_STREAM_MAX_NUM 60
L
Liu Jicong 已提交
35

L
Liu Jicong 已提交
36 37
static int32_t mndStreamActionInsert(SSdb *pSdb, SStreamObj *pStream);
static int32_t mndStreamActionDelete(SSdb *pSdb, SStreamObj *pStream);
38
static int32_t mndStreamActionUpdate(SSdb *pSdb, SStreamObj *pOldStream, SStreamObj *pNewStream);
S
Shengliang Guan 已提交
39
static int32_t mndProcessCreateStreamReq(SRpcMsg *pReq);
L
Liu Jicong 已提交
40
static int32_t mndProcessDropStreamReq(SRpcMsg *pReq);
41
static int32_t mndProcessStreamCheckpointTmr(SRpcMsg *pReq);
42 43
static int32_t mndProcessStreamDoCheckpoint(SRpcMsg *pReq);
static int32_t mndProcessRecoverStreamReq(SRpcMsg *pReq);
S
Shengliang Guan 已提交
44 45 46
static int32_t mndProcessStreamMetaReq(SRpcMsg *pReq);
static int32_t mndGetStreamMeta(SRpcMsg *pReq, SShowObj *pShow, STableMetaRsp *pMeta);
static int32_t mndRetrieveStream(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows);
L
Liu Jicong 已提交
47
static void    mndCancelGetNextStream(SMnode *pMnode, void *pIter);
48 49
static int32_t mndRetrieveStreamTask(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows);
static void    mndCancelGetNextStreamTask(SMnode *pMnode, void *pIter);
5
54liuyao 已提交
50 51
static int32_t mndProcessPauseStreamReq(SRpcMsg *pReq);
static int32_t mndProcessResumeStreamReq(SRpcMsg *pReq);
L
Liu Jicong 已提交
52 53

int32_t mndInitStream(SMnode *pMnode) {
54 55 56 57 58 59 60 61 62
  SSdbTable table = {
      .sdbType = SDB_STREAM,
      .keyType = SDB_KEY_BINARY,
      .encodeFp = (SdbEncodeFp)mndStreamActionEncode,
      .decodeFp = (SdbDecodeFp)mndStreamActionDecode,
      .insertFp = (SdbInsertFp)mndStreamActionInsert,
      .updateFp = (SdbUpdateFp)mndStreamActionUpdate,
      .deleteFp = (SdbDeleteFp)mndStreamActionDelete,
  };
L
Liu Jicong 已提交
63 64

  mndSetMsgHandle(pMnode, TDMT_MND_CREATE_STREAM, mndProcessCreateStreamReq);
L
Liu Jicong 已提交
65
  mndSetMsgHandle(pMnode, TDMT_MND_DROP_STREAM, mndProcessDropStreamReq);
L
Liu Jicong 已提交
66
  /*mndSetMsgHandle(pMnode, TDMT_MND_RECOVER_STREAM, mndProcessRecoverStreamReq);*/
L
Liu Jicong 已提交
67 68 69

  mndSetMsgHandle(pMnode, TDMT_STREAM_TASK_DEPLOY_RSP, mndTransProcessRsp);
  mndSetMsgHandle(pMnode, TDMT_STREAM_TASK_DROP_RSP, mndTransProcessRsp);
L
Liu Jicong 已提交
70

5
54liuyao 已提交
71 72
  // mndSetMsgHandle(pMnode, TDMT_MND_STREAM_CHECKPOINT_TIMER, mndProcessStreamCheckpointTmr);
  // mndSetMsgHandle(pMnode, TDMT_MND_STREAM_BEGIN_CHECKPOINT, mndProcessStreamDoCheckpoint);
73 74
  mndSetMsgHandle(pMnode, TDMT_STREAM_TASK_REPORT_CHECKPOINT, mndTransProcessRsp);

5
54liuyao 已提交
75 76 77
  mndSetMsgHandle(pMnode, TDMT_MND_PAUSE_STREAM, mndProcessPauseStreamReq);
  mndSetMsgHandle(pMnode, TDMT_MND_RESUME_STREAM, mndProcessResumeStreamReq);

L
Liu Jicong 已提交
78 79
  mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_STREAMS, mndRetrieveStream);
  mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_STREAMS, mndCancelGetNextStream);
80 81
  mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_STREAM_TASKS, mndRetrieveStreamTask);
  mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_STREAM_TASKS, mndCancelGetNextStreamTask);
L
Liu Jicong 已提交
82 83 84 85 86 87 88 89 90 91

  return sdbSetTable(pMnode->pSdb, table);
}

void mndCleanupStream(SMnode *pMnode) {}

SSdbRaw *mndStreamActionEncode(SStreamObj *pStream) {
  terrno = TSDB_CODE_OUT_OF_MEMORY;
  void *buf = NULL;

H
Hongze Cheng 已提交
92 93
  SEncoder encoder;
  tEncoderInit(&encoder, NULL, 0);
L
Liu Jicong 已提交
94
  if (tEncodeSStreamObj(&encoder, pStream) < 0) {
H
Hongze Cheng 已提交
95
    tEncoderClear(&encoder);
L
Liu Jicong 已提交
96 97 98
    goto STREAM_ENCODE_OVER;
  }
  int32_t tlen = encoder.pos;
H
Hongze Cheng 已提交
99
  tEncoderClear(&encoder);
L
Liu Jicong 已提交
100 101 102 103 104

  int32_t  size = sizeof(int32_t) + tlen + MND_STREAM_RESERVE_SIZE;
  SSdbRaw *pRaw = sdbAllocRaw(SDB_STREAM, MND_STREAM_VER_NUMBER, size);
  if (pRaw == NULL) goto STREAM_ENCODE_OVER;

wafwerar's avatar
wafwerar 已提交
105
  buf = taosMemoryMalloc(tlen);
L
Liu Jicong 已提交
106 107
  if (buf == NULL) goto STREAM_ENCODE_OVER;

H
Hongze Cheng 已提交
108
  tEncoderInit(&encoder, buf, tlen);
L
Liu Jicong 已提交
109
  if (tEncodeSStreamObj(&encoder, pStream) < 0) {
H
Hongze Cheng 已提交
110
    tEncoderClear(&encoder);
L
Liu Jicong 已提交
111 112
    goto STREAM_ENCODE_OVER;
  }
H
Hongze Cheng 已提交
113
  tEncoderClear(&encoder);
L
Liu Jicong 已提交
114 115 116 117 118 119 120 121 122

  int32_t dataPos = 0;
  SDB_SET_INT32(pRaw, dataPos, tlen, STREAM_ENCODE_OVER);
  SDB_SET_BINARY(pRaw, dataPos, buf, tlen, STREAM_ENCODE_OVER);
  SDB_SET_DATALEN(pRaw, dataPos, STREAM_ENCODE_OVER);

  terrno = TSDB_CODE_SUCCESS;

STREAM_ENCODE_OVER:
wafwerar's avatar
wafwerar 已提交
123
  taosMemoryFreeClear(buf);
L
Liu Jicong 已提交
124 125 126 127 128 129 130 131 132 133 134 135
  if (terrno != TSDB_CODE_SUCCESS) {
    mError("stream:%s, failed to encode to raw:%p since %s", pStream->name, pRaw, terrstr());
    sdbFreeRaw(pRaw);
    return NULL;
  }

  mTrace("stream:%s, encode to raw:%p, row:%p", pStream->name, pRaw, pStream);
  return pRaw;
}

SSdbRow *mndStreamActionDecode(SSdbRaw *pRaw) {
  terrno = TSDB_CODE_OUT_OF_MEMORY;
136 137 138
  SSdbRow    *pRow = NULL;
  SStreamObj *pStream = NULL;
  void       *buf = NULL;
L
Liu Jicong 已提交
139 140 141 142

  int8_t sver = 0;
  if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto STREAM_DECODE_OVER;

143
  if (sver != 1 && sver != 2) {
L
Liu Jicong 已提交
144 145 146 147
    terrno = TSDB_CODE_SDB_INVALID_DATA_VER;
    goto STREAM_DECODE_OVER;
  }

148
  pRow = sdbAllocRow(sizeof(SStreamObj));
L
Liu Jicong 已提交
149 150
  if (pRow == NULL) goto STREAM_DECODE_OVER;

151
  pStream = sdbGetRowObj(pRow);
L
Liu Jicong 已提交
152 153 154 155 156
  if (pStream == NULL) goto STREAM_DECODE_OVER;

  int32_t tlen;
  int32_t dataPos = 0;
  SDB_GET_INT32(pRaw, dataPos, &tlen, STREAM_DECODE_OVER);
wafwerar's avatar
wafwerar 已提交
157
  buf = taosMemoryMalloc(tlen + 1);
L
Liu Jicong 已提交
158 159 160
  if (buf == NULL) goto STREAM_DECODE_OVER;
  SDB_GET_BINARY(pRaw, dataPos, buf, tlen, STREAM_DECODE_OVER);

H
Hongze Cheng 已提交
161 162
  SDecoder decoder;
  tDecoderInit(&decoder, buf, tlen + 1);
163
  if (tDecodeSStreamObj(&decoder, pStream, sver) < 0) {
L
Liu Jicong 已提交
164
    tDecoderClear(&decoder);
L
Liu Jicong 已提交
165 166
    goto STREAM_DECODE_OVER;
  }
L
Liu Jicong 已提交
167
  tDecoderClear(&decoder);
L
Liu Jicong 已提交
168 169 170 171

  terrno = TSDB_CODE_SUCCESS;

STREAM_DECODE_OVER:
wafwerar's avatar
wafwerar 已提交
172
  taosMemoryFreeClear(buf);
L
Liu Jicong 已提交
173
  if (terrno != TSDB_CODE_SUCCESS) {
174 175
    mError("stream:%s, failed to decode from raw:%p since %s", pStream == NULL ? "null" : pStream->name, pRaw,
           terrstr());
wafwerar's avatar
wafwerar 已提交
176
    taosMemoryFreeClear(pRow);
L
Liu Jicong 已提交
177 178 179 180 181 182 183 184 185 186 187 188 189 190
    return NULL;
  }

  mTrace("stream:%s, decode from raw:%p, row:%p", pStream->name, pRaw, pStream);
  return pRow;
}

static int32_t mndStreamActionInsert(SSdb *pSdb, SStreamObj *pStream) {
  mTrace("stream:%s, perform insert action", pStream->name);
  return 0;
}

static int32_t mndStreamActionDelete(SSdb *pSdb, SStreamObj *pStream) {
  mTrace("stream:%s, perform delete action", pStream->name);
L
Liu Jicong 已提交
191 192 193
  taosWLockLatch(&pStream->lock);
  tFreeStreamObj(pStream);
  taosWUnLockLatch(&pStream->lock);
L
Liu Jicong 已提交
194 195 196 197 198
  return 0;
}

static int32_t mndStreamActionUpdate(SSdb *pSdb, SStreamObj *pOldStream, SStreamObj *pNewStream) {
  mTrace("stream:%s, perform update action", pOldStream->name);
wafwerar's avatar
wafwerar 已提交
199
  atomic_exchange_64(&pOldStream->updateTime, pNewStream->updateTime);
L
Liu Jicong 已提交
200 201 202 203
  atomic_exchange_32(&pOldStream->version, pNewStream->version);

  taosWLockLatch(&pOldStream->lock);

204
  pOldStream->status = pNewStream->status;
L
Liu Jicong 已提交
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223

  taosWUnLockLatch(&pOldStream->lock);
  return 0;
}

SStreamObj *mndAcquireStream(SMnode *pMnode, char *streamName) {
  SSdb       *pSdb = pMnode->pSdb;
  SStreamObj *pStream = sdbAcquire(pSdb, SDB_STREAM, streamName);
  if (pStream == NULL && terrno == TSDB_CODE_SDB_OBJ_NOT_THERE) {
    terrno = TSDB_CODE_MND_STREAM_NOT_EXIST;
  }
  return pStream;
}

void mndReleaseStream(SMnode *pMnode, SStreamObj *pStream) {
  SSdb *pSdb = pMnode->pSdb;
  sdbRelease(pSdb, pStream);
}

L
Liu Jicong 已提交
224 225 226 227 228 229 230 231 232 233
static void mndShowStreamStatus(char *dst, SStreamObj *pStream) {
  int8_t status = atomic_load_8(&pStream->status);
  if (status == STREAM_STATUS__NORMAL) {
    strcpy(dst, "normal");
  } else if (status == STREAM_STATUS__STOP) {
    strcpy(dst, "stop");
  } else if (status == STREAM_STATUS__FAILED) {
    strcpy(dst, "failed");
  } else if (status == STREAM_STATUS__RECOVER) {
    strcpy(dst, "recover");
5
54liuyao 已提交
234 235
  } else if (status == STREAM_STATUS__PAUSE) {
    strcpy(dst, "pause");
L
Liu Jicong 已提交
236 237 238 239 240 241 242 243 244 245 246 247 248 249
  }
}

static void mndShowStreamTrigger(char *dst, SStreamObj *pStream) {
  int8_t trigger = pStream->trigger;
  if (trigger == STREAM_TRIGGER_AT_ONCE) {
    strcpy(dst, "at once");
  } else if (trigger == STREAM_TRIGGER_WINDOW_CLOSE) {
    strcpy(dst, "window close");
  } else if (trigger == STREAM_TRIGGER_MAX_DELAY) {
    strcpy(dst, "max delay");
  }
}

L
Liu Jicong 已提交
250
static int32_t mndCheckCreateStreamReq(SCMCreateStreamReq *pCreate) {
L
Liu Jicong 已提交
251 252
  if (pCreate->name[0] == 0 || pCreate->sql == NULL || pCreate->sql[0] == 0 || pCreate->sourceDB[0] == 0 ||
      pCreate->targetStbFullName[0] == 0) {
L
Liu Jicong 已提交
253 254 255 256 257 258
    terrno = TSDB_CODE_MND_INVALID_STREAM_OPTION;
    return -1;
  }
  return 0;
}

X
Xiaoyu Wang 已提交
259
static int32_t mndStreamGetPlanString(const char *ast, int8_t triggerType, int64_t watermark, char **pStr) {
S
sma  
Shengliang Guan 已提交
260
  if (NULL == ast) {
L
Liu Jicong 已提交
261 262 263 264
    return TSDB_CODE_SUCCESS;
  }

  SNode  *pAst = NULL;
S
sma  
Shengliang Guan 已提交
265
  int32_t code = nodesStringToNode(ast, &pAst);
L
Liu Jicong 已提交
266 267 268 269 270 271 272

  SQueryPlan *pPlan = NULL;
  if (TSDB_CODE_SUCCESS == code) {
    SPlanContext cxt = {
        .pAstRoot = pAst,
        .topicQuery = false,
        .streamQuery = true,
273
        .triggerType = triggerType == STREAM_TRIGGER_MAX_DELAY ? STREAM_TRIGGER_WINDOW_CLOSE : triggerType,
X
Xiaoyu Wang 已提交
274
        .watermark = watermark,
L
Liu Jicong 已提交
275 276 277 278 279
    };
    code = qCreateQueryPlan(&cxt, &pPlan, NULL);
  }

  if (TSDB_CODE_SUCCESS == code) {
280
    code = nodesNodeToString((SNode *)pPlan, false, pStr, NULL);
L
Liu Jicong 已提交
281 282
  }
  nodesDestroyNode(pAst);
283
  nodesDestroyNode((SNode *)pPlan);
L
Liu Jicong 已提交
284 285 286 287
  terrno = code;
  return code;
}

L
Liu Jicong 已提交
288
static int32_t mndBuildStreamObjFromCreateReq(SMnode *pMnode, SStreamObj *pObj, SCMCreateStreamReq *pCreate) {
289 290
  SNode      *pAst = NULL;
  SQueryPlan *pPlan = NULL;
L
Liu Jicong 已提交
291

292
  mInfo("stream:%s to create", pCreate->name);
L
Liu Jicong 已提交
293 294 295 296 297 298 299 300 301
  memcpy(pObj->name, pCreate->name, TSDB_STREAM_FNAME_LEN);
  pObj->createTime = taosGetTimestampMs();
  pObj->updateTime = pObj->createTime;
  pObj->version = 1;
  pObj->smaId = 0;

  pObj->uid = mndGenerateUid(pObj->name, strlen(pObj->name));
  pObj->status = 0;

302
  pObj->igExpired = pCreate->igExpired;
L
Liu Jicong 已提交
303 304 305
  pObj->trigger = pCreate->triggerType;
  pObj->triggerParam = pCreate->maxDelay;
  pObj->watermark = pCreate->watermark;
L
Liu Jicong 已提交
306
  pObj->fillHistory = pCreate->fillHistory;
5
54liuyao 已提交
307
  pObj->deleteMark = pCreate->deleteMark;
308
  pObj->igCheckUpdate = pCreate->igUpdate;
L
Liu Jicong 已提交
309 310 311 312

  memcpy(pObj->sourceDb, pCreate->sourceDB, TSDB_DB_FNAME_LEN);
  SDbObj *pSourceDb = mndAcquireDb(pMnode, pCreate->sourceDB);
  if (pSourceDb == NULL) {
313
    mInfo("stream:%s failed to create, source db %s not exist since %s", pCreate->name, pObj->sourceDb, terrstr());
L
Liu Jicong 已提交
314 315 316
    return -1;
  }
  pObj->sourceDbUid = pSourceDb->uid;
317
  mndReleaseDb(pMnode, pSourceDb);
L
Liu Jicong 已提交
318 319 320 321 322

  memcpy(pObj->targetSTbName, pCreate->targetStbFullName, TSDB_TABLE_FNAME_LEN);

  SDbObj *pTargetDb = mndAcquireDbByStb(pMnode, pObj->targetSTbName);
  if (pTargetDb == NULL) {
323
    mInfo("stream:%s failed to create, target db %s not exist since %s", pCreate->name, pObj->targetDb, terrstr());
L
Liu Jicong 已提交
324 325 326 327
    return -1;
  }
  tstrncpy(pObj->targetDb, pTargetDb->name, TSDB_DB_FNAME_LEN);

328 329 330 331 332
  if (pCreate->createStb == STREAM_CREATE_STABLE_TRUE) {
    pObj->targetStbUid = mndGenerateUid(pObj->targetSTbName, TSDB_TABLE_FNAME_LEN);
  } else {
    pObj->targetStbUid = pCreate->targetStbUid;
  }
L
Liu Jicong 已提交
333
  pObj->targetDbUid = pTargetDb->uid;
334
  mndReleaseDb(pMnode, pTargetDb);
L
Liu Jicong 已提交
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351

  pObj->sql = pCreate->sql;
  pObj->ast = pCreate->ast;

  pCreate->sql = NULL;
  pCreate->ast = NULL;

  // deserialize ast
  if (nodesStringToNode(pObj->ast, &pAst) < 0) {
    goto FAIL;
  }

  // extract output schema from ast
  if (qExtractResultSchema(pAst, (int32_t *)&pObj->outputSchema.nCols, &pObj->outputSchema.pSchema) != 0) {
    goto FAIL;
  }

352
  int32_t numOfNULL = taosArrayGetSize(pCreate->fillNullCols);
X
Xiaoyu Wang 已提交
353
  if (numOfNULL > 0) {
354
    pObj->outputSchema.nCols += numOfNULL;
X
Xiaoyu Wang 已提交
355
    SSchema *pFullSchema = taosMemoryCalloc(pObj->outputSchema.nCols, sizeof(SSchema));
356 357 358 359 360 361 362
    if (!pFullSchema) {
      goto FAIL;
    }

    int32_t nullIndex = 0;
    int32_t dataIndex = 0;
    for (int16_t i = 0; i < pObj->outputSchema.nCols; i++) {
X
Xiaoyu Wang 已提交
363
      SColLocation *pos = taosArrayGet(pCreate->fillNullCols, nullIndex);
5
54liuyao 已提交
364
      if (nullIndex >= numOfNULL || i < pos->slotId) {
365
        pFullSchema[i].bytes = pObj->outputSchema.pSchema[dataIndex].bytes;
X
Xiaoyu Wang 已提交
366
        pFullSchema[i].colId = i + 1;  // pObj->outputSchema.pSchema[dataIndex].colId;
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
        pFullSchema[i].flags = pObj->outputSchema.pSchema[dataIndex].flags;
        strcpy(pFullSchema[i].name, pObj->outputSchema.pSchema[dataIndex].name);
        pFullSchema[i].type = pObj->outputSchema.pSchema[dataIndex].type;
        dataIndex++;
      } else {
        pFullSchema[i].bytes = 0;
        pFullSchema[i].colId = pos->colId;
        pFullSchema[i].flags = COL_SET_NULL;
        memset(pFullSchema[i].name, 0, TSDB_COL_NAME_LEN);
        pFullSchema[i].type = pos->type;
        nullIndex++;
      }
    }
    taosMemoryFree(pObj->outputSchema.pSchema);
    pObj->outputSchema.pSchema = pFullSchema;
  }

L
Liu Jicong 已提交
384 385 386 387 388 389
  SPlanContext cxt = {
      .pAstRoot = pAst,
      .topicQuery = false,
      .streamQuery = true,
      .triggerType = pObj->trigger == STREAM_TRIGGER_MAX_DELAY ? STREAM_TRIGGER_WINDOW_CLOSE : pObj->trigger,
      .watermark = pObj->watermark,
390
      .igExpired = pObj->igExpired,
5
54liuyao 已提交
391
      .deleteMark = pObj->deleteMark,
392
      .igCheckUpdate = pObj->igCheckUpdate,
L
Liu Jicong 已提交
393 394 395 396 397 398 399 400 401 402 403 404
  };

  // using ast and param to build physical plan
  if (qCreateQueryPlan(&cxt, &pPlan, NULL) < 0) {
    goto FAIL;
  }

  // save physcial plan
  if (nodesNodeToString((SNode *)pPlan, false, &pObj->physicalPlan, NULL) != 0) {
    goto FAIL;
  }

405 406 407 408
  pObj->tagSchema.nCols = pCreate->numOfTags;
  if (pCreate->numOfTags) {
    pObj->tagSchema.pSchema = taosMemoryCalloc(pCreate->numOfTags, sizeof(SSchema));
  }
L
Liu Jicong 已提交
409
  /*A(pCreate->numOfTags == taosArrayGetSize(pCreate->pTags));*/
410 411 412 413 414 415 416 417 418
  for (int32_t i = 0; i < pCreate->numOfTags; i++) {
    SField *pField = taosArrayGet(pCreate->pTags, i);
    pObj->tagSchema.pSchema[i].colId = pObj->outputSchema.nCols + i + 1;
    pObj->tagSchema.pSchema[i].bytes = pField->bytes;
    pObj->tagSchema.pSchema[i].flags = pField->flags;
    pObj->tagSchema.pSchema[i].type = pField->type;
    memcpy(pObj->tagSchema.pSchema[i].name, pField->name, TSDB_COL_NAME_LEN);
  }

L
Liu Jicong 已提交
419 420
FAIL:
  if (pAst != NULL) nodesDestroyNode(pAst);
421
  if (pPlan != NULL) qDestroyQueryPlan(pPlan);
L
Liu Jicong 已提交
422 423 424
  return 0;
}

425 426 427
int32_t mndPersistTaskDeployReq(STrans *pTrans, const SStreamTask *pTask) {
  SEncoder encoder;
  tEncoderInit(&encoder, NULL, 0);
428
  tEncodeStreamTask(&encoder, pTask);
429 430 431 432 433 434
  int32_t size = encoder.pos;
  int32_t tlen = sizeof(SMsgHead) + size;
  tEncoderClear(&encoder);
  void *buf = taosMemoryCalloc(1, tlen);
  if (buf == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
L
Liu Jicong 已提交
435 436
    return -1;
  }
437 438 439
  ((SMsgHead *)buf)->vgId = htonl(pTask->nodeId);
  void *abuf = POINTER_SHIFT(buf, sizeof(SMsgHead));
  tEncoderInit(&encoder, abuf, size);
440
  tEncodeStreamTask(&encoder, pTask);
441
  tEncoderClear(&encoder);
L
Liu Jicong 已提交
442

443
  STransAction action = {0};
dengyihao's avatar
dengyihao 已提交
444
  action.mTraceId = pTrans->mTraceId;
445 446 447 448 449 450
  memcpy(&action.epSet, &pTask->epSet, sizeof(SEpSet));
  action.pCont = buf;
  action.contLen = tlen;
  action.msgType = TDMT_STREAM_TASK_DEPLOY;
  if (mndTransAppendRedoAction(pTrans, &action) != 0) {
    taosMemoryFree(buf);
L
Liu Jicong 已提交
451 452 453 454 455
    return -1;
  }
  return 0;
}

456 457 458 459 460 461 462 463 464 465 466
int32_t mndPersistStreamTasks(SMnode *pMnode, STrans *pTrans, SStreamObj *pStream) {
  int32_t level = taosArrayGetSize(pStream->tasks);
  for (int32_t i = 0; i < level; i++) {
    SArray *pLevel = taosArrayGetP(pStream->tasks, i);
    int32_t sz = taosArrayGetSize(pLevel);
    for (int32_t j = 0; j < sz; j++) {
      SStreamTask *pTask = taosArrayGetP(pLevel, j);
      if (mndPersistTaskDeployReq(pTrans, pTask) < 0) {
        return -1;
      }
    }
L
Liu Jicong 已提交
467
  }
468 469
  return 0;
}
L
Liu Jicong 已提交
470

471 472
int32_t mndPersistStream(SMnode *pMnode, STrans *pTrans, SStreamObj *pStream) {
  if (mndPersistStreamTasks(pMnode, pTrans, pStream) < 0) {
L
Liu Jicong 已提交
473 474
    return -1;
  }
475 476 477
  SSdbRaw *pCommitRaw = mndStreamActionEncode(pStream);
  if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
    mError("trans:%d, failed to append commit log since %s", pTrans->id, terrstr());
L
Liu Jicong 已提交
478 479
    return -1;
  }
S
Shengliang Guan 已提交
480
  (void)sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY);
481 482
  return 0;
}
L
Liu Jicong 已提交
483

484
int32_t mndPersistDropStreamLog(SMnode *pMnode, STrans *pTrans, SStreamObj *pStream) {
485 486 487
  SSdbRaw *pCommitRaw = mndStreamActionEncode(pStream);
  if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
    mError("trans:%d, failed to append commit log since %s", pTrans->id, terrstr());
L
Liu Jicong 已提交
488 489 490
    mndTransDrop(pTrans);
    return -1;
  }
S
Shengliang Guan 已提交
491
  (void)sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED);
S
sma  
Shengliang Guan 已提交
492 493 494
  return 0;
}

495 496 497 498
static int32_t mndSetStreamRecover(SMnode *pMnode, STrans *pTrans, const SStreamObj *pStream) {
  SStreamObj streamObj = {0};
  memcpy(streamObj.name, pStream->name, TSDB_STREAM_FNAME_LEN);
  streamObj.status = STREAM_STATUS__RECOVER;
S
Shengliang Guan 已提交
499

500
  SSdbRaw *pCommitRaw = mndStreamActionEncode(&streamObj);
S
Shengliang Guan 已提交
501 502
  if (pCommitRaw == NULL) return -1;
  if (mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
503 504 505 506
    mError("stream trans:%d, failed to append commit log since %s", pTrans->id, terrstr());
    mndTransDrop(pTrans);
    return -1;
  }
S
Shengliang Guan 已提交
507
  (void)sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY);
508 509 510
  return 0;
}

L
Liu Jicong 已提交
511
static int32_t mndCreateStbForStream(SMnode *pMnode, STrans *pTrans, const SStreamObj *pStream, const char *user) {
L
Liu Jicong 已提交
512 513
  SStbObj *pStb = NULL;
  SDbObj  *pDb = NULL;
514 515 516 517 518

  SMCreateStbReq createReq = {0};
  tstrncpy(createReq.name, pStream->targetSTbName, TSDB_TABLE_FNAME_LEN);
  createReq.numOfColumns = pStream->outputSchema.nCols;
  createReq.numOfTags = 1;  // group id
519
  createReq.pColumns = taosArrayInit_s(sizeof(SField), createReq.numOfColumns);
520
  // build fields
L
Liu Jicong 已提交
521 522 523 524 525 526 527
  for (int32_t i = 0; i < createReq.numOfColumns; i++) {
    SField *pField = taosArrayGet(createReq.pColumns, i);
    tstrncpy(pField->name, pStream->outputSchema.pSchema[i].name, TSDB_COL_NAME_LEN);
    pField->flags = pStream->outputSchema.pSchema[i].flags;
    pField->type = pStream->outputSchema.pSchema[i].type;
    pField->bytes = pStream->outputSchema.pSchema[i].bytes;
  }
5
54liuyao 已提交
528 529 530

  if (pStream->tagSchema.nCols == 0) {
    createReq.numOfTags = 1;
X
Xiaoyu Wang 已提交
531
    createReq.pTags = taosArrayInit_s(sizeof(SField), 1);
5
54liuyao 已提交
532 533 534 535 536 537 538 539
    // build tags
    SField *pField = taosArrayGet(createReq.pTags, 0);
    strcpy(pField->name, "group_id");
    pField->type = TSDB_DATA_TYPE_UBIGINT;
    pField->flags = 0;
    pField->bytes = 8;
  } else {
    createReq.numOfTags = pStream->tagSchema.nCols;
X
Xiaoyu Wang 已提交
540
    createReq.pTags = taosArrayInit_s(sizeof(SField), createReq.numOfTags);
5
54liuyao 已提交
541 542 543 544 545 546 547 548
    for (int32_t i = 0; i < createReq.numOfTags; i++) {
      SField *pField = taosArrayGet(createReq.pTags, i);
      pField->bytes = pStream->tagSchema.pSchema[i].bytes;
      pField->flags = pStream->tagSchema.pSchema[i].flags;
      pField->type = pStream->tagSchema.pSchema[i].type;
      tstrncpy(pField->name, pStream->tagSchema.pSchema[i].name, TSDB_COL_NAME_LEN);
    }
  }
549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566

  if (mndCheckCreateStbReq(&createReq) != 0) {
    goto _OVER;
  }

  pStb = mndAcquireStb(pMnode, createReq.name);
  if (pStb != NULL) {
    terrno = TSDB_CODE_MND_STB_ALREADY_EXIST;
    goto _OVER;
  }

  pDb = mndAcquireDbByStb(pMnode, createReq.name);
  if (pDb == NULL) {
    terrno = TSDB_CODE_MND_DB_NOT_SELECTED;
    goto _OVER;
  }

  int32_t numOfStbs = -1;
S
Shengliang Guan 已提交
567 568 569 570
  if (mndGetNumOfStbs(pMnode, pDb->name, &numOfStbs) != 0) {
    goto _OVER;
  }

571 572 573 574 575 576 577 578 579 580 581
  if (pDb->cfg.numOfStables == 1 && numOfStbs != 0) {
    terrno = TSDB_CODE_MND_SINGLE_STB_MODE_DB;
    goto _OVER;
  }

  SStbObj stbObj = {0};

  if (mndBuildStbFromReq(pMnode, &stbObj, &createReq, pDb) != 0) {
    goto _OVER;
  }

L
Liu Jicong 已提交
582 583
  stbObj.uid = pStream->targetStbUid;

L
Liu Jicong 已提交
584 585 586 587 588 589 590
  if (mndAddStbToTrans(pMnode, pTrans, pDb, &stbObj) < 0) {
    mndFreeStb(&stbObj);
    goto _OVER;
  }

  tFreeSMCreateStbReq(&createReq);
  mndFreeStb(&stbObj);
S
Shengliang Guan 已提交
591
  mndReleaseStb(pMnode, pStb);
592
  mndReleaseDb(pMnode, pDb);
593

L
Liu Jicong 已提交
594
  return 0;
595
_OVER:
L
Liu Jicong 已提交
596
  tFreeSMCreateStbReq(&createReq);
597 598
  mndReleaseStb(pMnode, pStb);
  mndReleaseDb(pMnode, pDb);
L
Liu Jicong 已提交
599
  return -1;
600 601
}

L
Liu Jicong 已提交
602 603
static int32_t mndPersistTaskDropReq(STrans *pTrans, SStreamTask *pTask) {
  // vnode
L
Liu Jicong 已提交
604 605 606 607 608 609 610
  /*if (pTask->nodeId > 0) {*/
  SVDropStreamTaskReq *pReq = taosMemoryCalloc(1, sizeof(SVDropStreamTaskReq));
  if (pReq == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return -1;
  }
  pReq->head.vgId = htonl(pTask->nodeId);
611
  pReq->taskId = pTask->id.taskId;
L
Liu Jicong 已提交
612 613 614 615
  STransAction action = {0};
  memcpy(&action.epSet, &pTask->epSet, sizeof(SEpSet));
  action.pCont = pReq;
  action.contLen = sizeof(SVDropStreamTaskReq);
L
Liu Jicong 已提交
616
  action.msgType = TDMT_STREAM_TASK_DROP;
L
Liu Jicong 已提交
617 618 619
  if (mndTransAppendRedoAction(pTrans, &action) != 0) {
    taosMemoryFree(pReq);
    return -1;
L
Liu Jicong 已提交
620
  }
L
Liu Jicong 已提交
621
  /*}*/
L
Liu Jicong 已提交
622 623 624 625

  return 0;
}

L
Liu Jicong 已提交
626
int32_t mndDropStreamTasks(SMnode *pMnode, STrans *pTrans, SStreamObj *pStream) {
L
Liu Jicong 已提交
627 628 629 630 631 632 633 634 635 636 637 638 639 640
  int32_t lv = taosArrayGetSize(pStream->tasks);
  for (int32_t i = 0; i < lv; i++) {
    SArray *pTasks = taosArrayGetP(pStream->tasks, i);
    int32_t sz = taosArrayGetSize(pTasks);
    for (int32_t j = 0; j < sz; j++) {
      SStreamTask *pTask = taosArrayGetP(pTasks, j);
      if (mndPersistTaskDropReq(pTrans, pTask) < 0) {
        return -1;
      }
    }
  }
  return 0;
}

S
Shengliang Guan 已提交
641 642
static int32_t mndProcessCreateStreamReq(SRpcMsg *pReq) {
  SMnode            *pMnode = pReq->info.node;
L
Liu Jicong 已提交
643 644 645 646
  int32_t            code = -1;
  SStreamObj        *pStream = NULL;
  SDbObj            *pDb = NULL;
  SCMCreateStreamReq createStreamReq = {0};
647
  SStreamObj         streamObj = {0};
L
Liu Jicong 已提交
648

S
Shengliang Guan 已提交
649
  if (tDeserializeSCMCreateStreamReq(pReq->pCont, pReq->contLen, &createStreamReq) != 0) {
L
Liu Jicong 已提交
650
    terrno = TSDB_CODE_INVALID_MSG;
651
    goto _OVER;
L
Liu Jicong 已提交
652 653
  }

654
  mInfo("stream:%s, start to create, sql:%s", createStreamReq.name, createStreamReq.sql);
L
Liu Jicong 已提交
655 656 657

  if (mndCheckCreateStreamReq(&createStreamReq) != 0) {
    mError("stream:%s, failed to create since %s", createStreamReq.name, terrstr());
658
    goto _OVER;
L
Liu Jicong 已提交
659 660 661 662 663
  }

  pStream = mndAcquireStream(pMnode, createStreamReq.name);
  if (pStream != NULL) {
    if (createStreamReq.igExists) {
664
      mInfo("stream:%s, already exist, ignore exist is set", createStreamReq.name);
L
Liu Jicong 已提交
665
      code = 0;
666
      goto _OVER;
L
Liu Jicong 已提交
667 668
    } else {
      terrno = TSDB_CODE_MND_STREAM_ALREADY_EXIST;
669
      goto _OVER;
L
Liu Jicong 已提交
670 671
    }
  } else if (terrno != TSDB_CODE_MND_STREAM_NOT_EXIST) {
672
    goto _OVER;
L
Liu Jicong 已提交
673 674
  }

L
Liu Jicong 已提交
675 676 677 678 679 680
  // build stream obj from request
  if (mndBuildStreamObjFromCreateReq(pMnode, &streamObj, &createStreamReq) < 0) {
    mError("stream:%s, failed to create since %s", createStreamReq.name, terrstr());
    goto _OVER;
  }

L
Liu Jicong 已提交
681 682 683 684 685 686 687 688 689 690
  {
    int32_t numOfStream = 0;

    SStreamObj *pStream = NULL;
    void       *pIter = NULL;

    while (1) {
      pIter = sdbFetch(pMnode->pSdb, SDB_STREAM, pIter, (void **)&pStream);
      if (pIter == NULL) {
        if (numOfStream > MND_STREAM_MAX_NUM) {
691
          mError("too many streams, no more than %d for each database", MND_STREAM_MAX_NUM);
L
Liu Jicong 已提交
692 693 694 695 696 697 698 699 700
          terrno = TSDB_CODE_MND_TOO_MANY_STREAMS;
          goto _OVER;
        }
        break;
      }

      if (pStream->sourceDbUid == streamObj.sourceDbUid) {
        ++numOfStream;
      }
L
Liu Jicong 已提交
701
      sdbRelease(pMnode->pSdb, pStream);
L
Liu Jicong 已提交
702
      if (numOfStream > MND_STREAM_MAX_NUM) {
703
        mError("too many streams, no more than %d for each database", MND_STREAM_MAX_NUM);
L
Liu Jicong 已提交
704 705 706
        terrno = TSDB_CODE_MND_TOO_MANY_STREAMS;
        goto _OVER;
      }
5
54liuyao 已提交
707 708 709 710 711 712

      if (pStream->targetStbUid == streamObj.targetStbUid) {
        mError("Cannot write the same stable as other stream:%s", pStream->name);
        terrno = TSDB_CODE_MND_INVALID_TARGET_TABLE;
        goto _OVER;
      }
L
Liu Jicong 已提交
713 714 715
    }
  }

716 717 718 719 720 721 722 723
  pDb = mndAcquireDb(pMnode, streamObj.sourceDb);
  if (pDb->cfg.replications != 1) {
    mError("stream source db must have only 1 replica, but %s has %d", pDb->name, pDb->cfg.replications);
    terrno = TSDB_CODE_MND_MULTI_REPLICA_SOURCE_DB;
    mndReleaseDb(pMnode, pDb);
    pDb = NULL;
    goto _OVER;
  }
724
  mndReleaseDb(pMnode, pDb);
725

726
  STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_DB_INSIDE, pReq, "create-stream");
727 728 729 730
  if (pTrans == NULL) {
    mError("stream:%s, failed to create since %s", createStreamReq.name, terrstr());
    goto _OVER;
  }
731
  mInfo("trans:%d, used to create stream:%s", pTrans->id, createStreamReq.name);
732

733
  mndTransSetDbName(pTrans, createStreamReq.sourceDB, streamObj.targetDb);
M
Minglei Jin 已提交
734 735 736 737
  if (mndTrancCheckConflict(pMnode, pTrans) != 0) {
    mndTransDrop(pTrans);
    goto _OVER;
  }
L
Liu Jicong 已提交
738
  // create stb for stream
X
Xiaoyu Wang 已提交
739 740
  if (createStreamReq.createStb == STREAM_CREATE_STABLE_TRUE &&
      mndCreateStbForStream(pMnode, pTrans, &streamObj, pReq->info.conn.user) < 0) {
L
Liu Jicong 已提交
741 742 743 744 745
    mError("trans:%d, failed to create stb for stream %s since %s", pTrans->id, createStreamReq.name, terrstr());
    mndTransDrop(pTrans);
    goto _OVER;
  }

L
Liu Jicong 已提交
746
  // schedule stream task for stream obj
747
  if (mndScheduleStream(pMnode, &streamObj) < 0) {
L
Liu Jicong 已提交
748 749 750 751 752
    mError("stream:%s, failed to schedule since %s", createStreamReq.name, terrstr());
    mndTransDrop(pTrans);
    goto _OVER;
  }

L
Liu Jicong 已提交
753
  // add stream to trans
L
Liu Jicong 已提交
754 755 756 757 758 759
  if (mndPersistStream(pMnode, pTrans, &streamObj) < 0) {
    mError("stream:%s, failed to schedule since %s", createStreamReq.name, terrstr());
    mndTransDrop(pTrans);
    goto _OVER;
  }

760 761 762 763 764 765 766 767 768 769
  if (mndCheckDbPrivilegeByName(pMnode, pReq->info.conn.user, MND_OPER_READ_DB, streamObj.sourceDb) != 0) {
    mndTransDrop(pTrans);
    goto _OVER;
  }

  if (mndCheckDbPrivilegeByName(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, streamObj.targetDb) != 0) {
    mndTransDrop(pTrans);
    goto _OVER;
  }

L
Liu Jicong 已提交
770
  // execute creation
L
Liu Jicong 已提交
771 772 773 774 775
  if (mndTransPrepare(pMnode, pTrans) != 0) {
    mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr());
    mndTransDrop(pTrans);
    goto _OVER;
  }
L
Liu Jicong 已提交
776

L
Liu Jicong 已提交
777 778 779
  mndTransDrop(pTrans);

  code = TSDB_CODE_ACTION_IN_PROGRESS;
L
Liu Jicong 已提交
780

781
_OVER:
S
Shengliang Guan 已提交
782
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
L
Liu Jicong 已提交
783 784 785 786 787 788
    mError("stream:%s, failed to create since %s", createStreamReq.name, terrstr());
  }

  mndReleaseStream(pMnode, pStream);

  tFreeSCMCreateStreamReq(&createStreamReq);
L
Liu Jicong 已提交
789
  tFreeStreamObj(&streamObj);
L
Liu Jicong 已提交
790 791
  return code;
}
5
54liuyao 已提交
792 793 794

#if 0

795
static int32_t mndProcessStreamCheckpointTmr(SRpcMsg *pReq) {
L
Liu Jicong 已提交
796
  SMnode     *pMnode = pReq->info.node;
797 798
  SSdb       *pSdb = pMnode->pSdb;
  void       *pIter = NULL;
L
Liu Jicong 已提交
799 800
  SStreamObj *pStream = NULL;

801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823
  // iterate all stream obj
  while (1) {
    pIter = sdbFetch(pSdb, SDB_STREAM, pIter, (void **)&pStream);
    if (pIter == NULL) break;
    // incr tick
    int64_t currentTick = atomic_add_fetch_64(&pStream->currentTick, 1);
    // if >= checkpointFreq, build msg TDMT_MND_STREAM_BEGIN_CHECKPOINT, put into write q
    if (currentTick >= pStream->checkpointFreq) {
      atomic_store_64(&pStream->currentTick, 0);
      SMStreamDoCheckpointMsg *pMsg = rpcMallocCont(sizeof(SMStreamDoCheckpointMsg));

      pMsg->streamId = pStream->uid;
      pMsg->checkpointId = tGenIdPI64();
      memcpy(pMsg->streamName, pStream->name, TSDB_STREAM_FNAME_LEN);

      SRpcMsg rpcMsg = {
          .msgType = TDMT_MND_STREAM_BEGIN_CHECKPOINT,
          .pCont = pMsg,
          .contLen = sizeof(SMStreamDoCheckpointMsg),
      };

      tmsgPutToQueue(&pMnode->msgCb, WRITE_QUEUE, &rpcMsg);
    }
L
Liu Jicong 已提交
824
  }
L
Liu Jicong 已提交
825

826 827
  return 0;
}
L
Liu Jicong 已提交
828

829 830 831 832 833 834 835 836
static int32_t mndBuildStreamCheckpointSourceReq(void **pBuf, int32_t *pLen, const SStreamTask *pTask,
                                                 SMStreamDoCheckpointMsg *pMsg) {
  SStreamCheckpointSourceReq req = {0};
  req.checkpointId = pMsg->checkpointId;
  req.nodeId = pTask->nodeId;
  req.expireTime = -1;
  req.streamId = pTask->streamId;
  req.taskId = pTask->taskId;
L
Liu Jicong 已提交
837

838 839 840 841 842 843
  int32_t code;
  int32_t blen;

  tEncodeSize(tEncodeSStreamCheckpointSourceReq, &req, blen, code);
  if (code < 0) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
844
    return -1;
L
Liu Jicong 已提交
845 846
  }

847 848 849 850 851
  int32_t tlen = sizeof(SMsgHead) + blen;

  void *buf = taosMemoryMalloc(tlen);
  if (buf == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
L
Liu Jicong 已提交
852
    return -1;
L
Liu Jicong 已提交
853 854
  }

855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881
  void    *abuf = POINTER_SHIFT(buf, sizeof(SMsgHead));
  SEncoder encoder;
  tEncoderInit(&encoder, abuf, tlen);
  tEncodeSStreamCheckpointSourceReq(&encoder, &req);

  SMsgHead *pMsgHead = (SMsgHead *)buf;
  pMsgHead->contLen = htonl(tlen);
  pMsgHead->vgId = htonl(pTask->nodeId);

  tEncoderClear(&encoder);

  *pBuf = buf;
  *pLen = tlen;

  return 0;
}

static int32_t mndProcessStreamDoCheckpoint(SRpcMsg *pReq) {
  SMnode *pMnode = pReq->info.node;
  SSdb   *pSdb = pMnode->pSdb;

  SMStreamDoCheckpointMsg *pMsg = (SMStreamDoCheckpointMsg *)pReq->pCont;

  SStreamObj *pStream = mndAcquireStream(pMnode, pMsg->streamName);

  if (pStream == NULL || pStream->uid != pMsg->streamId) {
    mError("start checkpointing failed since stream %s not found", pMsg->streamName);
L
Liu Jicong 已提交
882
    return -1;
L
Liu Jicong 已提交
883 884
  }

885 886 887 888
  // build new transaction:
  STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB_INSIDE, pReq, "stream-checkpoint");
  if (pTrans == NULL) return -1;
  mndTransSetDbName(pTrans, pStream->sourceDb, pStream->targetDb);
889 890 891 892 893 894
  if (mndTrancCheckConflict(pMnode, pTrans) != 0) {
    mndReleaseStream(pMnode, pStream);
    mndTransDrop(pTrans);
    return -1;
  }

895 896 897 898 899 900 901 902 903 904
  taosRLockLatch(&pStream->lock);
  // 1. redo action: broadcast checkpoint source msg for all source vg
  int32_t totLevel = taosArrayGetSize(pStream->tasks);
  for (int32_t i = 0; i < totLevel; i++) {
    SArray      *pLevel = taosArrayGetP(pStream->tasks, i);
    SStreamTask *pTask = taosArrayGetP(pLevel, 0);
    if (pTask->taskLevel == TASK_LEVEL__SOURCE) {
      int32_t sz = taosArrayGetSize(pLevel);
      for (int32_t j = 0; j < sz; j++) {
        SStreamTask *pTask = taosArrayGetP(pLevel, j);
L
Liu Jicong 已提交
905
        /*A(pTask->nodeId > 0);*/
906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939
        SVgObj *pVgObj = mndAcquireVgroup(pMnode, pTask->nodeId);
        if (pVgObj == NULL) {
          taosRUnLockLatch(&pStream->lock);
          mndReleaseStream(pMnode, pStream);
          mndTransDrop(pTrans);
          return -1;
        }

        void   *buf;
        int32_t tlen;
        if (mndBuildStreamCheckpointSourceReq(&buf, &tlen, pTask, pMsg) < 0) {
          taosRUnLockLatch(&pStream->lock);
          mndReleaseStream(pMnode, pStream);
          mndTransDrop(pTrans);
          return -1;
        }

        STransAction action = {0};
        action.epSet = mndGetVgroupEpset(pMnode, pVgObj);
        action.pCont = buf;
        action.contLen = tlen;
        action.msgType = TDMT_VND_STREAM_CHECK_POINT_SOURCE;

        mndReleaseVgroup(pMnode, pVgObj);

        if (mndTransAppendRedoAction(pTrans, &action) != 0) {
          taosMemoryFree(buf);
          taosRUnLockLatch(&pStream->lock);
          mndReleaseStream(pMnode, pStream);
          mndTransDrop(pTrans);
          return -1;
        }
      }
    }
L
Liu Jicong 已提交
940
  }
941 942 943 944
  // 2. reset tick
  atomic_store_64(&pStream->currentTick, 0);
  // 3. commit log: stream checkpoint info
  taosRUnLockLatch(&pStream->lock);
L
Liu Jicong 已提交
945

L
Liu Jicong 已提交
946
  if (mndTransPrepare(pMnode, pTrans) != 0) {
947
    mError("failed to prepare trans rebalance since %s", terrstr());
L
Liu Jicong 已提交
948
    mndTransDrop(pTrans);
949
    mndReleaseStream(pMnode, pStream);
L
Liu Jicong 已提交
950 951 952
    return -1;
  }

953
  mndReleaseStream(pMnode, pStream);
L
Liu Jicong 已提交
954
  mndTransDrop(pTrans);
L
Liu Jicong 已提交
955

956
  return 0;
L
Liu Jicong 已提交
957 958
}

5
54liuyao 已提交
959 960
#endif

961
static int32_t mndProcessDropStreamReq(SRpcMsg *pReq) {
L
Liu Jicong 已提交
962 963 964 965 966
  SMnode     *pMnode = pReq->info.node;
  SStreamObj *pStream = NULL;
  /*SDbObj     *pDb = NULL;*/
  /*SUserObj   *pUser = NULL;*/

967 968
  SMDropStreamReq dropReq = {0};
  if (tDeserializeSMDropStreamReq(pReq->pCont, pReq->contLen, &dropReq) < 0) {
L
Liu Jicong 已提交
969 970 971 972
    terrno = TSDB_CODE_INVALID_MSG;
    return -1;
  }

973
  pStream = mndAcquireStream(pMnode, dropReq.name);
L
Liu Jicong 已提交
974 975

  if (pStream == NULL) {
976 977
    if (dropReq.igNotExists) {
      mInfo("stream:%s, not exist, ignore not exist is set", dropReq.name);
L
Liu Jicong 已提交
978 979 980 981 982 983 984 985 986
      sdbRelease(pMnode->pSdb, pStream);
      return 0;
    } else {
      terrno = TSDB_CODE_MND_STREAM_NOT_EXIST;
      return -1;
    }
  }

  if (mndCheckDbPrivilegeByName(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, pStream->targetDb) != 0) {
987
    sdbRelease(pMnode->pSdb, pStream);
L
Liu Jicong 已提交
988 989 990
    return -1;
  }

991
  STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB_INSIDE, pReq, "drop-stream");
L
Liu Jicong 已提交
992
  if (pTrans == NULL) {
993
    mError("stream:%s, failed to drop since %s", dropReq.name, terrstr());
L
Liu Jicong 已提交
994 995 996
    sdbRelease(pMnode->pSdb, pStream);
    return -1;
  }
997
  mInfo("trans:%d, used to drop stream:%s", pTrans->id, dropReq.name);
L
Liu Jicong 已提交
998

999 1000 1001 1002 1003 1004 1005
  mndTransSetDbName(pTrans, pStream->sourceDb, pStream->targetDb);
  if (mndTrancCheckConflict(pMnode, pTrans) != 0) {
    sdbRelease(pMnode->pSdb, pStream);
    mndTransDrop(pTrans);
    return -1;
  }

1006 1007 1008
  // drop all tasks
  if (mndDropStreamTasks(pMnode, pTrans, pStream) < 0) {
    mError("stream:%s, failed to drop task since %s", dropReq.name, terrstr());
L
Liu Jicong 已提交
1009
    sdbRelease(pMnode->pSdb, pStream);
1010
    mndTransDrop(pTrans);
L
Liu Jicong 已提交
1011 1012 1013
    return -1;
  }

1014 1015
  // drop stream
  if (mndPersistDropStreamLog(pMnode, pTrans, pStream) < 0) {
L
Liu Jicong 已提交
1016
    sdbRelease(pMnode->pSdb, pStream);
1017
    mndTransDrop(pTrans);
L
Liu Jicong 已提交
1018 1019 1020 1021
    return -1;
  }

  if (mndTransPrepare(pMnode, pTrans) != 0) {
1022
    mError("trans:%d, failed to prepare drop stream trans since %s", pTrans->id, terrstr());
L
Liu Jicong 已提交
1023 1024 1025 1026 1027 1028
    sdbRelease(pMnode->pSdb, pStream);
    mndTransDrop(pTrans);
    return -1;
  }

  sdbRelease(pMnode->pSdb, pStream);
1029
  mndTransDrop(pTrans);
L
Liu Jicong 已提交
1030 1031 1032 1033

  return TSDB_CODE_ACTION_IN_PROGRESS;
}

L
Liu Jicong 已提交
1034 1035
int32_t mndDropStreamByDb(SMnode *pMnode, STrans *pTrans, SDbObj *pDb) {
  SSdb *pSdb = pMnode->pSdb;
S
Shengliang Guan 已提交
1036
  void *pIter = NULL;
L
Liu Jicong 已提交
1037 1038

  while (1) {
S
Shengliang Guan 已提交
1039
    SStreamObj *pStream = NULL;
L
Liu Jicong 已提交
1040 1041 1042 1043 1044 1045
    pIter = sdbFetch(pSdb, SDB_STREAM, pIter, (void **)&pStream);
    if (pIter == NULL) break;

    if (pStream->sourceDbUid == pDb->uid || pStream->targetDbUid == pDb->uid) {
      if (pStream->sourceDbUid != pStream->targetDbUid) {
        sdbRelease(pSdb, pStream);
S
Shengliang Guan 已提交
1046 1047 1048
        sdbCancelFetch(pSdb, pIter);
        mError("db:%s, failed to drop stream:%s since sourceDbUid:%" PRId64 " not match with targetDbUid:%" PRId64,
               pDb->name, pStream->name, pStream->sourceDbUid, pStream->targetDbUid);
1049
        terrno = TSDB_CODE_MND_STREAM_MUST_BE_DELETED;
L
Liu Jicong 已提交
1050 1051
        return -1;
      } else {
1052 1053 1054 1055 1056 1057 1058 1059
#if 0
        if (mndDropStreamTasks(pMnode, pTrans, pStream) < 0) {
          mError("stream:%s, failed to drop task since %s", pStream->name, terrstr());
          sdbRelease(pMnode->pSdb, pStream);
          sdbCancelFetch(pSdb, pIter);
          return -1;
        }
#endif
L
Liu Jicong 已提交
1060 1061
        if (mndPersistDropStreamLog(pMnode, pTrans, pStream) < 0) {
          sdbRelease(pSdb, pStream);
S
Shengliang Guan 已提交
1062
          sdbCancelFetch(pSdb, pIter);
L
Liu Jicong 已提交
1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073
          return -1;
        }
      }
    }

    sdbRelease(pSdb, pStream);
  }

  return 0;
}

L
Liu Jicong 已提交
1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088
static int32_t mndGetNumOfStreams(SMnode *pMnode, char *dbName, int32_t *pNumOfStreams) {
  SSdb   *pSdb = pMnode->pSdb;
  SDbObj *pDb = mndAcquireDb(pMnode, dbName);
  if (pDb == NULL) {
    terrno = TSDB_CODE_MND_DB_NOT_SELECTED;
    return -1;
  }

  int32_t numOfStreams = 0;
  void   *pIter = NULL;
  while (1) {
    SStreamObj *pStream = NULL;
    pIter = sdbFetch(pSdb, SDB_STREAM, pIter, (void **)&pStream);
    if (pIter == NULL) break;

L
Liu Jicong 已提交
1089
    if (pStream->sourceDbUid == pDb->uid) {
L
Liu Jicong 已提交
1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100
      numOfStreams++;
    }

    sdbRelease(pSdb, pStream);
  }

  *pNumOfStreams = numOfStreams;
  mndReleaseDb(pMnode, pDb);
  return 0;
}

S
Shengliang Guan 已提交
1101 1102
static int32_t mndRetrieveStream(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
  SMnode     *pMnode = pReq->info.node;
L
Liu Jicong 已提交
1103 1104 1105 1106 1107
  SSdb       *pSdb = pMnode->pSdb;
  int32_t     numOfRows = 0;
  SStreamObj *pStream = NULL;

  while (numOfRows < rows) {
L
Liu Jicong 已提交
1108
    pShow->pIter = sdbFetch(pSdb, SDB_STREAM, pShow->pIter, (void **)&pStream);
L
Liu Jicong 已提交
1109 1110
    if (pShow->pIter == NULL) break;

L
Liu Jicong 已提交
1111 1112 1113
    SColumnInfoData *pColInfo;
    SName            n;
    int32_t          cols = 0;
L
Liu Jicong 已提交
1114

1115
    char streamName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
S
Shengliang Guan 已提交
1116
    STR_WITH_MAXSIZE_TO_VARSTR(streamName, mndGetDbStr(pStream->name), sizeof(streamName));
L
Liu Jicong 已提交
1117
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1118
    colDataSetVal(pColInfo, numOfRows, (const char *)streamName, false);
L
Liu Jicong 已提交
1119

L
Liu Jicong 已提交
1120
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1121
    colDataSetVal(pColInfo, numOfRows, (const char *)&pStream->createTime, false);
L
Liu Jicong 已提交
1122

L
Liu Jicong 已提交
1123
    char sql[TSDB_SHOW_SQL_LEN + VARSTR_HEADER_SIZE] = {0};
S
Shengliang Guan 已提交
1124
    STR_WITH_MAXSIZE_TO_VARSTR(sql, pStream->sql, sizeof(sql));
L
Liu Jicong 已提交
1125
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1126
    colDataSetVal(pColInfo, numOfRows, (const char *)sql, false);
L
Liu Jicong 已提交
1127

L
Liu Jicong 已提交
1128
    char status[20 + VARSTR_HEADER_SIZE] = {0};
S
Shengliang Guan 已提交
1129 1130 1131
    char status2[20] = {0};
    mndShowStreamStatus(status2, pStream);
    STR_WITH_MAXSIZE_TO_VARSTR(status, status2, sizeof(status));
L
Liu Jicong 已提交
1132
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1133
    colDataSetVal(pColInfo, numOfRows, (const char *)&status, false);
L
Liu Jicong 已提交
1134

1135
    char sourceDB[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
S
Shengliang Guan 已提交
1136
    STR_WITH_MAXSIZE_TO_VARSTR(sourceDB, mndGetDbStr(pStream->sourceDb), sizeof(sourceDB));
L
Liu Jicong 已提交
1137
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1138
    colDataSetVal(pColInfo, numOfRows, (const char *)&sourceDB, false);
L
Liu Jicong 已提交
1139

1140
    char targetDB[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
S
Shengliang Guan 已提交
1141
    STR_WITH_MAXSIZE_TO_VARSTR(targetDB, mndGetDbStr(pStream->targetDb), sizeof(targetDB));
L
Liu Jicong 已提交
1142
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1143
    colDataSetVal(pColInfo, numOfRows, (const char *)&targetDB, false);
L
Liu Jicong 已提交
1144

1145 1146
    if (pStream->targetSTbName[0] == 0) {
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1147
      colDataSetVal(pColInfo, numOfRows, NULL, true);
1148 1149
    } else {
      char targetSTB[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
S
Shengliang Guan 已提交
1150
      STR_WITH_MAXSIZE_TO_VARSTR(targetSTB, mndGetStbStr(pStream->targetSTbName), sizeof(targetSTB));
1151
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1152
      colDataSetVal(pColInfo, numOfRows, (const char *)&targetSTB, false);
1153
    }
L
Liu Jicong 已提交
1154 1155

    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1156
    colDataSetVal(pColInfo, numOfRows, (const char *)&pStream->watermark, false);
L
Liu Jicong 已提交
1157

L
Liu Jicong 已提交
1158
    char trigger[20 + VARSTR_HEADER_SIZE] = {0};
S
Shengliang Guan 已提交
1159 1160 1161
    char trigger2[20] = {0};
    mndShowStreamTrigger(trigger2, pStream);
    STR_WITH_MAXSIZE_TO_VARSTR(trigger, trigger2, sizeof(trigger));
L
Liu Jicong 已提交
1162
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1163
    colDataSetVal(pColInfo, numOfRows, (const char *)&trigger, false);
L
Liu Jicong 已提交
1164 1165 1166

    numOfRows++;
    sdbRelease(pSdb, pStream);
L
Liu Jicong 已提交
1167
  }
L
Liu Jicong 已提交
1168 1169 1170

  pShow->numOfRows += numOfRows;
  return numOfRows;
L
Liu Jicong 已提交
1171 1172 1173 1174 1175 1176
}

static void mndCancelGetNextStream(SMnode *pMnode, void *pIter) {
  SSdb *pSdb = pMnode->pSdb;
  sdbCancelFetch(pSdb, pIter);
}
1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214

static int32_t mndRetrieveStreamTask(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rowsCapacity) {
  SMnode     *pMnode = pReq->info.node;
  SSdb       *pSdb = pMnode->pSdb;
  int32_t     numOfRows = 0;
  SStreamObj *pStream = NULL;

  while (numOfRows < rowsCapacity) {
    pShow->pIter = sdbFetch(pSdb, SDB_STREAM, pShow->pIter, (void **)&pStream);
    if (pShow->pIter == NULL) break;

    // lock
    taosRLockLatch(&pStream->lock);
    // count task num
    int32_t sz = taosArrayGetSize(pStream->tasks);
    int32_t count = 0;
    for (int32_t i = 0; i < sz; i++) {
      SArray *pLevel = taosArrayGetP(pStream->tasks, i);
      count += taosArrayGetSize(pLevel);
    }

    if (numOfRows + count > rowsCapacity) {
      blockDataEnsureCapacity(pBlock, numOfRows + count);
    }
    // add row for each task
    for (int32_t i = 0; i < sz; i++) {
      SArray *pLevel = taosArrayGetP(pStream->tasks, i);
      int32_t levelCnt = taosArrayGetSize(pLevel);
      for (int32_t j = 0; j < levelCnt; j++) {
        SStreamTask *pTask = taosArrayGetP(pLevel, j);

        SColumnInfoData *pColInfo;
        int32_t          cols = 0;

        // stream name
        char streamName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
        STR_WITH_MAXSIZE_TO_VARSTR(streamName, mndGetDbStr(pStream->name), sizeof(streamName));
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1215
        colDataSetVal(pColInfo, numOfRows, (const char *)streamName, false);
1216 1217 1218

        // task id
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1219
        colDataSetVal(pColInfo, numOfRows, (const char *)&pTask->id.taskId, false);
1220 1221 1222 1223 1224 1225 1226 1227 1228 1229

        // node type
        char nodeType[20 + VARSTR_HEADER_SIZE] = {0};
        varDataSetLen(nodeType, 5);
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
        if (pTask->nodeId > 0) {
          memcpy(varDataVal(nodeType), "vnode", 5);
        } else {
          memcpy(varDataVal(nodeType), "snode", 5);
        }
1230
        colDataSetVal(pColInfo, numOfRows, nodeType, false);
1231 1232 1233

        // node id
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
5
54liuyao 已提交
1234
        int64_t nodeId = TMAX(pTask->nodeId, 0);
1235
        colDataSetVal(pColInfo, numOfRows, (const char *)&nodeId, false);
1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250

        // level
        char level[20 + VARSTR_HEADER_SIZE] = {0};
        if (pTask->taskLevel == TASK_LEVEL__SOURCE) {
          memcpy(varDataVal(level), "source", 6);
          varDataSetLen(level, 6);
        } else if (pTask->taskLevel == TASK_LEVEL__AGG) {
          memcpy(varDataVal(level), "agg", 3);
          varDataSetLen(level, 3);
        } else if (pTask->taskLevel == TASK_LEVEL__SINK) {
          memcpy(varDataVal(level), "sink", 4);
          varDataSetLen(level, 4);
        } else if (pTask->taskLevel == TASK_LEVEL__SINK) {
        }
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1251
        colDataSetVal(pColInfo, numOfRows, (const char *)&level, false);
1252 1253 1254 1255 1256 1257 1258

        // status
        char status[20 + VARSTR_HEADER_SIZE] = {0};
        char status2[20] = {0};
        strcpy(status, "normal");
        STR_WITH_MAXSIZE_TO_VARSTR(status, status2, sizeof(status));
        pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
1259
        colDataSetVal(pColInfo, numOfRows, (const char *)&status, false);
1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278

        numOfRows++;
      }
    }

    // unlock
    taosRUnLockLatch(&pStream->lock);

    sdbRelease(pSdb, pStream);
  }

  pShow->numOfRows += numOfRows;
  return numOfRows;
}

static void mndCancelGetNextStreamTask(SMnode *pMnode, void *pIter) {
  SSdb *pSdb = pMnode->pSdb;
  sdbCancelFetch(pSdb, pIter);
}
5
54liuyao 已提交
1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507

static int32_t mndPauseStreamTask(STrans *pTrans, SStreamTask *pTask) {
  SVPauseStreamTaskReq *pReq = taosMemoryCalloc(1, sizeof(SVPauseStreamTaskReq));
  if (pReq == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return -1;
  }
  pReq->head.vgId = htonl(pTask->nodeId);
  pReq->taskId = pTask->id.taskId;
  STransAction action = {0};
  memcpy(&action.epSet, &pTask->epSet, sizeof(SEpSet));
  action.pCont = pReq;
  action.contLen = sizeof(SVPauseStreamTaskReq);
  action.msgType = TDMT_STREAM_TASK_RESUME;
  if (mndTransAppendRedoAction(pTrans, &action) != 0) {
    taosMemoryFree(pReq);
    return -1;
  }
  return 0;
}

int32_t mndPauseAllStreamTasks(STrans *pTrans, SStreamObj *pStream) {
  int32_t size = taosArrayGetSize(pStream->tasks);
  for (int32_t i = 0; i < size; i++) {
    SArray *pTasks = taosArrayGetP(pStream->tasks, i);
    int32_t sz = taosArrayGetSize(pTasks);
    for (int32_t j = 0; j < sz; j++) {
      SStreamTask *pTask = taosArrayGetP(pTasks, j);
      if (mndPauseStreamTask(pTrans, pTask) < 0) {
        return -1;
      }
    }
  }
  return 0;
}

static int32_t mndPersistStreamLog(STrans *pTrans, const SStreamObj *pStream, int8_t status) {
  SStreamObj streamObj = {0};
  memcpy(streamObj.name, pStream->name, TSDB_STREAM_FNAME_LEN);
  streamObj.status = status;

  SSdbRaw *pCommitRaw = mndStreamActionEncode(&streamObj);
  if (pCommitRaw == NULL) return -1;
  if (mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
    mError("stream trans:%d, failed to append commit log since %s", pTrans->id, terrstr());
    mndTransDrop(pTrans);
    return -1;
  }
  (void)sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY);
  return 0;
}

static int32_t mndProcessPauseStreamReq(SRpcMsg *pReq) {
  SMnode     *pMnode = pReq->info.node;
  SStreamObj *pStream = NULL;

  SMPauseStreamReq pauseReq = {0};
  if (tDeserializeSMPauseStreamReq(pReq->pCont, pReq->contLen, &pauseReq) < 0) {
    terrno = TSDB_CODE_INVALID_MSG;
    return -1;
  }

  pStream = mndAcquireStream(pMnode, pauseReq.name);

  if (pStream == NULL) {
    if (pauseReq.igNotExists) {
      mInfo("stream:%s, not exist, if exist is set", pauseReq.name);
      sdbRelease(pMnode->pSdb, pStream);
      return 0;
    } else {
      terrno = TSDB_CODE_MND_STREAM_NOT_EXIST;
      return -1;
    }
  }

  if (mndCheckDbPrivilegeByName(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, pStream->targetDb) != 0) {
    sdbRelease(pMnode->pSdb, pStream);
    return -1;
  }

  STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB_INSIDE, pReq, "pause-stream");
  if (pTrans == NULL) {
    mError("stream:%s, failed to pause stream since %s", pauseReq.name, terrstr());
    sdbRelease(pMnode->pSdb, pStream);
    return -1;
  }
  mInfo("trans:%d, used to pause stream:%s", pTrans->id, pauseReq.name);

  mndTransSetDbName(pTrans, pStream->sourceDb, pStream->targetDb);
  if (mndTrancCheckConflict(pMnode, pTrans) != 0) {
    sdbRelease(pMnode->pSdb, pStream);
    mndTransDrop(pTrans);
    return -1;
  }

  // pause all tasks
  if (mndPauseAllStreamTasks(pTrans, pStream) < 0) {
    mError("stream:%s, failed to drop task since %s", pauseReq.name, terrstr());
    sdbRelease(pMnode->pSdb, pStream);
    mndTransDrop(pTrans);
    return -1;
  }

  // pause stream
  if (mndPersistStreamLog(pTrans, pStream, STREAM_STATUS__PAUSE) < 0) {
    sdbRelease(pMnode->pSdb, pStream);
    mndTransDrop(pTrans);
    return -1;
  }

  if (mndTransPrepare(pMnode, pTrans) != 0) {
    mError("trans:%d, failed to prepare pause stream trans since %s", pTrans->id, terrstr());
    sdbRelease(pMnode->pSdb, pStream);
    mndTransDrop(pTrans);
    return -1;
  }

  sdbRelease(pMnode->pSdb, pStream);
  mndTransDrop(pTrans);

  return TSDB_CODE_ACTION_IN_PROGRESS;
}


static int32_t mndResumeStreamTask(STrans *pTrans, SStreamTask *pTask) {
  SVResumeStreamTaskReq *pReq = taosMemoryCalloc(1, sizeof(SVResumeStreamTaskReq));
  if (pReq == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return -1;
  }
  pReq->head.vgId = htonl(pTask->nodeId);
  pReq->taskId = pTask->id.taskId;
  STransAction action = {0};
  memcpy(&action.epSet, &pTask->epSet, sizeof(SEpSet));
  action.pCont = pReq;
  action.contLen = sizeof(SVPauseStreamTaskReq);
  action.msgType = TDMT_STREAM_TASK_RESUME;
  if (mndTransAppendRedoAction(pTrans, &action) != 0) {
    taosMemoryFree(pReq);
    return -1;
  }
  return 0;
}

int32_t mndResumeAllStreamTasks(STrans *pTrans, SStreamObj *pStream) {
  int32_t size = taosArrayGetSize(pStream->tasks);
  for (int32_t i = 0; i < size; i++) {
    SArray *pTasks = taosArrayGetP(pStream->tasks, i);
    int32_t sz = taosArrayGetSize(pTasks);
    for (int32_t j = 0; j < sz; j++) {
      SStreamTask *pTask = taosArrayGetP(pTasks, j);
      if (mndResumeStreamTask(pTrans, pTask) < 0) {
        return -1;
      }
    }
  }
  return 0;
}

static int32_t mndProcessResumeStreamReq(SRpcMsg *pReq) {
  SMnode     *pMnode = pReq->info.node;
  SStreamObj *pStream = NULL;

  SMPauseStreamReq pauseReq = {0};
  if (tDeserializeSMPauseStreamReq(pReq->pCont, pReq->contLen, &pauseReq) < 0) {
    terrno = TSDB_CODE_INVALID_MSG;
    return -1;
  }

  pStream = mndAcquireStream(pMnode, pauseReq.name);

  if (pStream == NULL) {
    if (pauseReq.igNotExists) {
      mInfo("stream:%s, not exist, if exist is set", pauseReq.name);
      sdbRelease(pMnode->pSdb, pStream);
      return 0;
    } else {
      terrno = TSDB_CODE_MND_STREAM_NOT_EXIST;
      return -1;
    }
  }

  if (mndCheckDbPrivilegeByName(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, pStream->targetDb) != 0) {
    sdbRelease(pMnode->pSdb, pStream);
    return -1;
  }

  STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB_INSIDE, pReq, "pause-stream");
  if (pTrans == NULL) {
    mError("stream:%s, failed to pause stream since %s", pauseReq.name, terrstr());
    sdbRelease(pMnode->pSdb, pStream);
    return -1;
  }
  mInfo("trans:%d, used to pause stream:%s", pTrans->id, pauseReq.name);

  mndTransSetDbName(pTrans, pStream->sourceDb, pStream->targetDb);
  if (mndTrancCheckConflict(pMnode, pTrans) != 0) {
    sdbRelease(pMnode->pSdb, pStream);
    mndTransDrop(pTrans);
    return -1;
  }

  // resume all tasks
  if (mndResumeAllStreamTasks(pTrans, pStream) < 0) {
    mError("stream:%s, failed to drop task since %s", pauseReq.name, terrstr());
    sdbRelease(pMnode->pSdb, pStream);
    mndTransDrop(pTrans);
    return -1;
  }

  // resume stream
  if (mndPersistStreamLog(pTrans, pStream, STREAM_STATUS__NORMAL) < 0) {
    sdbRelease(pMnode->pSdb, pStream);
    mndTransDrop(pTrans);
    return -1;
  }

  if (mndTransPrepare(pMnode, pTrans) != 0) {
    mError("trans:%d, failed to prepare pause stream trans since %s", pTrans->id, terrstr());
    sdbRelease(pMnode->pSdb, pStream);
    mndTransDrop(pTrans);
    return -1;
  }

  sdbRelease(pMnode->pSdb, pStream);
  mndTransDrop(pTrans);

  return TSDB_CODE_ACTION_IN_PROGRESS;
}