Merge pull request #13507 from taosdata/feature/stream
refactor(stream)
This commit is contained in:
commit
edb9da8484
|
@ -77,7 +77,9 @@ typedef struct SDataBlockInfo {
|
||||||
int16_t numOfCols;
|
int16_t numOfCols;
|
||||||
int16_t hasVarCol;
|
int16_t hasVarCol;
|
||||||
int32_t capacity;
|
int32_t capacity;
|
||||||
EStreamType type;
|
// TODO: optimize and remove following
|
||||||
|
int32_t childId; // used for stream, do not serialize
|
||||||
|
EStreamType type; // used for stream, do not serialize
|
||||||
} SDataBlockInfo;
|
} SDataBlockInfo;
|
||||||
|
|
||||||
typedef struct SSDataBlock {
|
typedef struct SSDataBlock {
|
||||||
|
@ -105,14 +107,14 @@ typedef struct SColumnInfoData {
|
||||||
} SColumnInfoData;
|
} SColumnInfoData;
|
||||||
|
|
||||||
typedef struct SQueryTableDataCond {
|
typedef struct SQueryTableDataCond {
|
||||||
//STimeWindow twindow;
|
// STimeWindow twindow;
|
||||||
int32_t order; // desc|asc order to iterate the data block
|
int32_t order; // desc|asc order to iterate the data block
|
||||||
int32_t numOfCols;
|
int32_t numOfCols;
|
||||||
SColumnInfo *colList;
|
SColumnInfo* colList;
|
||||||
bool loadExternalRows; // load external rows or not
|
bool loadExternalRows; // load external rows or not
|
||||||
int32_t type; // data block load type:
|
int32_t type; // data block load type:
|
||||||
int32_t numOfTWindows;
|
int32_t numOfTWindows;
|
||||||
STimeWindow *twindows;
|
STimeWindow* twindows;
|
||||||
} SQueryTableDataCond;
|
} SQueryTableDataCond;
|
||||||
|
|
||||||
void* blockDataDestroy(SSDataBlock* pBlock);
|
void* blockDataDestroy(SSDataBlock* pBlock);
|
||||||
|
@ -202,17 +204,17 @@ typedef struct SExprInfo {
|
||||||
} SExprInfo;
|
} SExprInfo;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char* key;
|
const char* key;
|
||||||
int32_t keyLen;
|
int32_t keyLen;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
union{
|
union {
|
||||||
const char* value;
|
const char* value;
|
||||||
int64_t i;
|
int64_t i;
|
||||||
uint64_t u;
|
uint64_t u;
|
||||||
double d;
|
double d;
|
||||||
float f;
|
float f;
|
||||||
};
|
};
|
||||||
int32_t length;
|
int32_t length;
|
||||||
} SSmlKv;
|
} SSmlKv;
|
||||||
|
|
||||||
#define QUERY_ASC_FORWARD_STEP 1
|
#define QUERY_ASC_FORWARD_STEP 1
|
||||||
|
@ -220,7 +222,7 @@ typedef struct {
|
||||||
|
|
||||||
#define GET_FORWARD_DIRECTION_FACTOR(ord) (((ord) == TSDB_ORDER_ASC) ? QUERY_ASC_FORWARD_STEP : QUERY_DESC_FORWARD_STEP)
|
#define GET_FORWARD_DIRECTION_FACTOR(ord) (((ord) == TSDB_ORDER_ASC) ? QUERY_ASC_FORWARD_STEP : QUERY_DESC_FORWARD_STEP)
|
||||||
|
|
||||||
#define SORT_QSORT_T 0x1
|
#define SORT_QSORT_T 0x1
|
||||||
#define SORT_SPILLED_MERGE_SORT_T 0x2
|
#define SORT_SPILLED_MERGE_SORT_T 0x2
|
||||||
typedef struct SSortExecInfo {
|
typedef struct SSortExecInfo {
|
||||||
int32_t sortMethod;
|
int32_t sortMethod;
|
||||||
|
|
|
@ -24,8 +24,8 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _TSTREAM_H_
|
#ifndef _STREAM_H_
|
||||||
#define _TSTREAM_H_
|
#define _STREAM_H_
|
||||||
|
|
||||||
typedef struct SStreamTask SStreamTask;
|
typedef struct SStreamTask SStreamTask;
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ enum {
|
||||||
TASK_INPUT_STATUS__NORMAL = 1,
|
TASK_INPUT_STATUS__NORMAL = 1,
|
||||||
TASK_INPUT_STATUS__BLOCKED,
|
TASK_INPUT_STATUS__BLOCKED,
|
||||||
TASK_INPUT_STATUS__RECOVER,
|
TASK_INPUT_STATUS__RECOVER,
|
||||||
|
TASK_INPUT_STATUS__PROCESSING,
|
||||||
TASK_INPUT_STATUS__STOP,
|
TASK_INPUT_STATUS__STOP,
|
||||||
TASK_INPUT_STATUS__FAILED,
|
TASK_INPUT_STATUS__FAILED,
|
||||||
};
|
};
|
||||||
|
@ -60,6 +61,10 @@ enum {
|
||||||
STREAM_INPUT__CHECKPOINT,
|
STREAM_INPUT__CHECKPOINT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int8_t type;
|
||||||
|
} SStreamQueueItem;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int8_t type;
|
int8_t type;
|
||||||
int64_t ver;
|
int64_t ver;
|
||||||
|
@ -80,55 +85,51 @@ typedef struct {
|
||||||
int8_t type;
|
int8_t type;
|
||||||
} SStreamCheckpoint;
|
} SStreamCheckpoint;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
STREAM_QUEUE__SUCESS = 1,
|
||||||
|
STREAM_QUEUE__FAILED,
|
||||||
|
STREAM_QUEUE__PROCESSING,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
STaosQueue* queue;
|
STaosQueue* queue;
|
||||||
STaosQall* qall;
|
STaosQall* qall;
|
||||||
void* qItem;
|
void* qItem;
|
||||||
int8_t failed;
|
int8_t status;
|
||||||
} SStreamQ;
|
} SStreamQueue;
|
||||||
|
|
||||||
static FORCE_INLINE void* streamQCurItem(SStreamQ* queue) {
|
SStreamQueue* streamQueueOpen();
|
||||||
//
|
void streamQueueClose(SStreamQueue* queue);
|
||||||
return queue->qItem;
|
|
||||||
|
static FORCE_INLINE void streamQueueProcessSuccess(SStreamQueue* queue) {
|
||||||
|
ASSERT(atomic_load_8(&queue->status) == STREAM_QUEUE__PROCESSING);
|
||||||
|
queue->qItem = NULL;
|
||||||
|
atomic_store_8(&queue->status, STREAM_QUEUE__SUCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FORCE_INLINE void* streamQNextItem(SStreamQ* queue) {
|
static FORCE_INLINE void streamQueueProcessFail(SStreamQueue* queue) {
|
||||||
int8_t failed = atomic_load_8(&queue->failed);
|
ASSERT(atomic_load_8(&queue->status) == STREAM_QUEUE__PROCESSING);
|
||||||
if (failed) {
|
atomic_store_8(&queue->status, STREAM_QUEUE__FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static FORCE_INLINE void* streamQueueCurItem(SStreamQueue* queue) { return queue->qItem; }
|
||||||
|
|
||||||
|
static FORCE_INLINE void* streamQueueNextItem(SStreamQueue* queue) {
|
||||||
|
int8_t dequeueFlag = atomic_exchange_8(&queue->status, STREAM_QUEUE__PROCESSING);
|
||||||
|
if (dequeueFlag == STREAM_QUEUE__FAILED) {
|
||||||
ASSERT(queue->qItem != NULL);
|
ASSERT(queue->qItem != NULL);
|
||||||
return streamQCurItem(queue);
|
return streamQueueCurItem(queue);
|
||||||
} else {
|
} else {
|
||||||
taosGetQitem(queue->qall, &queue->qItem);
|
taosGetQitem(queue->qall, &queue->qItem);
|
||||||
if (queue->qItem == NULL) {
|
if (queue->qItem == NULL) {
|
||||||
taosReadAllQitems(queue->queue, queue->qall);
|
taosReadAllQitems(queue->queue, queue->qall);
|
||||||
taosGetQitem(queue->qall, &queue->qItem);
|
taosGetQitem(queue->qall, &queue->qItem);
|
||||||
}
|
}
|
||||||
return streamQCurItem(queue);
|
return streamQueueCurItem(queue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static FORCE_INLINE void streamQSetFail(SStreamQ* queue) { atomic_store_8(&queue->failed, 1); }
|
SStreamDataSubmit* streamDataSubmitNew(SSubmitReq* pReq);
|
||||||
|
|
||||||
static FORCE_INLINE void streamQSetSuccess(SStreamQ* queue) { atomic_store_8(&queue->failed, 0); }
|
|
||||||
|
|
||||||
static FORCE_INLINE SStreamDataSubmit* streamDataSubmitNew(SSubmitReq* pReq) {
|
|
||||||
SStreamDataSubmit* pDataSubmit = (SStreamDataSubmit*)taosAllocateQitem(sizeof(SStreamDataSubmit), DEF_QITEM);
|
|
||||||
if (pDataSubmit == NULL) return NULL;
|
|
||||||
pDataSubmit->dataRef = (int32_t*)taosMemoryMalloc(sizeof(int32_t));
|
|
||||||
if (pDataSubmit->dataRef == NULL) goto FAIL;
|
|
||||||
pDataSubmit->data = pReq;
|
|
||||||
*pDataSubmit->dataRef = 1;
|
|
||||||
pDataSubmit->type = STREAM_INPUT__DATA_SUBMIT;
|
|
||||||
return pDataSubmit;
|
|
||||||
FAIL:
|
|
||||||
taosFreeQitem(pDataSubmit);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE void streamDataSubmitRefInc(SStreamDataSubmit* pDataSubmit) {
|
|
||||||
//
|
|
||||||
atomic_add_fetch_32(pDataSubmit->dataRef, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE void streamDataSubmitRefDec(SStreamDataSubmit* pDataSubmit) {
|
static FORCE_INLINE void streamDataSubmitRefDec(SStreamDataSubmit* pDataSubmit) {
|
||||||
int32_t ref = atomic_sub_fetch_32(pDataSubmit->dataRef, 1);
|
int32_t ref = atomic_sub_fetch_32(pDataSubmit->dataRef, 1);
|
||||||
|
@ -141,9 +142,31 @@ static FORCE_INLINE void streamDataSubmitRefDec(SStreamDataSubmit* pDataSubmit)
|
||||||
|
|
||||||
SStreamDataSubmit* streamSubmitRefClone(SStreamDataSubmit* pSubmit);
|
SStreamDataSubmit* streamSubmitRefClone(SStreamDataSubmit* pSubmit);
|
||||||
|
|
||||||
|
#if 0
|
||||||
int32_t streamDataBlockEncode(void** buf, const SStreamDataBlock* pOutput);
|
int32_t streamDataBlockEncode(void** buf, const SStreamDataBlock* pOutput);
|
||||||
void* streamDataBlockDecode(const void* buf, SStreamDataBlock* pInput);
|
void* streamDataBlockDecode(const void* buf, SStreamDataBlock* pInput);
|
||||||
|
|
||||||
|
static FORCE_INLINE int32_t streamEnqueue1(SStreamQueue* queue, SStreamQueueItem* pItem) {
|
||||||
|
int8_t inputStatus = atomic_load_8(&queue->enqueueStatus);
|
||||||
|
if (inputStatus == TASK_INPUT_STATUS__NORMAL) {
|
||||||
|
if (pItem->type == STREAM_INPUT__DATA_SUBMIT) {
|
||||||
|
SStreamDataSubmit* pSubmitClone = streamSubmitRefClone((SStreamDataSubmit*)pItem);
|
||||||
|
if (pSubmitClone == NULL) {
|
||||||
|
atomic_store_8(&queue->enqueueStatus, TASK_INPUT_STATUS__FAILED);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
taosWriteQitem(queue->queue, pSubmitClone);
|
||||||
|
} else if (pItem->type == STREAM_INPUT__DATA_BLOCK) {
|
||||||
|
taosWriteQitem(queue->queue, pItem);
|
||||||
|
} else if (pItem->type == STREAM_INPUT__CHECKPOINT) {
|
||||||
|
taosWriteQitem(queue->queue, pItem);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int8_t parallelizable;
|
int8_t parallelizable;
|
||||||
char* qmsg;
|
char* qmsg;
|
||||||
|
@ -236,13 +259,17 @@ struct SStreamTask {
|
||||||
int8_t dispatchType;
|
int8_t dispatchType;
|
||||||
int16_t dispatchMsgType;
|
int16_t dispatchMsgType;
|
||||||
|
|
||||||
|
// node info
|
||||||
|
int32_t childId;
|
||||||
int32_t nodeId;
|
int32_t nodeId;
|
||||||
SEpSet epSet;
|
SEpSet epSet;
|
||||||
|
|
||||||
// exec
|
// exec
|
||||||
STaskExec exec;
|
STaskExec exec;
|
||||||
|
|
||||||
// local sink
|
// TODO: merge sink and dispatch
|
||||||
|
|
||||||
|
// local sink
|
||||||
union {
|
union {
|
||||||
STaskSinkTb tbSink;
|
STaskSinkTb tbSink;
|
||||||
STaskSinkSma smaSink;
|
STaskSinkSma smaSink;
|
||||||
|
@ -258,25 +285,61 @@ struct SStreamTask {
|
||||||
|
|
||||||
int8_t inputStatus;
|
int8_t inputStatus;
|
||||||
int8_t outputStatus;
|
int8_t outputStatus;
|
||||||
|
#if 0
|
||||||
STaosQueue* inputQ;
|
STaosQueue* inputQ;
|
||||||
STaosQall* inputQAll;
|
STaosQall* inputQAll;
|
||||||
STaosQueue* outputQ;
|
STaosQueue* outputQ;
|
||||||
STaosQall* outputQAll;
|
STaosQall* outputQAll;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SStreamQueue* inputQueue;
|
||||||
|
SStreamQueue* outputQueue;
|
||||||
|
|
||||||
// application storage
|
// application storage
|
||||||
void* ahandle;
|
void* ahandle;
|
||||||
};
|
};
|
||||||
|
|
||||||
SStreamTask* tNewSStreamTask(int64_t streamId);
|
SStreamTask* tNewSStreamTask(int64_t streamId, int32_t childId);
|
||||||
int32_t tEncodeSStreamTask(SEncoder* pEncoder, const SStreamTask* pTask);
|
int32_t tEncodeSStreamTask(SEncoder* pEncoder, const SStreamTask* pTask);
|
||||||
int32_t tDecodeSStreamTask(SDecoder* pDecoder, SStreamTask* pTask);
|
int32_t tDecodeSStreamTask(SDecoder* pDecoder, SStreamTask* pTask);
|
||||||
void tFreeSStreamTask(SStreamTask* pTask);
|
void tFreeSStreamTask(SStreamTask* pTask);
|
||||||
|
|
||||||
typedef struct {
|
static FORCE_INLINE int32_t streamTaskInput(SStreamTask* pTask, SStreamQueueItem* pItem) {
|
||||||
// SMsgHead head;
|
while (1) {
|
||||||
SStreamTask* task;
|
int8_t inputStatus =
|
||||||
} SStreamTaskDeployReq;
|
atomic_val_compare_exchange_8(&pTask->inputStatus, TASK_INPUT_STATUS__NORMAL, TASK_INPUT_STATUS__PROCESSING);
|
||||||
|
if (inputStatus == TASK_INPUT_STATUS__NORMAL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ASSERT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pItem->type == STREAM_INPUT__DATA_SUBMIT) {
|
||||||
|
SStreamDataSubmit* pSubmitClone = streamSubmitRefClone((SStreamDataSubmit*)pItem);
|
||||||
|
if (pSubmitClone == NULL) {
|
||||||
|
atomic_store_8(&pTask->inputStatus, TASK_INPUT_STATUS__FAILED);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
taosWriteQitem(pTask->inputQueue->queue, pSubmitClone);
|
||||||
|
} else if (pItem->type == STREAM_INPUT__DATA_BLOCK) {
|
||||||
|
taosWriteQitem(pTask->inputQueue->queue, pItem);
|
||||||
|
} else if (pItem->type == STREAM_INPUT__CHECKPOINT) {
|
||||||
|
taosWriteQitem(pTask->inputQueue->queue, pItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: back pressure
|
||||||
|
atomic_store_8(&pTask->inputStatus, TASK_INPUT_STATUS__NORMAL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FORCE_INLINE void streamTaskInputFail(SStreamTask* pTask) {
|
||||||
|
atomic_store_8(&pTask->inputStatus, TASK_INPUT_STATUS__FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static FORCE_INLINE int32_t streamTaskOutput(SStreamTask* pTask, SStreamDataBlock* pBlock) {
|
||||||
|
taosWriteQitem(pTask->outputQueue->queue, pBlock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int32_t reserved;
|
int32_t reserved;
|
||||||
|
@ -289,6 +352,11 @@ typedef struct {
|
||||||
SArray* data; // SArray<SSDataBlock>
|
SArray* data; // SArray<SSDataBlock>
|
||||||
} SStreamTaskExecReq;
|
} SStreamTaskExecReq;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// SMsgHead head;
|
||||||
|
SStreamTask* task;
|
||||||
|
} SStreamTaskDeployReq;
|
||||||
|
|
||||||
int32_t tEncodeSStreamTaskExecReq(void** buf, const SStreamTaskExecReq* pReq);
|
int32_t tEncodeSStreamTaskExecReq(void** buf, const SStreamTaskExecReq* pReq);
|
||||||
void* tDecodeSStreamTaskExecReq(const void* buf, SStreamTaskExecReq* pReq);
|
void* tDecodeSStreamTaskExecReq(const void* buf, SStreamTaskExecReq* pReq);
|
||||||
void tFreeSStreamTaskExecReq(SStreamTaskExecReq* pReq);
|
void tFreeSStreamTaskExecReq(SStreamTaskExecReq* pReq);
|
||||||
|
@ -297,6 +365,12 @@ typedef struct {
|
||||||
int32_t reserved;
|
int32_t reserved;
|
||||||
} SStreamTaskExecRsp;
|
} SStreamTaskExecRsp;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SMsgHead head;
|
||||||
|
int64_t streamId;
|
||||||
|
int32_t taskId;
|
||||||
|
} SStreamTaskRunReq;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// SMsgHead head;
|
// SMsgHead head;
|
||||||
int64_t streamId;
|
int64_t streamId;
|
||||||
|
@ -304,21 +378,18 @@ typedef struct {
|
||||||
SArray* res; // SArray<SSDataBlock>
|
SArray* res; // SArray<SSDataBlock>
|
||||||
} SStreamSinkReq;
|
} SStreamSinkReq;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SMsgHead head;
|
|
||||||
int64_t streamId;
|
|
||||||
int32_t taskId;
|
|
||||||
} SStreamTaskRunReq;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int64_t streamId;
|
int64_t streamId;
|
||||||
int32_t taskId;
|
int32_t taskId;
|
||||||
int32_t sourceTaskId;
|
int32_t sourceTaskId;
|
||||||
int32_t sourceVg;
|
int32_t sourceVg;
|
||||||
|
int32_t sourceChildId;
|
||||||
#if 0
|
#if 0
|
||||||
int64_t sourceVer;
|
int64_t sourceVer;
|
||||||
#endif
|
#endif
|
||||||
SArray* data; // SArray<SSDataBlock>
|
int32_t blockNum;
|
||||||
|
SArray* dataLen; // SArray<int32_t>
|
||||||
|
SArray* data; // SArray<SRetrieveTableRsp*>
|
||||||
} SStreamDispatchReq;
|
} SStreamDispatchReq;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -340,6 +411,8 @@ typedef struct {
|
||||||
int8_t inputStatus;
|
int8_t inputStatus;
|
||||||
} SStreamTaskRecoverRsp;
|
} SStreamTaskRecoverRsp;
|
||||||
|
|
||||||
|
int32_t streamTriggerByWrite(SStreamTask* pTask, int32_t vgId, SMsgCb* pMsgCb);
|
||||||
|
|
||||||
int32_t streamEnqueueDataSubmit(SStreamTask* pTask, SStreamDataSubmit* input);
|
int32_t streamEnqueueDataSubmit(SStreamTask* pTask, SStreamDataSubmit* input);
|
||||||
int32_t streamEnqueueDataBlk(SStreamTask* pTask, SStreamDataBlock* input);
|
int32_t streamEnqueueDataBlk(SStreamTask* pTask, SStreamDataBlock* input);
|
||||||
int32_t streamDequeueOutput(SStreamTask* pTask, void** output);
|
int32_t streamDequeueOutput(SStreamTask* pTask, void** output);
|
||||||
|
@ -356,4 +429,4 @@ int32_t streamProcessRecoverRsp(SStreamTask* pTask, SStreamTaskRecoverRsp* pRsp)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* ifndef _TSTREAM_H_ */
|
#endif /* ifndef _STREAM_H_ */
|
||||||
|
|
|
@ -190,7 +190,7 @@ int32_t mndAddShuffledSinkToStream(SMnode* pMnode, STrans* pTrans, SStreamObj* p
|
||||||
sdbRelease(pSdb, pVgroup);
|
sdbRelease(pSdb, pVgroup);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
SStreamTask* pTask = tNewSStreamTask(pStream->uid);
|
SStreamTask* pTask = tNewSStreamTask(pStream->uid, 0);
|
||||||
if (pTask == NULL) {
|
if (pTask == NULL) {
|
||||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -230,7 +230,7 @@ int32_t mndAddShuffledSinkToStream(SMnode* pMnode, STrans* pTrans, SStreamObj* p
|
||||||
int32_t mndAddFixedSinkToStream(SMnode* pMnode, STrans* pTrans, SStreamObj* pStream) {
|
int32_t mndAddFixedSinkToStream(SMnode* pMnode, STrans* pTrans, SStreamObj* pStream) {
|
||||||
ASSERT(pStream->fixedSinkVgId != 0);
|
ASSERT(pStream->fixedSinkVgId != 0);
|
||||||
SArray* tasks = taosArrayGetP(pStream->tasks, 0);
|
SArray* tasks = taosArrayGetP(pStream->tasks, 0);
|
||||||
SStreamTask* pTask = tNewSStreamTask(pStream->uid);
|
SStreamTask* pTask = tNewSStreamTask(pStream->uid, 0);
|
||||||
if (pTask == NULL) {
|
if (pTask == NULL) {
|
||||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -322,7 +322,7 @@ int32_t mndScheduleStream(SMnode* pMnode, STrans* pTrans, SStreamObj* pStream) {
|
||||||
sdbRelease(pSdb, pVgroup);
|
sdbRelease(pSdb, pVgroup);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
SStreamTask* pTask = tNewSStreamTask(pStream->uid);
|
SStreamTask* pTask = tNewSStreamTask(pStream->uid, 0);
|
||||||
// source part
|
// source part
|
||||||
pTask->sourceType = TASK_SOURCE__SCAN;
|
pTask->sourceType = TASK_SOURCE__SCAN;
|
||||||
pTask->inputType = TASK_INPUT_TYPE__SUMBIT_BLOCK;
|
pTask->inputType = TASK_INPUT_TYPE__SUMBIT_BLOCK;
|
||||||
|
@ -387,7 +387,7 @@ int32_t mndScheduleStream(SMnode* pMnode, STrans* pTrans, SStreamObj* pStream) {
|
||||||
|
|
||||||
// else, assign to vnode
|
// else, assign to vnode
|
||||||
ASSERT(plan->subplanType == SUBPLAN_TYPE_MERGE);
|
ASSERT(plan->subplanType == SUBPLAN_TYPE_MERGE);
|
||||||
SStreamTask* pTask = tNewSStreamTask(pStream->uid);
|
SStreamTask* pTask = tNewSStreamTask(pStream->uid, 0);
|
||||||
|
|
||||||
// source part, currently only support multi source
|
// source part, currently only support multi source
|
||||||
pTask->sourceType = TASK_SOURCE__PIPE;
|
pTask->sourceType = TASK_SOURCE__PIPE;
|
||||||
|
@ -477,7 +477,7 @@ int32_t mndScheduleStream(SMnode* pMnode, STrans* pTrans, SStreamObj* pStream) {
|
||||||
sdbRelease(pSdb, pVgroup);
|
sdbRelease(pSdb, pVgroup);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
SStreamTask* pTask = tNewSStreamTask(pStream->uid);
|
SStreamTask* pTask = tNewSStreamTask(pStream->uid, 0);
|
||||||
|
|
||||||
// source part
|
// source part
|
||||||
pTask->sourceType = TASK_SOURCE__MERGE;
|
pTask->sourceType = TASK_SOURCE__MERGE;
|
||||||
|
|
|
@ -78,10 +78,10 @@ typedef struct {
|
||||||
tmr_h timerId;
|
tmr_h timerId;
|
||||||
int8_t tmrStopped;
|
int8_t tmrStopped;
|
||||||
// exec
|
// exec
|
||||||
int8_t inputStatus;
|
int8_t inputStatus;
|
||||||
int8_t execStatus;
|
int8_t execStatus;
|
||||||
SStreamQ inputQ;
|
SStreamQueue inputQ;
|
||||||
SRWLatch lock;
|
SRWLatch lock;
|
||||||
} STqPushHandle;
|
} STqPushHandle;
|
||||||
|
|
||||||
// tqExec
|
// tqExec
|
||||||
|
@ -107,7 +107,7 @@ typedef struct {
|
||||||
STqExecCol execCol;
|
STqExecCol execCol;
|
||||||
STqExecTb execTb;
|
STqExecTb execTb;
|
||||||
STqExecDb execDb;
|
STqExecDb execDb;
|
||||||
} exec;
|
};
|
||||||
} STqExecHandle;
|
} STqExecHandle;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -266,7 +266,7 @@ int32_t tqProcessVgChangeReq(STQ* pTq, char* msg, int32_t msgLen) {
|
||||||
pHandle->execHandle.pExecReader[i] = tqInitSubmitMsgScanner(pTq->pVnode->pMeta);
|
pHandle->execHandle.pExecReader[i] = tqInitSubmitMsgScanner(pTq->pVnode->pMeta);
|
||||||
}
|
}
|
||||||
if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) {
|
if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) {
|
||||||
pHandle->execHandle.exec.execCol.qmsg = req.qmsg;
|
pHandle->execHandle.execCol.qmsg = req.qmsg;
|
||||||
req.qmsg = NULL;
|
req.qmsg = NULL;
|
||||||
for (int32_t i = 0; i < 5; i++) {
|
for (int32_t i = 0; i < 5; i++) {
|
||||||
SReadHandle handle = {
|
SReadHandle handle = {
|
||||||
|
@ -274,15 +274,14 @@ int32_t tqProcessVgChangeReq(STQ* pTq, char* msg, int32_t msgLen) {
|
||||||
.meta = pTq->pVnode->pMeta,
|
.meta = pTq->pVnode->pMeta,
|
||||||
.pMsgCb = &pTq->pVnode->msgCb,
|
.pMsgCb = &pTq->pVnode->msgCb,
|
||||||
};
|
};
|
||||||
pHandle->execHandle.exec.execCol.task[i] =
|
pHandle->execHandle.execCol.task[i] = qCreateStreamExecTaskInfo(pHandle->execHandle.execCol.qmsg, &handle);
|
||||||
qCreateStreamExecTaskInfo(pHandle->execHandle.exec.execCol.qmsg, &handle);
|
ASSERT(pHandle->execHandle.execCol.task[i]);
|
||||||
ASSERT(pHandle->execHandle.exec.execCol.task[i]);
|
|
||||||
}
|
}
|
||||||
} else if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__DB) {
|
} else if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__DB) {
|
||||||
pHandle->execHandle.exec.execDb.pFilterOutTbUid =
|
pHandle->execHandle.execDb.pFilterOutTbUid =
|
||||||
taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
|
taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
|
||||||
} else if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__TABLE) {
|
} else if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__TABLE) {
|
||||||
pHandle->execHandle.exec.execTb.suid = req.suid;
|
pHandle->execHandle.execTb.suid = req.suid;
|
||||||
SArray* tbUidList = taosArrayInit(0, sizeof(int64_t));
|
SArray* tbUidList = taosArrayInit(0, sizeof(int64_t));
|
||||||
tsdbGetCtbIdList(pTq->pVnode->pMeta, req.suid, tbUidList);
|
tsdbGetCtbIdList(pTq->pVnode->pMeta, req.suid, tbUidList);
|
||||||
tqDebug("vg %d, tq try get suid: %ld", pTq->pVnode->config.vgId, req.suid);
|
tqDebug("vg %d, tq try get suid: %ld", pTq->pVnode->config.vgId, req.suid);
|
||||||
|
@ -296,17 +295,20 @@ int32_t tqProcessVgChangeReq(STQ* pTq, char* msg, int32_t msgLen) {
|
||||||
taosArrayDestroy(tbUidList);
|
taosArrayDestroy(tbUidList);
|
||||||
}
|
}
|
||||||
taosHashPut(pTq->handles, req.subKey, strlen(req.subKey), pHandle, sizeof(STqHandle));
|
taosHashPut(pTq->handles, req.subKey, strlen(req.subKey), pHandle, sizeof(STqHandle));
|
||||||
|
if (tqMetaSaveHandle(pTq, req.subKey, pHandle) < 0) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/*ASSERT(pExec->consumerId == req.oldConsumerId);*/
|
/*ASSERT(pExec->consumerId == req.oldConsumerId);*/
|
||||||
// TODO handle qmsg and exec modification
|
// TODO handle qmsg and exec modification
|
||||||
atomic_store_32(&pHandle->epoch, -1);
|
atomic_store_32(&pHandle->epoch, -1);
|
||||||
atomic_store_64(&pHandle->consumerId, req.newConsumerId);
|
atomic_store_64(&pHandle->consumerId, req.newConsumerId);
|
||||||
atomic_add_fetch_32(&pHandle->epoch, 1);
|
atomic_add_fetch_32(&pHandle->epoch, 1);
|
||||||
|
if (tqMetaSaveHandle(pTq, req.subKey, pHandle) < 0) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tqMetaSaveHandle(pTq, req.subKey, pHandle) < 0) {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,16 +325,13 @@ int32_t tqProcessTaskDeploy(STQ* pTq, char* msg, int32_t msgLen) {
|
||||||
tDecoderClear(&decoder);
|
tDecoderClear(&decoder);
|
||||||
|
|
||||||
pTask->status = TASK_STATUS__IDLE;
|
pTask->status = TASK_STATUS__IDLE;
|
||||||
|
|
||||||
|
pTask->inputQueue = streamQueueOpen();
|
||||||
|
pTask->outputQueue = streamQueueOpen();
|
||||||
pTask->inputStatus = TASK_INPUT_STATUS__NORMAL;
|
pTask->inputStatus = TASK_INPUT_STATUS__NORMAL;
|
||||||
pTask->outputStatus = TASK_OUTPUT_STATUS__NORMAL;
|
pTask->outputStatus = TASK_OUTPUT_STATUS__NORMAL;
|
||||||
|
|
||||||
pTask->inputQ = taosOpenQueue();
|
if (pTask->inputQueue == NULL || pTask->outputQueue == NULL) goto FAIL;
|
||||||
pTask->outputQ = taosOpenQueue();
|
|
||||||
pTask->inputQAll = taosAllocateQall();
|
|
||||||
pTask->outputQAll = taosAllocateQall();
|
|
||||||
|
|
||||||
if (pTask->inputQ == NULL || pTask->outputQ == NULL || pTask->inputQAll == NULL || pTask->outputQAll == NULL)
|
|
||||||
goto FAIL;
|
|
||||||
|
|
||||||
// exec
|
// exec
|
||||||
if (pTask->execType != TASK_EXEC__NONE) {
|
if (pTask->execType != TASK_EXEC__NONE) {
|
||||||
|
@ -369,10 +368,8 @@ int32_t tqProcessTaskDeploy(STQ* pTq, char* msg, int32_t msgLen) {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
FAIL:
|
FAIL:
|
||||||
if (pTask->inputQ) taosCloseQueue(pTask->inputQ);
|
if (pTask->inputQueue) streamQueueClose(pTask->inputQueue);
|
||||||
if (pTask->outputQ) taosCloseQueue(pTask->outputQ);
|
if (pTask->outputQueue) streamQueueClose(pTask->outputQueue);
|
||||||
if (pTask->inputQAll) taosFreeQall(pTask->inputQAll);
|
|
||||||
if (pTask->outputQAll) taosFreeQall(pTask->outputQAll);
|
|
||||||
if (pTask) taosMemoryFree(pTask);
|
if (pTask) taosMemoryFree(pTask);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -393,38 +390,16 @@ int32_t tqProcessStreamTrigger(STQ* pTq, SSubmitReq* pReq) {
|
||||||
SStreamTask* pTask = (SStreamTask*)pIter;
|
SStreamTask* pTask = (SStreamTask*)pIter;
|
||||||
if (pTask->inputType != STREAM_INPUT__DATA_SUBMIT) continue;
|
if (pTask->inputType != STREAM_INPUT__DATA_SUBMIT) continue;
|
||||||
|
|
||||||
int8_t inputStatus = atomic_load_8(&pTask->inputStatus);
|
if (!failed) {
|
||||||
if (inputStatus == TASK_INPUT_STATUS__NORMAL) {
|
if (streamTaskInput(pTask, (SStreamQueueItem*)pSubmit) < 0) {
|
||||||
if (failed) {
|
|
||||||
atomic_store_8(&pTask->inputStatus, TASK_INPUT_STATUS__FAILED);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
SStreamDataSubmit* pSubmitClone = streamSubmitRefClone(pSubmit);
|
if (streamTriggerByWrite(pTask, pTq->pVnode->config.vgId, &pTq->pVnode->msgCb) < 0) {
|
||||||
if (pSubmitClone == NULL) {
|
|
||||||
atomic_store_8(&pTask->inputStatus, TASK_INPUT_STATUS__FAILED);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
taosWriteQitem(pTask->inputQ, pSubmitClone);
|
|
||||||
|
|
||||||
int8_t execStatus = atomic_load_8(&pTask->status);
|
|
||||||
if (execStatus == TASK_STATUS__IDLE || execStatus == TASK_STATUS__CLOSING) {
|
|
||||||
SStreamTaskRunReq* pRunReq = taosMemoryMalloc(sizeof(SStreamTaskRunReq));
|
|
||||||
if (pRunReq == NULL) continue;
|
|
||||||
// TODO: do we need htonl?
|
|
||||||
pRunReq->head.vgId = pTq->pVnode->config.vgId;
|
|
||||||
pRunReq->streamId = pTask->streamId;
|
|
||||||
pRunReq->taskId = pTask->taskId;
|
|
||||||
SRpcMsg msg = {
|
|
||||||
.msgType = TDMT_VND_TASK_RUN,
|
|
||||||
.pCont = pRunReq,
|
|
||||||
.contLen = sizeof(SStreamTaskRunReq),
|
|
||||||
};
|
|
||||||
tmsgPutToQueue(&pTq->pVnode->msgCb, FETCH_QUEUE, &msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// blocked or stopped, do nothing
|
streamTaskInputFail(pTask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ static int32_t tqAddTbNameToRsp(const STQ* pTq, const STqExecHandle* pExec, SMqD
|
||||||
|
|
||||||
int32_t tqDataExec(STQ* pTq, STqExecHandle* pExec, SSubmitReq* pReq, SMqDataBlkRsp* pRsp, int32_t workerId) {
|
int32_t tqDataExec(STQ* pTq, STqExecHandle* pExec, SSubmitReq* pReq, SMqDataBlkRsp* pRsp, int32_t workerId) {
|
||||||
if (pExec->subType == TOPIC_SUB_TYPE__COLUMN) {
|
if (pExec->subType == TOPIC_SUB_TYPE__COLUMN) {
|
||||||
qTaskInfo_t task = pExec->exec.execCol.task[workerId];
|
qTaskInfo_t task = pExec->execCol.task[workerId];
|
||||||
ASSERT(task);
|
ASSERT(task);
|
||||||
qSetStreamInput(task, pReq, STREAM_DATA_TYPE_SUBMIT_BLOCK, false);
|
qSetStreamInput(task, pReq, STREAM_DATA_TYPE_SUBMIT_BLOCK, false);
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -101,7 +101,7 @@ int32_t tqDataExec(STQ* pTq, STqExecHandle* pExec, SSubmitReq* pReq, SMqDataBlkR
|
||||||
pRsp->withSchema = 1;
|
pRsp->withSchema = 1;
|
||||||
STqReadHandle* pReader = pExec->pExecReader[workerId];
|
STqReadHandle* pReader = pExec->pExecReader[workerId];
|
||||||
tqReadHandleSetMsg(pReader, pReq, 0);
|
tqReadHandleSetMsg(pReader, pReq, 0);
|
||||||
while (tqNextDataBlockFilterOut(pReader, pExec->exec.execDb.pFilterOutTbUid)) {
|
while (tqNextDataBlockFilterOut(pReader, pExec->execDb.pFilterOutTbUid)) {
|
||||||
SSDataBlock block = {0};
|
SSDataBlock block = {0};
|
||||||
if (tqRetrieveDataBlock(&block.pDataBlock, pReader, &block.info.groupId, &block.info.uid, &block.info.rows,
|
if (tqRetrieveDataBlock(&block.pDataBlock, pReader, &block.info.groupId, &block.info.uid, &block.info.rows,
|
||||||
&block.info.numOfCols) < 0) {
|
&block.info.numOfCols) < 0) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ static int32_t tEncodeSTqHandle(SEncoder* pEncoder, const STqHandle* pHandle) {
|
||||||
if (tEncodeI32(pEncoder, pHandle->epoch) < 0) return -1;
|
if (tEncodeI32(pEncoder, pHandle->epoch) < 0) return -1;
|
||||||
if (tEncodeI8(pEncoder, pHandle->execHandle.subType) < 0) return -1;
|
if (tEncodeI8(pEncoder, pHandle->execHandle.subType) < 0) return -1;
|
||||||
if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) {
|
if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) {
|
||||||
if (tEncodeCStr(pEncoder, pHandle->execHandle.exec.execCol.qmsg) < 0) return -1;
|
if (tEncodeCStr(pEncoder, pHandle->execHandle.execCol.qmsg) < 0) return -1;
|
||||||
}
|
}
|
||||||
tEndEncode(pEncoder);
|
tEndEncode(pEncoder);
|
||||||
return pEncoder->pos;
|
return pEncoder->pos;
|
||||||
|
@ -35,7 +35,7 @@ static int32_t tDecodeSTqHandle(SDecoder* pDecoder, STqHandle* pHandle) {
|
||||||
if (tDecodeI32(pDecoder, &pHandle->epoch) < 0) return -1;
|
if (tDecodeI32(pDecoder, &pHandle->epoch) < 0) return -1;
|
||||||
if (tDecodeI8(pDecoder, &pHandle->execHandle.subType) < 0) return -1;
|
if (tDecodeI8(pDecoder, &pHandle->execHandle.subType) < 0) return -1;
|
||||||
if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) {
|
if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) {
|
||||||
if (tDecodeCStrAlloc(pDecoder, &pHandle->execHandle.exec.execCol.qmsg) < 0) return -1;
|
if (tDecodeCStrAlloc(pDecoder, &pHandle->execHandle.execCol.qmsg) < 0) return -1;
|
||||||
}
|
}
|
||||||
tEndDecode(pDecoder);
|
tEndDecode(pDecoder);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -88,12 +88,11 @@ int32_t tqMetaOpen(STQ* pTq) {
|
||||||
.meta = pTq->pVnode->pMeta,
|
.meta = pTq->pVnode->pMeta,
|
||||||
.pMsgCb = &pTq->pVnode->msgCb,
|
.pMsgCb = &pTq->pVnode->msgCb,
|
||||||
};
|
};
|
||||||
handle.execHandle.exec.execCol.task[i] =
|
handle.execHandle.execCol.task[i] = qCreateStreamExecTaskInfo(handle.execHandle.execCol.qmsg, &reader);
|
||||||
qCreateStreamExecTaskInfo(handle.execHandle.exec.execCol.qmsg, &reader);
|
ASSERT(handle.execHandle.execCol.task[i]);
|
||||||
ASSERT(handle.execHandle.exec.execCol.task[i]);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
handle.execHandle.exec.execDb.pFilterOutTbUid =
|
handle.execHandle.execDb.pFilterOutTbUid =
|
||||||
taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
|
taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
|
||||||
}
|
}
|
||||||
taosHashPut(pTq->handles, pKey, kLen, &handle, sizeof(STqHandle));
|
taosHashPut(pTq->handles, pKey, kLen, &handle, sizeof(STqHandle));
|
||||||
|
|
|
@ -29,13 +29,13 @@ static int32_t tqLoopExecFromQueue(STQ* pTq, STqHandle* pHandle, SStreamDataSubm
|
||||||
}
|
}
|
||||||
// update processed
|
// update processed
|
||||||
atomic_store_64(&pHandle->pushHandle.processedVer, pSubmit->ver);
|
atomic_store_64(&pHandle->pushHandle.processedVer, pSubmit->ver);
|
||||||
streamQSetSuccess(&pHandle->pushHandle.inputQ);
|
streamQueueProcessSuccess(&pHandle->pushHandle.inputQ);
|
||||||
streamDataSubmitRefDec(pSubmit);
|
streamDataSubmitRefDec(pSubmit);
|
||||||
if (pRsp->blockNum > 0) {
|
if (pRsp->blockNum > 0) {
|
||||||
*ppSubmit = pSubmit;
|
*ppSubmit = pSubmit;
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
pSubmit = streamQNextItem(&pHandle->pushHandle.inputQ);
|
pSubmit = streamQueueNextItem(&pHandle->pushHandle.inputQ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*ppSubmit = pSubmit;
|
*ppSubmit = pSubmit;
|
||||||
|
@ -52,14 +52,14 @@ int32_t tqExecFromInputQ(STQ* pTq, STqHandle* pHandle) {
|
||||||
// 2. check processedVer
|
// 2. check processedVer
|
||||||
// 2.1. if not missed, get msg from queue
|
// 2.1. if not missed, get msg from queue
|
||||||
// 2.2. if missed, scan wal
|
// 2.2. if missed, scan wal
|
||||||
pSubmit = streamQNextItem(&pHandle->pushHandle.inputQ);
|
pSubmit = streamQueueNextItem(&pHandle->pushHandle.inputQ);
|
||||||
while (pHandle->pushHandle.processedVer <= pSubmit->ver) {
|
while (pHandle->pushHandle.processedVer <= pSubmit->ver) {
|
||||||
// read from wal
|
// read from wal
|
||||||
}
|
}
|
||||||
while (pHandle->pushHandle.processedVer > pSubmit->ver + 1) {
|
while (pHandle->pushHandle.processedVer > pSubmit->ver + 1) {
|
||||||
streamQSetSuccess(&pHandle->pushHandle.inputQ);
|
streamQueueProcessSuccess(&pHandle->pushHandle.inputQ);
|
||||||
streamDataSubmitRefDec(pSubmit);
|
streamDataSubmitRefDec(pSubmit);
|
||||||
pSubmit = streamQNextItem(&pHandle->pushHandle.inputQ);
|
pSubmit = streamQueueNextItem(&pHandle->pushHandle.inputQ);
|
||||||
if (pSubmit == NULL) break;
|
if (pSubmit == NULL) break;
|
||||||
}
|
}
|
||||||
// 3. exec, after each success, update processed ver
|
// 3. exec, after each success, update processed ver
|
||||||
|
|
|
@ -307,7 +307,7 @@ int32_t tqUpdateTbUidList(STQ* pTq, const SArray* tbUidList, bool isAdd) {
|
||||||
STqHandle* pExec = (STqHandle*)pIter;
|
STqHandle* pExec = (STqHandle*)pIter;
|
||||||
if (pExec->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) {
|
if (pExec->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) {
|
||||||
for (int32_t i = 0; i < 5; i++) {
|
for (int32_t i = 0; i < 5; i++) {
|
||||||
int32_t code = qUpdateQualifiedTableId(pExec->execHandle.exec.execCol.task[i], tbUidList, isAdd);
|
int32_t code = qUpdateQualifiedTableId(pExec->execHandle.execCol.task[i], tbUidList, isAdd);
|
||||||
ASSERT(code == 0);
|
ASSERT(code == 0);
|
||||||
}
|
}
|
||||||
} else if (pExec->execHandle.subType == TOPIC_SUB_TYPE__DB) {
|
} else if (pExec->execHandle.subType == TOPIC_SUB_TYPE__DB) {
|
||||||
|
@ -315,7 +315,7 @@ int32_t tqUpdateTbUidList(STQ* pTq, const SArray* tbUidList, bool isAdd) {
|
||||||
int32_t sz = taosArrayGetSize(tbUidList);
|
int32_t sz = taosArrayGetSize(tbUidList);
|
||||||
for (int32_t i = 0; i < sz; i++) {
|
for (int32_t i = 0; i < sz; i++) {
|
||||||
int64_t tbUid = *(int64_t*)taosArrayGet(tbUidList, i);
|
int64_t tbUid = *(int64_t*)taosArrayGet(tbUidList, i);
|
||||||
taosHashPut(pExec->execHandle.exec.execDb.pFilterOutTbUid, &tbUid, sizeof(int64_t), NULL, 0);
|
taosHashPut(pExec->execHandle.execDb.pFilterOutTbUid, &tbUid, sizeof(int64_t), NULL, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -13,15 +13,21 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _STREAM_INC_H_
|
||||||
|
#define _STREAM_INC_H_
|
||||||
|
|
||||||
|
#include "executor.h"
|
||||||
|
#include "tstream.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _TSTREAM_H_
|
int32_t streamExec(SStreamTask* pTask, SMsgCb* pMsgCb);
|
||||||
#define _TSTREAM_H_
|
int32_t streamSink1(SStreamTask* pTask, SMsgCb* pMsgCb);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* ifndef _TSTREAM_H_ */
|
#endif /* ifndef _STREAM_INC_H_ */
|
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
* 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 "streamInc.h"
|
||||||
|
|
||||||
|
int32_t streamTriggerByWrite(SStreamTask* pTask, int32_t vgId, SMsgCb* pMsgCb) {
|
||||||
|
int8_t execStatus = atomic_load_8(&pTask->status);
|
||||||
|
if (execStatus == TASK_STATUS__IDLE || execStatus == TASK_STATUS__CLOSING) {
|
||||||
|
SStreamTaskRunReq* pRunReq = rpcMallocCont(sizeof(SStreamTaskRunReq));
|
||||||
|
if (pRunReq == NULL) return -1;
|
||||||
|
|
||||||
|
// TODO: do we need htonl?
|
||||||
|
pRunReq->head.vgId = vgId;
|
||||||
|
pRunReq->streamId = pTask->streamId;
|
||||||
|
pRunReq->taskId = pTask->taskId;
|
||||||
|
SRpcMsg msg = {
|
||||||
|
.msgType = TDMT_VND_TASK_RUN,
|
||||||
|
.pCont = pRunReq,
|
||||||
|
.contLen = sizeof(SStreamTaskRunReq),
|
||||||
|
};
|
||||||
|
tmsgPutToQueue(pMsgCb, FETCH_QUEUE, &msg);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
int32_t streamTaskEnqueue(SStreamTask* pTask, SStreamDispatchReq* pReq, SRpcMsg* pRsp) {
|
||||||
|
SStreamDataBlock* pBlock = taosAllocateQitem(sizeof(SStreamDataBlock), DEF_QITEM);
|
||||||
|
int8_t status;
|
||||||
|
|
||||||
|
// enqueue
|
||||||
|
if (pBlock != NULL) {
|
||||||
|
pBlock->type = STREAM_DATA_TYPE_SSDATA_BLOCK;
|
||||||
|
pBlock->sourceVg = pReq->sourceVg;
|
||||||
|
pBlock->blocks = pReq->data;
|
||||||
|
/*pBlock->sourceVer = pReq->sourceVer;*/
|
||||||
|
if (streamTaskInput(pTask, (SStreamQueueItem*)pBlock) == 0) {
|
||||||
|
status = TASK_INPUT_STATUS__NORMAL;
|
||||||
|
} else {
|
||||||
|
status = TASK_INPUT_STATUS__FAILED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
streamTaskInputFail(pTask);
|
||||||
|
status = TASK_INPUT_STATUS__FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rsp by input status
|
||||||
|
SStreamDispatchRsp* pCont = rpcMallocCont(sizeof(SStreamDispatchRsp));
|
||||||
|
pCont->inputStatus = status;
|
||||||
|
pCont->streamId = pReq->streamId;
|
||||||
|
pCont->taskId = pReq->sourceTaskId;
|
||||||
|
pRsp->pCont = pCont;
|
||||||
|
pRsp->contLen = sizeof(SStreamDispatchRsp);
|
||||||
|
tmsgSendRsp(pRsp);
|
||||||
|
return status == TASK_INPUT_STATUS__NORMAL ? 0 : -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int32_t streamProcessDispatchReq(SStreamTask* pTask, SMsgCb* pMsgCb, SStreamDispatchReq* pReq, SRpcMsg* pRsp) {
|
||||||
|
// 1. handle input
|
||||||
|
streamTaskEnqueue(pTask, pReq, pRsp);
|
||||||
|
|
||||||
|
// 2. try exec
|
||||||
|
// 2.1. idle: exec
|
||||||
|
// 2.2. executing: return
|
||||||
|
// 2.3. closing: keep trying
|
||||||
|
streamExec(pTask, pMsgCb);
|
||||||
|
|
||||||
|
// 3. handle output
|
||||||
|
// 3.1 check and set status
|
||||||
|
// 3.2 dispatch / sink
|
||||||
|
streamSink1(pTask, pMsgCb);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t streamProcessDispatchRsp(SStreamTask* pTask, SMsgCb* pMsgCb, SStreamDispatchRsp* pRsp) {
|
||||||
|
if (pRsp->inputStatus == TASK_INPUT_STATUS__BLOCKED) {
|
||||||
|
// TODO: init recover timer
|
||||||
|
}
|
||||||
|
// continue dispatch
|
||||||
|
streamSink1(pTask, pMsgCb);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t streamTaskProcessRunReq(SStreamTask* pTask, SMsgCb* pMsgCb) {
|
||||||
|
streamExec(pTask, pMsgCb);
|
||||||
|
streamSink1(pTask, pMsgCb);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t streamProcessRecoverReq(SStreamTask* pTask, SMsgCb* pMsgCb, SStreamTaskRecoverReq* pReq, SRpcMsg* pMsg) {
|
||||||
|
//
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t streamProcessRecoverRsp(SStreamTask* pTask, SStreamTaskRecoverRsp* pRsp) {
|
||||||
|
//
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* 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 "tstream.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
int32_t streamDataBlockEncode(void** buf, const SStreamDataBlock* pOutput) {
|
||||||
|
int32_t tlen = 0;
|
||||||
|
tlen += taosEncodeFixedI8(buf, pOutput->type);
|
||||||
|
tlen += taosEncodeFixedI32(buf, pOutput->sourceVg);
|
||||||
|
tlen += taosEncodeFixedI64(buf, pOutput->sourceVer);
|
||||||
|
ASSERT(pOutput->type == STREAM_INPUT__DATA_BLOCK);
|
||||||
|
tlen += tEncodeDataBlocks(buf, pOutput->blocks);
|
||||||
|
return tlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* streamDataBlockDecode(const void* buf, SStreamDataBlock* pInput) {
|
||||||
|
buf = taosDecodeFixedI8(buf, &pInput->type);
|
||||||
|
buf = taosDecodeFixedI32(buf, &pInput->sourceVg);
|
||||||
|
buf = taosDecodeFixedI64(buf, &pInput->sourceVer);
|
||||||
|
ASSERT(pInput->type == STREAM_INPUT__DATA_BLOCK);
|
||||||
|
buf = tDecodeDataBlocks(buf, &pInput->blocks);
|
||||||
|
return (void*)buf;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SStreamDataSubmit* streamDataSubmitNew(SSubmitReq* pReq) {
|
||||||
|
SStreamDataSubmit* pDataSubmit = (SStreamDataSubmit*)taosAllocateQitem(sizeof(SStreamDataSubmit), DEF_QITEM);
|
||||||
|
if (pDataSubmit == NULL) return NULL;
|
||||||
|
pDataSubmit->dataRef = (int32_t*)taosMemoryMalloc(sizeof(int32_t));
|
||||||
|
if (pDataSubmit->dataRef == NULL) goto FAIL;
|
||||||
|
pDataSubmit->data = pReq;
|
||||||
|
*pDataSubmit->dataRef = 1;
|
||||||
|
pDataSubmit->type = STREAM_INPUT__DATA_SUBMIT;
|
||||||
|
return pDataSubmit;
|
||||||
|
FAIL:
|
||||||
|
taosFreeQitem(pDataSubmit);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FORCE_INLINE void streamDataSubmitRefInc(SStreamDataSubmit* pDataSubmit) {
|
||||||
|
//
|
||||||
|
atomic_add_fetch_32(pDataSubmit->dataRef, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
SStreamDataSubmit* streamSubmitRefClone(SStreamDataSubmit* pSubmit) {
|
||||||
|
SStreamDataSubmit* pSubmitClone = taosAllocateQitem(sizeof(SStreamDataSubmit), DEF_QITEM);
|
||||||
|
if (pSubmitClone == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
streamDataSubmitRefInc(pSubmit);
|
||||||
|
memcpy(pSubmitClone, pSubmit, sizeof(SStreamDataSubmit));
|
||||||
|
return pSubmitClone;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
int32_t tEncodeSStreamTaskExecReq(void** buf, const SStreamTaskExecReq* pReq) {
|
||||||
|
int32_t tlen = 0;
|
||||||
|
tlen += taosEncodeFixedI64(buf, pReq->streamId);
|
||||||
|
tlen += taosEncodeFixedI32(buf, pReq->taskId);
|
||||||
|
tlen += tEncodeDataBlocks(buf, pReq->data);
|
||||||
|
return tlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* tDecodeSStreamTaskExecReq(const void* buf, SStreamTaskExecReq* pReq) {
|
||||||
|
buf = taosDecodeFixedI64(buf, &pReq->streamId);
|
||||||
|
buf = taosDecodeFixedI32(buf, &pReq->taskId);
|
||||||
|
buf = tDecodeDataBlocks(buf, &pReq->data);
|
||||||
|
return (void*)buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tFreeSStreamTaskExecReq(SStreamTaskExecReq* pReq) { taosArrayDestroy(pReq->data); }
|
||||||
|
#endif
|
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* 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 "executor.h"
|
||||||
|
#include "tstream.h"
|
||||||
|
|
||||||
|
static int32_t streamTaskExecImpl(SStreamTask* pTask, void* data, SArray* pRes) {
|
||||||
|
void* exec = pTask->exec.executor;
|
||||||
|
|
||||||
|
// set input
|
||||||
|
if (pTask->inputType == STREAM_INPUT__DATA_SUBMIT) {
|
||||||
|
SStreamDataSubmit* pSubmit = (SStreamDataSubmit*)data;
|
||||||
|
ASSERT(pSubmit->type == STREAM_INPUT__DATA_SUBMIT);
|
||||||
|
|
||||||
|
qSetStreamInput(exec, pSubmit->data, STREAM_DATA_TYPE_SUBMIT_BLOCK, false);
|
||||||
|
} else if (pTask->inputType == STREAM_INPUT__DATA_BLOCK) {
|
||||||
|
SStreamDataBlock* pBlock = (SStreamDataBlock*)data;
|
||||||
|
ASSERT(pBlock->type == STREAM_INPUT__DATA_BLOCK);
|
||||||
|
|
||||||
|
SArray* blocks = pBlock->blocks;
|
||||||
|
qSetMultiStreamInput(exec, blocks->pData, blocks->size, STREAM_DATA_TYPE_SSDATA_BLOCK, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// exec
|
||||||
|
while (1) {
|
||||||
|
SSDataBlock* output = NULL;
|
||||||
|
uint64_t ts = 0;
|
||||||
|
if (qExecTask(exec, &output, &ts) < 0) {
|
||||||
|
ASSERT(false);
|
||||||
|
}
|
||||||
|
if (output == NULL) break;
|
||||||
|
// TODO: do we need free memory?
|
||||||
|
SSDataBlock* outputCopy = createOneDataBlock(output, true);
|
||||||
|
taosArrayPush(pRes, outputCopy);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SArray* streamExecForQall(SStreamTask* pTask, SArray* pRes) {
|
||||||
|
while (1) {
|
||||||
|
void* data = streamQueueNextItem(pTask->inputQueue);
|
||||||
|
if (data == NULL) break;
|
||||||
|
|
||||||
|
streamTaskExecImpl(pTask, data, pRes);
|
||||||
|
|
||||||
|
if (taosArrayGetSize(pRes) != 0) {
|
||||||
|
SStreamDataBlock* qRes = taosAllocateQitem(sizeof(SStreamDataBlock), DEF_QITEM);
|
||||||
|
if (qRes == NULL) {
|
||||||
|
streamQueueProcessFail(pTask->inputQueue);
|
||||||
|
taosArrayDestroy(pRes);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
qRes->type = STREAM_INPUT__DATA_BLOCK;
|
||||||
|
qRes->blocks = pRes;
|
||||||
|
if (streamTaskOutput(pTask, qRes) < 0) {
|
||||||
|
streamQueueProcessFail(pTask->inputQueue);
|
||||||
|
taosArrayDestroy(pRes);
|
||||||
|
taosFreeQitem(qRes);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pTask->inputType == STREAM_INPUT__DATA_SUBMIT) {
|
||||||
|
streamDataSubmitRefDec((SStreamDataSubmit*)data);
|
||||||
|
taosFreeQitem(data);
|
||||||
|
} else {
|
||||||
|
taosArrayDestroyEx(((SStreamDataBlock*)data)->blocks, (FDelete)tDeleteSSDataBlock);
|
||||||
|
taosFreeQitem(data);
|
||||||
|
}
|
||||||
|
streamQueueProcessSuccess(pTask->inputQueue);
|
||||||
|
return taosArrayInit(0, sizeof(SSDataBlock));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: handle version
|
||||||
|
int32_t streamExec(SStreamTask* pTask, SMsgCb* pMsgCb) {
|
||||||
|
SArray* pRes = taosArrayInit(0, sizeof(SSDataBlock));
|
||||||
|
if (pRes == NULL) return -1;
|
||||||
|
while (1) {
|
||||||
|
int8_t execStatus = atomic_val_compare_exchange_8(&pTask->status, TASK_STATUS__IDLE, TASK_STATUS__EXECUTING);
|
||||||
|
if (execStatus == TASK_STATUS__IDLE) {
|
||||||
|
// first run
|
||||||
|
pRes = streamExecForQall(pTask, pRes);
|
||||||
|
if (pRes == NULL) goto FAIL;
|
||||||
|
|
||||||
|
// set status closing
|
||||||
|
atomic_store_8(&pTask->status, TASK_STATUS__CLOSING);
|
||||||
|
|
||||||
|
// second run, make sure inputQ and qall are cleared
|
||||||
|
pRes = streamExecForQall(pTask, pRes);
|
||||||
|
if (pRes == NULL) goto FAIL;
|
||||||
|
|
||||||
|
break;
|
||||||
|
} else if (execStatus == TASK_STATUS__CLOSING) {
|
||||||
|
continue;
|
||||||
|
} else if (execStatus == TASK_STATUS__EXECUTING) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
ASSERT(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pRes) taosArrayDestroy(pRes);
|
||||||
|
atomic_store_8(&pTask->status, TASK_STATUS__IDLE);
|
||||||
|
return 0;
|
||||||
|
FAIL:
|
||||||
|
if (pRes) taosArrayDestroy(pRes);
|
||||||
|
atomic_store_8(&pTask->status, TASK_STATUS__IDLE);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
/*
|
||||||
|
* 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 "tstream.h"
|
||||||
|
|
||||||
|
int32_t tEncodeStreamDispatchReq(SEncoder* pEncoder, const SStreamDispatchReq* pReq) {
|
||||||
|
if (tStartEncode(pEncoder) < 0) return -1;
|
||||||
|
if (tEncodeI64(pEncoder, pReq->streamId) < 0) return -1;
|
||||||
|
if (tEncodeI32(pEncoder, pReq->taskId) < 0) return -1;
|
||||||
|
if (tEncodeI32(pEncoder, pReq->sourceTaskId) < 0) return -1;
|
||||||
|
if (tEncodeI32(pEncoder, pReq->sourceVg) < 0) return -1;
|
||||||
|
if (tEncodeI32(pEncoder, pReq->sourceChildId) < 0) return -1;
|
||||||
|
if (tEncodeI32(pEncoder, pReq->blockNum) < 0) return -1;
|
||||||
|
ASSERT(taosArrayGetSize(pReq->data) == pReq->blockNum);
|
||||||
|
ASSERT(taosArrayGetSize(pReq->dataLen) == pReq->blockNum);
|
||||||
|
for (int32_t i = 0; i < pReq->blockNum; i++) {
|
||||||
|
int32_t len = *(int32_t*)taosArrayGet(pReq->dataLen, i);
|
||||||
|
void* data = taosArrayGetP(pReq->data, i);
|
||||||
|
if (tEncodeI32(pEncoder, len) < 0) return -1;
|
||||||
|
if (tEncodeBinary(pEncoder, data, len) < 0) return -1;
|
||||||
|
}
|
||||||
|
tEndEncode(pEncoder);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t tDecodeStreamDispatchReq(SDecoder* pDecoder, SStreamDispatchReq* pReq) {
|
||||||
|
if (tStartDecode(pDecoder) < 0) return -1;
|
||||||
|
if (tDecodeI64(pDecoder, &pReq->streamId) < 0) return -1;
|
||||||
|
if (tDecodeI32(pDecoder, &pReq->taskId) < 0) return -1;
|
||||||
|
if (tDecodeI32(pDecoder, &pReq->sourceTaskId) < 0) return -1;
|
||||||
|
if (tDecodeI32(pDecoder, &pReq->sourceVg) < 0) return -1;
|
||||||
|
if (tDecodeI32(pDecoder, &pReq->sourceChildId) < 0) return -1;
|
||||||
|
if (tDecodeI32(pDecoder, &pReq->blockNum) < 0) return -1;
|
||||||
|
ASSERT(pReq->blockNum > 0);
|
||||||
|
pReq->data = taosArrayInit(pReq->blockNum, sizeof(void*));
|
||||||
|
pReq->dataLen = taosArrayInit(pReq->blockNum, sizeof(int32_t));
|
||||||
|
for (int32_t i = 0; i < pReq->blockNum; i++) {
|
||||||
|
int32_t len1;
|
||||||
|
uint64_t len2;
|
||||||
|
void* data;
|
||||||
|
if (tDecodeI32(pDecoder, &len1) < 0) return -1;
|
||||||
|
if (tDecodeBinaryAlloc(pDecoder, &data, &len2) < 0) return -1;
|
||||||
|
ASSERT(len1 == len2);
|
||||||
|
taosArrayPush(pReq->dataLen, &len1);
|
||||||
|
taosArrayPush(pReq->data, &data);
|
||||||
|
}
|
||||||
|
tEndDecode(pDecoder);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t streamBuildDispatchMsg(SStreamTask* pTask, SArray* data, SRpcMsg* pMsg, SEpSet** ppEpSet) {
|
||||||
|
SStreamDispatchReq req = {
|
||||||
|
.streamId = pTask->streamId,
|
||||||
|
.data = data,
|
||||||
|
};
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t streamBuildExecMsg(SStreamTask* pTask, SArray* data, SRpcMsg* pMsg, SEpSet** ppEpSet) {
|
||||||
|
SStreamTaskExecReq req = {
|
||||||
|
.streamId = pTask->streamId,
|
||||||
|
.data = data,
|
||||||
|
};
|
||||||
|
|
||||||
|
int32_t tlen = sizeof(SMsgHead) + tEncodeSStreamTaskExecReq(NULL, &req);
|
||||||
|
void* buf = rpcMallocCont(tlen);
|
||||||
|
|
||||||
|
if (buf == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pTask->dispatchType == TASK_DISPATCH__INPLACE) {
|
||||||
|
((SMsgHead*)buf)->vgId = 0;
|
||||||
|
req.taskId = pTask->inplaceDispatcher.taskId;
|
||||||
|
|
||||||
|
} else if (pTask->dispatchType == TASK_DISPATCH__FIXED) {
|
||||||
|
((SMsgHead*)buf)->vgId = htonl(pTask->fixedEpDispatcher.nodeId);
|
||||||
|
*ppEpSet = &pTask->fixedEpDispatcher.epSet;
|
||||||
|
req.taskId = pTask->fixedEpDispatcher.taskId;
|
||||||
|
|
||||||
|
} else if (pTask->dispatchType == TASK_DISPATCH__SHUFFLE) {
|
||||||
|
// TODO use general name rule of schemaless
|
||||||
|
char ctbName[TSDB_TABLE_FNAME_LEN + 22] = {0};
|
||||||
|
// all groupId must be the same in an array
|
||||||
|
SSDataBlock* pBlock = taosArrayGet(data, 0);
|
||||||
|
sprintf(ctbName, "%s:%ld", pTask->shuffleDispatcher.stbFullName, pBlock->info.groupId);
|
||||||
|
|
||||||
|
// TODO: get hash function by hashMethod
|
||||||
|
|
||||||
|
// get groupId, compute hash value
|
||||||
|
uint32_t hashValue = MurmurHash3_32(ctbName, strlen(ctbName));
|
||||||
|
|
||||||
|
// get node
|
||||||
|
// TODO: optimize search process
|
||||||
|
SArray* vgInfo = pTask->shuffleDispatcher.dbInfo.pVgroupInfos;
|
||||||
|
int32_t sz = taosArrayGetSize(vgInfo);
|
||||||
|
int32_t nodeId = 0;
|
||||||
|
for (int32_t i = 0; i < sz; i++) {
|
||||||
|
SVgroupInfo* pVgInfo = taosArrayGet(vgInfo, i);
|
||||||
|
if (hashValue >= pVgInfo->hashBegin && hashValue <= pVgInfo->hashEnd) {
|
||||||
|
nodeId = pVgInfo->vgId;
|
||||||
|
req.taskId = pVgInfo->taskId;
|
||||||
|
*ppEpSet = &pVgInfo->epSet;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASSERT(nodeId != 0);
|
||||||
|
((SMsgHead*)buf)->vgId = htonl(nodeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* abuf = POINTER_SHIFT(buf, sizeof(SMsgHead));
|
||||||
|
tEncodeSStreamTaskExecReq(&abuf, &req);
|
||||||
|
|
||||||
|
pMsg->pCont = buf;
|
||||||
|
pMsg->contLen = tlen;
|
||||||
|
pMsg->code = 0;
|
||||||
|
pMsg->msgType = pTask->dispatchMsgType;
|
||||||
|
pMsg->info.noResp = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t streamShuffleDispatch(SStreamTask* pTask, SMsgCb* pMsgCb, SHashObj* data) {
|
||||||
|
void* pIter = NULL;
|
||||||
|
while (1) {
|
||||||
|
pIter = taosHashIterate(data, pIter);
|
||||||
|
if (pIter == NULL) return 0;
|
||||||
|
SArray* pData = *(SArray**)pIter;
|
||||||
|
SRpcMsg dispatchMsg = {0};
|
||||||
|
SEpSet* pEpSet;
|
||||||
|
if (streamBuildExecMsg(pTask, pData, &dispatchMsg, &pEpSet) < 0) {
|
||||||
|
ASSERT(0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tmsgSendReq(pEpSet, &dispatchMsg);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* 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 "tstream.h"
|
||||||
|
|
||||||
|
SStreamQueue* streamQueueOpen() {
|
||||||
|
SStreamQueue* pQueue = taosMemoryCalloc(1, sizeof(SStreamQueue));
|
||||||
|
if (pQueue == NULL) return NULL;
|
||||||
|
pQueue->queue = taosOpenQueue();
|
||||||
|
pQueue->qall = taosAllocateQall();
|
||||||
|
if (pQueue->queue == NULL || pQueue->qall == NULL) {
|
||||||
|
goto FAIL;
|
||||||
|
}
|
||||||
|
pQueue->status = STREAM_QUEUE__SUCESS;
|
||||||
|
return pQueue;
|
||||||
|
FAIL:
|
||||||
|
if (pQueue->queue) taosCloseQueue(pQueue->queue);
|
||||||
|
if (pQueue->qall) taosFreeQall(pQueue->qall);
|
||||||
|
taosMemoryFree(pQueue);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void streamQueueClose(SStreamQueue* queue) {
|
||||||
|
while (1) {
|
||||||
|
void* qItem = streamQueueNextItem(queue);
|
||||||
|
if (qItem)
|
||||||
|
taosFreeQitem(qItem);
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,157 @@
|
||||||
|
/*
|
||||||
|
* 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 "executor.h"
|
||||||
|
#include "tstream.h"
|
||||||
|
|
||||||
|
int32_t streamSink1(SStreamTask* pTask, SMsgCb* pMsgCb) {
|
||||||
|
SStreamQueue* queue;
|
||||||
|
if (pTask->execType == TASK_EXEC__NONE) {
|
||||||
|
queue = pTask->inputQueue;
|
||||||
|
} else {
|
||||||
|
queue = pTask->outputQueue;
|
||||||
|
}
|
||||||
|
/*if (streamDequeueBegin(queue) == true) {*/
|
||||||
|
/*return -1;*/
|
||||||
|
/*}*/
|
||||||
|
|
||||||
|
if (pTask->sinkType == TASK_SINK__TABLE || pTask->sinkType == TASK_SINK__SMA) {
|
||||||
|
ASSERT(pTask->dispatchType == TASK_DISPATCH__NONE);
|
||||||
|
while (1) {
|
||||||
|
SStreamDataBlock* pBlock = streamQueueNextItem(queue);
|
||||||
|
if (pBlock == NULL) break;
|
||||||
|
ASSERT(pBlock->type == STREAM_DATA_TYPE_SSDATA_BLOCK);
|
||||||
|
|
||||||
|
// local sink
|
||||||
|
if (pTask->sinkType == TASK_SINK__TABLE) {
|
||||||
|
pTask->tbSink.tbSinkFunc(pTask, pTask->tbSink.vnode, 0, pBlock->blocks);
|
||||||
|
} else if (pTask->sinkType == TASK_SINK__SMA) {
|
||||||
|
pTask->smaSink.smaSink(pTask->ahandle, pTask->smaSink.smaId, pBlock->blocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pTask->dispatchType == TASK_DISPATCH__INPLACE) {
|
||||||
|
ASSERT(queue == pTask->outputQueue);
|
||||||
|
} else if (pTask->dispatchType == TASK_DISPATCH__SHUFFLE) {
|
||||||
|
ASSERT(queue == pTask->outputQueue);
|
||||||
|
} else if (pTask->dispatchType == TASK_DISPATCH__FIXED) {
|
||||||
|
ASSERT(queue == pTask->outputQueue);
|
||||||
|
}
|
||||||
|
|
||||||
|
streamQueueProcessSuccess(queue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
int32_t streamSink(SStreamTask* pTask, SMsgCb* pMsgCb) {
|
||||||
|
bool firstRun = 1;
|
||||||
|
while (1) {
|
||||||
|
SStreamDataBlock* pBlock = NULL;
|
||||||
|
if (!firstRun) {
|
||||||
|
taosReadAllQitems(pTask->outputQ, pTask->outputQAll);
|
||||||
|
}
|
||||||
|
taosGetQitem(pTask->outputQAll, (void**)&pBlock);
|
||||||
|
if (pBlock == NULL) {
|
||||||
|
if (firstRun) {
|
||||||
|
firstRun = 0;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SArray* pRes = pBlock->blocks;
|
||||||
|
|
||||||
|
// sink
|
||||||
|
if (pTask->sinkType == TASK_SINK__TABLE) {
|
||||||
|
// blockDebugShowData(pRes);
|
||||||
|
pTask->tbSink.tbSinkFunc(pTask, pTask->tbSink.vnode, 0, pRes);
|
||||||
|
} else if (pTask->sinkType == TASK_SINK__SMA) {
|
||||||
|
pTask->smaSink.smaSink(pTask->ahandle, pTask->smaSink.smaId, pRes);
|
||||||
|
//
|
||||||
|
} else if (pTask->sinkType == TASK_SINK__FETCH) {
|
||||||
|
//
|
||||||
|
} else {
|
||||||
|
ASSERT(pTask->sinkType == TASK_SINK__NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// dispatch
|
||||||
|
// TODO dispatch guard
|
||||||
|
int8_t outputStatus = atomic_load_8(&pTask->outputStatus);
|
||||||
|
if (outputStatus == TASK_OUTPUT_STATUS__NORMAL) {
|
||||||
|
if (pTask->dispatchType == TASK_DISPATCH__INPLACE) {
|
||||||
|
SRpcMsg dispatchMsg = {0};
|
||||||
|
if (streamBuildExecMsg(pTask, pRes, &dispatchMsg, NULL) < 0) {
|
||||||
|
ASSERT(0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t qType;
|
||||||
|
if (pTask->dispatchMsgType == TDMT_VND_TASK_DISPATCH || pTask->dispatchMsgType == TDMT_SND_TASK_DISPATCH) {
|
||||||
|
qType = FETCH_QUEUE;
|
||||||
|
/*} else if (pTask->dispatchMsgType == TDMT_VND_TASK_MERGE_EXEC ||*/
|
||||||
|
/*pTask->dispatchMsgType == TDMT_SND_TASK_MERGE_EXEC) {*/
|
||||||
|
/*qType = MERGE_QUEUE;*/
|
||||||
|
/*} else if (pTask->dispatchMsgType == TDMT_VND_TASK_WRITE_EXEC) {*/
|
||||||
|
/*qType = WRITE_QUEUE;*/
|
||||||
|
} else {
|
||||||
|
ASSERT(0);
|
||||||
|
}
|
||||||
|
tmsgPutToQueue(pMsgCb, qType, &dispatchMsg);
|
||||||
|
|
||||||
|
} else if (pTask->dispatchType == TASK_DISPATCH__FIXED) {
|
||||||
|
SRpcMsg dispatchMsg = {0};
|
||||||
|
SEpSet* pEpSet = NULL;
|
||||||
|
if (streamBuildExecMsg(pTask, pRes, &dispatchMsg, &pEpSet) < 0) {
|
||||||
|
ASSERT(0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmsgSendReq(pEpSet, &dispatchMsg);
|
||||||
|
|
||||||
|
} else if (pTask->dispatchType == TASK_DISPATCH__SHUFFLE) {
|
||||||
|
SHashObj* pShuffleRes = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
|
||||||
|
if (pShuffleRes == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t sz = taosArrayGetSize(pRes);
|
||||||
|
for (int32_t i = 0; i < sz; i++) {
|
||||||
|
SSDataBlock* pDataBlock = taosArrayGet(pRes, i);
|
||||||
|
SArray* pArray = taosHashGet(pShuffleRes, &pDataBlock->info.groupId, sizeof(int64_t));
|
||||||
|
if (pArray == NULL) {
|
||||||
|
pArray = taosArrayInit(0, sizeof(SSDataBlock));
|
||||||
|
if (pArray == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
taosHashPut(pShuffleRes, &pDataBlock->info.groupId, sizeof(int64_t), &pArray, sizeof(void*));
|
||||||
|
}
|
||||||
|
taosArrayPush(pArray, pDataBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (streamShuffleDispatch(pTask, pMsgCb, pShuffleRes) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ASSERT(pTask->dispatchType == TASK_DISPATCH__NONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,138 @@
|
||||||
|
/*
|
||||||
|
* 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 "executor.h"
|
||||||
|
#include "tstream.h"
|
||||||
|
|
||||||
|
SStreamTask* tNewSStreamTask(int64_t streamId, int32_t childId) {
|
||||||
|
SStreamTask* pTask = (SStreamTask*)taosMemoryCalloc(1, sizeof(SStreamTask));
|
||||||
|
if (pTask == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
pTask->taskId = tGenIdPI32();
|
||||||
|
pTask->streamId = streamId;
|
||||||
|
pTask->childId = childId;
|
||||||
|
pTask->status = TASK_STATUS__IDLE;
|
||||||
|
pTask->inputStatus = TASK_INPUT_STATUS__NORMAL;
|
||||||
|
pTask->outputStatus = TASK_OUTPUT_STATUS__NORMAL;
|
||||||
|
|
||||||
|
return pTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t tEncodeSStreamTask(SEncoder* pEncoder, const SStreamTask* pTask) {
|
||||||
|
/*if (tStartEncode(pEncoder) < 0) return -1;*/
|
||||||
|
if (tEncodeI64(pEncoder, pTask->streamId) < 0) return -1;
|
||||||
|
if (tEncodeI32(pEncoder, pTask->taskId) < 0) return -1;
|
||||||
|
if (tEncodeI8(pEncoder, pTask->inputType) < 0) return -1;
|
||||||
|
if (tEncodeI8(pEncoder, pTask->status) < 0) return -1;
|
||||||
|
if (tEncodeI8(pEncoder, pTask->sourceType) < 0) return -1;
|
||||||
|
if (tEncodeI8(pEncoder, pTask->execType) < 0) return -1;
|
||||||
|
if (tEncodeI8(pEncoder, pTask->sinkType) < 0) return -1;
|
||||||
|
if (tEncodeI8(pEncoder, pTask->dispatchType) < 0) return -1;
|
||||||
|
if (tEncodeI16(pEncoder, pTask->dispatchMsgType) < 0) return -1;
|
||||||
|
|
||||||
|
if (tEncodeI32(pEncoder, pTask->childId) < 0) return -1;
|
||||||
|
if (tEncodeI32(pEncoder, pTask->nodeId) < 0) return -1;
|
||||||
|
if (tEncodeSEpSet(pEncoder, &pTask->epSet) < 0) return -1;
|
||||||
|
|
||||||
|
if (pTask->execType != TASK_EXEC__NONE) {
|
||||||
|
if (tEncodeI8(pEncoder, pTask->exec.parallelizable) < 0) return -1;
|
||||||
|
if (tEncodeCStr(pEncoder, pTask->exec.qmsg) < 0) return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pTask->sinkType == TASK_SINK__TABLE) {
|
||||||
|
if (tEncodeI64(pEncoder, pTask->tbSink.stbUid) < 0) return -1;
|
||||||
|
if (tEncodeCStr(pEncoder, pTask->tbSink.stbFullName) < 0) return -1;
|
||||||
|
if (tEncodeSSchemaWrapper(pEncoder, pTask->tbSink.pSchemaWrapper) < 0) return -1;
|
||||||
|
} else if (pTask->sinkType == TASK_SINK__SMA) {
|
||||||
|
if (tEncodeI64(pEncoder, pTask->smaSink.smaId) < 0) return -1;
|
||||||
|
} else if (pTask->sinkType == TASK_SINK__FETCH) {
|
||||||
|
if (tEncodeI8(pEncoder, pTask->fetchSink.reserved) < 0) return -1;
|
||||||
|
} else {
|
||||||
|
ASSERT(pTask->sinkType == TASK_SINK__NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pTask->dispatchType == TASK_DISPATCH__INPLACE) {
|
||||||
|
if (tEncodeI32(pEncoder, pTask->inplaceDispatcher.taskId) < 0) return -1;
|
||||||
|
} else if (pTask->dispatchType == TASK_DISPATCH__FIXED) {
|
||||||
|
if (tEncodeI32(pEncoder, pTask->fixedEpDispatcher.taskId) < 0) return -1;
|
||||||
|
if (tEncodeI32(pEncoder, pTask->fixedEpDispatcher.nodeId) < 0) return -1;
|
||||||
|
if (tEncodeSEpSet(pEncoder, &pTask->fixedEpDispatcher.epSet) < 0) return -1;
|
||||||
|
} else if (pTask->dispatchType == TASK_DISPATCH__SHUFFLE) {
|
||||||
|
if (tSerializeSUseDbRspImp(pEncoder, &pTask->shuffleDispatcher.dbInfo) < 0) return -1;
|
||||||
|
/*if (tEncodeI8(pEncoder, pTask->shuffleDispatcher.hashMethod) < 0) return -1;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/*tEndEncode(pEncoder);*/
|
||||||
|
return pEncoder->pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t tDecodeSStreamTask(SDecoder* pDecoder, SStreamTask* pTask) {
|
||||||
|
/*if (tStartDecode(pDecoder) < 0) return -1;*/
|
||||||
|
if (tDecodeI64(pDecoder, &pTask->streamId) < 0) return -1;
|
||||||
|
if (tDecodeI32(pDecoder, &pTask->taskId) < 0) return -1;
|
||||||
|
if (tDecodeI8(pDecoder, &pTask->inputType) < 0) return -1;
|
||||||
|
if (tDecodeI8(pDecoder, &pTask->status) < 0) return -1;
|
||||||
|
if (tDecodeI8(pDecoder, &pTask->sourceType) < 0) return -1;
|
||||||
|
if (tDecodeI8(pDecoder, &pTask->execType) < 0) return -1;
|
||||||
|
if (tDecodeI8(pDecoder, &pTask->sinkType) < 0) return -1;
|
||||||
|
if (tDecodeI8(pDecoder, &pTask->dispatchType) < 0) return -1;
|
||||||
|
if (tDecodeI16(pDecoder, &pTask->dispatchMsgType) < 0) return -1;
|
||||||
|
|
||||||
|
if (tDecodeI32(pDecoder, &pTask->childId) < 0) return -1;
|
||||||
|
if (tDecodeI32(pDecoder, &pTask->nodeId) < 0) return -1;
|
||||||
|
if (tDecodeSEpSet(pDecoder, &pTask->epSet) < 0) return -1;
|
||||||
|
|
||||||
|
if (pTask->execType != TASK_EXEC__NONE) {
|
||||||
|
if (tDecodeI8(pDecoder, &pTask->exec.parallelizable) < 0) return -1;
|
||||||
|
if (tDecodeCStrAlloc(pDecoder, &pTask->exec.qmsg) < 0) return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pTask->sinkType == TASK_SINK__TABLE) {
|
||||||
|
if (tDecodeI64(pDecoder, &pTask->tbSink.stbUid) < 0) return -1;
|
||||||
|
if (tDecodeCStrTo(pDecoder, pTask->tbSink.stbFullName) < 0) return -1;
|
||||||
|
pTask->tbSink.pSchemaWrapper = taosMemoryCalloc(1, sizeof(SSchemaWrapper));
|
||||||
|
if (pTask->tbSink.pSchemaWrapper == NULL) return -1;
|
||||||
|
if (tDecodeSSchemaWrapper(pDecoder, pTask->tbSink.pSchemaWrapper) < 0) return -1;
|
||||||
|
} else if (pTask->sinkType == TASK_SINK__SMA) {
|
||||||
|
if (tDecodeI64(pDecoder, &pTask->smaSink.smaId) < 0) return -1;
|
||||||
|
} else if (pTask->sinkType == TASK_SINK__FETCH) {
|
||||||
|
if (tDecodeI8(pDecoder, &pTask->fetchSink.reserved) < 0) return -1;
|
||||||
|
} else {
|
||||||
|
ASSERT(pTask->sinkType == TASK_SINK__NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pTask->dispatchType == TASK_DISPATCH__INPLACE) {
|
||||||
|
if (tDecodeI32(pDecoder, &pTask->inplaceDispatcher.taskId) < 0) return -1;
|
||||||
|
} else if (pTask->dispatchType == TASK_DISPATCH__FIXED) {
|
||||||
|
if (tDecodeI32(pDecoder, &pTask->fixedEpDispatcher.taskId) < 0) return -1;
|
||||||
|
if (tDecodeI32(pDecoder, &pTask->fixedEpDispatcher.nodeId) < 0) return -1;
|
||||||
|
if (tDecodeSEpSet(pDecoder, &pTask->fixedEpDispatcher.epSet) < 0) return -1;
|
||||||
|
} else if (pTask->dispatchType == TASK_DISPATCH__SHUFFLE) {
|
||||||
|
/*if (tDecodeI8(pDecoder, &pTask->shuffleDispatcher.hashMethod) < 0) return -1;*/
|
||||||
|
if (tDeserializeSUseDbRspImp(pDecoder, &pTask->shuffleDispatcher.dbInfo) < 0) return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*tEndDecode(pDecoder);*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tFreeSStreamTask(SStreamTask* pTask) {
|
||||||
|
streamQueueClose(pTask->inputQueue);
|
||||||
|
streamQueueClose(pTask->outputQueue);
|
||||||
|
if (pTask->exec.qmsg) taosMemoryFree(pTask->exec.qmsg);
|
||||||
|
qDestroyTask(pTask->exec.executor);
|
||||||
|
taosMemoryFree(pTask);
|
||||||
|
}
|
|
@ -1,594 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 "tstream.h"
|
|
||||||
#include "executor.h"
|
|
||||||
|
|
||||||
int32_t streamDataBlockEncode(void** buf, const SStreamDataBlock* pOutput) {
|
|
||||||
int32_t tlen = 0;
|
|
||||||
tlen += taosEncodeFixedI8(buf, pOutput->type);
|
|
||||||
tlen += taosEncodeFixedI32(buf, pOutput->sourceVg);
|
|
||||||
tlen += taosEncodeFixedI64(buf, pOutput->sourceVer);
|
|
||||||
ASSERT(pOutput->type == STREAM_INPUT__DATA_BLOCK);
|
|
||||||
tlen += tEncodeDataBlocks(buf, pOutput->blocks);
|
|
||||||
return tlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* streamDataBlockDecode(const void* buf, SStreamDataBlock* pInput) {
|
|
||||||
buf = taosDecodeFixedI8(buf, &pInput->type);
|
|
||||||
buf = taosDecodeFixedI32(buf, &pInput->sourceVg);
|
|
||||||
buf = taosDecodeFixedI64(buf, &pInput->sourceVer);
|
|
||||||
ASSERT(pInput->type == STREAM_INPUT__DATA_BLOCK);
|
|
||||||
buf = tDecodeDataBlocks(buf, &pInput->blocks);
|
|
||||||
return (void*)buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
SStreamDataSubmit* streamSubmitRefClone(SStreamDataSubmit* pSubmit) {
|
|
||||||
SStreamDataSubmit* pSubmitClone = taosAllocateQitem(sizeof(SStreamDataSubmit), DEF_QITEM);
|
|
||||||
if (pSubmitClone == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
streamDataSubmitRefInc(pSubmit);
|
|
||||||
memcpy(pSubmitClone, pSubmit, sizeof(SStreamDataSubmit));
|
|
||||||
return pSubmitClone;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t streamBuildDispatchMsg(SStreamTask* pTask, SArray* data, SRpcMsg* pMsg, SEpSet** ppEpSet) {
|
|
||||||
SStreamDispatchReq req = {
|
|
||||||
.streamId = pTask->streamId,
|
|
||||||
.data = data,
|
|
||||||
};
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t streamBuildExecMsg(SStreamTask* pTask, SArray* data, SRpcMsg* pMsg, SEpSet** ppEpSet) {
|
|
||||||
SStreamTaskExecReq req = {
|
|
||||||
.streamId = pTask->streamId,
|
|
||||||
.data = data,
|
|
||||||
};
|
|
||||||
|
|
||||||
int32_t tlen = sizeof(SMsgHead) + tEncodeSStreamTaskExecReq(NULL, &req);
|
|
||||||
void* buf = rpcMallocCont(tlen);
|
|
||||||
|
|
||||||
if (buf == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pTask->dispatchType == TASK_DISPATCH__INPLACE) {
|
|
||||||
((SMsgHead*)buf)->vgId = 0;
|
|
||||||
req.taskId = pTask->inplaceDispatcher.taskId;
|
|
||||||
|
|
||||||
} else if (pTask->dispatchType == TASK_DISPATCH__FIXED) {
|
|
||||||
((SMsgHead*)buf)->vgId = htonl(pTask->fixedEpDispatcher.nodeId);
|
|
||||||
*ppEpSet = &pTask->fixedEpDispatcher.epSet;
|
|
||||||
req.taskId = pTask->fixedEpDispatcher.taskId;
|
|
||||||
|
|
||||||
} else if (pTask->dispatchType == TASK_DISPATCH__SHUFFLE) {
|
|
||||||
// TODO use general name rule of schemaless
|
|
||||||
char ctbName[TSDB_TABLE_FNAME_LEN + 22] = {0};
|
|
||||||
// all groupId must be the same in an array
|
|
||||||
SSDataBlock* pBlock = taosArrayGet(data, 0);
|
|
||||||
sprintf(ctbName, "%s:%ld", pTask->shuffleDispatcher.stbFullName, pBlock->info.groupId);
|
|
||||||
|
|
||||||
// TODO: get hash function by hashMethod
|
|
||||||
|
|
||||||
// get groupId, compute hash value
|
|
||||||
uint32_t hashValue = MurmurHash3_32(ctbName, strlen(ctbName));
|
|
||||||
|
|
||||||
// get node
|
|
||||||
// TODO: optimize search process
|
|
||||||
SArray* vgInfo = pTask->shuffleDispatcher.dbInfo.pVgroupInfos;
|
|
||||||
int32_t sz = taosArrayGetSize(vgInfo);
|
|
||||||
int32_t nodeId = 0;
|
|
||||||
for (int32_t i = 0; i < sz; i++) {
|
|
||||||
SVgroupInfo* pVgInfo = taosArrayGet(vgInfo, i);
|
|
||||||
if (hashValue >= pVgInfo->hashBegin && hashValue <= pVgInfo->hashEnd) {
|
|
||||||
nodeId = pVgInfo->vgId;
|
|
||||||
req.taskId = pVgInfo->taskId;
|
|
||||||
*ppEpSet = &pVgInfo->epSet;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ASSERT(nodeId != 0);
|
|
||||||
((SMsgHead*)buf)->vgId = htonl(nodeId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* abuf = POINTER_SHIFT(buf, sizeof(SMsgHead));
|
|
||||||
tEncodeSStreamTaskExecReq(&abuf, &req);
|
|
||||||
|
|
||||||
pMsg->pCont = buf;
|
|
||||||
pMsg->contLen = tlen;
|
|
||||||
pMsg->code = 0;
|
|
||||||
pMsg->msgType = pTask->dispatchMsgType;
|
|
||||||
pMsg->info.noResp = 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t streamShuffleDispatch(SStreamTask* pTask, SMsgCb* pMsgCb, SHashObj* data) {
|
|
||||||
void* pIter = NULL;
|
|
||||||
while (1) {
|
|
||||||
pIter = taosHashIterate(data, pIter);
|
|
||||||
if (pIter == NULL) return 0;
|
|
||||||
SArray* pData = *(SArray**)pIter;
|
|
||||||
SRpcMsg dispatchMsg = {0};
|
|
||||||
SEpSet* pEpSet;
|
|
||||||
if (streamBuildExecMsg(pTask, pData, &dispatchMsg, &pEpSet) < 0) {
|
|
||||||
ASSERT(0);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
tmsgSendReq(pEpSet, &dispatchMsg);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t streamEnqueueDataSubmit(SStreamTask* pTask, SStreamDataSubmit* input) {
|
|
||||||
ASSERT(pTask->inputType == TASK_INPUT_TYPE__SUMBIT_BLOCK);
|
|
||||||
int8_t inputStatus = atomic_load_8(&pTask->inputStatus);
|
|
||||||
if (inputStatus == TASK_INPUT_STATUS__NORMAL) {
|
|
||||||
streamDataSubmitRefInc(input);
|
|
||||||
taosWriteQitem(pTask->inputQ, input);
|
|
||||||
}
|
|
||||||
return inputStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t streamEnqueueDataBlk(SStreamTask* pTask, SStreamDataBlock* input) {
|
|
||||||
ASSERT(pTask->inputType == TASK_INPUT_TYPE__DATA_BLOCK);
|
|
||||||
taosWriteQitem(pTask->inputQ, input);
|
|
||||||
int8_t inputStatus = atomic_load_8(&pTask->inputStatus);
|
|
||||||
return inputStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t streamTaskExecImpl(SStreamTask* pTask, void* data, SArray* pRes) {
|
|
||||||
void* exec = pTask->exec.executor;
|
|
||||||
|
|
||||||
// set input
|
|
||||||
if (pTask->inputType == STREAM_INPUT__DATA_SUBMIT) {
|
|
||||||
SStreamDataSubmit* pSubmit = (SStreamDataSubmit*)data;
|
|
||||||
ASSERT(pSubmit->type == STREAM_INPUT__DATA_SUBMIT);
|
|
||||||
|
|
||||||
qSetStreamInput(exec, pSubmit->data, STREAM_DATA_TYPE_SUBMIT_BLOCK, false);
|
|
||||||
} else if (pTask->inputType == STREAM_INPUT__DATA_BLOCK) {
|
|
||||||
SStreamDataBlock* pBlock = (SStreamDataBlock*)data;
|
|
||||||
ASSERT(pBlock->type == STREAM_INPUT__DATA_BLOCK);
|
|
||||||
|
|
||||||
SArray* blocks = pBlock->blocks;
|
|
||||||
qSetMultiStreamInput(exec, blocks->pData, blocks->size, STREAM_DATA_TYPE_SSDATA_BLOCK, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// exec
|
|
||||||
while (1) {
|
|
||||||
SSDataBlock* output = NULL;
|
|
||||||
uint64_t ts = 0;
|
|
||||||
if (qExecTask(exec, &output, &ts) < 0) {
|
|
||||||
ASSERT(false);
|
|
||||||
}
|
|
||||||
if (output == NULL) break;
|
|
||||||
// TODO: do we need free memory?
|
|
||||||
SSDataBlock* outputCopy = createOneDataBlock(output, true);
|
|
||||||
taosArrayPush(pRes, outputCopy);
|
|
||||||
}
|
|
||||||
|
|
||||||
// destroy
|
|
||||||
if (pTask->inputType == STREAM_INPUT__DATA_SUBMIT) {
|
|
||||||
streamDataSubmitRefDec((SStreamDataSubmit*)data);
|
|
||||||
taosFreeQitem(data);
|
|
||||||
} else {
|
|
||||||
taosArrayDestroyEx(((SStreamDataBlock*)data)->blocks, (FDelete)tDeleteSSDataBlock);
|
|
||||||
taosFreeQitem(data);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static SArray* streamExecForQall(SStreamTask* pTask, SArray* pRes) {
|
|
||||||
while (1) {
|
|
||||||
void* data = NULL;
|
|
||||||
taosGetQitem(pTask->inputQAll, &data);
|
|
||||||
if (data == NULL) break;
|
|
||||||
|
|
||||||
streamTaskExecImpl(pTask, data, pRes);
|
|
||||||
|
|
||||||
if (taosArrayGetSize(pRes) != 0) {
|
|
||||||
SStreamDataBlock* qRes = taosAllocateQitem(sizeof(SStreamDataBlock), DEF_QITEM);
|
|
||||||
qRes->type = STREAM_INPUT__DATA_BLOCK;
|
|
||||||
qRes->blocks = pRes;
|
|
||||||
taosWriteQitem(pTask->outputQ, qRes);
|
|
||||||
return taosArrayInit(0, sizeof(SSDataBlock));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return pRes;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: handle version
|
|
||||||
int32_t streamExec(SStreamTask* pTask, SMsgCb* pMsgCb) {
|
|
||||||
SArray* pRes = taosArrayInit(0, sizeof(SSDataBlock));
|
|
||||||
if (pRes == NULL) return -1;
|
|
||||||
while (1) {
|
|
||||||
int8_t execStatus = atomic_val_compare_exchange_8(&pTask->status, TASK_STATUS__IDLE, TASK_STATUS__EXECUTING);
|
|
||||||
if (execStatus == TASK_STATUS__IDLE) {
|
|
||||||
// first run, from qall, handle failure from last exec
|
|
||||||
pRes = streamExecForQall(pTask, pRes);
|
|
||||||
if (pRes == NULL) goto FAIL;
|
|
||||||
|
|
||||||
// second run, from inputQ
|
|
||||||
taosReadAllQitems(pTask->inputQ, pTask->inputQAll);
|
|
||||||
pRes = streamExecForQall(pTask, pRes);
|
|
||||||
if (pRes == NULL) goto FAIL;
|
|
||||||
|
|
||||||
// set status closing
|
|
||||||
atomic_store_8(&pTask->status, TASK_STATUS__CLOSING);
|
|
||||||
|
|
||||||
// third run, make sure inputQ and qall are cleared
|
|
||||||
taosReadAllQitems(pTask->inputQ, pTask->inputQAll);
|
|
||||||
pRes = streamExecForQall(pTask, pRes);
|
|
||||||
if (pRes == NULL) goto FAIL;
|
|
||||||
|
|
||||||
atomic_store_8(&pTask->status, TASK_STATUS__IDLE);
|
|
||||||
break;
|
|
||||||
} else if (execStatus == TASK_STATUS__CLOSING) {
|
|
||||||
continue;
|
|
||||||
} else if (execStatus == TASK_STATUS__EXECUTING) {
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
ASSERT(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
FAIL:
|
|
||||||
atomic_store_8(&pTask->status, TASK_STATUS__IDLE);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t streamSink(SStreamTask* pTask, SMsgCb* pMsgCb) {
|
|
||||||
bool firstRun = 1;
|
|
||||||
while (1) {
|
|
||||||
SStreamDataBlock* pBlock = NULL;
|
|
||||||
if (!firstRun) {
|
|
||||||
taosReadAllQitems(pTask->outputQ, pTask->outputQAll);
|
|
||||||
}
|
|
||||||
taosGetQitem(pTask->outputQAll, (void**)&pBlock);
|
|
||||||
if (pBlock == NULL) {
|
|
||||||
if (firstRun) {
|
|
||||||
firstRun = 0;
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SArray* pRes = pBlock->blocks;
|
|
||||||
|
|
||||||
// sink
|
|
||||||
if (pTask->sinkType == TASK_SINK__TABLE) {
|
|
||||||
// blockDebugShowData(pRes);
|
|
||||||
pTask->tbSink.tbSinkFunc(pTask, pTask->tbSink.vnode, 0, pRes);
|
|
||||||
} else if (pTask->sinkType == TASK_SINK__SMA) {
|
|
||||||
pTask->smaSink.smaSink(pTask->ahandle, pTask->smaSink.smaId, pRes);
|
|
||||||
//
|
|
||||||
} else if (pTask->sinkType == TASK_SINK__FETCH) {
|
|
||||||
//
|
|
||||||
} else {
|
|
||||||
ASSERT(pTask->sinkType == TASK_SINK__NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// dispatch
|
|
||||||
// TODO dispatch guard
|
|
||||||
int8_t outputStatus = atomic_load_8(&pTask->outputStatus);
|
|
||||||
if (outputStatus == TASK_OUTPUT_STATUS__NORMAL) {
|
|
||||||
if (pTask->dispatchType == TASK_DISPATCH__INPLACE) {
|
|
||||||
SRpcMsg dispatchMsg = {0};
|
|
||||||
if (streamBuildExecMsg(pTask, pRes, &dispatchMsg, NULL) < 0) {
|
|
||||||
ASSERT(0);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t qType;
|
|
||||||
if (pTask->dispatchMsgType == TDMT_VND_TASK_DISPATCH || pTask->dispatchMsgType == TDMT_SND_TASK_DISPATCH) {
|
|
||||||
qType = FETCH_QUEUE;
|
|
||||||
/*} else if (pTask->dispatchMsgType == TDMT_VND_TASK_MERGE_EXEC ||*/
|
|
||||||
/*pTask->dispatchMsgType == TDMT_SND_TASK_MERGE_EXEC) {*/
|
|
||||||
/*qType = MERGE_QUEUE;*/
|
|
||||||
/*} else if (pTask->dispatchMsgType == TDMT_VND_TASK_WRITE_EXEC) {*/
|
|
||||||
/*qType = WRITE_QUEUE;*/
|
|
||||||
} else {
|
|
||||||
ASSERT(0);
|
|
||||||
}
|
|
||||||
tmsgPutToQueue(pMsgCb, qType, &dispatchMsg);
|
|
||||||
|
|
||||||
} else if (pTask->dispatchType == TASK_DISPATCH__FIXED) {
|
|
||||||
SRpcMsg dispatchMsg = {0};
|
|
||||||
SEpSet* pEpSet = NULL;
|
|
||||||
if (streamBuildExecMsg(pTask, pRes, &dispatchMsg, &pEpSet) < 0) {
|
|
||||||
ASSERT(0);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmsgSendReq(pEpSet, &dispatchMsg);
|
|
||||||
|
|
||||||
} else if (pTask->dispatchType == TASK_DISPATCH__SHUFFLE) {
|
|
||||||
SHashObj* pShuffleRes = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
|
|
||||||
if (pShuffleRes == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t sz = taosArrayGetSize(pRes);
|
|
||||||
for (int32_t i = 0; i < sz; i++) {
|
|
||||||
SSDataBlock* pDataBlock = taosArrayGet(pRes, i);
|
|
||||||
SArray* pArray = taosHashGet(pShuffleRes, &pDataBlock->info.groupId, sizeof(int64_t));
|
|
||||||
if (pArray == NULL) {
|
|
||||||
pArray = taosArrayInit(0, sizeof(SSDataBlock));
|
|
||||||
if (pArray == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
taosHashPut(pShuffleRes, &pDataBlock->info.groupId, sizeof(int64_t), &pArray, sizeof(void*));
|
|
||||||
}
|
|
||||||
taosArrayPush(pArray, pDataBlock);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (streamShuffleDispatch(pTask, pMsgCb, pShuffleRes) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
ASSERT(pTask->dispatchType == TASK_DISPATCH__NONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t streamTaskEnqueue(SStreamTask* pTask, SStreamDispatchReq* pReq, SRpcMsg* pRsp) {
|
|
||||||
SStreamDataBlock* pBlock = taosAllocateQitem(sizeof(SStreamDataBlock), DEF_QITEM);
|
|
||||||
int8_t status;
|
|
||||||
|
|
||||||
// 1.1 update status
|
|
||||||
// TODO cal backpressure
|
|
||||||
if (pBlock == NULL) {
|
|
||||||
atomic_store_8(&pTask->inputStatus, TASK_INPUT_STATUS__FAILED);
|
|
||||||
status = TASK_INPUT_STATUS__FAILED;
|
|
||||||
} else {
|
|
||||||
status = atomic_load_8(&pTask->inputStatus);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1.2 enqueue
|
|
||||||
pBlock->type = STREAM_DATA_TYPE_SSDATA_BLOCK;
|
|
||||||
pBlock->sourceVg = pReq->sourceVg;
|
|
||||||
/*pBlock->sourceVer = pReq->sourceVer;*/
|
|
||||||
taosWriteQitem(pTask->inputQ, pBlock);
|
|
||||||
|
|
||||||
// 1.3 rsp by input status
|
|
||||||
SStreamDispatchRsp* pCont = rpcMallocCont(sizeof(SStreamDispatchRsp));
|
|
||||||
pCont->inputStatus = status;
|
|
||||||
pCont->streamId = pReq->streamId;
|
|
||||||
pCont->taskId = pReq->sourceTaskId;
|
|
||||||
pRsp->pCont = pCont;
|
|
||||||
pRsp->contLen = sizeof(SStreamDispatchRsp);
|
|
||||||
tmsgSendRsp(pRsp);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t streamProcessDispatchReq(SStreamTask* pTask, SMsgCb* pMsgCb, SStreamDispatchReq* pReq, SRpcMsg* pRsp) {
|
|
||||||
// 1. handle input
|
|
||||||
streamTaskEnqueue(pTask, pReq, pRsp);
|
|
||||||
|
|
||||||
// 2. try exec
|
|
||||||
// 2.1. idle: exec
|
|
||||||
// 2.2. executing: return
|
|
||||||
// 2.3. closing: keep trying
|
|
||||||
streamExec(pTask, pMsgCb);
|
|
||||||
|
|
||||||
// 3. handle output
|
|
||||||
// 3.1 check and set status
|
|
||||||
// 3.2 dispatch / sink
|
|
||||||
streamSink(pTask, pMsgCb);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t streamProcessDispatchRsp(SStreamTask* pTask, SMsgCb* pMsgCb, SStreamDispatchRsp* pRsp) {
|
|
||||||
atomic_store_8(&pTask->inputStatus, pRsp->inputStatus);
|
|
||||||
if (pRsp->inputStatus == TASK_INPUT_STATUS__BLOCKED) {
|
|
||||||
// TODO: init recover timer
|
|
||||||
}
|
|
||||||
// continue dispatch
|
|
||||||
streamSink(pTask, pMsgCb);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t streamTaskProcessRunReq(SStreamTask* pTask, SMsgCb* pMsgCb) {
|
|
||||||
streamExec(pTask, pMsgCb);
|
|
||||||
streamSink(pTask, pMsgCb);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t streamProcessRecoverReq(SStreamTask* pTask, SMsgCb* pMsgCb, SStreamTaskRecoverReq* pReq, SRpcMsg* pMsg) {
|
|
||||||
//
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t streamProcessRecoverRsp(SStreamTask* pTask, SStreamTaskRecoverRsp* pRsp) {
|
|
||||||
//
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t tEncodeStreamDispatchReq(SEncoder* pEncoder, const SStreamDispatchReq* pReq) {
|
|
||||||
if (tStartEncode(pEncoder) < 0) return -1;
|
|
||||||
if (tEncodeI64(pEncoder, pReq->streamId) < 0) return -1;
|
|
||||||
if (tEncodeI32(pEncoder, pReq->taskId) < 0) return -1;
|
|
||||||
if (tEncodeI32(pEncoder, pReq->sourceTaskId) < 0) return -1;
|
|
||||||
if (tEncodeI32(pEncoder, pReq->sourceVg) < 0) return -1;
|
|
||||||
tEndEncode(pEncoder);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t tDecodeStreamDispatchReq(SDecoder* pDecoder, SStreamDispatchReq* pReq) {
|
|
||||||
if (tStartDecode(pDecoder) < 0) return -1;
|
|
||||||
if (tDecodeI64(pDecoder, &pReq->streamId) < 0) return -1;
|
|
||||||
if (tDecodeI32(pDecoder, &pReq->taskId) < 0) return -1;
|
|
||||||
if (tDecodeI32(pDecoder, &pReq->sourceTaskId) < 0) return -1;
|
|
||||||
if (tDecodeI32(pDecoder, &pReq->sourceVg) < 0) return -1;
|
|
||||||
tEndDecode(pDecoder);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t tEncodeSStreamTaskExecReq(void** buf, const SStreamTaskExecReq* pReq) {
|
|
||||||
int32_t tlen = 0;
|
|
||||||
tlen += taosEncodeFixedI64(buf, pReq->streamId);
|
|
||||||
tlen += taosEncodeFixedI32(buf, pReq->taskId);
|
|
||||||
tlen += tEncodeDataBlocks(buf, pReq->data);
|
|
||||||
return tlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* tDecodeSStreamTaskExecReq(const void* buf, SStreamTaskExecReq* pReq) {
|
|
||||||
buf = taosDecodeFixedI64(buf, &pReq->streamId);
|
|
||||||
buf = taosDecodeFixedI32(buf, &pReq->taskId);
|
|
||||||
buf = tDecodeDataBlocks(buf, &pReq->data);
|
|
||||||
return (void*)buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tFreeSStreamTaskExecReq(SStreamTaskExecReq* pReq) { taosArrayDestroy(pReq->data); }
|
|
||||||
|
|
||||||
SStreamTask* tNewSStreamTask(int64_t streamId) {
|
|
||||||
SStreamTask* pTask = (SStreamTask*)taosMemoryCalloc(1, sizeof(SStreamTask));
|
|
||||||
if (pTask == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
pTask->taskId = tGenIdPI32();
|
|
||||||
pTask->streamId = streamId;
|
|
||||||
pTask->status = TASK_STATUS__IDLE;
|
|
||||||
|
|
||||||
return pTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t tEncodeSStreamTask(SEncoder* pEncoder, const SStreamTask* pTask) {
|
|
||||||
/*if (tStartEncode(pEncoder) < 0) return -1;*/
|
|
||||||
if (tEncodeI64(pEncoder, pTask->streamId) < 0) return -1;
|
|
||||||
if (tEncodeI32(pEncoder, pTask->taskId) < 0) return -1;
|
|
||||||
if (tEncodeI8(pEncoder, pTask->inputType) < 0) return -1;
|
|
||||||
if (tEncodeI8(pEncoder, pTask->status) < 0) return -1;
|
|
||||||
if (tEncodeI8(pEncoder, pTask->sourceType) < 0) return -1;
|
|
||||||
if (tEncodeI8(pEncoder, pTask->execType) < 0) return -1;
|
|
||||||
if (tEncodeI8(pEncoder, pTask->sinkType) < 0) return -1;
|
|
||||||
if (tEncodeI8(pEncoder, pTask->dispatchType) < 0) return -1;
|
|
||||||
if (tEncodeI16(pEncoder, pTask->dispatchMsgType) < 0) return -1;
|
|
||||||
|
|
||||||
if (tEncodeI32(pEncoder, pTask->nodeId) < 0) return -1;
|
|
||||||
if (tEncodeSEpSet(pEncoder, &pTask->epSet) < 0) return -1;
|
|
||||||
|
|
||||||
if (pTask->execType != TASK_EXEC__NONE) {
|
|
||||||
if (tEncodeI8(pEncoder, pTask->exec.parallelizable) < 0) return -1;
|
|
||||||
if (tEncodeCStr(pEncoder, pTask->exec.qmsg) < 0) return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pTask->sinkType == TASK_SINK__TABLE) {
|
|
||||||
if (tEncodeI64(pEncoder, pTask->tbSink.stbUid) < 0) return -1;
|
|
||||||
if (tEncodeCStr(pEncoder, pTask->tbSink.stbFullName) < 0) return -1;
|
|
||||||
if (tEncodeSSchemaWrapper(pEncoder, pTask->tbSink.pSchemaWrapper) < 0) return -1;
|
|
||||||
} else if (pTask->sinkType == TASK_SINK__SMA) {
|
|
||||||
if (tEncodeI64(pEncoder, pTask->smaSink.smaId) < 0) return -1;
|
|
||||||
} else if (pTask->sinkType == TASK_SINK__FETCH) {
|
|
||||||
if (tEncodeI8(pEncoder, pTask->fetchSink.reserved) < 0) return -1;
|
|
||||||
} else {
|
|
||||||
ASSERT(pTask->sinkType == TASK_SINK__NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pTask->dispatchType == TASK_DISPATCH__INPLACE) {
|
|
||||||
if (tEncodeI32(pEncoder, pTask->inplaceDispatcher.taskId) < 0) return -1;
|
|
||||||
} else if (pTask->dispatchType == TASK_DISPATCH__FIXED) {
|
|
||||||
if (tEncodeI32(pEncoder, pTask->fixedEpDispatcher.taskId) < 0) return -1;
|
|
||||||
if (tEncodeI32(pEncoder, pTask->fixedEpDispatcher.nodeId) < 0) return -1;
|
|
||||||
if (tEncodeSEpSet(pEncoder, &pTask->fixedEpDispatcher.epSet) < 0) return -1;
|
|
||||||
} else if (pTask->dispatchType == TASK_DISPATCH__SHUFFLE) {
|
|
||||||
if (tSerializeSUseDbRspImp(pEncoder, &pTask->shuffleDispatcher.dbInfo) < 0) return -1;
|
|
||||||
/*if (tEncodeI8(pEncoder, pTask->shuffleDispatcher.hashMethod) < 0) return -1;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/*tEndEncode(pEncoder);*/
|
|
||||||
return pEncoder->pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t tDecodeSStreamTask(SDecoder* pDecoder, SStreamTask* pTask) {
|
|
||||||
/*if (tStartDecode(pDecoder) < 0) return -1;*/
|
|
||||||
if (tDecodeI64(pDecoder, &pTask->streamId) < 0) return -1;
|
|
||||||
if (tDecodeI32(pDecoder, &pTask->taskId) < 0) return -1;
|
|
||||||
if (tDecodeI8(pDecoder, &pTask->inputType) < 0) return -1;
|
|
||||||
if (tDecodeI8(pDecoder, &pTask->status) < 0) return -1;
|
|
||||||
if (tDecodeI8(pDecoder, &pTask->sourceType) < 0) return -1;
|
|
||||||
if (tDecodeI8(pDecoder, &pTask->execType) < 0) return -1;
|
|
||||||
if (tDecodeI8(pDecoder, &pTask->sinkType) < 0) return -1;
|
|
||||||
if (tDecodeI8(pDecoder, &pTask->dispatchType) < 0) return -1;
|
|
||||||
if (tDecodeI16(pDecoder, &pTask->dispatchMsgType) < 0) return -1;
|
|
||||||
|
|
||||||
if (tDecodeI32(pDecoder, &pTask->nodeId) < 0) return -1;
|
|
||||||
if (tDecodeSEpSet(pDecoder, &pTask->epSet) < 0) return -1;
|
|
||||||
|
|
||||||
if (pTask->execType != TASK_EXEC__NONE) {
|
|
||||||
if (tDecodeI8(pDecoder, &pTask->exec.parallelizable) < 0) return -1;
|
|
||||||
if (tDecodeCStrAlloc(pDecoder, &pTask->exec.qmsg) < 0) return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pTask->sinkType == TASK_SINK__TABLE) {
|
|
||||||
if (tDecodeI64(pDecoder, &pTask->tbSink.stbUid) < 0) return -1;
|
|
||||||
if (tDecodeCStrTo(pDecoder, pTask->tbSink.stbFullName) < 0) return -1;
|
|
||||||
pTask->tbSink.pSchemaWrapper = taosMemoryCalloc(1, sizeof(SSchemaWrapper));
|
|
||||||
if (pTask->tbSink.pSchemaWrapper == NULL) return -1;
|
|
||||||
if (tDecodeSSchemaWrapper(pDecoder, pTask->tbSink.pSchemaWrapper) < 0) return -1;
|
|
||||||
} else if (pTask->sinkType == TASK_SINK__SMA) {
|
|
||||||
if (tDecodeI64(pDecoder, &pTask->smaSink.smaId) < 0) return -1;
|
|
||||||
} else if (pTask->sinkType == TASK_SINK__FETCH) {
|
|
||||||
if (tDecodeI8(pDecoder, &pTask->fetchSink.reserved) < 0) return -1;
|
|
||||||
} else {
|
|
||||||
ASSERT(pTask->sinkType == TASK_SINK__NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pTask->dispatchType == TASK_DISPATCH__INPLACE) {
|
|
||||||
if (tDecodeI32(pDecoder, &pTask->inplaceDispatcher.taskId) < 0) return -1;
|
|
||||||
} else if (pTask->dispatchType == TASK_DISPATCH__FIXED) {
|
|
||||||
if (tDecodeI32(pDecoder, &pTask->fixedEpDispatcher.taskId) < 0) return -1;
|
|
||||||
if (tDecodeI32(pDecoder, &pTask->fixedEpDispatcher.nodeId) < 0) return -1;
|
|
||||||
if (tDecodeSEpSet(pDecoder, &pTask->fixedEpDispatcher.epSet) < 0) return -1;
|
|
||||||
} else if (pTask->dispatchType == TASK_DISPATCH__SHUFFLE) {
|
|
||||||
/*if (tDecodeI8(pDecoder, &pTask->shuffleDispatcher.hashMethod) < 0) return -1;*/
|
|
||||||
if (tDeserializeSUseDbRspImp(pDecoder, &pTask->shuffleDispatcher.dbInfo) < 0) return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*tEndDecode(pDecoder);*/
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tFreeSStreamTask(SStreamTask* pTask) {
|
|
||||||
taosCloseQueue(pTask->inputQ);
|
|
||||||
taosCloseQueue(pTask->outputQ);
|
|
||||||
// TODO
|
|
||||||
if (pTask->exec.qmsg) taosMemoryFree(pTask->exec.qmsg);
|
|
||||||
qDestroyTask(pTask->exec.executor);
|
|
||||||
taosMemoryFree(pTask);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
int32_t tEncodeSStreamTaskExecReq(SCoder* pEncoder, const SStreamTaskExecReq* pReq) {
|
|
||||||
if (tEncodeI64(pEncoder, pReq->streamId) < 0) return -1;
|
|
||||||
if (tEncodeI32(pEncoder, pReq->taskId) < 0) return -1;
|
|
||||||
/*if (tEncodeDataBlocks(buf, pReq->streamId) < 0) return -1;*/
|
|
||||||
return pEncoder->size;
|
|
||||||
}
|
|
||||||
int32_t tDecodeSStreamTaskExecReq(SCoder* pDecoder, SStreamTaskExecReq* pReq) {
|
|
||||||
return pEncoder->size;
|
|
||||||
}
|
|
||||||
void tFreeSStreamTaskExecReq(SStreamTaskExecReq* pReq) {
|
|
||||||
taosArrayDestroyEx(pReq->data, tDeleteSSDataBlock);
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -34,11 +34,11 @@ typedef struct STaosQnode {
|
||||||
} STaosQnode;
|
} STaosQnode;
|
||||||
|
|
||||||
typedef struct STaosQueue {
|
typedef struct STaosQueue {
|
||||||
STaosQnode * head;
|
STaosQnode *head;
|
||||||
STaosQnode * tail;
|
STaosQnode *tail;
|
||||||
STaosQueue * next; // for queue set
|
STaosQueue *next; // for queue set
|
||||||
STaosQset * qset; // for queue set
|
STaosQset *qset; // for queue set
|
||||||
void * ahandle; // for queue set
|
void *ahandle; // for queue set
|
||||||
FItem itemFp;
|
FItem itemFp;
|
||||||
FItems itemsFp;
|
FItems itemsFp;
|
||||||
TdThreadMutex mutex;
|
TdThreadMutex mutex;
|
||||||
|
@ -47,8 +47,8 @@ typedef struct STaosQueue {
|
||||||
} STaosQueue;
|
} STaosQueue;
|
||||||
|
|
||||||
typedef struct STaosQset {
|
typedef struct STaosQset {
|
||||||
STaosQueue * head;
|
STaosQueue *head;
|
||||||
STaosQueue * current;
|
STaosQueue *current;
|
||||||
TdThreadMutex mutex;
|
TdThreadMutex mutex;
|
||||||
tsem_t sem;
|
tsem_t sem;
|
||||||
int32_t numOfQueues;
|
int32_t numOfQueues;
|
||||||
|
@ -86,7 +86,7 @@ void taosSetQueueFp(STaosQueue *queue, FItem itemFp, FItems itemsFp) {
|
||||||
void taosCloseQueue(STaosQueue *queue) {
|
void taosCloseQueue(STaosQueue *queue) {
|
||||||
if (queue == NULL) return;
|
if (queue == NULL) return;
|
||||||
STaosQnode *pTemp;
|
STaosQnode *pTemp;
|
||||||
STaosQset * qset;
|
STaosQset *qset;
|
||||||
|
|
||||||
taosThreadMutexLock(&queue->mutex);
|
taosThreadMutexLock(&queue->mutex);
|
||||||
STaosQnode *pNode = queue->head;
|
STaosQnode *pNode = queue->head;
|
||||||
|
@ -282,6 +282,8 @@ int32_t taosGetQitem(STaosQall *qall, void **ppItem) {
|
||||||
*ppItem = pNode->item;
|
*ppItem = pNode->item;
|
||||||
num = 1;
|
num = 1;
|
||||||
uTrace("item:%p is fetched", *ppItem);
|
uTrace("item:%p is fetched", *ppItem);
|
||||||
|
} else {
|
||||||
|
*ppItem = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return num;
|
return num;
|
||||||
|
|
Loading…
Reference in New Issue