Merge branch '3.0' of https://github.com/taosdata/TDengine into feature/tdb
This commit is contained in:
commit
ead430b46a
|
@ -47,13 +47,13 @@ option(
|
||||||
option(
|
option(
|
||||||
BUILD_WITH_UV
|
BUILD_WITH_UV
|
||||||
"If build with libuv"
|
"If build with libuv"
|
||||||
OFF
|
ON
|
||||||
)
|
)
|
||||||
|
|
||||||
option(
|
option(
|
||||||
BUILD_WITH_UV_TRANS
|
BUILD_WITH_UV_TRANS
|
||||||
"If build with libuv_trans "
|
"If build with libuv_trans "
|
||||||
OFF
|
ON
|
||||||
)
|
)
|
||||||
|
|
||||||
option(
|
option(
|
||||||
|
|
|
@ -23,8 +23,12 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int32_t compareStrPatternComp(const void* pLeft, const void* pRight);
|
int32_t compareStrPatternMatch(const void* pLeft, const void* pRight);
|
||||||
int32_t compareWStrPatternComp(const void* pLeft, const void* pRight);
|
int32_t compareStrPatternNotMatch(const void* pLeft, const void* pRight);
|
||||||
|
|
||||||
|
int32_t compareWStrPatternMatch(const void* pLeft, const void* pRight);
|
||||||
|
int32_t compareWStrPatternNotMatch(const void* pLeft, const void* pRight);
|
||||||
|
|
||||||
__compar_fn_t getComparFunc(int32_t type, int32_t optr);
|
__compar_fn_t getComparFunc(int32_t type, int32_t optr);
|
||||||
__compar_fn_t getKeyComparFunc(int32_t keyType, int32_t order);
|
__compar_fn_t getKeyComparFunc(int32_t keyType, int32_t order);
|
||||||
int32_t doCompare(const char* a, const char* b, int32_t type, size_t size);
|
int32_t doCompare(const char* a, const char* b, int32_t type, size_t size);
|
||||||
|
|
|
@ -16,6 +16,11 @@
|
||||||
#ifndef TDENGINE_TNAME_H
|
#ifndef TDENGINE_TNAME_H
|
||||||
#define TDENGINE_TNAME_H
|
#define TDENGINE_TNAME_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "tdef.h"
|
#include "tdef.h"
|
||||||
#include "tmsg.h"
|
#include "tmsg.h"
|
||||||
|
|
||||||
|
@ -59,4 +64,9 @@ int32_t tNameSetAcctId(SName* dst, int32_t acctId);
|
||||||
|
|
||||||
SSchema createSchema(uint8_t type, int32_t bytes, int32_t colId, const char* name);
|
SSchema createSchema(uint8_t type, int32_t bytes, int32_t colId, const char* name);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif // TDENGINE_TNAME_H
|
#endif // TDENGINE_TNAME_H
|
||||||
|
|
|
@ -78,9 +78,12 @@ typedef struct {
|
||||||
case TSDB_DATA_TYPE_UINT: \
|
case TSDB_DATA_TYPE_UINT: \
|
||||||
(_v) = (_finalType)GET_UINT32_VAL(_data); \
|
(_v) = (_finalType)GET_UINT32_VAL(_data); \
|
||||||
break; \
|
break; \
|
||||||
default: \
|
case TSDB_DATA_TYPE_INT: \
|
||||||
(_v) = (_finalType)GET_INT32_VAL(_data); \
|
(_v) = (_finalType)GET_INT32_VAL(_data); \
|
||||||
break; \
|
break; \
|
||||||
|
default: \
|
||||||
|
(_v) = (_finalType)varDataLen(_data); \
|
||||||
|
break; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -115,9 +118,11 @@ typedef struct {
|
||||||
case TSDB_DATA_TYPE_UINT: \
|
case TSDB_DATA_TYPE_UINT: \
|
||||||
*(uint32_t *)(_v) = (uint32_t)(_data); \
|
*(uint32_t *)(_v) = (uint32_t)(_data); \
|
||||||
break; \
|
break; \
|
||||||
default: \
|
case TSDB_DATA_TYPE_INT: \
|
||||||
*(int32_t *)(_v) = (int32_t)(_data); \
|
*(int32_t *)(_v) = (int32_t)(_data); \
|
||||||
break; \
|
break; \
|
||||||
|
default: \
|
||||||
|
break; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -138,6 +143,9 @@ typedef struct {
|
||||||
#define IS_VALID_FLOAT(_t) ((_t) >= -FLT_MAX && (_t) <= FLT_MAX)
|
#define IS_VALID_FLOAT(_t) ((_t) >= -FLT_MAX && (_t) <= FLT_MAX)
|
||||||
#define IS_VALID_DOUBLE(_t) ((_t) >= -DBL_MAX && (_t) <= DBL_MAX)
|
#define IS_VALID_DOUBLE(_t) ((_t) >= -DBL_MAX && (_t) <= DBL_MAX)
|
||||||
|
|
||||||
|
#define IS_CONVERT_AS_SIGNED(_t) (IS_SIGNED_NUMERIC_TYPE(_t) || (_t) == (TSDB_DATA_TYPE_BOOL) || (_t) == (TSDB_DATA_TYPE_TIMESTAMP))
|
||||||
|
#define IS_CONVERT_AS_UNSIGNED(_t) (IS_UNSIGNED_NUMERIC_TYPE(_t) || (_t) == (TSDB_DATA_TYPE_BOOL))
|
||||||
|
|
||||||
static FORCE_INLINE bool isNull(const void *val, int32_t type) {
|
static FORCE_INLINE bool isNull(const void *val, int32_t type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TSDB_DATA_TYPE_BOOL:
|
case TSDB_DATA_TYPE_BOOL:
|
||||||
|
@ -205,6 +213,7 @@ void* getDataMax(int32_t type);
|
||||||
|
|
||||||
|
|
||||||
#define SET_DOUBLE_NULL(v) (*(uint64_t *)(v) = TSDB_DATA_DOUBLE_NULL)
|
#define SET_DOUBLE_NULL(v) (*(uint64_t *)(v) = TSDB_DATA_DOUBLE_NULL)
|
||||||
|
#define SET_BIGINT_NULL(v) (*(uint64_t *)(v) = TSDB_DATA_BIGINT_NULL)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,13 +226,18 @@ typedef struct SAggFunctionInfo {
|
||||||
int32_t (*dataReqFunc)(SqlFunctionCtx *pCtx, STimeWindow* w, int32_t colId);
|
int32_t (*dataReqFunc)(SqlFunctionCtx *pCtx, STimeWindow* w, int32_t colId);
|
||||||
} SAggFunctionInfo;
|
} SAggFunctionInfo;
|
||||||
|
|
||||||
struct SScalarFuncParam;
|
typedef struct SScalarParam {
|
||||||
|
void* data;
|
||||||
|
int32_t num;
|
||||||
|
int32_t type;
|
||||||
|
int32_t bytes;
|
||||||
|
} SScalarParam;
|
||||||
|
|
||||||
typedef struct SScalarFunctionInfo {
|
typedef struct SScalarFunctionInfo {
|
||||||
char name[FUNCTIONS_NAME_MAX_LENGTH];
|
char name[FUNCTIONS_NAME_MAX_LENGTH];
|
||||||
int8_t type; // scalar function or aggregation function
|
int8_t type; // scalar function or aggregation function
|
||||||
uint32_t functionId; // index of scalar function
|
uint32_t functionId; // index of scalar function
|
||||||
void (*process)(struct SScalarFuncParam* pOutput, size_t numOfInput, const struct SScalarFuncParam *pInput);
|
void (*process)(struct SScalarParam* pOutput, size_t numOfInput, const struct SScalarParam *pInput);
|
||||||
} SScalarFunctionInfo;
|
} SScalarFunctionInfo;
|
||||||
|
|
||||||
typedef struct SMultiFunctionsDesc {
|
typedef struct SMultiFunctionsDesc {
|
||||||
|
@ -285,10 +290,6 @@ int32_t getNumOfResult(SqlFunctionCtx* pCtx, int32_t num);
|
||||||
bool isRowEntryCompleted(struct SResultRowEntryInfo* pEntry);
|
bool isRowEntryCompleted(struct SResultRowEntryInfo* pEntry);
|
||||||
bool isRowEntryInitialized(struct SResultRowEntryInfo* pEntry);
|
bool isRowEntryInitialized(struct SResultRowEntryInfo* pEntry);
|
||||||
|
|
||||||
struct SScalarFunctionSupport* createScalarFuncSupport(int32_t num);
|
|
||||||
void destroyScalarFuncSupport(struct SScalarFunctionSupport* pSupport, int32_t num);
|
|
||||||
struct SScalarFunctionSupport* getScalarFuncSupport(struct SScalarFunctionSupport* pSupport, int32_t index);
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// fill api
|
// fill api
|
||||||
struct SFillInfo;
|
struct SFillInfo;
|
||||||
|
|
|
@ -21,6 +21,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "querynodes.h"
|
#include "querynodes.h"
|
||||||
|
#include "function.h"
|
||||||
|
|
||||||
typedef enum EFunctionType {
|
typedef enum EFunctionType {
|
||||||
// aggregate function
|
// aggregate function
|
||||||
|
@ -117,6 +118,13 @@ typedef struct SFuncExecFuncs {
|
||||||
FExecFinalize finalize;
|
FExecFinalize finalize;
|
||||||
} SFuncExecFuncs;
|
} SFuncExecFuncs;
|
||||||
|
|
||||||
|
typedef int32_t (*FScalarExecProcess)(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||||
|
|
||||||
|
typedef struct SScalarFuncExecFuncs {
|
||||||
|
FScalarExecProcess process;
|
||||||
|
} SScalarFuncExecFuncs;
|
||||||
|
|
||||||
|
|
||||||
int32_t fmFuncMgtInit();
|
int32_t fmFuncMgtInit();
|
||||||
|
|
||||||
int32_t fmGetFuncInfo(const char* pFuncName, int32_t* pFuncId, int32_t* pFuncType);
|
int32_t fmGetFuncInfo(const char* pFuncName, int32_t* pFuncId, int32_t* pFuncType);
|
||||||
|
@ -134,6 +142,7 @@ bool fmIsTimeorderFunc(int32_t funcId);
|
||||||
int32_t fmFuncScanType(int32_t funcId);
|
int32_t fmFuncScanType(int32_t funcId);
|
||||||
|
|
||||||
int32_t fmGetFuncExecFuncs(int32_t funcId, SFuncExecFuncs* pFpSet);
|
int32_t fmGetFuncExecFuncs(int32_t funcId, SFuncExecFuncs* pFpSet);
|
||||||
|
int32_t fmGetScalarFuncExecFuncs(int32_t funcId, SScalarFuncExecFuncs* pFpSet);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,7 +132,7 @@ bool nodesEqualNode(const SNode* a, const SNode* b);
|
||||||
SNode* nodesCloneNode(const SNode* pNode);
|
SNode* nodesCloneNode(const SNode* pNode);
|
||||||
SNodeList* nodesCloneList(const SNodeList* pList);
|
SNodeList* nodesCloneList(const SNodeList* pList);
|
||||||
|
|
||||||
int32_t nodesNodeToString(const SNode* pNode, char** pStr, int32_t* pLen);
|
int32_t nodesNodeToString(const SNode* pNode, bool format, char** pStr, int32_t* pLen);
|
||||||
int32_t nodesStringToNode(const char* pStr, SNode** pNode);
|
int32_t nodesStringToNode(const char* pStr, SNode** pNode);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -306,6 +306,7 @@ bool nodesIsJsonOp(const SOperatorNode* pOp);
|
||||||
|
|
||||||
bool nodesIsTimeorderQuery(const SNode* pQuery);
|
bool nodesIsTimeorderQuery(const SNode* pQuery);
|
||||||
bool nodesIsTimelineQuery(const SNode* pQuery);
|
bool nodesIsTimelineQuery(const SNode* pQuery);
|
||||||
|
void *nodesGetValueFromNode(SValueNode *pNode);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
#ifndef TDENGINE_FILTER_H
|
||||||
|
#define TDENGINE_FILTER_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct SFilterInfo SFilterInfo;
|
||||||
|
|
||||||
|
typedef struct SFilterColumnParam{
|
||||||
|
int32_t numOfCols;
|
||||||
|
SArray* pDataBlock;
|
||||||
|
} SFilterColumnParam;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // TDENGINE_FILTER_H
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
#ifndef TDENGINE_SCALAR_H
|
||||||
|
#define TDENGINE_SCALAR_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "function.h"
|
||||||
|
#include "nodes.h"
|
||||||
|
#include "querynodes.h"
|
||||||
|
|
||||||
|
typedef struct SFilterInfo SFilterInfo;
|
||||||
|
|
||||||
|
|
||||||
|
int32_t scalarCalculateConstants(SNode *pNode, SNode **pRes);
|
||||||
|
int32_t scalarCalculate(SNode *pNode, SSDataBlock *pSrc, SScalarParam *pDst);
|
||||||
|
int32_t scalarGetOperatorParamNum(EOperatorType type);
|
||||||
|
|
||||||
|
int32_t vectorGetConvertType(int32_t type1, int32_t type2);
|
||||||
|
int32_t vectorConvertImpl(SScalarParam* pIn, SScalarParam* pOut);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // TDENGINE_SCALAR_H
|
|
@ -137,22 +137,21 @@ typedef struct {
|
||||||
|
|
||||||
} SSyncInfo;
|
} SSyncInfo;
|
||||||
|
|
||||||
// will be defined in syncInt.h, here just for complie
|
struct SSyncNode;
|
||||||
typedef struct SSyncNode {
|
typedef struct SSyncNode SSyncNode;
|
||||||
} SSyncNode;
|
|
||||||
|
|
||||||
int32_t syncInit();
|
int32_t syncInit();
|
||||||
void syncCleanUp();
|
void syncCleanUp();
|
||||||
|
|
||||||
int64_t syncStart(const SSyncInfo*);
|
int64_t syncStart(const SSyncInfo* pSyncInfo);
|
||||||
void syncStop(int64_t rid);
|
void syncStop(int64_t rid);
|
||||||
int32_t syncReconfig(int64_t rid, const SSyncCfg*);
|
int32_t syncReconfig(int64_t rid, const SSyncCfg* pSyncCfg);
|
||||||
|
|
||||||
// int32_t syncForwardToPeer(int64_t rid, const SRpcMsg* pBuf, bool isWeak);
|
// int32_t syncForwardToPeer(int64_t rid, const SRpcMsg* pBuf, bool isWeak);
|
||||||
int32_t syncForwardToPeer(int64_t rid, const SSyncBuffer* pBuf, bool isWeak);
|
int32_t syncForwardToPeer(int64_t rid, const SSyncBuffer* pBuf, bool isWeak);
|
||||||
|
|
||||||
ESyncState syncGetMyRole(int64_t rid);
|
ESyncState syncGetMyRole(int64_t rid);
|
||||||
void syncGetNodesRole(int64_t rid, SNodesRole*);
|
void syncGetNodesRole(int64_t rid, SNodesRole* pNodeRole);
|
||||||
|
|
||||||
extern int32_t sDebugFlag;
|
extern int32_t sDebugFlag;
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,7 @@ typedef struct SRpcInit {
|
||||||
int8_t connType; // TAOS_CONN_UDP, TAOS_CONN_TCPC, TAOS_CONN_TCPS
|
int8_t connType; // TAOS_CONN_UDP, TAOS_CONN_TCPC, TAOS_CONN_TCPS
|
||||||
int idleTime; // milliseconds, 0 means idle timer is disabled
|
int idleTime; // milliseconds, 0 means idle timer is disabled
|
||||||
|
|
||||||
|
bool noPool; // create conn pool or not
|
||||||
// the following is for client app ecurity only
|
// the following is for client app ecurity only
|
||||||
char *user; // user name
|
char *user; // user name
|
||||||
char spi; // security parameter index
|
char spi; // security parameter index
|
||||||
|
|
|
@ -49,10 +49,19 @@ int32_t WCSPatternMatch(const wchar_t *pattern, const wchar_t *str, size_t size,
|
||||||
|
|
||||||
int32_t taosArrayCompareString(const void *a, const void *b);
|
int32_t taosArrayCompareString(const void *a, const void *b);
|
||||||
|
|
||||||
int32_t setCompareBytes1(const void *pLeft, const void *pRight);
|
int32_t setChkInBytes1(const void *pLeft, const void *pRight);
|
||||||
int32_t setCompareBytes2(const void *pLeft, const void *pRight);
|
int32_t setChkInBytes2(const void *pLeft, const void *pRight);
|
||||||
int32_t setCompareBytes4(const void *pLeft, const void *pRight);
|
int32_t setChkInBytes4(const void *pLeft, const void *pRight);
|
||||||
int32_t setCompareBytes8(const void *pLeft, const void *pRight);
|
int32_t setChkInBytes8(const void *pLeft, const void *pRight);
|
||||||
|
|
||||||
|
int32_t setChkNotInBytes1(const void *pLeft, const void *pRight);
|
||||||
|
int32_t setChkNotInBytes2(const void *pLeft, const void *pRight);
|
||||||
|
int32_t setChkNotInBytes4(const void *pLeft, const void *pRight);
|
||||||
|
int32_t setChkNotInBytes8(const void *pLeft, const void *pRight);
|
||||||
|
|
||||||
|
int32_t compareChkInString(const void *pLeft, const void *pRight);
|
||||||
|
int32_t compareChkNotInString(const void *pLeft, const void *pRight);
|
||||||
|
|
||||||
|
|
||||||
int32_t compareInt8Val(const void *pLeft, const void *pRight);
|
int32_t compareInt8Val(const void *pLeft, const void *pRight);
|
||||||
int32_t compareInt16Val(const void *pLeft, const void *pRight);
|
int32_t compareInt16Val(const void *pLeft, const void *pRight);
|
||||||
|
@ -74,7 +83,6 @@ int32_t compareStrRegexComp(const void *pLeft, const void *pRight);
|
||||||
int32_t compareStrRegexCompMatch(const void *pLeft, const void *pRight);
|
int32_t compareStrRegexCompMatch(const void *pLeft, const void *pRight);
|
||||||
int32_t compareStrRegexCompNMatch(const void *pLeft, const void *pRight);
|
int32_t compareStrRegexCompNMatch(const void *pLeft, const void *pRight);
|
||||||
|
|
||||||
int32_t compareFindItemInSet(const void *pLeft, const void *pRight);
|
|
||||||
|
|
||||||
int32_t compareInt8ValDesc(const void *pLeft, const void *pRight);
|
int32_t compareInt8ValDesc(const void *pLeft, const void *pRight);
|
||||||
int32_t compareInt16ValDesc(const void *pLeft, const void *pRight);
|
int32_t compareInt16ValDesc(const void *pLeft, const void *pRight);
|
||||||
|
@ -92,6 +100,9 @@ int32_t compareUint64ValDesc(const void *pLeft, const void *pRight);
|
||||||
int32_t compareLenPrefixedStrDesc(const void *pLeft, const void *pRight);
|
int32_t compareLenPrefixedStrDesc(const void *pLeft, const void *pRight);
|
||||||
int32_t compareLenPrefixedWStrDesc(const void *pLeft, const void *pRight);
|
int32_t compareLenPrefixedWStrDesc(const void *pLeft, const void *pRight);
|
||||||
|
|
||||||
|
__compar_fn_t getComparFunc(int32_t type, int32_t optr);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -118,16 +118,18 @@ do { \
|
||||||
#define TSDB_RELATION_GREATER_EQUAL 5
|
#define TSDB_RELATION_GREATER_EQUAL 5
|
||||||
#define TSDB_RELATION_NOT_EQUAL 6
|
#define TSDB_RELATION_NOT_EQUAL 6
|
||||||
#define TSDB_RELATION_LIKE 7
|
#define TSDB_RELATION_LIKE 7
|
||||||
#define TSDB_RELATION_ISNULL 8
|
#define TSDB_RELATION_NOT_LIKE 8
|
||||||
#define TSDB_RELATION_NOTNULL 9
|
#define TSDB_RELATION_ISNULL 9
|
||||||
#define TSDB_RELATION_IN 10
|
#define TSDB_RELATION_NOTNULL 10
|
||||||
|
#define TSDB_RELATION_IN 11
|
||||||
|
#define TSDB_RELATION_NOT_IN 12
|
||||||
|
|
||||||
#define TSDB_RELATION_AND 11
|
#define TSDB_RELATION_AND 13
|
||||||
#define TSDB_RELATION_OR 12
|
#define TSDB_RELATION_OR 14
|
||||||
#define TSDB_RELATION_NOT 13
|
#define TSDB_RELATION_NOT 15
|
||||||
|
|
||||||
#define TSDB_RELATION_MATCH 14
|
#define TSDB_RELATION_MATCH 16
|
||||||
#define TSDB_RELATION_NMATCH 15
|
#define TSDB_RELATION_NMATCH 17
|
||||||
|
|
||||||
#define TSDB_BINARY_OP_ADD 4000
|
#define TSDB_BINARY_OP_ADD 4000
|
||||||
#define TSDB_BINARY_OP_SUBTRACT 4001
|
#define TSDB_BINARY_OP_SUBTRACT 4001
|
||||||
|
|
|
@ -55,6 +55,8 @@ uint32_t taosIntHash_64(const char *key, uint32_t len);
|
||||||
|
|
||||||
_hash_fn_t taosGetDefaultHashFunction(int32_t type);
|
_hash_fn_t taosGetDefaultHashFunction(int32_t type);
|
||||||
|
|
||||||
|
_equal_fn_t taosGetDefaultEqualFunction(int32_t type);
|
||||||
|
|
||||||
typedef struct SHashNode {
|
typedef struct SHashNode {
|
||||||
struct SHashNode *next;
|
struct SHashNode *next;
|
||||||
uint32_t hashVal; // the hash value of key
|
uint32_t hashVal; // the hash value of key
|
||||||
|
@ -258,6 +260,8 @@ void* taosHashAcquire(SHashObj *pHashObj, const void *key, size_t keyLen);
|
||||||
*/
|
*/
|
||||||
void taosHashRelease(SHashObj *pHashObj, void *p);
|
void taosHashRelease(SHashObj *pHashObj, void *p);
|
||||||
|
|
||||||
|
void taosHashSetEqualFp(SHashObj *pHashObj, _equal_fn_t fp);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ void tjsonDelete(SJson* pJson);
|
||||||
SJson* tjsonAddArrayToObject(SJson* pJson, const char* pName);
|
SJson* tjsonAddArrayToObject(SJson* pJson, const char* pName);
|
||||||
|
|
||||||
int32_t tjsonAddIntegerToObject(SJson* pJson, const char* pName, const uint64_t number);
|
int32_t tjsonAddIntegerToObject(SJson* pJson, const char* pName, const uint64_t number);
|
||||||
|
int32_t tjsonAddDoubleToObject(SJson* pJson, const char* pName, const double number);
|
||||||
int32_t tjsonAddStringToObject(SJson* pJson, const char* pName, const char* pVal);
|
int32_t tjsonAddStringToObject(SJson* pJson, const char* pName, const char* pVal);
|
||||||
int32_t tjsonAddItemToObject(SJson* pJson, const char* pName, SJson* pItem);
|
int32_t tjsonAddItemToObject(SJson* pJson, const char* pName, SJson* pItem);
|
||||||
int32_t tjsonAddItemToArray(SJson* pJson, SJson* pItem);
|
int32_t tjsonAddItemToArray(SJson* pJson, SJson* pItem);
|
||||||
|
@ -42,6 +43,7 @@ int32_t tjsonAddItem(SJson* pJson, FToJson func, const void* pObj);
|
||||||
typedef int32_t (*FFromJson)(const SJson* pJson, void* pObj);
|
typedef int32_t (*FFromJson)(const SJson* pJson, void* pObj);
|
||||||
|
|
||||||
char* tjsonToString(const SJson* pJson);
|
char* tjsonToString(const SJson* pJson);
|
||||||
|
char* tjsonToUnformattedString(const SJson* pJson);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,7 @@ static FORCE_INLINE double taos_align_get_double(const char *pBuf) {
|
||||||
// #else
|
// #else
|
||||||
#define GET_FLOAT_VAL(x) (*(float *)(x))
|
#define GET_FLOAT_VAL(x) (*(float *)(x))
|
||||||
#define GET_DOUBLE_VAL(x) (*(double *)(x))
|
#define GET_DOUBLE_VAL(x) (*(double *)(x))
|
||||||
|
#define SET_BIGINT_VAL(x, y) { (*(int64_t *)(x)) = (int64_t)(y); }
|
||||||
#define SET_FLOAT_VAL(x, y) { (*(float *)(x)) = (float)(y); }
|
#define SET_FLOAT_VAL(x, y) { (*(float *)(x)) = (float)(y); }
|
||||||
#define SET_DOUBLE_VAL(x, y) { (*(double *)(x)) = (double)(y); }
|
#define SET_DOUBLE_VAL(x, y) { (*(double *)(x)) = (double)(y); }
|
||||||
#define SET_FLOAT_PTR(x, y) { (*(float *)(x)) = (*(float *)(y)); }
|
#define SET_FLOAT_PTR(x, y) { (*(float *)(x)) = (*(float *)(y)); }
|
||||||
|
|
|
@ -15,116 +15,6 @@
|
||||||
|
|
||||||
#include "tcompare.h"
|
#include "tcompare.h"
|
||||||
|
|
||||||
int32_t compareStrPatternComp(const void* pLeft, const void* pRight) {
|
|
||||||
SPatternCompareInfo pInfo = {'%', '_'};
|
|
||||||
|
|
||||||
assert(varDataLen(pRight) <= TSDB_MAX_FIELD_LEN);
|
|
||||||
char *pattern = calloc(varDataLen(pRight) + 1, sizeof(char));
|
|
||||||
memcpy(pattern, varDataVal(pRight), varDataLen(pRight));
|
|
||||||
|
|
||||||
size_t sz = varDataLen(pLeft);
|
|
||||||
char *buf = malloc(sz + 1);
|
|
||||||
memcpy(buf, varDataVal(pLeft), sz);
|
|
||||||
buf[sz] = 0;
|
|
||||||
|
|
||||||
int32_t ret = patternMatch(pattern, buf, sz, &pInfo);
|
|
||||||
free(buf);
|
|
||||||
free(pattern);
|
|
||||||
return (ret == TSDB_PATTERN_MATCH) ? 0 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t compareWStrPatternComp(const void* pLeft, const void* pRight) {
|
|
||||||
SPatternCompareInfo pInfo = {'%', '_'};
|
|
||||||
|
|
||||||
assert(varDataLen(pRight) <= TSDB_MAX_FIELD_LEN * TSDB_NCHAR_SIZE);
|
|
||||||
|
|
||||||
wchar_t *pattern = calloc(varDataLen(pRight) + 1, sizeof(wchar_t));
|
|
||||||
memcpy(pattern, varDataVal(pRight), varDataLen(pRight));
|
|
||||||
|
|
||||||
int32_t ret = WCSPatternMatch(pattern, varDataVal(pLeft), varDataLen(pLeft)/TSDB_NCHAR_SIZE, &pInfo);
|
|
||||||
free(pattern);
|
|
||||||
|
|
||||||
return (ret == TSDB_PATTERN_MATCH) ? 0 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
__compar_fn_t getComparFunc(int32_t type, int32_t optr) {
|
|
||||||
__compar_fn_t comparFn = NULL;
|
|
||||||
|
|
||||||
if (optr == TSDB_RELATION_IN && (type != TSDB_DATA_TYPE_BINARY && type != TSDB_DATA_TYPE_NCHAR)) {
|
|
||||||
switch (type) {
|
|
||||||
case TSDB_DATA_TYPE_BOOL:
|
|
||||||
case TSDB_DATA_TYPE_TINYINT:
|
|
||||||
case TSDB_DATA_TYPE_UTINYINT:
|
|
||||||
return setCompareBytes1;
|
|
||||||
case TSDB_DATA_TYPE_SMALLINT:
|
|
||||||
case TSDB_DATA_TYPE_USMALLINT:
|
|
||||||
return setCompareBytes2;
|
|
||||||
case TSDB_DATA_TYPE_INT:
|
|
||||||
case TSDB_DATA_TYPE_UINT:
|
|
||||||
case TSDB_DATA_TYPE_FLOAT:
|
|
||||||
return setCompareBytes4;
|
|
||||||
case TSDB_DATA_TYPE_BIGINT:
|
|
||||||
case TSDB_DATA_TYPE_UBIGINT:
|
|
||||||
case TSDB_DATA_TYPE_DOUBLE:
|
|
||||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
|
||||||
return setCompareBytes8;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case TSDB_DATA_TYPE_BOOL:
|
|
||||||
case TSDB_DATA_TYPE_TINYINT: comparFn = compareInt8Val; break;
|
|
||||||
case TSDB_DATA_TYPE_SMALLINT: comparFn = compareInt16Val; break;
|
|
||||||
case TSDB_DATA_TYPE_INT: comparFn = compareInt32Val; break;
|
|
||||||
case TSDB_DATA_TYPE_BIGINT:
|
|
||||||
case TSDB_DATA_TYPE_TIMESTAMP: comparFn = compareInt64Val; break;
|
|
||||||
case TSDB_DATA_TYPE_FLOAT: comparFn = compareFloatVal; break;
|
|
||||||
case TSDB_DATA_TYPE_DOUBLE: comparFn = compareDoubleVal; break;
|
|
||||||
case TSDB_DATA_TYPE_BINARY: {
|
|
||||||
if (optr == TSDB_RELATION_MATCH) {
|
|
||||||
comparFn = compareStrRegexCompMatch;
|
|
||||||
} else if (optr == TSDB_RELATION_NMATCH) {
|
|
||||||
comparFn = compareStrRegexCompNMatch;
|
|
||||||
} else if (optr == TSDB_RELATION_LIKE) { /* wildcard query using like operator */
|
|
||||||
comparFn = compareStrPatternComp;
|
|
||||||
} else if (optr == TSDB_RELATION_IN) {
|
|
||||||
comparFn = compareFindItemInSet;
|
|
||||||
} else { /* normal relational comparFn */
|
|
||||||
comparFn = compareLenPrefixedStr;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TSDB_DATA_TYPE_NCHAR: {
|
|
||||||
if (optr == TSDB_RELATION_MATCH) {
|
|
||||||
comparFn = compareStrRegexCompMatch;
|
|
||||||
} else if (optr == TSDB_RELATION_NMATCH) {
|
|
||||||
comparFn = compareStrRegexCompNMatch;
|
|
||||||
} else if (optr == TSDB_RELATION_LIKE) {
|
|
||||||
comparFn = compareWStrPatternComp;
|
|
||||||
} else if (optr == TSDB_RELATION_IN) {
|
|
||||||
comparFn = compareFindItemInSet;
|
|
||||||
} else {
|
|
||||||
comparFn = compareLenPrefixedWStr;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TSDB_DATA_TYPE_UTINYINT: comparFn = compareUint8Val; break;
|
|
||||||
case TSDB_DATA_TYPE_USMALLINT: comparFn = compareUint16Val;break;
|
|
||||||
case TSDB_DATA_TYPE_UINT: comparFn = compareUint32Val;break;
|
|
||||||
case TSDB_DATA_TYPE_UBIGINT: comparFn = compareUint64Val;break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
comparFn = compareInt32Val;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return comparFn;
|
|
||||||
}
|
|
||||||
|
|
||||||
__compar_fn_t getKeyComparFunc(int32_t keyType, int32_t order) {
|
__compar_fn_t getKeyComparFunc(int32_t keyType, int32_t order) {
|
||||||
__compar_fn_t comparFn = NULL;
|
__compar_fn_t comparFn = NULL;
|
||||||
|
|
|
@ -155,7 +155,7 @@ static void dndInitMsgFp(STransMgmt *pMgmt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dndProcessResponse(void *parent, SRpcMsg *pRsp, SEpSet *pEpSet) {
|
static void dndProcessResponse(void *parent, SRpcMsg *pRsp, SEpSet *pEpSet) {
|
||||||
SDnode *pDnode = parent;
|
SDnode * pDnode = parent;
|
||||||
STransMgmt *pMgmt = &pDnode->tmgmt;
|
STransMgmt *pMgmt = &pDnode->tmgmt;
|
||||||
|
|
||||||
tmsg_t msgType = pRsp->msgType;
|
tmsg_t msgType = pRsp->msgType;
|
||||||
|
@ -193,6 +193,7 @@ static int32_t dndInitClient(SDnode *pDnode) {
|
||||||
rpcInit.ckey = INTERNAL_CKEY;
|
rpcInit.ckey = INTERNAL_CKEY;
|
||||||
rpcInit.spi = 1;
|
rpcInit.spi = 1;
|
||||||
rpcInit.parent = pDnode;
|
rpcInit.parent = pDnode;
|
||||||
|
rpcInit.noPool = true;
|
||||||
|
|
||||||
char pass[TSDB_PASSWORD_LEN + 1] = {0};
|
char pass[TSDB_PASSWORD_LEN + 1] = {0};
|
||||||
taosEncryptPass_c((uint8_t *)(INTERNAL_SECRET), strlen(INTERNAL_SECRET), pass);
|
taosEncryptPass_c((uint8_t *)(INTERNAL_SECRET), strlen(INTERNAL_SECRET), pass);
|
||||||
|
@ -218,7 +219,7 @@ static void dndCleanupClient(SDnode *pDnode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dndProcessRequest(void *param, SRpcMsg *pReq, SEpSet *pEpSet) {
|
static void dndProcessRequest(void *param, SRpcMsg *pReq, SEpSet *pEpSet) {
|
||||||
SDnode *pDnode = param;
|
SDnode * pDnode = param;
|
||||||
STransMgmt *pMgmt = &pDnode->tmgmt;
|
STransMgmt *pMgmt = &pDnode->tmgmt;
|
||||||
|
|
||||||
tmsg_t msgType = pReq->msgType;
|
tmsg_t msgType = pReq->msgType;
|
||||||
|
@ -312,7 +313,7 @@ static int32_t dndRetrieveUserAuthInfo(void *parent, char *user, char *spi, char
|
||||||
SAuthReq authReq = {0};
|
SAuthReq authReq = {0};
|
||||||
tstrncpy(authReq.user, user, TSDB_USER_LEN);
|
tstrncpy(authReq.user, user, TSDB_USER_LEN);
|
||||||
int32_t contLen = tSerializeSAuthReq(NULL, 0, &authReq);
|
int32_t contLen = tSerializeSAuthReq(NULL, 0, &authReq);
|
||||||
void *pReq = rpcMallocCont(contLen);
|
void * pReq = rpcMallocCont(contLen);
|
||||||
tSerializeSAuthReq(pReq, contLen, &authReq);
|
tSerializeSAuthReq(pReq, contLen, &authReq);
|
||||||
|
|
||||||
SRpcMsg rpcMsg = {.pCont = pReq, .contLen = contLen, .msgType = TDMT_MND_AUTH, .ahandle = (void *)9528};
|
SRpcMsg rpcMsg = {.pCont = pReq, .contLen = contLen, .msgType = TDMT_MND_AUTH, .ahandle = (void *)9528};
|
||||||
|
|
|
@ -21,13 +21,18 @@ class TestClient {
|
||||||
bool Init(const char* user, const char* pass, const char* fqdn, uint16_t port);
|
bool Init(const char* user, const char* pass, const char* fqdn, uint16_t port);
|
||||||
void Cleanup();
|
void Cleanup();
|
||||||
|
|
||||||
|
void DoInit();
|
||||||
|
|
||||||
SRpcMsg* SendReq(SRpcMsg* pReq);
|
SRpcMsg* SendReq(SRpcMsg* pReq);
|
||||||
void SetRpcRsp(SRpcMsg* pRsp);
|
void SetRpcRsp(SRpcMsg* pRsp);
|
||||||
tsem_t* GetSem();
|
tsem_t* GetSem();
|
||||||
|
void Restart();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char fqdn[TSDB_FQDN_LEN];
|
char fqdn[TSDB_FQDN_LEN];
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
|
char user[128];
|
||||||
|
char pass[128];
|
||||||
void* clientRpc;
|
void* clientRpc;
|
||||||
SRpcMsg* pRsp;
|
SRpcMsg* pRsp;
|
||||||
tsem_t sem;
|
tsem_t sem;
|
||||||
|
|
|
@ -20,10 +20,10 @@
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
|
||||||
#include "dnode.h"
|
#include "dnode.h"
|
||||||
#include "tmsg.h"
|
|
||||||
#include "tconfig.h"
|
#include "tconfig.h"
|
||||||
#include "tdataformat.h"
|
#include "tdataformat.h"
|
||||||
#include "tglobal.h"
|
#include "tglobal.h"
|
||||||
|
#include "tmsg.h"
|
||||||
#include "tnote.h"
|
#include "tnote.h"
|
||||||
#include "trpc.h"
|
#include "trpc.h"
|
||||||
#include "tthread.h"
|
#include "tthread.h"
|
||||||
|
@ -39,6 +39,7 @@ class Testbase {
|
||||||
void Restart();
|
void Restart();
|
||||||
void ServerStop();
|
void ServerStop();
|
||||||
void ServerStart();
|
void ServerStart();
|
||||||
|
void ClientRestart();
|
||||||
SRpcMsg* SendReq(tmsg_t msgType, void* pCont, int32_t contLen);
|
SRpcMsg* SendReq(tmsg_t msgType, void* pCont, int32_t contLen);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -100,7 +101,7 @@ class Testbase {
|
||||||
{ \
|
{ \
|
||||||
char* bytes = (char*)calloc(1, len); \
|
char* bytes = (char*)calloc(1, len); \
|
||||||
for (int32_t i = 0; i < len - 1; ++i) { \
|
for (int32_t i = 0; i < len - 1; ++i) { \
|
||||||
bytes[i] = b; \
|
bytes[i] = b; \
|
||||||
} \
|
} \
|
||||||
EXPECT_STREQ(test.GetShowBinary(len), bytes); \
|
EXPECT_STREQ(test.GetShowBinary(len), bytes); \
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,33 +13,41 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tep.h"
|
|
||||||
#include "sut.h"
|
#include "sut.h"
|
||||||
|
#include "tep.h"
|
||||||
|
|
||||||
static void processClientRsp(void* parent, SRpcMsg* pRsp, SEpSet* pEpSet) {
|
static void processClientRsp(void* parent, SRpcMsg* pRsp, SEpSet* pEpSet) {
|
||||||
TestClient* client = (TestClient*)parent;
|
TestClient* client = (TestClient*)parent;
|
||||||
client->SetRpcRsp(pRsp);
|
client->SetRpcRsp(pRsp);
|
||||||
uInfo("response:%s from dnode, code:0x%x", TMSG_INFO(pRsp->msgType), pRsp->code);
|
uInfo("x response:%s from dnode, code:0x%x, msgSize: %d", TMSG_INFO(pRsp->msgType), pRsp->code, pRsp->contLen);
|
||||||
tsem_post(client->GetSem());
|
tsem_post(client->GetSem());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestClient::SetRpcRsp(SRpcMsg* pRsp) { this->pRsp = pRsp; };
|
void TestClient::SetRpcRsp(SRpcMsg* rsp) {
|
||||||
|
if (this->pRsp) {
|
||||||
|
free(this->pRsp);
|
||||||
|
}
|
||||||
|
this->pRsp = (SRpcMsg*)calloc(1, sizeof(SRpcMsg));
|
||||||
|
this->pRsp->msgType = rsp->msgType;
|
||||||
|
this->pRsp->code = rsp->code;
|
||||||
|
this->pRsp->pCont = rsp->pCont;
|
||||||
|
this->pRsp->contLen = rsp->contLen;
|
||||||
|
};
|
||||||
|
|
||||||
tsem_t* TestClient::GetSem() { return &sem; }
|
tsem_t* TestClient::GetSem() { return &sem; }
|
||||||
|
|
||||||
bool TestClient::Init(const char* user, const char* pass, const char* fqdn, uint16_t port) {
|
void TestClient::DoInit() {
|
||||||
char secretEncrypt[TSDB_PASSWORD_LEN + 1] = {0};
|
char secretEncrypt[TSDB_PASSWORD_LEN + 1] = {0};
|
||||||
taosEncryptPass_c((uint8_t*)pass, strlen(pass), secretEncrypt);
|
taosEncryptPass_c((uint8_t*)pass, strlen(pass), secretEncrypt);
|
||||||
|
|
||||||
SRpcInit rpcInit;
|
SRpcInit rpcInit;
|
||||||
memset(&rpcInit, 0, sizeof(rpcInit));
|
memset(&rpcInit, 0, sizeof(rpcInit));
|
||||||
rpcInit.label = (char*)"DND-C";
|
rpcInit.label = (char*)"shell";
|
||||||
rpcInit.numOfThreads = 1;
|
rpcInit.numOfThreads = 1;
|
||||||
rpcInit.cfp = processClientRsp;
|
rpcInit.cfp = processClientRsp;
|
||||||
rpcInit.sessions = 1024;
|
rpcInit.sessions = 1024;
|
||||||
rpcInit.connType = TAOS_CONN_CLIENT;
|
rpcInit.connType = TAOS_CONN_CLIENT;
|
||||||
rpcInit.idleTime = 30 * 1000;
|
rpcInit.idleTime = 30 * 1000;
|
||||||
rpcInit.user = (char*)user;
|
rpcInit.user = (char*)this->user;
|
||||||
rpcInit.ckey = (char*)"key";
|
rpcInit.ckey = (char*)"key";
|
||||||
rpcInit.parent = this;
|
rpcInit.parent = this;
|
||||||
rpcInit.secret = (char*)secretEncrypt;
|
rpcInit.secret = (char*)secretEncrypt;
|
||||||
|
@ -47,11 +55,16 @@ bool TestClient::Init(const char* user, const char* pass, const char* fqdn, uint
|
||||||
|
|
||||||
clientRpc = rpcOpen(&rpcInit);
|
clientRpc = rpcOpen(&rpcInit);
|
||||||
ASSERT(clientRpc);
|
ASSERT(clientRpc);
|
||||||
|
tsem_init(&this->sem, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
tsem_init(&sem, 0, 0);
|
bool TestClient::Init(const char* user, const char* pass, const char* fqdn, uint16_t port) {
|
||||||
strcpy(this->fqdn, fqdn);
|
strcpy(this->fqdn, fqdn);
|
||||||
|
strcpy(this->user, user);
|
||||||
|
strcpy(this->pass, pass);
|
||||||
this->port = port;
|
this->port = port;
|
||||||
|
this->pRsp = NULL;
|
||||||
|
this->DoInit();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,11 +73,16 @@ void TestClient::Cleanup() {
|
||||||
rpcClose(clientRpc);
|
rpcClose(clientRpc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestClient::Restart() {
|
||||||
|
this->Cleanup();
|
||||||
|
this->DoInit();
|
||||||
|
}
|
||||||
SRpcMsg* TestClient::SendReq(SRpcMsg* pReq) {
|
SRpcMsg* TestClient::SendReq(SRpcMsg* pReq) {
|
||||||
SEpSet epSet = {0};
|
SEpSet epSet = {0};
|
||||||
addEpIntoEpSet(&epSet, fqdn, port);
|
addEpIntoEpSet(&epSet, fqdn, port);
|
||||||
rpcSendRequest(clientRpc, &epSet, pReq, NULL);
|
rpcSendRequest(clientRpc, &epSet, pReq, NULL);
|
||||||
tsem_wait(&sem);
|
tsem_wait(&sem);
|
||||||
|
uInfo("y response:%s from dnode, code:0x%x, msgSize: %d", TMSG_INFO(pRsp->msgType), pRsp->code, pRsp->contLen);
|
||||||
|
|
||||||
return pRsp;
|
return pRsp;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,9 @@ void Testbase::InitLog(const char* path) {
|
||||||
mDebugFlag = 143;
|
mDebugFlag = 143;
|
||||||
cDebugFlag = 0;
|
cDebugFlag = 0;
|
||||||
jniDebugFlag = 0;
|
jniDebugFlag = 0;
|
||||||
tmrDebugFlag = 0;
|
tmrDebugFlag = 143;
|
||||||
uDebugFlag = 0;
|
uDebugFlag = 143;
|
||||||
rpcDebugFlag = 0;
|
rpcDebugFlag = 143;
|
||||||
qDebugFlag = 0;
|
qDebugFlag = 0;
|
||||||
wDebugFlag = 0;
|
wDebugFlag = 0;
|
||||||
sDebugFlag = 0;
|
sDebugFlag = 0;
|
||||||
|
@ -66,16 +66,21 @@ void Testbase::Init(const char* path, int16_t port) {
|
||||||
|
|
||||||
void Testbase::Cleanup() {
|
void Testbase::Cleanup() {
|
||||||
tFreeSTableMetaRsp(&metaRsp);
|
tFreeSTableMetaRsp(&metaRsp);
|
||||||
server.Stop();
|
|
||||||
client.Cleanup();
|
client.Cleanup();
|
||||||
|
taosMsleep(10);
|
||||||
|
server.Stop();
|
||||||
dndCleanup();
|
dndCleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Testbase::Restart() { server.Restart(); }
|
void Testbase::Restart() {
|
||||||
|
server.Restart();
|
||||||
|
client.Restart();
|
||||||
|
}
|
||||||
|
|
||||||
void Testbase::ServerStop() { server.Stop(); }
|
void Testbase::ServerStop() { server.Stop(); }
|
||||||
|
|
||||||
void Testbase::ServerStart() { server.DoStart(); }
|
void Testbase::ServerStart() { server.DoStart(); }
|
||||||
|
void Testbase::ClientRestart() { client.Restart(); }
|
||||||
|
|
||||||
SRpcMsg* Testbase::SendReq(tmsg_t msgType, void* pCont, int32_t contLen) {
|
SRpcMsg* Testbase::SendReq(tmsg_t msgType, void* pCont, int32_t contLen) {
|
||||||
SRpcMsg rpcMsg = {0};
|
SRpcMsg rpcMsg = {0};
|
||||||
|
|
|
@ -77,7 +77,7 @@ static void mndTransReExecute(void *param, void *tmrId) {
|
||||||
SMnode *pMnode = param;
|
SMnode *pMnode = param;
|
||||||
if (mndIsMaster(pMnode)) {
|
if (mndIsMaster(pMnode)) {
|
||||||
int32_t contLen = 0;
|
int32_t contLen = 0;
|
||||||
void *pReq = mndBuildTimerMsg(&contLen);
|
void * pReq = mndBuildTimerMsg(&contLen);
|
||||||
SRpcMsg rpcMsg = {.msgType = TDMT_MND_TRANS, .pCont = pReq, .contLen = contLen};
|
SRpcMsg rpcMsg = {.msgType = TDMT_MND_TRANS, .pCont = pReq, .contLen = contLen};
|
||||||
pMnode->putReqToMWriteQFp(pMnode->pDnode, &rpcMsg);
|
pMnode->putReqToMWriteQFp(pMnode->pDnode, &rpcMsg);
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ static void mndCalMqRebalance(void *param, void *tmrId) {
|
||||||
SMnode *pMnode = param;
|
SMnode *pMnode = param;
|
||||||
if (mndIsMaster(pMnode)) {
|
if (mndIsMaster(pMnode)) {
|
||||||
int32_t contLen = 0;
|
int32_t contLen = 0;
|
||||||
void *pReq = mndBuildTimerMsg(&contLen);
|
void * pReq = mndBuildTimerMsg(&contLen);
|
||||||
SRpcMsg rpcMsg = {.msgType = TDMT_MND_MQ_TIMER, .pCont = pReq, .contLen = contLen};
|
SRpcMsg rpcMsg = {.msgType = TDMT_MND_MQ_TIMER, .pCont = pReq, .contLen = contLen};
|
||||||
pMnode->putReqToMReadQFp(pMnode->pDnode, &rpcMsg);
|
pMnode->putReqToMReadQFp(pMnode->pDnode, &rpcMsg);
|
||||||
}
|
}
|
||||||
|
@ -404,7 +404,8 @@ SMnodeMsg *mndInitMsg(SMnode *pMnode, SRpcMsg *pRpcMsg) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pRpcMsg->msgType != TDMT_MND_TRANS && pRpcMsg->msgType != TDMT_MND_MQ_TIMER && pRpcMsg->msgType != TDMT_MND_MQ_DO_REBALANCE) {
|
if (pRpcMsg->msgType != TDMT_MND_TRANS && pRpcMsg->msgType != TDMT_MND_MQ_TIMER &&
|
||||||
|
pRpcMsg->msgType != TDMT_MND_MQ_DO_REBALANCE) {
|
||||||
SRpcConnInfo connInfo = {0};
|
SRpcConnInfo connInfo = {0};
|
||||||
if ((pRpcMsg->msgType & 1U) && rpcGetConnInfo(pRpcMsg->handle, &connInfo) != 0) {
|
if ((pRpcMsg->msgType & 1U) && rpcGetConnInfo(pRpcMsg->handle, &connInfo) != 0) {
|
||||||
taosFreeQitem(pMsg);
|
taosFreeQitem(pMsg);
|
||||||
|
@ -439,7 +440,7 @@ void mndProcessMsg(SMnodeMsg *pMsg) {
|
||||||
SMnode *pMnode = pMsg->pMnode;
|
SMnode *pMnode = pMsg->pMnode;
|
||||||
int32_t code = 0;
|
int32_t code = 0;
|
||||||
tmsg_t msgType = pMsg->rpcMsg.msgType;
|
tmsg_t msgType = pMsg->rpcMsg.msgType;
|
||||||
void *ahandle = pMsg->rpcMsg.ahandle;
|
void * ahandle = pMsg->rpcMsg.ahandle;
|
||||||
bool isReq = (msgType & 1U);
|
bool isReq = (msgType & 1U);
|
||||||
|
|
||||||
mTrace("msg:%p, type:%s will be processed, app:%p", pMsg, TMSG_INFO(msgType), ahandle);
|
mTrace("msg:%p, type:%s will be processed, app:%p", pMsg, TMSG_INFO(msgType), ahandle);
|
||||||
|
|
|
@ -190,6 +190,9 @@ TEST_F(MndTestQnode, 03_Create_Qnode_Rollback) {
|
||||||
tSerializeSMCreateDropQSBNodeReq(pReq, contLen, &createReq);
|
tSerializeSMCreateDropQSBNodeReq(pReq, contLen, &createReq);
|
||||||
|
|
||||||
server2.Stop();
|
server2.Stop();
|
||||||
|
taosMsleep(1000);
|
||||||
|
// test.ClientRestart();
|
||||||
|
|
||||||
SRpcMsg* pRsp = test.SendReq(TDMT_MND_CREATE_QNODE, pReq, contLen);
|
SRpcMsg* pRsp = test.SendReq(TDMT_MND_CREATE_QNODE, pReq, contLen);
|
||||||
ASSERT_NE(pRsp, nullptr);
|
ASSERT_NE(pRsp, nullptr);
|
||||||
ASSERT_EQ(pRsp->code, TSDB_CODE_RPC_NETWORK_UNAVAIL);
|
ASSERT_EQ(pRsp->code, TSDB_CODE_RPC_NETWORK_UNAVAIL);
|
||||||
|
@ -226,6 +229,7 @@ TEST_F(MndTestQnode, 03_Create_Qnode_Rollback) {
|
||||||
{
|
{
|
||||||
// server start, wait until the rollback finished
|
// server start, wait until the rollback finished
|
||||||
server2.DoStart();
|
server2.DoStart();
|
||||||
|
test.ClientRestart();
|
||||||
taosMsleep(1000);
|
taosMsleep(1000);
|
||||||
|
|
||||||
int32_t retry = 0;
|
int32_t retry = 0;
|
||||||
|
@ -248,7 +252,6 @@ TEST_F(MndTestQnode, 03_Create_Qnode_Rollback) {
|
||||||
ASSERT_NE(retry, retryMax);
|
ASSERT_NE(retry, retryMax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MndTestQnode, 04_Drop_Qnode_Rollback) {
|
TEST_F(MndTestQnode, 04_Drop_Qnode_Rollback) {
|
||||||
{
|
{
|
||||||
// send message first, then dnode2 crash, result is returned, and rollback is started
|
// send message first, then dnode2 crash, result is returned, and rollback is started
|
||||||
|
|
|
@ -46,8 +46,10 @@ class MndTestTrans : public ::testing::Test {
|
||||||
free(buffer);
|
free(buffer);
|
||||||
taosFsyncFile(fd);
|
taosFsyncFile(fd);
|
||||||
taosCloseFile(fd);
|
taosCloseFile(fd);
|
||||||
|
taosMsleep(1000);
|
||||||
|
|
||||||
test.ServerStart();
|
test.ServerStart();
|
||||||
|
test.ClientRestart();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Testbase test;
|
static Testbase test;
|
||||||
|
@ -284,6 +286,7 @@ TEST_F(MndTestTrans, 03_Create_Qnode2_Crash) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// create db
|
// create db
|
||||||
// partial create stb
|
// partial create stb
|
||||||
// drop db failed
|
// drop db failed
|
||||||
|
|
|
@ -617,6 +617,7 @@ TEST_F(MndTestUser, 06_Create_Drop_Alter_User) {
|
||||||
// restart
|
// restart
|
||||||
test.Restart();
|
test.Restart();
|
||||||
|
|
||||||
|
taosMsleep(1000);
|
||||||
test.SendShowMetaReq(TSDB_MGMT_TABLE_USER, "");
|
test.SendShowMetaReq(TSDB_MGMT_TABLE_USER, "");
|
||||||
CHECK_META("show users", 4);
|
CHECK_META("show users", 4);
|
||||||
|
|
||||||
|
|
|
@ -126,7 +126,7 @@ static int vnodeGetTableMeta(SVnode *pVnode, SRpcMsg *pMsg) {
|
||||||
goto _exit;
|
goto _exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
metaRsp.dbId = htobe64(pVnode->config.dbId);
|
metaRsp.dbId = pVnode->config.dbId;
|
||||||
memcpy(metaRsp.dbFName, infoReq.dbFName, sizeof(metaRsp.dbFName));
|
memcpy(metaRsp.dbFName, infoReq.dbFName, sizeof(metaRsp.dbFName));
|
||||||
strcpy(metaRsp.tbName, infoReq.tbName);
|
strcpy(metaRsp.tbName, infoReq.tbName);
|
||||||
if (pTbCfg->type == META_CHILD_TABLE) {
|
if (pTbCfg->type == META_CHILD_TABLE) {
|
||||||
|
|
|
@ -14,3 +14,4 @@ add_subdirectory(qcom)
|
||||||
add_subdirectory(qworker)
|
add_subdirectory(qworker)
|
||||||
add_subdirectory(tfs)
|
add_subdirectory(tfs)
|
||||||
add_subdirectory(nodes)
|
add_subdirectory(nodes)
|
||||||
|
add_subdirectory(scalar)
|
|
@ -1556,39 +1556,43 @@ int32_t ctgGetTableMeta(SCatalog* pCtg, void *pRpc, const SEpSet* pMgmtEps, cons
|
||||||
|
|
||||||
STableMetaOutput *output = NULL;
|
STableMetaOutput *output = NULL;
|
||||||
|
|
||||||
CTG_ERR_JRET(ctgRefreshTblMeta(pCtg, pRpc, pMgmtEps, pTableName, isSTable, &output));
|
while (true) {
|
||||||
|
CTG_ERR_JRET(ctgRefreshTblMeta(pCtg, pRpc, pMgmtEps, pTableName, isSTable, &output));
|
||||||
|
|
||||||
if (CTG_IS_META_TABLE(output->metaType)) {
|
if (CTG_IS_META_TABLE(output->metaType)) {
|
||||||
*pTableMeta = output->tbMeta;
|
*pTableMeta = output->tbMeta;
|
||||||
goto _return;
|
goto _return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CTG_IS_META_BOTH(output->metaType)) {
|
||||||
|
memcpy(output->tbMeta, &output->ctbMeta, sizeof(output->ctbMeta));
|
||||||
|
|
||||||
|
*pTableMeta = output->tbMeta;
|
||||||
|
goto _return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!CTG_IS_META_CTABLE(output->metaType)) || output->tbMeta) {
|
||||||
|
ctgError("invalid metaType:%d", output->metaType);
|
||||||
|
tfree(output->tbMeta);
|
||||||
|
CTG_ERR_JRET(TSDB_CODE_CTG_INTERNAL_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// HANDLE ONLY CHILD TABLE META
|
||||||
|
|
||||||
|
SName stbName = *pTableName;
|
||||||
|
strcpy(stbName.tname, output->tbName);
|
||||||
|
|
||||||
|
CTG_ERR_JRET(ctgGetTableMetaFromCache(pCtg, &stbName, pTableMeta, &exist));
|
||||||
|
if (0 == exist) {
|
||||||
|
ctgDebug("stb no longer exist, dbFName:%s, tbName:%s", output->dbFName, pTableName->tname);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(*pTableMeta, &output->ctbMeta, sizeof(output->ctbMeta));
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CTG_IS_META_BOTH(output->metaType)) {
|
|
||||||
memcpy(output->tbMeta, &output->ctbMeta, sizeof(output->ctbMeta));
|
|
||||||
|
|
||||||
*pTableMeta = output->tbMeta;
|
|
||||||
goto _return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((!CTG_IS_META_CTABLE(output->metaType)) || output->tbMeta) {
|
|
||||||
ctgError("invalid metaType:%d", output->metaType);
|
|
||||||
tfree(output->tbMeta);
|
|
||||||
CTG_ERR_JRET(TSDB_CODE_CTG_INTERNAL_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
// HANDLE ONLY CHILD TABLE META
|
|
||||||
|
|
||||||
SName stbName = *pTableName;
|
|
||||||
strcpy(stbName.tname, output->tbName);
|
|
||||||
|
|
||||||
CTG_ERR_JRET(ctgGetTableMetaFromCache(pCtg, &stbName, pTableMeta, &exist));
|
|
||||||
if (0 == exist) {
|
|
||||||
ctgDebug("stb no longer exist, dbFName:%s, tbName:%s", output->dbFName, pTableName->tname);
|
|
||||||
CTG_ERR_JRET(TSDB_CODE_VND_TB_NOT_EXIST);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(*pTableMeta, &output->ctbMeta, sizeof(output->ctbMeta));
|
|
||||||
|
|
||||||
_return:
|
_return:
|
||||||
|
|
||||||
tfree(output);
|
tfree(output);
|
||||||
|
|
|
@ -13,7 +13,7 @@ add_library(executor STATIC ${EXECUTOR_SRC})
|
||||||
# INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/include/libs/executor"
|
# INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/include/libs/executor"
|
||||||
# )
|
# )
|
||||||
target_link_libraries(executor
|
target_link_libraries(executor
|
||||||
PRIVATE os util common function parser planner qcom vnode
|
PRIVATE os util common function parser planner qcom vnode scalar nodes
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(
|
target_include_directories(
|
||||||
|
|
|
@ -29,9 +29,9 @@ extern "C" {
|
||||||
#include "executil.h"
|
#include "executil.h"
|
||||||
#include "executor.h"
|
#include "executor.h"
|
||||||
#include "planner.h"
|
#include "planner.h"
|
||||||
|
#include "scalar.h"
|
||||||
#include "taosdef.h"
|
#include "taosdef.h"
|
||||||
#include "tarray.h"
|
#include "tarray.h"
|
||||||
#include "tfilter.h"
|
|
||||||
#include "thash.h"
|
#include "thash.h"
|
||||||
#include "tlockfree.h"
|
#include "tlockfree.h"
|
||||||
#include "tpagedbuf.h"
|
#include "tpagedbuf.h"
|
||||||
|
|
|
@ -2148,7 +2148,7 @@ static int32_t setupQueryRuntimeEnv(STaskRuntimeEnv *pRuntimeEnv, int32_t numOfT
|
||||||
// NOTE: pTableCheckInfo need to update the query time range and the lastKey info
|
// NOTE: pTableCheckInfo need to update the query time range and the lastKey info
|
||||||
pRuntimeEnv->pTableRetrieveTsMap = taosHashInit(numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
|
pRuntimeEnv->pTableRetrieveTsMap = taosHashInit(numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
|
||||||
|
|
||||||
pRuntimeEnv->scalarSup = createScalarFuncSupport(pQueryAttr->numOfOutput);
|
//pRuntimeEnv->scalarSup = createScalarFuncSupport(pQueryAttr->numOfOutput);
|
||||||
|
|
||||||
if (pRuntimeEnv->scalarSup == NULL || pRuntimeEnv->pResultRowHashTable == NULL || pRuntimeEnv->keyBuf == NULL ||
|
if (pRuntimeEnv->scalarSup == NULL || pRuntimeEnv->pResultRowHashTable == NULL || pRuntimeEnv->keyBuf == NULL ||
|
||||||
pRuntimeEnv->prevRow == NULL || pRuntimeEnv->tagVal == NULL) {
|
pRuntimeEnv->prevRow == NULL || pRuntimeEnv->tagVal == NULL) {
|
||||||
|
@ -2174,7 +2174,7 @@ static int32_t setupQueryRuntimeEnv(STaskRuntimeEnv *pRuntimeEnv, int32_t numOfT
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
|
|
||||||
_clean:
|
_clean:
|
||||||
destroyScalarFuncSupport(pRuntimeEnv->scalarSup, pRuntimeEnv->pQueryAttr->numOfOutput);
|
//destroyScalarFuncSupport(pRuntimeEnv->scalarSup, pRuntimeEnv->pQueryAttr->numOfOutput);
|
||||||
tfree(pRuntimeEnv->pResultRowHashTable);
|
tfree(pRuntimeEnv->pResultRowHashTable);
|
||||||
tfree(pRuntimeEnv->keyBuf);
|
tfree(pRuntimeEnv->keyBuf);
|
||||||
tfree(pRuntimeEnv->prevRow);
|
tfree(pRuntimeEnv->prevRow);
|
||||||
|
@ -2212,7 +2212,7 @@ static void teardownQueryRuntimeEnv(STaskRuntimeEnv *pRuntimeEnv) {
|
||||||
|
|
||||||
//qDebug("QInfo:0x%"PRIx64" teardown runtime env", pQInfo->qId);
|
//qDebug("QInfo:0x%"PRIx64" teardown runtime env", pQInfo->qId);
|
||||||
|
|
||||||
destroyScalarFuncSupport(pRuntimeEnv->scalarSup, pQueryAttr->numOfOutput);
|
//destroyScalarFuncSupport(pRuntimeEnv->scalarSup, pQueryAttr->numOfOutput);
|
||||||
// destroyUdfInfo(pRuntimeEnv->pUdfInfo);
|
// destroyUdfInfo(pRuntimeEnv->pUdfInfo);
|
||||||
destroyResultBuf(pRuntimeEnv->pResultBuf);
|
destroyResultBuf(pRuntimeEnv->pResultBuf);
|
||||||
doFreeQueryHandle(pRuntimeEnv);
|
doFreeQueryHandle(pRuntimeEnv);
|
||||||
|
|
|
@ -8,7 +8,7 @@ AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
|
||||||
ADD_EXECUTABLE(executorTest ${SOURCE_LIST})
|
ADD_EXECUTABLE(executorTest ${SOURCE_LIST})
|
||||||
TARGET_LINK_LIBRARIES(
|
TARGET_LINK_LIBRARIES(
|
||||||
executorTest
|
executorTest
|
||||||
PUBLIC os util common transport gtest taos qcom executor function planner
|
PRIVATE os util common transport gtest taos qcom executor function planner scalar nodes
|
||||||
)
|
)
|
||||||
|
|
||||||
TARGET_INCLUDE_DIRECTORIES(
|
TARGET_INCLUDE_DIRECTORIES(
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
#include "trpc.h"
|
#include "trpc.h"
|
||||||
#include "stub.h"
|
#include "stub.h"
|
||||||
#include "executor.h"
|
#include "executor.h"
|
||||||
|
#include "tmsg.h"
|
||||||
|
#include "tname.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,10 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "tscalarfunction.h"
|
//#include "tscalarfunction.h"
|
||||||
|
|
||||||
typedef void (*_unary_scalar_fn_t)(SScalarFuncParam *pLeft, SScalarFuncParam* pOutput);
|
//typedef void (*_unary_scalar_fn_t)(SScalarParam *pLeft, SScalarParam* pOutput);
|
||||||
_unary_scalar_fn_t getUnaryScalarOperatorFn(int32_t binOperator);
|
//_unary_scalar_fn_t getUnaryScalarOperatorFn(int32_t binOperator);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tscalarfunction.h"
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "taosdef.h"
|
#include "taosdef.h"
|
||||||
#include "tmsg.h"
|
#include "tmsg.h"
|
||||||
|
@ -3221,6 +3220,7 @@ static void diff_function(SqlFunctionCtx *pCtx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
char *getArithColumnData(void *param, const char* name, int32_t colId) {
|
char *getArithColumnData(void *param, const char* name, int32_t colId) {
|
||||||
SScalarFunctionSupport *pSupport = (SScalarFunctionSupport *)param;
|
SScalarFunctionSupport *pSupport = (SScalarFunctionSupport *)param;
|
||||||
|
|
||||||
|
@ -3235,15 +3235,16 @@ char *getArithColumnData(void *param, const char* name, int32_t colId) {
|
||||||
assert(index >= 0);
|
assert(index >= 0);
|
||||||
return pSupport->data[index] + pSupport->offset * pSupport->colList[index].bytes;
|
return pSupport->data[index] + pSupport->offset * pSupport->colList[index].bytes;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void arithmetic_function(SqlFunctionCtx *pCtx) {
|
static void arithmetic_function(SqlFunctionCtx *pCtx) {
|
||||||
GET_RES_INFO(pCtx)->numOfRes += pCtx->size;
|
GET_RES_INFO(pCtx)->numOfRes += pCtx->size;
|
||||||
SScalarFunctionSupport *pSup = (SScalarFunctionSupport *)pCtx->param[1].pz;
|
//SScalarFunctionSupport *pSup = (SScalarFunctionSupport *)pCtx->param[1].pz;
|
||||||
|
|
||||||
SScalarFuncParam output = {0};
|
SScalarParam output = {0};
|
||||||
output.data = pCtx->pOutput;
|
output.data = pCtx->pOutput;
|
||||||
|
|
||||||
evaluateExprNodeTree(pSup->pExprInfo->pExpr, pCtx->size, &output, pSup, getArithColumnData);
|
//evaluateExprNodeTree(pSup->pExprInfo->pExpr, pCtx->size, &output, pSup, getArithColumnData);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LIST_MINMAX_N(ctx, minOutput, maxOutput, elemCnt, data, type, tsdbType, numOfNotNullElem) \
|
#define LIST_MINMAX_N(ctx, minOutput, maxOutput, elemCnt, data, type, tsdbType, numOfNotNullElem) \
|
||||||
|
|
|
@ -1,488 +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 "os.h"
|
|
||||||
|
|
||||||
#include "ttypes.h"
|
|
||||||
#include "tbinoperator.h"
|
|
||||||
#include "tcompare.h"
|
|
||||||
|
|
||||||
//GET_TYPED_DATA(v, double, pRight->type, (char *)&((right)[i]));
|
|
||||||
|
|
||||||
void calc_i32_i32_add(void *left, void *right, int32_t numLeft, int32_t numRight, void *output, int32_t order) {
|
|
||||||
int32_t *pLeft = (int32_t *)left;
|
|
||||||
int32_t *pRight = (int32_t *)right;
|
|
||||||
double * pOutput = (double *)output;
|
|
||||||
|
|
||||||
int32_t i = (order == TSDB_ORDER_ASC) ? 0 : TMAX(numLeft, numRight) - 1;
|
|
||||||
int32_t step = (order == TSDB_ORDER_ASC) ? 1 : -1;
|
|
||||||
|
|
||||||
if (numLeft == numRight) {
|
|
||||||
for (; i >= 0 && i < numRight; i += step, pOutput += 1) {
|
|
||||||
if (isNull((char *)&(pLeft[i]), TSDB_DATA_TYPE_INT) || isNull((char *)&(pRight[i]), TSDB_DATA_TYPE_INT)) {
|
|
||||||
SET_DOUBLE_NULL(pOutput);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
*pOutput = (double)pLeft[i] + pRight[i];
|
|
||||||
}
|
|
||||||
} else if (numLeft == 1) {
|
|
||||||
for (; i >= 0 && i < numRight; i += step, pOutput += 1) {
|
|
||||||
if (isNull((char *)(pLeft), TSDB_DATA_TYPE_INT) || isNull((char *)&(pRight[i]), TSDB_DATA_TYPE_INT)) {
|
|
||||||
SET_DOUBLE_NULL(pOutput);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
*pOutput = (double)pLeft[0] + pRight[i];
|
|
||||||
}
|
|
||||||
} else if (numRight == 1) {
|
|
||||||
for (; i >= 0 && i < numLeft; i += step, pOutput += 1) {
|
|
||||||
if (isNull((char *)&(pLeft[i]), TSDB_DATA_TYPE_INT) || isNull((char *)(pRight), TSDB_DATA_TYPE_INT)) {
|
|
||||||
SET_DOUBLE_NULL(pOutput);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
*pOutput = (double)pLeft[i] + pRight[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef double (*_getDoubleValue_fn_t)(void *src, int32_t index);
|
|
||||||
|
|
||||||
double getVectorDoubleValue_TINYINT(void *src, int32_t index) {
|
|
||||||
return (double)*((int8_t *)src + index);
|
|
||||||
}
|
|
||||||
double getVectorDoubleValue_UTINYINT(void *src, int32_t index) {
|
|
||||||
return (double)*((uint8_t *)src + index);
|
|
||||||
}
|
|
||||||
double getVectorDoubleValue_SMALLINT(void *src, int32_t index) {
|
|
||||||
return (double)*((int16_t *)src + index);
|
|
||||||
}
|
|
||||||
double getVectorDoubleValue_USMALLINT(void *src, int32_t index) {
|
|
||||||
return (double)*((uint16_t *)src + index);
|
|
||||||
}
|
|
||||||
double getVectorDoubleValue_INT(void *src, int32_t index) {
|
|
||||||
return (double)*((int32_t *)src + index);
|
|
||||||
}
|
|
||||||
double getVectorDoubleValue_UINT(void *src, int32_t index) {
|
|
||||||
return (double)*((uint32_t *)src + index);
|
|
||||||
}
|
|
||||||
double getVectorDoubleValue_BIGINT(void *src, int32_t index) {
|
|
||||||
return (double)*((int64_t *)src + index);
|
|
||||||
}
|
|
||||||
double getVectorDoubleValue_UBIGINT(void *src, int32_t index) {
|
|
||||||
return (double)*((uint64_t *)src + index);
|
|
||||||
}
|
|
||||||
double getVectorDoubleValue_FLOAT(void *src, int32_t index) {
|
|
||||||
return (double)*((float *)src + index);
|
|
||||||
}
|
|
||||||
double getVectorDoubleValue_DOUBLE(void *src, int32_t index) {
|
|
||||||
return (double)*((double *)src + index);
|
|
||||||
}
|
|
||||||
_getDoubleValue_fn_t getVectorDoubleValueFn(int32_t srcType) {
|
|
||||||
_getDoubleValue_fn_t p = NULL;
|
|
||||||
if(srcType==TSDB_DATA_TYPE_TINYINT) {
|
|
||||||
p = getVectorDoubleValue_TINYINT;
|
|
||||||
}else if(srcType==TSDB_DATA_TYPE_UTINYINT) {
|
|
||||||
p = getVectorDoubleValue_UTINYINT;
|
|
||||||
}else if(srcType==TSDB_DATA_TYPE_SMALLINT) {
|
|
||||||
p = getVectorDoubleValue_SMALLINT;
|
|
||||||
}else if(srcType==TSDB_DATA_TYPE_USMALLINT) {
|
|
||||||
p = getVectorDoubleValue_USMALLINT;
|
|
||||||
}else if(srcType==TSDB_DATA_TYPE_INT) {
|
|
||||||
p = getVectorDoubleValue_INT;
|
|
||||||
}else if(srcType==TSDB_DATA_TYPE_UINT) {
|
|
||||||
p = getVectorDoubleValue_UINT;
|
|
||||||
}else if(srcType==TSDB_DATA_TYPE_BIGINT) {
|
|
||||||
p = getVectorDoubleValue_BIGINT;
|
|
||||||
}else if(srcType==TSDB_DATA_TYPE_UBIGINT) {
|
|
||||||
p = getVectorDoubleValue_UBIGINT;
|
|
||||||
}else if(srcType==TSDB_DATA_TYPE_FLOAT) {
|
|
||||||
p = getVectorDoubleValue_FLOAT;
|
|
||||||
}else if(srcType==TSDB_DATA_TYPE_DOUBLE) {
|
|
||||||
p = getVectorDoubleValue_DOUBLE;
|
|
||||||
}else {
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
typedef void* (*_getValueAddr_fn_t)(void *src, int32_t index);
|
|
||||||
|
|
||||||
void* getVectorValueAddr_TINYINT(void *src, int32_t index) {
|
|
||||||
return (void*)((int8_t *)src + index);
|
|
||||||
}
|
|
||||||
void* getVectorValueAddr_UTINYINT(void *src, int32_t index) {
|
|
||||||
return (void*)((uint8_t *)src + index);
|
|
||||||
}
|
|
||||||
void* getVectorValueAddr_SMALLINT(void *src, int32_t index) {
|
|
||||||
return (void*)((int16_t *)src + index);
|
|
||||||
}
|
|
||||||
void* getVectorValueAddr_USMALLINT(void *src, int32_t index) {
|
|
||||||
return (void*)((uint16_t *)src + index);
|
|
||||||
}
|
|
||||||
void* getVectorValueAddr_INT(void *src, int32_t index) {
|
|
||||||
return (void*)((int32_t *)src + index);
|
|
||||||
}
|
|
||||||
void* getVectorValueAddr_UINT(void *src, int32_t index) {
|
|
||||||
return (void*)((uint32_t *)src + index);
|
|
||||||
}
|
|
||||||
void* getVectorValueAddr_BIGINT(void *src, int32_t index) {
|
|
||||||
return (void*)((int64_t *)src + index);
|
|
||||||
}
|
|
||||||
void* getVectorValueAddr_UBIGINT(void *src, int32_t index) {
|
|
||||||
return (void*)((uint64_t *)src + index);
|
|
||||||
}
|
|
||||||
void* getVectorValueAddr_FLOAT(void *src, int32_t index) {
|
|
||||||
return (void*)((float *)src + index);
|
|
||||||
}
|
|
||||||
void* getVectorValueAddr_DOUBLE(void *src, int32_t index) {
|
|
||||||
return (void*)((double *)src + index);
|
|
||||||
}
|
|
||||||
|
|
||||||
_getValueAddr_fn_t getVectorValueAddrFn(int32_t srcType) {
|
|
||||||
_getValueAddr_fn_t p = NULL;
|
|
||||||
if(srcType==TSDB_DATA_TYPE_TINYINT) {
|
|
||||||
p = getVectorValueAddr_TINYINT;
|
|
||||||
}else if(srcType==TSDB_DATA_TYPE_UTINYINT) {
|
|
||||||
p = getVectorValueAddr_UTINYINT;
|
|
||||||
}else if(srcType==TSDB_DATA_TYPE_SMALLINT) {
|
|
||||||
p = getVectorValueAddr_SMALLINT;
|
|
||||||
}else if(srcType==TSDB_DATA_TYPE_USMALLINT) {
|
|
||||||
p = getVectorValueAddr_USMALLINT;
|
|
||||||
}else if(srcType==TSDB_DATA_TYPE_INT) {
|
|
||||||
p = getVectorValueAddr_INT;
|
|
||||||
}else if(srcType==TSDB_DATA_TYPE_UINT) {
|
|
||||||
p = getVectorValueAddr_UINT;
|
|
||||||
}else if(srcType==TSDB_DATA_TYPE_BIGINT) {
|
|
||||||
p = getVectorValueAddr_BIGINT;
|
|
||||||
}else if(srcType==TSDB_DATA_TYPE_UBIGINT) {
|
|
||||||
p = getVectorValueAddr_UBIGINT;
|
|
||||||
}else if(srcType==TSDB_DATA_TYPE_FLOAT) {
|
|
||||||
p = getVectorValueAddr_FLOAT;
|
|
||||||
}else if(srcType==TSDB_DATA_TYPE_DOUBLE) {
|
|
||||||
p = getVectorValueAddr_DOUBLE;
|
|
||||||
}else {
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vectorAdd(SScalarFuncParam* pLeft, SScalarFuncParam* pRight, void *out, int32_t _ord) {
|
|
||||||
int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : TMAX(pLeft->num, pRight->num) - 1;
|
|
||||||
int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1;
|
|
||||||
|
|
||||||
double *output=(double*)out;
|
|
||||||
_getValueAddr_fn_t getVectorValueAddrFnLeft = getVectorValueAddrFn(pLeft->type);
|
|
||||||
_getValueAddr_fn_t getVectorValueAddrFnRight = getVectorValueAddrFn(pRight->type);
|
|
||||||
_getDoubleValue_fn_t getVectorDoubleValueFnLeft = getVectorDoubleValueFn(pLeft->type);
|
|
||||||
_getDoubleValue_fn_t getVectorDoubleValueFnRight = getVectorDoubleValueFn(pRight->type);
|
|
||||||
|
|
||||||
if (pLeft->num == pRight->num) {
|
|
||||||
for (; i < pRight->num && i >= 0; i += step, output += 1) {
|
|
||||||
if (isNull(getVectorValueAddrFnLeft(pLeft->data, i), pLeft->type) ||
|
|
||||||
isNull(getVectorValueAddrFnRight(pRight->data, i), pRight->type)) {
|
|
||||||
SET_DOUBLE_NULL(output);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
SET_DOUBLE_VAL(output, getVectorDoubleValueFnLeft(pLeft->data, i) + getVectorDoubleValueFnRight(pRight->data, i));
|
|
||||||
}
|
|
||||||
} else if (pLeft->num == 1) {
|
|
||||||
for (; i >= 0 && i < pRight->num; i += step, output += 1) {
|
|
||||||
if (isNull(getVectorValueAddrFnLeft(pLeft->data, 0), pLeft->type) || isNull(getVectorValueAddrFnRight(pRight->data,i), pRight->type)) {
|
|
||||||
SET_DOUBLE_NULL(output);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
SET_DOUBLE_VAL(output,getVectorDoubleValueFnLeft(pLeft->data, 0) + getVectorDoubleValueFnRight(pRight->data,i));
|
|
||||||
}
|
|
||||||
} else if (pRight->num == 1) {
|
|
||||||
for (; i >= 0 && i < pLeft->num; i += step, output += 1) {
|
|
||||||
if (isNull(getVectorValueAddrFnLeft(pLeft->data,i), pLeft->type) || isNull(getVectorValueAddrFnRight(pRight->data,0), pRight->type)) {
|
|
||||||
SET_DOUBLE_NULL(output);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
SET_DOUBLE_VAL(output,getVectorDoubleValueFnLeft(pLeft->data,i) + getVectorDoubleValueFnRight(pRight->data,0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void vectorSub(SScalarFuncParam* pLeft, SScalarFuncParam* pRight, void *out, int32_t _ord) {
|
|
||||||
int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : TMAX(pLeft->num, pRight->num) - 1;
|
|
||||||
int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1;
|
|
||||||
|
|
||||||
double *output=(double*)out;
|
|
||||||
_getValueAddr_fn_t getVectorValueAddrFnLeft = getVectorValueAddrFn(pLeft->type);
|
|
||||||
_getValueAddr_fn_t getVectorValueAddrFnRight = getVectorValueAddrFn(pRight->type);
|
|
||||||
_getDoubleValue_fn_t getVectorDoubleValueFnLeft = getVectorDoubleValueFn(pLeft->type);
|
|
||||||
_getDoubleValue_fn_t getVectorDoubleValueFnRight = getVectorDoubleValueFn(pRight->type);
|
|
||||||
|
|
||||||
if (pLeft->num == pRight->num) {
|
|
||||||
for (; i < pRight->num && i >= 0; i += step, output += 1) {
|
|
||||||
if (isNull(getVectorValueAddrFnLeft(pLeft->data, i), pLeft->type) ||
|
|
||||||
isNull(getVectorValueAddrFnRight(pRight->data, i), pRight->type)) {
|
|
||||||
SET_DOUBLE_NULL(output);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
SET_DOUBLE_VAL(output, getVectorDoubleValueFnLeft(pLeft->data, i) - getVectorDoubleValueFnRight(pRight->data, i));
|
|
||||||
}
|
|
||||||
} else if (pLeft->num == 1) {
|
|
||||||
for (; i >= 0 && i < pRight->num; i += step, output += 1) {
|
|
||||||
if (isNull(getVectorValueAddrFnLeft(pLeft->data, 0), pLeft->type) || isNull(getVectorValueAddrFnRight(pRight->data,i), pRight->type)) {
|
|
||||||
SET_DOUBLE_NULL(output);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
SET_DOUBLE_VAL(output,getVectorDoubleValueFnLeft(pLeft->data, 0) - getVectorDoubleValueFnRight(pRight->data,i));
|
|
||||||
}
|
|
||||||
} else if (pRight->num == 1) {
|
|
||||||
for (; i >= 0 && i < pLeft->num; i += step, output += 1) {
|
|
||||||
if (isNull(getVectorValueAddrFnLeft(pLeft->data,i), pLeft->type) || isNull(getVectorValueAddrFnRight(pRight->data,0), pRight->type)) {
|
|
||||||
SET_DOUBLE_NULL(output);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
SET_DOUBLE_VAL(output,getVectorDoubleValueFnLeft(pLeft->data,i) - getVectorDoubleValueFnRight(pRight->data,0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void vectorMultiply(SScalarFuncParam* pLeft, SScalarFuncParam* pRight, void *out, int32_t _ord) {
|
|
||||||
int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : TMAX(pLeft->num, pRight->num) - 1;
|
|
||||||
int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1;
|
|
||||||
|
|
||||||
double *output=(double*)out;
|
|
||||||
_getValueAddr_fn_t getVectorValueAddrFnLeft = getVectorValueAddrFn(pLeft->type);
|
|
||||||
_getValueAddr_fn_t getVectorValueAddrFnRight = getVectorValueAddrFn(pRight->type);
|
|
||||||
_getDoubleValue_fn_t getVectorDoubleValueFnLeft = getVectorDoubleValueFn(pLeft->type);
|
|
||||||
_getDoubleValue_fn_t getVectorDoubleValueFnRight = getVectorDoubleValueFn(pRight->type);
|
|
||||||
|
|
||||||
if (pLeft->num == pRight->num) {
|
|
||||||
for (; i < pRight->num && i >= 0; i += step, output += 1) {
|
|
||||||
if (isNull(getVectorValueAddrFnLeft(pLeft->data, i), pLeft->type) ||
|
|
||||||
isNull(getVectorValueAddrFnRight(pRight->data, i), pRight->type)) {
|
|
||||||
SET_DOUBLE_NULL(output);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
SET_DOUBLE_VAL(output, getVectorDoubleValueFnLeft(pLeft->data, i) * getVectorDoubleValueFnRight(pRight->data, i));
|
|
||||||
}
|
|
||||||
} else if (pLeft->num == 1) {
|
|
||||||
for (; i >= 0 && i < pRight->num; i += step, output += 1) {
|
|
||||||
if (isNull(getVectorValueAddrFnLeft(pLeft->data, 0), pLeft->type) || isNull(getVectorValueAddrFnRight(pRight->data,i), pRight->type)) {
|
|
||||||
SET_DOUBLE_NULL(output);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
SET_DOUBLE_VAL(output,getVectorDoubleValueFnLeft(pLeft->data, 0) * getVectorDoubleValueFnRight(pRight->data,i));
|
|
||||||
}
|
|
||||||
} else if (pRight->num == 1) {
|
|
||||||
for (; i >= 0 && i < pLeft->num; i += step, output += 1) {
|
|
||||||
if (isNull(getVectorValueAddrFnLeft(pLeft->data,i), pLeft->type) || isNull(getVectorValueAddrFnRight(pRight->data,0), pRight->type)) {
|
|
||||||
SET_DOUBLE_NULL(output);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
SET_DOUBLE_VAL(output,getVectorDoubleValueFnLeft(pLeft->data,i) * getVectorDoubleValueFnRight(pRight->data,0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void vectorDivide(SScalarFuncParam* pLeft, SScalarFuncParam* pRight, void *out, int32_t _ord) {
|
|
||||||
int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : TMAX(pLeft->num, pRight->num) - 1;
|
|
||||||
int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1;
|
|
||||||
|
|
||||||
double *output=(double*)out;
|
|
||||||
_getValueAddr_fn_t getVectorValueAddrFnLeft = getVectorValueAddrFn(pLeft->type);
|
|
||||||
_getValueAddr_fn_t getVectorValueAddrFnRight = getVectorValueAddrFn(pRight->type);
|
|
||||||
_getDoubleValue_fn_t getVectorDoubleValueFnLeft = getVectorDoubleValueFn(pLeft->type);
|
|
||||||
_getDoubleValue_fn_t getVectorDoubleValueFnRight = getVectorDoubleValueFn(pRight->type);
|
|
||||||
|
|
||||||
if (pLeft->num == pRight->num) {
|
|
||||||
for (; i < pRight->num && i >= 0; i += step, output += 1) {
|
|
||||||
if (isNull(getVectorValueAddrFnLeft(pLeft->data, i), pLeft->type) ||
|
|
||||||
isNull(getVectorValueAddrFnRight(pRight->data, i), pRight->type)) {
|
|
||||||
SET_DOUBLE_NULL(output);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
SET_DOUBLE_VAL(output, getVectorDoubleValueFnLeft(pLeft->data, i) / getVectorDoubleValueFnRight(pRight->data, i));
|
|
||||||
}
|
|
||||||
} else if (pLeft->num == 1) {
|
|
||||||
double left = getVectorDoubleValueFnLeft(pLeft->data, 0);
|
|
||||||
|
|
||||||
for (; i >= 0 && i < pRight->num; i += step, output += 1) {
|
|
||||||
if (isNull(&left, pLeft->type) || isNull(getVectorValueAddrFnRight(pRight->data,i), pRight->type)) {
|
|
||||||
SET_DOUBLE_NULL(output);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
SET_DOUBLE_VAL(output,left / getVectorDoubleValueFnRight(pRight->data,i));
|
|
||||||
}
|
|
||||||
} else if (pRight->num == 1) {
|
|
||||||
double right = getVectorDoubleValueFnRight(pRight->data, 0);
|
|
||||||
|
|
||||||
for (; i >= 0 && i < pLeft->num; i += step, output += 1) {
|
|
||||||
if (isNull(getVectorValueAddrFnLeft(pLeft->data, i), pLeft->type) ||
|
|
||||||
isNull(&right, pRight->type)) {
|
|
||||||
SET_DOUBLE_NULL(output);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
SET_DOUBLE_VAL(output, getVectorDoubleValueFnLeft(pLeft->data, i) / right);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void vectorRemainder(SScalarFuncParam* pLeft, SScalarFuncParam* pRight, void *out, int32_t _ord) {
|
|
||||||
int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : TMAX(pLeft->num, pRight->num) - 1;
|
|
||||||
int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1;
|
|
||||||
|
|
||||||
double * output = (double *)out;
|
|
||||||
_getValueAddr_fn_t getVectorValueAddrFnLeft = getVectorValueAddrFn(pLeft->type);
|
|
||||||
_getValueAddr_fn_t getVectorValueAddrFnRight = getVectorValueAddrFn(pRight->type);
|
|
||||||
_getDoubleValue_fn_t getVectorDoubleValueFnLeft = getVectorDoubleValueFn(pLeft->type);
|
|
||||||
_getDoubleValue_fn_t getVectorDoubleValueFnRight = getVectorDoubleValueFn(pRight->type);
|
|
||||||
|
|
||||||
if (pLeft->num == pRight->num) {
|
|
||||||
for (; i < pRight->num && i >= 0; i += step, output += 1) {
|
|
||||||
if (isNull(getVectorValueAddrFnLeft(pLeft->data, i), pLeft->type) ||
|
|
||||||
isNull(getVectorValueAddrFnRight(pRight->data, i), pRight->type)) {
|
|
||||||
SET_DOUBLE_NULL(output);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
double v, u = 0.0;
|
|
||||||
GET_TYPED_DATA(v, double, pRight->type, getVectorValueAddrFnRight(pRight->data, i));
|
|
||||||
if (getComparFunc(TSDB_DATA_TYPE_DOUBLE, 0)(&v, &u) == 0) {
|
|
||||||
SET_DOUBLE_NULL(output);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
double left = getVectorDoubleValueFnLeft(pLeft->data, i);
|
|
||||||
double right = getVectorDoubleValueFnRight(pRight->data, i);
|
|
||||||
SET_DOUBLE_VAL(output, left - ((int64_t)(left / right)) * right);
|
|
||||||
}
|
|
||||||
} else if (pLeft->num == 1) {
|
|
||||||
double left = getVectorDoubleValueFnLeft(pLeft->data, 0);
|
|
||||||
|
|
||||||
for (; i >= 0 && i < pRight->num; i += step, output += 1) {
|
|
||||||
if (isNull(&left, pLeft->type) ||
|
|
||||||
isNull(getVectorValueAddrFnRight(pRight->data, i), pRight->type)) {
|
|
||||||
SET_DOUBLE_NULL(output);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
double v, u = 0.0;
|
|
||||||
GET_TYPED_DATA(v, double, pRight->type, getVectorValueAddrFnRight(pRight->data, i));
|
|
||||||
if (getComparFunc(TSDB_DATA_TYPE_DOUBLE, 0)(&v, &u) == 0) {
|
|
||||||
SET_DOUBLE_NULL(output);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
double right = getVectorDoubleValueFnRight(pRight->data, i);
|
|
||||||
SET_DOUBLE_VAL(output, left - ((int64_t)(left / right)) * right);
|
|
||||||
}
|
|
||||||
} else if (pRight->num == 1) {
|
|
||||||
double right = getVectorDoubleValueFnRight(pRight->data, 0);
|
|
||||||
|
|
||||||
for (; i >= 0 && i < pLeft->num; i += step, output += 1) {
|
|
||||||
if (isNull(getVectorValueAddrFnLeft(pLeft->data, i), pLeft->type) ||
|
|
||||||
isNull(&right, pRight->type)) {
|
|
||||||
SET_DOUBLE_NULL(output);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
double v, u = 0.0;
|
|
||||||
GET_TYPED_DATA(v, double, pRight->type, getVectorValueAddrFnRight(pRight->data, 0));
|
|
||||||
if (getComparFunc(TSDB_DATA_TYPE_DOUBLE, 0)(&v, &u) == 0) {
|
|
||||||
SET_DOUBLE_NULL(output);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
double left = getVectorDoubleValueFnLeft(pLeft->data, i);
|
|
||||||
SET_DOUBLE_VAL(output, left - ((int64_t)(left / right)) * right);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void vectorConcat(SScalarFuncParam* pLeft, SScalarFuncParam* pRight, void *out, int32_t _ord) {
|
|
||||||
int32_t len = pLeft->bytes + pRight->bytes;
|
|
||||||
|
|
||||||
int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : TMAX(pLeft->num, pRight->num) - 1;
|
|
||||||
int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1;
|
|
||||||
|
|
||||||
char *output = (char *)out;
|
|
||||||
if (pLeft->num == pRight->num) {
|
|
||||||
for (; i < pRight->num && i >= 0; i += step, output += len) {
|
|
||||||
char* left = POINTER_SHIFT(pLeft->data, pLeft->bytes * i);
|
|
||||||
char* right = POINTER_SHIFT(pRight->data, pRight->bytes * i);
|
|
||||||
|
|
||||||
if (isNull(left, pLeft->type) || isNull(right, pRight->type)) {
|
|
||||||
setVardataNull(output, TSDB_DATA_TYPE_BINARY);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo define a macro
|
|
||||||
memcpy(varDataVal(output), varDataVal(left), varDataLen(left));
|
|
||||||
memcpy(varDataVal(output) + varDataLen(left), varDataVal(right), varDataLen(right));
|
|
||||||
varDataSetLen(output, varDataLen(left) + varDataLen(right));
|
|
||||||
}
|
|
||||||
} else if (pLeft->num == 1) {
|
|
||||||
for (; i >= 0 && i < pRight->num; i += step, output += len) {
|
|
||||||
char *right = POINTER_SHIFT(pRight->data, pRight->bytes * i);
|
|
||||||
if (isNull(pLeft->data, pLeft->type) || isNull(right, pRight->type)) {
|
|
||||||
setVardataNull(output, TSDB_DATA_TYPE_BINARY);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(varDataVal(output), varDataVal(pLeft->data), varDataLen(pLeft->data));
|
|
||||||
memcpy(varDataVal(output) + varDataLen(pLeft->data), varDataVal(right), varDataLen(right));
|
|
||||||
varDataSetLen(output, varDataLen(pLeft->data) + varDataLen(right));
|
|
||||||
}
|
|
||||||
} else if (pRight->num == 1) {
|
|
||||||
for (; i >= 0 && i < pLeft->num; i += step, output += len) {
|
|
||||||
char* left = POINTER_SHIFT(pLeft->data, pLeft->bytes * i);
|
|
||||||
if (isNull(left, pLeft->type) || isNull(pRight->data, pRight->type)) {
|
|
||||||
SET_DOUBLE_NULL(output);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(varDataVal(output), varDataVal(left), varDataLen(pRight->data));
|
|
||||||
memcpy(varDataVal(output) + varDataLen(left), varDataVal(pRight->data), varDataLen(pRight->data));
|
|
||||||
varDataSetLen(output, varDataLen(left) + varDataLen(pRight->data));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
_bin_scalar_fn_t getBinScalarOperatorFn(int32_t binFunctionId) {
|
|
||||||
switch (binFunctionId) {
|
|
||||||
case TSDB_BINARY_OP_ADD:
|
|
||||||
return vectorAdd;
|
|
||||||
case TSDB_BINARY_OP_SUBTRACT:
|
|
||||||
return vectorSub;
|
|
||||||
case TSDB_BINARY_OP_MULTIPLY:
|
|
||||||
return vectorMultiply;
|
|
||||||
case TSDB_BINARY_OP_DIVIDE:
|
|
||||||
return vectorDivide;
|
|
||||||
case TSDB_BINARY_OP_REMAINDER:
|
|
||||||
return vectorRemainder;
|
|
||||||
case TSDB_BINARY_OP_CONCAT:
|
|
||||||
return vectorConcat;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isBinaryStringOp(int32_t op) {
|
|
||||||
return op == TSDB_BINARY_OP_CONCAT;
|
|
||||||
}
|
|
|
@ -3,7 +3,6 @@
|
||||||
#include "function.h"
|
#include "function.h"
|
||||||
#include "thash.h"
|
#include "thash.h"
|
||||||
#include "taggfunction.h"
|
#include "taggfunction.h"
|
||||||
#include "tscalarfunction.h"
|
|
||||||
|
|
||||||
static SHashObj* functionHashTable = NULL;
|
static SHashObj* functionHashTable = NULL;
|
||||||
static SHashObj* udfHashTable = NULL;
|
static SHashObj* udfHashTable = NULL;
|
||||||
|
@ -18,12 +17,14 @@ static void doInitFunctionHashTable() {
|
||||||
taosHashPut(functionHashTable, aggFunc[i].name, len, (void*)&ptr, POINTER_BYTES);
|
taosHashPut(functionHashTable, aggFunc[i].name, len, (void*)&ptr, POINTER_BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
numOfEntries = tListLen(scalarFunc);
|
numOfEntries = tListLen(scalarFunc);
|
||||||
for(int32_t i = 0; i < numOfEntries; ++i) {
|
for(int32_t i = 0; i < numOfEntries; ++i) {
|
||||||
int32_t len = (int32_t) strlen(scalarFunc[i].name);
|
int32_t len = (int32_t) strlen(scalarFunc[i].name);
|
||||||
SScalarFunctionInfo* ptr = &scalarFunc[i];
|
SScalarFunctionInfo* ptr = &scalarFunc[i];
|
||||||
taosHashPut(functionHashTable, scalarFunc[i].name, len, (void*)&ptr, POINTER_BYTES);
|
taosHashPut(functionHashTable, scalarFunc[i].name, len, (void*)&ptr, POINTER_BYTES);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
udfHashTable = taosHashInit(numOfEntries, MurmurHash3_32, true, true);
|
udfHashTable = taosHashInit(numOfEntries, MurmurHash3_32, true, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,10 @@
|
||||||
|
|
||||||
|
|
||||||
// TODO dynamic define these functions
|
// TODO dynamic define these functions
|
||||||
_unary_scalar_fn_t getUnaryScalarOperatorFn(int32_t operator) {
|
//_unary_scalar_fn_t getUnaryScalarOperatorFn(int32_t operator) {
|
||||||
assert(0);
|
// assert(0);
|
||||||
}
|
//}
|
||||||
|
|
||||||
bool isStringOperatorFn(int32_t op) {
|
//bool isStringOperatorFn(int32_t op) {
|
||||||
return op == FUNCTION_LENGTH;
|
// return op == FUNCTION_LENGTH;
|
||||||
}
|
//}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#include "querynodes.h"
|
#include "querynodes.h"
|
||||||
#include "taos.h"
|
#include "taos.h"
|
||||||
|
#include "taoserror.h"
|
||||||
|
|
||||||
#define COPY_SCALAR_FIELD(fldname) \
|
#define COPY_SCALAR_FIELD(fldname) \
|
||||||
do { \
|
do { \
|
||||||
|
@ -57,14 +58,13 @@ static void dataTypeCopy(const SDataType* pSrc, SDataType* pDst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void exprNodeCopy(const SExprNode* pSrc, SExprNode* pDst) {
|
static void exprNodeCopy(const SExprNode* pSrc, SExprNode* pDst) {
|
||||||
COPY_SCALAR_FIELD(type);
|
|
||||||
dataTypeCopy(&pSrc->resType, &pDst->resType);
|
dataTypeCopy(&pSrc->resType, &pDst->resType);
|
||||||
COPY_CHAR_ARRAY_FIELD(aliasName);
|
COPY_CHAR_ARRAY_FIELD(aliasName);
|
||||||
// COPY_NODE_LIST_FIELD(pAssociationList);
|
// COPY_NODE_LIST_FIELD(pAssociationList);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SNode* columnNodeCopy(const SColumnNode* pSrc, SColumnNode* pDst) {
|
static SNode* columnNodeCopy(const SColumnNode* pSrc, SColumnNode* pDst) {
|
||||||
exprNodeCopy((const SExprNode*)&pSrc, (SExprNode*)&pDst);
|
exprNodeCopy((const SExprNode*)pSrc, (SExprNode*)pDst);
|
||||||
COPY_SCALAR_FIELD(colId);
|
COPY_SCALAR_FIELD(colId);
|
||||||
COPY_SCALAR_FIELD(colType);
|
COPY_SCALAR_FIELD(colType);
|
||||||
COPY_CHAR_ARRAY_FIELD(dbName);
|
COPY_CHAR_ARRAY_FIELD(dbName);
|
||||||
|
@ -76,7 +76,7 @@ static SNode* columnNodeCopy(const SColumnNode* pSrc, SColumnNode* pDst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static SNode* valueNodeCopy(const SValueNode* pSrc, SValueNode* pDst) {
|
static SNode* valueNodeCopy(const SValueNode* pSrc, SValueNode* pDst) {
|
||||||
exprNodeCopy((const SExprNode*)&pSrc, (SExprNode*)&pDst);
|
exprNodeCopy((const SExprNode*)pSrc, (SExprNode*)pDst);
|
||||||
COPY_CHAR_POINT_FIELD(literal);
|
COPY_CHAR_POINT_FIELD(literal);
|
||||||
COPY_SCALAR_FIELD(isDuration);
|
COPY_SCALAR_FIELD(isDuration);
|
||||||
switch (pSrc->node.resType.type) {
|
switch (pSrc->node.resType.type) {
|
||||||
|
@ -119,7 +119,7 @@ static SNode* valueNodeCopy(const SValueNode* pSrc, SValueNode* pDst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static SNode* operatorNodeCopy(const SOperatorNode* pSrc, SOperatorNode* pDst) {
|
static SNode* operatorNodeCopy(const SOperatorNode* pSrc, SOperatorNode* pDst) {
|
||||||
exprNodeCopy((const SExprNode*)&pSrc, (SExprNode*)&pDst);
|
exprNodeCopy((const SExprNode*)pSrc, (SExprNode*)pDst);
|
||||||
COPY_SCALAR_FIELD(opType);
|
COPY_SCALAR_FIELD(opType);
|
||||||
COPY_NODE_FIELD(pLeft);
|
COPY_NODE_FIELD(pLeft);
|
||||||
COPY_NODE_FIELD(pRight);
|
COPY_NODE_FIELD(pRight);
|
||||||
|
@ -127,14 +127,14 @@ static SNode* operatorNodeCopy(const SOperatorNode* pSrc, SOperatorNode* pDst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static SNode* logicConditionNodeCopy(const SLogicConditionNode* pSrc, SLogicConditionNode* pDst) {
|
static SNode* logicConditionNodeCopy(const SLogicConditionNode* pSrc, SLogicConditionNode* pDst) {
|
||||||
exprNodeCopy((const SExprNode*)&pSrc, (SExprNode*)&pDst);
|
exprNodeCopy((const SExprNode*)pSrc, (SExprNode*)pDst);
|
||||||
COPY_SCALAR_FIELD(condType);
|
COPY_SCALAR_FIELD(condType);
|
||||||
COPY_NODE_LIST_FIELD(pParameterList);
|
COPY_NODE_LIST_FIELD(pParameterList);
|
||||||
return (SNode*)pDst;
|
return (SNode*)pDst;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SNode* functionNodeCopy(const SFunctionNode* pSrc, SFunctionNode* pDst) {
|
static SNode* functionNodeCopy(const SFunctionNode* pSrc, SFunctionNode* pDst) {
|
||||||
exprNodeCopy((const SExprNode*)&pSrc, (SExprNode*)&pDst);
|
exprNodeCopy((const SExprNode*)pSrc, (SExprNode*)pDst);
|
||||||
COPY_CHAR_ARRAY_FIELD(functionName);
|
COPY_CHAR_ARRAY_FIELD(functionName);
|
||||||
COPY_SCALAR_FIELD(funcId);
|
COPY_SCALAR_FIELD(funcId);
|
||||||
COPY_SCALAR_FIELD(funcType);
|
COPY_SCALAR_FIELD(funcType);
|
||||||
|
@ -142,12 +142,19 @@ static SNode* functionNodeCopy(const SFunctionNode* pSrc, SFunctionNode* pDst) {
|
||||||
return (SNode*)pDst;
|
return (SNode*)pDst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SNode* groupingSetNodeCopy(const SGroupingSetNode* pSrc, SGroupingSetNode* pDst) {
|
||||||
|
COPY_SCALAR_FIELD(groupingSetType);
|
||||||
|
COPY_NODE_LIST_FIELD(pParameterList);
|
||||||
|
return (SNode*)pDst;
|
||||||
|
}
|
||||||
|
|
||||||
SNode* nodesCloneNode(const SNode* pNode) {
|
SNode* nodesCloneNode(const SNode* pNode) {
|
||||||
if (NULL == pNode) {
|
if (NULL == pNode) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
SNode* pDst = nodesMakeNode(nodeType(pNode));
|
SNode* pDst = nodesMakeNode(nodeType(pNode));
|
||||||
if (NULL == pDst) {
|
if (NULL == pDst) {
|
||||||
|
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
switch (nodeType(pNode)) {
|
switch (nodeType(pNode)) {
|
||||||
|
@ -164,7 +171,9 @@ SNode* nodesCloneNode(const SNode* pNode) {
|
||||||
case QUERY_NODE_REAL_TABLE:
|
case QUERY_NODE_REAL_TABLE:
|
||||||
case QUERY_NODE_TEMP_TABLE:
|
case QUERY_NODE_TEMP_TABLE:
|
||||||
case QUERY_NODE_JOIN_TABLE:
|
case QUERY_NODE_JOIN_TABLE:
|
||||||
|
break;
|
||||||
case QUERY_NODE_GROUPING_SET:
|
case QUERY_NODE_GROUPING_SET:
|
||||||
|
return groupingSetNodeCopy((const SGroupingSetNode*)pNode, (SGroupingSetNode*)pDst);
|
||||||
case QUERY_NODE_ORDER_BY_EXPR:
|
case QUERY_NODE_ORDER_BY_EXPR:
|
||||||
case QUERY_NODE_LIMIT:
|
case QUERY_NODE_LIMIT:
|
||||||
default:
|
default:
|
||||||
|
@ -174,8 +183,13 @@ SNode* nodesCloneNode(const SNode* pNode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SNodeList* nodesCloneList(const SNodeList* pList) {
|
SNodeList* nodesCloneList(const SNodeList* pList) {
|
||||||
|
if (NULL == pList) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
SNodeList* pDst = nodesMakeList();
|
SNodeList* pDst = nodesMakeList();
|
||||||
if (NULL == pDst) {
|
if (NULL == pDst) {
|
||||||
|
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
SNode* pNode;
|
SNode* pNode;
|
||||||
|
|
|
@ -26,27 +26,47 @@ static char* nodeName(ENodeType type) {
|
||||||
case QUERY_NODE_COLUMN:
|
case QUERY_NODE_COLUMN:
|
||||||
return "Column";
|
return "Column";
|
||||||
case QUERY_NODE_VALUE:
|
case QUERY_NODE_VALUE:
|
||||||
|
return "Value";
|
||||||
case QUERY_NODE_OPERATOR:
|
case QUERY_NODE_OPERATOR:
|
||||||
|
return "Operator";
|
||||||
case QUERY_NODE_LOGIC_CONDITION:
|
case QUERY_NODE_LOGIC_CONDITION:
|
||||||
|
return "LogicCondition";
|
||||||
case QUERY_NODE_FUNCTION:
|
case QUERY_NODE_FUNCTION:
|
||||||
|
return "Function";
|
||||||
case QUERY_NODE_REAL_TABLE:
|
case QUERY_NODE_REAL_TABLE:
|
||||||
|
return "RealTable";
|
||||||
case QUERY_NODE_TEMP_TABLE:
|
case QUERY_NODE_TEMP_TABLE:
|
||||||
|
return "TempTable";
|
||||||
case QUERY_NODE_JOIN_TABLE:
|
case QUERY_NODE_JOIN_TABLE:
|
||||||
|
return "JoinTable";
|
||||||
case QUERY_NODE_GROUPING_SET:
|
case QUERY_NODE_GROUPING_SET:
|
||||||
|
return "GroupingSet";
|
||||||
case QUERY_NODE_ORDER_BY_EXPR:
|
case QUERY_NODE_ORDER_BY_EXPR:
|
||||||
|
return "OrderByExpr";
|
||||||
case QUERY_NODE_LIMIT:
|
case QUERY_NODE_LIMIT:
|
||||||
|
return "Limit";
|
||||||
case QUERY_NODE_STATE_WINDOW:
|
case QUERY_NODE_STATE_WINDOW:
|
||||||
|
return "StateWindow";
|
||||||
case QUERY_NODE_SESSION_WINDOW:
|
case QUERY_NODE_SESSION_WINDOW:
|
||||||
|
return "SessionWinow";
|
||||||
case QUERY_NODE_INTERVAL_WINDOW:
|
case QUERY_NODE_INTERVAL_WINDOW:
|
||||||
|
return "IntervalWindow";
|
||||||
case QUERY_NODE_NODE_LIST:
|
case QUERY_NODE_NODE_LIST:
|
||||||
|
return "NodeList";
|
||||||
case QUERY_NODE_FILL:
|
case QUERY_NODE_FILL:
|
||||||
|
return "Fill";
|
||||||
case QUERY_NODE_COLUMN_REF:
|
case QUERY_NODE_COLUMN_REF:
|
||||||
|
return "ColumnRef";
|
||||||
case QUERY_NODE_TARGET:
|
case QUERY_NODE_TARGET:
|
||||||
|
return "Target";
|
||||||
case QUERY_NODE_RAW_EXPR:
|
case QUERY_NODE_RAW_EXPR:
|
||||||
|
return "RawExpr";
|
||||||
case QUERY_NODE_SET_OPERATOR:
|
case QUERY_NODE_SET_OPERATOR:
|
||||||
|
return "SetOperator";
|
||||||
case QUERY_NODE_SELECT_STMT:
|
case QUERY_NODE_SELECT_STMT:
|
||||||
|
return "SelectStmt";
|
||||||
case QUERY_NODE_SHOW_STMT:
|
case QUERY_NODE_SHOW_STMT:
|
||||||
break;
|
return "ShowStmt";
|
||||||
case QUERY_NODE_LOGIC_PLAN_SCAN:
|
case QUERY_NODE_LOGIC_PLAN_SCAN:
|
||||||
return "LogicScan";
|
return "LogicScan";
|
||||||
case QUERY_NODE_LOGIC_PLAN_JOIN:
|
case QUERY_NODE_LOGIC_PLAN_JOIN:
|
||||||
|
@ -119,7 +139,7 @@ static int32_t logicPlanNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
static const char* jkScanLogicPlanScanCols = "ScanCols";
|
static const char* jkScanLogicPlanScanCols = "ScanCols";
|
||||||
static const char* jkScanLogicPlanTableMeta = "TableMeta";
|
static const char* jkScanLogicPlanTableMeta = "TableMeta";
|
||||||
|
|
||||||
static int32_t logicScanToJson(const void* pObj, SJson* pJson) {
|
static int32_t logicScanNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
const SScanLogicNode* pNode = (const SScanLogicNode*)pObj;
|
const SScanLogicNode* pNode = (const SScanLogicNode*)pObj;
|
||||||
|
|
||||||
int32_t code = logicPlanNodeToJson(pObj, pJson);
|
int32_t code = logicPlanNodeToJson(pObj, pJson);
|
||||||
|
@ -135,7 +155,7 @@ static int32_t logicScanToJson(const void* pObj, SJson* pJson) {
|
||||||
|
|
||||||
static const char* jkProjectLogicPlanProjections = "Projections";
|
static const char* jkProjectLogicPlanProjections = "Projections";
|
||||||
|
|
||||||
static int32_t logicProjectToJson(const void* pObj, SJson* pJson) {
|
static int32_t logicProjectNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
const SProjectLogicNode* pNode = (const SProjectLogicNode*)pObj;
|
const SProjectLogicNode* pNode = (const SProjectLogicNode*)pObj;
|
||||||
|
|
||||||
int32_t code = logicPlanNodeToJson(pObj, pJson);
|
int32_t code = logicPlanNodeToJson(pObj, pJson);
|
||||||
|
@ -149,7 +169,7 @@ static int32_t logicProjectToJson(const void* pObj, SJson* pJson) {
|
||||||
static const char* jkJoinLogicPlanJoinType = "JoinType";
|
static const char* jkJoinLogicPlanJoinType = "JoinType";
|
||||||
static const char* jkJoinLogicPlanOnConditions = "OnConditions";
|
static const char* jkJoinLogicPlanOnConditions = "OnConditions";
|
||||||
|
|
||||||
static int32_t logicJoinToJson(const void* pObj, SJson* pJson) {
|
static int32_t logicJoinNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
const SJoinLogicNode* pNode = (const SJoinLogicNode*)pObj;
|
const SJoinLogicNode* pNode = (const SJoinLogicNode*)pObj;
|
||||||
|
|
||||||
int32_t code = logicPlanNodeToJson(pObj, pJson);
|
int32_t code = logicPlanNodeToJson(pObj, pJson);
|
||||||
|
@ -163,14 +183,14 @@ static int32_t logicJoinToJson(const void* pObj, SJson* pJson) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t logicFilterToJson(const void* pObj, SJson* pJson) {
|
static int32_t logicFilterNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
return logicPlanNodeToJson(pObj, pJson);
|
return logicPlanNodeToJson(pObj, pJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* jkAggLogicPlanGroupKeys = "GroupKeys";
|
static const char* jkAggLogicPlanGroupKeys = "GroupKeys";
|
||||||
static const char* jkAggLogicPlanAggFuncs = "AggFuncs";
|
static const char* jkAggLogicPlanAggFuncs = "AggFuncs";
|
||||||
|
|
||||||
static int32_t logicAggToJson(const void* pObj, SJson* pJson) {
|
static int32_t logicAggNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
const SAggLogicNode* pNode = (const SAggLogicNode*)pObj;
|
const SAggLogicNode* pNode = (const SAggLogicNode*)pObj;
|
||||||
|
|
||||||
int32_t code = logicPlanNodeToJson(pObj, pJson);
|
int32_t code = logicPlanNodeToJson(pObj, pJson);
|
||||||
|
@ -184,17 +204,291 @@ static int32_t logicAggToJson(const void* pObj, SJson* pJson) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char* jkDataTypeType = "Type";
|
||||||
|
static const char* jkDataTypePrecision = "Precision";
|
||||||
|
static const char* jkDataTypeScale = "Scale";
|
||||||
|
static const char* jkDataTypeDataBytes = "Bytes";
|
||||||
|
|
||||||
|
static int32_t dataTypeToJson(const void* pObj, SJson* pJson) {
|
||||||
|
const SDataType* pNode = (const SDataType*)pObj;
|
||||||
|
|
||||||
|
int32_t code = tjsonAddIntegerToObject(pJson, jkDataTypeType, pNode->type);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkDataTypePrecision, pNode->precision);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkDataTypeScale, pNode->scale);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkDataTypeDataBytes, pNode->bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* jkExprDataType = "DataType";
|
||||||
|
static const char* jkExprAliasName = "AliasName";
|
||||||
|
|
||||||
|
static int32_t exprNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
|
const SExprNode* pNode = (const SExprNode*)pObj;
|
||||||
|
|
||||||
|
int32_t code = tjsonAddObject(pJson, jkExprDataType, dataTypeToJson, &pNode->resType);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddStringToObject(pJson, jkExprAliasName, pNode->aliasName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* jkColumnTableId = "TableId";
|
||||||
|
static const char* jkColumnColId = "ColId";
|
||||||
|
static const char* jkColumnColType = "ColType";
|
||||||
|
static const char* jkColumnDbName = "DbName";
|
||||||
|
static const char* jkColumnTableName = "TableName";
|
||||||
|
static const char* jkColumnTableAlias = "TableAlias";
|
||||||
|
static const char* jkColumnColName = "ColName";
|
||||||
|
|
||||||
|
static int32_t columnNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
|
const SColumnNode* pNode = (const SColumnNode*)pObj;
|
||||||
|
|
||||||
|
int32_t code = exprNodeToJson(pObj, pJson);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkColumnTableId, pNode->tableId);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkColumnColId, pNode->colId);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkColumnColType, pNode->colType);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddStringToObject(pJson, jkColumnDbName, pNode->dbName);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddStringToObject(pJson, jkColumnTableName, pNode->tableName);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddStringToObject(pJson, jkColumnTableAlias, pNode->tableAlias);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddStringToObject(pJson, jkColumnColName, pNode->colName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// typedef struct SValueNode {
|
||||||
|
// SExprNode node; // QUERY_NODE_VALUE
|
||||||
|
// char* ;
|
||||||
|
// bool ;
|
||||||
|
// union {
|
||||||
|
// bool b;
|
||||||
|
// int64_t i;
|
||||||
|
// uint64_t u;
|
||||||
|
// double d;
|
||||||
|
// char* p;
|
||||||
|
// } datum;
|
||||||
|
// } SValueNode;
|
||||||
|
|
||||||
|
static const char* jkValueLiteral = "Literal";
|
||||||
|
static const char* jkValueDuration = "Duration";
|
||||||
|
static const char* jkValueDatum = "Datum";
|
||||||
|
|
||||||
|
static int32_t valueNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
|
const SValueNode* pNode = (const SValueNode*)pObj;
|
||||||
|
|
||||||
|
int32_t code = exprNodeToJson(pObj, pJson);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddStringToObject(pJson, jkValueLiteral, pNode->literal);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkValueDuration, pNode->isDuration);
|
||||||
|
}
|
||||||
|
switch (pNode->node.resType.type) {
|
||||||
|
case TSDB_DATA_TYPE_NULL:
|
||||||
|
break;
|
||||||
|
case TSDB_DATA_TYPE_BOOL:
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkValueDuration, pNode->datum.b);
|
||||||
|
break;
|
||||||
|
case TSDB_DATA_TYPE_TINYINT:
|
||||||
|
case TSDB_DATA_TYPE_SMALLINT:
|
||||||
|
case TSDB_DATA_TYPE_INT:
|
||||||
|
case TSDB_DATA_TYPE_BIGINT:
|
||||||
|
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkValueDuration, pNode->datum.i);
|
||||||
|
break;
|
||||||
|
case TSDB_DATA_TYPE_UTINYINT:
|
||||||
|
case TSDB_DATA_TYPE_USMALLINT:
|
||||||
|
case TSDB_DATA_TYPE_UINT:
|
||||||
|
case TSDB_DATA_TYPE_UBIGINT:
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkValueDuration, pNode->datum.u);
|
||||||
|
break;
|
||||||
|
case TSDB_DATA_TYPE_FLOAT:
|
||||||
|
case TSDB_DATA_TYPE_DOUBLE:
|
||||||
|
code = tjsonAddDoubleToObject(pJson, jkValueDuration, pNode->datum.d);
|
||||||
|
break;
|
||||||
|
case TSDB_DATA_TYPE_BINARY:
|
||||||
|
case TSDB_DATA_TYPE_NCHAR:
|
||||||
|
case TSDB_DATA_TYPE_VARCHAR:
|
||||||
|
case TSDB_DATA_TYPE_VARBINARY:
|
||||||
|
code = tjsonAddStringToObject(pJson, jkValueLiteral, pNode->datum.p);
|
||||||
|
break;
|
||||||
|
case TSDB_DATA_TYPE_JSON:
|
||||||
|
case TSDB_DATA_TYPE_DECIMAL:
|
||||||
|
case TSDB_DATA_TYPE_BLOB:
|
||||||
|
// todo
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* jkOperatorType = "OpType";
|
||||||
|
static const char* jkOperatorLeft = "Left";
|
||||||
|
static const char* jkOperatorRight = "Right";
|
||||||
|
|
||||||
|
static int32_t operatorNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
|
const SOperatorNode* pNode = (const SOperatorNode*)pObj;
|
||||||
|
|
||||||
|
int32_t code = exprNodeToJson(pObj, pJson);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkOperatorType, pNode->opType);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddObject(pJson, jkOperatorLeft, nodeToJson, pNode->pLeft);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddObject(pJson, jkOperatorRight, nodeToJson, pNode->pRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* jkLogicCondType = "CondType";
|
||||||
|
static const char* jkLogicCondParameters = "Parameters";
|
||||||
|
|
||||||
|
static int32_t logicConditionNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
|
const SLogicConditionNode* pNode = (const SLogicConditionNode*)pObj;
|
||||||
|
|
||||||
|
int32_t code = exprNodeToJson(pObj, pJson);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkLogicCondType, pNode->condType);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = addNodeList(pJson, jkLogicCondParameters, nodeToJson, pNode->pParameterList);
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* jkFunctionName = "Name";
|
||||||
|
static const char* jkFunctionId = "Id";
|
||||||
|
static const char* jkFunctionType = "Type";
|
||||||
|
static const char* jkFunctionParameter = "Parameters";
|
||||||
|
|
||||||
|
static int32_t functionNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
|
const SFunctionNode* pNode = (const SFunctionNode*)pObj;
|
||||||
|
|
||||||
|
int32_t code = exprNodeToJson(pObj, pJson);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddStringToObject(pJson, jkFunctionName, pNode->functionName);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkFunctionId, pNode->funcId);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkFunctionType, pNode->funcType);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = addNodeList(pJson, jkFunctionParameter, nodeToJson, pNode->pParameterList);
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* jkGroupingSetType = "GroupingSetType";
|
||||||
|
static const char* jkGroupingSetParameter = "Parameters";
|
||||||
|
|
||||||
|
static int32_t groupingSetNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
|
const SGroupingSetNode* pNode = (const SGroupingSetNode*)pObj;
|
||||||
|
|
||||||
|
int32_t code = tjsonAddIntegerToObject(pJson, jkGroupingSetType, pNode->groupingSetType);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = addNodeList(pJson, jkGroupingSetParameter, nodeToJson, pNode->pParameterList);
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* jkSelectStmtDistinct = "Distinct";
|
||||||
|
static const char* jkSelectStmtProjections = "Projections";
|
||||||
|
static const char* jkSelectStmtFrom = "From";
|
||||||
|
static const char* jkSelectStmtWhere = "Where";
|
||||||
|
static const char* jkSelectStmtPartitionBy = "PartitionBy";
|
||||||
|
static const char* jkSelectStmtWindow = "Window";
|
||||||
|
static const char* jkSelectStmtGroupBy = "GroupBy";
|
||||||
|
static const char* jkSelectStmtHaving = "Having";
|
||||||
|
static const char* jkSelectStmtOrderBy = "OrderBy";
|
||||||
|
static const char* jkSelectStmtLimit = "Limit";
|
||||||
|
static const char* jkSelectStmtSlimit = "Slimit";
|
||||||
|
|
||||||
|
static int32_t selectStmtTojson(const void* pObj, SJson* pJson) {
|
||||||
|
const SSelectStmt* pNode = (const SSelectStmt*)pObj;
|
||||||
|
|
||||||
|
int32_t code = tjsonAddIntegerToObject(pJson, jkSelectStmtDistinct, pNode->isDistinct);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = addNodeList(pJson, jkSelectStmtProjections, nodeToJson, pNode->pProjectionList);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddObject(pJson, jkSelectStmtFrom, nodeToJson, pNode->pFromTable);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddObject(pJson, jkSelectStmtWhere, nodeToJson, pNode->pWhere);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = addNodeList(pJson, jkSelectStmtPartitionBy, nodeToJson, pNode->pPartitionByList);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddObject(pJson, jkSelectStmtWindow, nodeToJson, pNode->pWindow);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = addNodeList(pJson, jkSelectStmtGroupBy, nodeToJson, pNode->pGroupByList);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddObject(pJson, jkSelectStmtHaving, nodeToJson, pNode->pHaving);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = addNodeList(pJson, jkSelectStmtOrderBy, nodeToJson, pNode->pOrderByList);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddObject(pJson, jkSelectStmtLimit, nodeToJson, pNode->pLimit);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddObject(pJson, jkSelectStmtSlimit, nodeToJson, pNode->pSlimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
|
static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
switch (nodeType(pObj)) {
|
switch (nodeType(pObj)) {
|
||||||
case QUERY_NODE_COLUMN:
|
case QUERY_NODE_COLUMN:
|
||||||
|
return columnNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_VALUE:
|
case QUERY_NODE_VALUE:
|
||||||
|
return valueNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_OPERATOR:
|
case QUERY_NODE_OPERATOR:
|
||||||
|
return operatorNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_LOGIC_CONDITION:
|
case QUERY_NODE_LOGIC_CONDITION:
|
||||||
|
return logicConditionNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_FUNCTION:
|
case QUERY_NODE_FUNCTION:
|
||||||
|
return functionNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_REAL_TABLE:
|
case QUERY_NODE_REAL_TABLE:
|
||||||
case QUERY_NODE_TEMP_TABLE:
|
case QUERY_NODE_TEMP_TABLE:
|
||||||
case QUERY_NODE_JOIN_TABLE:
|
case QUERY_NODE_JOIN_TABLE:
|
||||||
|
break;
|
||||||
case QUERY_NODE_GROUPING_SET:
|
case QUERY_NODE_GROUPING_SET:
|
||||||
|
return groupingSetNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_ORDER_BY_EXPR:
|
case QUERY_NODE_ORDER_BY_EXPR:
|
||||||
case QUERY_NODE_LIMIT:
|
case QUERY_NODE_LIMIT:
|
||||||
case QUERY_NODE_STATE_WINDOW:
|
case QUERY_NODE_STATE_WINDOW:
|
||||||
|
@ -206,19 +500,21 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
case QUERY_NODE_TARGET:
|
case QUERY_NODE_TARGET:
|
||||||
case QUERY_NODE_RAW_EXPR:
|
case QUERY_NODE_RAW_EXPR:
|
||||||
case QUERY_NODE_SET_OPERATOR:
|
case QUERY_NODE_SET_OPERATOR:
|
||||||
|
break;
|
||||||
case QUERY_NODE_SELECT_STMT:
|
case QUERY_NODE_SELECT_STMT:
|
||||||
|
return selectStmtTojson(pObj, pJson);
|
||||||
case QUERY_NODE_SHOW_STMT:
|
case QUERY_NODE_SHOW_STMT:
|
||||||
break;
|
break;
|
||||||
case QUERY_NODE_LOGIC_PLAN_SCAN:
|
case QUERY_NODE_LOGIC_PLAN_SCAN:
|
||||||
return logicScanToJson(pObj, pJson);
|
return logicScanNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_LOGIC_PLAN_JOIN:
|
case QUERY_NODE_LOGIC_PLAN_JOIN:
|
||||||
return logicJoinToJson(pObj, pJson);
|
return logicJoinNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_LOGIC_PLAN_FILTER:
|
case QUERY_NODE_LOGIC_PLAN_FILTER:
|
||||||
return logicFilterToJson(pObj, pJson);
|
return logicFilterNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_LOGIC_PLAN_AGG:
|
case QUERY_NODE_LOGIC_PLAN_AGG:
|
||||||
return logicAggToJson(pObj, pJson);
|
return logicAggNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_LOGIC_PLAN_PROJECT:
|
case QUERY_NODE_LOGIC_PLAN_PROJECT:
|
||||||
return logicProjectToJson(pObj, pJson);
|
return logicProjectNodeToJson(pObj, pJson);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -238,7 +534,7 @@ static int32_t nodeToJson(const void* pObj, SJson* pJson) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t nodesNodeToString(const SNode* pNode, char** pStr, int32_t* pLen) {
|
int32_t nodesNodeToString(const SNode* pNode, bool format, char** pStr, int32_t* pLen) {
|
||||||
if (NULL == pNode || NULL == pStr || NULL == pLen) {
|
if (NULL == pNode || NULL == pStr || NULL == pLen) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -255,7 +551,7 @@ int32_t nodesNodeToString(const SNode* pNode, char** pStr, int32_t* pLen) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
*pStr = tjsonToString(pJson);
|
*pStr = format ? tjsonToString(pJson) : tjsonToUnformattedString(pJson);
|
||||||
tjsonDelete(pJson);
|
tjsonDelete(pJson);
|
||||||
|
|
||||||
*pLen = strlen(*pStr) + 1;
|
*pLen = strlen(*pStr) + 1;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "plannodes.h"
|
#include "plannodes.h"
|
||||||
#include "taos.h"
|
#include "taos.h"
|
||||||
#include "taoserror.h"
|
#include "taoserror.h"
|
||||||
|
#include "taos.h"
|
||||||
#include "thash.h"
|
#include "thash.h"
|
||||||
|
|
||||||
static SNode* makeNode(ENodeType type, size_t size) {
|
static SNode* makeNode(ENodeType type, size_t size) {
|
||||||
|
@ -132,11 +133,22 @@ int32_t nodesListAppend(SNodeList* pList, SNode* pNode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t nodesListAppendList(SNodeList* pTarget, SNodeList* pSrc) {
|
int32_t nodesListAppendList(SNodeList* pTarget, SNodeList* pSrc) {
|
||||||
pTarget->pTail->pNext = pSrc->pHead;
|
if (NULL == pTarget || NULL == pSrc) {
|
||||||
pSrc->pHead->pPrev = pTarget->pTail;
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL == pTarget->pHead) {
|
||||||
|
pTarget->pHead = pSrc->pHead;
|
||||||
|
} else {
|
||||||
|
pTarget->pTail->pNext = pSrc->pHead;
|
||||||
|
if (NULL != pSrc->pHead) {
|
||||||
|
pSrc->pHead->pPrev = pTarget->pTail;
|
||||||
|
}
|
||||||
|
}
|
||||||
pTarget->pTail = pSrc->pTail;
|
pTarget->pTail = pSrc->pTail;
|
||||||
pTarget->length += pSrc->length;
|
pTarget->length += pSrc->length;
|
||||||
tfree(pSrc);
|
tfree(pSrc);
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,6 +184,36 @@ void nodesDestroyList(SNodeList* pList) {
|
||||||
tfree(pList);
|
tfree(pList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *nodesGetValueFromNode(SValueNode *pNode) {
|
||||||
|
switch (pNode->node.resType.type) {
|
||||||
|
case TSDB_DATA_TYPE_BOOL:
|
||||||
|
return (void *)&pNode->datum.b;
|
||||||
|
case TSDB_DATA_TYPE_TINYINT:
|
||||||
|
case TSDB_DATA_TYPE_SMALLINT:
|
||||||
|
case TSDB_DATA_TYPE_INT:
|
||||||
|
case TSDB_DATA_TYPE_BIGINT:
|
||||||
|
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||||
|
return (void *)&pNode->datum.i;
|
||||||
|
case TSDB_DATA_TYPE_UTINYINT:
|
||||||
|
case TSDB_DATA_TYPE_USMALLINT:
|
||||||
|
case TSDB_DATA_TYPE_UINT:
|
||||||
|
case TSDB_DATA_TYPE_UBIGINT:
|
||||||
|
return (void *)&pNode->datum.u;
|
||||||
|
case TSDB_DATA_TYPE_FLOAT:
|
||||||
|
case TSDB_DATA_TYPE_DOUBLE:
|
||||||
|
return (void *)&pNode->datum.d;
|
||||||
|
case TSDB_DATA_TYPE_BINARY:
|
||||||
|
case TSDB_DATA_TYPE_NCHAR:
|
||||||
|
case TSDB_DATA_TYPE_VARCHAR:
|
||||||
|
case TSDB_DATA_TYPE_VARBINARY:
|
||||||
|
return (void *)pNode->datum.p;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
bool nodesIsExprNode(const SNode* pNode) {
|
bool nodesIsExprNode(const SNode* pNode) {
|
||||||
ENodeType type = nodeType(pNode);
|
ENodeType type = nodeType(pNode);
|
||||||
return (QUERY_NODE_COLUMN == type || QUERY_NODE_VALUE == type || QUERY_NODE_OPERATOR == type || QUERY_NODE_FUNCTION == type);
|
return (QUERY_NODE_COLUMN == type || QUERY_NODE_VALUE == type || QUERY_NODE_OPERATOR == type || QUERY_NODE_FUNCTION == type);
|
||||||
|
@ -290,6 +332,10 @@ int32_t nodesCollectColumns(SSelectStmt* pSelect, ESqlClause clause, const char*
|
||||||
nodesDestroyList(cxt.pCols);
|
nodesDestroyList(cxt.pCols);
|
||||||
return cxt.errCode;
|
return cxt.errCode;
|
||||||
}
|
}
|
||||||
|
if (0 == LIST_LENGTH(cxt.pCols)) {
|
||||||
|
nodesDestroyList(cxt.pCols);
|
||||||
|
cxt.pCols = NULL;
|
||||||
|
}
|
||||||
*pCols = cxt.pCols;
|
*pCols = cxt.pCols;
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -349,7 +349,7 @@ static SNodeList* getProjectList(SNode* pNode) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setColumnInfoBySchema(const SRealTableNode* pTable, const SSchema* pColSchema, SColumnNode* pCol) {
|
static void setColumnInfoBySchema(const SRealTableNode* pTable, const SSchema* pColSchema, bool isTag, SColumnNode* pCol) {
|
||||||
strcpy(pCol->dbName, pTable->table.dbName);
|
strcpy(pCol->dbName, pTable->table.dbName);
|
||||||
strcpy(pCol->tableAlias, pTable->table.tableAlias);
|
strcpy(pCol->tableAlias, pTable->table.tableAlias);
|
||||||
strcpy(pCol->tableName, pTable->table.tableName);
|
strcpy(pCol->tableName, pTable->table.tableName);
|
||||||
|
@ -359,7 +359,7 @@ static void setColumnInfoBySchema(const SRealTableNode* pTable, const SSchema* p
|
||||||
}
|
}
|
||||||
pCol->tableId = pTable->pMeta->uid;
|
pCol->tableId = pTable->pMeta->uid;
|
||||||
pCol->colId = pColSchema->colId;
|
pCol->colId = pColSchema->colId;
|
||||||
// pCol->colType = pColSchema->type;
|
pCol->colType = isTag ? COLUMN_TYPE_TAG : COLUMN_TYPE_COLUMN;
|
||||||
pCol->node.resType.type = pColSchema->type;
|
pCol->node.resType.type = pColSchema->type;
|
||||||
pCol->node.resType.bytes = pColSchema->bytes;
|
pCol->node.resType.bytes = pColSchema->bytes;
|
||||||
}
|
}
|
||||||
|
@ -383,7 +383,7 @@ static int32_t createColumnNodeByTable(STranslateContext* pCxt, const STableNode
|
||||||
if (NULL == pCol) {
|
if (NULL == pCol) {
|
||||||
return generateSyntaxErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY);
|
return generateSyntaxErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY);
|
||||||
}
|
}
|
||||||
setColumnInfoBySchema((SRealTableNode*)pTable, pMeta->schema + i, pCol);
|
setColumnInfoBySchema((SRealTableNode*)pTable, pMeta->schema + i, (i < pMeta->tableInfo.numOfTags), pCol);
|
||||||
nodesListAppend(pList, (SNode*)pCol);
|
nodesListAppend(pList, (SNode*)pCol);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -408,7 +408,7 @@ static bool findAndSetColumn(SColumnNode* pCol, const STableNode* pTable) {
|
||||||
int32_t nums = pMeta->tableInfo.numOfTags + pMeta->tableInfo.numOfColumns;
|
int32_t nums = pMeta->tableInfo.numOfTags + pMeta->tableInfo.numOfColumns;
|
||||||
for (int32_t i = 0; i < nums; ++i) {
|
for (int32_t i = 0; i < nums; ++i) {
|
||||||
if (0 == strcmp(pCol->colName, pMeta->schema[i].name)) {
|
if (0 == strcmp(pCol->colName, pMeta->schema[i].name)) {
|
||||||
setColumnInfoBySchema((SRealTableNode*)pTable, pMeta->schema + i, pCol);
|
setColumnInfoBySchema((SRealTableNode*)pTable, pMeta->schema + i, (i < pMeta->tableInfo.numOfTags), pCol);
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,9 @@
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void generateTestT1(MockCatalogService* mcs) {
|
void generateTestT1(MockCatalogService* mcs) {
|
||||||
ITableBuilder& builder = mcs->createTableBuilder("test", "t1", TSDB_NORMAL_TABLE, 3)
|
ITableBuilder& builder = mcs->createTableBuilder("test", "t1", TSDB_NORMAL_TABLE, 4)
|
||||||
.setPrecision(TSDB_TIME_PRECISION_MILLI).setVgid(1).addColumn("ts", TSDB_DATA_TYPE_TIMESTAMP)
|
.setPrecision(TSDB_TIME_PRECISION_MILLI).setVgid(1).addColumn("ts", TSDB_DATA_TYPE_TIMESTAMP)
|
||||||
.addColumn("c1", TSDB_DATA_TYPE_INT).addColumn("c2", TSDB_DATA_TYPE_BINARY, 20);
|
.addColumn("c1", TSDB_DATA_TYPE_INT).addColumn("c2", TSDB_DATA_TYPE_BINARY, 20).addColumn("c3", TSDB_DATA_TYPE_BIGINT);
|
||||||
builder.done();
|
builder.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,20 +18,20 @@
|
||||||
|
|
||||||
#define CHECK_ALLOC(p, res) \
|
#define CHECK_ALLOC(p, res) \
|
||||||
do { \
|
do { \
|
||||||
if (NULL == p) { \
|
if (NULL == (p)) { \
|
||||||
printf("%s : %d\n", __FUNCTION__, __LINE__); \
|
printf("%s : %d\n", __FUNCTION__, __LINE__); \
|
||||||
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; \
|
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; \
|
||||||
return res; \
|
return (res); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define CHECK_CODE(exec, res) \
|
#define CHECK_CODE(exec, res) \
|
||||||
do { \
|
do { \
|
||||||
int32_t code = exec; \
|
int32_t code = (exec); \
|
||||||
if (TSDB_CODE_SUCCESS != code) { \
|
if (TSDB_CODE_SUCCESS != code) { \
|
||||||
printf("%s : %d\n", __FUNCTION__, __LINE__); \
|
printf("%s : %d\n", __FUNCTION__, __LINE__); \
|
||||||
pCxt->errCode = code; \
|
pCxt->errCode = code; \
|
||||||
return res; \
|
return (res); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -83,14 +83,30 @@ static EDealRes doRewriteExpr(SNode** pNode, void* pContext) {
|
||||||
return DEAL_RES_CONTINUE;
|
return DEAL_RES_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t rewriteExpr(int32_t planNodeId, int32_t rewriteId, SNodeList* pExprs, SSelectStmt* pSelect, ESqlClause clause) {
|
typedef struct SNameExprCxt {
|
||||||
SNode* pNode;
|
int32_t planNodeId;
|
||||||
FOREACH(pNode, pExprs) {
|
int32_t rewriteId;
|
||||||
if (QUERY_NODE_COLUMN == nodeType(pNode) || QUERY_NODE_VALUE == nodeType(pNode)) {
|
} SNameExprCxt;
|
||||||
continue;
|
|
||||||
|
static EDealRes doNameExpr(SNode* pNode, void* pContext) {
|
||||||
|
switch (nodeType(pNode)) {
|
||||||
|
case QUERY_NODE_OPERATOR:
|
||||||
|
case QUERY_NODE_LOGIC_CONDITION:
|
||||||
|
case QUERY_NODE_FUNCTION: {
|
||||||
|
SNameExprCxt* pCxt = (SNameExprCxt*)pContext;
|
||||||
|
sprintf(((SExprNode*)pNode)->aliasName, "#expr_%d_%d", pCxt->planNodeId, pCxt->rewriteId++);
|
||||||
|
return DEAL_RES_IGNORE_CHILD;
|
||||||
}
|
}
|
||||||
sprintf(((SExprNode*)pNode)->aliasName, "#expr_%d_%d", planNodeId, rewriteId);
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return DEAL_RES_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t rewriteExpr(int32_t planNodeId, int32_t rewriteId, SNodeList* pExprs, SSelectStmt* pSelect, ESqlClause clause) {
|
||||||
|
SNameExprCxt nameCxt = { .planNodeId = planNodeId, .rewriteId = rewriteId };
|
||||||
|
nodesWalkList(pExprs, doNameExpr, &nameCxt);
|
||||||
SRewriteExprCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pExprs = pExprs };
|
SRewriteExprCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pExprs = pExprs };
|
||||||
nodesRewriteSelectStmt(pSelect, clause, doRewriteExpr, &cxt);
|
nodesRewriteSelectStmt(pSelect, clause, doRewriteExpr, &cxt);
|
||||||
return cxt.errCode;
|
return cxt.errCode;
|
||||||
|
@ -135,12 +151,16 @@ static SLogicNode* createScanLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect,
|
||||||
// set columns to scan
|
// set columns to scan
|
||||||
SNodeList* pCols = NULL;
|
SNodeList* pCols = NULL;
|
||||||
CHECK_CODE(nodesCollectColumns(pSelect, SQL_CLAUSE_FROM, pRealTable->table.tableAlias, &pCols), (SLogicNode*)pScan);
|
CHECK_CODE(nodesCollectColumns(pSelect, SQL_CLAUSE_FROM, pRealTable->table.tableAlias, &pCols), (SLogicNode*)pScan);
|
||||||
pScan->pScanCols = nodesCloneList(pCols);
|
if (NULL != pCols) {
|
||||||
CHECK_ALLOC(pScan->pScanCols, (SLogicNode*)pScan);
|
pScan->pScanCols = nodesCloneList(pCols);
|
||||||
|
CHECK_ALLOC(pScan->pScanCols, (SLogicNode*)pScan);
|
||||||
|
}
|
||||||
|
|
||||||
// set output
|
// set output
|
||||||
pScan->node.pTargets = nodesCloneList(pCols);
|
if (NULL != pCols) {
|
||||||
CHECK_ALLOC(pScan->node.pTargets, (SLogicNode*)pScan);
|
pScan->node.pTargets = nodesCloneList(pCols);
|
||||||
|
CHECK_ALLOC(pScan->node.pTargets, (SLogicNode*)pScan);
|
||||||
|
}
|
||||||
|
|
||||||
return (SLogicNode*)pScan;
|
return (SLogicNode*)pScan;
|
||||||
}
|
}
|
||||||
|
@ -173,8 +193,10 @@ static SLogicNode* createJoinLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect,
|
||||||
CHECK_CODE(nodesListAppend(pJoin->node.pChildren, (SNode*)pRight), (SLogicNode*)pJoin);
|
CHECK_CODE(nodesListAppend(pJoin->node.pChildren, (SNode*)pRight), (SLogicNode*)pJoin);
|
||||||
|
|
||||||
// set on conditions
|
// set on conditions
|
||||||
pJoin->pOnConditions = nodesCloneNode(pJoinTable->pOnCond);
|
if (NULL != pJoinTable->pOnCond) {
|
||||||
CHECK_ALLOC(pJoin->pOnConditions, (SLogicNode*)pJoin);
|
pJoin->pOnConditions = nodesCloneNode(pJoinTable->pOnCond);
|
||||||
|
CHECK_ALLOC(pJoin->pOnConditions, (SLogicNode*)pJoin);
|
||||||
|
}
|
||||||
|
|
||||||
// set the output
|
// set the output
|
||||||
pJoin->node.pTargets = nodesCloneList(pLeft->pTargets);
|
pJoin->node.pTargets = nodesCloneList(pLeft->pTargets);
|
||||||
|
@ -220,35 +242,57 @@ static SLogicNode* createWhereFilterLogicNode(SPlanContext* pCxt, SLogicNode* pC
|
||||||
return (SLogicNode*)pFilter;
|
return (SLogicNode*)pFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SNodeList* createColumnByRewriteExps(SPlanContext* pCxt, SNodeList* pExprs) {
|
typedef struct SCreateColumnCxt {
|
||||||
SNodeList* pList = nodesMakeList();
|
int32_t errCode;
|
||||||
CHECK_ALLOC(pList, NULL);
|
SNodeList* pList;
|
||||||
SNode* pNode;
|
} SCreateColumnCxt;
|
||||||
FOREACH(pNode, pExprs) {
|
|
||||||
if (QUERY_NODE_VALUE == nodeType(pNode)) {
|
static EDealRes doCreateColumn(SNode* pNode, void* pContext) {
|
||||||
continue;
|
SCreateColumnCxt* pCxt = (SCreateColumnCxt*)pContext;
|
||||||
} else if (QUERY_NODE_COLUMN == nodeType(pNode)) {
|
switch (nodeType(pNode)) {
|
||||||
|
case QUERY_NODE_COLUMN: {
|
||||||
SNode* pCol = nodesCloneNode(pNode);
|
SNode* pCol = nodesCloneNode(pNode);
|
||||||
if (NULL == pCol) {
|
if (NULL == pCol || TSDB_CODE_SUCCESS != nodesListAppend(pCxt->pList, pCol)) {
|
||||||
goto error;
|
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
return DEAL_RES_ERROR;
|
||||||
}
|
}
|
||||||
if (TSDB_CODE_SUCCESS != nodesListAppend(pList, pCol)) {
|
return DEAL_RES_IGNORE_CHILD;
|
||||||
goto error;
|
}
|
||||||
}
|
case QUERY_NODE_OPERATOR:
|
||||||
} else {
|
case QUERY_NODE_LOGIC_CONDITION:
|
||||||
|
case QUERY_NODE_FUNCTION: {
|
||||||
SExprNode* pExpr = (SExprNode*)pNode;
|
SExprNode* pExpr = (SExprNode*)pNode;
|
||||||
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
|
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
|
||||||
if (NULL == pCol) {
|
if (NULL == pCol) {
|
||||||
goto error;
|
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
return DEAL_RES_ERROR;
|
||||||
}
|
}
|
||||||
pCol->node.resType = pExpr->resType;
|
pCol->node.resType = pExpr->resType;
|
||||||
strcpy(pCol->colName, pExpr->aliasName);
|
strcpy(pCol->colName, pExpr->aliasName);
|
||||||
|
if (TSDB_CODE_SUCCESS != nodesListAppend(pCxt->pList, (SNode*)pCol)) {
|
||||||
|
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
return DEAL_RES_ERROR;
|
||||||
|
}
|
||||||
|
return DEAL_RES_IGNORE_CHILD;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return pList;
|
|
||||||
error:
|
return DEAL_RES_CONTINUE;
|
||||||
nodesDestroyList(pList);
|
}
|
||||||
return NULL;
|
|
||||||
|
static SNodeList* createColumnByRewriteExps(SPlanContext* pCxt, SNodeList* pExprs) {
|
||||||
|
SCreateColumnCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pList = nodesMakeList() };
|
||||||
|
if (NULL == cxt.pList) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
nodesWalkList(pExprs, doCreateColumn, &cxt);
|
||||||
|
if (TSDB_CODE_SUCCESS != cxt.errCode) {
|
||||||
|
nodesDestroyList(cxt.pList);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return cxt.pList;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SLogicNode* createAggLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) {
|
static SLogicNode* createAggLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) {
|
||||||
|
@ -263,24 +307,37 @@ static SLogicNode* createAggLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect)
|
||||||
pAgg->node.id = pCxt->planNodeId++;
|
pAgg->node.id = pCxt->planNodeId++;
|
||||||
|
|
||||||
// set grouyp keys, agg funcs and having conditions
|
// set grouyp keys, agg funcs and having conditions
|
||||||
pAgg->pGroupKeys = nodesCloneList(pSelect->pGroupByList);
|
if (NULL != pSelect->pGroupByList) {
|
||||||
CHECK_ALLOC(pAgg->pGroupKeys, (SLogicNode*)pAgg);
|
pAgg->pGroupKeys = nodesCloneList(pSelect->pGroupByList);
|
||||||
pAgg->pAggFuncs = nodesCloneList(pAggFuncs);
|
CHECK_ALLOC(pAgg->pGroupKeys, (SLogicNode*)pAgg);
|
||||||
CHECK_ALLOC(pAgg->pAggFuncs, (SLogicNode*)pAgg);
|
}
|
||||||
|
if (NULL != pAggFuncs) {
|
||||||
|
pAgg->pAggFuncs = nodesCloneList(pAggFuncs);
|
||||||
|
CHECK_ALLOC(pAgg->pAggFuncs, (SLogicNode*)pAgg);
|
||||||
|
}
|
||||||
|
|
||||||
// rewrite the expression in subsequent clauses
|
// rewrite the expression in subsequent clauses
|
||||||
CHECK_CODE(rewriteExpr(pAgg->node.id, 1, pAgg->pGroupKeys, pSelect, SQL_CLAUSE_GROUP_BY), (SLogicNode*)pAgg);
|
CHECK_CODE(rewriteExpr(pAgg->node.id, 1, pAgg->pGroupKeys, pSelect, SQL_CLAUSE_GROUP_BY), (SLogicNode*)pAgg);
|
||||||
CHECK_CODE(rewriteExpr(pAgg->node.id, 1 + LIST_LENGTH(pAgg->pGroupKeys), pAgg->pAggFuncs, pSelect, SQL_CLAUSE_GROUP_BY), (SLogicNode*)pAgg);
|
CHECK_CODE(rewriteExpr(pAgg->node.id, 1 + LIST_LENGTH(pAgg->pGroupKeys), pAgg->pAggFuncs, pSelect, SQL_CLAUSE_GROUP_BY), (SLogicNode*)pAgg);
|
||||||
|
|
||||||
pAgg->node.pConditions = nodesCloneNode(pSelect->pHaving);
|
if (NULL != pSelect->pHaving) {
|
||||||
CHECK_ALLOC(pAgg->node.pConditions, (SLogicNode*)pAgg);
|
pAgg->node.pConditions = nodesCloneNode(pSelect->pHaving);
|
||||||
|
CHECK_ALLOC(pAgg->node.pConditions, (SLogicNode*)pAgg);
|
||||||
|
}
|
||||||
|
|
||||||
// set the output
|
// set the output
|
||||||
pAgg->node.pTargets = createColumnByRewriteExps(pCxt, pAgg->pGroupKeys);
|
pAgg->node.pTargets = nodesMakeList();
|
||||||
CHECK_ALLOC(pAgg->node.pTargets, (SLogicNode*)pAgg);
|
CHECK_ALLOC(pAgg->node.pTargets, (SLogicNode*)pAgg);
|
||||||
SNodeList* pTargets = createColumnByRewriteExps(pCxt, pAgg->pAggFuncs);
|
if (NULL != pAgg->pGroupKeys) {
|
||||||
CHECK_ALLOC(pTargets, (SLogicNode*)pAgg);
|
SNodeList* pTargets = createColumnByRewriteExps(pCxt, pAgg->pGroupKeys);
|
||||||
nodesListAppendList(pAgg->node.pTargets, pTargets);
|
CHECK_ALLOC(pAgg->node.pTargets, (SLogicNode*)pAgg);
|
||||||
|
nodesListAppendList(pAgg->node.pTargets, pTargets);
|
||||||
|
}
|
||||||
|
if (NULL != pAgg->pAggFuncs) {
|
||||||
|
SNodeList* pTargets = createColumnByRewriteExps(pCxt, pAgg->pAggFuncs);
|
||||||
|
CHECK_ALLOC(pTargets, (SLogicNode*)pAgg);
|
||||||
|
nodesListAppendList(pAgg->node.pTargets, pTargets);
|
||||||
|
}
|
||||||
|
|
||||||
return (SLogicNode*)pAgg;
|
return (SLogicNode*)pAgg;
|
||||||
}
|
}
|
||||||
|
@ -344,7 +401,7 @@ static SLogicNode* createQueryLogicNode(SPlanContext* pCxt, SNode* pStmt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t createLogicPlan(SNode* pNode, SLogicNode** pLogicNode) {
|
int32_t createLogicPlan(SNode* pNode, SLogicNode** pLogicNode) {
|
||||||
SPlanContext cxt = { .errCode = TSDB_CODE_SUCCESS, .planNodeId = 0 };
|
SPlanContext cxt = { .errCode = TSDB_CODE_SUCCESS, .planNodeId = 1 };
|
||||||
SLogicNode* pRoot = createQueryLogicNode(&cxt, pNode);
|
SLogicNode* pRoot = createQueryLogicNode(&cxt, pNode);
|
||||||
if (TSDB_CODE_SUCCESS != cxt.errCode) {
|
if (TSDB_CODE_SUCCESS != cxt.errCode) {
|
||||||
nodesDestroyNode((SNode*)pRoot);
|
nodesDestroyNode((SNode*)pRoot);
|
||||||
|
|
|
@ -42,26 +42,28 @@ protected:
|
||||||
|
|
||||||
bool run() {
|
bool run() {
|
||||||
int32_t code = parser(&cxt_, &query_);
|
int32_t code = parser(&cxt_, &query_);
|
||||||
// cout << "parser return " << code << endl;
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
cout << "sql:[" << cxt_.pSql << "] parser code:" << tstrerror(code) << ", msg:" << errMagBuf_ << endl;
|
cout << "sql:[" << cxt_.pSql << "] parser code:" << code << ", strerror:" << tstrerror(code) << ", msg:" << errMagBuf_ << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const string syntaxTreeStr = toString(query_.pRoot, false);
|
||||||
|
|
||||||
SLogicNode* pLogicPlan = nullptr;
|
SLogicNode* pLogicPlan = nullptr;
|
||||||
code = createLogicPlan(query_.pRoot, &pLogicPlan);
|
code = createLogicPlan(query_.pRoot, &pLogicPlan);
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
cout << "sql:[" << cxt_.pSql << "] plan code:" << tstrerror(code) << endl;
|
cout << "sql:[" << cxt_.pSql << "] plan code:" << code << ", strerror:" << tstrerror(code) << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
char* pStr = NULL;
|
|
||||||
int32_t len = 0;
|
cout << "sql : [" << cxt_.pSql << "]" << endl;
|
||||||
code = nodesNodeToString((const SNode*)pLogicPlan, &pStr, &len);
|
cout << "syntax test : " << endl;
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
cout << syntaxTreeStr << endl;
|
||||||
cout << "sql:[" << cxt_.pSql << "] toString code:" << tstrerror(code) << endl;
|
// cout << "logic plan : " << endl;
|
||||||
return false;
|
// cout << toString((const SNode*)pLogicPlan) << endl;
|
||||||
}
|
cout << "unformatted logic plan : " << endl;
|
||||||
cout << "logic plan : " << endl;
|
cout << toString((const SNode*)pLogicPlan, false) << endl;
|
||||||
cout << pStr << endl;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +77,19 @@ private:
|
||||||
cxt_.msgLen = max_err_len;
|
cxt_.msgLen = max_err_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string toString(const SNode* pRoot, bool format = true) {
|
||||||
|
char* pStr = NULL;
|
||||||
|
int32_t len = 0;
|
||||||
|
int32_t code = nodesNodeToString(pRoot, format, &pStr, &len);
|
||||||
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
|
cout << "sql:[" << cxt_.pSql << "] toString code:" << code << ", strerror:" << tstrerror(code) << endl;
|
||||||
|
return string();
|
||||||
|
}
|
||||||
|
string str(pStr);
|
||||||
|
tfree(pStr);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
string acctId_;
|
string acctId_;
|
||||||
string db_;
|
string db_;
|
||||||
char errMagBuf_[max_err_len];
|
char errMagBuf_[max_err_len];
|
||||||
|
@ -89,3 +104,19 @@ TEST_F(NewPlannerTest, simple) {
|
||||||
bind("SELECT * FROM t1");
|
bind("SELECT * FROM t1");
|
||||||
ASSERT_TRUE(run());
|
ASSERT_TRUE(run());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(NewPlannerTest, groupBy) {
|
||||||
|
setDatabase("root", "test");
|
||||||
|
|
||||||
|
bind("SELECT count(*) FROM t1");
|
||||||
|
ASSERT_TRUE(run());
|
||||||
|
|
||||||
|
bind("SELECT c1, count(*) FROM t1 GROUP BY c1");
|
||||||
|
ASSERT_TRUE(run());
|
||||||
|
|
||||||
|
bind("SELECT c1 + c3, c1 + count(*) FROM t1 where c2 = 'abc' GROUP BY c1, c3");
|
||||||
|
ASSERT_TRUE(run());
|
||||||
|
|
||||||
|
bind("SELECT c1 + c3, count(*) FROM t1 where concat(c2, 'wwww') = 'abcwww' GROUP BY c1 + c3");
|
||||||
|
ASSERT_TRUE(run());
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
aux_source_directory(src SCALAR_SRC)
|
||||||
|
|
||||||
|
add_library(scalar STATIC ${SCALAR_SRC})
|
||||||
|
target_include_directories(
|
||||||
|
scalar
|
||||||
|
PUBLIC "${CMAKE_SOURCE_DIR}/include/libs/scalar"
|
||||||
|
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/inc"
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(scalar
|
||||||
|
PRIVATE os util common nodes function qcom
|
||||||
|
)
|
||||||
|
|
||||||
|
if(${BUILD_TEST})
|
||||||
|
ADD_SUBDIRECTORY(test)
|
||||||
|
endif(${BUILD_TEST})
|
|
@ -13,8 +13,8 @@
|
||||||
* 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 TDENGINE_QFILTER_H
|
#ifndef TDENGINE_FILTER_INT_H
|
||||||
#define TDENGINE_QFILTER_H
|
#define TDENGINE_FILTER_INT_H
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -22,7 +22,10 @@ extern "C" {
|
||||||
|
|
||||||
#include "thash.h"
|
#include "thash.h"
|
||||||
#include "tname.h"
|
#include "tname.h"
|
||||||
#include "function.h"
|
#include "common.h"
|
||||||
|
#include "scalar.h"
|
||||||
|
#include "querynodes.h"
|
||||||
|
#include "query.h"
|
||||||
|
|
||||||
#define FILTER_DEFAULT_GROUP_SIZE 4
|
#define FILTER_DEFAULT_GROUP_SIZE 4
|
||||||
#define FILTER_DEFAULT_UNIT_SIZE 4
|
#define FILTER_DEFAULT_UNIT_SIZE 4
|
||||||
|
@ -83,6 +86,12 @@ enum {
|
||||||
RANGE_TYPE_MR_CTX = 3,
|
RANGE_TYPE_MR_CTX = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
FI_ACTION_NO_NEED = 1,
|
||||||
|
FI_ACTION_CONTINUE,
|
||||||
|
FI_ACTION_STOP,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct OptrStr {
|
typedef struct OptrStr {
|
||||||
uint16_t optr;
|
uint16_t optr;
|
||||||
char *str;
|
char *str;
|
||||||
|
@ -95,17 +104,11 @@ typedef struct SFilterRange {
|
||||||
char eflag;
|
char eflag;
|
||||||
} SFilterRange;
|
} SFilterRange;
|
||||||
|
|
||||||
typedef struct SFilterColRange {
|
|
||||||
uint16_t idx; //column field idx
|
|
||||||
bool isNull;
|
|
||||||
bool notNull;
|
|
||||||
bool isRange;
|
|
||||||
SFilterRange ra;
|
|
||||||
} SFilterColRange;
|
|
||||||
|
|
||||||
typedef bool (*rangeCompFunc) (const void *, const void *, const void *, const void *, __compar_fn_t);
|
typedef bool (*rangeCompFunc) (const void *, const void *, const void *, const void *, __compar_fn_t);
|
||||||
typedef int32_t(*filter_desc_compare_func)(const void *, const void *);
|
typedef int32_t(*filter_desc_compare_func)(const void *, const void *);
|
||||||
typedef bool(*filter_exec_func)(void *, int32_t, int8_t**, SColumnDataAgg *, int16_t);
|
typedef bool(*filter_exec_func)(void *, int32_t, int8_t**, SColumnDataAgg *, int16_t);
|
||||||
|
typedef int32_t (*filer_get_col_from_id)(void *, int32_t, void **);
|
||||||
|
typedef int32_t (*filer_get_col_from_name)(void *, int32_t, char*, void **);
|
||||||
|
|
||||||
typedef struct SFilterRangeCompare {
|
typedef struct SFilterRangeCompare {
|
||||||
int64_t s;
|
int64_t s;
|
||||||
|
@ -153,37 +156,39 @@ typedef struct SFilterField {
|
||||||
} SFilterField;
|
} SFilterField;
|
||||||
|
|
||||||
typedef struct SFilterFields {
|
typedef struct SFilterFields {
|
||||||
uint16_t size;
|
uint32_t size;
|
||||||
uint16_t num;
|
uint32_t num;
|
||||||
SFilterField *fields;
|
SFilterField *fields;
|
||||||
} SFilterFields;
|
} SFilterFields;
|
||||||
|
|
||||||
typedef struct SFilterFieldId {
|
typedef struct SFilterFieldId {
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
uint16_t idx;
|
uint32_t idx;
|
||||||
} SFilterFieldId;
|
} SFilterFieldId;
|
||||||
|
|
||||||
typedef struct SFilterGroup {
|
typedef struct SFilterGroup {
|
||||||
uint16_t unitSize;
|
uint32_t unitSize;
|
||||||
uint16_t unitNum;
|
uint32_t unitNum;
|
||||||
uint16_t *unitIdxs;
|
uint32_t *unitIdxs;
|
||||||
uint8_t *unitFlags; // !unit result
|
uint8_t *unitFlags; // !unit result
|
||||||
} SFilterGroup;
|
} SFilterGroup;
|
||||||
|
|
||||||
typedef struct SFilterColInfo {
|
typedef struct SFilterColInfo {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
int32_t dataType;
|
int32_t dataType;
|
||||||
|
uint8_t optr; // for equal operation in the relation of RELATION_IN
|
||||||
|
int64_t value; // for equal operation in the relation of RELATION_IN
|
||||||
void *info;
|
void *info;
|
||||||
} SFilterColInfo;
|
} SFilterColInfo;
|
||||||
|
|
||||||
typedef struct SFilterGroupCtx {
|
typedef struct SFilterGroupCtx {
|
||||||
uint16_t colNum;
|
uint32_t colNum;
|
||||||
uint16_t *colIdx;
|
uint32_t *colIdx;
|
||||||
SFilterColInfo *colInfo;
|
SFilterColInfo *colInfo;
|
||||||
} SFilterGroupCtx;
|
} SFilterGroupCtx;
|
||||||
|
|
||||||
typedef struct SFilterColCtx {
|
typedef struct SFilterColCtx {
|
||||||
uint16_t colIdx;
|
uint32_t colIdx;
|
||||||
void* ctx;
|
void* ctx;
|
||||||
} SFilterColCtx;
|
} SFilterColCtx;
|
||||||
|
|
||||||
|
@ -217,16 +222,32 @@ typedef struct SFilterPCtx {
|
||||||
SHashObj *unitHash;
|
SHashObj *unitHash;
|
||||||
} SFilterPCtx;
|
} SFilterPCtx;
|
||||||
|
|
||||||
|
typedef struct SFltTreeStat {
|
||||||
|
int32_t code;
|
||||||
|
bool scalarMode;
|
||||||
|
} SFltTreeStat;
|
||||||
|
|
||||||
|
typedef struct SFltScalarCtx {
|
||||||
|
SNode *node;
|
||||||
|
} SFltScalarCtx;
|
||||||
|
|
||||||
|
typedef struct SFltBuildGroupCtx {
|
||||||
|
SFilterInfo *info;
|
||||||
|
SArray *group;
|
||||||
|
int32_t code;
|
||||||
|
} SFltBuildGroupCtx;
|
||||||
|
|
||||||
typedef struct SFilterInfo {
|
typedef struct SFilterInfo {
|
||||||
|
bool scalarMode;
|
||||||
|
SFltScalarCtx sclCtx;
|
||||||
uint32_t options;
|
uint32_t options;
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
uint16_t unitSize;
|
uint32_t unitSize;
|
||||||
uint16_t unitNum;
|
uint32_t unitNum;
|
||||||
uint16_t groupNum;
|
uint32_t groupNum;
|
||||||
uint16_t colRangeNum;
|
uint32_t colRangeNum;
|
||||||
SFilterFields fields[FLD_TYPE_MAX];
|
SFilterFields fields[FLD_TYPE_MAX];
|
||||||
SFilterGroup *groups;
|
SFilterGroup *groups;
|
||||||
uint16_t *cgroups;
|
|
||||||
SFilterUnit *units;
|
SFilterUnit *units;
|
||||||
SFilterComUnit *cunits;
|
SFilterComUnit *cunits;
|
||||||
uint8_t *unitRes; // result
|
uint8_t *unitRes; // result
|
||||||
|
@ -234,16 +255,15 @@ typedef struct SFilterInfo {
|
||||||
SFilterRangeCtx **colRange;
|
SFilterRangeCtx **colRange;
|
||||||
filter_exec_func func;
|
filter_exec_func func;
|
||||||
uint8_t blkFlag;
|
uint8_t blkFlag;
|
||||||
uint16_t blkGroupNum;
|
uint32_t blkGroupNum;
|
||||||
uint16_t *blkUnits;
|
uint32_t *blkUnits;
|
||||||
int8_t *blkUnitRes;
|
int8_t *blkUnitRes;
|
||||||
|
void *pTable;
|
||||||
|
|
||||||
SFilterPCtx pctx;
|
SFilterPCtx pctx;
|
||||||
} SFilterInfo;
|
} SFilterInfo;
|
||||||
|
|
||||||
#define COL_FIELD_SIZE (sizeof(SFilterField) + 2 * sizeof(int64_t))
|
#define FILTER_NO_MERGE_DATA_TYPE(t) ((t) == TSDB_DATA_TYPE_BINARY || (t) == TSDB_DATA_TYPE_NCHAR || (t) == TSDB_DATA_TYPE_JSON)
|
||||||
|
|
||||||
#define FILTER_NO_MERGE_DATA_TYPE(t) ((t) == TSDB_DATA_TYPE_BINARY || (t) == TSDB_DATA_TYPE_NCHAR)
|
|
||||||
#define FILTER_NO_MERGE_OPTR(o) ((o) == TSDB_RELATION_ISNULL || (o) == TSDB_RELATION_NOTNULL || (o) == FILTER_DUMMY_EMPTY_OPTR)
|
#define FILTER_NO_MERGE_OPTR(o) ((o) == TSDB_RELATION_ISNULL || (o) == TSDB_RELATION_NOTNULL || (o) == FILTER_DUMMY_EMPTY_OPTR)
|
||||||
|
|
||||||
#define MR_EMPTY_RES(ctx) (ctx->rs == NULL)
|
#define MR_EMPTY_RES(ctx) (ctx->rs == NULL)
|
||||||
|
@ -259,7 +279,7 @@ typedef struct SFilterInfo {
|
||||||
#define FILTER_CLR_FLAG(st, f) st &= (~f)
|
#define FILTER_CLR_FLAG(st, f) st &= (~f)
|
||||||
|
|
||||||
#define SIMPLE_COPY_VALUES(dst, src) *((int64_t *)dst) = *((int64_t *)src)
|
#define SIMPLE_COPY_VALUES(dst, src) *((int64_t *)dst) = *((int64_t *)src)
|
||||||
#define FILTER_PACKAGE_UNIT_HASH_KEY(v, optr, idx1, idx2) do { char *_t = (char *)v; _t[0] = optr; *(uint16_t *)(_t + 1) = idx1; *(uint16_t *)(_t + 3) = idx2; } while (0)
|
#define FILTER_PACKAGE_UNIT_HASH_KEY(v, optr, idx1, idx2) do { char *_t = (char *)v; _t[0] = optr; *(uint32_t *)(_t + 1) = idx1; *(uint32_t *)(_t + 3) = idx2; } while (0)
|
||||||
#define FILTER_GREATER(cr,sflag,eflag) ((cr > 0) || ((cr == 0) && (FILTER_GET_FLAG(sflag,RANGE_FLG_EXCLUDE) || FILTER_GET_FLAG(eflag,RANGE_FLG_EXCLUDE))))
|
#define FILTER_GREATER(cr,sflag,eflag) ((cr > 0) || ((cr == 0) && (FILTER_GET_FLAG(sflag,RANGE_FLG_EXCLUDE) || FILTER_GET_FLAG(eflag,RANGE_FLG_EXCLUDE))))
|
||||||
#define FILTER_COPY_RA(dst, src) do { (dst)->sflag = (src)->sflag; (dst)->eflag = (src)->eflag; (dst)->s = (src)->s; (dst)->e = (src)->e; } while (0)
|
#define FILTER_COPY_RA(dst, src) do { (dst)->sflag = (src)->sflag; (dst)->eflag = (src)->eflag; (dst)->s = (src)->s; (dst)->e = (src)->e; } while (0)
|
||||||
|
|
||||||
|
@ -269,25 +289,33 @@ typedef struct SFilterInfo {
|
||||||
#define INSERT_RANGE(ctx, r, ra) do { SFilterRangeNode *n = filterNewRange(ctx, ra); n->prev = (r)->prev; if ((r)->prev) { (r)->prev->next = n; } else { (ctx)->rs = n; } (r)->prev = n; n->next = r; } while (0)
|
#define INSERT_RANGE(ctx, r, ra) do { SFilterRangeNode *n = filterNewRange(ctx, ra); n->prev = (r)->prev; if ((r)->prev) { (r)->prev->next = n; } else { (ctx)->rs = n; } (r)->prev = n; n->next = r; } while (0)
|
||||||
#define APPEND_RANGE(ctx, r, ra) do { SFilterRangeNode *n = filterNewRange(ctx, ra); n->prev = (r); if (r) { (r)->next = n; } else { (ctx)->rs = n; } } while (0)
|
#define APPEND_RANGE(ctx, r, ra) do { SFilterRangeNode *n = filterNewRange(ctx, ra); n->prev = (r); if (r) { (r)->next = n; } else { (ctx)->rs = n; } } while (0)
|
||||||
|
|
||||||
#define ERR_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { return _code; } } while (0)
|
#define FLT_IS_COMPARISON_OPERATOR(_op) ((_op) >= OP_TYPE_GREATER_THAN && (_op) < OP_TYPE_IS_NOT_NULL)
|
||||||
#define ERR_LRET(c,...) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { qError(__VA_ARGS__); return _code; } } while (0)
|
|
||||||
#define ERR_JRET(c) do { code = c; if (code != TSDB_CODE_SUCCESS) { goto _return; } } while (0)
|
#define fltFatal(...) qFatal(__VA_ARGS__)
|
||||||
|
#define fltError(...) qError(__VA_ARGS__)
|
||||||
|
#define fltWarn(...) qWarn(__VA_ARGS__)
|
||||||
|
#define fltInfo(...) qInfo(__VA_ARGS__)
|
||||||
|
#define fltDebug(...) qDebug(__VA_ARGS__)
|
||||||
|
#define fltTrace(...) qTrace(__VA_ARGS__)
|
||||||
|
|
||||||
|
|
||||||
|
#define FLT_CHK_JMP(c) do { if (c) { goto _return; } } while (0)
|
||||||
|
#define FLT_ERR_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { terrno = _code; return _code; } } while (0)
|
||||||
|
#define FLT_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { terrno = _code; } return _code; } while (0)
|
||||||
|
#define FLT_ERR_JRET(c) do { code = c; if (code != TSDB_CODE_SUCCESS) { terrno = code; goto _return; } } while (0)
|
||||||
|
|
||||||
#define CHK_RETV(c) do { if (c) { return; } } while (0)
|
|
||||||
#define CHK_RET(c, r) do { if (c) { return r; } } while (0)
|
|
||||||
#define CHK_JMP(c) do { if (c) { goto _return; } } while (0)
|
|
||||||
#define CHK_LRETV(c,...) do { if (c) { qError(__VA_ARGS__); return; } } while (0)
|
|
||||||
#define CHK_LRET(c, r,...) do { if (c) { if (r) {qError(__VA_ARGS__); } else { qDebug(__VA_ARGS__); } return r; } } while (0)
|
|
||||||
|
|
||||||
#define FILTER_GET_FIELD(i, id) (&((i)->fields[(id).type].fields[(id).idx]))
|
#define FILTER_GET_FIELD(i, id) (&((i)->fields[(id).type].fields[(id).idx]))
|
||||||
#define FILTER_GET_COL_FIELD(i, idx) (&((i)->fields[FLD_TYPE_COLUMN].fields[idx]))
|
#define FILTER_GET_COL_FIELD(i, idx) (&((i)->fields[FLD_TYPE_COLUMN].fields[idx]))
|
||||||
#define FILTER_GET_COL_FIELD_TYPE(fi) (((SSchema *)((fi)->desc))->type)
|
#define FILTER_GET_COL_FIELD_TYPE(fi) (((SColumnRefNode *)((fi)->desc))->dataType.type)
|
||||||
#define FILTER_GET_COL_FIELD_SIZE(fi) (((SSchema *)((fi)->desc))->bytes)
|
#define FILTER_GET_COL_FIELD_SIZE(fi) (((SColumnRefNode *)((fi)->desc))->dataType.bytes)
|
||||||
#define FILTER_GET_COL_FIELD_ID(fi) (((SSchema *)((fi)->desc))->colId)
|
#define FILTER_GET_COL_FIELD_ID(fi) (((SColumnRefNode *)((fi)->desc))->columnId)
|
||||||
#define FILTER_GET_COL_FIELD_DESC(fi) ((SSchema *)((fi)->desc))
|
#define FILTER_GET_COL_FIELD_SLOT_ID(fi) (((SColumnRefNode *)((fi)->desc))->slotId)
|
||||||
#define FILTER_GET_COL_FIELD_DATA(fi, ri) ((char *)(fi)->data + ((SSchema *)((fi)->desc))->bytes * (ri))
|
#define FILTER_GET_COL_FIELD_DESC(fi) ((SColumnRefNode *)((fi)->desc))
|
||||||
#define FILTER_GET_VAL_FIELD_TYPE(fi) (((tVariant *)((fi)->desc))->nType)
|
#define FILTER_GET_COL_FIELD_DATA(fi, ri) ((char *)(fi)->data + ((SColumnRefNode *)((fi)->desc))->dataType.bytes * (ri))
|
||||||
|
#define FILTER_GET_VAL_FIELD_TYPE(fi) (((SValueNode *)((fi)->desc))->node.resType.type)
|
||||||
#define FILTER_GET_VAL_FIELD_DATA(fi) ((char *)(fi)->data)
|
#define FILTER_GET_VAL_FIELD_DATA(fi) ((char *)(fi)->data)
|
||||||
|
#define FILTER_GET_JSON_VAL_FIELD_DATA(fi) ((char *)(fi)->desc)
|
||||||
#define FILTER_GET_TYPE(fl) ((fl) & FLD_TYPE_MAX)
|
#define FILTER_GET_TYPE(fl) ((fl) & FLD_TYPE_MAX)
|
||||||
|
|
||||||
#define FILTER_GROUP_UNIT(i, g, uid) ((i)->units + (g)->unitIdxs[uid])
|
#define FILTER_GROUP_UNIT(i, g, uid) ((i)->units + (g)->unitIdxs[uid])
|
||||||
|
@ -300,6 +328,7 @@ typedef struct SFilterInfo {
|
||||||
#define FILTER_UNIT_COL_SIZE(i, u) FILTER_GET_COL_FIELD_SIZE(FILTER_UNIT_LEFT_FIELD(i, u))
|
#define FILTER_UNIT_COL_SIZE(i, u) FILTER_GET_COL_FIELD_SIZE(FILTER_UNIT_LEFT_FIELD(i, u))
|
||||||
#define FILTER_UNIT_COL_ID(i, u) FILTER_GET_COL_FIELD_ID(FILTER_UNIT_LEFT_FIELD(i, u))
|
#define FILTER_UNIT_COL_ID(i, u) FILTER_GET_COL_FIELD_ID(FILTER_UNIT_LEFT_FIELD(i, u))
|
||||||
#define FILTER_UNIT_VAL_DATA(i, u) FILTER_GET_VAL_FIELD_DATA(FILTER_UNIT_RIGHT_FIELD(i, u))
|
#define FILTER_UNIT_VAL_DATA(i, u) FILTER_GET_VAL_FIELD_DATA(FILTER_UNIT_RIGHT_FIELD(i, u))
|
||||||
|
#define FILTER_UNIT_JSON_VAL_DATA(i, u) FILTER_GET_JSON_VAL_FIELD_DATA(FILTER_UNIT_RIGHT_FIELD(i, u))
|
||||||
#define FILTER_UNIT_COL_IDX(u) ((u)->left.idx)
|
#define FILTER_UNIT_COL_IDX(u) ((u)->left.idx)
|
||||||
#define FILTER_UNIT_OPTR(u) ((u)->compare.optr)
|
#define FILTER_UNIT_OPTR(u) ((u)->compare.optr)
|
||||||
#define FILTER_UNIT_COMP_FUNC(u) ((u)->compare.func)
|
#define FILTER_UNIT_COMP_FUNC(u) ((u)->compare.func)
|
||||||
|
@ -314,7 +343,7 @@ typedef struct SFilterInfo {
|
||||||
#define FILTER_PUSH_VAR_HASH(colInfo, ha) do { (colInfo).type = RANGE_TYPE_VAR_HASH; (colInfo).info = ha;} while (0)
|
#define FILTER_PUSH_VAR_HASH(colInfo, ha) do { (colInfo).type = RANGE_TYPE_VAR_HASH; (colInfo).info = ha;} while (0)
|
||||||
#define FILTER_PUSH_CTX(colInfo, ctx) do { (colInfo).type = RANGE_TYPE_MR_CTX; (colInfo).info = ctx;} while (0)
|
#define FILTER_PUSH_CTX(colInfo, ctx) do { (colInfo).type = RANGE_TYPE_MR_CTX; (colInfo).info = ctx;} while (0)
|
||||||
|
|
||||||
#define FILTER_COPY_IDX(dst, src, n) do { *(dst) = malloc(sizeof(uint16_t) * n); memcpy(*(dst), src, sizeof(uint16_t) * n);} while (0)
|
#define FILTER_COPY_IDX(dst, src, n) do { *(dst) = malloc(sizeof(uint32_t) * n); memcpy(*(dst), src, sizeof(uint32_t) * n);} while (0)
|
||||||
|
|
||||||
#define FILTER_ADD_CTX_TO_GRES(gres, idx, ctx) do { if ((gres)->colCtxs == NULL) { (gres)->colCtxs = taosArrayInit(gres->colNum, sizeof(SFilterColCtx)); } SFilterColCtx cCtx = {idx, ctx}; taosArrayPush((gres)->colCtxs, &cCtx); } while (0)
|
#define FILTER_ADD_CTX_TO_GRES(gres, idx, ctx) do { if ((gres)->colCtxs == NULL) { (gres)->colCtxs = taosArrayInit(gres->colNum, sizeof(SFilterColCtx)); } SFilterColCtx cCtx = {idx, ctx}; taosArrayPush((gres)->colCtxs, &cCtx); } while (0)
|
||||||
|
|
||||||
|
@ -322,18 +351,25 @@ typedef struct SFilterInfo {
|
||||||
#define FILTER_ALL_RES(i) FILTER_GET_FLAG((i)->status, FI_STATUS_ALL)
|
#define FILTER_ALL_RES(i) FILTER_GET_FLAG((i)->status, FI_STATUS_ALL)
|
||||||
#define FILTER_EMPTY_RES(i) FILTER_GET_FLAG((i)->status, FI_STATUS_EMPTY)
|
#define FILTER_EMPTY_RES(i) FILTER_GET_FLAG((i)->status, FI_STATUS_EMPTY)
|
||||||
|
|
||||||
|
#if 0
|
||||||
extern int32_t filterInitFromTree(tExprNode* tree, SFilterInfo **pinfo, uint32_t options);
|
extern int32_t filterInitFromTree(tExprNode* tree, void **pinfo, uint32_t options);
|
||||||
extern bool filterExecute(SFilterInfo *info, int32_t numOfRows, int8_t** p, SColumnDataAgg *statis, int16_t numOfCols);
|
extern bool filterExecute(SFilterInfo *info, int32_t numOfRows, int8_t** p, SColumnDataAgg *statis, int16_t numOfCols);
|
||||||
extern int32_t filterSetColFieldData(SFilterInfo *info, int32_t numOfCols, SArray* pDataBlock);
|
extern int32_t filterSetColFieldData(SFilterInfo *info, void *param, filer_get_col_from_id fp);
|
||||||
|
extern int32_t filterSetJsonColFieldData(SFilterInfo *info, void *param, filer_get_col_from_name fp);
|
||||||
extern int32_t filterGetTimeRange(SFilterInfo *info, STimeWindow *win);
|
extern int32_t filterGetTimeRange(SFilterInfo *info, STimeWindow *win);
|
||||||
extern int32_t filterConverNcharColumns(SFilterInfo* pFilterInfo, int32_t rows, bool *gotNchar);
|
extern int32_t filterConverNcharColumns(SFilterInfo* pFilterInfo, int32_t rows, bool *gotNchar);
|
||||||
extern int32_t filterFreeNcharColumns(SFilterInfo* pFilterInfo);
|
extern int32_t filterFreeNcharColumns(SFilterInfo* pFilterInfo);
|
||||||
extern void filterFreeInfo(SFilterInfo *info);
|
extern void filterFreeInfo(SFilterInfo *info);
|
||||||
extern bool filterRangeExecute(SFilterInfo *info, SColumnDataAgg *pDataStatis, int32_t numOfCols, int32_t numOfRows);
|
extern bool filterRangeExecute(SFilterInfo *info, SColumnDataAgg *pDataStatis, int32_t numOfCols, int32_t numOfRows);
|
||||||
|
#else
|
||||||
|
//REMOVE THESE!!!!!!!!!!!!!!!!!!!!
|
||||||
|
#include "function.h"
|
||||||
|
#endif
|
||||||
|
extern bool filterDoCompare(__compar_fn_t func, uint8_t optr, void *left, void *right);
|
||||||
|
extern __compar_fn_t filterGetCompFunc(int32_t type, int32_t optr);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // TDENGINE_QFILTER_H
|
#endif // TDENGINE_FILTER_INT_H
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
#ifndef TDENGINE_SCALARINT_H
|
||||||
|
#define TDENGINE_SCALARINT_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#include "common.h"
|
||||||
|
#include "thash.h"
|
||||||
|
#include "query.h"
|
||||||
|
|
||||||
|
typedef struct SScalarCtx {
|
||||||
|
int32_t code;
|
||||||
|
SSDataBlock *pSrc;
|
||||||
|
SHashObj *pRes; /* element is SScalarParam */
|
||||||
|
} SScalarCtx;
|
||||||
|
|
||||||
|
#define SCL_DEFAULT_OP_NUM 10
|
||||||
|
|
||||||
|
#define sclFatal(...) qFatal(__VA_ARGS__)
|
||||||
|
#define sclError(...) qError(__VA_ARGS__)
|
||||||
|
#define sclWarn(...) qWarn(__VA_ARGS__)
|
||||||
|
#define sclInfo(...) qInfo(__VA_ARGS__)
|
||||||
|
#define sclDebug(...) qDebug(__VA_ARGS__)
|
||||||
|
#define sclTrace(...) qTrace(__VA_ARGS__)
|
||||||
|
|
||||||
|
#define SCL_ERR_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { terrno = _code; return _code; } } while (0)
|
||||||
|
#define SCL_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { terrno = _code; } return _code; } while (0)
|
||||||
|
#define SCL_ERR_JRET(c) do { code = c; if (code != TSDB_CODE_SUCCESS) { terrno = code; goto _return; } } while (0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // TDENGINE_SCALARINT_H
|
|
@ -20,13 +20,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "function.h"
|
#include "function.h"
|
||||||
|
#include "scalar.h"
|
||||||
typedef struct SScalarFuncParam {
|
|
||||||
void* data;
|
|
||||||
int32_t num;
|
|
||||||
int32_t type;
|
|
||||||
int32_t bytes;
|
|
||||||
} SScalarFuncParam;
|
|
||||||
|
|
||||||
typedef struct SScalarFunctionSupport {
|
typedef struct SScalarFunctionSupport {
|
||||||
struct SExprInfo *pExprInfo;
|
struct SExprInfo *pExprInfo;
|
||||||
|
@ -39,7 +33,7 @@ typedef struct SScalarFunctionSupport {
|
||||||
|
|
||||||
extern struct SScalarFunctionInfo scalarFunc[8];
|
extern struct SScalarFunctionInfo scalarFunc[8];
|
||||||
|
|
||||||
int32_t evaluateExprNodeTree(tExprNode* pExprs, int32_t numOfRows, SScalarFuncParam* pOutput,
|
int32_t evaluateExprNodeTree(tExprNode* pExprs, int32_t numOfRows, SScalarParam* pOutput,
|
||||||
void* param, char* (*getSourceDataBlock)(void*, const char*, int32_t));
|
void* param, char* (*getSourceDataBlock)(void*, const char*, int32_t));
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "tscalarfunction.h"
|
#include "sclfunc.h"
|
||||||
|
|
||||||
typedef void (*_bin_scalar_fn_t)(SScalarFuncParam* pLeft, SScalarFuncParam* pRight, void *output, int32_t order);
|
typedef void (*_bin_scalar_fn_t)(SScalarParam* pLeft, SScalarParam* pRight, void *output, int32_t order);
|
||||||
_bin_scalar_fn_t getBinScalarOperatorFn(int32_t binOperator);
|
_bin_scalar_fn_t getBinScalarOperatorFn(int32_t binOperator);
|
||||||
bool isBinaryStringOp(int32_t op);
|
bool isBinaryStringOp(int32_t op);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,594 @@
|
||||||
|
#include "nodes.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "querynodes.h"
|
||||||
|
#include "function.h"
|
||||||
|
#include "functionMgt.h"
|
||||||
|
#include "sclvector.h"
|
||||||
|
#include "sclInt.h"
|
||||||
|
|
||||||
|
int32_t scalarGetOperatorParamNum(EOperatorType type) {
|
||||||
|
if (OP_TYPE_IS_NULL == type || OP_TYPE_IS_NOT_NULL == type) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sclFreeRes(SHashObj *res) {
|
||||||
|
SScalarParam *p = NULL;
|
||||||
|
void *pIter = taosHashIterate(res, NULL);
|
||||||
|
while (pIter) {
|
||||||
|
p = (SScalarParam *)pIter;
|
||||||
|
|
||||||
|
if (p) {
|
||||||
|
tfree(p->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
pIter = taosHashIterate(res, pIter);
|
||||||
|
}
|
||||||
|
|
||||||
|
taosHashCleanup(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sclFreeParam(SScalarParam *param) {
|
||||||
|
tfree(param->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t sclInitParam(SNode* node, SScalarParam *param, SScalarCtx *ctx, int32_t *rowNum) {
|
||||||
|
switch (nodeType(node)) {
|
||||||
|
case QUERY_NODE_VALUE: {
|
||||||
|
SValueNode *valueNode = (SValueNode *)node;
|
||||||
|
param->data = nodesGetValueFromNode(valueNode);
|
||||||
|
param->num = 1;
|
||||||
|
param->type = valueNode->node.resType.type;
|
||||||
|
param->bytes = valueNode->node.resType.bytes;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QUERY_NODE_NODE_LIST: {
|
||||||
|
SNodeListNode *nodeList = (SNodeListNode *)node;
|
||||||
|
//TODO BUILD HASH
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QUERY_NODE_COLUMN_REF: {
|
||||||
|
if (NULL == ctx) {
|
||||||
|
sclError("invalid node type for constant calculating, type:%d, ctx:%p", nodeType(node), ctx);
|
||||||
|
SCL_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
SColumnRefNode *ref = (SColumnRefNode *)node;
|
||||||
|
if (ref->slotId >= taosArrayGetSize(ctx->pSrc->pDataBlock)) {
|
||||||
|
sclError("column ref slotId is too big, slodId:%d, dataBlockSize:%d", ref->slotId, (int32_t)taosArrayGetSize(ctx->pSrc->pDataBlock));
|
||||||
|
SCL_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
SColumnInfoData *columnData = (SColumnInfoData *)taosArrayGet(ctx->pSrc->pDataBlock, ref->slotId);
|
||||||
|
param->data = columnData->pData;
|
||||||
|
param->num = ctx->pSrc->info.rows;
|
||||||
|
param->type = columnData->info.type;
|
||||||
|
param->bytes = columnData->info.bytes;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QUERY_NODE_LOGIC_CONDITION:
|
||||||
|
case QUERY_NODE_OPERATOR: {
|
||||||
|
if (NULL == ctx) {
|
||||||
|
sclError("invalid node type for constant calculating, type:%d, ctx:%p", nodeType(node), ctx);
|
||||||
|
SCL_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
SScalarParam *res = (SScalarParam *)taosHashGet(ctx->pRes, &node, POINTER_BYTES);
|
||||||
|
if (NULL == res) {
|
||||||
|
sclError("no result for node, type:%d, node:%p", nodeType(node), node);
|
||||||
|
SCL_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
*param = *res;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (param->num > *rowNum) {
|
||||||
|
if ((1 != param->num) && (1 < *rowNum)) {
|
||||||
|
sclError("different row nums, rowNum:%d, newRowNum:%d", *rowNum, param->num);
|
||||||
|
SCL_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
*rowNum = param->num;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t sclParamMoveNext(SScalarParam *params, int32_t num) {
|
||||||
|
SScalarParam *param = NULL;
|
||||||
|
|
||||||
|
for (int32_t i = 0; i < num; ++i) {
|
||||||
|
param = params + i;
|
||||||
|
|
||||||
|
if (1 == param->num) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_VAR_DATA_TYPE(param->type)) {
|
||||||
|
param->data = (char *)(param->data) + varDataTLen(param->data);
|
||||||
|
} else {
|
||||||
|
param->data = (char *)(param->data) + tDataTypes[param->type].bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t sclInitParamList(SScalarParam **pParams, SNodeList* pParamList, SScalarCtx *ctx, int32_t *rowNum) {
|
||||||
|
int32_t code = 0;
|
||||||
|
SScalarParam *paramList = calloc(pParamList->length, sizeof(SScalarParam));
|
||||||
|
if (NULL == paramList) {
|
||||||
|
sclError("calloc %d failed", (int32_t)(pParamList->length * sizeof(SScalarParam)));
|
||||||
|
SCL_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
SListCell *cell = pParamList->pHead;
|
||||||
|
for (int32_t i = 0; i < pParamList->length; ++i) {
|
||||||
|
if (NULL == cell || NULL == cell->pNode) {
|
||||||
|
sclError("invalid cell, cell:%p, pNode:%p", cell, cell->pNode);
|
||||||
|
SCL_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
SCL_ERR_JRET(sclInitParam(cell->pNode, ¶mList[i], ctx, rowNum));
|
||||||
|
|
||||||
|
cell = cell->pNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pParams = paramList;
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
|
||||||
|
_return:
|
||||||
|
|
||||||
|
tfree(paramList);
|
||||||
|
SCL_RET(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t sclInitOperatorParams(SScalarParam **pParams, SOperatorNode *node, SScalarCtx *ctx, int32_t *rowNum) {
|
||||||
|
int32_t code = 0;
|
||||||
|
int32_t paramNum = scalarGetOperatorParamNum(node->opType);
|
||||||
|
if (NULL == node->pLeft || (paramNum == 2 && NULL == node->pRight)) {
|
||||||
|
sclError("invalid operation node, left:%p, right:%p", node->pLeft, node->pRight);
|
||||||
|
SCL_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
SScalarParam *paramList = calloc(paramNum, sizeof(SScalarParam));
|
||||||
|
if (NULL == paramList) {
|
||||||
|
sclError("calloc %d failed", (int32_t)(paramNum * sizeof(SScalarParam)));
|
||||||
|
SCL_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
SCL_ERR_JRET(sclInitParam(node->pLeft, ¶mList[0], ctx, rowNum));
|
||||||
|
if (paramNum > 1) {
|
||||||
|
SCL_ERR_JRET(sclInitParam(node->pRight, ¶mList[1], ctx, rowNum));
|
||||||
|
}
|
||||||
|
|
||||||
|
*pParams = paramList;
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
|
||||||
|
_return:
|
||||||
|
|
||||||
|
tfree(paramList);
|
||||||
|
SCL_RET(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t sclExecFuncion(SFunctionNode *node, SScalarCtx *ctx, SScalarParam *output) {
|
||||||
|
if (NULL == node->pParameterList || node->pParameterList->length <= 0) {
|
||||||
|
sclError("invalid function parameter list, list:%p, paramNum:%d", node->pParameterList, node->pParameterList ? node->pParameterList->length : 0);
|
||||||
|
SCL_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
SScalarFuncExecFuncs ffpSet = {0};
|
||||||
|
int32_t code = fmGetScalarFuncExecFuncs(node->funcId, &ffpSet);
|
||||||
|
if (code) {
|
||||||
|
sclError(
"fmGetFuncExecFuncs failed, funcId:%d, code:%s", node->funcId, tstrerror(code));
|
||||||
|
SCL_ERR_RET(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
SScalarParam *params = NULL;
|
||||||
|
int32_t rowNum = 0;
|
||||||
|
SCL_ERR_RET(sclInitParamList(¶ms, node->pParameterList, ctx, &rowNum));
|
||||||
|
|
||||||
|
output->type = node->node.resType.type;
|
||||||
|
output->data = calloc(rowNum, sizeof(tDataTypes[output->type].bytes));
|
||||||
|
if (NULL == output->data) {
|
||||||
|
sclError("calloc %d failed", (int32_t)(rowNum * sizeof(tDataTypes[output->type].bytes)));
|
||||||
|
SCL_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int32_t i = 0; i < rowNum; ++i) {
|
||||||
|
code = (*ffpSet.process)(params, node->pParameterList->length, output);
|
||||||
|
if (code) {
|
||||||
|
sclError(
"scalar function exec failed, funcId:%d, code:%s", node->funcId, tstrerror(code));
|
||||||
|
SCL_ERR_JRET(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
sclParamMoveNext(output, 1);
|
||||||
|
sclParamMoveNext(params, node->pParameterList->length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
|
||||||
|
_return:
|
||||||
|
|
||||||
|
tfree(params);
|
||||||
|
SCL_RET(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t sclExecLogic(SLogicConditionNode *node, SScalarCtx *ctx, SScalarParam *output) {
|
||||||
|
if (NULL == node->pParameterList || node->pParameterList->length <= 0) {
|
||||||
|
sclError("invalid logic parameter list, list:%p, paramNum:%d", node->pParameterList, node->pParameterList ? node->pParameterList->length : 0);
|
||||||
|
SCL_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TSDB_DATA_TYPE_BOOL != node->node.resType.type) {
|
||||||
|
sclError("invalid logic resType, type:%d", node->node.resType.type);
|
||||||
|
SCL_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LOGIC_COND_TYPE_NOT == node->condType && node->pParameterList->length > 1) {
|
||||||
|
sclError("invalid NOT operation parameter number, paramNum:%d", node->pParameterList->length);
|
||||||
|
SCL_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
SScalarParam *params = NULL;
|
||||||
|
int32_t rowNum = 0;
|
||||||
|
int32_t code = 0;
|
||||||
|
|
||||||
|
SCL_ERR_RET(sclInitParamList(¶ms, node->pParameterList, ctx, &rowNum));
|
||||||
|
|
||||||
|
output->type = node->node.resType.type;
|
||||||
|
output->data = calloc(rowNum, sizeof(bool));
|
||||||
|
if (NULL == output->data) {
|
||||||
|
sclError("calloc %d failed", (int32_t)(rowNum * sizeof(bool)));
|
||||||
|
SCL_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool value = false;
|
||||||
|
|
||||||
|
for (int32_t i = 0; i < rowNum; ++i) {
|
||||||
|
for (int32_t m = 0; m < node->pParameterList->length; ++m) {
|
||||||
|
GET_TYPED_DATA(value, bool, params[m].type, params[m].data);
|
||||||
|
|
||||||
|
if (LOGIC_COND_TYPE_AND == node->condType && (false == value)) {
|
||||||
|
break;
|
||||||
|
} else if (LOGIC_COND_TYPE_OR == node->condType && value) {
|
||||||
|
break;
|
||||||
|
} else if (LOGIC_COND_TYPE_NOT == node->condType) {
|
||||||
|
value = !value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*(bool *)output->data = value;
|
||||||
|
|
||||||
|
sclParamMoveNext(output, 1);
|
||||||
|
sclParamMoveNext(params, node->pParameterList->length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
|
||||||
|
_return:
|
||||||
|
|
||||||
|
tfree(params);
|
||||||
|
SCL_RET(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t sclExecOperator(SOperatorNode *node, SScalarCtx *ctx, SScalarParam *output) {
|
||||||
|
SScalarParam *params = NULL;
|
||||||
|
int32_t rowNum = 0;
|
||||||
|
int32_t code = 0;
|
||||||
|
|
||||||
|
SCL_ERR_RET(sclInitOperatorParams(¶ms, node, ctx, &rowNum));
|
||||||
|
|
||||||
|
output->type = node->node.resType.type;
|
||||||
|
output->data = calloc(rowNum, tDataTypes[output->type].bytes);
|
||||||
|
if (NULL == output->data) {
|
||||||
|
sclError("calloc %d failed", (int32_t)rowNum * tDataTypes[output->type].bytes);
|
||||||
|
SCL_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
_bin_scalar_fn_t OperatorFn = getBinScalarOperatorFn(node->opType);
|
||||||
|
|
||||||
|
int32_t paramNum = scalarGetOperatorParamNum(node->opType);
|
||||||
|
SScalarParam* pLeft = ¶ms[0];
|
||||||
|
SScalarParam* pRight = paramNum > 1 ? ¶ms[1] : NULL;
|
||||||
|
|
||||||
|
for (int32_t i = 0; i < rowNum; ++i) {
|
||||||
|
|
||||||
|
OperatorFn(pLeft, pRight, output->data, TSDB_ORDER_ASC);
|
||||||
|
|
||||||
|
sclParamMoveNext(output, 1);
|
||||||
|
sclParamMoveNext(pLeft, 1);
|
||||||
|
if (pRight) {
|
||||||
|
sclParamMoveNext(pRight, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
|
||||||
|
_return:
|
||||||
|
|
||||||
|
tfree(params);
|
||||||
|
SCL_RET(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EDealRes sclRewriteFunction(SNode** pNode, void* pContext) {
|
||||||
|
SFunctionNode *node = (SFunctionNode *)*pNode;
|
||||||
|
SScalarParam output = {0};
|
||||||
|
|
||||||
|
*(int32_t *)pContext = sclExecFuncion(node, NULL, &output);
|
||||||
|
if (*(int32_t *)pContext) {
|
||||||
|
return DEAL_RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
SValueNode *res = (SValueNode *)nodesMakeNode(QUERY_NODE_VALUE);
|
||||||
|
if (NULL == res) {
|
||||||
|
sclError("make value node failed");
|
||||||
|
sclFreeParam(&output);
|
||||||
|
*(int32_t *)pContext = TSDB_CODE_QRY_OUT_OF_MEMORY;
|
||||||
|
return DEAL_RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
res->node.resType = node->node.resType;
|
||||||
|
|
||||||
|
if (IS_VAR_DATA_TYPE(output.type)) {
|
||||||
|
res->datum.p = output.data;
|
||||||
|
output.data = NULL;
|
||||||
|
} else {
|
||||||
|
memcpy(nodesGetValueFromNode(res), output.data, tDataTypes[output.type].bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
nodesDestroyNode(*pNode);
|
||||||
|
*pNode = (SNode*)res;
|
||||||
|
|
||||||
|
sclFreeParam(&output);
|
||||||
|
|
||||||
|
return DEAL_RES_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
EDealRes sclRewriteLogic(SNode** pNode, void* pContext) {
|
||||||
|
SLogicConditionNode *node = (SLogicConditionNode *)*pNode;
|
||||||
|
SScalarParam output = {0};
|
||||||
|
|
||||||
|
*(int32_t *)pContext = sclExecLogic(node, NULL, &output);
|
||||||
|
if (*(int32_t *)pContext) {
|
||||||
|
return DEAL_RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
SValueNode *res = (SValueNode *)nodesMakeNode(QUERY_NODE_VALUE);
|
||||||
|
if (NULL == res) {
|
||||||
|
sclError("make value node failed");
|
||||||
|
sclFreeParam(&output);
|
||||||
|
*(int32_t *)pContext = TSDB_CODE_QRY_OUT_OF_MEMORY;
|
||||||
|
return DEAL_RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
res->node.resType = node->node.resType;
|
||||||
|
|
||||||
|
if (IS_VAR_DATA_TYPE(output.type)) {
|
||||||
|
res->datum.p = output.data;
|
||||||
|
output.data = NULL;
|
||||||
|
} else {
|
||||||
|
memcpy(nodesGetValueFromNode(res), output.data, tDataTypes[output.type].bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
nodesDestroyNode(*pNode);
|
||||||
|
*pNode = (SNode*)res;
|
||||||
|
|
||||||
|
sclFreeParam(&output);
|
||||||
|
|
||||||
|
return DEAL_RES_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
EDealRes sclRewriteOperator(SNode** pNode, void* pContext) {
|
||||||
|
SOperatorNode *node = (SOperatorNode *)*pNode;
|
||||||
|
SScalarParam output = {0};
|
||||||
|
|
||||||
|
*(int32_t *)pContext = sclExecOperator(node, NULL, &output);
|
||||||
|
if (*(int32_t *)pContext) {
|
||||||
|
return DEAL_RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
SValueNode *res = (SValueNode *)nodesMakeNode(QUERY_NODE_VALUE);
|
||||||
|
if (NULL == res) {
|
||||||
|
sclError("make value node failed");
|
||||||
|
sclFreeParam(&output);
|
||||||
|
*(int32_t *)pContext = TSDB_CODE_QRY_OUT_OF_MEMORY;
|
||||||
|
return DEAL_RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
res->node.resType = node->node.resType;
|
||||||
|
|
||||||
|
if (IS_VAR_DATA_TYPE(output.type)) {
|
||||||
|
res->datum.p = output.data;
|
||||||
|
output.data = NULL;
|
||||||
|
} else {
|
||||||
|
memcpy(nodesGetValueFromNode(res), output.data, tDataTypes[output.type].bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
nodesDestroyNode(*pNode);
|
||||||
|
*pNode = (SNode*)res;
|
||||||
|
|
||||||
|
sclFreeParam(&output);
|
||||||
|
|
||||||
|
return DEAL_RES_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EDealRes sclConstantsRewriter(SNode** pNode, void* pContext) {
|
||||||
|
if (QUERY_NODE_VALUE == nodeType(*pNode)) {
|
||||||
|
return DEAL_RES_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (QUERY_NODE_FUNCTION == nodeType(*pNode)) {
|
||||||
|
return sclRewriteFunction(pNode, pContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pNode)) {
|
||||||
|
return sclRewriteLogic(pNode, pContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (QUERY_NODE_OPERATOR == nodeType(*pNode)) {
|
||||||
|
return sclRewriteOperator(pNode, pContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
sclError("invalid node type for calculating constants, type:%d", nodeType(*pNode));
|
||||||
|
|
||||||
|
*(int32_t *)pContext = TSDB_CODE_QRY_INVALID_INPUT;
|
||||||
|
|
||||||
|
return DEAL_RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EDealRes sclWalkFunction(SNode* pNode, void* pContext) {
|
||||||
|
SScalarCtx *ctx = (SScalarCtx *)pContext;
|
||||||
|
SFunctionNode *node = (SFunctionNode *)pNode;
|
||||||
|
SScalarParam output = {0};
|
||||||
|
|
||||||
|
ctx->code = sclExecFuncion(node, ctx, &output);
|
||||||
|
if (ctx->code) {
|
||||||
|
return DEAL_RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (taosHashPut(ctx->pRes, &pNode, POINTER_BYTES, &output, sizeof(output))) {
|
||||||
|
ctx->code = TSDB_CODE_QRY_OUT_OF_MEMORY;
|
||||||
|
return DEAL_RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DEAL_RES_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EDealRes sclWalkLogic(SNode* pNode, void* pContext) {
|
||||||
|
SScalarCtx *ctx = (SScalarCtx *)pContext;
|
||||||
|
SLogicConditionNode *node = (SLogicConditionNode *)pNode;
|
||||||
|
SScalarParam output = {0};
|
||||||
|
|
||||||
|
ctx->code = sclExecLogic(node, ctx, &output);
|
||||||
|
if (ctx->code) {
|
||||||
|
return DEAL_RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (taosHashPut(ctx->pRes, &pNode, POINTER_BYTES, &output, sizeof(output))) {
|
||||||
|
ctx->code = TSDB_CODE_QRY_OUT_OF_MEMORY;
|
||||||
|
return DEAL_RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DEAL_RES_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EDealRes sclWalkOperator(SNode* pNode, void* pContext) {
|
||||||
|
SScalarCtx *ctx = (SScalarCtx *)pContext;
|
||||||
|
SOperatorNode *node = (SOperatorNode *)pNode;
|
||||||
|
SScalarParam output = {0};
|
||||||
|
|
||||||
|
ctx->code = sclExecOperator(node, ctx, &output);
|
||||||
|
if (ctx->code) {
|
||||||
|
return DEAL_RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (taosHashPut(ctx->pRes, &pNode, POINTER_BYTES, &output, sizeof(output))) {
|
||||||
|
ctx->code = TSDB_CODE_QRY_OUT_OF_MEMORY;
|
||||||
|
return DEAL_RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DEAL_RES_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EDealRes sclCalcWalker(SNode* pNode, void* pContext) {
|
||||||
|
if (QUERY_NODE_VALUE == nodeType(pNode)) {
|
||||||
|
return DEAL_RES_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (QUERY_NODE_FUNCTION == nodeType(pNode)) {
|
||||||
|
return sclWalkFunction(pNode, pContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pNode)) {
|
||||||
|
return sclWalkLogic(pNode, pContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (QUERY_NODE_OPERATOR == nodeType(pNode)) {
|
||||||
|
return sclWalkOperator(pNode, pContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
sclError("invalid node type for calculating constants, type:%d", nodeType(pNode));
|
||||||
|
|
||||||
|
SScalarCtx *ctx = (SScalarCtx *)pContext;
|
||||||
|
|
||||||
|
ctx->code = TSDB_CODE_QRY_INVALID_INPUT;
|
||||||
|
|
||||||
|
return DEAL_RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int32_t scalarCalculateConstants(SNode *pNode, SNode **pRes) {
|
||||||
|
if (NULL == pNode) {
|
||||||
|
SCL_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t code = 0;
|
||||||
|
|
||||||
|
nodesRewriteNodePostOrder(&pNode, sclConstantsRewriter, (void *)&code);
|
||||||
|
|
||||||
|
if (code) {
|
||||||
|
nodesDestroyNode(pNode);
|
||||||
|
SCL_ERR_RET(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
*pRes = pNode;
|
||||||
|
|
||||||
|
SCL_RET(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t scalarCalculate(SNode *pNode, SSDataBlock *pSrc, SScalarParam *pDst) {
|
||||||
|
if (NULL == pNode || NULL == pSrc || NULL == pDst) {
|
||||||
|
SCL_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t code = 0;
|
||||||
|
SScalarCtx ctx = {.code = 0, .pSrc = pSrc};
|
||||||
|
|
||||||
|
ctx.pRes = taosHashInit(SCL_DEFAULT_OP_NUM, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
|
||||||
|
if (NULL == ctx.pRes) {
|
||||||
|
sclError("taosHashInit failed, num:%d", SCL_DEFAULT_OP_NUM);
|
||||||
|
SCL_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
nodesWalkNodePostOrder(pNode, sclCalcWalker, (void *)&ctx);
|
||||||
|
|
||||||
|
if (ctx.code) {
|
||||||
|
nodesDestroyNode(pNode);
|
||||||
|
sclFreeRes(ctx.pRes);
|
||||||
|
SCL_ERR_RET(ctx.code);
|
||||||
|
}
|
||||||
|
|
||||||
|
SScalarParam *res = (SScalarParam *)taosHashGet(ctx.pRes, (void *)&pNode, POINTER_BYTES);
|
||||||
|
if (NULL == res) {
|
||||||
|
sclError("no res for calculating, node:%p, type:%d", pNode, nodeType(pNode));
|
||||||
|
SCL_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
*pDst = *res;
|
||||||
|
|
||||||
|
nodesDestroyNode(pNode);
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
#include "tscalarfunction.h"
|
#include "sclfunc.h"
|
||||||
#include "tbinoperator.h"
|
#include "sclvector.h"
|
||||||
#include "tunaryoperator.h"
|
|
||||||
|
|
||||||
static void assignBasicParaInfo(struct SScalarFuncParam* dst, const struct SScalarFuncParam* src) {
|
static void assignBasicParaInfo(struct SScalarParam* dst, const struct SScalarParam* src) {
|
||||||
dst->type = src->type;
|
dst->type = src->type;
|
||||||
dst->bytes = src->bytes;
|
dst->bytes = src->bytes;
|
||||||
dst->num = src->num;
|
dst->num = src->num;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tceil(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) {
|
static void tceil(SScalarParam* pOutput, size_t numOfInput, const SScalarParam *pLeft) {
|
||||||
assignBasicParaInfo(pOutput, pLeft);
|
assignBasicParaInfo(pOutput, pLeft);
|
||||||
assert(numOfInput == 1);
|
assert(numOfInput == 1);
|
||||||
|
|
||||||
|
@ -34,7 +33,7 @@ static void tceil(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFun
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tfloor(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) {
|
static void tfloor(SScalarParam* pOutput, size_t numOfInput, const SScalarParam *pLeft) {
|
||||||
assignBasicParaInfo(pOutput, pLeft);
|
assignBasicParaInfo(pOutput, pLeft);
|
||||||
assert(numOfInput == 1);
|
assert(numOfInput == 1);
|
||||||
|
|
||||||
|
@ -62,7 +61,7 @@ static void tfloor(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _tabs(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) {
|
static void _tabs(SScalarParam* pOutput, size_t numOfInput, const SScalarParam *pLeft) {
|
||||||
assignBasicParaInfo(pOutput, pLeft);
|
assignBasicParaInfo(pOutput, pLeft);
|
||||||
assert(numOfInput == 1);
|
assert(numOfInput == 1);
|
||||||
|
|
||||||
|
@ -120,7 +119,7 @@ static void _tabs(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFun
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tround(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) {
|
static void tround(SScalarParam* pOutput, size_t numOfInput, const SScalarParam *pLeft) {
|
||||||
assignBasicParaInfo(pOutput, pLeft);
|
assignBasicParaInfo(pOutput, pLeft);
|
||||||
assert(numOfInput == 1);
|
assert(numOfInput == 1);
|
||||||
|
|
||||||
|
@ -146,7 +145,7 @@ static void tround(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tlength(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) {
|
static void tlength(SScalarParam* pOutput, size_t numOfInput, const SScalarParam *pLeft) {
|
||||||
assert(numOfInput == 1);
|
assert(numOfInput == 1);
|
||||||
|
|
||||||
int64_t* out = (int64_t*) pOutput->data;
|
int64_t* out = (int64_t*) pOutput->data;
|
||||||
|
@ -157,7 +156,7 @@ static void tlength(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tconcat(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) {
|
static void tconcat(SScalarParam* pOutput, size_t numOfInput, const SScalarParam *pLeft) {
|
||||||
assert(numOfInput > 0);
|
assert(numOfInput > 0);
|
||||||
|
|
||||||
int32_t rowLen = 0;
|
int32_t rowLen = 0;
|
||||||
|
@ -189,11 +188,11 @@ static void tconcat(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tltrim(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) {
|
static void tltrim(SScalarParam* pOutput, size_t numOfInput, const SScalarParam *pLeft) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void trtrim(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) {
|
static void trtrim(SScalarParam* pOutput, size_t numOfInput, const SScalarParam *pLeft) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +261,7 @@ static void reverseCopy(char* dest, const char* src, int16_t type, int32_t numOf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setScalarFuncParam(SScalarFuncParam* param, int32_t type, int32_t bytes, void* pInput, int32_t numOfRows) {
|
static void setScalarFuncParam(SScalarParam* param, int32_t type, int32_t bytes, void* pInput, int32_t numOfRows) {
|
||||||
param->bytes = bytes;
|
param->bytes = bytes;
|
||||||
param->type = type;
|
param->type = type;
|
||||||
param->num = numOfRows;
|
param->num = numOfRows;
|
||||||
|
@ -273,6 +272,7 @@ bool isStringOp(int32_t op) {
|
||||||
return op == TSDB_BINARY_OP_CONCAT;
|
return op == TSDB_BINARY_OP_CONCAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
int32_t evaluateExprNodeTree(tExprNode* pExprs, int32_t numOfRows, SScalarFuncParam* pOutput, void* param,
|
int32_t evaluateExprNodeTree(tExprNode* pExprs, int32_t numOfRows, SScalarFuncParam* pOutput, void* param,
|
||||||
char* (*getSourceDataBlock)(void*, const char*, int32_t)) {
|
char* (*getSourceDataBlock)(void*, const char*, int32_t)) {
|
||||||
if (pExprs == NULL) {
|
if (pExprs == NULL) {
|
||||||
|
@ -361,6 +361,8 @@ int32_t evaluateExprNodeTree(tExprNode* pExprs, int32_t numOfRows, SScalarFuncPa
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
SScalarFunctionInfo scalarFunc[8] = {
|
SScalarFunctionInfo scalarFunc[8] = {
|
||||||
{"ceil", FUNCTION_TYPE_SCALAR, FUNCTION_CEIL, tceil},
|
{"ceil", FUNCTION_TYPE_SCALAR, FUNCTION_CEIL, tceil},
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
MESSAGE(STATUS "build scalar unit test")
|
||||||
|
|
||||||
|
# GoogleTest requires at least C++11
|
||||||
|
SET(CMAKE_CXX_STANDARD 11)
|
||||||
|
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
|
||||||
|
|
||||||
|
ADD_EXECUTABLE(scalarTest ${SOURCE_LIST})
|
||||||
|
TARGET_LINK_LIBRARIES(
|
||||||
|
scalarTest
|
||||||
|
PUBLIC os util common gtest qcom function nodes
|
||||||
|
)
|
||||||
|
|
||||||
|
TARGET_INCLUDE_DIRECTORIES(
|
||||||
|
scalarTest
|
||||||
|
PUBLIC "${CMAKE_SOURCE_DIR}/include/libs/scalar/"
|
||||||
|
PRIVATE "${CMAKE_SOURCE_DIR}/source/libs/scalar/inc"
|
||||||
|
)
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* 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 <gtest/gtest.h>
|
||||||
|
#include <tglobal.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wwrite-strings"
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||||
|
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||||
|
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||||
|
#pragma GCC diagnostic ignored "-Wformat"
|
||||||
|
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
|
||||||
|
#pragma GCC diagnostic ignored "-Wpointer-arith"
|
||||||
|
|
||||||
|
#include "os.h"
|
||||||
|
|
||||||
|
#include "taos.h"
|
||||||
|
#include "tdef.h"
|
||||||
|
#include "tvariant.h"
|
||||||
|
#include "tep.h"
|
||||||
|
#include "stub.h"
|
||||||
|
#include "addr_any.h"
|
||||||
|
#include "scalar.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(scalarTest, func) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
srand(time(NULL));
|
||||||
|
testing::InitGoogleTest(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma GCC diagnostic pop
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
aux_source_directory(src SYNC_SRC)
|
aux_source_directory(src SYNC_SRC)
|
||||||
add_library(sync ${SYNC_SRC})
|
add_library(sync ${SYNC_SRC})
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TD_LIBS_SYNC_APPEND_ENTRIES_H
|
||||||
|
#define _TD_LIBS_SYNC_APPEND_ENTRIES_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "syncMessage.h"
|
||||||
|
#include "syncRaft.h"
|
||||||
|
#include "taosdef.h"
|
||||||
|
|
||||||
|
void appendEntries(SRaft *pRaft, const SyncAppendEntries *pMsg);
|
||||||
|
|
||||||
|
void onAppendEntries(SRaft *pRaft, const SyncAppendEntries *pMsg);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*_TD_LIBS_SYNC_APPEND_ENTRIES_H*/
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TD_LIBS_SYNC_APPEND_ENTRIES_REPLY_H
|
||||||
|
#define _TD_LIBS_SYNC_APPEND_ENTRIES_REPLY_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "syncMessage.h"
|
||||||
|
#include "syncRaft.h"
|
||||||
|
#include "taosdef.h"
|
||||||
|
|
||||||
|
void onAppendEntriesReply(SRaft *pRaft, const SyncAppendEntriesReply *pMsg);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*_TD_LIBS_SYNC_APPEND_ENTRIES_REPLY_H*/
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TD_LIBS_SYNC_ELECTION_H
|
||||||
|
#define _TD_LIBS_SYNC_ELECTION_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "taosdef.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*_TD_LIBS_SYNC_ELECTION_H*/
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TD_LIBS_SYNC_INT_H
|
||||||
|
#define _TD_LIBS_SYNC_INT_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "taosdef.h"
|
||||||
|
|
||||||
|
#define sFatal(...) \
|
||||||
|
{ \
|
||||||
|
if (sDebugFlag & DEBUG_FATAL) { \
|
||||||
|
taosPrintLog("SYN FATAL ", sDebugFlag, __VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#define sError(...) \
|
||||||
|
{ \
|
||||||
|
if (sDebugFlag & DEBUG_ERROR) { \
|
||||||
|
taosPrintLog("SYN ERROR ", sDebugFlag, __VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#define sWarn(...) \
|
||||||
|
{ \
|
||||||
|
if (sDebugFlag & DEBUG_WARN) { \
|
||||||
|
taosPrintLog("SYN WARN ", sDebugFlag, __VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#define sInfo(...) \
|
||||||
|
{ \
|
||||||
|
if (sDebugFlag & DEBUG_INFO) { \
|
||||||
|
taosPrintLog("SYN ", sDebugFlag, __VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#define sDebug(...) \
|
||||||
|
{ \
|
||||||
|
if (sDebugFlag & DEBUG_DEBUG) { \
|
||||||
|
taosPrintLog("SYN ", sDebugFlag, __VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#define sTrace(...) \
|
||||||
|
{ \
|
||||||
|
if (sDebugFlag & DEBUG_TRACE) { \
|
||||||
|
taosPrintLog("SYN ", sDebugFlag, __VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct SSyncNode {
|
||||||
|
char path[TSDB_FILENAME_LEN];
|
||||||
|
int8_t replica;
|
||||||
|
int8_t quorum;
|
||||||
|
int8_t selfIndex;
|
||||||
|
uint32_t vgId;
|
||||||
|
int32_t refCount;
|
||||||
|
int64_t rid;
|
||||||
|
} SSyncNode;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*_TD_LIBS_SYNC_INT_H*/
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TD_LIBS_SYNC_MESSAGE_H
|
||||||
|
#define _TD_LIBS_SYNC_MESSAGE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "sync.h"
|
||||||
|
#include "syncRaftEntry.h"
|
||||||
|
#include "taosdef.h"
|
||||||
|
|
||||||
|
typedef enum ESyncMessageType {
|
||||||
|
SYNC_PING = 0,
|
||||||
|
SYNC_PING_REPLY,
|
||||||
|
SYNC_CLIENT_REQUEST,
|
||||||
|
SYNC_CLIENT_REQUEST_REPLY,
|
||||||
|
SYNC_REQUEST_VOTE,
|
||||||
|
SYNC_REQUEST_VOTE_REPLY,
|
||||||
|
SYNC_APPEND_ENTRIES,
|
||||||
|
SYNC_APPEND_ENTRIES_REPLY,
|
||||||
|
} ESyncMessageType;
|
||||||
|
|
||||||
|
typedef struct SyncPing {
|
||||||
|
ESyncMessageType msgType;
|
||||||
|
const SSyncBuffer *pData;
|
||||||
|
} SyncPing;
|
||||||
|
|
||||||
|
typedef struct SyncPingReply {
|
||||||
|
ESyncMessageType msgType;
|
||||||
|
const SSyncBuffer *pData;
|
||||||
|
} SyncPingReply;
|
||||||
|
|
||||||
|
typedef struct SyncClientRequest {
|
||||||
|
ESyncMessageType msgType;
|
||||||
|
const SSyncBuffer *pData;
|
||||||
|
int64_t seqNum;
|
||||||
|
bool isWeak;
|
||||||
|
} SyncClientRequest;
|
||||||
|
|
||||||
|
typedef struct SyncClientRequestReply {
|
||||||
|
ESyncMessageType msgType;
|
||||||
|
int32_t errCode;
|
||||||
|
const SSyncBuffer *pErrMsg;
|
||||||
|
const SSyncBuffer *pLeaderHint;
|
||||||
|
} SyncClientRequestReply;
|
||||||
|
|
||||||
|
typedef struct SyncRequestVote {
|
||||||
|
ESyncMessageType msgType;
|
||||||
|
SyncTerm currentTerm;
|
||||||
|
SyncNodeId nodeId;
|
||||||
|
SyncGroupId vgId;
|
||||||
|
SyncIndex lastLogIndex;
|
||||||
|
SyncTerm lastLogTerm;
|
||||||
|
} SyncRequestVote;
|
||||||
|
|
||||||
|
typedef struct SyncRequestVoteReply {
|
||||||
|
ESyncMessageType msgType;
|
||||||
|
SyncTerm currentTerm;
|
||||||
|
SyncNodeId nodeId;
|
||||||
|
SyncGroupId vgId;
|
||||||
|
bool voteGranted;
|
||||||
|
} SyncRequestVoteReply;
|
||||||
|
|
||||||
|
typedef struct SyncAppendEntries {
|
||||||
|
ESyncMessageType msgType;
|
||||||
|
SyncTerm currentTerm;
|
||||||
|
SyncNodeId nodeId;
|
||||||
|
SyncIndex prevLogIndex;
|
||||||
|
SyncTerm prevLogTerm;
|
||||||
|
int32_t entryCount;
|
||||||
|
SSyncRaftEntry * logEntries;
|
||||||
|
SyncIndex commitIndex;
|
||||||
|
} SyncAppendEntries;
|
||||||
|
|
||||||
|
typedef struct SyncAppendEntriesReply {
|
||||||
|
ESyncMessageType msgType;
|
||||||
|
SyncTerm currentTerm;
|
||||||
|
SyncNodeId nodeId;
|
||||||
|
bool success;
|
||||||
|
SyncIndex matchIndex;
|
||||||
|
} SyncAppendEntriesReply;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*_TD_LIBS_SYNC_MESSAGE_H*/
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TD_LIBS_SYNC_ON_MESSAGE_H
|
||||||
|
#define _TD_LIBS_SYNC_ON_MESSAGE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "syncRaft.h"
|
||||||
|
#include "taosdef.h"
|
||||||
|
|
||||||
|
void onMessage(SRaft *pRaft, void *pMsg);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*_TD_LIBS_SYNC_ON_MESSAGE_H*/
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TD_LIBS_SYNC_RAFT_H
|
||||||
|
#define _TD_LIBS_SYNC_RAFT_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "sync.h"
|
||||||
|
#include "syncMessage.h"
|
||||||
|
#include "taosdef.h"
|
||||||
|
|
||||||
|
typedef struct SRaftId {
|
||||||
|
SyncNodeId nodeId;
|
||||||
|
SyncGroupId vgId;
|
||||||
|
} SRaftId;
|
||||||
|
|
||||||
|
typedef struct SRaft {
|
||||||
|
SRaftId id;
|
||||||
|
} SRaft;
|
||||||
|
|
||||||
|
int32_t raftPropose(SRaft* pRaft, const SSyncBuffer* pBuf, bool isWeak);
|
||||||
|
|
||||||
|
static int raftSendMsg(SRaftId destRaftId, const void* pMsg, const SRaft* pRaft);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*_TD_LIBS_SYNC_RAFT_H*/
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TD_LIBS_TPL_H
|
||||||
|
#define _TD_LIBS_TPL_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "sync.h"
|
||||||
|
#include "taosdef.h"
|
||||||
|
|
||||||
|
typedef struct SSyncRaftEntry {
|
||||||
|
SyncTerm term;
|
||||||
|
SyncIndex index;
|
||||||
|
SSyncBuffer data;
|
||||||
|
int8_t flag;
|
||||||
|
} SSyncRaftEntry;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*_TD_LIBS_TPL_H*/
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TD_LIBS_SYNC_RAFT_LOG_H
|
||||||
|
#define _TD_LIBS_SYNC_RAFT_LOG_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "sync.h"
|
||||||
|
#include "taosdef.h"
|
||||||
|
|
||||||
|
int32_t raftLogAppendEntry(struct SSyncLogStore* pLogStore, SSyncBuffer* pBuf);
|
||||||
|
|
||||||
|
// get one log entry, user need to free pBuf->data
|
||||||
|
int32_t raftLogGetEntry(struct SSyncLogStore* pLogStore, SyncIndex index, SSyncBuffer* pBuf);
|
||||||
|
|
||||||
|
// update log store commit index with "index"
|
||||||
|
int32_t raftLogUpdateCommitIndex(struct SSyncLogStore* pLogStore, SyncIndex index);
|
||||||
|
|
||||||
|
// truncate log with index, entries after the given index (>index) will be deleted
|
||||||
|
int32_t raftLogTruncate(struct SSyncLogStore* pLogStore, SyncIndex index);
|
||||||
|
|
||||||
|
// return commit index of log
|
||||||
|
SyncIndex raftLogGetCommitIndex(struct SSyncLogStore* pLogStore);
|
||||||
|
|
||||||
|
// return index of last entry
|
||||||
|
SyncIndex raftLogGetLastIndex(struct SSyncLogStore* pLogStore);
|
||||||
|
|
||||||
|
// return term of last entry
|
||||||
|
SyncTerm raftLogGetLastTerm(struct SSyncLogStore* pLogStore);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*_TD_LIBS_SYNC_RAFT_LOG_H*/
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TD_LIBS_SYNC_RAFT_STORE_H
|
||||||
|
#define _TD_LIBS_SYNC_RAFT_STORE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "sync.h"
|
||||||
|
#include "syncRaft.h"
|
||||||
|
#include "taosdef.h"
|
||||||
|
|
||||||
|
int32_t currentTerm(SyncTerm *pCurrentTerm);
|
||||||
|
|
||||||
|
int32_t persistCurrentTerm(SyncTerm currentTerm);
|
||||||
|
|
||||||
|
int32_t voteFor(SRaftId *pRaftId);
|
||||||
|
|
||||||
|
int32_t persistVoteFor(SRaftId *pRaftId);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*_TD_LIBS_SYNC_RAFT_STORE_H*/
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TD_LIBS_SYNC_REPLICATION_H
|
||||||
|
#define _TD_LIBS_SYNC_REPLICATION_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "taosdef.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*_TD_LIBS_SYNC_REPLICATION_H*/
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TD_LIBS_SYNC_REQUEST_VOTE_H
|
||||||
|
#define _TD_LIBS_SYNC_REQUEST_VOTE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "syncMessage.h"
|
||||||
|
#include "syncRaft.h"
|
||||||
|
#include "taosdef.h"
|
||||||
|
|
||||||
|
void requestVote(SRaft *pRaft, const SyncRequestVote *pMsg);
|
||||||
|
|
||||||
|
void onRequestVote(SRaft *pRaft, const SyncRequestVote *pMsg);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*_TD_LIBS_SYNC_REQUEST_VOTE_H*/
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TD_LIBS_SYNC_REQUEST_VOTE_REPLY_H
|
||||||
|
#define _TD_LIBS_SYNC_REQUEST_VOTE_REPLY_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "syncMessage.h"
|
||||||
|
#include "syncRaft.h"
|
||||||
|
#include "taosdef.h"
|
||||||
|
|
||||||
|
void onRequestVoteReply(SRaft *pRaft, const SyncRequestVoteReply *pMsg);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*_TD_LIBS_SYNC_REQUEST_VOTE_REPLY_H*/
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TD_LIBS_SYNC_SNAPSHOT_H
|
||||||
|
#define _TD_LIBS_SYNC_SNAPSHOT_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "sync.h"
|
||||||
|
#include "syncRaft.h"
|
||||||
|
#include "taosdef.h"
|
||||||
|
|
||||||
|
int32_t takeSnapshot(SSyncFSM *pFsm, SSnapshot *pSnapshot);
|
||||||
|
|
||||||
|
int32_t restoreSnapshot(SSyncFSM *pFsm, SSnapshot *pSnapshot);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*_TD_LIBS_SYNC_SNAPSHOT_H*/
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TD_LIBS_SYNC_TIMEOUT_H
|
||||||
|
#define _TD_LIBS_SYNC_TIMEOUT_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "syncMessage.h"
|
||||||
|
#include "syncRaft.h"
|
||||||
|
#include "taosdef.h"
|
||||||
|
|
||||||
|
void onTimeout(SRaft *pRaft, void *pMsg);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*_TD_LIBS_SYNC_TIMEOUT_H*/
|
|
@ -1 +0,0 @@
|
||||||
#include "sync.h"
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* 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 "syncAppendEntries.h"
|
||||||
|
#include "sync.h"
|
||||||
|
|
||||||
|
void appendEntries(SRaft *pRaft, const SyncAppendEntries *pMsg) {
|
||||||
|
|
||||||
|
// TLA+ Spec
|
||||||
|
//AppendEntries(i, j) ==
|
||||||
|
// /\ i /= j
|
||||||
|
// /\ state[i] = Leader
|
||||||
|
// /\ LET prevLogIndex == nextIndex[i][j] - 1
|
||||||
|
// prevLogTerm == IF prevLogIndex > 0 THEN
|
||||||
|
// log[i][prevLogIndex].term
|
||||||
|
// ELSE
|
||||||
|
// 0
|
||||||
|
// \* Send up to 1 entry, constrained by the end of the log.
|
||||||
|
// lastEntry == Min({Len(log[i]), nextIndex[i][j]})
|
||||||
|
// entries == SubSeq(log[i], nextIndex[i][j], lastEntry)
|
||||||
|
// IN Send([mtype |-> AppendEntriesRequest,
|
||||||
|
// mterm |-> currentTerm[i],
|
||||||
|
// mprevLogIndex |-> prevLogIndex,
|
||||||
|
// mprevLogTerm |-> prevLogTerm,
|
||||||
|
// mentries |-> entries,
|
||||||
|
// \* mlog is used as a history variable for the proof.
|
||||||
|
// \* It would not exist in a real implementation.
|
||||||
|
// mlog |-> log[i],
|
||||||
|
// mcommitIndex |-> Min({commitIndex[i], lastEntry}),
|
||||||
|
// msource |-> i,
|
||||||
|
// mdest |-> j])
|
||||||
|
// /\ UNCHANGED <<serverVars, candidateVars, leaderVars, logVars>>
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void onAppendEntries(SRaft *pRaft, const SyncAppendEntries *pMsg) {
|
||||||
|
|
||||||
|
// TLA+ Spec
|
||||||
|
//HandleAppendEntriesRequest(i, j, m) ==
|
||||||
|
// LET logOk == \/ m.mprevLogIndex = 0
|
||||||
|
// \/ /\ m.mprevLogIndex > 0
|
||||||
|
// /\ m.mprevLogIndex <= Len(log[i])
|
||||||
|
// /\ m.mprevLogTerm = log[i][m.mprevLogIndex].term
|
||||||
|
// IN /\ m.mterm <= currentTerm[i]
|
||||||
|
// /\ \/ /\ \* reject request
|
||||||
|
// \/ m.mterm < currentTerm[i]
|
||||||
|
// \/ /\ m.mterm = currentTerm[i]
|
||||||
|
// /\ state[i] = Follower
|
||||||
|
// /\ \lnot logOk
|
||||||
|
// /\ Reply([mtype |-> AppendEntriesResponse,
|
||||||
|
// mterm |-> currentTerm[i],
|
||||||
|
// msuccess |-> FALSE,
|
||||||
|
// mmatchIndex |-> 0,
|
||||||
|
// msource |-> i,
|
||||||
|
// mdest |-> j],
|
||||||
|
// m)
|
||||||
|
// /\ UNCHANGED <<serverVars, logVars>>
|
||||||
|
// \/ \* return to follower state
|
||||||
|
// /\ m.mterm = currentTerm[i]
|
||||||
|
// /\ state[i] = Candidate
|
||||||
|
// /\ state' = [state EXCEPT ![i] = Follower]
|
||||||
|
// /\ UNCHANGED <<currentTerm, votedFor, logVars, messages>>
|
||||||
|
// \/ \* accept request
|
||||||
|
// /\ m.mterm = currentTerm[i]
|
||||||
|
// /\ state[i] = Follower
|
||||||
|
// /\ logOk
|
||||||
|
// /\ LET index == m.mprevLogIndex + 1
|
||||||
|
// IN \/ \* already done with request
|
||||||
|
// /\ \/ m.mentries = << >>
|
||||||
|
// \/ /\ m.mentries /= << >>
|
||||||
|
// /\ Len(log[i]) >= index
|
||||||
|
// /\ log[i][index].term = m.mentries[1].term
|
||||||
|
// \* This could make our commitIndex decrease (for
|
||||||
|
// \* example if we process an old, duplicated request),
|
||||||
|
// \* but that doesn't really affect anything.
|
||||||
|
// /\ commitIndex' = [commitIndex EXCEPT ![i] =
|
||||||
|
// m.mcommitIndex]
|
||||||
|
// /\ Reply([mtype |-> AppendEntriesResponse,
|
||||||
|
// mterm |-> currentTerm[i],
|
||||||
|
// msuccess |-> TRUE,
|
||||||
|
// mmatchIndex |-> m.mprevLogIndex +
|
||||||
|
// Len(m.mentries),
|
||||||
|
// msource |-> i,
|
||||||
|
// mdest |-> j],
|
||||||
|
// m)
|
||||||
|
// /\ UNCHANGED <<serverVars, log>>
|
||||||
|
// \/ \* conflict: remove 1 entry
|
||||||
|
// /\ m.mentries /= << >>
|
||||||
|
// /\ Len(log[i]) >= index
|
||||||
|
// /\ log[i][index].term /= m.mentries[1].term
|
||||||
|
// /\ LET new == [index2 \in 1..(Len(log[i]) - 1) |->
|
||||||
|
// log[i][index2]]
|
||||||
|
// IN log' = [log EXCEPT ![i] = new]
|
||||||
|
// /\ UNCHANGED <<serverVars, commitIndex, messages>>
|
||||||
|
// \/ \* no conflict: append entry
|
||||||
|
// /\ m.mentries /= << >>
|
||||||
|
// /\ Len(log[i]) = m.mprevLogIndex
|
||||||
|
// /\ log' = [log EXCEPT ![i] =
|
||||||
|
// Append(log[i], m.mentries[1])]
|
||||||
|
// /\ UNCHANGED <<serverVars, commitIndex, messages>>
|
||||||
|
// /\ UNCHANGED <<candidateVars, leaderVars>>
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* 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 "syncAppendEntriesReply.h"
|
||||||
|
#include "sync.h"
|
||||||
|
|
||||||
|
void onAppendEntriesReply(SRaft *pRaft, const SyncAppendEntriesReply *pMsg) {
|
||||||
|
|
||||||
|
// TLA+ Spec
|
||||||
|
//HandleAppendEntriesResponse(i, j, m) ==
|
||||||
|
// /\ m.mterm = currentTerm[i]
|
||||||
|
// /\ \/ /\ m.msuccess \* successful
|
||||||
|
// /\ nextIndex' = [nextIndex EXCEPT ![i][j] = m.mmatchIndex + 1]
|
||||||
|
// /\ matchIndex' = [matchIndex EXCEPT ![i][j] = m.mmatchIndex]
|
||||||
|
// \/ /\ \lnot m.msuccess \* not successful
|
||||||
|
// /\ nextIndex' = [nextIndex EXCEPT ![i][j] =
|
||||||
|
// Max({nextIndex[i][j] - 1, 1})]
|
||||||
|
// /\ UNCHANGED <<matchIndex>>
|
||||||
|
// /\ Discard(m)
|
||||||
|
// /\ UNCHANGED <<serverVars, candidateVars, logVars, elections>>
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* 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 "sync.h"
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* 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 <stdint.h>
|
||||||
|
#include "sync.h"
|
||||||
|
#include "syncInt.h"
|
||||||
|
|
||||||
|
int32_t syncInit() { return 0; }
|
||||||
|
|
||||||
|
void syncCleanUp() {}
|
||||||
|
|
||||||
|
int64_t syncStart(const SSyncInfo* pSyncInfo) { return 0; }
|
||||||
|
|
||||||
|
void syncStop(int64_t rid) {}
|
||||||
|
|
||||||
|
int32_t syncReconfig(int64_t rid, const SSyncCfg* pSyncCfg) { return 0; }
|
||||||
|
|
||||||
|
int32_t syncForwardToPeer(int64_t rid, const SSyncBuffer* pBuf, bool isWeak) { return 0; }
|
||||||
|
|
||||||
|
ESyncState syncGetMyRole(int64_t rid) { return TAOS_SYNC_STATE_LEADER; }
|
||||||
|
|
||||||
|
void syncGetNodesRole(int64_t rid, SNodesRole* pNodeRole) {}
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* 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 "syncMessage.h"
|
||||||
|
#include "sync.h"
|
||||||
|
#include "syncRaft.h"
|
||||||
|
|
||||||
|
void onMessage(SRaft *pRaft, void *pMsg) {}
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* 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 "sync.h"
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* 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 "syncRaft.h"
|
||||||
|
#include "sync.h"
|
||||||
|
|
||||||
|
int32_t raftPropose(SRaft* pRaft, const SSyncBuffer* pBuf, bool isWeak) { return 0; }
|
||||||
|
|
||||||
|
static int raftSendMsg(SRaftId destRaftId, const void* pMsg, const SRaft* pRaft) { return 0; }
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* 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 "sync.h"
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* 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 "syncRaftLog.h"
|
||||||
|
#include "sync.h"
|
||||||
|
|
||||||
|
int32_t raftLogAppendEntry(struct SSyncLogStore* pLogStore, SSyncBuffer* pBuf) { return 0; }
|
||||||
|
|
||||||
|
// get one log entry, user need to free pBuf->data
|
||||||
|
int32_t raftLogGetEntry(struct SSyncLogStore* pLogStore, SyncIndex index, SSyncBuffer* pBuf) { return 0; }
|
||||||
|
|
||||||
|
// update log store commit index with "index"
|
||||||
|
int32_t raftLogupdateCommitIndex(struct SSyncLogStore* pLogStore, SyncIndex index) { return 0; }
|
||||||
|
|
||||||
|
// truncate log with index, entries after the given index (>index) will be deleted
|
||||||
|
int32_t raftLogTruncate(struct SSyncLogStore* pLogStore, SyncIndex index) { return 0; }
|
||||||
|
|
||||||
|
// return commit index of log
|
||||||
|
SyncIndex raftLogGetCommitIndex(struct SSyncLogStore* pLogStore) { return 0; }
|
||||||
|
|
||||||
|
// return index of last entry
|
||||||
|
SyncIndex raftLogGetLastIndex(struct SSyncLogStore* pLogStore) { return 0; }
|
||||||
|
|
||||||
|
// return term of last entry
|
||||||
|
SyncTerm raftLogGetLastTerm(struct SSyncLogStore* pLogStore) { return 0; }
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* 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 "syncRaftStore.h"
|
||||||
|
#include "sync.h"
|
||||||
|
|
||||||
|
int32_t currentTerm(SyncTerm *pCurrentTerm) { return 0; }
|
||||||
|
|
||||||
|
int32_t persistCurrentTerm(SyncTerm currentTerm) { return 0; }
|
||||||
|
|
||||||
|
int32_t voteFor(SRaftId *pRaftId) { return 0; }
|
||||||
|
|
||||||
|
int32_t persistVoteFor(SRaftId *pRaftId) { return 0; }
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* 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 "sync.h"
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* 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 "syncRequestVote.h"
|
||||||
|
#include "sync.h"
|
||||||
|
|
||||||
|
void requestVote(SRaft *pRaft, const SyncRequestVote *pMsg) {
|
||||||
|
|
||||||
|
// TLA+ Spec
|
||||||
|
//RequestVote(i, j) ==
|
||||||
|
// /\ state[i] = Candidate
|
||||||
|
// /\ j \notin votesResponded[i]
|
||||||
|
// /\ Send([mtype |-> RequestVoteRequest,
|
||||||
|
// mterm |-> currentTerm[i],
|
||||||
|
// mlastLogTerm |-> LastTerm(log[i]),
|
||||||
|
// mlastLogIndex |-> Len(log[i]),
|
||||||
|
// msource |-> i,
|
||||||
|
// mdest |-> j])
|
||||||
|
// /\ UNCHANGED <<serverVars, candidateVars, leaderVars, logVars>>
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void onRequestVote(SRaft *pRaft, const SyncRequestVote *pMsg) {
|
||||||
|
|
||||||
|
// TLA+ Spec
|
||||||
|
//HandleRequestVoteRequest(i, j, m) ==
|
||||||
|
// LET logOk == \/ m.mlastLogTerm > LastTerm(log[i])
|
||||||
|
// \/ /\ m.mlastLogTerm = LastTerm(log[i])
|
||||||
|
// /\ m.mlastLogIndex >= Len(log[i])
|
||||||
|
// grant == /\ m.mterm = currentTerm[i]
|
||||||
|
// /\ logOk
|
||||||
|
// /\ votedFor[i] \in {Nil, j}
|
||||||
|
// IN /\ m.mterm <= currentTerm[i]
|
||||||
|
// /\ \/ grant /\ votedFor' = [votedFor EXCEPT ![i] = j]
|
||||||
|
// \/ ~grant /\ UNCHANGED votedFor
|
||||||
|
// /\ Reply([mtype |-> RequestVoteResponse,
|
||||||
|
// mterm |-> currentTerm[i],
|
||||||
|
// mvoteGranted |-> grant,
|
||||||
|
// \* mlog is used just for the `elections' history variable for
|
||||||
|
// \* the proof. It would not exist in a real implementation.
|
||||||
|
// mlog |-> log[i],
|
||||||
|
// msource |-> i,
|
||||||
|
// mdest |-> j],
|
||||||
|
// m)
|
||||||
|
// /\ UNCHANGED <<state, currentTerm, candidateVars, leaderVars, logVars>>
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* 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 "syncRequestVoteReply.h"
|
||||||
|
#include "sync.h"
|
||||||
|
|
||||||
|
void onRequestVoteReply(SRaft *pRaft, const SyncRequestVoteReply *pMsg) {
|
||||||
|
|
||||||
|
// TLA+ Spec
|
||||||
|
//HandleRequestVoteResponse(i, j, m) ==
|
||||||
|
// \* This tallies votes even when the current state is not Candidate, but
|
||||||
|
// \* they won't be looked at, so it doesn't matter.
|
||||||
|
// /\ m.mterm = currentTerm[i]
|
||||||
|
// /\ votesResponded' = [votesResponded EXCEPT ![i] =
|
||||||
|
// votesResponded[i] \cup {j}]
|
||||||
|
// /\ \/ /\ m.mvoteGranted
|
||||||
|
// /\ votesGranted' = [votesGranted EXCEPT ![i] =
|
||||||
|
// votesGranted[i] \cup {j}]
|
||||||
|
// /\ voterLog' = [voterLog EXCEPT ![i] =
|
||||||
|
// voterLog[i] @@ (j :> m.mlog)]
|
||||||
|
// \/ /\ ~m.mvoteGranted
|
||||||
|
// /\ UNCHANGED <<votesGranted, voterLog>>
|
||||||
|
// /\ Discard(m)
|
||||||
|
// /\ UNCHANGED <<serverVars, votedFor, leaderVars, logVars>>
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* 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 "syncSnapshot.h"
|
||||||
|
#include "sync.h"
|
||||||
|
#include "syncRaft.h"
|
||||||
|
|
||||||
|
int32_t takeSnapshot(SSyncFSM *pFsm, SSnapshot *pSnapshot) { return 0; }
|
||||||
|
|
||||||
|
int32_t restoreSnapshot(SSyncFSM *pFsm, SSnapshot *pSnapshot) { return 0; }
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can use, redistribute, and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3
|
||||||
|
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "syncTimeout.h"
|
||||||
|
#include "sync.h"
|
||||||
|
|
||||||
|
void onTimeout(SRaft *pRaft, void *pMsg) {}
|
|
@ -0,0 +1,7 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
printf("test \n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -217,7 +217,7 @@ typedef struct SConnBuffer {
|
||||||
char* buf;
|
char* buf;
|
||||||
int len;
|
int len;
|
||||||
int cap;
|
int cap;
|
||||||
int left;
|
int total;
|
||||||
} SConnBuffer;
|
} SConnBuffer;
|
||||||
|
|
||||||
typedef void (*AsyncCB)(uv_async_t* handle);
|
typedef void (*AsyncCB)(uv_async_t* handle);
|
||||||
|
@ -238,10 +238,11 @@ SAsyncPool* transCreateAsyncPool(uv_loop_t* loop, int sz, void* arg, AsyncCB cb)
|
||||||
void transDestroyAsyncPool(SAsyncPool* pool);
|
void transDestroyAsyncPool(SAsyncPool* pool);
|
||||||
int transSendAsync(SAsyncPool* pool, queue* mq);
|
int transSendAsync(SAsyncPool* pool, queue* mq);
|
||||||
|
|
||||||
int transInitBuffer(SConnBuffer* buf);
|
int transInitBuffer(SConnBuffer* buf);
|
||||||
int transClearBuffer(SConnBuffer* buf);
|
int transClearBuffer(SConnBuffer* buf);
|
||||||
int transDestroyBuffer(SConnBuffer* buf);
|
int transDestroyBuffer(SConnBuffer* buf);
|
||||||
int transAllocBuffer(SConnBuffer* connBuf, uv_buf_t* uvBuf);
|
int transAllocBuffer(SConnBuffer* connBuf, uv_buf_t* uvBuf);
|
||||||
|
bool transReadComplete(SConnBuffer* connBuf);
|
||||||
|
|
||||||
// int transPackMsg(SRpcMsg *rpcMsg, bool sercured, bool auth, char **msg, int32_t *msgLen);
|
// int transPackMsg(SRpcMsg *rpcMsg, bool sercured, bool auth, char **msg, int32_t *msgLen);
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,7 @@ typedef struct {
|
||||||
int8_t connType;
|
int8_t connType;
|
||||||
int64_t index;
|
int64_t index;
|
||||||
char label[TSDB_LABEL_LEN];
|
char label[TSDB_LABEL_LEN];
|
||||||
|
bool noPool; // pool or not
|
||||||
|
|
||||||
char user[TSDB_UNI_LEN]; // meter ID
|
char user[TSDB_UNI_LEN]; // meter ID
|
||||||
char spi; // security parameter index
|
char spi; // security parameter index
|
||||||
|
|
|
@ -64,6 +64,7 @@ typedef struct {
|
||||||
void (*cfp)(void *parent, SRpcMsg *, SEpSet *);
|
void (*cfp)(void *parent, SRpcMsg *, SEpSet *);
|
||||||
int (*afp)(void *parent, char *user, char *spi, char *encrypt, char *secret, char *ckey);
|
int (*afp)(void *parent, char *user, char *spi, char *encrypt, char *secret, char *ckey);
|
||||||
|
|
||||||
|
bool noPool;
|
||||||
int32_t refCount;
|
int32_t refCount;
|
||||||
void * parent;
|
void * parent;
|
||||||
void * idPool; // handle to ID pool
|
void * idPool; // handle to ID pool
|
||||||
|
|
|
@ -27,7 +27,7 @@ void* rpcOpen(const SRpcInit* pInit) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (pInit->label) {
|
if (pInit->label) {
|
||||||
tstrncpy(pRpc->label, pInit->label, strlen(pInit->label));
|
tstrncpy(pRpc->label, pInit->label, strlen(pInit->label) + 1);
|
||||||
}
|
}
|
||||||
pRpc->cfp = pInit->cfp;
|
pRpc->cfp = pInit->cfp;
|
||||||
if (pInit->connType == TAOS_CONN_SERVER) {
|
if (pInit->connType == TAOS_CONN_SERVER) {
|
||||||
|
@ -35,6 +35,8 @@ void* rpcOpen(const SRpcInit* pInit) {
|
||||||
} else {
|
} else {
|
||||||
pRpc->numOfThreads = pInit->numOfThreads;
|
pRpc->numOfThreads = pInit->numOfThreads;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pRpc->noPool = pInit->noPool;
|
||||||
pRpc->connType = pInit->connType;
|
pRpc->connType = pInit->connType;
|
||||||
pRpc->idleTime = pInit->idleTime;
|
pRpc->idleTime = pInit->idleTime;
|
||||||
pRpc->tcphandle = (*taosInitHandle[pRpc->connType])(0, pInit->localPort, pRpc->label, pRpc->numOfThreads, NULL, pRpc);
|
pRpc->tcphandle = (*taosInitHandle[pRpc->connType])(0, pInit->localPort, pRpc->label, pRpc->numOfThreads, NULL, pRpc);
|
||||||
|
|
|
@ -84,8 +84,6 @@ static void addConnToPool(void* pool, char* ip, uint32_t port, SCliConn* co
|
||||||
|
|
||||||
// register timer in each thread to clear expire conn
|
// register timer in each thread to clear expire conn
|
||||||
static void clientTimeoutCb(uv_timer_t* handle);
|
static void clientTimeoutCb(uv_timer_t* handle);
|
||||||
// check whether already read complete packet from server
|
|
||||||
static bool clientReadComplete(SConnBuffer* pBuf);
|
|
||||||
// alloc buf for read
|
// alloc buf for read
|
||||||
static void clientAllocBufferCb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf);
|
static void clientAllocBufferCb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf);
|
||||||
// callback after read nbytes from socket
|
// callback after read nbytes from socket
|
||||||
|
@ -126,6 +124,9 @@ static void clientHandleResp(SCliConn* conn) {
|
||||||
pHead->code = htonl(pHead->code);
|
pHead->code = htonl(pHead->code);
|
||||||
pHead->msgLen = htonl(pHead->msgLen);
|
pHead->msgLen = htonl(pHead->msgLen);
|
||||||
|
|
||||||
|
// buf's mem alread translated to rpcMsg.pCont
|
||||||
|
transClearBuffer(&conn->readBuf);
|
||||||
|
|
||||||
SRpcMsg rpcMsg;
|
SRpcMsg rpcMsg;
|
||||||
rpcMsg.contLen = transContLenFromMsg(pHead->msgLen);
|
rpcMsg.contLen = transContLenFromMsg(pHead->msgLen);
|
||||||
rpcMsg.pCont = transContFromHead((char*)pHead);
|
rpcMsg.pCont = transContFromHead((char*)pHead);
|
||||||
|
@ -134,15 +135,15 @@ static void clientHandleResp(SCliConn* conn) {
|
||||||
rpcMsg.ahandle = pCtx->ahandle;
|
rpcMsg.ahandle = pCtx->ahandle;
|
||||||
|
|
||||||
if (rpcMsg.msgType == TDMT_VND_QUERY_RSP || rpcMsg.msgType == TDMT_VND_FETCH_RSP ||
|
if (rpcMsg.msgType == TDMT_VND_QUERY_RSP || rpcMsg.msgType == TDMT_VND_FETCH_RSP ||
|
||||||
rpcMsg.msgType == TDMT_VND_RES_READY) {
|
rpcMsg.msgType == TDMT_VND_RES_READY_RSP) {
|
||||||
rpcMsg.handle = conn;
|
rpcMsg.handle = conn;
|
||||||
conn->persist = 1;
|
conn->persist = 1;
|
||||||
tDebug("client conn %p persist by app", conn);
|
tDebug("client conn %p persist by app", conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
tDebug("client conn %p %s received from %s:%d, local info: %s:%d", conn, TMSG_INFO(pHead->msgType),
|
tDebug("%s client conn %p %s received from %s:%d, local info: %s:%d, msg size: %d", pRpc->label, conn,
|
||||||
inet_ntoa(conn->addr.sin_addr), ntohs(conn->addr.sin_port), inet_ntoa(conn->locaddr.sin_addr),
|
TMSG_INFO(pHead->msgType), inet_ntoa(conn->addr.sin_addr), ntohs(conn->addr.sin_port),
|
||||||
ntohs(conn->locaddr.sin_port));
|
inet_ntoa(conn->locaddr.sin_addr), ntohs(conn->locaddr.sin_port), rpcMsg.contLen);
|
||||||
|
|
||||||
conn->secured = pHead->secured;
|
conn->secured = pHead->secured;
|
||||||
if (conn->push != NULL && conn->ctnRdCnt != 0) {
|
if (conn->push != NULL && conn->ctnRdCnt != 0) {
|
||||||
|
@ -150,26 +151,26 @@ static void clientHandleResp(SCliConn* conn) {
|
||||||
conn->push = NULL;
|
conn->push = NULL;
|
||||||
} else {
|
} else {
|
||||||
if (pCtx->pSem == NULL) {
|
if (pCtx->pSem == NULL) {
|
||||||
tTrace("client conn %p handle resp", conn);
|
tTrace("%s client conn %p handle resp", pRpc->label, conn);
|
||||||
(pRpc->cfp)(pRpc->parent, &rpcMsg, NULL);
|
(pRpc->cfp)(pRpc->parent, &rpcMsg, NULL);
|
||||||
} else {
|
} else {
|
||||||
tTrace("client conn(sync) %p handle resp", conn);
|
tTrace("%s client conn(sync) %p handle resp", pRpc->label, conn);
|
||||||
memcpy((char*)pCtx->pRsp, (char*)&rpcMsg, sizeof(rpcMsg));
|
memcpy((char*)pCtx->pRsp, (char*)&rpcMsg, sizeof(rpcMsg));
|
||||||
tsem_post(pCtx->pSem);
|
tsem_post(pCtx->pSem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
conn->ctnRdCnt += 1;
|
conn->ctnRdCnt += 1;
|
||||||
|
|
||||||
// buf's mem alread translated to rpcMsg.pCont
|
|
||||||
transClearBuffer(&conn->readBuf);
|
|
||||||
|
|
||||||
uv_read_start((uv_stream_t*)conn->stream, clientAllocBufferCb, clientReadCb);
|
uv_read_start((uv_stream_t*)conn->stream, clientAllocBufferCb, clientReadCb);
|
||||||
|
|
||||||
SCliThrdObj* pThrd = conn->hostThrd;
|
SCliThrdObj* pThrd = conn->hostThrd;
|
||||||
|
|
||||||
// user owns conn->persist = 1
|
// user owns conn->persist = 1
|
||||||
if (conn->push == NULL && conn->persist == 0) {
|
if (conn->push == NULL && conn->persist == 0) {
|
||||||
addConnToPool(pThrd->pool, pCtx->ip, pCtx->port, conn);
|
if (pRpc->noPool == true) {
|
||||||
|
} else {
|
||||||
|
addConnToPool(pThrd->pool, pCtx->ip, pCtx->port, conn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
destroyCmsg(conn->data);
|
destroyCmsg(conn->data);
|
||||||
conn->data = NULL;
|
conn->data = NULL;
|
||||||
|
@ -184,7 +185,6 @@ static void clientHandleExcept(SCliConn* pConn) {
|
||||||
clientConnDestroy(pConn, true);
|
clientConnDestroy(pConn, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tTrace("client conn %p start to destroy", pConn);
|
|
||||||
SCliMsg* pMsg = pConn->data;
|
SCliMsg* pMsg = pConn->data;
|
||||||
|
|
||||||
tmsg_t msgType = TDMT_MND_CONNECT;
|
tmsg_t msgType = TDMT_MND_CONNECT;
|
||||||
|
@ -213,6 +213,7 @@ static void clientHandleExcept(SCliConn* pConn) {
|
||||||
}
|
}
|
||||||
pConn->push = NULL;
|
pConn->push = NULL;
|
||||||
}
|
}
|
||||||
|
tTrace("%s client conn %p start to destroy", pCtx->pTransInst->label, pConn);
|
||||||
if (pConn->push == NULL) {
|
if (pConn->push == NULL) {
|
||||||
destroyCmsg(pConn->data);
|
destroyCmsg(pConn->data);
|
||||||
pConn->data = NULL;
|
pConn->data = NULL;
|
||||||
|
@ -226,7 +227,7 @@ static void clientTimeoutCb(uv_timer_t* handle) {
|
||||||
SCliThrdObj* pThrd = handle->data;
|
SCliThrdObj* pThrd = handle->data;
|
||||||
SRpcInfo* pRpc = pThrd->pTransInst;
|
SRpcInfo* pRpc = pThrd->pTransInst;
|
||||||
int64_t currentTime = pThrd->nextTimeout;
|
int64_t currentTime = pThrd->nextTimeout;
|
||||||
tTrace("client conn timeout, try to remove expire conn from conn pool");
|
tTrace("%s, client conn timeout, try to remove expire conn from conn pool", pRpc->label);
|
||||||
|
|
||||||
SConnList* p = taosHashIterate((SHashObj*)pThrd->pool, NULL);
|
SConnList* p = taosHashIterate((SHashObj*)pThrd->pool, NULL);
|
||||||
while (p != NULL) {
|
while (p != NULL) {
|
||||||
|
@ -306,23 +307,6 @@ static void addConnToPool(void* pool, char* ip, uint32_t port, SCliConn* conn) {
|
||||||
assert(plist != NULL);
|
assert(plist != NULL);
|
||||||
QUEUE_PUSH(&plist->conn, &conn->conn);
|
QUEUE_PUSH(&plist->conn, &conn->conn);
|
||||||
}
|
}
|
||||||
static bool clientReadComplete(SConnBuffer* data) {
|
|
||||||
STransMsgHead head;
|
|
||||||
int32_t headLen = sizeof(head);
|
|
||||||
if (data->len >= headLen) {
|
|
||||||
memcpy((char*)&head, data->buf, headLen);
|
|
||||||
int32_t msgLen = (int32_t)htonl((uint32_t)head.msgLen);
|
|
||||||
if (msgLen > data->len) {
|
|
||||||
data->left = msgLen - data->len;
|
|
||||||
return false;
|
|
||||||
} else if (msgLen == data->len) {
|
|
||||||
data->left = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void clientAllocBufferCb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
|
static void clientAllocBufferCb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
|
||||||
SCliConn* conn = handle->data;
|
SCliConn* conn = handle->data;
|
||||||
SConnBuffer* pBuf = &conn->readBuf;
|
SConnBuffer* pBuf = &conn->readBuf;
|
||||||
|
@ -337,8 +321,7 @@ static void clientReadCb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf
|
||||||
SConnBuffer* pBuf = &conn->readBuf;
|
SConnBuffer* pBuf = &conn->readBuf;
|
||||||
if (nread > 0) {
|
if (nread > 0) {
|
||||||
pBuf->len += nread;
|
pBuf->len += nread;
|
||||||
if (clientReadComplete(pBuf)) {
|
if (transReadComplete(pBuf)) {
|
||||||
uv_read_stop((uv_stream_t*)conn->stream);
|
|
||||||
tTrace("client conn %p read complete", conn);
|
tTrace("client conn %p read complete", conn);
|
||||||
clientHandleResp(conn);
|
clientHandleResp(conn);
|
||||||
} else {
|
} else {
|
||||||
|
@ -346,6 +329,10 @@ static void clientReadCb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (nread == UV_EOF) {
|
||||||
|
tError("client conn %p read error: %s", conn, uv_err_name(nread));
|
||||||
|
clientHandleExcept(conn);
|
||||||
|
}
|
||||||
assert(nread <= 0);
|
assert(nread <= 0);
|
||||||
if (nread == 0) {
|
if (nread == 0) {
|
||||||
// ref http://docs.libuv.org/en/v1.x/stream.html?highlight=uv_read_start#c.uv_read_cb
|
// ref http://docs.libuv.org/en/v1.x/stream.html?highlight=uv_read_start#c.uv_read_cb
|
||||||
|
@ -353,7 +340,7 @@ static void clientReadCb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf
|
||||||
// read(2).
|
// read(2).
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (nread < 0 || nread == UV_EOF) {
|
if (nread < 0) {
|
||||||
tError("client conn %p read error: %s", conn, uv_err_name(nread));
|
tError("client conn %p read error: %s", conn, uv_err_name(nread));
|
||||||
clientHandleExcept(conn);
|
clientHandleExcept(conn);
|
||||||
}
|
}
|
||||||
|
@ -467,6 +454,7 @@ static void clientConnCb(uv_connect_t* req, int status) {
|
||||||
static void clientHandleQuit(SCliMsg* pMsg, SCliThrdObj* pThrd) {
|
static void clientHandleQuit(SCliMsg* pMsg, SCliThrdObj* pThrd) {
|
||||||
tDebug("client work thread %p start to quit", pThrd);
|
tDebug("client work thread %p start to quit", pThrd);
|
||||||
destroyCmsg(pMsg);
|
destroyCmsg(pMsg);
|
||||||
|
destroyConnPool(pThrd->pool);
|
||||||
// transDestroyAsyncPool(pThr) uv_close((uv_handle_t*)pThrd->cliAsync, NULL);
|
// transDestroyAsyncPool(pThr) uv_close((uv_handle_t*)pThrd->cliAsync, NULL);
|
||||||
uv_timer_stop(pThrd->timer);
|
uv_timer_stop(pThrd->timer);
|
||||||
pThrd->quit = true;
|
pThrd->quit = true;
|
||||||
|
@ -483,7 +471,10 @@ static void clientHandleReq(SCliMsg* pMsg, SCliThrdObj* pThrd) {
|
||||||
|
|
||||||
SCliConn* conn = NULL;
|
SCliConn* conn = NULL;
|
||||||
if (pMsg->msg.handle == NULL) {
|
if (pMsg->msg.handle == NULL) {
|
||||||
conn = getConnFromPool(pThrd->pool, pCtx->ip, pCtx->port);
|
if (pCtx->pTransInst->noPool == true) {
|
||||||
|
} else {
|
||||||
|
conn = getConnFromPool(pThrd->pool, pCtx->ip, pCtx->port);
|
||||||
|
}
|
||||||
if (conn != NULL) {
|
if (conn != NULL) {
|
||||||
tTrace("client conn %p get from conn pool", conn);
|
tTrace("client conn %p get from conn pool", conn);
|
||||||
}
|
}
|
||||||
|
@ -512,7 +503,11 @@ static void clientHandleReq(SCliMsg* pMsg, SCliThrdObj* pThrd) {
|
||||||
conn->stream = (uv_stream_t*)malloc(sizeof(uv_tcp_t));
|
conn->stream = (uv_stream_t*)malloc(sizeof(uv_tcp_t));
|
||||||
uv_tcp_init(pThrd->loop, (uv_tcp_t*)(conn->stream));
|
uv_tcp_init(pThrd->loop, (uv_tcp_t*)(conn->stream));
|
||||||
conn->stream->data = conn;
|
conn->stream->data = conn;
|
||||||
|
uv_tcp_nodelay((uv_tcp_t*)conn->stream, 1);
|
||||||
|
int ret = uv_tcp_keepalive((uv_tcp_t*)conn->stream, 1, 1);
|
||||||
|
if (ret) {
|
||||||
|
tTrace("client conn %p failed to set keepalive, %s", conn, uv_err_name(ret));
|
||||||
|
}
|
||||||
// write req handle
|
// write req handle
|
||||||
conn->writeReq = malloc(sizeof(uv_write_t));
|
conn->writeReq = malloc(sizeof(uv_write_t));
|
||||||
conn->writeReq->data = conn;
|
conn->writeReq->data = conn;
|
||||||
|
|
|
@ -205,6 +205,7 @@ int transInitBuffer(SConnBuffer* buf) {
|
||||||
}
|
}
|
||||||
int transClearBuffer(SConnBuffer* buf) {
|
int transClearBuffer(SConnBuffer* buf) {
|
||||||
memset(buf, 0, sizeof(*buf));
|
memset(buf, 0, sizeof(*buf));
|
||||||
|
buf->total = -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int transAllocBuffer(SConnBuffer* connBuf, uv_buf_t* uvBuf) {
|
int transAllocBuffer(SConnBuffer* connBuf, uv_buf_t* uvBuf) {
|
||||||
|
@ -214,32 +215,38 @@ int transAllocBuffer(SConnBuffer* connBuf, uv_buf_t* uvBuf) {
|
||||||
* |<------STransMsgHead------->|<-------------------userdata--------------->|<-----auth data----->|<----user
|
* |<------STransMsgHead------->|<-------------------userdata--------------->|<-----auth data----->|<----user
|
||||||
* info--->|
|
* info--->|
|
||||||
*/
|
*/
|
||||||
static const int CAPACITY = 1024;
|
static const int CAPACITY = sizeof(STransMsgHead);
|
||||||
|
|
||||||
SConnBuffer* p = connBuf;
|
SConnBuffer* p = connBuf;
|
||||||
if (p->cap == 0) {
|
if (p->cap == 0) {
|
||||||
p->buf = (char*)calloc(CAPACITY, sizeof(char));
|
p->buf = (char*)calloc(CAPACITY, sizeof(char));
|
||||||
p->len = 0;
|
p->len = 0;
|
||||||
p->cap = CAPACITY;
|
p->cap = CAPACITY;
|
||||||
p->left = -1;
|
p->total = -1;
|
||||||
|
|
||||||
uvBuf->base = p->buf;
|
uvBuf->base = p->buf;
|
||||||
uvBuf->len = CAPACITY;
|
uvBuf->len = CAPACITY;
|
||||||
} else {
|
} else {
|
||||||
if (p->len >= p->cap) {
|
p->cap = p->total;
|
||||||
if (p->left == -1) {
|
p->buf = realloc(p->buf, p->cap);
|
||||||
p->cap *= 2;
|
|
||||||
p->buf = realloc(p->buf, p->cap);
|
|
||||||
} else if (p->len + p->left > p->cap) {
|
|
||||||
p->cap = p->len + p->left;
|
|
||||||
p->buf = realloc(p->buf, p->len + p->left);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uvBuf->base = p->buf + p->len;
|
uvBuf->base = p->buf + p->len;
|
||||||
uvBuf->len = p->cap - p->len;
|
uvBuf->len = p->cap - p->len;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
// check whether already read complete
|
||||||
|
bool transReadComplete(SConnBuffer* connBuf) {
|
||||||
|
if (connBuf->total == -1 && connBuf->len >= sizeof(STransMsgHead)) {
|
||||||
|
STransMsgHead head;
|
||||||
|
memcpy((char*)&head, connBuf->buf, sizeof(head));
|
||||||
|
int32_t msgLen = (int32_t)htonl(head.msgLen);
|
||||||
|
connBuf->total = msgLen;
|
||||||
|
}
|
||||||
|
if (connBuf->len == connBuf->cap && connBuf->total == connBuf->cap) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
int transPackMsg(STransMsgHead* msgHead, bool sercured, bool auth) {}
|
int transPackMsg(STransMsgHead* msgHead, bool sercured, bool auth) {}
|
||||||
|
|
||||||
int transUnpackMsg(STransMsgHead* msgHead) {}
|
int transUnpackMsg(STransMsgHead* msgHead) {}
|
||||||
|
|
|
@ -61,6 +61,7 @@ typedef struct SWorkThrdObj {
|
||||||
SAsyncPool* asyncPool;
|
SAsyncPool* asyncPool;
|
||||||
// uv_async_t* workerAsync; //
|
// uv_async_t* workerAsync; //
|
||||||
queue msg;
|
queue msg;
|
||||||
|
queue conn;
|
||||||
pthread_mutex_t msgMtx;
|
pthread_mutex_t msgMtx;
|
||||||
void* pTransInst;
|
void* pTransInst;
|
||||||
} SWorkThrdObj;
|
} SWorkThrdObj;
|
||||||
|
@ -95,6 +96,7 @@ static void uvOnAcceptCb(uv_stream_t* stream, int status);
|
||||||
static void uvOnConnectionCb(uv_stream_t* q, ssize_t nread, const uv_buf_t* buf);
|
static void uvOnConnectionCb(uv_stream_t* q, ssize_t nread, const uv_buf_t* buf);
|
||||||
static void uvWorkerAsyncCb(uv_async_t* handle);
|
static void uvWorkerAsyncCb(uv_async_t* handle);
|
||||||
static void uvAcceptAsyncCb(uv_async_t* handle);
|
static void uvAcceptAsyncCb(uv_async_t* handle);
|
||||||
|
static void uvShutDownCb(uv_shutdown_t* req, int status);
|
||||||
|
|
||||||
static void uvStartSendRespInternal(SSrvMsg* smsg);
|
static void uvStartSendRespInternal(SSrvMsg* smsg);
|
||||||
static void uvPrepareSendData(SSrvMsg* msg, uv_buf_t* wb);
|
static void uvPrepareSendData(SSrvMsg* msg, uv_buf_t* wb);
|
||||||
|
@ -102,8 +104,7 @@ static void uvStartSendResp(SSrvMsg* msg);
|
||||||
|
|
||||||
static void destroySmsg(SSrvMsg* smsg);
|
static void destroySmsg(SSrvMsg* smsg);
|
||||||
// check whether already read complete packet
|
// check whether already read complete packet
|
||||||
static bool readComplete(SConnBuffer* buf);
|
static SSrvConn* createConn(void* hThrd);
|
||||||
static SSrvConn* createConn();
|
|
||||||
static void destroyConn(SSrvConn* conn, bool clear /*clear handle or not*/);
|
static void destroyConn(SSrvConn* conn, bool clear /*clear handle or not*/);
|
||||||
|
|
||||||
static void uvDestroyConn(uv_handle_t* handle);
|
static void uvDestroyConn(uv_handle_t* handle);
|
||||||
|
@ -117,51 +118,11 @@ static bool addHandleToWorkloop(void* arg);
|
||||||
static bool addHandleToAcceptloop(void* arg);
|
static bool addHandleToAcceptloop(void* arg);
|
||||||
|
|
||||||
void uvAllocReadBufferCb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
|
void uvAllocReadBufferCb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
|
||||||
/*
|
|
||||||
* formate of data buffer:
|
|
||||||
* |<--------------------------data from socket------------------------------->|
|
|
||||||
* |<------STransMsgHead------->|<-------------------other data--------------->|
|
|
||||||
*/
|
|
||||||
SSrvConn* conn = handle->data;
|
SSrvConn* conn = handle->data;
|
||||||
SConnBuffer* pBuf = &conn->readBuf;
|
SConnBuffer* pBuf = &conn->readBuf;
|
||||||
transAllocBuffer(pBuf, buf);
|
transAllocBuffer(pBuf, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check data read from socket complete or not
|
|
||||||
//
|
|
||||||
static bool readComplete(SConnBuffer* data) {
|
|
||||||
// TODO(yihao): handle pipeline later
|
|
||||||
STransMsgHead head;
|
|
||||||
int32_t headLen = sizeof(head);
|
|
||||||
if (data->len >= headLen) {
|
|
||||||
memcpy((char*)&head, data->buf, headLen);
|
|
||||||
int32_t msgLen = (int32_t)htonl((uint32_t)head.msgLen);
|
|
||||||
if (msgLen > data->len) {
|
|
||||||
data->left = msgLen - data->len;
|
|
||||||
return false;
|
|
||||||
} else if (msgLen == data->len) {
|
|
||||||
return true;
|
|
||||||
} else if (msgLen < data->len) {
|
|
||||||
return false;
|
|
||||||
// handle other packet later
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// static void uvDoProcess(SRecvInfo* pRecv) {
|
|
||||||
// // impl later
|
|
||||||
// STransMsgHead* pHead = (STransMsgHead*)pRecv->msg;
|
|
||||||
// SRpcInfo* pRpc = (SRpcInfo*)pRecv->shandle;
|
|
||||||
// SSrvConn* pConn = pRecv->thandle;
|
|
||||||
// tDump(pRecv->msg, pRecv->msgLen);
|
|
||||||
// terrno = 0;
|
|
||||||
// // SRpcReqContext* pContest;
|
|
||||||
//
|
|
||||||
// // do auth and check
|
|
||||||
//}
|
|
||||||
|
|
||||||
static int uvAuthMsg(SSrvConn* pConn, char* msg, int len) {
|
static int uvAuthMsg(SSrvConn* pConn, char* msg, int len) {
|
||||||
STransMsgHead* pHead = (STransMsgHead*)msg;
|
STransMsgHead* pHead = (STransMsgHead*)msg;
|
||||||
|
|
||||||
|
@ -241,7 +202,7 @@ static void uvHandleReq(SSrvConn* pConn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pConn->inType = pHead->msgType;
|
pConn->inType = pHead->msgType;
|
||||||
assert(transIsReq(pHead->msgType));
|
// assert(transIsReq(pHead->msgType));
|
||||||
|
|
||||||
SRpcInfo* pRpc = (SRpcInfo*)p->shandle;
|
SRpcInfo* pRpc = (SRpcInfo*)p->shandle;
|
||||||
pHead->code = htonl(pHead->code);
|
pHead->code = htonl(pHead->code);
|
||||||
|
@ -266,9 +227,9 @@ static void uvHandleReq(SSrvConn* pConn) {
|
||||||
|
|
||||||
transClearBuffer(&pConn->readBuf);
|
transClearBuffer(&pConn->readBuf);
|
||||||
pConn->ref++;
|
pConn->ref++;
|
||||||
tDebug("server conn %p %s received from %s:%d, local info: %s:%d", pConn, TMSG_INFO(rpcMsg.msgType),
|
tDebug("server conn %p %s received from %s:%d, local info: %s:%d, msg size: %d", pConn, TMSG_INFO(rpcMsg.msgType),
|
||||||
inet_ntoa(pConn->addr.sin_addr), ntohs(pConn->addr.sin_port), inet_ntoa(pConn->locaddr.sin_addr),
|
inet_ntoa(pConn->addr.sin_addr), ntohs(pConn->addr.sin_port), inet_ntoa(pConn->locaddr.sin_addr),
|
||||||
ntohs(pConn->locaddr.sin_port));
|
ntohs(pConn->locaddr.sin_port), rpcMsg.contLen);
|
||||||
(*(pRpc->cfp))(pRpc->parent, &rpcMsg, NULL);
|
(*(pRpc->cfp))(pRpc->parent, &rpcMsg, NULL);
|
||||||
// uv_timer_start(pConn->pTimer, uvHandleActivityTimeout, pRpc->idleTime * 10000, 0);
|
// uv_timer_start(pConn->pTimer, uvHandleActivityTimeout, pRpc->idleTime * 10000, 0);
|
||||||
// auth
|
// auth
|
||||||
|
@ -282,7 +243,7 @@ void uvOnReadCb(uv_stream_t* cli, ssize_t nread, const uv_buf_t* buf) {
|
||||||
if (nread > 0) {
|
if (nread > 0) {
|
||||||
pBuf->len += nread;
|
pBuf->len += nread;
|
||||||
tTrace("server conn %p read summary, total read: %d, current read: %d", conn, pBuf->len, (int)nread);
|
tTrace("server conn %p read summary, total read: %d, current read: %d", conn, pBuf->len, (int)nread);
|
||||||
if (readComplete(pBuf)) {
|
if (transReadComplete(pBuf)) {
|
||||||
tTrace("server conn %p alread read complete packet", conn);
|
tTrace("server conn %p alread read complete packet", conn);
|
||||||
uvHandleReq(conn);
|
uvHandleReq(conn);
|
||||||
} else {
|
} else {
|
||||||
|
@ -290,6 +251,14 @@ void uvOnReadCb(uv_stream_t* cli, ssize_t nread, const uv_buf_t* buf) {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (nread == UV_EOF) {
|
||||||
|
tError("server conn %p read error: %s", conn, uv_err_name(nread));
|
||||||
|
if (conn->ref > 1) {
|
||||||
|
conn->ref++; // ref > 1 signed that write is in progress
|
||||||
|
}
|
||||||
|
destroyConn(conn, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (nread == 0) {
|
if (nread == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -302,8 +271,8 @@ void uvOnReadCb(uv_stream_t* cli, ssize_t nread, const uv_buf_t* buf) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void uvAllocConnBufferCb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
|
void uvAllocConnBufferCb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
|
||||||
buf->base = malloc(sizeof(char));
|
|
||||||
buf->len = 2;
|
buf->len = 2;
|
||||||
|
buf->base = calloc(1, sizeof(char) * buf->len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void uvOnTimeoutCb(uv_timer_t* handle) {
|
void uvOnTimeoutCb(uv_timer_t* handle) {
|
||||||
|
@ -386,6 +355,7 @@ static void uvStartSendRespInternal(SSrvMsg* smsg) {
|
||||||
static void uvStartSendResp(SSrvMsg* smsg) {
|
static void uvStartSendResp(SSrvMsg* smsg) {
|
||||||
// impl
|
// impl
|
||||||
SSrvConn* pConn = smsg->pConn;
|
SSrvConn* pConn = smsg->pConn;
|
||||||
|
pConn->ref--; //
|
||||||
if (taosArrayGetSize(pConn->srvMsgs) > 0) {
|
if (taosArrayGetSize(pConn->srvMsgs) > 0) {
|
||||||
tDebug("server conn %p push data to client %s:%d, local info: %s:%d", pConn, inet_ntoa(pConn->addr.sin_addr),
|
tDebug("server conn %p push data to client %s:%d, local info: %s:%d", pConn, inet_ntoa(pConn->addr.sin_addr),
|
||||||
ntohs(pConn->addr.sin_port), inet_ntoa(pConn->locaddr.sin_addr), ntohs(pConn->locaddr.sin_port));
|
ntohs(pConn->addr.sin_port), inet_ntoa(pConn->locaddr.sin_addr), ntohs(pConn->locaddr.sin_port));
|
||||||
|
@ -403,6 +373,16 @@ static void destroySmsg(SSrvMsg* smsg) {
|
||||||
transFreeMsg(smsg->msg.pCont);
|
transFreeMsg(smsg->msg.pCont);
|
||||||
free(smsg);
|
free(smsg);
|
||||||
}
|
}
|
||||||
|
static void destroyAllConn(SWorkThrdObj* pThrd) {
|
||||||
|
while (!QUEUE_IS_EMPTY(&pThrd->conn)) {
|
||||||
|
queue* h = QUEUE_HEAD(&pThrd->conn);
|
||||||
|
QUEUE_REMOVE(h);
|
||||||
|
QUEUE_INIT(h);
|
||||||
|
|
||||||
|
SSrvConn* c = QUEUE_DATA(h, SSrvConn, queue);
|
||||||
|
destroyConn(c, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
void uvWorkerAsyncCb(uv_async_t* handle) {
|
void uvWorkerAsyncCb(uv_async_t* handle) {
|
||||||
SAsyncItem* item = handle->data;
|
SAsyncItem* item = handle->data;
|
||||||
SWorkThrdObj* pThrd = item->pThrd;
|
SWorkThrdObj* pThrd = item->pThrd;
|
||||||
|
@ -424,8 +404,11 @@ void uvWorkerAsyncCb(uv_async_t* handle) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (msg->pConn == NULL) {
|
if (msg->pConn == NULL) {
|
||||||
//
|
|
||||||
free(msg);
|
free(msg);
|
||||||
|
|
||||||
|
destroyAllConn(pThrd);
|
||||||
|
|
||||||
|
uv_loop_close(pThrd->loop);
|
||||||
uv_stop(pThrd->loop);
|
uv_stop(pThrd->loop);
|
||||||
} else {
|
} else {
|
||||||
uvStartSendResp(msg);
|
uvStartSendResp(msg);
|
||||||
|
@ -439,9 +422,16 @@ void uvWorkerAsyncCb(uv_async_t* handle) {
|
||||||
}
|
}
|
||||||
static void uvAcceptAsyncCb(uv_async_t* async) {
|
static void uvAcceptAsyncCb(uv_async_t* async) {
|
||||||
SServerObj* srv = async->data;
|
SServerObj* srv = async->data;
|
||||||
|
uv_close((uv_handle_t*)&srv->server, NULL);
|
||||||
uv_stop(srv->loop);
|
uv_stop(srv->loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void uvShutDownCb(uv_shutdown_t* req, int status) {
|
||||||
|
tDebug("conn failed to shut down: %s", uv_err_name(status));
|
||||||
|
uv_close((uv_handle_t*)req->handle, uvDestroyConn);
|
||||||
|
free(req);
|
||||||
|
}
|
||||||
|
|
||||||
void uvOnAcceptCb(uv_stream_t* stream, int status) {
|
void uvOnAcceptCb(uv_stream_t* stream, int status) {
|
||||||
if (status == -1) {
|
if (status == -1) {
|
||||||
return;
|
return;
|
||||||
|
@ -491,7 +481,7 @@ void uvOnConnectionCb(uv_stream_t* q, ssize_t nread, const uv_buf_t* buf) {
|
||||||
uv_handle_type pending = uv_pipe_pending_type(pipe);
|
uv_handle_type pending = uv_pipe_pending_type(pipe);
|
||||||
assert(pending == UV_TCP);
|
assert(pending == UV_TCP);
|
||||||
|
|
||||||
SSrvConn* pConn = createConn();
|
SSrvConn* pConn = createConn(pThrd);
|
||||||
|
|
||||||
pConn->pTransInst = pThrd->pTransInst;
|
pConn->pTransInst = pThrd->pTransInst;
|
||||||
/* init conn timer*/
|
/* init conn timer*/
|
||||||
|
@ -507,6 +497,9 @@ void uvOnConnectionCb(uv_stream_t* q, ssize_t nread, const uv_buf_t* buf) {
|
||||||
uv_tcp_init(pThrd->loop, pConn->pTcp);
|
uv_tcp_init(pThrd->loop, pConn->pTcp);
|
||||||
pConn->pTcp->data = pConn;
|
pConn->pTcp->data = pConn;
|
||||||
|
|
||||||
|
// uv_tcp_nodelay(pConn->pTcp, 1);
|
||||||
|
// uv_tcp_keepalive(pConn->pTcp, 1, 1);
|
||||||
|
|
||||||
// init write request, just
|
// init write request, just
|
||||||
pConn->pWriter = calloc(1, sizeof(uv_write_t));
|
pConn->pWriter = calloc(1, sizeof(uv_write_t));
|
||||||
pConn->pWriter->data = pConn;
|
pConn->pWriter->data = pConn;
|
||||||
|
@ -560,6 +553,9 @@ static bool addHandleToWorkloop(void* arg) {
|
||||||
QUEUE_INIT(&pThrd->msg);
|
QUEUE_INIT(&pThrd->msg);
|
||||||
pthread_mutex_init(&pThrd->msgMtx, NULL);
|
pthread_mutex_init(&pThrd->msgMtx, NULL);
|
||||||
|
|
||||||
|
// conn set
|
||||||
|
QUEUE_INIT(&pThrd->conn);
|
||||||
|
|
||||||
pThrd->asyncPool = transCreateAsyncPool(pThrd->loop, 4, pThrd, uvWorkerAsyncCb);
|
pThrd->asyncPool = transCreateAsyncPool(pThrd->loop, 4, pThrd, uvWorkerAsyncCb);
|
||||||
uv_read_start((uv_stream_t*)pThrd->pipe, uvAllocConnBufferCb, uvOnConnectionCb);
|
uv_read_start((uv_stream_t*)pThrd->pipe, uvAllocConnBufferCb, uvOnConnectionCb);
|
||||||
return true;
|
return true;
|
||||||
|
@ -598,8 +594,13 @@ void* workerThread(void* arg) {
|
||||||
uv_run(pThrd->loop, UV_RUN_DEFAULT);
|
uv_run(pThrd->loop, UV_RUN_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SSrvConn* createConn() {
|
static SSrvConn* createConn(void* hThrd) {
|
||||||
|
SWorkThrdObj* pThrd = hThrd;
|
||||||
|
|
||||||
SSrvConn* pConn = (SSrvConn*)calloc(1, sizeof(SSrvConn));
|
SSrvConn* pConn = (SSrvConn*)calloc(1, sizeof(SSrvConn));
|
||||||
|
QUEUE_INIT(&pConn->queue);
|
||||||
|
|
||||||
|
QUEUE_PUSH(&pThrd->conn, &pConn->queue);
|
||||||
pConn->srvMsgs = taosArrayInit(2, sizeof(void*)); //
|
pConn->srvMsgs = taosArrayInit(2, sizeof(void*)); //
|
||||||
tTrace("conn %p created", pConn);
|
tTrace("conn %p created", pConn);
|
||||||
++pConn->ref;
|
++pConn->ref;
|
||||||
|
@ -610,7 +611,7 @@ static void destroyConn(SSrvConn* conn, bool clear) {
|
||||||
if (conn == NULL) {
|
if (conn == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tTrace("server conn %p try to destroy", conn);
|
tTrace("server conn %p try to destroy, ref: %d", conn, conn->ref);
|
||||||
if (--conn->ref > 0) {
|
if (--conn->ref > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -621,20 +622,23 @@ static void destroyConn(SSrvConn* conn, bool clear) {
|
||||||
destroySmsg(msg);
|
destroySmsg(msg);
|
||||||
}
|
}
|
||||||
taosArrayDestroy(conn->srvMsgs);
|
taosArrayDestroy(conn->srvMsgs);
|
||||||
|
QUEUE_REMOVE(&conn->queue);
|
||||||
// destroySmsg(conn->pSrvMsg);
|
|
||||||
// conn->pSrvMsg = NULL;
|
|
||||||
|
|
||||||
if (clear) {
|
if (clear) {
|
||||||
uv_close((uv_handle_t*)conn->pTcp, uvDestroyConn);
|
tTrace("try to destroy conn %p", conn);
|
||||||
|
uv_tcp_close_reset(conn->pTcp, uvDestroyConn);
|
||||||
|
// uv_shutdown_t* req = malloc(sizeof(uv_shutdown_t));
|
||||||
|
// uv_shutdown(req, (uv_stream_t*)conn->pTcp, uvShutDownCb);
|
||||||
|
// uv_unref((uv_handle_t*)conn->pTcp);
|
||||||
|
// uv_close((uv_handle_t*)conn->pTcp, uvDestroyConn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void uvDestroyConn(uv_handle_t* handle) {
|
static void uvDestroyConn(uv_handle_t* handle) {
|
||||||
SSrvConn* conn = handle->data;
|
SSrvConn* conn = handle->data;
|
||||||
tDebug("server conn %p destroy", conn);
|
tDebug("server conn %p destroy", conn);
|
||||||
uv_timer_stop(conn->pTimer);
|
uv_timer_stop(conn->pTimer);
|
||||||
free(conn->pTimer);
|
// free(conn->pTimer);
|
||||||
// free(conn->pTcp);
|
free(conn->pTcp);
|
||||||
free(conn->pWriter);
|
free(conn->pWriter);
|
||||||
free(conn);
|
free(conn);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,69 +16,168 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "tep.h"
|
#include "tep.h"
|
||||||
|
#include "tglobal.h"
|
||||||
#include "trpc.h"
|
#include "trpc.h"
|
||||||
|
#include "ulog.h"
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
class TransObj {
|
const char *label = "APP";
|
||||||
public:
|
const char *secret = "secret";
|
||||||
TransObj() {
|
const char *user = "user";
|
||||||
const char *label = "APP";
|
const char *ckey = "ckey";
|
||||||
const char *secret = "secret";
|
|
||||||
const char *user = "user";
|
|
||||||
const char *ckey = "ckey";
|
|
||||||
|
|
||||||
|
class Server;
|
||||||
|
int port = 7000;
|
||||||
|
// server process
|
||||||
|
static void processReq(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet);
|
||||||
|
// client process;
|
||||||
|
static void processResp(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet);
|
||||||
|
class Client {
|
||||||
|
public:
|
||||||
|
void Init(int nThread) {
|
||||||
memset(&rpcInit, 0, sizeof(rpcInit));
|
memset(&rpcInit, 0, sizeof(rpcInit));
|
||||||
rpcInit.localPort = 0;
|
rpcInit.localPort = 0;
|
||||||
rpcInit.label = (char *)label;
|
rpcInit.label = (char *)label;
|
||||||
rpcInit.numOfThreads = 5;
|
rpcInit.numOfThreads = nThread;
|
||||||
rpcInit.cfp = NULL;
|
rpcInit.cfp = processResp;
|
||||||
rpcInit.sessions = 100;
|
|
||||||
rpcInit.idleTime = 100;
|
|
||||||
rpcInit.user = (char *)user;
|
rpcInit.user = (char *)user;
|
||||||
rpcInit.secret = (char *)secret;
|
rpcInit.secret = (char *)secret;
|
||||||
rpcInit.ckey = (char *)ckey;
|
rpcInit.ckey = (char *)ckey;
|
||||||
rpcInit.spi = 1;
|
rpcInit.spi = 1;
|
||||||
}
|
rpcInit.parent = this;
|
||||||
bool startCli() {
|
|
||||||
trans = NULL;
|
|
||||||
rpcInit.connType = TAOS_CONN_CLIENT;
|
rpcInit.connType = TAOS_CONN_CLIENT;
|
||||||
trans = rpcOpen(&rpcInit);
|
this->transCli = rpcOpen(&rpcInit);
|
||||||
return trans != NULL ? true : false;
|
tsem_init(&this->sem, 0, 0);
|
||||||
}
|
}
|
||||||
bool startSrv() {
|
void SetResp(SRpcMsg *pMsg) {
|
||||||
trans = NULL;
|
// set up resp;
|
||||||
rpcInit.connType = TAOS_CONN_SERVER;
|
this->resp = *pMsg;
|
||||||
trans = rpcOpen(&rpcInit);
|
}
|
||||||
return trans != NULL ? true : false;
|
SRpcMsg *Resp() { return &this->resp; }
|
||||||
|
|
||||||
|
void Restart() {
|
||||||
|
rpcClose(this->transCli);
|
||||||
|
this->transCli = rpcOpen(&rpcInit);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sendAndRecv() {
|
void SendAndRecv(SRpcMsg *req, SRpcMsg *resp) {
|
||||||
SEpSet epSet = {0};
|
SEpSet epSet = {0};
|
||||||
epSet.inUse = 0;
|
epSet.inUse = 0;
|
||||||
addEpIntoEpSet(&epSet, "192.168.1.1", 7000);
|
addEpIntoEpSet(&epSet, "127.0.0.1", 7000);
|
||||||
addEpIntoEpSet(&epSet, "192.168.0.1", 7000);
|
|
||||||
|
|
||||||
if (trans == NULL) {
|
rpcSendRequest(this->transCli, &epSet, req, NULL);
|
||||||
return false;
|
SemWait();
|
||||||
}
|
*resp = this->resp;
|
||||||
SRpcMsg rpcMsg = {0}, reqMsg = {0};
|
|
||||||
reqMsg.pCont = rpcMallocCont(10);
|
|
||||||
reqMsg.contLen = 10;
|
|
||||||
reqMsg.ahandle = NULL;
|
|
||||||
rpcSendRecv(trans, &epSet, &reqMsg, &rpcMsg);
|
|
||||||
int code = rpcMsg.code;
|
|
||||||
std::cout << tstrerror(code) << std::endl;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
bool stop() {
|
void SemWait() { tsem_wait(&this->sem); }
|
||||||
rpcClose(trans);
|
void SemPost() { tsem_post(&this->sem); }
|
||||||
trans = NULL;
|
void Reset() {}
|
||||||
return true;
|
|
||||||
|
~Client() {
|
||||||
|
if (this->transCli) rpcClose(this->transCli);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void * trans;
|
tsem_t sem;
|
||||||
SRpcInit rpcInit;
|
SRpcInit rpcInit;
|
||||||
|
void * transCli;
|
||||||
|
SRpcMsg resp;
|
||||||
|
};
|
||||||
|
class Server {
|
||||||
|
public:
|
||||||
|
Server() {
|
||||||
|
memset(&rpcInit, 0, sizeof(rpcInit));
|
||||||
|
rpcInit.localPort = port;
|
||||||
|
rpcInit.label = (char *)label;
|
||||||
|
rpcInit.numOfThreads = 5;
|
||||||
|
rpcInit.cfp = processReq;
|
||||||
|
rpcInit.user = (char *)user;
|
||||||
|
rpcInit.secret = (char *)secret;
|
||||||
|
rpcInit.ckey = (char *)ckey;
|
||||||
|
rpcInit.spi = 1;
|
||||||
|
rpcInit.connType = TAOS_CONN_SERVER;
|
||||||
|
}
|
||||||
|
void Start() {
|
||||||
|
this->transSrv = rpcOpen(&this->rpcInit);
|
||||||
|
taosMsleep(1000);
|
||||||
|
}
|
||||||
|
void Stop() {
|
||||||
|
if (this->transSrv == NULL) return;
|
||||||
|
rpcClose(this->transSrv);
|
||||||
|
this->transSrv = NULL;
|
||||||
|
}
|
||||||
|
void Restart() {
|
||||||
|
this->Stop();
|
||||||
|
this->Start();
|
||||||
|
}
|
||||||
|
~Server() {
|
||||||
|
if (this->transSrv) rpcClose(this->transSrv);
|
||||||
|
this->transSrv = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SRpcInit rpcInit;
|
||||||
|
void * transSrv;
|
||||||
|
};
|
||||||
|
static void processReq(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet) {
|
||||||
|
SRpcMsg rpcMsg = {0};
|
||||||
|
rpcMsg.pCont = rpcMallocCont(100);
|
||||||
|
rpcMsg.contLen = 100;
|
||||||
|
rpcMsg.handle = pMsg->handle;
|
||||||
|
rpcMsg.code = 0;
|
||||||
|
rpcSendResponse(&rpcMsg);
|
||||||
|
}
|
||||||
|
// client process;
|
||||||
|
static void processResp(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet) {
|
||||||
|
Client *client = (Client *)parent;
|
||||||
|
client->SetResp(pMsg);
|
||||||
|
client->SemPost();
|
||||||
|
}
|
||||||
|
class TransObj {
|
||||||
|
public:
|
||||||
|
TransObj() {
|
||||||
|
dDebugFlag = 143;
|
||||||
|
vDebugFlag = 0;
|
||||||
|
mDebugFlag = 143;
|
||||||
|
cDebugFlag = 0;
|
||||||
|
jniDebugFlag = 0;
|
||||||
|
tmrDebugFlag = 143;
|
||||||
|
uDebugFlag = 143;
|
||||||
|
rpcDebugFlag = 143;
|
||||||
|
qDebugFlag = 0;
|
||||||
|
wDebugFlag = 0;
|
||||||
|
sDebugFlag = 0;
|
||||||
|
tsdbDebugFlag = 0;
|
||||||
|
cqDebugFlag = 0;
|
||||||
|
tscEmbeddedInUtil = 1;
|
||||||
|
tsAsyncLog = 0;
|
||||||
|
|
||||||
|
std::string path = "/tmp/transport";
|
||||||
|
taosRemoveDir(path.c_str());
|
||||||
|
taosMkDir(path.c_str());
|
||||||
|
|
||||||
|
char temp[PATH_MAX];
|
||||||
|
snprintf(temp, PATH_MAX, "%s/taosdlog", path.c_str());
|
||||||
|
if (taosInitLog(temp, tsNumOfLogLines, 1) != 0) {
|
||||||
|
printf("failed to init log file\n");
|
||||||
|
}
|
||||||
|
cli = new Client;
|
||||||
|
cli->Init(1);
|
||||||
|
srv = new Server;
|
||||||
|
srv->Start();
|
||||||
|
}
|
||||||
|
void RestartCli() { cli->Restart(); }
|
||||||
|
void StopSrv() { srv->Stop(); }
|
||||||
|
void RestartSrv() { srv->Restart(); }
|
||||||
|
void cliSendAndRecv(SRpcMsg *req, SRpcMsg *resp) { cli->SendAndRecv(req, resp); }
|
||||||
|
~TransObj() {
|
||||||
|
delete cli;
|
||||||
|
delete srv;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Client *cli;
|
||||||
|
Server *srv;
|
||||||
};
|
};
|
||||||
class TransEnv : public ::testing::Test {
|
class TransEnv : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
|
@ -93,11 +192,34 @@ class TransEnv : public ::testing::Test {
|
||||||
|
|
||||||
TransObj *tr = NULL;
|
TransObj *tr = NULL;
|
||||||
};
|
};
|
||||||
TEST_F(TransEnv, test_start_stop) {
|
|
||||||
assert(tr->startCli());
|
|
||||||
assert(tr->sendAndRecv());
|
|
||||||
assert(tr->stop());
|
|
||||||
|
|
||||||
assert(tr->startSrv());
|
// TEST_F(TransEnv, 01sendAndRec) {
|
||||||
assert(tr->stop());
|
// for (int i = 0; i < 1; i++) {
|
||||||
|
// SRpcMsg req = {0}, resp = {0};
|
||||||
|
// req.msgType = 0;
|
||||||
|
// req.pCont = rpcMallocCont(10);
|
||||||
|
// req.contLen = 10;
|
||||||
|
// tr->cliSendAndRecv(&req, &resp);
|
||||||
|
// assert(resp.code == 0);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
TEST_F(TransEnv, 02StopServer) {
|
||||||
|
for (int i = 0; i < 1; i++) {
|
||||||
|
SRpcMsg req = {0}, resp = {0};
|
||||||
|
req.msgType = 0;
|
||||||
|
req.pCont = rpcMallocCont(10);
|
||||||
|
req.contLen = 10;
|
||||||
|
tr->cliSendAndRecv(&req, &resp);
|
||||||
|
assert(resp.code == 0);
|
||||||
|
}
|
||||||
|
SRpcMsg req = {0}, resp = {0};
|
||||||
|
req.msgType = 1;
|
||||||
|
req.pCont = rpcMallocCont(10);
|
||||||
|
req.contLen = 10;
|
||||||
|
tr->StopSrv();
|
||||||
|
// tr->RestartSrv();
|
||||||
|
tr->cliSendAndRecv(&req, &resp);
|
||||||
|
|
||||||
|
assert(resp.code != 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,13 +22,12 @@
|
||||||
* windows implementation
|
* windows implementation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <Windows.h>
|
|
||||||
#include <Mmsystem.h>
|
#include <Mmsystem.h>
|
||||||
#include <stdio.h>
|
#include <Windows.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#pragma warning( disable : 4244 )
|
#pragma warning(disable : 4244)
|
||||||
|
|
||||||
typedef void (*win_timer_f)(int signo);
|
typedef void (*win_timer_f)(int signo);
|
||||||
|
|
||||||
|
@ -40,8 +39,8 @@ void WINAPI taosWinOnTimer(UINT wTimerID, UINT msg, DWORD_PTR dwUser, DWORD_PTR
|
||||||
}
|
}
|
||||||
|
|
||||||
static MMRESULT timerId;
|
static MMRESULT timerId;
|
||||||
int taosInitTimer(win_timer_f callback, int ms) {
|
int taosInitTimer(win_timer_f callback, int ms) {
|
||||||
DWORD_PTR param = *((int64_t *) & callback);
|
DWORD_PTR param = *((int64_t *)&callback);
|
||||||
|
|
||||||
timerId = timeSetEvent(ms, 1, (LPTIMECALLBACK)taosWinOnTimer, param, TIME_PERIODIC);
|
timerId = timeSetEvent(ms, 1, (LPTIMECALLBACK)taosWinOnTimer, param, TIME_PERIODIC);
|
||||||
if (timerId == 0) {
|
if (timerId == 0) {
|
||||||
|
@ -50,9 +49,7 @@ int taosInitTimer(win_timer_f callback, int ms) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void taosUninitTimer() {
|
void taosUninitTimer() { timeKillEvent(timerId); }
|
||||||
timeKillEvent(timerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(_TD_DARWIN_64)
|
#elif defined(_TD_DARWIN_64)
|
||||||
|
|
||||||
|
@ -60,32 +57,32 @@ void taosUninitTimer() {
|
||||||
* darwin implementation
|
* darwin implementation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/syscall.h>
|
|
||||||
#include <sys/event.h>
|
#include <sys/event.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
static void (*timer_callback)(int);
|
static void (*timer_callback)(int);
|
||||||
static int timer_ms = 0;
|
static int timer_ms = 0;
|
||||||
static pthread_t timer_thread;
|
static pthread_t timer_thread;
|
||||||
static int timer_kq = -1;
|
static int timer_kq = -1;
|
||||||
static volatile int timer_stop = 0;
|
static volatile int timer_stop = 0;
|
||||||
|
|
||||||
static void* timer_routine(void *arg) {
|
static void* timer_routine(void* arg) {
|
||||||
(void)arg;
|
(void)arg;
|
||||||
setThreadName("timer");
|
setThreadName("timer");
|
||||||
|
|
||||||
int r = 0;
|
int r = 0;
|
||||||
struct timespec to = {0};
|
struct timespec to = {0};
|
||||||
to.tv_sec = timer_ms / 1000;
|
to.tv_sec = timer_ms / 1000;
|
||||||
to.tv_nsec = (timer_ms % 1000) * 1000000;
|
to.tv_nsec = (timer_ms % 1000) * 1000000;
|
||||||
while (!timer_stop) {
|
while (!timer_stop) {
|
||||||
struct kevent64_s kev[10] = {0};
|
struct kevent64_s kev[10] = {0};
|
||||||
r = kevent64(timer_kq, NULL, 0, kev, sizeof(kev)/sizeof(kev[0]), 0, &to);
|
r = kevent64(timer_kq, NULL, 0, kev, sizeof(kev) / sizeof(kev[0]), 0, &to);
|
||||||
if (r!=0) {
|
if (r != 0) {
|
||||||
fprintf(stderr, "==%s[%d]%s()==kevent64 failed\n", basename(__FILE__), __LINE__, __func__);
|
fprintf(stderr, "==%s[%d]%s()==kevent64 failed\n", basename(__FILE__), __LINE__, __func__);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
timer_callback(SIGALRM); // just mock
|
timer_callback(SIGALRM); // just mock
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -93,11 +90,13 @@ static void* timer_routine(void *arg) {
|
||||||
|
|
||||||
int taosInitTimer(void (*callback)(int), int ms) {
|
int taosInitTimer(void (*callback)(int), int ms) {
|
||||||
int r = 0;
|
int r = 0;
|
||||||
timer_ms = ms;
|
timer_kq = -1;
|
||||||
|
timer_stop = 0;
|
||||||
|
timer_ms = ms;
|
||||||
timer_callback = callback;
|
timer_callback = callback;
|
||||||
|
|
||||||
timer_kq = kqueue();
|
timer_kq = kqueue();
|
||||||
if (timer_kq==-1) {
|
if (timer_kq == -1) {
|
||||||
fprintf(stderr, "==%s[%d]%s()==failed to create timer kq\n", basename(__FILE__), __LINE__, __func__);
|
fprintf(stderr, "==%s[%d]%s()==failed to create timer kq\n", basename(__FILE__), __LINE__, __func__);
|
||||||
// since no caller of this func checks the return value for the moment
|
// since no caller of this func checks the return value for the moment
|
||||||
abort();
|
abort();
|
||||||
|
@ -144,10 +143,10 @@ static void taosDeleteTimer(void *tharg) {
|
||||||
timer_delete(*pTimer);
|
timer_delete(*pTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static pthread_t timerThread;
|
static pthread_t timerThread;
|
||||||
static timer_t timerId;
|
static timer_t timerId;
|
||||||
static volatile bool stopTimer = false;
|
static volatile bool stopTimer = false;
|
||||||
static void *taosProcessAlarmSignal(void *tharg) {
|
static void * taosProcessAlarmSignal(void *tharg) {
|
||||||
// Block the signal
|
// Block the signal
|
||||||
sigset_t sigset;
|
sigset_t sigset;
|
||||||
sigemptyset(&sigset);
|
sigemptyset(&sigset);
|
||||||
|
@ -159,18 +158,18 @@ static void *taosProcessAlarmSignal(void *tharg) {
|
||||||
|
|
||||||
setThreadName("tmr");
|
setThreadName("tmr");
|
||||||
|
|
||||||
#ifdef _ALPINE
|
#ifdef _ALPINE
|
||||||
sevent.sigev_notify = SIGEV_THREAD;
|
sevent.sigev_notify = SIGEV_THREAD;
|
||||||
sevent.sigev_value.sival_int = syscall(__NR_gettid);
|
sevent.sigev_value.sival_int = syscall(__NR_gettid);
|
||||||
#else
|
#else
|
||||||
sevent.sigev_notify = SIGEV_THREAD_ID;
|
sevent.sigev_notify = SIGEV_THREAD_ID;
|
||||||
sevent._sigev_un._tid = syscall(__NR_gettid);
|
sevent._sigev_un._tid = syscall(__NR_gettid);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sevent.sigev_signo = SIGALRM;
|
sevent.sigev_signo = SIGALRM;
|
||||||
|
|
||||||
if (timer_create(CLOCK_REALTIME, &sevent, &timerId) == -1) {
|
if (timer_create(CLOCK_REALTIME, &sevent, &timerId) == -1) {
|
||||||
//printf("Failed to create timer");
|
// printf("Failed to create timer");
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_cleanup_push(taosDeleteTimer, &timerId);
|
pthread_cleanup_push(taosDeleteTimer, &timerId);
|
||||||
|
@ -182,14 +181,14 @@ static void *taosProcessAlarmSignal(void *tharg) {
|
||||||
ts.it_interval.tv_nsec = 1000000 * MSECONDS_PER_TICK;
|
ts.it_interval.tv_nsec = 1000000 * MSECONDS_PER_TICK;
|
||||||
|
|
||||||
if (timer_settime(timerId, 0, &ts, NULL)) {
|
if (timer_settime(timerId, 0, &ts, NULL)) {
|
||||||
//printf("Failed to init timer");
|
// printf("Failed to init timer");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int signo;
|
int signo;
|
||||||
while (!stopTimer) {
|
while (!stopTimer) {
|
||||||
if (sigwait(&sigset, &signo)) {
|
if (sigwait(&sigset, &signo)) {
|
||||||
//printf("Failed to wait signal: number %d", signo);
|
// printf("Failed to wait signal: number %d", signo);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* //printf("Signal handling: number %d ......\n", signo); */
|
/* //printf("Signal handling: number %d ......\n", signo); */
|
||||||
|
@ -203,15 +202,16 @@ static void *taosProcessAlarmSignal(void *tharg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int taosInitTimer(void (*callback)(int), int ms) {
|
int taosInitTimer(void (*callback)(int), int ms) {
|
||||||
|
stopTimer = false;
|
||||||
pthread_attr_t tattr;
|
pthread_attr_t tattr;
|
||||||
pthread_attr_init(&tattr);
|
pthread_attr_init(&tattr);
|
||||||
int code = pthread_create(&timerThread, &tattr, taosProcessAlarmSignal, callback);
|
int code = pthread_create(&timerThread, &tattr, taosProcessAlarmSignal, callback);
|
||||||
pthread_attr_destroy(&tattr);
|
pthread_attr_destroy(&tattr);
|
||||||
if (code != 0) {
|
if (code != 0) {
|
||||||
//printf("failed to create timer thread");
|
// printf("failed to create timer thread");
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
//printf("timer thread:0x%08" PRIx64 " is created", taosGetPthreadId(timerThread));
|
// printf("timer thread:0x%08" PRIx64 " is created", taosGetPthreadId(timerThread));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -220,7 +220,7 @@ int taosInitTimer(void (*callback)(int), int ms) {
|
||||||
void taosUninitTimer() {
|
void taosUninitTimer() {
|
||||||
stopTimer = true;
|
stopTimer = true;
|
||||||
|
|
||||||
//printf("join timer thread:0x%08" PRIx64, taosGetPthreadId(timerThread));
|
// printf("join timer thread:0x%08" PRIx64, taosGetPthreadId(timerThread));
|
||||||
pthread_join(timerThread, NULL);
|
pthread_join(timerThread, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue