diff --git a/cmake/cmake.options b/cmake/cmake.options
index e84d02800c..e19c10f6b2 100644
--- a/cmake/cmake.options
+++ b/cmake/cmake.options
@@ -47,13 +47,13 @@ option(
option(
BUILD_WITH_UV
"If build with libuv"
- OFF
+ ON
)
option(
BUILD_WITH_UV_TRANS
"If build with libuv_trans "
- OFF
+ ON
)
option(
diff --git a/include/libs/nodes/nodes.h b/include/libs/nodes/nodes.h
index 6a0422cd80..3ef832a69b 100644
--- a/include/libs/nodes/nodes.h
+++ b/include/libs/nodes/nodes.h
@@ -132,7 +132,7 @@ bool nodesEqualNode(const SNode* a, const SNode* b);
SNode* nodesCloneNode(const SNode* pNode);
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);
#ifdef __cplusplus
diff --git a/include/libs/sync/sync.h b/include/libs/sync/sync.h
index 00ba1120e7..0ec741ec3e 100644
--- a/include/libs/sync/sync.h
+++ b/include/libs/sync/sync.h
@@ -137,22 +137,21 @@ typedef struct {
} SSyncInfo;
-// will be defined in syncInt.h, here just for complie
-typedef struct SSyncNode {
-} SSyncNode;
+struct SSyncNode;
+typedef struct SSyncNode SSyncNode;
int32_t syncInit();
void syncCleanUp();
-int64_t syncStart(const SSyncInfo*);
+int64_t syncStart(const SSyncInfo* pSyncInfo);
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 SSyncBuffer* pBuf, bool isWeak);
ESyncState syncGetMyRole(int64_t rid);
-void syncGetNodesRole(int64_t rid, SNodesRole*);
+void syncGetNodesRole(int64_t rid, SNodesRole* pNodeRole);
extern int32_t sDebugFlag;
diff --git a/include/libs/transport/trpc.h b/include/libs/transport/trpc.h
index f913ba06d0..538aeb1a0e 100644
--- a/include/libs/transport/trpc.h
+++ b/include/libs/transport/trpc.h
@@ -64,6 +64,7 @@ typedef struct SRpcInit {
int8_t connType; // TAOS_CONN_UDP, TAOS_CONN_TCPC, TAOS_CONN_TCPS
int idleTime; // milliseconds, 0 means idle timer is disabled
+ bool noPool; // create conn pool or not
// the following is for client app ecurity only
char *user; // user name
char spi; // security parameter index
diff --git a/include/util/tdef.h b/include/util/tdef.h
index 217753a611..a4c333a4d2 100644
--- a/include/util/tdef.h
+++ b/include/util/tdef.h
@@ -335,6 +335,8 @@ do { \
#define TSDB_QUERY_TYPE_NON_TYPE 0x00u // none type
#define TSDB_QUERY_TYPE_FREE_RESOURCE 0x01u // free qhandle at vnode
+#define TSDB_QUERY_TYPE_NON_TYPE 0x00u // none type
+#define TSDB_QUERY_TYPE_FREE_RESOURCE 0x01u // free qhandle at vnode
#define TSDB_META_COMPACT_RATIO 0 // disable tsdb meta compact by default
diff --git a/include/util/tjson.h b/include/util/tjson.h
index a4eb6e5385..a0c2fef05b 100644
--- a/include/util/tjson.h
+++ b/include/util/tjson.h
@@ -30,6 +30,7 @@ void tjsonDelete(SJson* pJson);
SJson* tjsonAddArrayToObject(SJson* pJson, const char* pName);
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 tjsonAddItemToObject(SJson* pJson, const char* pName, 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);
char* tjsonToString(const SJson* pJson);
+char* tjsonToUnformattedString(const SJson* pJson);
#ifdef __cplusplus
}
diff --git a/source/client/src/tmq.c b/source/client/src/tmq.c
index 9855a65b0b..229d3a9ec3 100644
--- a/source/client/src/tmq.c
+++ b/source/client/src/tmq.c
@@ -75,7 +75,7 @@ struct tmq_message_t {
SMqConsumeRsp rsp;
};
-typedef struct SMqClientVg {
+typedef struct {
// statistics
int64_t pollCnt;
// offset
@@ -86,7 +86,7 @@ typedef struct SMqClientVg {
SEpSet epSet;
} SMqClientVg;
-typedef struct SMqClientTopic {
+typedef struct {
// subscribe info
int32_t sqlLen;
char* sql;
@@ -779,11 +779,9 @@ tmq_message_t* tmq_consumer_poll(tmq_t* tmq, int64_t blocking_time) {
param->pVg = pVg;
tsem_init(¶m->rspSem, 0, 0);
-
SRequestObj* pRequest = createRequest(tmq->pTscObj, NULL, NULL, TDMT_VND_CONSUME);
pRequest->body.requestMsg = (SDataBuf){.pData = pReq, .len = sizeof(SMqConsumeReq), .handle = NULL};
-
SMsgSendInfo* sendInfo = buildMsgInfoImpl(pRequest);
sendInfo->requestObjRefId = 0;
sendInfo->param = param;
diff --git a/source/common/src/tmsg.c b/source/common/src/tmsg.c
index ac46c0c48c..46feab7791 100644
--- a/source/common/src/tmsg.c
+++ b/source/common/src/tmsg.c
@@ -34,6 +34,7 @@ int32_t tInitSubmitMsgIter(SSubmitReq *pMsg, SSubmitMsgIter *pIter) {
}
pIter->totalLen = pMsg->length;
+ ASSERT(pIter->totalLen > 0);
pIter->len = 0;
pIter->pMsg = pMsg;
if (pMsg->length <= sizeof(SSubmitReq)) {
@@ -52,6 +53,7 @@ int32_t tGetSubmitMsgNext(SSubmitMsgIter *pIter, SSubmitBlk **pPBlock) {
} else {
SSubmitBlk *pSubmitBlk = (SSubmitBlk *)POINTER_SHIFT(pIter->pMsg, pIter->len);
pIter->len += (sizeof(SSubmitBlk) + pSubmitBlk->dataLen + pSubmitBlk->schemaLen);
+ ASSERT(pIter->len > 0);
}
if (pIter->len > pIter->totalLen) {
diff --git a/source/dnode/mgmt/impl/src/dndTransport.c b/source/dnode/mgmt/impl/src/dndTransport.c
index a0ba71a1eb..4e35baf905 100644
--- a/source/dnode/mgmt/impl/src/dndTransport.c
+++ b/source/dnode/mgmt/impl/src/dndTransport.c
@@ -155,7 +155,7 @@ static void dndInitMsgFp(STransMgmt *pMgmt) {
}
static void dndProcessResponse(void *parent, SRpcMsg *pRsp, SEpSet *pEpSet) {
- SDnode *pDnode = parent;
+ SDnode * pDnode = parent;
STransMgmt *pMgmt = &pDnode->tmgmt;
tmsg_t msgType = pRsp->msgType;
@@ -193,6 +193,7 @@ static int32_t dndInitClient(SDnode *pDnode) {
rpcInit.ckey = INTERNAL_CKEY;
rpcInit.spi = 1;
rpcInit.parent = pDnode;
+ rpcInit.noPool = true;
char pass[TSDB_PASSWORD_LEN + 1] = {0};
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) {
- SDnode *pDnode = param;
+ SDnode * pDnode = param;
STransMgmt *pMgmt = &pDnode->tmgmt;
tmsg_t msgType = pReq->msgType;
@@ -312,7 +313,7 @@ static int32_t dndRetrieveUserAuthInfo(void *parent, char *user, char *spi, char
SAuthReq authReq = {0};
tstrncpy(authReq.user, user, TSDB_USER_LEN);
int32_t contLen = tSerializeSAuthReq(NULL, 0, &authReq);
- void *pReq = rpcMallocCont(contLen);
+ void * pReq = rpcMallocCont(contLen);
tSerializeSAuthReq(pReq, contLen, &authReq);
SRpcMsg rpcMsg = {.pCont = pReq, .contLen = contLen, .msgType = TDMT_MND_AUTH, .ahandle = (void *)9528};
diff --git a/source/dnode/mgmt/impl/test/sut/inc/client.h b/source/dnode/mgmt/impl/test/sut/inc/client.h
index 9cf688fc02..925680d528 100644
--- a/source/dnode/mgmt/impl/test/sut/inc/client.h
+++ b/source/dnode/mgmt/impl/test/sut/inc/client.h
@@ -21,16 +21,21 @@ class TestClient {
bool Init(const char* user, const char* pass, const char* fqdn, uint16_t port);
void Cleanup();
+ void DoInit();
+
SRpcMsg* SendReq(SRpcMsg* pReq);
void SetRpcRsp(SRpcMsg* pRsp);
tsem_t* GetSem();
+ void Restart();
private:
char fqdn[TSDB_FQDN_LEN];
uint16_t port;
+ char user[128];
+ char pass[128];
void* clientRpc;
SRpcMsg* pRsp;
tsem_t sem;
};
-#endif /* _TD_TEST_CLIENT_H_ */
\ No newline at end of file
+#endif /* _TD_TEST_CLIENT_H_ */
diff --git a/source/dnode/mgmt/impl/test/sut/inc/sut.h b/source/dnode/mgmt/impl/test/sut/inc/sut.h
index 23913b0531..250d563a8b 100644
--- a/source/dnode/mgmt/impl/test/sut/inc/sut.h
+++ b/source/dnode/mgmt/impl/test/sut/inc/sut.h
@@ -20,10 +20,10 @@
#include "os.h"
#include "dnode.h"
-#include "tmsg.h"
#include "tconfig.h"
#include "tdataformat.h"
#include "tglobal.h"
+#include "tmsg.h"
#include "tnote.h"
#include "trpc.h"
#include "tthread.h"
@@ -39,6 +39,7 @@ class Testbase {
void Restart();
void ServerStop();
void ServerStart();
+ void ClientRestart();
SRpcMsg* SendReq(tmsg_t msgType, void* pCont, int32_t contLen);
private:
@@ -100,7 +101,7 @@ class Testbase {
{ \
char* bytes = (char*)calloc(1, len); \
for (int32_t i = 0; i < len - 1; ++i) { \
- bytes[i] = b; \
+ bytes[i] = b; \
} \
EXPECT_STREQ(test.GetShowBinary(len), bytes); \
}
@@ -138,4 +139,4 @@ class Testbase {
#define IgnoreTimestamp() \
{ test.GetShowTimestamp(); }
-#endif /* _TD_TEST_BASE_H_ */
\ No newline at end of file
+#endif /* _TD_TEST_BASE_H_ */
diff --git a/source/dnode/mgmt/impl/test/sut/src/client.cpp b/source/dnode/mgmt/impl/test/sut/src/client.cpp
index 8403dbf034..b89cb02834 100644
--- a/source/dnode/mgmt/impl/test/sut/src/client.cpp
+++ b/source/dnode/mgmt/impl/test/sut/src/client.cpp
@@ -13,33 +13,41 @@
* along with this program. If not, see .
*/
-#include "tep.h"
#include "sut.h"
+#include "tep.h"
static void processClientRsp(void* parent, SRpcMsg* pRsp, SEpSet* pEpSet) {
TestClient* client = (TestClient*)parent;
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());
}
-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; }
-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};
taosEncryptPass_c((uint8_t*)pass, strlen(pass), secretEncrypt);
-
SRpcInit rpcInit;
memset(&rpcInit, 0, sizeof(rpcInit));
- rpcInit.label = (char*)"DND-C";
+ rpcInit.label = (char*)"shell";
rpcInit.numOfThreads = 1;
rpcInit.cfp = processClientRsp;
rpcInit.sessions = 1024;
rpcInit.connType = TAOS_CONN_CLIENT;
rpcInit.idleTime = 30 * 1000;
- rpcInit.user = (char*)user;
+ rpcInit.user = (char*)this->user;
rpcInit.ckey = (char*)"key";
rpcInit.parent = this;
rpcInit.secret = (char*)secretEncrypt;
@@ -47,11 +55,16 @@ bool TestClient::Init(const char* user, const char* pass, const char* fqdn, uint
clientRpc = rpcOpen(&rpcInit);
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->user, user);
+ strcpy(this->pass, pass);
this->port = port;
-
+ this->pRsp = NULL;
+ this->DoInit();
return true;
}
@@ -60,11 +73,16 @@ void TestClient::Cleanup() {
rpcClose(clientRpc);
}
+void TestClient::Restart() {
+ this->Cleanup();
+ this->DoInit();
+}
SRpcMsg* TestClient::SendReq(SRpcMsg* pReq) {
SEpSet epSet = {0};
addEpIntoEpSet(&epSet, fqdn, port);
rpcSendRequest(clientRpc, &epSet, pReq, NULL);
tsem_wait(&sem);
+ uInfo("y response:%s from dnode, code:0x%x, msgSize: %d", TMSG_INFO(pRsp->msgType), pRsp->code, pRsp->contLen);
return pRsp;
}
diff --git a/source/dnode/mgmt/impl/test/sut/src/sut.cpp b/source/dnode/mgmt/impl/test/sut/src/sut.cpp
index 09a738be3b..771c5886ef 100644
--- a/source/dnode/mgmt/impl/test/sut/src/sut.cpp
+++ b/source/dnode/mgmt/impl/test/sut/src/sut.cpp
@@ -21,9 +21,9 @@ void Testbase::InitLog(const char* path) {
mDebugFlag = 143;
cDebugFlag = 0;
jniDebugFlag = 0;
- tmrDebugFlag = 0;
- uDebugFlag = 0;
- rpcDebugFlag = 0;
+ tmrDebugFlag = 143;
+ uDebugFlag = 143;
+ rpcDebugFlag = 143;
qDebugFlag = 0;
wDebugFlag = 0;
sDebugFlag = 0;
@@ -66,16 +66,21 @@ void Testbase::Init(const char* path, int16_t port) {
void Testbase::Cleanup() {
tFreeSTableMetaRsp(&metaRsp);
- server.Stop();
client.Cleanup();
+ taosMsleep(10);
+ server.Stop();
dndCleanup();
}
-void Testbase::Restart() { server.Restart(); }
+void Testbase::Restart() {
+ server.Restart();
+ client.Restart();
+}
void Testbase::ServerStop() { server.Stop(); }
void Testbase::ServerStart() { server.DoStart(); }
+void Testbase::ClientRestart() { client.Restart(); }
SRpcMsg* Testbase::SendReq(tmsg_t msgType, void* pCont, int32_t contLen) {
SRpcMsg rpcMsg = {0};
@@ -194,4 +199,4 @@ int32_t Testbase::GetShowRows() { return pRetrieveRsp->numOfRows; }
STableMetaRsp* Testbase::GetShowMeta() { return &metaRsp; }
-SRetrieveTableRsp* Testbase::GetRetrieveRsp() { return pRetrieveRsp; }
\ No newline at end of file
+SRetrieveTableRsp* Testbase::GetRetrieveRsp() { return pRetrieveRsp; }
diff --git a/source/dnode/mnode/impl/src/mnode.c b/source/dnode/mnode/impl/src/mnode.c
index 699ccab92c..64b4aa6dd7 100644
--- a/source/dnode/mnode/impl/src/mnode.c
+++ b/source/dnode/mnode/impl/src/mnode.c
@@ -77,7 +77,7 @@ static void mndTransReExecute(void *param, void *tmrId) {
SMnode *pMnode = param;
if (mndIsMaster(pMnode)) {
int32_t contLen = 0;
- void *pReq = mndBuildTimerMsg(&contLen);
+ void * pReq = mndBuildTimerMsg(&contLen);
SRpcMsg rpcMsg = {.msgType = TDMT_MND_TRANS, .pCont = pReq, .contLen = contLen};
pMnode->putReqToMWriteQFp(pMnode->pDnode, &rpcMsg);
}
@@ -89,7 +89,7 @@ static void mndCalMqRebalance(void *param, void *tmrId) {
SMnode *pMnode = param;
if (mndIsMaster(pMnode)) {
int32_t contLen = 0;
- void *pReq = mndBuildTimerMsg(&contLen);
+ void * pReq = mndBuildTimerMsg(&contLen);
SRpcMsg rpcMsg = {.msgType = TDMT_MND_MQ_TIMER, .pCont = pReq, .contLen = contLen};
pMnode->putReqToMReadQFp(pMnode->pDnode, &rpcMsg);
}
@@ -404,7 +404,8 @@ SMnodeMsg *mndInitMsg(SMnode *pMnode, SRpcMsg *pRpcMsg) {
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};
if ((pRpcMsg->msgType & 1U) && rpcGetConnInfo(pRpcMsg->handle, &connInfo) != 0) {
taosFreeQitem(pMsg);
@@ -439,7 +440,7 @@ void mndProcessMsg(SMnodeMsg *pMsg) {
SMnode *pMnode = pMsg->pMnode;
int32_t code = 0;
tmsg_t msgType = pMsg->rpcMsg.msgType;
- void *ahandle = pMsg->rpcMsg.ahandle;
+ void * ahandle = pMsg->rpcMsg.ahandle;
bool isReq = (msgType & 1U);
mTrace("msg:%p, type:%s will be processed, app:%p", pMsg, TMSG_INFO(msgType), ahandle);
diff --git a/source/dnode/mnode/impl/test/qnode/qnode.cpp b/source/dnode/mnode/impl/test/qnode/qnode.cpp
index d4e308268a..b8a0e61ca3 100644
--- a/source/dnode/mnode/impl/test/qnode/qnode.cpp
+++ b/source/dnode/mnode/impl/test/qnode/qnode.cpp
@@ -190,6 +190,9 @@ TEST_F(MndTestQnode, 03_Create_Qnode_Rollback) {
tSerializeSMCreateDropQSBNodeReq(pReq, contLen, &createReq);
server2.Stop();
+ taosMsleep(1000);
+ // test.ClientRestart();
+
SRpcMsg* pRsp = test.SendReq(TDMT_MND_CREATE_QNODE, pReq, contLen);
ASSERT_NE(pRsp, nullptr);
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
server2.DoStart();
+ test.ClientRestart();
taosMsleep(1000);
int32_t retry = 0;
@@ -248,7 +252,6 @@ TEST_F(MndTestQnode, 03_Create_Qnode_Rollback) {
ASSERT_NE(retry, retryMax);
}
}
-
TEST_F(MndTestQnode, 04_Drop_Qnode_Rollback) {
{
// send message first, then dnode2 crash, result is returned, and rollback is started
@@ -315,4 +318,4 @@ TEST_F(MndTestQnode, 04_Drop_Qnode_Rollback) {
ASSERT_NE(retry, retryMax);
}
-}
\ No newline at end of file
+}
diff --git a/source/dnode/mnode/impl/test/trans/trans.cpp b/source/dnode/mnode/impl/test/trans/trans.cpp
index d4c40dd428..88d4fc4f75 100644
--- a/source/dnode/mnode/impl/test/trans/trans.cpp
+++ b/source/dnode/mnode/impl/test/trans/trans.cpp
@@ -46,8 +46,10 @@ class MndTestTrans : public ::testing::Test {
free(buffer);
taosFsyncFile(fd);
taosCloseFile(fd);
+ taosMsleep(1000);
test.ServerStart();
+ test.ClientRestart();
}
static Testbase test;
@@ -284,6 +286,7 @@ TEST_F(MndTestTrans, 03_Create_Qnode2_Crash) {
}
}
+
// create db
// partial create stb
// drop db failed
diff --git a/source/dnode/mnode/impl/test/user/user.cpp b/source/dnode/mnode/impl/test/user/user.cpp
index d8ce599be1..61b99beeb7 100644
--- a/source/dnode/mnode/impl/test/user/user.cpp
+++ b/source/dnode/mnode/impl/test/user/user.cpp
@@ -617,6 +617,7 @@ TEST_F(MndTestUser, 06_Create_Drop_Alter_User) {
// restart
test.Restart();
+ taosMsleep(1000);
test.SendShowMetaReq(TSDB_MGMT_TABLE_USER, "");
CHECK_META("show users", 4);
@@ -631,4 +632,4 @@ TEST_F(MndTestUser, 06_Create_Drop_Alter_User) {
CheckTimestamp();
CheckBinary("root", TSDB_USER_LEN);
CheckBinary("root", TSDB_USER_LEN);
-}
\ No newline at end of file
+}
diff --git a/source/dnode/vnode/inc/vnode.h b/source/dnode/vnode/inc/vnode.h
index 1fb0b05f9e..3a06674e3c 100644
--- a/source/dnode/vnode/inc/vnode.h
+++ b/source/dnode/vnode/inc/vnode.h
@@ -226,9 +226,9 @@ static FORCE_INLINE int tqReadHandleSetTbUidList(STqReadHandle *pHandle, const S
return 0;
}
-void tqReadHandleSetMsg(STqReadHandle *pHandle, SSubmitReq *pMsg, int64_t ver);
-bool tqNextDataBlock(STqReadHandle *pHandle);
-int tqRetrieveDataBlockInfo(STqReadHandle *pHandle, SDataBlockInfo *pBlockInfo);
+int32_t tqReadHandleSetMsg(STqReadHandle *pHandle, SSubmitReq *pMsg, int64_t ver);
+bool tqNextDataBlock(STqReadHandle *pHandle);
+int tqRetrieveDataBlockInfo(STqReadHandle *pHandle, SDataBlockInfo *pBlockInfo);
// return SArray
SArray *tqRetrieveDataBlock(STqReadHandle *pHandle);
diff --git a/source/dnode/vnode/src/tq/tqRead.c b/source/dnode/vnode/src/tq/tqRead.c
index e76d43becd..bfa811feec 100644
--- a/source/dnode/vnode/src/tq/tqRead.c
+++ b/source/dnode/vnode/src/tq/tqRead.c
@@ -31,13 +31,28 @@ STqReadHandle* tqInitSubmitMsgScanner(SMeta* pMeta) {
return pReadHandle;
}
-void tqReadHandleSetMsg(STqReadHandle* pReadHandle, SSubmitReq* pMsg, int64_t ver) {
+int32_t tqReadHandleSetMsg(STqReadHandle* pReadHandle, SSubmitReq* pMsg, int64_t ver) {
pReadHandle->pMsg = pMsg;
pMsg->length = htonl(pMsg->length);
pMsg->numOfBlocks = htonl(pMsg->numOfBlocks);
- tInitSubmitMsgIter(pMsg, &pReadHandle->msgIter);
+
+ if (tInitSubmitMsgIter(pMsg, &pReadHandle->msgIter) < 0) return -1;
+ while (true) {
+ if (tGetSubmitMsgNext(&pReadHandle->msgIter, &pReadHandle->pBlock) < 0) return -1;
+ if (pReadHandle->pBlock == NULL) break;
+
+ pReadHandle->pBlock->uid = htobe64(pReadHandle->pBlock->uid);
+ pReadHandle->pBlock->tid = htonl(pReadHandle->pBlock->tid);
+ pReadHandle->pBlock->sversion = htonl(pReadHandle->pBlock->sversion);
+ pReadHandle->pBlock->dataLen = htonl(pReadHandle->pBlock->dataLen);
+ pReadHandle->pBlock->schemaLen = htonl(pReadHandle->pBlock->schemaLen);
+ pReadHandle->pBlock->numOfRows = htons(pReadHandle->pBlock->numOfRows);
+ }
+
+ if (tInitSubmitMsgIter(pMsg, &pReadHandle->msgIter) < 0) return -1;
pReadHandle->ver = ver;
memset(&pReadHandle->blkIter, 0, sizeof(SSubmitBlkIter));
+ return 0;
}
bool tqNextDataBlock(STqReadHandle* pHandle) {
@@ -47,19 +62,19 @@ bool tqNextDataBlock(STqReadHandle* pHandle) {
}
if (pHandle->pBlock == NULL) return false;
- pHandle->pBlock->uid = htobe64(pHandle->pBlock->uid);
+ /*pHandle->pBlock->uid = htobe64(pHandle->pBlock->uid);*/
/*if (pHandle->tbUid == pHandle->pBlock->uid) {*/
ASSERT(pHandle->tbIdHash);
void* ret = taosHashGet(pHandle->tbIdHash, &pHandle->pBlock->uid, sizeof(int64_t));
if (ret != NULL) {
/*printf("retrieve one tb %ld\n", pHandle->pBlock->uid);*/
- pHandle->pBlock->tid = htonl(pHandle->pBlock->tid);
- pHandle->pBlock->sversion = htonl(pHandle->pBlock->sversion);
- pHandle->pBlock->dataLen = htonl(pHandle->pBlock->dataLen);
- pHandle->pBlock->schemaLen = htonl(pHandle->pBlock->schemaLen);
- pHandle->pBlock->numOfRows = htons(pHandle->pBlock->numOfRows);
+ /*pHandle->pBlock->tid = htonl(pHandle->pBlock->tid);*/
+ /*pHandle->pBlock->sversion = htonl(pHandle->pBlock->sversion);*/
+ /*pHandle->pBlock->dataLen = htonl(pHandle->pBlock->dataLen);*/
+ /*pHandle->pBlock->schemaLen = htonl(pHandle->pBlock->schemaLen);*/
+ /*pHandle->pBlock->numOfRows = htons(pHandle->pBlock->numOfRows);*/
return true;
- } else {
+ /*} else {*/
/*printf("skip one tb %ld\n", pHandle->pBlock->uid);*/
}
}
diff --git a/source/dnode/vnode/src/vnd/vnodeQuery.c b/source/dnode/vnode/src/vnd/vnodeQuery.c
index f779949f14..4b47413715 100644
--- a/source/dnode/vnode/src/vnd/vnodeQuery.c
+++ b/source/dnode/vnode/src/vnd/vnodeQuery.c
@@ -126,7 +126,7 @@ static int vnodeGetTableMeta(SVnode *pVnode, SRpcMsg *pMsg) {
goto _exit;
}
- metaRsp.dbId = htobe64(pVnode->config.dbId);
+ metaRsp.dbId = pVnode->config.dbId;
memcpy(metaRsp.dbFName, infoReq.dbFName, sizeof(metaRsp.dbFName));
strcpy(metaRsp.tbName, infoReq.tbName);
if (pTbCfg->type == META_CHILD_TABLE) {
diff --git a/source/libs/catalog/src/catalog.c b/source/libs/catalog/src/catalog.c
index 142699f541..d62c189d33 100644
--- a/source/libs/catalog/src/catalog.c
+++ b/source/libs/catalog/src/catalog.c
@@ -1556,39 +1556,43 @@ int32_t ctgGetTableMeta(SCatalog* pCtg, void *pRpc, const SEpSet* pMgmtEps, cons
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)) {
- *pTableMeta = output->tbMeta;
- goto _return;
- }
+ if (CTG_IS_META_TABLE(output->metaType)) {
+ *pTableMeta = output->tbMeta;
+ goto _return;
+ }
- if (CTG_IS_META_BOTH(output->metaType)) {
- memcpy(output->tbMeta, &output->ctbMeta, sizeof(output->ctbMeta));
+ 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);
- *pTableMeta = output->tbMeta;
- goto _return;
+ 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_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:
tfree(output);
diff --git a/source/libs/executor/src/executor.c b/source/libs/executor/src/executor.c
index c47c83ba29..18485249b3 100644
--- a/source/libs/executor/src/executor.c
+++ b/source/libs/executor/src/executor.c
@@ -14,9 +14,9 @@
*/
#include "executor.h"
-#include "tq.h"
#include "executorimpl.h"
#include "planner.h"
+#include "tq.h"
static int32_t doSetStreamBlock(SOperatorInfo* pOperator, void* input, char* id) {
ASSERT(pOperator != NULL);
@@ -34,7 +34,10 @@ static int32_t doSetStreamBlock(SOperatorInfo* pOperator, void* input, char* id)
return doSetStreamBlock(pOperator->pDownstream[0], input, id);
} else {
SStreamBlockScanInfo* pInfo = pOperator->info;
- tqReadHandleSetMsg(pInfo->readerHandle, input, 0);
+ if (tqReadHandleSetMsg(pInfo->readerHandle, input, 0) < 0) {
+ qError("submit msg error while set stream msg, %s" PRIx64, id);
+ return TSDB_CODE_QRY_APP_ERROR;
+ }
return TSDB_CODE_SUCCESS;
}
}
@@ -48,9 +51,9 @@ int32_t qSetStreamInput(qTaskInfo_t tinfo, const void* input) {
return TSDB_CODE_SUCCESS;
}
- SExecTaskInfo* pTaskInfo = (SExecTaskInfo*) tinfo;
+ SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo;
- int32_t code = doSetStreamBlock(pTaskInfo->pRoot, (void*) input, GET_TASKID(pTaskInfo));
+ int32_t code = doSetStreamBlock(pTaskInfo->pRoot, (void*)input, GET_TASKID(pTaskInfo));
if (code != TSDB_CODE_SUCCESS) {
qError("%s failed to set the stream block data", GET_TASKID(pTaskInfo));
} else {
diff --git a/source/libs/index/src/index.c b/source/libs/index/src/index.c
index 0c222eae1a..9287a91828 100644
--- a/source/libs/index/src/index.c
+++ b/source/libs/index/src/index.c
@@ -66,7 +66,9 @@ static void indexMergeSameKey(SArray* result, TFileValue* tv);
int indexOpen(SIndexOpts* opts, const char* path, SIndex** index) {
pthread_once(&isInit, indexInit);
SIndex* sIdx = calloc(1, sizeof(SIndex));
- if (sIdx == NULL) { return -1; }
+ if (sIdx == NULL) {
+ return -1;
+ }
#ifdef USE_LUCENE
index_t* index = index_open(path);
@@ -76,7 +78,9 @@ int indexOpen(SIndexOpts* opts, const char* path, SIndex** index) {
#ifdef USE_INVERTED_INDEX
// sIdx->cache = (void*)indexCacheCreate(sIdx);
sIdx->tindex = indexTFileCreate(path);
- if (sIdx->tindex == NULL) { goto END; }
+ if (sIdx->tindex == NULL) {
+ goto END;
+ }
sIdx->colObj = taosHashInit(8, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK);
sIdx->cVersion = 1;
@@ -87,7 +91,9 @@ int indexOpen(SIndexOpts* opts, const char* path, SIndex** index) {
#endif
END:
- if (sIdx != NULL) { indexClose(sIdx); }
+ if (sIdx != NULL) {
+ indexClose(sIdx);
+ }
*index = NULL;
return -1;
@@ -103,7 +109,9 @@ void indexClose(SIndex* sIdx) {
void* iter = taosHashIterate(sIdx->colObj, NULL);
while (iter) {
IndexCache** pCache = iter;
- if (*pCache) { indexCacheUnRef(*pCache); }
+ if (*pCache) {
+ indexCacheUnRef(*pCache);
+ }
iter = taosHashIterate(sIdx->colObj, iter);
}
taosHashCleanup(sIdx->colObj);
@@ -161,7 +169,9 @@ int indexPut(SIndex* index, SIndexMultiTerm* fVals, uint64_t uid) {
IndexCache** cache = taosHashGet(index->colObj, buf, sz);
assert(*cache != NULL);
int ret = indexCachePut(*cache, p, uid);
- if (ret != 0) { return ret; }
+ if (ret != 0) {
+ return ret;
+ }
}
#endif
@@ -191,7 +201,9 @@ int indexSearch(SIndex* index, SIndexMultiTermQuery* multiQuerys, SArray* result
int tsz = 0;
index_multi_search(index->index, (const char**)fields, (const char**)keys, types, nQuery, opera, &tResult, &tsz);
- for (int i = 0; i < tsz; i++) { taosArrayPush(result, &tResult[i]); }
+ for (int i = 0; i < tsz; i++) {
+ taosArrayPush(result, &tResult[i]);
+ }
for (int i = 0; i < nQuery; i++) {
free(fields[i]);
@@ -248,7 +260,9 @@ void indexOptsDestroy(SIndexOpts* opts) {
*/
SIndexMultiTermQuery* indexMultiTermQueryCreate(EIndexOperatorType opera) {
SIndexMultiTermQuery* p = (SIndexMultiTermQuery*)malloc(sizeof(SIndexMultiTermQuery));
- if (p == NULL) { return NULL; }
+ if (p == NULL) {
+ return NULL;
+ }
p->opera = opera;
p->query = taosArrayInit(4, sizeof(SIndexTermQuery));
return p;
@@ -270,7 +284,9 @@ int indexMultiTermQueryAdd(SIndexMultiTermQuery* pQuery, SIndexTerm* term, EInde
SIndexTerm* indexTermCreate(int64_t suid, SIndexOperOnColumn oper, uint8_t colType, const char* colName,
int32_t nColName, const char* colVal, int32_t nColVal) {
SIndexTerm* t = (SIndexTerm*)calloc(1, (sizeof(SIndexTerm)));
- if (t == NULL) { return NULL; }
+ if (t == NULL) {
+ return NULL;
+ }
t->suid = suid;
t->operType = oper;
@@ -343,7 +359,9 @@ static int indexTermSearch(SIndex* sIdx, SIndexTermQuery* query, SArray** result
return 0;
}
static void indexInterResultsDestroy(SArray* results) {
- if (results == NULL) { return; }
+ if (results == NULL) {
+ return;
+ }
size_t sz = taosArrayGetSize(results);
for (size_t i = 0; i < sz; i++) {
@@ -419,18 +437,24 @@ static void indexDestroyTempResult(SArray* result) {
taosArrayDestroy(result);
}
int indexFlushCacheToTFile(SIndex* sIdx, void* cache) {
- if (sIdx == NULL) { return -1; }
+ if (sIdx == NULL) {
+ return -1;
+ }
indexInfo("suid %" PRIu64 " merge cache into tindex", sIdx->suid);
int64_t st = taosGetTimestampUs();
IndexCache* pCache = (IndexCache*)cache;
TFileReader* pReader = tfileGetReaderByCol(sIdx->tindex, pCache->suid, pCache->colName);
- if (pReader == NULL) { indexWarn("empty tfile reader found"); }
+ if (pReader == NULL) {
+ indexWarn("empty tfile reader found");
+ }
// handle flush
Iterate* cacheIter = indexCacheIteratorCreate(pCache);
Iterate* tfileIter = tfileIteratorCreate(pReader);
- if (tfileIter == NULL) { indexWarn("empty tfile reader iterator"); }
+ if (tfileIter == NULL) {
+ indexWarn("empty tfile reader iterator");
+ }
SArray* result = taosArrayInit(1024, sizeof(void*));
@@ -484,7 +508,9 @@ void iterateValueDestroy(IterateValue* value, bool destroy) {
taosArrayDestroy(value->val);
value->val = NULL;
} else {
- if (value->val != NULL) { taosArrayClear(value->val); }
+ if (value->val != NULL) {
+ taosArrayClear(value->val);
+ }
}
free(value->colVal);
value->colVal = NULL;
@@ -507,7 +533,9 @@ static int indexGenTFile(SIndex* sIdx, IndexCache* cache, SArray* batch) {
tfileWriterClose(tw);
TFileReader* reader = tfileReaderOpen(sIdx->path, cache->suid, version, cache->colName);
- if (reader == NULL) { return -1; }
+ if (reader == NULL) {
+ return -1;
+ }
TFileHeader* header = &reader->header;
ICacheKey key = {.suid = cache->suid, .colName = header->colName, .nColName = strlen(header->colName)};
diff --git a/source/libs/index/src/index_cache.c b/source/libs/index/src/index_cache.c
index 48566a8674..d6a7141825 100644
--- a/source/libs/index/src/index_cache.c
+++ b/source/libs/index/src/index_cache.c
@@ -119,13 +119,17 @@ void indexCacheDestroySkiplist(SSkipList* slt) {
tSkipListDestroy(slt);
}
void indexCacheDestroyImm(IndexCache* cache) {
- if (cache == NULL) { return; }
+ if (cache == NULL) {
+ return;
+ }
MemTable* tbl = NULL;
pthread_mutex_lock(&cache->mtx);
+
tbl = cache->imm;
cache->imm = NULL; // or throw int bg thread
pthread_cond_broadcast(&cache->finished);
+
pthread_mutex_unlock(&cache->mtx);
indexMemUnRef(tbl);
@@ -133,7 +137,9 @@ void indexCacheDestroyImm(IndexCache* cache) {
}
void indexCacheDestroy(void* cache) {
IndexCache* pCache = cache;
- if (pCache == NULL) { return; }
+ if (pCache == NULL) {
+ return;
+ }
indexMemUnRef(pCache->mem);
indexMemUnRef(pCache->imm);
free(pCache->colName);
@@ -146,7 +152,9 @@ void indexCacheDestroy(void* cache) {
Iterate* indexCacheIteratorCreate(IndexCache* cache) {
Iterate* iiter = calloc(1, sizeof(Iterate));
- if (iiter == NULL) { return NULL; }
+ if (iiter == NULL) {
+ return NULL;
+ }
pthread_mutex_lock(&cache->mtx);
@@ -164,7 +172,9 @@ Iterate* indexCacheIteratorCreate(IndexCache* cache) {
return iiter;
}
void indexCacheIteratorDestroy(Iterate* iter) {
- if (iter == NULL) { return; }
+ if (iter == NULL) {
+ return;
+ }
tSkipListDestroyIter(iter->iter);
iterateValueDestroy(&iter->val, true);
free(iter);
@@ -186,9 +196,6 @@ static void indexCacheMakeRoomForWrite(IndexCache* cache) {
} else if (cache->imm != NULL) {
// TODO: wake up by condition variable
pthread_cond_wait(&cache->finished, &cache->mtx);
- // pthread_mutex_unlock(&cache->mtx);
- // taosMsleep(50);
- // pthread_mutex_lock(&cache->mtx);
} else {
indexCacheRef(cache);
cache->imm = cache->mem;
@@ -202,13 +209,17 @@ static void indexCacheMakeRoomForWrite(IndexCache* cache) {
}
int indexCachePut(void* cache, SIndexTerm* term, uint64_t uid) {
- if (cache == NULL) { return -1; }
+ if (cache == NULL) {
+ return -1;
+ }
IndexCache* pCache = cache;
indexCacheRef(pCache);
// encode data
CacheTerm* ct = calloc(1, sizeof(CacheTerm));
- if (cache == NULL) { return -1; }
+ if (cache == NULL) {
+ return -1;
+ }
// set up key
ct->colType = term->colType;
ct->colVal = (char*)calloc(1, sizeof(char) * (term->nColVal + 1));
@@ -240,7 +251,9 @@ int indexCacheDel(void* cache, const char* fieldValue, int32_t fvlen, uint64_t u
}
static int indexQueryMem(MemTable* mem, CacheTerm* ct, EIndexQueryType qtype, SArray* result, STermValueType* s) {
- if (mem == NULL) { return 0; }
+ if (mem == NULL) {
+ return 0;
+ }
char* key = indexCacheTermGet(ct);
SSkipListIterator* iter = tSkipListCreateIterFromVal(mem->mem, key, TSDB_DATA_TYPE_BINARY, TSDB_ORDER_ASC);
@@ -266,7 +279,9 @@ static int indexQueryMem(MemTable* mem, CacheTerm* ct, EIndexQueryType qtype, SA
return 0;
}
int indexCacheSearch(void* cache, SIndexTermQuery* query, SArray* result, STermValueType* s) {
- if (cache == NULL) { return 0; }
+ if (cache == NULL) {
+ return 0;
+ }
IndexCache* pCache = cache;
MemTable *mem = NULL, *imm = NULL;
@@ -294,23 +309,33 @@ int indexCacheSearch(void* cache, SIndexTermQuery* query, SArray* result, STermV
}
void indexCacheRef(IndexCache* cache) {
- if (cache == NULL) { return; }
+ if (cache == NULL) {
+ return;
+ }
int ref = T_REF_INC(cache);
UNUSED(ref);
}
void indexCacheUnRef(IndexCache* cache) {
- if (cache == NULL) { return; }
+ if (cache == NULL) {
+ return;
+ }
int ref = T_REF_DEC(cache);
- if (ref == 0) { indexCacheDestroy(cache); }
+ if (ref == 0) {
+ indexCacheDestroy(cache);
+ }
}
void indexMemRef(MemTable* tbl) {
- if (tbl == NULL) { return; }
+ if (tbl == NULL) {
+ return;
+ }
int ref = T_REF_INC(tbl);
UNUSED(ref);
}
void indexMemUnRef(MemTable* tbl) {
- if (tbl == NULL) { return; }
+ if (tbl == NULL) {
+ return;
+ }
int ref = T_REF_DEC(tbl);
if (ref == 0) {
SSkipList* slt = tbl->mem;
@@ -320,7 +345,9 @@ void indexMemUnRef(MemTable* tbl) {
}
static void indexCacheTermDestroy(CacheTerm* ct) {
- if (ct == NULL) { return; }
+ if (ct == NULL) {
+ return;
+ }
free(ct->colVal);
free(ct);
}
@@ -333,7 +360,9 @@ static int32_t indexCacheTermCompare(const void* l, const void* r) {
CacheTerm* rt = (CacheTerm*)r;
// compare colVal
int32_t cmp = strcmp(lt->colVal, rt->colVal);
- if (cmp == 0) { return rt->version - lt->version; }
+ if (cmp == 0) {
+ return rt->version - lt->version;
+ }
return cmp;
}
@@ -354,7 +383,9 @@ static void doMergeWork(SSchedMsg* msg) {
}
static bool indexCacheIteratorNext(Iterate* itera) {
SSkipListIterator* iter = itera->iter;
- if (iter == NULL) { return false; }
+ if (iter == NULL) {
+ return false;
+ }
IterateValue* iv = &itera->val;
iterateValueDestroy(iv, false);
diff --git a/source/libs/index/src/index_fst.c b/source/libs/index/src/index_fst.c
index 46b4c9d7c6..3664bcfad0 100644
--- a/source/libs/index/src/index_fst.c
+++ b/source/libs/index/src/index_fst.c
@@ -31,20 +31,24 @@ static uint8_t fstPackDetla(FstCountingWriter* wrt, CompiledAddr nodeAddr, Compi
FstUnFinishedNodes* fstUnFinishedNodesCreate() {
FstUnFinishedNodes* nodes = malloc(sizeof(FstUnFinishedNodes));
- if (nodes == NULL) { return NULL; }
+ if (nodes == NULL) {
+ return NULL;
+ }
nodes->stack = (SArray*)taosArrayInit(64, sizeof(FstBuilderNodeUnfinished));
fstUnFinishedNodesPushEmpty(nodes, false);
return nodes;
}
-void unFinishedNodeDestroyElem(void* elem) {
+static void unFinishedNodeDestroyElem(void* elem) {
FstBuilderNodeUnfinished* b = (FstBuilderNodeUnfinished*)elem;
fstBuilderNodeDestroy(b->node);
free(b->last);
b->last = NULL;
}
void fstUnFinishedNodesDestroy(FstUnFinishedNodes* nodes) {
- if (nodes == NULL) { return; }
+ if (nodes == NULL) {
+ return;
+ }
taosArrayDestroyEx(nodes->stack, unFinishedNodeDestroyElem);
free(nodes);
@@ -92,7 +96,9 @@ void fstUnFinishedNodesTopLastFreeze(FstUnFinishedNodes* nodes, CompiledAddr add
}
void fstUnFinishedNodesAddSuffix(FstUnFinishedNodes* nodes, FstSlice bs, Output out) {
FstSlice* s = &bs;
- if (fstSliceIsEmpty(s)) { return; }
+ if (fstSliceIsEmpty(s)) {
+ return;
+ }
size_t sz = taosArrayGetSize(nodes->stack) - 1;
FstBuilderNodeUnfinished* un = taosArrayGet(nodes->stack, sz);
assert(un->last == NULL);
@@ -172,7 +178,9 @@ uint64_t fstUnFinishedNodesFindCommPrefixAndSetOutput(FstUnFinishedNodes* node,
FstState fstStateCreateFrom(FstSlice* slice, CompiledAddr addr) {
FstState fs = {.state = EmptyFinal, .val = 0};
- if (addr == EMPTY_ADDRESS) { return fs; }
+ if (addr == EMPTY_ADDRESS) {
+ return fs;
+ }
uint8_t* data = fstSliceData(slice, NULL);
uint8_t v = data[addr];
@@ -229,7 +237,9 @@ void fstStateCompileForOneTrans(FstCountingWriter* w, CompiledAddr addr, FstTran
fstStateSetCommInput(&st, trn->inp);
bool null = false;
uint8_t inp = fstStateCommInput(&st, &null);
- if (null == true) { fstCountingWriterWrite(w, (char*)&trn->inp, sizeof(trn->inp)); }
+ if (null == true) {
+ fstCountingWriterWrite(w, (char*)&trn->inp, sizeof(trn->inp));
+ }
fstCountingWriterWrite(w, (char*)(&(st.val)), sizeof(st.val));
return;
}
@@ -263,7 +273,9 @@ void fstStateCompileForAnyTrans(FstCountingWriter* w, CompiledAddr addr, FstBuil
fstStateSetStateNtrans(&st, (uint8_t)sz);
if (anyOuts) {
- if (FST_BUILDER_NODE_IS_FINAL(node)) { fstCountingWriterPackUintIn(w, node->finalOutput, oSize); }
+ if (FST_BUILDER_NODE_IS_FINAL(node)) {
+ fstCountingWriterPackUintIn(w, node->finalOutput, oSize);
+ }
for (int32_t i = sz - 1; i >= 0; i--) {
FstTransition* t = taosArrayGet(node->trans, i);
fstCountingWriterPackUintIn(w, t->out, oSize);
@@ -428,7 +440,9 @@ Output fstStateOutput(FstState* s, FstNode* node) {
assert(s->state == OneTrans);
uint8_t oSizes = FST_GET_OUTPUT_PACK_SIZE(node->sizes);
- if (oSizes == 0) { return 0; }
+ if (oSizes == 0) {
+ return 0;
+ }
FstSlice* slice = &node->data;
uint8_t tSizes = FST_GET_TRANSITION_PACK_SIZE(node->sizes);
@@ -440,7 +454,9 @@ Output fstStateOutputForAnyTrans(FstState* s, FstNode* node, uint64_t i) {
assert(s->state == AnyTrans);
uint8_t oSizes = FST_GET_OUTPUT_PACK_SIZE(node->sizes);
- if (oSizes == 0) { return 0; }
+ if (oSizes == 0) {
+ return 0;
+ }
FstSlice* slice = &node->data;
uint8_t* data = fstSliceData(slice, NULL);
uint64_t at = node->start - fstStateNtransLen(s) - 1 // pack size
@@ -453,7 +469,9 @@ Output fstStateOutputForAnyTrans(FstState* s, FstNode* node, uint64_t i) {
void fstStateSetFinalState(FstState* s, bool yes) {
assert(s->state == AnyTrans);
- if (yes) { s->val |= 0b01000000; }
+ if (yes) {
+ s->val |= 0b01000000;
+ }
return;
}
bool fstStateIsFinalState(FstState* s) {
@@ -463,7 +481,9 @@ bool fstStateIsFinalState(FstState* s) {
void fstStateSetStateNtrans(FstState* s, uint8_t n) {
assert(s->state == AnyTrans);
- if (n <= 0b00111111) { s->val = (s->val & 0b11000000) | n; }
+ if (n <= 0b00111111) {
+ s->val = (s->val & 0b11000000) | n;
+ }
return;
}
// state_ntrans
@@ -495,7 +515,9 @@ uint64_t fstStateNtransLen(FstState* s) {
uint64_t fstStateNtrans(FstState* s, FstSlice* slice) {
bool null = false;
uint8_t n = fstStateStateNtrans(s, &null);
- if (null != true) { return n; }
+ if (null != true) {
+ return n;
+ }
int32_t len;
uint8_t* data = fstSliceData(slice, &len);
n = data[len - 2];
@@ -505,7 +527,9 @@ uint64_t fstStateNtrans(FstState* s, FstSlice* slice) {
}
Output fstStateFinalOutput(FstState* s, uint64_t version, FstSlice* slice, PackSizes sizes, uint64_t nTrans) {
uint8_t oSizes = FST_GET_OUTPUT_PACK_SIZE(sizes);
- if (oSizes == 0 || !fstStateIsFinalState(s)) { return 0; }
+ if (oSizes == 0 || !fstStateIsFinalState(s)) {
+ return 0;
+ }
uint64_t at = FST_SLICE_LEN(slice) - 1 - fstStateNtransLen(s) - 1 // pack size
- fstStateTotalTransSize(s, version, sizes, nTrans) - (nTrans * oSizes) - oSizes;
@@ -522,7 +546,9 @@ uint64_t fstStateFindInput(FstState* s, FstNode* node, uint8_t b, bool* null) {
uint8_t* data = fstSliceData(slice, &dlen);
uint64_t i = data[at + b];
// uint64_t i = slice->data[slice->start + at + b];
- if (i >= node->nTrans) { *null = true; }
+ if (i >= node->nTrans) {
+ *null = true;
+ }
return i;
} else {
uint64_t start = node->start - fstStateNtransLen(s) - 1 // pack size
@@ -539,7 +565,9 @@ uint64_t fstStateFindInput(FstState* s, FstNode* node, uint8_t b, bool* null) {
return node->nTrans - i - 1; // bug
}
}
- if (i == len) { *null = true; }
+ if (i == len) {
+ *null = true;
+ }
fstSliceDestroy(&t);
}
}
@@ -548,7 +576,9 @@ uint64_t fstStateFindInput(FstState* s, FstNode* node, uint8_t b, bool* null) {
FstNode* fstNodeCreate(int64_t version, CompiledAddr addr, FstSlice* slice) {
FstNode* n = (FstNode*)malloc(sizeof(FstNode));
- if (n == NULL) { return NULL; }
+ if (n == NULL) {
+ return NULL;
+ }
FstState st = fstStateCreateFrom(slice, addr);
@@ -614,7 +644,9 @@ void fstNodeDestroy(FstNode* node) {
}
FstTransitions* fstNodeTransitions(FstNode* node) {
FstTransitions* t = malloc(sizeof(FstTransitions));
- if (NULL == t) { return NULL; }
+ if (NULL == t) {
+ return NULL;
+ }
FstRange range = {.start = 0, .end = FST_NODE_LEN(node)};
t->range = range;
t->node = node;
@@ -721,7 +753,9 @@ bool fstBuilderNodeCompileTo(FstBuilderNode* b, FstCountingWriter* wrt, Compiled
FstBuilder* fstBuilderCreate(void* w, FstType ty) {
FstBuilder* b = malloc(sizeof(FstBuilder));
- if (NULL == b) { return b; }
+ if (NULL == b) {
+ return b;
+ }
b->wrt = fstCountingWriterCreate(w);
b->unfinished = fstUnFinishedNodesCreate();
@@ -735,15 +769,17 @@ FstBuilder* fstBuilderCreate(void* w, FstType ty) {
taosEncodeFixedU64(&pBuf64, VERSION);
fstCountingWriterWrite(b->wrt, buf64, sizeof(buf64));
- memset(buf64, 0, sizeof(buf64));
pBuf64 = buf64;
+ memset(buf64, 0, sizeof(buf64));
taosEncodeFixedU64(&pBuf64, ty);
fstCountingWriterWrite(b->wrt, buf64, sizeof(buf64));
return b;
}
void fstBuilderDestroy(FstBuilder* b) {
- if (b == NULL) { return; }
+ if (b == NULL) {
+ return;
+ }
fstCountingWriterDestroy(b->wrt);
fstUnFinishedNodesDestroy(b->unfinished);
@@ -830,6 +866,7 @@ void fstBuilderCompileFrom(FstBuilder* b, uint64_t istate) {
fstUnFinishedNodesTopLastFreeze(b->unfinished, addr);
return;
}
+
CompiledAddr fstBuilderCompile(FstBuilder* b, FstBuilderNode* bn) {
if (FST_BUILDER_NODE_IS_FINAL(bn) && FST_BUILDER_NODE_TRANS_ISEMPTY(bn) && FST_BUILDER_NODE_FINALOUTPUT_ISZERO(bn)) {
return EMPTY_ADDRESS;
@@ -844,7 +881,9 @@ CompiledAddr fstBuilderCompile(FstBuilder* b, FstBuilderNode* bn) {
fstBuilderNodeCompileTo(bn, b->wrt, b->lastAddr, startAddr);
b->lastAddr = (CompiledAddr)(FST_WRITER_COUNT(b->wrt) - 1);
- if (entry->state == NOTFOUND) { FST_REGISTRY_CELL_INSERT(entry->cell, b->lastAddr); }
+ if (entry->state == NOTFOUND) {
+ FST_REGISTRY_CELL_INSERT(entry->cell, b->lastAddr);
+ }
fstRegistryEntryDestroy(entry);
return b->lastAddr;
@@ -887,7 +926,9 @@ FstSlice fstNodeAsSlice(FstNode* node) {
FstLastTransition* fstLastTransitionCreate(uint8_t inp, Output out) {
FstLastTransition* trn = malloc(sizeof(FstLastTransition));
- if (trn == NULL) { return NULL; }
+ if (trn == NULL) {
+ return NULL;
+ }
trn->inp = inp;
trn->out = out;
@@ -897,7 +938,9 @@ FstLastTransition* fstLastTransitionCreate(uint8_t inp, Output out) {
void fstLastTransitionDestroy(FstLastTransition* trn) { free(trn); }
void fstBuilderNodeUnfinishedLastCompiled(FstBuilderNodeUnfinished* unNode, CompiledAddr addr) {
FstLastTransition* trn = unNode->last;
- if (trn == NULL) { return; }
+ if (trn == NULL) {
+ return;
+ }
FstTransition t = {.inp = trn->inp, .out = trn->out, .addr = addr};
taosArrayPush(unNode->node->trans, &t);
fstLastTransitionDestroy(trn);
@@ -906,27 +949,35 @@ void fstBuilderNodeUnfinishedLastCompiled(FstBuilderNodeUnfinished* unNode, Comp
}
void fstBuilderNodeUnfinishedAddOutputPrefix(FstBuilderNodeUnfinished* unNode, Output out) {
- if (FST_BUILDER_NODE_IS_FINAL(unNode->node)) { unNode->node->finalOutput += out; }
+ if (FST_BUILDER_NODE_IS_FINAL(unNode->node)) {
+ unNode->node->finalOutput += out;
+ }
size_t sz = taosArrayGetSize(unNode->node->trans);
for (size_t i = 0; i < sz; i++) {
FstTransition* trn = taosArrayGet(unNode->node->trans, i);
trn->out += out;
}
- if (unNode->last) { unNode->last->out += out; }
+ if (unNode->last) {
+ unNode->last->out += out;
+ }
return;
}
Fst* fstCreate(FstSlice* slice) {
int32_t slen;
char* buf = fstSliceData(slice, &slen);
- if (slen < 36) { return NULL; }
+ if (slen < 36) {
+ return NULL;
+ }
uint64_t len = slen;
uint64_t skip = 0;
uint64_t version;
taosDecodeFixedU64(buf, &version);
skip += sizeof(version);
- if (version == 0 || version > VERSION) { return NULL; }
+ if (version == 0 || version > VERSION) {
+ return NULL;
+ }
uint64_t type;
taosDecodeFixedU64(buf + skip, &type);
@@ -949,10 +1000,14 @@ Fst* fstCreate(FstSlice* slice) {
taosDecodeFixedU64(buf + len, &fstLen);
// TODO(validate root addr)
Fst* fst = (Fst*)calloc(1, sizeof(Fst));
- if (fst == NULL) { return NULL; }
+ if (fst == NULL) {
+ return NULL;
+ }
fst->meta = (FstMeta*)malloc(sizeof(FstMeta));
- if (NULL == fst->meta) { goto FST_CREAT_FAILED; }
+ if (NULL == fst->meta) {
+ goto FST_CREAT_FAILED;
+ }
fst->meta->version = version;
fst->meta->rootAddr = rootAddr;
@@ -983,7 +1038,7 @@ void fstDestroy(Fst* fst) {
bool fstGet(Fst* fst, FstSlice* b, Output* out) {
// dec lock range
- pthread_mutex_lock(&fst->mtx);
+ // pthread_mutex_lock(&fst->mtx);
FstNode* root = fstGetRoot(fst);
Output tOut = 0;
int32_t len;
@@ -996,7 +1051,7 @@ bool fstGet(Fst* fst, FstSlice* b, Output* out) {
uint8_t inp = data[i];
Output res = 0;
if (false == fstNodeFindInput(root, inp, &res)) {
- pthread_mutex_unlock(&fst->mtx);
+ // pthread_mutex_unlock(&fst->mtx);
return false;
}
@@ -1007,7 +1062,7 @@ bool fstGet(Fst* fst, FstSlice* b, Output* out) {
taosArrayPush(nodes, &root);
}
if (!FST_NODE_IS_FINAL(root)) {
- pthread_mutex_unlock(&fst->mtx);
+ // pthread_mutex_unlock(&fst->mtx);
return false;
} else {
tOut = tOut + FST_NODE_FINAL_OUTPUT(root);
@@ -1018,8 +1073,8 @@ bool fstGet(Fst* fst, FstSlice* b, Output* out) {
fstNodeDestroy(*node);
}
taosArrayDestroy(nodes);
- fst->root = NULL;
- pthread_mutex_unlock(&fst->mtx);
+ // fst->root = NULL;
+ // pthread_mutex_unlock(&fst->mtx);
*out = tOut;
return true;
}
@@ -1028,7 +1083,9 @@ FstStreamBuilder* fstSearch(Fst* fst, AutomationCtx* ctx) {
return fstStreamBuilderCreate(fst, ctx);
}
StreamWithState* streamBuilderIntoStream(FstStreamBuilder* sb) {
- if (sb == NULL) { return NULL; }
+ if (sb == NULL) {
+ return NULL;
+ }
return streamWithStateCreate(sb->fst, sb->aut, sb->min, sb->max);
}
FstStreamWithStateBuilder* fstSearchWithState(Fst* fst, AutomationCtx* ctx) {
@@ -1039,15 +1096,6 @@ FstStreamWithStateBuilder* fstSearchWithState(Fst* fst, AutomationCtx* ctx) {
FstNode* fstGetRoot(Fst* fst) {
CompiledAddr rAddr = fstGetRootAddr(fst);
return fstGetNode(fst, rAddr);
- // pthread_mutex_lock(&fst->mtx);
- // if (fst->root != NULL) {
- // // pthread_mutex_unlock(&fst->mtx);
- // return fst->root;
- //}
- // CompiledAddr rAddr = fstGetRootAddr(fst);
- // fst->root = fstGetNode(fst, rAddr);
- //// pthread_mutex_unlock(&fst->mtx);
- // return fst->root;
}
FstNode* fstGetNode(Fst* fst, CompiledAddr addr) {
@@ -1074,14 +1122,18 @@ bool fstVerify(Fst* fst) {
uint32_t len, checkSum = fst->meta->checkSum;
uint8_t* data = fstSliceData(fst->data, &len);
TSCKSUM initSum = 0;
- if (!taosCheckChecksumWhole(data, len)) { return false; }
+ if (!taosCheckChecksumWhole(data, len)) {
+ return false;
+ }
return true;
}
// data bound function
FstBoundWithData* fstBoundStateCreate(FstBound type, FstSlice* data) {
FstBoundWithData* b = calloc(1, sizeof(FstBoundWithData));
- if (b == NULL) { return NULL; }
+ if (b == NULL) {
+ return NULL;
+ }
if (data != NULL) {
b->data = fstSliceCopy(data, data->start, data->end);
@@ -1118,7 +1170,9 @@ void fstBoundDestroy(FstBoundWithData* bound) { free(bound); }
StreamWithState* streamWithStateCreate(Fst* fst, AutomationCtx* automation, FstBoundWithData* min,
FstBoundWithData* max) {
StreamWithState* sws = calloc(1, sizeof(StreamWithState));
- if (sws == NULL) { return NULL; }
+ if (sws == NULL) {
+ return NULL;
+ }
sws->fst = fst;
sws->aut = automation;
@@ -1134,7 +1188,9 @@ StreamWithState* streamWithStateCreate(Fst* fst, AutomationCtx* automation, FstB
return sws;
}
void streamWithStateDestroy(StreamWithState* sws) {
- if (sws == NULL) { return; }
+ if (sws == NULL) {
+ return;
+ }
taosArrayDestroy(sws->inp);
taosArrayDestroyEx(sws->stack, streamStateDestroy);
@@ -1200,7 +1256,9 @@ bool streamWithStateSeekMin(StreamWithState* sws, FstBoundWithData* min) {
uint64_t i = 0;
for (i = trans->range.start; i < trans->range.end; i++) {
FstTransition trn;
- if (fstNodeGetTransitionAt(node, i, &trn) && trn.inp > b) { break; }
+ if (fstNodeGetTransitionAt(node, i, &trn) && trn.inp > b) {
+ break;
+ }
}
StreamState s = {.node = node, .trans = i, .out = {.null = false, .out = out}, .autState = autState};
@@ -1248,7 +1306,9 @@ StreamWithStateResult* streamWithStateNextWith(StreamWithState* sws, StreamCallb
while (taosArrayGetSize(sws->stack) > 0) {
StreamState* p = (StreamState*)taosArrayPop(sws->stack);
if (p->trans >= FST_NODE_LEN(p->node) || !automFuncs[aut->type].canMatch(aut, p->autState)) {
- if (FST_NODE_ADDR(p->node) != fstGetRootAddr(sws->fst)) { taosArrayPop(sws->inp); }
+ if (FST_NODE_ADDR(p->node) != fstGetRootAddr(sws->fst)) {
+ taosArrayPop(sws->inp);
+ }
streamStateDestroy(p);
continue;
}
@@ -1267,7 +1327,9 @@ StreamWithStateResult* streamWithStateNextWith(StreamWithState* sws, StreamCallb
if (FST_NODE_IS_FINAL(nextNode)) {
// void *eofState = sws->aut->acceptEof(nextState);
void* eofState = automFuncs[aut->type].acceptEof(aut, nextState);
- if (eofState != NULL) { isMatch = automFuncs[aut->type].isMatch(aut, eofState); }
+ if (eofState != NULL) {
+ isMatch = automFuncs[aut->type].isMatch(aut, eofState);
+ }
}
StreamState s1 = {.node = p->node, .trans = p->trans + 1, .out = p->out, .autState = p->autState};
taosArrayPush(sws->stack, &s1);
@@ -1277,24 +1339,26 @@ StreamWithStateResult* streamWithStateNextWith(StreamWithState* sws, StreamCallb
size_t isz = taosArrayGetSize(sws->inp);
uint8_t* buf = (uint8_t*)malloc(isz * sizeof(uint8_t));
- for (uint32_t i = 0; i < isz; i++) { buf[i] = *(uint8_t*)taosArrayGet(sws->inp, i); }
+ for (uint32_t i = 0; i < isz; i++) {
+ buf[i] = *(uint8_t*)taosArrayGet(sws->inp, i);
+ }
FstSlice slice = fstSliceCreate(buf, taosArrayGetSize(sws->inp));
if (fstBoundWithDataExceededBy(sws->endAt, &slice)) {
taosArrayDestroyEx(sws->stack, streamStateDestroy);
sws->stack = (SArray*)taosArrayInit(256, sizeof(StreamState));
- free(buf);
+ tfree(buf);
fstSliceDestroy(&slice);
return NULL;
}
if (FST_NODE_IS_FINAL(nextNode) && isMatch) {
FstOutput fOutput = {.null = false, .out = out + FST_NODE_FINAL_OUTPUT(nextNode)};
StreamWithStateResult* result = swsResultCreate(&slice, fOutput, tState);
- free(buf);
+ tfree(buf);
fstSliceDestroy(&slice);
taosArrayDestroy(nodes);
return result;
}
- free(buf);
+ tfree(buf);
fstSliceDestroy(&slice);
}
for (size_t i = 0; i < taosArrayGetSize(nodes); i++) {
@@ -1307,16 +1371,19 @@ StreamWithStateResult* streamWithStateNextWith(StreamWithState* sws, StreamCallb
StreamWithStateResult* swsResultCreate(FstSlice* data, FstOutput fOut, void* state) {
StreamWithStateResult* result = calloc(1, sizeof(StreamWithStateResult));
- if (result == NULL) { return NULL; }
+ if (result == NULL) {
+ return NULL;
+ }
result->data = fstSliceCopy(data, 0, FST_SLICE_LEN(data) - 1);
result->out = fOut;
result->state = state;
-
return result;
}
void swsResultDestroy(StreamWithStateResult* result) {
- if (NULL == result) { return; }
+ if (NULL == result) {
+ return;
+ }
fstSliceDestroy(&result->data);
startWithStateValueDestroy(result->state);
@@ -1324,16 +1391,18 @@ void swsResultDestroy(StreamWithStateResult* result) {
}
void streamStateDestroy(void* s) {
- if (NULL == s) { return; }
+ if (NULL == s) {
+ return;
+ }
StreamState* ss = (StreamState*)s;
-
fstNodeDestroy(ss->node);
- // free(s->autoState);
}
FstStreamBuilder* fstStreamBuilderCreate(Fst* fst, AutomationCtx* aut) {
FstStreamBuilder* b = calloc(1, sizeof(FstStreamBuilder));
- if (NULL == b) { return NULL; }
+ if (NULL == b) {
+ return NULL;
+ }
b->fst = fst;
b->aut = aut;
@@ -1349,8 +1418,9 @@ void fstStreamBuilderDestroy(FstStreamBuilder* b) {
free(b);
}
FstStreamBuilder* fstStreamBuilderRange(FstStreamBuilder* b, FstSlice* val, RangeType type) {
- if (b == NULL) { return NULL; }
-
+ if (b == NULL) {
+ return NULL;
+ }
if (type == GE) {
b->min->type = Included;
fstSliceDestroy(&(b->min->data));
diff --git a/source/libs/index/src/index_fst_automation.c b/source/libs/index/src/index_fst_automation.c
index c6e3cee3e3..590ff294bf 100644
--- a/source/libs/index/src/index_fst_automation.c
+++ b/source/libs/index/src/index_fst_automation.c
@@ -17,7 +17,9 @@
StartWithStateValue* startWithStateValueCreate(StartWithStateKind kind, ValueType ty, void* val) {
StartWithStateValue* nsv = calloc(1, sizeof(StartWithStateValue));
- if (nsv == NULL) { return NULL; }
+ if (nsv == NULL) {
+ return NULL;
+ }
nsv->kind = kind;
nsv->type = ty;
@@ -35,7 +37,9 @@ StartWithStateValue* startWithStateValueCreate(StartWithStateKind kind, ValueTyp
}
void startWithStateValueDestroy(void* val) {
StartWithStateValue* sv = (StartWithStateValue*)val;
- if (sv == NULL) { return; }
+ if (sv == NULL) {
+ return;
+ }
if (sv->type == FST_INT) {
//
@@ -48,7 +52,9 @@ void startWithStateValueDestroy(void* val) {
}
StartWithStateValue* startWithStateValueDump(StartWithStateValue* sv) {
StartWithStateValue* nsv = calloc(1, sizeof(StartWithStateValue));
- if (nsv == NULL) { return NULL; }
+ if (nsv == NULL) {
+ return NULL;
+ }
nsv->kind = sv->kind;
nsv->type = sv->type;
@@ -88,10 +94,14 @@ static bool prefixCanMatch(AutomationCtx* ctx, void* sv) {
static bool prefixWillAlwaysMatch(AutomationCtx* ctx, void* state) { return true; }
static void* prefixAccept(AutomationCtx* ctx, void* state, uint8_t byte) {
StartWithStateValue* ssv = (StartWithStateValue*)state;
- if (ssv == NULL || ctx == NULL) { return NULL; }
+ if (ssv == NULL || ctx == NULL) {
+ return NULL;
+ }
char* data = ctx->data;
- if (ssv->kind == Done) { return startWithStateValueCreate(Done, FST_INT, &ssv->val); }
+ if (ssv->kind == Done) {
+ return startWithStateValueCreate(Done, FST_INT, &ssv->val);
+ }
if ((strlen(data) > ssv->val) && data[ssv->val] == byte) {
int val = ssv->val + 1;
@@ -128,7 +138,9 @@ AutomationFunc automFuncs[] = {
AutomationCtx* automCtxCreate(void* data, AutomationType atype) {
AutomationCtx* ctx = calloc(1, sizeof(AutomationCtx));
- if (ctx == NULL) { return NULL; }
+ if (ctx == NULL) {
+ return NULL;
+ }
StartWithStateValue* sv = NULL;
if (atype == AUTOMATION_ALWAYS) {
diff --git a/source/libs/index/src/index_fst_util.c b/source/libs/index/src/index_fst_util.c
index da1e177a18..f08a48c34e 100644
--- a/source/libs/index/src/index_fst_util.c
+++ b/source/libs/index/src/index_fst_util.c
@@ -29,18 +29,6 @@ const uint64_t VERSION = 3;
const uint64_t TRANS_INDEX_THRESHOLD = 32;
-// uint8_t commonInput(uint8_t idx) {
-// if (idx == 0) { return -1; }
-// else {
-// return COMMON_INPUTS_INV[idx - 1];
-// }
-//}
-//
-// uint8_t commonIdx(uint8_t v, uint8_t max) {
-// uint8_t v = ((uint16_t)tCOMMON_INPUTS[v] + 1)%256;
-// return v > max ? 0: v;
-//}
-
uint8_t packSize(uint64_t n) {
if (n < (1u << 8)) {
return 1;
@@ -103,9 +91,6 @@ FstSlice fstSliceCreate(uint8_t* data, uint64_t len) {
FstSlice fstSliceCopy(FstSlice* s, int32_t start, int32_t end) {
FstString* str = s->str;
str->ref++;
- // uint8_t *buf = fstSliceData(s, &alen);
- // start = buf + start - (buf - s->start);
- // end = buf + end - (buf - s->start);
FstSlice t = {.str = str, .start = start + s->start, .end = end + s->start};
return t;
@@ -130,19 +115,19 @@ FstSlice fstSliceDeepCopy(FstSlice* s, int32_t start, int32_t end) {
ans.end = tlen - 1;
return ans;
}
-bool fstSliceIsEmpty(FstSlice* s) {
- return s->str == NULL || s->str->len == 0 || s->start < 0 || s->end < 0;
-}
+bool fstSliceIsEmpty(FstSlice* s) { return s->str == NULL || s->str->len == 0 || s->start < 0 || s->end < 0; }
uint8_t* fstSliceData(FstSlice* s, int32_t* size) {
FstString* str = s->str;
- if (size != NULL) { *size = s->end - s->start + 1; }
+ if (size != NULL) {
+ *size = s->end - s->start + 1;
+ }
return str->data + s->start;
}
void fstSliceDestroy(FstSlice* s) {
FstString* str = s->str;
str->ref--;
- if (str->ref <= 0) {
+ if (str->ref == 0) {
free(str->data);
free(str);
s->str = NULL;
diff --git a/source/libs/index/src/index_tfile.c b/source/libs/index/src/index_tfile.c
index 98fede4f7b..87cc48146b 100644
--- a/source/libs/index/src/index_tfile.c
+++ b/source/libs/index/src/index_tfile.c
@@ -13,8 +13,6 @@ p *
* along with this program. If not, see .
*/
-//#include
-//#include
#include "index_tfile.h"
#include "index.h"
#include "index_fst.h"
@@ -61,7 +59,9 @@ static void tfileGenFileFullName(char* fullname, const char* path, uint64_t s
TFileCache* tfileCacheCreate(const char* path) {
TFileCache* tcache = calloc(1, sizeof(TFileCache));
- if (tcache == NULL) { return NULL; }
+ if (tcache == NULL) {
+ return NULL;
+ }
tcache->tableCache = taosHashInit(8, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK);
tcache->capacity = 64;
@@ -98,7 +98,9 @@ End:
return NULL;
}
void tfileCacheDestroy(TFileCache* tcache) {
- if (tcache == NULL) { return; }
+ if (tcache == NULL) {
+ return;
+ }
// free table cache
TFileReader** reader = taosHashIterate(tcache->tableCache, NULL);
@@ -119,7 +121,9 @@ TFileReader* tfileCacheGet(TFileCache* tcache, ICacheKey* key) {
int32_t sz = indexSerialCacheKey(key, buf);
assert(sz < sizeof(buf));
TFileReader** reader = taosHashGet(tcache->tableCache, buf, sz);
- if (reader == NULL) { return NULL; }
+ if (reader == NULL) {
+ return NULL;
+ }
tfileReaderRef(*reader);
return *reader;
@@ -142,7 +146,9 @@ void tfileCachePut(TFileCache* tcache, ICacheKey* key, TFileReader* reader) {
}
TFileReader* tfileReaderCreate(WriterCtx* ctx) {
TFileReader* reader = calloc(1, sizeof(TFileReader));
- if (reader == NULL) { return NULL; }
+ if (reader == NULL) {
+ return NULL;
+ }
reader->ctx = ctx;
@@ -169,7 +175,9 @@ TFileReader* tfileReaderCreate(WriterCtx* ctx) {
return reader;
}
void tfileReaderDestroy(TFileReader* reader) {
- if (reader == NULL) { return; }
+ if (reader == NULL) {
+ return;
+ }
// T_REF_INC(reader);
fstDestroy(reader->fst);
writerCtxDestroy(reader->ctx, reader->remove);
@@ -209,7 +217,9 @@ TFileWriter* tfileWriterOpen(char* path, uint64_t suid, int32_t version, const c
tfileGenFileFullName(fullname, path, suid, colName, version);
// indexInfo("open write file name %s", fullname);
WriterCtx* wcx = writerCtxCreate(TFile, fullname, false, 1024 * 1024 * 64);
- if (wcx == NULL) { return NULL; }
+ if (wcx == NULL) {
+ return NULL;
+ }
TFileHeader tfh = {0};
tfh.suid = suid;
@@ -225,7 +235,9 @@ TFileReader* tfileReaderOpen(char* path, uint64_t suid, int32_t version, const c
WriterCtx* wc = writerCtxCreate(TFile, fullname, true, 1024 * 1024 * 1024);
indexInfo("open read file name:%s, size: %d", wc->file.buf, wc->file.size);
- if (wc == NULL) { return NULL; }
+ if (wc == NULL) {
+ return NULL;
+ }
TFileReader* reader = tfileReaderCreate(wc);
return reader;
@@ -316,19 +328,25 @@ int tfileWriterPut(TFileWriter* tw, void* data, bool order) {
return 0;
}
void tfileWriterClose(TFileWriter* tw) {
- if (tw == NULL) { return; }
+ if (tw == NULL) {
+ return;
+ }
writerCtxDestroy(tw->ctx, false);
free(tw);
}
void tfileWriterDestroy(TFileWriter* tw) {
- if (tw == NULL) { return; }
+ if (tw == NULL) {
+ return;
+ }
writerCtxDestroy(tw->ctx, false);
free(tw);
}
IndexTFile* indexTFileCreate(const char* path) {
TFileCache* cache = tfileCacheCreate(path);
- if (cache == NULL) { return NULL; }
+ if (cache == NULL) {
+ return NULL;
+ }
IndexTFile* tfile = calloc(1, sizeof(IndexTFile));
if (tfile == NULL) {
@@ -340,21 +358,27 @@ IndexTFile* indexTFileCreate(const char* path) {
return tfile;
}
void indexTFileDestroy(IndexTFile* tfile) {
- if (tfile == NULL) { return; }
+ if (tfile == NULL) {
+ return;
+ }
tfileCacheDestroy(tfile->cache);
free(tfile);
}
int indexTFileSearch(void* tfile, SIndexTermQuery* query, SArray* result) {
int ret = -1;
- if (tfile == NULL) { return ret; }
+ if (tfile == NULL) {
+ return ret;
+ }
IndexTFile* pTfile = (IndexTFile*)tfile;
SIndexTerm* term = query->term;
ICacheKey key = {.suid = term->suid, .colType = term->colType, .colName = term->colName, .nColName = term->nColName};
TFileReader* reader = tfileCacheGet(pTfile->cache, &key);
- if (reader == NULL) { return 0; }
+ if (reader == NULL) {
+ return 0;
+ }
return tfileReaderSearch(reader, query, result);
}
@@ -373,7 +397,9 @@ static bool tfileIteratorNext(Iterate* iiter) {
TFileFstIter* tIter = iiter->iter;
StreamWithStateResult* rt = streamWithStateNextWith(tIter->st, NULL);
- if (rt == NULL) { return false; }
+ if (rt == NULL) {
+ return false;
+ }
int32_t sz = 0;
char* ch = (char*)fstSliceData(&rt->data, &sz);
@@ -383,7 +409,9 @@ static bool tfileIteratorNext(Iterate* iiter) {
offset = (uint64_t)(rt->out.out);
swsResultDestroy(rt);
// set up iterate value
- if (tfileReaderLoadTableIds(tIter->rdr, offset, iv->val) != 0) { return false; }
+ if (tfileReaderLoadTableIds(tIter->rdr, offset, iv->val) != 0) {
+ return false;
+ }
iv->colVal = colVal;
return true;
@@ -394,7 +422,9 @@ static IterateValue* tifileIterateGetValue(Iterate* iter) { return &iter->val; }
static TFileFstIter* tfileFstIteratorCreate(TFileReader* reader) {
TFileFstIter* tIter = calloc(1, sizeof(TFileFstIter));
- if (tIter == NULL) { return NULL; }
+ if (tIter == NULL) {
+ return NULL;
+ }
tIter->ctx = automCtxCreate(NULL, AUTOMATION_ALWAYS);
tIter->fb = fstSearch(reader->fst, tIter->ctx);
@@ -404,7 +434,9 @@ static TFileFstIter* tfileFstIteratorCreate(TFileReader* reader) {
}
Iterate* tfileIteratorCreate(TFileReader* reader) {
- if (reader == NULL) { return NULL; }
+ if (reader == NULL) {
+ return NULL;
+ }
Iterate* iter = calloc(1, sizeof(Iterate));
iter->iter = tfileFstIteratorCreate(reader);
@@ -419,7 +451,9 @@ Iterate* tfileIteratorCreate(TFileReader* reader) {
return iter;
}
void tfileIteratorDestroy(Iterate* iter) {
- if (iter == NULL) { return; }
+ if (iter == NULL) {
+ return;
+ }
IterateValue* iv = &iter->val;
iterateValueDestroy(iv, true);
@@ -434,7 +468,9 @@ void tfileIteratorDestroy(Iterate* iter) {
}
TFileReader* tfileGetReaderByCol(IndexTFile* tf, uint64_t suid, char* colName) {
- if (tf == NULL) { return NULL; }
+ if (tf == NULL) {
+ return NULL;
+ }
ICacheKey key = {.suid = suid, .colType = TSDB_DATA_TYPE_BINARY, .colName = colName, .nColName = strlen(colName)};
return tfileCacheGet(tf->cache, &key);
}
@@ -446,7 +482,9 @@ static int tfileUidCompare(const void* a, const void* b) {
}
static int tfileStrCompare(const void* a, const void* b) {
int ret = strcmp((char*)a, (char*)b);
- if (ret == 0) { return ret; }
+ if (ret == 0) {
+ return ret;
+ }
return ret < 0 ? -1 : 1;
}
@@ -461,13 +499,17 @@ static int tfileValueCompare(const void* a, const void* b, const void* param) {
TFileValue* tfileValueCreate(char* val) {
TFileValue* tf = calloc(1, sizeof(TFileValue));
- if (tf == NULL) { return NULL; }
+ if (tf == NULL) {
+ return NULL;
+ }
tf->colVal = tstrdup(val);
tf->tableId = taosArrayInit(32, sizeof(uint64_t));
return tf;
}
int tfileValuePush(TFileValue* tf, uint64_t val) {
- if (tf == NULL) { return -1; }
+ if (tf == NULL) {
+ return -1;
+ }
taosArrayPush(tf->tableId, &val);
return 0;
}
@@ -489,7 +531,9 @@ static int tfileWriteFstOffset(TFileWriter* tw, int32_t offset) {
int32_t fstOffset = offset + sizeof(tw->header.fstOffset);
tw->header.fstOffset = fstOffset;
- if (sizeof(fstOffset) != tw->ctx->write(tw->ctx, (char*)&fstOffset, sizeof(fstOffset))) { return -1; }
+ if (sizeof(fstOffset) != tw->ctx->write(tw->ctx, (char*)&fstOffset, sizeof(fstOffset))) {
+ return -1;
+ }
indexInfo("tfile write fst offset: %d", tw->ctx->size(tw->ctx));
tw->offset += sizeof(fstOffset);
return 0;
@@ -502,7 +546,9 @@ static int tfileWriteHeader(TFileWriter* writer) {
indexInfo("tfile pre write header size: %d", writer->ctx->size(writer->ctx));
int nwrite = writer->ctx->write(writer->ctx, buf, sizeof(buf));
- if (sizeof(buf) != nwrite) { return -1; }
+ if (sizeof(buf) != nwrite) {
+ return -1;
+ }
indexInfo("tfile after write header size: %d", writer->ctx->size(writer->ctx));
writer->offset = nwrite;
@@ -556,7 +602,9 @@ static int tfileReaderLoadFst(TFileReader* reader) {
static int FST_MAX_SIZE = 64 * 1024 * 1024;
char* buf = calloc(1, sizeof(char) * FST_MAX_SIZE);
- if (buf == NULL) { return -1; }
+ if (buf == NULL) {
+ return -1;
+ }
WriterCtx* ctx = reader->ctx;
int size = ctx->size(ctx);
@@ -586,12 +634,16 @@ static int tfileReaderLoadTableIds(TFileReader* reader, int32_t offset, SArray*
int32_t total = sizeof(uint64_t) * nid;
char* buf = calloc(1, total);
- if (buf == NULL) { return -1; }
+ if (buf == NULL) {
+ return -1;
+ }
nread = ctx->readFrom(ctx, buf, total, offset + sizeof(nid));
assert(total == nread);
- for (int32_t i = 0; i < nid; i++) { taosArrayPush(result, (uint64_t*)buf + i); }
+ for (int32_t i = 0; i < nid; i++) {
+ taosArrayPush(result, (uint64_t*)buf + i);
+ }
free(buf);
return 0;
}
@@ -615,13 +667,17 @@ static int tfileReaderVerify(TFileReader* reader) {
}
void tfileReaderRef(TFileReader* reader) {
- if (reader == NULL) { return; }
+ if (reader == NULL) {
+ return;
+ }
int ref = T_REF_INC(reader);
UNUSED(ref);
}
void tfileReaderUnRef(TFileReader* reader) {
- if (reader == NULL) { return; }
+ if (reader == NULL) {
+ return;
+ }
int ref = T_REF_DEC(reader);
if (ref == 0) {
// do nothing
@@ -637,11 +693,15 @@ static SArray* tfileGetFileList(const char* path) {
uint32_t version;
DIR* dir = opendir(path);
- if (NULL == dir) { return NULL; }
+ if (NULL == dir) {
+ return NULL;
+ }
struct dirent* entry;
while ((entry = readdir(dir)) != NULL) {
char* file = entry->d_name;
- if (0 != tfileParseFileName(file, &suid, buf, &version)) { continue; }
+ if (0 != tfileParseFileName(file, &suid, buf, &version)) {
+ continue;
+ }
size_t len = strlen(path) + 1 + strlen(file) + 1;
char* buf = calloc(1, len);
diff --git a/source/libs/index/test/CMakeLists.txt b/source/libs/index/test/CMakeLists.txt
index 3957554748..665dfd7318 100644
--- a/source/libs/index/test/CMakeLists.txt
+++ b/source/libs/index/test/CMakeLists.txt
@@ -1,5 +1,7 @@
add_executable(indexTest "")
add_executable(fstTest "")
+add_executable(fstUT "")
+
target_sources(indexTest
PRIVATE
"indexTests.cc"
@@ -8,6 +10,11 @@ target_sources(fstTest
PRIVATE
"fstTest.cc"
)
+
+target_sources(fstUT
+ PRIVATE
+ "fstUT.cc"
+)
target_include_directories ( indexTest
PUBLIC
"${CMAKE_SOURCE_DIR}/include/libs/index"
@@ -18,6 +25,12 @@ target_include_directories ( fstTest
"${CMAKE_SOURCE_DIR}/include/libs/index"
"${CMAKE_CURRENT_SOURCE_DIR}/../inc"
)
+
+target_include_directories ( fstUT
+ PUBLIC
+ "${CMAKE_SOURCE_DIR}/include/libs/index"
+ "${CMAKE_CURRENT_SOURCE_DIR}/../inc"
+)
target_link_libraries (indexTest
os
util
@@ -32,6 +45,13 @@ target_link_libraries (fstTest
gtest_main
index
)
+target_link_libraries (fstUT
+ os
+ util
+ common
+ gtest_main
+ index
+)
#add_test(
diff --git a/source/libs/index/test/fstTest.cc b/source/libs/index/test/fstTest.cc
index a2c0046f9a..65118a2bce 100644
--- a/source/libs/index/test/fstTest.cc
+++ b/source/libs/index/test/fstTest.cc
@@ -58,7 +58,9 @@ class FstReadMemory {
bool init() {
char* buf = (char*)calloc(1, sizeof(char) * _size);
int nRead = fstCountingWriterRead(_w, (uint8_t*)buf, _size);
- if (nRead <= 0) { return false; }
+ if (nRead <= 0) {
+ return false;
+ }
_size = nRead;
_s = fstSliceCreate((uint8_t*)buf, _size);
_fst = fstCreate(&_s);
@@ -97,7 +99,8 @@ class FstReadMemory {
printf("key: %s, val: %" PRIu64 "\n", key.c_str(), (uint64_t)(rt->out.out));
swsResultDestroy(rt);
}
- for (size_t i = 0; i < result.size(); i++) {}
+ for (size_t i = 0; i < result.size(); i++) {
+ }
std::cout << std::endl;
return true;
}
@@ -173,7 +176,9 @@ void checkMillonWriteAndReadOfFst() {
delete fw;
FstReadMemory* fr = new FstReadMemory(1024 * 64 * 1024);
- if (fr->init()) { printf("success to init fst read"); }
+ if (fr->init()) {
+ printf("success to init fst read");
+ }
Performance_fstReadRecords(fr);
tfCleanup();
diff --git a/source/libs/index/test/fstUT.cc b/source/libs/index/test/fstUT.cc
new file mode 100644
index 0000000000..47215693bb
--- /dev/null
+++ b/source/libs/index/test/fstUT.cc
@@ -0,0 +1,232 @@
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "index.h"
+#include "indexInt.h"
+#include "index_cache.h"
+#include "index_fst.h"
+#include "index_fst_counting_writer.h"
+#include "index_fst_util.h"
+#include "index_tfile.h"
+#include "tglobal.h"
+#include "tskiplist.h"
+#include "tutil.h"
+#include "ulog.h"
+
+static std::string dir = "/tmp/index";
+
+static char indexlog[PATH_MAX] = {0};
+static char tindex[PATH_MAX] = {0};
+static char tindexDir[PATH_MAX] = {0};
+
+static void EnvInit() {
+ tfInit();
+
+ std::string path = dir;
+ taosRemoveDir(path.c_str());
+ taosMkDir(path.c_str());
+ // init log file
+ snprintf(indexlog, PATH_MAX, "%s/tindex.idx", path.c_str());
+ if (taosInitLog(indexlog, tsNumOfLogLines, 1) != 0) {
+ printf("failed to init log");
+ }
+ // init index file
+ memset(tindex, 0, sizeof(tindex));
+ snprintf(tindex, PATH_MAX, "%s/tindex.idx", path.c_str());
+}
+static void EnvCleanup() {}
+class FstWriter {
+ public:
+ FstWriter() {
+ _wc = writerCtxCreate(TFile, tindex, false, 64 * 1024 * 1024);
+ _b = fstBuilderCreate(_wc, 0);
+ }
+ bool Put(const std::string& key, uint64_t val) {
+ // char buf[128] = {0};
+ // int len = 0;
+ // taosMbsToUcs4(key.c_str(), key.size(), buf, 128, &len);
+ // FstSlice skey = fstSliceCreate((uint8_t*)buf, len);
+ FstSlice skey = fstSliceCreate((uint8_t*)key.c_str(), key.size());
+ bool ok = fstBuilderInsert(_b, skey, val);
+
+ fstSliceDestroy(&skey);
+ return ok;
+ }
+ ~FstWriter() {
+ fstBuilderFinish(_b);
+ fstBuilderDestroy(_b);
+
+ writerCtxDestroy(_wc, false);
+ }
+
+ private:
+ FstBuilder* _b;
+ WriterCtx* _wc;
+};
+
+class FstReadMemory {
+ public:
+ FstReadMemory(size_t size) {
+ _wc = writerCtxCreate(TFile, tindex, true, 64 * 1024);
+ _w = fstCountingWriterCreate(_wc);
+ _size = size;
+ memset((void*)&_s, 0, sizeof(_s));
+ }
+ bool init() {
+ char* buf = (char*)calloc(1, sizeof(char) * _size);
+ int nRead = fstCountingWriterRead(_w, (uint8_t*)buf, _size);
+ if (nRead <= 0) {
+ return false;
+ }
+ _size = nRead;
+ _s = fstSliceCreate((uint8_t*)buf, _size);
+ _fst = fstCreate(&_s);
+ free(buf);
+ return _fst != NULL;
+ }
+ bool Get(const std::string& key, uint64_t* val) {
+ // char buf[128] = {0};
+ // int len = 0;
+ // taosMbsToUcs4(key.c_str(), key.size(), buf, 128, &len);
+ // FstSlice skey = fstSliceCreate((uint8_t*)buf, len);
+
+ FstSlice skey = fstSliceCreate((uint8_t*)key.c_str(), key.size());
+ bool ok = fstGet(_fst, &skey, val);
+ fstSliceDestroy(&skey);
+ return ok;
+ }
+ bool GetWithTimeCostUs(const std::string& key, uint64_t* val, uint64_t* elapse) {
+ int64_t s = taosGetTimestampUs();
+ bool ok = this->Get(key, val);
+ int64_t e = taosGetTimestampUs();
+ *elapse = e - s;
+ return ok;
+ }
+ // add later
+ bool Search(AutomationCtx* ctx, std::vector& result) {
+ FstStreamBuilder* sb = fstSearch(_fst, ctx);
+ StreamWithState* st = streamBuilderIntoStream(sb);
+ StreamWithStateResult* rt = NULL;
+ while ((rt = streamWithStateNextWith(st, NULL)) != NULL) {
+ // result.push_back((uint64_t)(rt->out.out));
+ FstSlice* s = &rt->data;
+ int32_t sz = 0;
+ char* ch = (char*)fstSliceData(s, &sz);
+ std::string key(ch, sz);
+ printf("key: %s, val: %" PRIu64 "\n", key.c_str(), (uint64_t)(rt->out.out));
+ swsResultDestroy(rt);
+ }
+ for (size_t i = 0; i < result.size(); i++) {
+ }
+ std::cout << std::endl;
+ return true;
+ }
+ bool SearchWithTimeCostUs(AutomationCtx* ctx, std::vector& result) {
+ int64_t s = taosGetTimestampUs();
+ bool ok = this->Search(ctx, result);
+ int64_t e = taosGetTimestampUs();
+ return ok;
+ }
+
+ ~FstReadMemory() {
+ fstCountingWriterDestroy(_w);
+ fstDestroy(_fst);
+ fstSliceDestroy(&_s);
+ writerCtxDestroy(_wc, false);
+ tfCleanup();
+ }
+
+ private:
+ FstCountingWriter* _w;
+ Fst* _fst;
+ FstSlice _s;
+ WriterCtx* _wc;
+ size_t _size;
+};
+
+class FstWriterEnv : public ::testing::Test {
+ protected:
+ virtual void SetUp() { fw = new FstWriter(); }
+ virtual void TearDown() { delete fw; }
+ FstWriter* fw = NULL;
+};
+
+class FstReadEnv : public ::testing::Test {
+ protected:
+ virtual void SetUp() { fr = new FstReadMemory(1024); }
+ virtual void TearDown() { delete fr; }
+ FstReadMemory* fr = NULL;
+};
+
+class TFst {
+ public:
+ void CreateWriter() { fw = new FstWriter; }
+ void ReCreateWriter() {
+ if (fw != NULL) delete fw;
+ fw = new FstWriter;
+ }
+ void DestroyWriter() {
+ if (fw != NULL) delete fw;
+ }
+ void CreateReader() {
+ fr = new FstReadMemory(1024);
+ fr->init();
+ }
+ void ReCreateReader() {
+ if (fr != NULL) delete fr;
+ fr = new FstReadMemory(1024);
+ }
+ void DestroyReader() {
+ delete fr;
+ fr = NULL;
+ }
+ bool Put(const std::string& k, uint64_t v) {
+ if (fw == NULL) {
+ return false;
+ }
+ return fw->Put(k, v);
+ }
+ bool Get(const std::string& k, uint64_t* v) {
+ if (fr == NULL) {
+ return false;
+ }
+ return fr->Get(k, v);
+ }
+
+ private:
+ FstWriter* fw;
+ FstReadMemory* fr;
+};
+class FstEnv : public ::testing::Test {
+ protected:
+ virtual void SetUp() {
+ EnvInit();
+ fst = new TFst;
+ }
+ virtual void TearDown() { delete fst; }
+ TFst* fst;
+};
+
+TEST_F(FstEnv, writeNormal) {
+ fst->CreateWriter();
+ std::string str("aa");
+ for (int i = 0; i < 10; i++) {
+ str[0] = 'a' + i;
+ str.resize(2);
+ assert(fst->Put(str, i) == true);
+ }
+ // order failed
+ assert(fst->Put("aa", 1) == false);
+
+ fst->DestroyWriter();
+
+ fst->CreateReader();
+ uint64_t val;
+ assert(fst->Get("a", &val) == false);
+ assert(fst->Get("aa", &val) == true);
+ assert(val == 0);
+}
diff --git a/source/libs/nodes/src/nodesCloneFuncs.c b/source/libs/nodes/src/nodesCloneFuncs.c
index 63bb11a821..78606cd7a2 100644
--- a/source/libs/nodes/src/nodesCloneFuncs.c
+++ b/source/libs/nodes/src/nodesCloneFuncs.c
@@ -15,6 +15,7 @@
#include "querynodes.h"
#include "taos.h"
+#include "taoserror.h"
#define COPY_SCALAR_FIELD(fldname) \
do { \
@@ -57,14 +58,13 @@ static void dataTypeCopy(const SDataType* pSrc, SDataType* pDst) {
}
static void exprNodeCopy(const SExprNode* pSrc, SExprNode* pDst) {
- COPY_SCALAR_FIELD(type);
dataTypeCopy(&pSrc->resType, &pDst->resType);
COPY_CHAR_ARRAY_FIELD(aliasName);
// COPY_NODE_LIST_FIELD(pAssociationList);
}
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(colType);
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) {
- exprNodeCopy((const SExprNode*)&pSrc, (SExprNode*)&pDst);
+ exprNodeCopy((const SExprNode*)pSrc, (SExprNode*)pDst);
COPY_CHAR_POINT_FIELD(literal);
COPY_SCALAR_FIELD(isDuration);
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) {
- exprNodeCopy((const SExprNode*)&pSrc, (SExprNode*)&pDst);
+ exprNodeCopy((const SExprNode*)pSrc, (SExprNode*)pDst);
COPY_SCALAR_FIELD(opType);
COPY_NODE_FIELD(pLeft);
COPY_NODE_FIELD(pRight);
@@ -127,14 +127,14 @@ static SNode* operatorNodeCopy(const SOperatorNode* pSrc, SOperatorNode* 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_NODE_LIST_FIELD(pParameterList);
return (SNode*)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_SCALAR_FIELD(funcId);
COPY_SCALAR_FIELD(funcType);
@@ -142,12 +142,19 @@ static SNode* functionNodeCopy(const SFunctionNode* pSrc, SFunctionNode* 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) {
if (NULL == pNode) {
return NULL;
}
SNode* pDst = nodesMakeNode(nodeType(pNode));
if (NULL == pDst) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
return NULL;
}
switch (nodeType(pNode)) {
@@ -164,7 +171,9 @@ SNode* nodesCloneNode(const SNode* pNode) {
case QUERY_NODE_REAL_TABLE:
case QUERY_NODE_TEMP_TABLE:
case QUERY_NODE_JOIN_TABLE:
+ break;
case QUERY_NODE_GROUPING_SET:
+ return groupingSetNodeCopy((const SGroupingSetNode*)pNode, (SGroupingSetNode*)pDst);
case QUERY_NODE_ORDER_BY_EXPR:
case QUERY_NODE_LIMIT:
default:
@@ -174,8 +183,13 @@ SNode* nodesCloneNode(const SNode* pNode) {
}
SNodeList* nodesCloneList(const SNodeList* pList) {
+ if (NULL == pList) {
+ return NULL;
+ }
+
SNodeList* pDst = nodesMakeList();
if (NULL == pDst) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
return NULL;
}
SNode* pNode;
diff --git a/source/libs/nodes/src/nodesCodeFuncs.c b/source/libs/nodes/src/nodesCodeFuncs.c
index d1f32ae314..8968f0579d 100644
--- a/source/libs/nodes/src/nodesCodeFuncs.c
+++ b/source/libs/nodes/src/nodesCodeFuncs.c
@@ -26,27 +26,47 @@ static char* nodeName(ENodeType type) {
case QUERY_NODE_COLUMN:
return "Column";
case QUERY_NODE_VALUE:
+ return "Value";
case QUERY_NODE_OPERATOR:
+ return "Operator";
case QUERY_NODE_LOGIC_CONDITION:
+ return "LogicCondition";
case QUERY_NODE_FUNCTION:
+ return "Function";
case QUERY_NODE_REAL_TABLE:
+ return "RealTable";
case QUERY_NODE_TEMP_TABLE:
+ return "TempTable";
case QUERY_NODE_JOIN_TABLE:
+ return "JoinTable";
case QUERY_NODE_GROUPING_SET:
+ return "GroupingSet";
case QUERY_NODE_ORDER_BY_EXPR:
+ return "OrderByExpr";
case QUERY_NODE_LIMIT:
+ return "Limit";
case QUERY_NODE_STATE_WINDOW:
+ return "StateWindow";
case QUERY_NODE_SESSION_WINDOW:
+ return "SessionWinow";
case QUERY_NODE_INTERVAL_WINDOW:
+ return "IntervalWindow";
case QUERY_NODE_NODE_LIST:
+ return "NodeList";
case QUERY_NODE_FILL:
+ return "Fill";
case QUERY_NODE_COLUMN_REF:
+ return "ColumnRef";
case QUERY_NODE_TARGET:
+ return "Target";
case QUERY_NODE_RAW_EXPR:
+ return "RawExpr";
case QUERY_NODE_SET_OPERATOR:
+ return "SetOperator";
case QUERY_NODE_SELECT_STMT:
+ return "SelectStmt";
case QUERY_NODE_SHOW_STMT:
- break;
+ return "ShowStmt";
case QUERY_NODE_LOGIC_PLAN_SCAN:
return "LogicScan";
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* 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;
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 int32_t logicProjectToJson(const void* pObj, SJson* pJson) {
+static int32_t logicProjectNodeToJson(const void* pObj, SJson* pJson) {
const SProjectLogicNode* pNode = (const SProjectLogicNode*)pObj;
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* 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;
int32_t code = logicPlanNodeToJson(pObj, pJson);
@@ -163,14 +183,14 @@ static int32_t logicJoinToJson(const void* pObj, SJson* pJson) {
return code;
}
-static int32_t logicFilterToJson(const void* pObj, SJson* pJson) {
+static int32_t logicFilterNodeToJson(const void* pObj, SJson* pJson) {
return logicPlanNodeToJson(pObj, pJson);
}
static const char* jkAggLogicPlanGroupKeys = "GroupKeys";
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;
int32_t code = logicPlanNodeToJson(pObj, pJson);
@@ -184,17 +204,291 @@ static int32_t logicAggToJson(const void* pObj, SJson* pJson) {
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) {
switch (nodeType(pObj)) {
case QUERY_NODE_COLUMN:
+ return columnNodeToJson(pObj, pJson);
case QUERY_NODE_VALUE:
+ return valueNodeToJson(pObj, pJson);
case QUERY_NODE_OPERATOR:
+ return operatorNodeToJson(pObj, pJson);
case QUERY_NODE_LOGIC_CONDITION:
+ return logicConditionNodeToJson(pObj, pJson);
case QUERY_NODE_FUNCTION:
+ return functionNodeToJson(pObj, pJson);
case QUERY_NODE_REAL_TABLE:
case QUERY_NODE_TEMP_TABLE:
case QUERY_NODE_JOIN_TABLE:
+ break;
case QUERY_NODE_GROUPING_SET:
+ return groupingSetNodeToJson(pObj, pJson);
case QUERY_NODE_ORDER_BY_EXPR:
case QUERY_NODE_LIMIT:
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_RAW_EXPR:
case QUERY_NODE_SET_OPERATOR:
+ break;
case QUERY_NODE_SELECT_STMT:
+ return selectStmtTojson(pObj, pJson);
case QUERY_NODE_SHOW_STMT:
break;
case QUERY_NODE_LOGIC_PLAN_SCAN:
- return logicScanToJson(pObj, pJson);
+ return logicScanNodeToJson(pObj, pJson);
case QUERY_NODE_LOGIC_PLAN_JOIN:
- return logicJoinToJson(pObj, pJson);
+ return logicJoinNodeToJson(pObj, pJson);
case QUERY_NODE_LOGIC_PLAN_FILTER:
- return logicFilterToJson(pObj, pJson);
+ return logicFilterNodeToJson(pObj, pJson);
case QUERY_NODE_LOGIC_PLAN_AGG:
- return logicAggToJson(pObj, pJson);
+ return logicAggNodeToJson(pObj, pJson);
case QUERY_NODE_LOGIC_PLAN_PROJECT:
- return logicProjectToJson(pObj, pJson);
+ return logicProjectNodeToJson(pObj, pJson);
default:
break;
}
@@ -238,7 +534,7 @@ static int32_t nodeToJson(const void* pObj, SJson* pJson) {
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) {
return TSDB_CODE_SUCCESS;
}
@@ -255,7 +551,7 @@ int32_t nodesNodeToString(const SNode* pNode, char** pStr, int32_t* pLen) {
return code;
}
- *pStr = tjsonToString(pJson);
+ *pStr = format ? tjsonToString(pJson) : tjsonToUnformattedString(pJson);
tjsonDelete(pJson);
*pLen = strlen(*pStr) + 1;
diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c
index 7e5e314b8d..d4ce35e981 100644
--- a/source/libs/nodes/src/nodesUtilFuncs.c
+++ b/source/libs/nodes/src/nodesUtilFuncs.c
@@ -135,11 +135,22 @@ int32_t nodesListAppend(SNodeList* pList, SNode* pNode) {
}
int32_t nodesListAppendList(SNodeList* pTarget, SNodeList* pSrc) {
- pTarget->pTail->pNext = pSrc->pHead;
- pSrc->pHead->pPrev = pTarget->pTail;
+ if (NULL == pTarget || NULL == pSrc) {
+ 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->length += pSrc->length;
tfree(pSrc);
+
return TSDB_CODE_SUCCESS;
}
@@ -323,6 +334,10 @@ int32_t nodesCollectColumns(SSelectStmt* pSelect, ESqlClause clause, const char*
nodesDestroyList(cxt.pCols);
return cxt.errCode;
}
+ if (0 == LIST_LENGTH(cxt.pCols)) {
+ nodesDestroyList(cxt.pCols);
+ cxt.pCols = NULL;
+ }
*pCols = cxt.pCols;
return TSDB_CODE_SUCCESS;
}
diff --git a/source/libs/parser/src/parserImpl.c b/source/libs/parser/src/parserImpl.c
index d353c245cb..cf8d05975b 100644
--- a/source/libs/parser/src/parserImpl.c
+++ b/source/libs/parser/src/parserImpl.c
@@ -349,7 +349,7 @@ static SNodeList* getProjectList(SNode* pNode) {
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->tableAlias, pTable->table.tableAlias);
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->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.bytes = pColSchema->bytes;
}
@@ -383,7 +383,7 @@ static int32_t createColumnNodeByTable(STranslateContext* pCxt, const STableNode
if (NULL == pCol) {
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);
}
} else {
@@ -408,7 +408,7 @@ static bool findAndSetColumn(SColumnNode* pCol, const STableNode* pTable) {
int32_t nums = pMeta->tableInfo.numOfTags + pMeta->tableInfo.numOfColumns;
for (int32_t i = 0; i < nums; ++i) {
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;
break;
}
diff --git a/source/libs/parser/test/mockCatalog.cpp b/source/libs/parser/test/mockCatalog.cpp
index d68b04a384..8ed67d7f2f 100644
--- a/source/libs/parser/test/mockCatalog.cpp
+++ b/source/libs/parser/test/mockCatalog.cpp
@@ -29,9 +29,9 @@
namespace {
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)
- .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();
}
diff --git a/source/libs/planner/src/plannerImpl.c b/source/libs/planner/src/plannerImpl.c
index 40a82f4175..54a7330667 100644
--- a/source/libs/planner/src/plannerImpl.c
+++ b/source/libs/planner/src/plannerImpl.c
@@ -18,20 +18,20 @@
#define CHECK_ALLOC(p, res) \
do { \
- if (NULL == p) { \
+ if (NULL == (p)) { \
printf("%s : %d\n", __FUNCTION__, __LINE__); \
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; \
- return res; \
+ return (res); \
} \
} while (0)
#define CHECK_CODE(exec, res) \
do { \
- int32_t code = exec; \
+ int32_t code = (exec); \
if (TSDB_CODE_SUCCESS != code) { \
printf("%s : %d\n", __FUNCTION__, __LINE__); \
pCxt->errCode = code; \
- return res; \
+ return (res); \
} \
} while (0)
@@ -83,14 +83,30 @@ static EDealRes doRewriteExpr(SNode** pNode, void* pContext) {
return DEAL_RES_CONTINUE;
}
-static int32_t rewriteExpr(int32_t planNodeId, int32_t rewriteId, SNodeList* pExprs, SSelectStmt* pSelect, ESqlClause clause) {
- SNode* pNode;
- FOREACH(pNode, pExprs) {
- if (QUERY_NODE_COLUMN == nodeType(pNode) || QUERY_NODE_VALUE == nodeType(pNode)) {
- continue;
+typedef struct SNameExprCxt {
+ int32_t planNodeId;
+ int32_t rewriteId;
+} SNameExprCxt;
+
+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 };
nodesRewriteSelectStmt(pSelect, clause, doRewriteExpr, &cxt);
return cxt.errCode;
@@ -135,12 +151,16 @@ static SLogicNode* createScanLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect,
// set columns to scan
SNodeList* pCols = NULL;
CHECK_CODE(nodesCollectColumns(pSelect, SQL_CLAUSE_FROM, pRealTable->table.tableAlias, &pCols), (SLogicNode*)pScan);
- pScan->pScanCols = nodesCloneList(pCols);
- CHECK_ALLOC(pScan->pScanCols, (SLogicNode*)pScan);
+ if (NULL != pCols) {
+ pScan->pScanCols = nodesCloneList(pCols);
+ CHECK_ALLOC(pScan->pScanCols, (SLogicNode*)pScan);
+ }
// set output
- pScan->node.pTargets = nodesCloneList(pCols);
- CHECK_ALLOC(pScan->node.pTargets, (SLogicNode*)pScan);
+ if (NULL != pCols) {
+ pScan->node.pTargets = nodesCloneList(pCols);
+ CHECK_ALLOC(pScan->node.pTargets, (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);
// set on conditions
- pJoin->pOnConditions = nodesCloneNode(pJoinTable->pOnCond);
- CHECK_ALLOC(pJoin->pOnConditions, (SLogicNode*)pJoin);
+ if (NULL != pJoinTable->pOnCond) {
+ pJoin->pOnConditions = nodesCloneNode(pJoinTable->pOnCond);
+ CHECK_ALLOC(pJoin->pOnConditions, (SLogicNode*)pJoin);
+ }
// set the output
pJoin->node.pTargets = nodesCloneList(pLeft->pTargets);
@@ -220,35 +242,57 @@ static SLogicNode* createWhereFilterLogicNode(SPlanContext* pCxt, SLogicNode* pC
return (SLogicNode*)pFilter;
}
-static SNodeList* createColumnByRewriteExps(SPlanContext* pCxt, SNodeList* pExprs) {
- SNodeList* pList = nodesMakeList();
- CHECK_ALLOC(pList, NULL);
- SNode* pNode;
- FOREACH(pNode, pExprs) {
- if (QUERY_NODE_VALUE == nodeType(pNode)) {
- continue;
- } else if (QUERY_NODE_COLUMN == nodeType(pNode)) {
+typedef struct SCreateColumnCxt {
+ int32_t errCode;
+ SNodeList* pList;
+} SCreateColumnCxt;
+
+static EDealRes doCreateColumn(SNode* pNode, void* pContext) {
+ SCreateColumnCxt* pCxt = (SCreateColumnCxt*)pContext;
+ switch (nodeType(pNode)) {
+ case QUERY_NODE_COLUMN: {
SNode* pCol = nodesCloneNode(pNode);
- if (NULL == pCol) {
- goto error;
+ if (NULL == pCol || TSDB_CODE_SUCCESS != nodesListAppend(pCxt->pList, pCol)) {
+ pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
+ return DEAL_RES_ERROR;
}
- if (TSDB_CODE_SUCCESS != nodesListAppend(pList, pCol)) {
- goto error;
- }
- } else {
+ return DEAL_RES_IGNORE_CHILD;
+ }
+ case QUERY_NODE_OPERATOR:
+ case QUERY_NODE_LOGIC_CONDITION:
+ case QUERY_NODE_FUNCTION: {
SExprNode* pExpr = (SExprNode*)pNode;
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
if (NULL == pCol) {
- goto error;
+ pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
+ return DEAL_RES_ERROR;
}
pCol->node.resType = pExpr->resType;
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:
- nodesDestroyList(pList);
- return NULL;
+
+ return DEAL_RES_CONTINUE;
+}
+
+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) {
@@ -263,24 +307,37 @@ static SLogicNode* createAggLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect)
pAgg->node.id = pCxt->planNodeId++;
// set grouyp keys, agg funcs and having conditions
- pAgg->pGroupKeys = nodesCloneList(pSelect->pGroupByList);
- CHECK_ALLOC(pAgg->pGroupKeys, (SLogicNode*)pAgg);
- pAgg->pAggFuncs = nodesCloneList(pAggFuncs);
- CHECK_ALLOC(pAgg->pAggFuncs, (SLogicNode*)pAgg);
+ if (NULL != pSelect->pGroupByList) {
+ pAgg->pGroupKeys = nodesCloneList(pSelect->pGroupByList);
+ CHECK_ALLOC(pAgg->pGroupKeys, (SLogicNode*)pAgg);
+ }
+ if (NULL != pAggFuncs) {
+ pAgg->pAggFuncs = nodesCloneList(pAggFuncs);
+ CHECK_ALLOC(pAgg->pAggFuncs, (SLogicNode*)pAgg);
+ }
// 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 + LIST_LENGTH(pAgg->pGroupKeys), pAgg->pAggFuncs, pSelect, SQL_CLAUSE_GROUP_BY), (SLogicNode*)pAgg);
- pAgg->node.pConditions = nodesCloneNode(pSelect->pHaving);
- CHECK_ALLOC(pAgg->node.pConditions, (SLogicNode*)pAgg);
+ if (NULL != pSelect->pHaving) {
+ pAgg->node.pConditions = nodesCloneNode(pSelect->pHaving);
+ CHECK_ALLOC(pAgg->node.pConditions, (SLogicNode*)pAgg);
+ }
// set the output
- pAgg->node.pTargets = createColumnByRewriteExps(pCxt, pAgg->pGroupKeys);
+ pAgg->node.pTargets = nodesMakeList();
CHECK_ALLOC(pAgg->node.pTargets, (SLogicNode*)pAgg);
- SNodeList* pTargets = createColumnByRewriteExps(pCxt, pAgg->pAggFuncs);
- CHECK_ALLOC(pTargets, (SLogicNode*)pAgg);
- nodesListAppendList(pAgg->node.pTargets, pTargets);
+ if (NULL != pAgg->pGroupKeys) {
+ SNodeList* pTargets = createColumnByRewriteExps(pCxt, pAgg->pGroupKeys);
+ 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;
}
@@ -344,7 +401,7 @@ static SLogicNode* createQueryLogicNode(SPlanContext* pCxt, SNode* pStmt) {
}
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);
if (TSDB_CODE_SUCCESS != cxt.errCode) {
nodesDestroyNode((SNode*)pRoot);
diff --git a/source/libs/planner/test/newPlannerTest.cpp b/source/libs/planner/test/newPlannerTest.cpp
index c227bf88ba..c3ee4fb9a8 100644
--- a/source/libs/planner/test/newPlannerTest.cpp
+++ b/source/libs/planner/test/newPlannerTest.cpp
@@ -42,26 +42,28 @@ protected:
bool run() {
int32_t code = parser(&cxt_, &query_);
- // cout << "parser return " << code << endl;
+
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;
}
+
+ const string syntaxTreeStr = toString(query_.pRoot, false);
+
SLogicNode* pLogicPlan = nullptr;
code = createLogicPlan(query_.pRoot, &pLogicPlan);
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;
}
- char* pStr = NULL;
- int32_t len = 0;
- code = nodesNodeToString((const SNode*)pLogicPlan, &pStr, &len);
- if (code != TSDB_CODE_SUCCESS) {
- cout << "sql:[" << cxt_.pSql << "] toString code:" << tstrerror(code) << endl;
- return false;
- }
- cout << "logic plan : " << endl;
- cout << pStr << endl;
+
+ cout << "sql : [" << cxt_.pSql << "]" << endl;
+ cout << "syntax test : " << endl;
+ cout << syntaxTreeStr << endl;
+ // cout << "logic plan : " << endl;
+ // cout << toString((const SNode*)pLogicPlan) << endl;
+ cout << "unformatted logic plan : " << endl;
+ cout << toString((const SNode*)pLogicPlan, false) << endl;
return true;
}
@@ -75,6 +77,19 @@ private:
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 db_;
char errMagBuf_[max_err_len];
@@ -89,3 +104,19 @@ TEST_F(NewPlannerTest, simple) {
bind("SELECT * FROM t1");
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());
+}
diff --git a/source/libs/sync/CMakeLists.txt b/source/libs/sync/CMakeLists.txt
index 784a864451..37ee5194c8 100644
--- a/source/libs/sync/CMakeLists.txt
+++ b/source/libs/sync/CMakeLists.txt
@@ -1,4 +1,3 @@
-
aux_source_directory(src SYNC_SRC)
add_library(sync ${SYNC_SRC})
diff --git a/source/libs/sync/inc/syncAppendEntries.h b/source/libs/sync/inc/syncAppendEntries.h
new file mode 100644
index 0000000000..9ca0de19c5
--- /dev/null
+++ b/source/libs/sync/inc/syncAppendEntries.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#ifndef _TD_LIBS_SYNC_APPEND_ENTRIES_H
+#define _TD_LIBS_SYNC_APPEND_ENTRIES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#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*/
diff --git a/source/libs/sync/inc/syncAppendEntriesReply.h b/source/libs/sync/inc/syncAppendEntriesReply.h
new file mode 100644
index 0000000000..8b5cbf1da5
--- /dev/null
+++ b/source/libs/sync/inc/syncAppendEntriesReply.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#ifndef _TD_LIBS_SYNC_APPEND_ENTRIES_REPLY_H
+#define _TD_LIBS_SYNC_APPEND_ENTRIES_REPLY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#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*/
diff --git a/source/libs/sync/inc/syncElection.h b/source/libs/sync/inc/syncElection.h
new file mode 100644
index 0000000000..34dfdb3d09
--- /dev/null
+++ b/source/libs/sync/inc/syncElection.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#ifndef _TD_LIBS_SYNC_ELECTION_H
+#define _TD_LIBS_SYNC_ELECTION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#include "taosdef.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_TD_LIBS_SYNC_ELECTION_H*/
diff --git a/source/libs/sync/inc/syncInt.h b/source/libs/sync/inc/syncInt.h
new file mode 100644
index 0000000000..551ce83122
--- /dev/null
+++ b/source/libs/sync/inc/syncInt.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#ifndef _TD_LIBS_SYNC_INT_H
+#define _TD_LIBS_SYNC_INT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#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*/
diff --git a/source/libs/sync/inc/syncMessage.h b/source/libs/sync/inc/syncMessage.h
new file mode 100644
index 0000000000..f410c8cf6e
--- /dev/null
+++ b/source/libs/sync/inc/syncMessage.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#ifndef _TD_LIBS_SYNC_MESSAGE_H
+#define _TD_LIBS_SYNC_MESSAGE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#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*/
diff --git a/source/libs/sync/inc/syncOnMessage.h b/source/libs/sync/inc/syncOnMessage.h
new file mode 100644
index 0000000000..07c44b6199
--- /dev/null
+++ b/source/libs/sync/inc/syncOnMessage.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#ifndef _TD_LIBS_SYNC_ON_MESSAGE_H
+#define _TD_LIBS_SYNC_ON_MESSAGE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#include "syncRaft.h"
+#include "taosdef.h"
+
+void onMessage(SRaft *pRaft, void *pMsg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_TD_LIBS_SYNC_ON_MESSAGE_H*/
diff --git a/source/libs/sync/inc/syncRaft.h b/source/libs/sync/inc/syncRaft.h
new file mode 100644
index 0000000000..0c7e573572
--- /dev/null
+++ b/source/libs/sync/inc/syncRaft.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#ifndef _TD_LIBS_SYNC_RAFT_H
+#define _TD_LIBS_SYNC_RAFT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#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*/
diff --git a/source/libs/sync/inc/syncRaftEntry.h b/source/libs/sync/inc/syncRaftEntry.h
new file mode 100644
index 0000000000..adc82f2c5d
--- /dev/null
+++ b/source/libs/sync/inc/syncRaftEntry.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#ifndef _TD_LIBS_TPL_H
+#define _TD_LIBS_TPL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#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*/
diff --git a/source/libs/sync/inc/syncRaftLog.h b/source/libs/sync/inc/syncRaftLog.h
new file mode 100644
index 0000000000..8c4b5116ea
--- /dev/null
+++ b/source/libs/sync/inc/syncRaftLog.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#ifndef _TD_LIBS_SYNC_RAFT_LOG_H
+#define _TD_LIBS_SYNC_RAFT_LOG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#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*/
diff --git a/source/libs/sync/inc/syncRaftStore.h b/source/libs/sync/inc/syncRaftStore.h
new file mode 100644
index 0000000000..4cb852f34a
--- /dev/null
+++ b/source/libs/sync/inc/syncRaftStore.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#ifndef _TD_LIBS_SYNC_RAFT_STORE_H
+#define _TD_LIBS_SYNC_RAFT_STORE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#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*/
diff --git a/source/libs/sync/inc/syncReplication.h b/source/libs/sync/inc/syncReplication.h
new file mode 100644
index 0000000000..40c5ff790b
--- /dev/null
+++ b/source/libs/sync/inc/syncReplication.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#ifndef _TD_LIBS_SYNC_REPLICATION_H
+#define _TD_LIBS_SYNC_REPLICATION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#include "taosdef.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_TD_LIBS_SYNC_REPLICATION_H*/
diff --git a/source/libs/sync/inc/syncRequestVote.h b/source/libs/sync/inc/syncRequestVote.h
new file mode 100644
index 0000000000..3ff96bbe8f
--- /dev/null
+++ b/source/libs/sync/inc/syncRequestVote.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#ifndef _TD_LIBS_SYNC_REQUEST_VOTE_H
+#define _TD_LIBS_SYNC_REQUEST_VOTE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#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*/
diff --git a/source/libs/sync/inc/syncRequestVoteReply.h b/source/libs/sync/inc/syncRequestVoteReply.h
new file mode 100644
index 0000000000..033ac89bc2
--- /dev/null
+++ b/source/libs/sync/inc/syncRequestVoteReply.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#ifndef _TD_LIBS_SYNC_REQUEST_VOTE_REPLY_H
+#define _TD_LIBS_SYNC_REQUEST_VOTE_REPLY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#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*/
diff --git a/source/libs/sync/inc/syncSnapshot.h b/source/libs/sync/inc/syncSnapshot.h
new file mode 100644
index 0000000000..3b6121578a
--- /dev/null
+++ b/source/libs/sync/inc/syncSnapshot.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#ifndef _TD_LIBS_SYNC_SNAPSHOT_H
+#define _TD_LIBS_SYNC_SNAPSHOT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#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*/
diff --git a/source/libs/sync/inc/syncTimeout.h b/source/libs/sync/inc/syncTimeout.h
new file mode 100644
index 0000000000..8159d2566c
--- /dev/null
+++ b/source/libs/sync/inc/syncTimeout.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#ifndef _TD_LIBS_SYNC_TIMEOUT_H
+#define _TD_LIBS_SYNC_TIMEOUT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#include "syncMessage.h"
+#include "syncRaft.h"
+#include "taosdef.h"
+
+void onTimeout(SRaft *pRaft, void *pMsg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_TD_LIBS_SYNC_TIMEOUT_H*/
diff --git a/source/libs/sync/src/sync.c b/source/libs/sync/src/sync.c
deleted file mode 100644
index 7ded53b6e6..0000000000
--- a/source/libs/sync/src/sync.c
+++ /dev/null
@@ -1 +0,0 @@
-#include "sync.h"
\ No newline at end of file
diff --git a/source/libs/sync/src/syncAppendEntries.c b/source/libs/sync/src/syncAppendEntries.c
new file mode 100644
index 0000000000..1286108664
--- /dev/null
+++ b/source/libs/sync/src/syncAppendEntries.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#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 <>
+
+}
+
+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 <>
+// \/ \* return to follower state
+// /\ m.mterm = currentTerm[i]
+// /\ state[i] = Candidate
+// /\ state' = [state EXCEPT ![i] = Follower]
+// /\ UNCHANGED <>
+// \/ \* 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 <>
+// \/ \* 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 <>
+// \/ \* no conflict: append entry
+// /\ m.mentries /= << >>
+// /\ Len(log[i]) = m.mprevLogIndex
+// /\ log' = [log EXCEPT ![i] =
+// Append(log[i], m.mentries[1])]
+// /\ UNCHANGED <>
+// /\ UNCHANGED <>
+//
+
+
+}
diff --git a/source/libs/sync/src/syncAppendEntriesReply.c b/source/libs/sync/src/syncAppendEntriesReply.c
new file mode 100644
index 0000000000..4a9055e172
--- /dev/null
+++ b/source/libs/sync/src/syncAppendEntriesReply.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#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 <>
+// /\ Discard(m)
+// /\ UNCHANGED <>
+
+}
diff --git a/source/libs/sync/src/syncElection.c b/source/libs/sync/src/syncElection.c
new file mode 100644
index 0000000000..738fc4c5e1
--- /dev/null
+++ b/source/libs/sync/src/syncElection.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#include "sync.h"
diff --git a/source/libs/sync/src/syncMain.c b/source/libs/sync/src/syncMain.c
new file mode 100644
index 0000000000..fbb969eb1c
--- /dev/null
+++ b/source/libs/sync/src/syncMain.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#include
+#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) {}
\ No newline at end of file
diff --git a/source/libs/sync/src/syncMessage.c b/source/libs/sync/src/syncMessage.c
new file mode 100644
index 0000000000..dcfc940f76
--- /dev/null
+++ b/source/libs/sync/src/syncMessage.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#include "syncMessage.h"
+#include "sync.h"
+#include "syncRaft.h"
+
+void onMessage(SRaft *pRaft, void *pMsg) {}
\ No newline at end of file
diff --git a/source/libs/sync/src/syncOnMessage.c b/source/libs/sync/src/syncOnMessage.c
new file mode 100644
index 0000000000..738fc4c5e1
--- /dev/null
+++ b/source/libs/sync/src/syncOnMessage.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#include "sync.h"
diff --git a/source/libs/sync/src/syncRaft.c b/source/libs/sync/src/syncRaft.c
new file mode 100644
index 0000000000..85c2c6fe27
--- /dev/null
+++ b/source/libs/sync/src/syncRaft.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#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; }
diff --git a/source/libs/sync/src/syncRaftEntry.c b/source/libs/sync/src/syncRaftEntry.c
new file mode 100644
index 0000000000..738fc4c5e1
--- /dev/null
+++ b/source/libs/sync/src/syncRaftEntry.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#include "sync.h"
diff --git a/source/libs/sync/src/syncRaftLog.c b/source/libs/sync/src/syncRaftLog.c
new file mode 100644
index 0000000000..4a5fc201b0
--- /dev/null
+++ b/source/libs/sync/src/syncRaftLog.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#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; }
\ No newline at end of file
diff --git a/source/libs/sync/src/syncRaftStore.c b/source/libs/sync/src/syncRaftStore.c
new file mode 100644
index 0000000000..d45e53132c
--- /dev/null
+++ b/source/libs/sync/src/syncRaftStore.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#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; }
\ No newline at end of file
diff --git a/source/libs/sync/src/syncReplication.c b/source/libs/sync/src/syncReplication.c
new file mode 100644
index 0000000000..738fc4c5e1
--- /dev/null
+++ b/source/libs/sync/src/syncReplication.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#include "sync.h"
diff --git a/source/libs/sync/src/syncRequestVote.c b/source/libs/sync/src/syncRequestVote.c
new file mode 100644
index 0000000000..c31ec0f34d
--- /dev/null
+++ b/source/libs/sync/src/syncRequestVote.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#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 <>
+
+}
+
+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 <>
+
+}
diff --git a/source/libs/sync/src/syncRequestVoteReply.c b/source/libs/sync/src/syncRequestVoteReply.c
new file mode 100644
index 0000000000..ba9787f00c
--- /dev/null
+++ b/source/libs/sync/src/syncRequestVoteReply.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#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 <>
+// /\ Discard(m)
+// /\ UNCHANGED <>
+
+}
diff --git a/source/libs/sync/src/syncSnapshot.c b/source/libs/sync/src/syncSnapshot.c
new file mode 100644
index 0000000000..8a27f097d1
--- /dev/null
+++ b/source/libs/sync/src/syncSnapshot.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#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; }
\ No newline at end of file
diff --git a/source/libs/sync/src/syncTimeout.c b/source/libs/sync/src/syncTimeout.c
new file mode 100644
index 0000000000..206dd70046
--- /dev/null
+++ b/source/libs/sync/src/syncTimeout.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+#include "syncTimeout.h"
+#include "sync.h"
+
+void onTimeout(SRaft *pRaft, void *pMsg) {}
\ No newline at end of file
diff --git a/source/libs/sync/test/syncTest.cpp b/source/libs/sync/test/syncTest.cpp
new file mode 100644
index 0000000000..47566d537e
--- /dev/null
+++ b/source/libs/sync/test/syncTest.cpp
@@ -0,0 +1,7 @@
+#include
+
+int main() {
+ printf("test \n");
+ return 0;
+}
+
diff --git a/source/libs/transport/inc/transComm.h b/source/libs/transport/inc/transComm.h
index d5a8cf5f84..d4d9bff56c 100644
--- a/source/libs/transport/inc/transComm.h
+++ b/source/libs/transport/inc/transComm.h
@@ -217,7 +217,7 @@ typedef struct SConnBuffer {
char* buf;
int len;
int cap;
- int left;
+ int total;
} SConnBuffer;
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);
int transSendAsync(SAsyncPool* pool, queue* mq);
-int transInitBuffer(SConnBuffer* buf);
-int transClearBuffer(SConnBuffer* buf);
-int transDestroyBuffer(SConnBuffer* buf);
-int transAllocBuffer(SConnBuffer* connBuf, uv_buf_t* uvBuf);
+int transInitBuffer(SConnBuffer* buf);
+int transClearBuffer(SConnBuffer* buf);
+int transDestroyBuffer(SConnBuffer* buf);
+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);
diff --git a/source/libs/transport/inc/transportInt.h b/source/libs/transport/inc/transportInt.h
index 3c8c922d83..a36b671eb4 100644
--- a/source/libs/transport/inc/transportInt.h
+++ b/source/libs/transport/inc/transportInt.h
@@ -56,6 +56,7 @@ typedef struct {
int8_t connType;
int64_t index;
char label[TSDB_LABEL_LEN];
+ bool noPool; // pool or not
char user[TSDB_UNI_LEN]; // meter ID
char spi; // security parameter index
diff --git a/source/libs/transport/src/rpcMain.c b/source/libs/transport/src/rpcMain.c
index 3bb7d103d7..72c1ff6893 100644
--- a/source/libs/transport/src/rpcMain.c
+++ b/source/libs/transport/src/rpcMain.c
@@ -64,6 +64,7 @@ typedef struct {
void (*cfp)(void *parent, SRpcMsg *, SEpSet *);
int (*afp)(void *parent, char *user, char *spi, char *encrypt, char *secret, char *ckey);
+ bool noPool;
int32_t refCount;
void * parent;
void * idPool; // handle to ID pool
diff --git a/source/libs/transport/src/trans.c b/source/libs/transport/src/trans.c
index c3d3cfa2ab..48c15ca286 100644
--- a/source/libs/transport/src/trans.c
+++ b/source/libs/transport/src/trans.c
@@ -27,7 +27,7 @@ void* rpcOpen(const SRpcInit* pInit) {
return NULL;
}
if (pInit->label) {
- tstrncpy(pRpc->label, pInit->label, strlen(pInit->label));
+ tstrncpy(pRpc->label, pInit->label, strlen(pInit->label) + 1);
}
pRpc->cfp = pInit->cfp;
if (pInit->connType == TAOS_CONN_SERVER) {
@@ -35,6 +35,8 @@ void* rpcOpen(const SRpcInit* pInit) {
} else {
pRpc->numOfThreads = pInit->numOfThreads;
}
+
+ pRpc->noPool = pInit->noPool;
pRpc->connType = pInit->connType;
pRpc->idleTime = pInit->idleTime;
pRpc->tcphandle = (*taosInitHandle[pRpc->connType])(0, pInit->localPort, pRpc->label, pRpc->numOfThreads, NULL, pRpc);
diff --git a/source/libs/transport/src/transCli.c b/source/libs/transport/src/transCli.c
index f1bd1ba980..8312c0217c 100644
--- a/source/libs/transport/src/transCli.c
+++ b/source/libs/transport/src/transCli.c
@@ -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
static void clientTimeoutCb(uv_timer_t* handle);
-// check whether already read complete packet from server
-static bool clientReadComplete(SConnBuffer* pBuf);
// alloc buf for read
static void clientAllocBufferCb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf);
// callback after read nbytes from socket
@@ -126,6 +124,9 @@ static void clientHandleResp(SCliConn* conn) {
pHead->code = htonl(pHead->code);
pHead->msgLen = htonl(pHead->msgLen);
+ // buf's mem alread translated to rpcMsg.pCont
+ transClearBuffer(&conn->readBuf);
+
SRpcMsg rpcMsg;
rpcMsg.contLen = transContLenFromMsg(pHead->msgLen);
rpcMsg.pCont = transContFromHead((char*)pHead);
@@ -134,15 +135,15 @@ static void clientHandleResp(SCliConn* conn) {
rpcMsg.ahandle = pCtx->ahandle;
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;
conn->persist = 1;
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),
- inet_ntoa(conn->addr.sin_addr), ntohs(conn->addr.sin_port), inet_ntoa(conn->locaddr.sin_addr),
- ntohs(conn->locaddr.sin_port));
+ tDebug("%s client conn %p %s received from %s:%d, local info: %s:%d, msg size: %d", pRpc->label, conn,
+ TMSG_INFO(pHead->msgType), inet_ntoa(conn->addr.sin_addr), ntohs(conn->addr.sin_port),
+ inet_ntoa(conn->locaddr.sin_addr), ntohs(conn->locaddr.sin_port), rpcMsg.contLen);
conn->secured = pHead->secured;
if (conn->push != NULL && conn->ctnRdCnt != 0) {
@@ -150,26 +151,26 @@ static void clientHandleResp(SCliConn* conn) {
conn->push = NULL;
} else {
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);
} 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));
tsem_post(pCtx->pSem);
}
}
conn->ctnRdCnt += 1;
- // buf's mem alread translated to rpcMsg.pCont
- transClearBuffer(&conn->readBuf);
-
uv_read_start((uv_stream_t*)conn->stream, clientAllocBufferCb, clientReadCb);
SCliThrdObj* pThrd = conn->hostThrd;
// user owns conn->persist = 1
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);
conn->data = NULL;
@@ -184,7 +185,6 @@ static void clientHandleExcept(SCliConn* pConn) {
clientConnDestroy(pConn, true);
return;
}
- tTrace("client conn %p start to destroy", pConn);
SCliMsg* pMsg = pConn->data;
tmsg_t msgType = TDMT_MND_CONNECT;
@@ -213,6 +213,7 @@ static void clientHandleExcept(SCliConn* pConn) {
}
pConn->push = NULL;
}
+ tTrace("%s client conn %p start to destroy", pCtx->pTransInst->label, pConn);
if (pConn->push == NULL) {
destroyCmsg(pConn->data);
pConn->data = NULL;
@@ -226,7 +227,7 @@ static void clientTimeoutCb(uv_timer_t* handle) {
SCliThrdObj* pThrd = handle->data;
SRpcInfo* pRpc = pThrd->pTransInst;
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);
while (p != NULL) {
@@ -306,23 +307,6 @@ static void addConnToPool(void* pool, char* ip, uint32_t port, SCliConn* conn) {
assert(plist != NULL);
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) {
SCliConn* conn = handle->data;
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;
if (nread > 0) {
pBuf->len += nread;
- if (clientReadComplete(pBuf)) {
- uv_read_stop((uv_stream_t*)conn->stream);
+ if (transReadComplete(pBuf)) {
tTrace("client conn %p read complete", conn);
clientHandleResp(conn);
} else {
@@ -346,6 +329,10 @@ static void clientReadCb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf
}
return;
}
+ if (nread == UV_EOF) {
+ tError("client conn %p read error: %s", conn, uv_err_name(nread));
+ clientHandleExcept(conn);
+ }
assert(nread <= 0);
if (nread == 0) {
// 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).
return;
}
- if (nread < 0 || nread == UV_EOF) {
+ if (nread < 0) {
tError("client conn %p read error: %s", conn, uv_err_name(nread));
clientHandleExcept(conn);
}
@@ -467,6 +454,7 @@ static void clientConnCb(uv_connect_t* req, int status) {
static void clientHandleQuit(SCliMsg* pMsg, SCliThrdObj* pThrd) {
tDebug("client work thread %p start to quit", pThrd);
destroyCmsg(pMsg);
+ destroyConnPool(pThrd->pool);
// transDestroyAsyncPool(pThr) uv_close((uv_handle_t*)pThrd->cliAsync, NULL);
uv_timer_stop(pThrd->timer);
pThrd->quit = true;
@@ -483,7 +471,10 @@ static void clientHandleReq(SCliMsg* pMsg, SCliThrdObj* pThrd) {
SCliConn* conn = 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) {
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));
uv_tcp_init(pThrd->loop, (uv_tcp_t*)(conn->stream));
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
conn->writeReq = malloc(sizeof(uv_write_t));
conn->writeReq->data = conn;
diff --git a/source/libs/transport/src/transComm.c b/source/libs/transport/src/transComm.c
index 7aa5aa16f1..9a8607b0ed 100644
--- a/source/libs/transport/src/transComm.c
+++ b/source/libs/transport/src/transComm.c
@@ -205,6 +205,7 @@ int transInitBuffer(SConnBuffer* buf) {
}
int transClearBuffer(SConnBuffer* buf) {
memset(buf, 0, sizeof(*buf));
+ buf->total = -1;
return 0;
}
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
* info--->|
*/
- static const int CAPACITY = 1024;
+ static const int CAPACITY = sizeof(STransMsgHead);
SConnBuffer* p = connBuf;
if (p->cap == 0) {
p->buf = (char*)calloc(CAPACITY, sizeof(char));
p->len = 0;
p->cap = CAPACITY;
- p->left = -1;
+ p->total = -1;
uvBuf->base = p->buf;
uvBuf->len = CAPACITY;
} else {
- if (p->len >= p->cap) {
- if (p->left == -1) {
- 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);
- }
- }
+ p->cap = p->total;
+ p->buf = realloc(p->buf, p->cap);
uvBuf->base = p->buf + p->len;
uvBuf->len = p->cap - p->len;
}
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 transUnpackMsg(STransMsgHead* msgHead) {}
diff --git a/source/libs/transport/src/transSrv.c b/source/libs/transport/src/transSrv.c
index 7ddeb99c9d..9fca371bf3 100644
--- a/source/libs/transport/src/transSrv.c
+++ b/source/libs/transport/src/transSrv.c
@@ -61,6 +61,7 @@ typedef struct SWorkThrdObj {
SAsyncPool* asyncPool;
// uv_async_t* workerAsync; //
queue msg;
+ queue conn;
pthread_mutex_t msgMtx;
void* pTransInst;
} 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 uvWorkerAsyncCb(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 uvPrepareSendData(SSrvMsg* msg, uv_buf_t* wb);
@@ -102,8 +104,7 @@ static void uvStartSendResp(SSrvMsg* msg);
static void destroySmsg(SSrvMsg* smsg);
// check whether already read complete packet
-static bool readComplete(SConnBuffer* buf);
-static SSrvConn* createConn();
+static SSrvConn* createConn(void* hThrd);
static void destroyConn(SSrvConn* conn, bool clear /*clear handle or not*/);
static void uvDestroyConn(uv_handle_t* handle);
@@ -117,51 +118,11 @@ static bool addHandleToWorkloop(void* arg);
static bool addHandleToAcceptloop(void* arg);
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;
SConnBuffer* pBuf = &conn->readBuf;
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) {
STransMsgHead* pHead = (STransMsgHead*)msg;
@@ -241,7 +202,7 @@ static void uvHandleReq(SSrvConn* pConn) {
}
pConn->inType = pHead->msgType;
- assert(transIsReq(pHead->msgType));
+ // assert(transIsReq(pHead->msgType));
SRpcInfo* pRpc = (SRpcInfo*)p->shandle;
pHead->code = htonl(pHead->code);
@@ -266,9 +227,9 @@ static void uvHandleReq(SSrvConn* pConn) {
transClearBuffer(&pConn->readBuf);
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),
- ntohs(pConn->locaddr.sin_port));
+ ntohs(pConn->locaddr.sin_port), rpcMsg.contLen);
(*(pRpc->cfp))(pRpc->parent, &rpcMsg, NULL);
// uv_timer_start(pConn->pTimer, uvHandleActivityTimeout, pRpc->idleTime * 10000, 0);
// auth
@@ -282,7 +243,7 @@ void uvOnReadCb(uv_stream_t* cli, ssize_t nread, const uv_buf_t* buf) {
if (nread > 0) {
pBuf->len += 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);
uvHandleReq(conn);
} else {
@@ -290,6 +251,14 @@ void uvOnReadCb(uv_stream_t* cli, ssize_t nread, const uv_buf_t* buf) {
}
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) {
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) {
- buf->base = malloc(sizeof(char));
buf->len = 2;
+ buf->base = calloc(1, sizeof(char) * buf->len);
}
void uvOnTimeoutCb(uv_timer_t* handle) {
@@ -386,6 +355,7 @@ static void uvStartSendRespInternal(SSrvMsg* smsg) {
static void uvStartSendResp(SSrvMsg* smsg) {
// impl
SSrvConn* pConn = smsg->pConn;
+ pConn->ref--; //
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),
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);
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) {
SAsyncItem* item = handle->data;
SWorkThrdObj* pThrd = item->pThrd;
@@ -424,8 +404,11 @@ void uvWorkerAsyncCb(uv_async_t* handle) {
continue;
}
if (msg->pConn == NULL) {
- //
free(msg);
+
+ destroyAllConn(pThrd);
+
+ uv_loop_close(pThrd->loop);
uv_stop(pThrd->loop);
} else {
uvStartSendResp(msg);
@@ -439,9 +422,16 @@ void uvWorkerAsyncCb(uv_async_t* handle) {
}
static void uvAcceptAsyncCb(uv_async_t* async) {
SServerObj* srv = async->data;
+ uv_close((uv_handle_t*)&srv->server, NULL);
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) {
if (status == -1) {
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);
assert(pending == UV_TCP);
- SSrvConn* pConn = createConn();
+ SSrvConn* pConn = createConn(pThrd);
pConn->pTransInst = pThrd->pTransInst;
/* 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);
pConn->pTcp->data = pConn;
+ // uv_tcp_nodelay(pConn->pTcp, 1);
+ // uv_tcp_keepalive(pConn->pTcp, 1, 1);
+
// init write request, just
pConn->pWriter = calloc(1, sizeof(uv_write_t));
pConn->pWriter->data = pConn;
@@ -560,6 +553,9 @@ static bool addHandleToWorkloop(void* arg) {
QUEUE_INIT(&pThrd->msg);
pthread_mutex_init(&pThrd->msgMtx, NULL);
+ // conn set
+ QUEUE_INIT(&pThrd->conn);
+
pThrd->asyncPool = transCreateAsyncPool(pThrd->loop, 4, pThrd, uvWorkerAsyncCb);
uv_read_start((uv_stream_t*)pThrd->pipe, uvAllocConnBufferCb, uvOnConnectionCb);
return true;
@@ -598,8 +594,13 @@ void* workerThread(void* arg) {
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));
+ QUEUE_INIT(&pConn->queue);
+
+ QUEUE_PUSH(&pThrd->conn, &pConn->queue);
pConn->srvMsgs = taosArrayInit(2, sizeof(void*)); //
tTrace("conn %p created", pConn);
++pConn->ref;
@@ -610,7 +611,7 @@ static void destroyConn(SSrvConn* conn, bool clear) {
if (conn == NULL) {
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) {
return;
}
@@ -621,20 +622,23 @@ static void destroyConn(SSrvConn* conn, bool clear) {
destroySmsg(msg);
}
taosArrayDestroy(conn->srvMsgs);
-
- // destroySmsg(conn->pSrvMsg);
- // conn->pSrvMsg = NULL;
+ QUEUE_REMOVE(&conn->queue);
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) {
SSrvConn* conn = handle->data;
tDebug("server conn %p destroy", conn);
uv_timer_stop(conn->pTimer);
- free(conn->pTimer);
- // free(conn->pTcp);
+ // free(conn->pTimer);
+ free(conn->pTcp);
free(conn->pWriter);
free(conn);
}
diff --git a/source/libs/transport/test/transUT.cc b/source/libs/transport/test/transUT.cc
index 6f80ea42ac..d1fefe2c72 100644
--- a/source/libs/transport/test/transUT.cc
+++ b/source/libs/transport/test/transUT.cc
@@ -16,69 +16,168 @@
#include
#include
#include "tep.h"
+#include "tglobal.h"
#include "trpc.h"
+#include "ulog.h"
using namespace std;
-class TransObj {
- public:
- TransObj() {
- const char *label = "APP";
- const char *secret = "secret";
- const char *user = "user";
- const char *ckey = "ckey";
+const char *label = "APP";
+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));
rpcInit.localPort = 0;
rpcInit.label = (char *)label;
- rpcInit.numOfThreads = 5;
- rpcInit.cfp = NULL;
- rpcInit.sessions = 100;
- rpcInit.idleTime = 100;
+ rpcInit.numOfThreads = nThread;
+ rpcInit.cfp = processResp;
rpcInit.user = (char *)user;
rpcInit.secret = (char *)secret;
rpcInit.ckey = (char *)ckey;
rpcInit.spi = 1;
- }
- bool startCli() {
- trans = NULL;
+ rpcInit.parent = this;
rpcInit.connType = TAOS_CONN_CLIENT;
- trans = rpcOpen(&rpcInit);
- return trans != NULL ? true : false;
+ this->transCli = rpcOpen(&rpcInit);
+ tsem_init(&this->sem, 0, 0);
}
- bool startSrv() {
- trans = NULL;
- rpcInit.connType = TAOS_CONN_SERVER;
- trans = rpcOpen(&rpcInit);
- return trans != NULL ? true : false;
+ void SetResp(SRpcMsg *pMsg) {
+ // set up resp;
+ this->resp = *pMsg;
+ }
+ 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};
epSet.inUse = 0;
- addEpIntoEpSet(&epSet, "192.168.1.1", 7000);
- addEpIntoEpSet(&epSet, "192.168.0.1", 7000);
+ addEpIntoEpSet(&epSet, "127.0.0.1", 7000);
- if (trans == NULL) {
- return false;
- }
- 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;
+ rpcSendRequest(this->transCli, &epSet, req, NULL);
+ SemWait();
+ *resp = this->resp;
}
- bool stop() {
- rpcClose(trans);
- trans = NULL;
- return true;
+ void SemWait() { tsem_wait(&this->sem); }
+ void SemPost() { tsem_post(&this->sem); }
+ void Reset() {}
+
+ ~Client() {
+ if (this->transCli) rpcClose(this->transCli);
}
private:
- void * trans;
+ tsem_t sem;
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 {
protected:
@@ -93,11 +192,34 @@ class TransEnv : public ::testing::Test {
TransObj *tr = NULL;
};
-TEST_F(TransEnv, test_start_stop) {
- assert(tr->startCli());
- assert(tr->sendAndRecv());
- assert(tr->stop());
- assert(tr->startSrv());
- assert(tr->stop());
+// TEST_F(TransEnv, 01sendAndRec) {
+// 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);
}
diff --git a/source/os/src/osTimer.c b/source/os/src/osTimer.c
index 7e542ef80f..bb526e0ba0 100644
--- a/source/os/src/osTimer.c
+++ b/source/os/src/osTimer.c
@@ -22,13 +22,12 @@
* windows implementation
*/
-
-#include
#include
-#include
+#include
#include
+#include
-#pragma warning( disable : 4244 )
+#pragma warning(disable : 4244)
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;
-int taosInitTimer(win_timer_f callback, int ms) {
- DWORD_PTR param = *((int64_t *) & callback);
+int taosInitTimer(win_timer_f callback, int ms) {
+ DWORD_PTR param = *((int64_t *)&callback);
timerId = timeSetEvent(ms, 1, (LPTIMECALLBACK)taosWinOnTimer, param, TIME_PERIODIC);
if (timerId == 0) {
@@ -50,9 +49,7 @@ int taosInitTimer(win_timer_f callback, int ms) {
return 0;
}
-void taosUninitTimer() {
- timeKillEvent(timerId);
-}
+void taosUninitTimer() { timeKillEvent(timerId); }
#elif defined(_TD_DARWIN_64)
@@ -60,32 +57,32 @@ void taosUninitTimer() {
* darwin implementation
*/
-#include
#include
+#include
#include
static void (*timer_callback)(int);
-static int timer_ms = 0;
-static pthread_t timer_thread;
-static int timer_kq = -1;
-static volatile int timer_stop = 0;
+static int timer_ms = 0;
+static pthread_t timer_thread;
+static int timer_kq = -1;
+static volatile int timer_stop = 0;
-static void* timer_routine(void *arg) {
+static void* timer_routine(void* arg) {
(void)arg;
setThreadName("timer");
- int r = 0;
+ int r = 0;
struct timespec to = {0};
- to.tv_sec = timer_ms / 1000;
- to.tv_nsec = (timer_ms % 1000) * 1000000;
+ to.tv_sec = timer_ms / 1000;
+ to.tv_nsec = (timer_ms % 1000) * 1000000;
while (!timer_stop) {
struct kevent64_s kev[10] = {0};
- r = kevent64(timer_kq, NULL, 0, kev, sizeof(kev)/sizeof(kev[0]), 0, &to);
- if (r!=0) {
+ r = kevent64(timer_kq, NULL, 0, kev, sizeof(kev) / sizeof(kev[0]), 0, &to);
+ if (r != 0) {
fprintf(stderr, "==%s[%d]%s()==kevent64 failed\n", basename(__FILE__), __LINE__, __func__);
abort();
}
- timer_callback(SIGALRM); // just mock
+ timer_callback(SIGALRM); // just mock
}
return NULL;
@@ -93,11 +90,13 @@ static void* timer_routine(void *arg) {
int taosInitTimer(void (*callback)(int), int ms) {
int r = 0;
- timer_ms = ms;
+ timer_kq = -1;
+ timer_stop = 0;
+ timer_ms = ms;
timer_callback = callback;
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__);
// since no caller of this func checks the return value for the moment
abort();
@@ -144,10 +143,10 @@ static void taosDeleteTimer(void *tharg) {
timer_delete(*pTimer);
}
-static pthread_t timerThread;
-static timer_t timerId;
+static pthread_t timerThread;
+static timer_t timerId;
static volatile bool stopTimer = false;
-static void *taosProcessAlarmSignal(void *tharg) {
+static void * taosProcessAlarmSignal(void *tharg) {
// Block the signal
sigset_t sigset;
sigemptyset(&sigset);
@@ -159,18 +158,18 @@ static void *taosProcessAlarmSignal(void *tharg) {
setThreadName("tmr");
- #ifdef _ALPINE
- sevent.sigev_notify = SIGEV_THREAD;
- sevent.sigev_value.sival_int = syscall(__NR_gettid);
- #else
- sevent.sigev_notify = SIGEV_THREAD_ID;
- sevent._sigev_un._tid = syscall(__NR_gettid);
- #endif
-
+#ifdef _ALPINE
+ sevent.sigev_notify = SIGEV_THREAD;
+ sevent.sigev_value.sival_int = syscall(__NR_gettid);
+#else
+ sevent.sigev_notify = SIGEV_THREAD_ID;
+ sevent._sigev_un._tid = syscall(__NR_gettid);
+#endif
+
sevent.sigev_signo = SIGALRM;
if (timer_create(CLOCK_REALTIME, &sevent, &timerId) == -1) {
- //printf("Failed to create timer");
+ // printf("Failed to create timer");
}
pthread_cleanup_push(taosDeleteTimer, &timerId);
@@ -182,36 +181,37 @@ static void *taosProcessAlarmSignal(void *tharg) {
ts.it_interval.tv_nsec = 1000000 * MSECONDS_PER_TICK;
if (timer_settime(timerId, 0, &ts, NULL)) {
- //printf("Failed to init timer");
+ // printf("Failed to init timer");
return NULL;
}
int signo;
while (!stopTimer) {
if (sigwait(&sigset, &signo)) {
- //printf("Failed to wait signal: number %d", signo);
+ // printf("Failed to wait signal: number %d", signo);
continue;
}
/* //printf("Signal handling: number %d ......\n", signo); */
callback(0);
}
-
+
pthread_cleanup_pop(1);
return NULL;
}
int taosInitTimer(void (*callback)(int), int ms) {
+ stopTimer = false;
pthread_attr_t tattr;
pthread_attr_init(&tattr);
int code = pthread_create(&timerThread, &tattr, taosProcessAlarmSignal, callback);
pthread_attr_destroy(&tattr);
if (code != 0) {
- //printf("failed to create timer thread");
+ // printf("failed to create timer thread");
return -1;
} else {
- //printf("timer thread:0x%08" PRIx64 " is created", taosGetPthreadId(timerThread));
+ // printf("timer thread:0x%08" PRIx64 " is created", taosGetPthreadId(timerThread));
}
return 0;
@@ -220,7 +220,7 @@ int taosInitTimer(void (*callback)(int), int ms) {
void taosUninitTimer() {
stopTimer = true;
- //printf("join timer thread:0x%08" PRIx64, taosGetPthreadId(timerThread));
+ // printf("join timer thread:0x%08" PRIx64, taosGetPthreadId(timerThread));
pthread_join(timerThread, NULL);
}
diff --git a/source/util/src/tjson.c b/source/util/src/tjson.c
index 556e8f8060..13367843fc 100644
--- a/source/util/src/tjson.c
+++ b/source/util/src/tjson.c
@@ -32,6 +32,10 @@ int32_t tjsonAddIntegerToObject(SJson* pJson, const char* pName, const uint64_t
return tjsonAddStringToObject(pJson, pName, tmp);
}
+int32_t tjsonAddDoubleToObject(SJson* pJson, const char* pName, const double number) {
+ return (NULL == cJSON_AddNumberToObject((cJSON*)pJson, pName, number) ? TSDB_CODE_FAILED : TSDB_CODE_SUCCESS);
+}
+
int32_t tjsonAddStringToObject(SJson* pJson, const char* pName, const char* pVal) {
return (NULL == cJSON_AddStringToObject((cJSON*)pJson, pName, pVal) ? TSDB_CODE_FAILED : TSDB_CODE_SUCCESS);
}
@@ -74,3 +78,7 @@ int32_t tjsonAddItem(SJson* pJson, FToJson func, const void* pObj) {
char* tjsonToString(const SJson* pJson) {
return cJSON_Print((cJSON*)pJson);
}
+
+char* tjsonToUnformattedString(const SJson* pJson) {
+ return cJSON_PrintUnformatted((cJSON*)pJson);
+}
\ No newline at end of file
diff --git a/source/util/src/ttimer.c b/source/util/src/ttimer.c
index 1fdc2257d7..65101a5e07 100644
--- a/source/util/src/ttimer.c
+++ b/source/util/src/ttimer.c
@@ -13,19 +13,49 @@
* along with this program. If not, see .
*/
+#include "ttimer.h"
#include "os.h"
+#include "taoserror.h"
#include "tlog.h"
#include "tsched.h"
-#include "ttimer.h"
#include "tutil.h"
-#include "taoserror.h"
-#define tmrFatal(...) { if (tmrDebugFlag & DEBUG_FATAL) { taosPrintLog("TMR FATAL ", tmrDebugFlag, __VA_ARGS__); }}
-#define tmrError(...) { if (tmrDebugFlag & DEBUG_ERROR) { taosPrintLog("TMR ERROR ", tmrDebugFlag, __VA_ARGS__); }}
-#define tmrWarn(...) { if (tmrDebugFlag & DEBUG_WARN) { taosPrintLog("TMR WARN ", tmrDebugFlag, __VA_ARGS__); }}
-#define tmrInfo(...) { if (tmrDebugFlag & DEBUG_INFO) { taosPrintLog("TMR ", tmrDebugFlag, __VA_ARGS__); }}
-#define tmrDebug(...) { if (tmrDebugFlag & DEBUG_DEBUG) { taosPrintLog("TMR ", tmrDebugFlag, __VA_ARGS__); }}
-#define tmrTrace(...) { if (tmrDebugFlag & DEBUG_TRACE) { taosPrintLog("TMR ", tmrDebugFlag, __VA_ARGS__); }}
+#define tmrFatal(...) \
+ { \
+ if (tmrDebugFlag & DEBUG_FATAL) { \
+ taosPrintLog("TMR FATAL ", tmrDebugFlag, __VA_ARGS__); \
+ } \
+ }
+#define tmrError(...) \
+ { \
+ if (tmrDebugFlag & DEBUG_ERROR) { \
+ taosPrintLog("TMR ERROR ", tmrDebugFlag, __VA_ARGS__); \
+ } \
+ }
+#define tmrWarn(...) \
+ { \
+ if (tmrDebugFlag & DEBUG_WARN) { \
+ taosPrintLog("TMR WARN ", tmrDebugFlag, __VA_ARGS__); \
+ } \
+ }
+#define tmrInfo(...) \
+ { \
+ if (tmrDebugFlag & DEBUG_INFO) { \
+ taosPrintLog("TMR ", tmrDebugFlag, __VA_ARGS__); \
+ } \
+ }
+#define tmrDebug(...) \
+ { \
+ if (tmrDebugFlag & DEBUG_DEBUG) { \
+ taosPrintLog("TMR ", tmrDebugFlag, __VA_ARGS__); \
+ } \
+ }
+#define tmrTrace(...) \
+ { \
+ if (tmrDebugFlag & DEBUG_TRACE) { \
+ taosPrintLog("TMR ", tmrDebugFlag, __VA_ARGS__); \
+ } \
+ }
#define TIMER_STATE_WAITING 0
#define TIMER_STATE_EXPIRED 1
@@ -81,7 +111,7 @@ typedef struct time_wheel_t {
tmr_obj_t** slots;
} time_wheel_t;
-int32_t tmrDebugFlag = 131;
+int32_t tmrDebugFlag = 131;
uint32_t tsMaxTmrCtrl = 512;
static pthread_once_t tmrModuleInit = PTHREAD_ONCE_INIT;
@@ -91,7 +121,7 @@ static tmr_ctrl_t* unusedTmrCtrl = NULL;
static void* tmrQhandle;
static int numOfTmrCtrl = 0;
-int taosTmrThreads = 1;
+int taosTmrThreads = 1;
static uintptr_t nextTimerId = 0;
static time_wheel_t wheels[] = {
@@ -119,7 +149,7 @@ static void timerDecRef(tmr_obj_t* timer) {
static void lockTimerList(timer_list_t* list) {
int64_t tid = taosGetSelfPthreadId();
- int i = 0;
+ int i = 0;
while (atomic_val_compare_exchange_64(&(list->lockedBy), 0, tid) != 0) {
if (++i % 1000 == 0) {
sched_yield();
@@ -276,11 +306,11 @@ static void addToExpired(tmr_obj_t* head) {
const char* fmt = "%s adding expired timer[id=%" PRIuPTR ", fp=%p, param=%p] to queue.";
while (head != NULL) {
- uintptr_t id = head->id;
+ uintptr_t id = head->id;
tmr_obj_t* next = head->next;
tmrDebug(fmt, head->ctrl->label, id, head->fp, head->param);
- SSchedMsg schedMsg;
+ SSchedMsg schedMsg;
schedMsg.fp = NULL;
schedMsg.tfp = processExpiredTimer;
schedMsg.msg = NULL;
@@ -491,6 +521,8 @@ static void taosTmrModuleInit(void) {
return;
}
+ memset(&timerMap, 0, sizeof(timerMap));
+
for (uint32_t i = 0; i < tsMaxTmrCtrl - 1; ++i) {
tmr_ctrl_t* ctrl = tmrCtrls + i;
ctrl->next = ctrl + 1;
@@ -570,7 +602,8 @@ void taosTmrCleanUp(void* handle) {
unusedTmrCtrl = ctrl;
pthread_mutex_unlock(&tmrCtrlMutex);
- if (numOfTmrCtrl <=0) {
+ tmrDebug("time controller's tmr ctrl size: %d", numOfTmrCtrl);
+ if (numOfTmrCtrl <= 0) {
taosUninitTimer();
taosCleanUpScheduler(tmrQhandle);
@@ -585,7 +618,7 @@ void taosTmrCleanUp(void* handle) {
for (size_t i = 0; i < timerMap.size; i++) {
timer_list_t* list = timerMap.slots + i;
- tmr_obj_t* t = list->timers;
+ tmr_obj_t* t = list->timers;
while (t != NULL) {
tmr_obj_t* next = t->mnext;
free(t);
@@ -595,6 +628,8 @@ void taosTmrCleanUp(void* handle) {
free(timerMap.slots);
free(tmrCtrls);
- tmrDebug("timer module is cleaned up");
+ tmrCtrls = NULL;
+ unusedTmrCtrl = NULL;
+ tmrModuleInit = PTHREAD_ONCE_INIT; // to support restart
}
}