diff --git a/include/common/taosmsg.h b/include/common/taosmsg.h index 2b765aa526..2769f8bc7a 100644 --- a/include/common/taosmsg.h +++ b/include/common/taosmsg.h @@ -360,10 +360,10 @@ typedef struct { } SConnectMsg; typedef struct SEpSet { - int8_t inUse; - int8_t numOfEps; - uint16_t port[TSDB_MAX_REPLICA]; - char fqdn[TSDB_MAX_REPLICA][TSDB_FQDN_LEN]; + int8_t inUse; + int8_t numOfEps; + uint16_t port[TSDB_MAX_REPLICA]; + char fqdn[TSDB_MAX_REPLICA][TSDB_FQDN_LEN]; } SEpSet; typedef struct { @@ -383,14 +383,9 @@ typedef struct { int32_t maxUsers; int32_t maxDbs; int32_t maxTimeSeries; - int32_t maxConnections; int32_t maxStreams; - int32_t maxPointsPerSecond; - int64_t maxStorage; // In unit of GB - int64_t maxQueryTime; // In unit of hour - int64_t maxInbound; - int64_t maxOutbound; - int8_t accessState; // Configured only by command + int64_t maxStorage; // In unit of GB + int32_t accessState; // Configured only by command } SCreateAcctMsg, SAlterAcctMsg; typedef struct { @@ -398,8 +393,8 @@ typedef struct { } SDropUserMsg, SDropAcctMsg; typedef struct { - char user[TSDB_USER_LEN]; - char pass[TSDB_KEY_LEN]; + char user[TSDB_USER_LEN]; + char pass[TSDB_KEY_LEN]; } SCreateUserMsg, SAlterUserMsg; typedef struct { @@ -418,10 +413,10 @@ typedef struct { } SDropSTableMsg; typedef struct SColIndex { - int16_t colId; // column id - int16_t colIndex; // column index in colList if it is a normal column or index in tagColList if a tag - uint16_t flag; // denote if it is a tag or a normal column - char name[TSDB_COL_NAME_LEN + TSDB_DB_NAME_LEN + 1]; + int16_t colId; // column id + int16_t colIndex; // column index in colList if it is a normal column or index in tagColList if a tag + int16_t flag; // denote if it is a tag or a normal column + char name[TSDB_COL_NAME_LEN + TSDB_DB_NAME_LEN + 1]; } SColIndex; typedef struct SColumnFilterInfo { @@ -515,8 +510,8 @@ typedef struct { int16_t numOfCols; // the number of columns will be load from vnode SInterval interval; // SSessionWindow sw; // session window - uint16_t tagCondLen; // tag length in current query - uint16_t colCondLen; // column length in current query + int16_t tagCondLen; // tag length in current query + int16_t colCondLen; // column length in current query int16_t numOfGroupCols; // num of group by columns int16_t orderByIdx; int16_t orderType; // used in group by xx order by xxx @@ -524,10 +519,10 @@ typedef struct { int16_t prjOrder; // global order in super table projection query. int64_t limit; int64_t offset; - uint32_t queryType; // denote another query process + int32_t queryType; // denote another query process int16_t numOfOutput; // final output columns numbers int16_t fillType; // interpolate type - uint64_t fillVal; // default value array list + int64_t fillVal; // default value array list int32_t secondStageOutput; STsBufInfo tsBuf; // tsBuf info int32_t numOfTags; // number of tags columns involved @@ -542,63 +537,71 @@ typedef struct { } SQueryTableMsg; typedef struct { - int32_t code; - union{uint64_t qhandle; uint64_t qId;}; // query handle + int32_t code; + union { + uint64_t qhandle; + uint64_t qId; + }; // query handle } SQueryTableRsp; // todo: the show handle should be replaced with id typedef struct { SMsgHead header; - union{uint64_t qhandle; uint64_t qId;}; // query handle - uint16_t free; + union { + int32_t showId; + int64_t qhandle; + int64_t qId; + }; // query handle + int8_t free; } SRetrieveTableMsg; typedef struct SRetrieveTableRsp { int32_t numOfRows; - int8_t completed; // all results are returned to client - int16_t precision; - int64_t offset; // updated offset value for multi-vnode projection query + int64_t offset; // updated offset value for multi-vnode projection query int64_t useconds; + int8_t completed; // all results are returned to client + int8_t precision; int8_t compressed; + int8_t reserved; int32_t compLen; char data[]; } SRetrieveTableRsp; typedef struct { - char db[TSDB_FULL_DB_NAME_LEN]; - int32_t cacheBlockSize; //MB - int32_t totalBlocks; - int32_t maxTables; - int32_t daysPerFile; - int32_t daysToKeep0; - int32_t daysToKeep1; - int32_t daysToKeep2; - int32_t minRowsPerFileBlock; - int32_t maxRowsPerFileBlock; - int32_t commitTime; - int32_t fsyncPeriod; - uint8_t precision; // time resolution - int8_t compression; - int8_t walLevel; - int8_t replications; - int8_t quorum; - int8_t ignoreExist; - int8_t update; - int8_t cacheLastRow; - int8_t dbType; - int16_t partitions; - int8_t reserve[5]; + char db[TSDB_FULL_DB_NAME_LEN]; + int32_t cacheBlockSize; // MB + int32_t totalBlocks; + int32_t maxTables; + int32_t daysPerFile; + int32_t daysToKeep0; + int32_t daysToKeep1; + int32_t daysToKeep2; + int32_t minRowsPerFileBlock; + int32_t maxRowsPerFileBlock; + int32_t commitTime; + int32_t fsyncPeriod; + int8_t precision; // time resolution + int8_t compression; + int8_t walLevel; + int8_t replications; + int8_t quorum; + int8_t ignoreExist; + int8_t update; + int8_t cacheLastRow; + int8_t dbType; + int16_t partitions; + int8_t reserve[5]; } SCreateDbMsg, SAlterDbMsg; typedef struct { - char name[TSDB_FUNC_NAME_LEN]; - char path[PATH_MAX]; - int32_t funcType; - uint8_t outputType; - int16_t outputLen; - int32_t bufSize; - int32_t codeLen; - char code[]; + char name[TSDB_FUNC_NAME_LEN]; + char path[PATH_MAX]; + int32_t funcType; + int8_t outputType; + int16_t outputLen; + int32_t bufSize; + int32_t codeLen; + char code[]; } SCreateFuncMsg; typedef struct { @@ -626,8 +629,8 @@ typedef struct { } SDropFuncMsg; typedef struct { - char db[TSDB_TABLE_FNAME_LEN]; - uint8_t ignoreNotExists; + char db[TSDB_TABLE_FNAME_LEN]; + int8_t ignoreNotExists; } SDropDbMsg, SUseDbMsg, SSyncDbMsg; typedef struct { @@ -701,7 +704,7 @@ typedef struct { typedef struct { char db[TSDB_FULL_DB_NAME_LEN]; - uint32_t vgId; + int32_t vgId; int32_t cacheBlockSize; int32_t totalBlocks; int32_t daysPerFile; @@ -762,32 +765,31 @@ typedef struct { } SVgroupsMsg, SVgroupsInfo; typedef struct STableMetaMsg { - int32_t contLen; - char tableFname[TSDB_TABLE_FNAME_LEN]; // table id - uint8_t numOfTags; - uint8_t precision; - uint8_t tableType; - int16_t numOfColumns; - int16_t sversion; - int16_t tversion; - int32_t tid; - uint64_t uid; - SVgroupMsg vgroup; - - char sTableName[TSDB_TABLE_FNAME_LEN]; - uint64_t suid; - SSchema schema[]; + int32_t contLen; + char tableFname[TSDB_TABLE_FNAME_LEN]; // table id + int8_t numOfTags; + int8_t precision; + int8_t tableType; + int16_t numOfColumns; + int16_t sversion; + int16_t tversion; + int32_t tid; + int64_t uid; + SVgroupMsg vgroup; + char sTableName[TSDB_TABLE_FNAME_LEN]; + int64_t suid; + SSchema schema[]; } STableMetaMsg; typedef struct SMultiTableMeta { - int32_t numOfTables; - int32_t numOfVgroup; - int32_t numOfUdf; - int32_t contLen; - uint8_t compressed; // denote if compressed or not - uint32_t rawLen; // size before compress - uint8_t metaClone; // make meta clone after retrieve meta from mnode - char meta[]; + int32_t numOfTables; + int32_t numOfVgroup; + int32_t numOfUdf; + int32_t contLen; + int8_t compressed; // denote if compressed or not + int32_t rawLen; // size before compress + uint8_t metaClone; // make meta clone after retrieve meta from mnode + char meta[]; } SMultiTableMeta; typedef struct { @@ -802,10 +804,10 @@ typedef struct { * payloadLen is the length of payload */ typedef struct { - int8_t type; - char db[TSDB_FULL_DB_NAME_LEN]; - uint16_t payloadLen; - char payload[]; + int8_t type; + char db[TSDB_FULL_DB_NAME_LEN]; + int16_t payloadLen; + char payload[]; } SShowMsg; typedef struct { @@ -815,7 +817,7 @@ typedef struct { } SCompactMsg; typedef struct SShowRsp { - uint64_t qhandle; + int32_t showId; STableMetaMsg tableMeta; } SShowRsp; @@ -837,8 +839,8 @@ typedef struct { } SConfigTableMsg; typedef struct { - uint32_t dnodeId; - int32_t vgId; + int32_t dnodeId; + int32_t vgId; } SConfigVnodeMsg; typedef struct { @@ -847,29 +849,29 @@ typedef struct { } SCfgDnodeMsg; typedef struct { - char sql[TSDB_SHOW_SQL_LEN]; - uint32_t queryId; - int64_t useconds; - int64_t stime; - uint64_t qId; - uint64_t sqlObjId; - int32_t pid; - char fqdn[TSDB_FQDN_LEN]; - uint8_t stableQuery; - int32_t numOfSub; - char subSqlInfo[TSDB_SHOW_SUBQUERY_LEN]; //include subqueries' index, Obj IDs and states(C-complete/I-imcomplete) + char sql[TSDB_SHOW_SQL_LEN]; + int32_t queryId; + int64_t useconds; + int64_t stime; + int64_t qId; + int64_t sqlObjId; + int32_t pid; + char fqdn[TSDB_FQDN_LEN]; + int8_t stableQuery; + int32_t numOfSub; + char subSqlInfo[TSDB_SHOW_SUBQUERY_LEN]; // include subqueries' index, Obj IDs and states(C-complete/I-imcomplete) } SQueryDesc; typedef struct { - char sql[TSDB_SHOW_SQL_LEN]; - char dstTable[TSDB_TABLE_NAME_LEN]; - uint32_t streamId; - int64_t num; // number of computing/cycles - int64_t useconds; - int64_t ctime; - int64_t stime; - int64_t slidingTime; - int64_t interval; + char sql[TSDB_SHOW_SQL_LEN]; + char dstTable[TSDB_TABLE_NAME_LEN]; + int32_t streamId; + int64_t num; // number of computing/cycles + int64_t useconds; + int64_t ctime; + int64_t stime; + int64_t slidingTime; + int64_t interval; } SStreamDesc; typedef struct { @@ -893,8 +895,18 @@ typedef struct { } SHeartBeatRsp; typedef struct { - char queryId[TSDB_KILL_MSG_LEN + 1]; -} SKillQueryMsg, SKillConnMsg; + int32_t connId; + int32_t streamId; +} SKillStreamMsg; + +typedef struct { + int32_t connId; + int32_t queryId; +} SKillQueryMsg; + +typedef struct { + int32_t connId; +} SKillConnMsg; typedef struct { char user[TSDB_USER_LEN]; diff --git a/include/dnode/mgmt/dnode.h b/include/dnode/mgmt/dnode.h index 50886932ce..540a501f3a 100644 --- a/include/dnode/mgmt/dnode.h +++ b/include/dnode/mgmt/dnode.h @@ -31,6 +31,7 @@ typedef struct { int16_t numOfSupportMnodes; int16_t numOfSupportVnodes; int16_t numOfSupportQnodes; + int8_t enableTelem; int32_t statusInterval; int32_t mnodeEqualVnodeNum; float numOfThreadsPerCore; @@ -45,6 +46,8 @@ typedef struct { char timezone[TSDB_TIMEZONE_LEN]; char locale[TSDB_LOCALE_LEN]; char charset[TSDB_LOCALE_LEN]; + char buildinfo[64]; + char gitinfo[48]; } SDnodeOpt; /* ------------------------ SDnode ------------------------ */ diff --git a/include/dnode/mnode/mnode.h b/include/dnode/mnode/mnode.h index 0a897b93f8..8a8346fbc0 100644 --- a/include/dnode/mnode/mnode.h +++ b/include/dnode/mnode/mnode.h @@ -43,24 +43,31 @@ typedef struct SMnodeLoad { int64_t compStorage; } SMnodeLoad; +typedef struct SMnodeCfg { + int32_t sver; + int8_t enableTelem; + int32_t statusInterval; + int32_t mnodeEqualVnodeNum; + int32_t shellActivityTimer; + char *timezone; + char *locale; + char *charset; + char *buildinfo; + char *gitinfo; +} SMnodeCfg; + typedef struct { int32_t dnodeId; int32_t clusterId; int8_t replica; int8_t selfIndex; SReplica replicas[TSDB_MAX_REPLICA]; + SMnodeCfg cfg; SDnode *pDnode; PutMsgToMnodeQFp putMsgToApplyMsgFp; SendMsgToDnodeFp sendMsgToDnodeFp; SendMsgToMnodeFp sendMsgToMnodeFp; SendRedirectMsgFp sendRedirectMsgFp; - int32_t sver; - int32_t statusInterval; - int32_t mnodeEqualVnodeNum; - int32_t shellActivityTimer; - char *timezone; - char *locale; - char *charset; } SMnodeOpt; /* ------------------------ SMnode ------------------------ */ diff --git a/include/util/taoserror.h b/include/util/taoserror.h index 413c84fe31..f6cefa96df 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -76,6 +76,10 @@ int32_t* taosGetErrno(); #define TSDB_CODE_REF_ALREADY_EXIST TAOS_DEF_ERROR_CODE(0, 0x0114) #define TSDB_CODE_REF_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x0115) +#define TSDB_CODE_INVALID_VERSION_NUMBER TAOS_DEF_ERROR_CODE(0, 0x0120) +#define TSDB_CODE_INVALID_VERSION_STRING TAOS_DEF_ERROR_CODE(0, 0x0121) +#define TSDB_CODE_VERSION_NOT_COMPATIBLE TAOS_DEF_ERROR_CODE(0, 0x0122) + //client #define TSDB_CODE_TSC_INVALID_OPERATION TAOS_DEF_ERROR_CODE(0, 0x0200) //"Invalid Operation") #define TSDB_CODE_TSC_INVALID_QHANDLE TAOS_DEF_ERROR_CODE(0, 0x0201) //"Invalid qhandle") diff --git a/include/util/tversion.h b/include/util/tversion.h new file mode 100644 index 0000000000..3d7a7e1b66 --- /dev/null +++ b/include/util/tversion.h @@ -0,0 +1,31 @@ +/* + * 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_UTIL_VERSION_H +#define _TD_UTIL_VERSION_H + +#ifdef __cplusplus +extern "C" { +#endif + +int32_t taosVersionStrToInt(const char *vstr, int32_t *vint); +int32_t taosVersionIntToStr(int32_t vint, char *vstr, int32_t len); +int32_t taosCheckVersionCompatible(int32_t clientVer, int32_t serverVer, int32_t comparedSegments); + +#ifdef __cplusplus +} +#endif + +#endif /*_TD_UTIL_VERSION_H*/ diff --git a/source/common/src/versionUtil.c b/source/common/src/versionUtil.c deleted file mode 100644 index 22c50fa5cf..0000000000 --- a/source/common/src/versionUtil.c +++ /dev/null @@ -1,63 +0,0 @@ -#include "os.h" -#include "tdef.h" -#include "ulog.h" -#include "taoserror.h" - -bool taosGetVersionNumber(char *versionStr, int *versionNubmer) { - if (versionStr == NULL || versionNubmer == NULL) { - return false; - } - - int versionNumberPos[5] = {0}; - int len = (int)strlen(versionStr); - int dot = 0; - for (int pos = 0; pos < len && dot < 4; ++pos) { - if (versionStr[pos] == '.') { - versionStr[pos] = 0; - versionNumberPos[++dot] = pos + 1; - } - } - - if (dot != 3) { - return false; - } - - for (int pos = 0; pos < 4; ++pos) { - versionNubmer[pos] = atoi(versionStr + versionNumberPos[pos]); - } - versionStr[versionNumberPos[1] - 1] = '.'; - versionStr[versionNumberPos[2] - 1] = '.'; - versionStr[versionNumberPos[3] - 1] = '.'; - - return true; -} - -int taosCheckVersion(char *input_client_version, char *input_server_version, int comparedSegments) { - char client_version[TSDB_VERSION_LEN] = {0}; - char server_version[TSDB_VERSION_LEN] = {0}; - int clientVersionNumber[4] = {0}; - int serverVersionNumber[4] = {0}; - - tstrncpy(client_version, input_client_version, sizeof(client_version)); - tstrncpy(server_version, input_server_version, sizeof(server_version)); - - if (!taosGetVersionNumber(client_version, clientVersionNumber)) { - uError("invalid client version:%s", client_version); - return TSDB_CODE_TSC_INVALID_VERSION; - } - - if (!taosGetVersionNumber(server_version, serverVersionNumber)) { - uError("invalid server version:%s", server_version); - return TSDB_CODE_TSC_INVALID_VERSION; - } - - for(int32_t i = 0; i < comparedSegments; ++i) { - if (clientVersionNumber[i] != serverVersionNumber[i]) { - uError("the %d-th number of server version:%s not matched with client version:%s", i, server_version, - client_version); - return TSDB_CODE_TSC_INVALID_VERSION; - } - } - - return 0; -} diff --git a/source/dnode/mgmt/daemon/src/daemon.c b/source/dnode/mgmt/daemon/src/daemon.c index 08624f20f4..cf9a960062 100644 --- a/source/dnode/mgmt/daemon/src/daemon.c +++ b/source/dnode/mgmt/daemon/src/daemon.c @@ -136,7 +136,7 @@ void dmnWaitSignal() { } void dmnInitOption(SDnodeOpt *pOption) { - pOption->sver = tsVersion; + pOption->sver = 30000000; //3.0.0.0 pOption->numOfCores = tsNumOfCores; pOption->numOfSupportMnodes = 1; pOption->numOfSupportVnodes = 1; @@ -155,6 +155,8 @@ void dmnInitOption(SDnodeOpt *pOption) { tstrncpy(pOption->timezone, tsTimezone, TSDB_TIMEZONE_LEN); tstrncpy(pOption->locale, tsLocale, TSDB_LOCALE_LEN); tstrncpy(pOption->charset, tsCharset, TSDB_LOCALE_LEN); + tstrncpy(pOption->buildinfo, buildinfo, 64); + tstrncpy(pOption->gitinfo, gitinfo, 48); } int dmnRunDnode() { diff --git a/source/dnode/mgmt/impl/src/dndMnode.c b/source/dnode/mgmt/impl/src/dndMnode.c index 4afce4655d..374a2f2b2c 100644 --- a/source/dnode/mgmt/impl/src/dndMnode.c +++ b/source/dnode/mgmt/impl/src/dndMnode.c @@ -331,13 +331,16 @@ static void dndInitMnodeOption(SDnode *pDnode, SMnodeOpt *pOption) { pOption->putMsgToApplyMsgFp = dndPutMsgIntoMnodeApplyQueue; pOption->dnodeId = dndGetDnodeId(pDnode); pOption->clusterId = dndGetClusterId(pDnode); - pOption->sver = pDnode->opt.sver; - pOption->statusInterval = pDnode->opt.statusInterval; - pOption->mnodeEqualVnodeNum = pDnode->opt.mnodeEqualVnodeNum; - pOption->shellActivityTimer = pDnode->opt.shellActivityTimer; - pOption->timezone = pDnode->opt.timezone; - pOption->charset = pDnode->opt.charset; - pOption->locale = pDnode->opt.locale; + pOption->cfg.sver = pDnode->opt.sver; + pOption->cfg.enableTelem = pDnode->opt.enableTelem; + pOption->cfg.statusInterval = pDnode->opt.statusInterval; + pOption->cfg.mnodeEqualVnodeNum = pDnode->opt.mnodeEqualVnodeNum; + pOption->cfg.shellActivityTimer = pDnode->opt.shellActivityTimer; + pOption->cfg.timezone = pDnode->opt.timezone; + pOption->cfg.charset = pDnode->opt.charset; + pOption->cfg.locale = pDnode->opt.locale; + pOption->cfg.gitinfo = pDnode->opt.gitinfo; + pOption->cfg.buildinfo = pDnode->opt.buildinfo; } static void dndBuildMnodeDeployOption(SDnode *pDnode, SMnodeOpt *pOption) { diff --git a/source/dnode/mgmt/impl/test/CMakeLists.txt b/source/dnode/mgmt/impl/test/CMakeLists.txt index 95ffa548b2..e7aa103996 100644 --- a/source/dnode/mgmt/impl/test/CMakeLists.txt +++ b/source/dnode/mgmt/impl/test/CMakeLists.txt @@ -1 +1,4 @@ -add_subdirectory(test01) \ No newline at end of file +add_subdirectory(acct) +add_subdirectory(cluster) +add_subdirectory(profile) +add_subdirectory(show) diff --git a/source/dnode/mgmt/impl/test/test01/CMakeLists.txt b/source/dnode/mgmt/impl/test/acct/CMakeLists.txt similarity index 64% rename from source/dnode/mgmt/impl/test/test01/CMakeLists.txt rename to source/dnode/mgmt/impl/test/acct/CMakeLists.txt index 5f88e9c116..3e963df2e6 100644 --- a/source/dnode/mgmt/impl/test/test01/CMakeLists.txt +++ b/source/dnode/mgmt/impl/test/acct/CMakeLists.txt @@ -1,20 +1,20 @@ -add_executable(dndTest01 "") +add_executable(dndTestAcct "") -target_sources(dndTest01 +target_sources(dndTestAcct PRIVATE - "test01.cpp" + "acct.cpp" "../sut/deploy.cpp" ) target_link_libraries( - dndTest01 + dndTestAcct PUBLIC dnode PUBLIC util PUBLIC os PUBLIC gtest_main ) -target_include_directories(dndTest01 +target_include_directories(dndTestAcct PUBLIC "${CMAKE_SOURCE_DIR}/include/server/dnode/mgmt" "${CMAKE_CURRENT_SOURCE_DIR}/../../inc" @@ -24,6 +24,6 @@ target_include_directories(dndTest01 enable_testing() add_test( - NAME dndTest01 - COMMAND dndTest01 + NAME dndTestAcct + COMMAND dndTestAcct ) diff --git a/source/dnode/mgmt/impl/test/acct/acct.cpp b/source/dnode/mgmt/impl/test/acct/acct.cpp new file mode 100644 index 0000000000..cda44a3be8 --- /dev/null +++ b/source/dnode/mgmt/impl/test/acct/acct.cpp @@ -0,0 +1,112 @@ +/* + * 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 "deploy.h" + +class DndTestAcct : public ::testing::Test { + protected: + void SetUp() override {} + void TearDown() override {} + + static void SetUpTestSuite() { + const char* user = "root"; + const char* pass = "taosdata"; + const char* path = "/tmp/dndTestAcct"; + const char* fqdn = "localhost"; + uint16_t port = 9520; + + pServer = createServer(path, fqdn, port); + ASSERT(pServer); + pClient = createClient(user, pass, fqdn, port); + } + + static void TearDownTestSuite() { + dropServer(pServer); + dropClient(pClient); + } + + static SServer* pServer; + static SClient* pClient; + static int32_t connId; +}; + +SServer* DndTestAcct::pServer; +SClient* DndTestAcct::pClient; +int32_t DndTestAcct::connId; + +TEST_F(DndTestAcct, CreateAcct) { + ASSERT_NE(pClient, nullptr); + + SCreateAcctMsg* pReq = (SCreateAcctMsg*)rpcMallocCont(sizeof(SCreateAcctMsg)); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SCreateAcctMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_CREATE_ACCT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_MSG_NOT_PROCESSED); +} + +TEST_F(DndTestAcct, AlterAcct) { + ASSERT_NE(pClient, nullptr); + + SAlterAcctMsg* pReq = (SAlterAcctMsg*)rpcMallocCont(sizeof(SAlterAcctMsg)); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SAlterAcctMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_ALTER_ACCT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_MSG_NOT_PROCESSED); +} + +TEST_F(DndTestAcct, DropAcct) { + ASSERT_NE(pClient, nullptr); + + SDropAcctMsg* pReq = (SDropAcctMsg*)rpcMallocCont(sizeof(SDropAcctMsg)); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SDropAcctMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_DROP_ACCT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_MSG_NOT_PROCESSED); +} + +TEST_F(DndTestAcct, ShowAcct) { + ASSERT_NE(pClient, nullptr); + + SShowMsg* pReq = (SShowMsg*)rpcMallocCont(sizeof(SShowMsg)); + pReq->type = TSDB_MGMT_TABLE_ACCT; + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SShowMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_INVALID_MSG_TYPE); +} \ No newline at end of file diff --git a/source/dnode/mgmt/impl/test/cluster/CMakeLists.txt b/source/dnode/mgmt/impl/test/cluster/CMakeLists.txt new file mode 100644 index 0000000000..b513f290e4 --- /dev/null +++ b/source/dnode/mgmt/impl/test/cluster/CMakeLists.txt @@ -0,0 +1,29 @@ +add_executable(dndTestCluster "") + +target_sources(dndTestCluster + PRIVATE + "cluster.cpp" + "../sut/deploy.cpp" +) + +target_link_libraries( + dndTestCluster + PUBLIC dnode + PUBLIC util + PUBLIC os + PUBLIC gtest_main +) + +target_include_directories(dndTestCluster + PUBLIC + "${CMAKE_SOURCE_DIR}/include/server/dnode/mgmt" + "${CMAKE_CURRENT_SOURCE_DIR}/../../inc" + "${CMAKE_CURRENT_SOURCE_DIR}/../sut" +) + +enable_testing() + +add_test( + NAME dndTestCluster + COMMAND dndTestCluster +) diff --git a/source/dnode/mgmt/impl/test/cluster/cluster.cpp b/source/dnode/mgmt/impl/test/cluster/cluster.cpp new file mode 100644 index 0000000000..d7f9bca5ed --- /dev/null +++ b/source/dnode/mgmt/impl/test/cluster/cluster.cpp @@ -0,0 +1,170 @@ +/* + * 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 "deploy.h" + +class DndTestCluster : public ::testing::Test { + protected: + void SetUp() override {} + void TearDown() override {} + + static void SetUpTestSuite() { + const char* user = "root"; + const char* pass = "taosdata"; + const char* path = "/tmp/dndTestCluster"; + const char* fqdn = "localhost"; + uint16_t port = 9521; + + pServer = createServer(path, fqdn, port); + ASSERT(pServer); + pClient = createClient(user, pass, fqdn, port); + } + + static void TearDownTestSuite() { + dropServer(pServer); + dropClient(pClient); + } + + static SServer* pServer; + static SClient* pClient; + static int32_t connId; +}; + +SServer* DndTestCluster::pServer; +SClient* DndTestCluster::pClient; +int32_t DndTestCluster::connId; + +TEST_F(DndTestCluster, ShowCluster) { + ASSERT_NE(pClient, nullptr); + int32_t showId = 0; + + { + SShowMsg* pReq = (SShowMsg*)rpcMallocCont(sizeof(SShowMsg)); + pReq->type = TSDB_MGMT_TABLE_CLUSTER; + strcpy(pReq->db, ""); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SShowMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SShowRsp* pRsp = (SShowRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->showId = htonl(pRsp->showId); + STableMetaMsg* pMeta = &pRsp->tableMeta; + pMeta->contLen = htonl(pMeta->contLen); + pMeta->numOfColumns = htons(pMeta->numOfColumns); + pMeta->sversion = htons(pMeta->sversion); + pMeta->tversion = htons(pMeta->tversion); + pMeta->tid = htonl(pMeta->tid); + pMeta->uid = htobe64(pMeta->uid); + pMeta->suid = htobe64(pMeta->suid); + + showId = pRsp->showId; + + EXPECT_NE(pRsp->showId, 0); + EXPECT_EQ(pMeta->contLen, 0); + EXPECT_STREQ(pMeta->tableFname, "show cluster"); + EXPECT_EQ(pMeta->numOfTags, 0); + EXPECT_EQ(pMeta->precision, 0); + EXPECT_EQ(pMeta->tableType, 0); + EXPECT_EQ(pMeta->numOfColumns, 3); + EXPECT_EQ(pMeta->sversion, 0); + EXPECT_EQ(pMeta->tversion, 0); + EXPECT_EQ(pMeta->tid, 0); + EXPECT_EQ(pMeta->uid, 0); + EXPECT_STREQ(pMeta->sTableName, ""); + EXPECT_EQ(pMeta->suid, 0); + + SSchema* pSchema = NULL; + pSchema = &pMeta->schema[0]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_INT); + EXPECT_EQ(pSchema->bytes, 4); + EXPECT_STREQ(pSchema->name, "id"); + + pSchema = &pMeta->schema[1]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_BINARY); + EXPECT_EQ(pSchema->bytes, TSDB_CLUSTER_ID_LEN + VARSTR_HEADER_SIZE); + EXPECT_STREQ(pSchema->name, "name"); + + pSchema = &pMeta->schema[2]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_TIMESTAMP); + EXPECT_EQ(pSchema->bytes, 8); + EXPECT_STREQ(pSchema->name, "create_time"); + } + + { + SRetrieveTableMsg* pReq = (SRetrieveTableMsg*)rpcMallocCont(sizeof(SRetrieveTableMsg)); + pReq->showId = htonl(showId); + pReq->free = 0; + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SRetrieveTableMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW_RETRIEVE; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, 0); + + SRetrieveTableRsp* pRsp = (SRetrieveTableRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->numOfRows = htonl(pRsp->numOfRows); + pRsp->offset = htobe64(pRsp->offset); + pRsp->useconds = htobe64(pRsp->useconds); + pRsp->compLen = htonl(pRsp->compLen); + + EXPECT_EQ(pRsp->numOfRows, 1); + EXPECT_EQ(pRsp->offset, 0); + EXPECT_EQ(pRsp->useconds, 0); + EXPECT_EQ(pRsp->completed, 1); + EXPECT_EQ(pRsp->precision, TSDB_TIME_PRECISION_MILLI); + EXPECT_EQ(pRsp->compressed, 0); + EXPECT_EQ(pRsp->reserved, 0); + EXPECT_EQ(pRsp->compLen, 0); + + char* pData = pRsp->data; + int32_t pos = 0; + + int32_t id = *((int32_t*)(pData + pos)); + pos += sizeof(int32_t); + + int32_t nameLen = varDataLen(pData + pos); + pos += sizeof(VarDataLenT); + + char* name = (char*)(pData + pos); + pos += TSDB_CLUSTER_ID_LEN; + + int64_t create_time = *((int64_t*)(pData + pos)); + pos += sizeof(int64_t); + + EXPECT_NE(id, 0); + EXPECT_EQ(nameLen, 36); + EXPECT_STRNE(name, ""); + EXPECT_GT(create_time, 0); + printf("--- id:%d nameLen:%d name:%s time:%" PRId64 " --- \n", id, nameLen, name, create_time); + } +} \ No newline at end of file diff --git a/source/dnode/mgmt/impl/test/profile/CMakeLists.txt b/source/dnode/mgmt/impl/test/profile/CMakeLists.txt new file mode 100644 index 0000000000..2e99a2e53d --- /dev/null +++ b/source/dnode/mgmt/impl/test/profile/CMakeLists.txt @@ -0,0 +1,29 @@ +add_executable(dndTestProfile "") + +target_sources(dndTestProfile + PRIVATE + "profile.cpp" + "../sut/deploy.cpp" +) + +target_link_libraries( + dndTestProfile + PUBLIC dnode + PUBLIC util + PUBLIC os + PUBLIC gtest_main +) + +target_include_directories(dndTestProfile + PUBLIC + "${CMAKE_SOURCE_DIR}/include/server/dnode/mgmt" + "${CMAKE_CURRENT_SOURCE_DIR}/../../inc" + "${CMAKE_CURRENT_SOURCE_DIR}/../sut" +) + +enable_testing() + +add_test( + NAME dndTestProfile + COMMAND dndTestProfile +) diff --git a/source/dnode/mgmt/impl/test/profile/profile.cpp b/source/dnode/mgmt/impl/test/profile/profile.cpp new file mode 100644 index 0000000000..14e8dda457 --- /dev/null +++ b/source/dnode/mgmt/impl/test/profile/profile.cpp @@ -0,0 +1,736 @@ +/* + * 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 "deploy.h" + +class DndTestProfile : public ::testing::Test { + protected: + void SetUp() override {} + void TearDown() override {} + + static void SetUpTestSuite() { + const char* user = "root"; + const char* pass = "taosdata"; + const char* path = "/tmp/dndTestProfile"; + const char* fqdn = "localhost"; + uint16_t port = 9522; + + pServer = createServer(path, fqdn, port); + ASSERT(pServer); + pClient = createClient(user, pass, fqdn, port); + } + + static void TearDownTestSuite() { + dropServer(pServer); + dropClient(pClient); + } + + static SServer* pServer; + static SClient* pClient; + static int32_t connId; +}; + +SServer* DndTestProfile::pServer; +SClient* DndTestProfile::pClient; +int32_t DndTestProfile::connId; + +TEST_F(DndTestProfile, SConnectMsg_01) { + ASSERT_NE(pClient, nullptr); + + SConnectMsg* pReq = (SConnectMsg*)rpcMallocCont(sizeof(SConnectMsg)); + pReq->pid = htonl(1234); + strcpy(pReq->app, "dndTestProfile"); + strcpy(pReq->db, ""); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SConnectMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_CONNECT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SConnectRsp* pRsp = (SConnectRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->acctId = htonl(pRsp->acctId); + pRsp->clusterId = htonl(pRsp->clusterId); + pRsp->connId = htonl(pRsp->connId); + pRsp->epSet.port[0] = htons(pRsp->epSet.port[0]); + + EXPECT_EQ(pRsp->acctId, 1); + EXPECT_GT(pRsp->clusterId, 0); + EXPECT_EQ(pRsp->connId, 1); + EXPECT_EQ(pRsp->superAuth, 1); + EXPECT_EQ(pRsp->readAuth, 1); + EXPECT_EQ(pRsp->writeAuth, 1); + + EXPECT_EQ(pRsp->epSet.inUse, 0); + EXPECT_EQ(pRsp->epSet.numOfEps, 1); + EXPECT_EQ(pRsp->epSet.port[0], 9522); + EXPECT_STREQ(pRsp->epSet.fqdn[0], "localhost"); + + connId = pRsp->connId; +} + +TEST_F(DndTestProfile, SConnectMsg_02) { + ASSERT_NE(pClient, nullptr); + + SConnectMsg* pReq = (SConnectMsg*)rpcMallocCont(sizeof(SConnectMsg)); + pReq->pid = htonl(1234); + strcpy(pReq->app, "dndTestProfile"); + strcpy(pReq->db, "invalid_db"); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SConnectMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_CONNECT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_INVALID_DB); + ASSERT_EQ(pMsg->contLen, 0); +} + +TEST_F(DndTestProfile, SConnectMsg_03) { + ASSERT_NE(pClient, nullptr); + int32_t showId = 0; + + { + SShowMsg* pReq = (SShowMsg*)rpcMallocCont(sizeof(SShowMsg)); + pReq->type = TSDB_MGMT_TABLE_CONNS; + strcpy(pReq->db, ""); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SShowMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SShowRsp* pRsp = (SShowRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->showId = htonl(pRsp->showId); + STableMetaMsg* pMeta = &pRsp->tableMeta; + pMeta->contLen = htonl(pMeta->contLen); + pMeta->numOfColumns = htons(pMeta->numOfColumns); + pMeta->sversion = htons(pMeta->sversion); + pMeta->tversion = htons(pMeta->tversion); + pMeta->tid = htonl(pMeta->tid); + pMeta->uid = htobe64(pMeta->uid); + pMeta->suid = htobe64(pMeta->suid); + + showId = pRsp->showId; + + EXPECT_NE(pRsp->showId, 0); + EXPECT_EQ(pMeta->contLen, 0); + EXPECT_STREQ(pMeta->tableFname, ""); + EXPECT_EQ(pMeta->numOfTags, 0); + EXPECT_EQ(pMeta->precision, 0); + EXPECT_EQ(pMeta->tableType, 0); + EXPECT_EQ(pMeta->numOfColumns, 7); + EXPECT_EQ(pMeta->sversion, 0); + EXPECT_EQ(pMeta->tversion, 0); + EXPECT_EQ(pMeta->tid, 0); + EXPECT_EQ(pMeta->uid, 0); + EXPECT_STREQ(pMeta->sTableName, ""); + EXPECT_EQ(pMeta->suid, 0); + + SSchema* pSchema = NULL; + pSchema = &pMeta->schema[0]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_INT); + EXPECT_EQ(pSchema->bytes, 4); + EXPECT_STREQ(pSchema->name, "connId"); + + pSchema = &pMeta->schema[1]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_BINARY); + EXPECT_EQ(pSchema->bytes, TSDB_USER_LEN + VARSTR_HEADER_SIZE); + EXPECT_STREQ(pSchema->name, "user"); + + pSchema = &pMeta->schema[2]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_BINARY); + EXPECT_EQ(pSchema->bytes, TSDB_USER_LEN + VARSTR_HEADER_SIZE); + EXPECT_STREQ(pSchema->name, "program"); + + pSchema = &pMeta->schema[3]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_INT); + EXPECT_EQ(pSchema->bytes, 4); + EXPECT_STREQ(pSchema->name, "pid"); + + pSchema = &pMeta->schema[4]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_BINARY); + EXPECT_EQ(pSchema->bytes, TSDB_IPv4ADDR_LEN + 6 + VARSTR_HEADER_SIZE); + EXPECT_STREQ(pSchema->name, "ip:port"); + + pSchema = &pMeta->schema[5]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_TIMESTAMP); + EXPECT_EQ(pSchema->bytes, 8); + EXPECT_STREQ(pSchema->name, "login_time"); + + pSchema = &pMeta->schema[6]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_TIMESTAMP); + EXPECT_EQ(pSchema->bytes, 8); + EXPECT_STREQ(pSchema->name, "last_access"); + } + + { + SRetrieveTableMsg* pReq = (SRetrieveTableMsg*)rpcMallocCont(sizeof(SRetrieveTableMsg)); + pReq->showId = htonl(showId); + pReq->free = 0; + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SRetrieveTableMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW_RETRIEVE; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, 0); + + SRetrieveTableRsp* pRsp = (SRetrieveTableRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->numOfRows = htonl(pRsp->numOfRows); + pRsp->offset = htobe64(pRsp->offset); + pRsp->useconds = htobe64(pRsp->useconds); + pRsp->compLen = htonl(pRsp->compLen); + + EXPECT_EQ(pRsp->numOfRows, 1); + EXPECT_EQ(pRsp->offset, 0); + EXPECT_EQ(pRsp->useconds, 0); + EXPECT_EQ(pRsp->completed, 1); + EXPECT_EQ(pRsp->precision, TSDB_TIME_PRECISION_MILLI); + EXPECT_EQ(pRsp->compressed, 0); + EXPECT_EQ(pRsp->reserved, 0); + EXPECT_EQ(pRsp->compLen, 0); + } +} + +TEST_F(DndTestProfile, SHeartBeatMsg_01) { + ASSERT_NE(pClient, nullptr); + + SHeartBeatMsg* pReq = (SHeartBeatMsg*)rpcMallocCont(sizeof(SHeartBeatMsg)); + pReq->connId = htonl(connId); + pReq->pid = htonl(1234); + pReq->numOfQueries = htonl(0); + pReq->numOfStreams = htonl(0); + strcpy(pReq->app, "dndTestProfile"); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SHeartBeatMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_HEARTBEAT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SHeartBeatRsp* pRsp = (SHeartBeatRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->connId = htonl(pRsp->connId); + pRsp->queryId = htonl(pRsp->queryId); + pRsp->streamId = htonl(pRsp->streamId); + pRsp->totalDnodes = htonl(pRsp->totalDnodes); + pRsp->onlineDnodes = htonl(pRsp->onlineDnodes); + pRsp->epSet.port[0] = htons(pRsp->epSet.port[0]); + + EXPECT_EQ(pRsp->connId, connId); + EXPECT_EQ(pRsp->queryId, 0); + EXPECT_EQ(pRsp->streamId, 0); + EXPECT_EQ(pRsp->totalDnodes, 1); + EXPECT_EQ(pRsp->onlineDnodes, 1); + EXPECT_EQ(pRsp->killConnection, 0); + + EXPECT_EQ(pRsp->epSet.inUse, 0); + EXPECT_EQ(pRsp->epSet.numOfEps, 1); + EXPECT_EQ(pRsp->epSet.port[0], 9522); + EXPECT_STREQ(pRsp->epSet.fqdn[0], "localhost"); +} + +TEST_F(DndTestProfile, SKillConnMsg_01) { + ASSERT_NE(pClient, nullptr); + + { + SKillConnMsg* pReq = (SKillConnMsg*)rpcMallocCont(sizeof(SKillConnMsg)); + pReq->connId = htonl(connId); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SKillConnMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_KILL_CONN; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, 0); + } + + { + SHeartBeatMsg* pReq = (SHeartBeatMsg*)rpcMallocCont(sizeof(SHeartBeatMsg)); + pReq->connId = htonl(connId); + pReq->pid = htonl(1234); + pReq->numOfQueries = htonl(0); + pReq->numOfStreams = htonl(0); + strcpy(pReq->app, "dndTestProfile"); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SHeartBeatMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_HEARTBEAT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_INVALID_CONNECTION); + ASSERT_EQ(pMsg->contLen, 0); + } + + { + SConnectMsg* pReq = (SConnectMsg*)rpcMallocCont(sizeof(SConnectMsg)); + pReq->pid = htonl(1234); + strcpy(pReq->app, "dndTestProfile"); + strcpy(pReq->db, ""); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SConnectMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_CONNECT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SConnectRsp* pRsp = (SConnectRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->acctId = htonl(pRsp->acctId); + pRsp->clusterId = htonl(pRsp->clusterId); + pRsp->connId = htonl(pRsp->connId); + pRsp->epSet.port[0] = htons(pRsp->epSet.port[0]); + + EXPECT_EQ(pRsp->acctId, 1); + EXPECT_GT(pRsp->clusterId, 0); + EXPECT_GT(pRsp->connId, connId); + EXPECT_EQ(pRsp->readAuth, 1); + EXPECT_EQ(pRsp->writeAuth, 1); + + EXPECT_EQ(pRsp->epSet.inUse, 0); + EXPECT_EQ(pRsp->epSet.numOfEps, 1); + EXPECT_EQ(pRsp->epSet.port[0], 9522); + EXPECT_STREQ(pRsp->epSet.fqdn[0], "localhost"); + + connId = pRsp->connId; + } +} + +TEST_F(DndTestProfile, SKillConnMsg_02) { + ASSERT_NE(pClient, nullptr); + + SKillConnMsg* pReq = (SKillConnMsg*)rpcMallocCont(sizeof(SKillConnMsg)); + pReq->connId = htonl(2345); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SKillConnMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_KILL_CONN; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_INVALID_CONN_ID); +} + +TEST_F(DndTestProfile, SKillQueryMsg_01) { + ASSERT_NE(pClient, nullptr); + + { + SKillQueryMsg* pReq = (SKillQueryMsg*)rpcMallocCont(sizeof(SKillQueryMsg)); + pReq->connId = htonl(connId); + pReq->queryId = htonl(1234); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SKillQueryMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_KILL_QUERY; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, 0); + ASSERT_EQ(pMsg->contLen, 0); + } + + { + SHeartBeatMsg* pReq = (SHeartBeatMsg*)rpcMallocCont(sizeof(SHeartBeatMsg)); + pReq->connId = htonl(connId); + pReq->pid = htonl(1234); + pReq->numOfQueries = htonl(0); + pReq->numOfStreams = htonl(0); + strcpy(pReq->app, "dndTestProfile"); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SHeartBeatMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_HEARTBEAT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SHeartBeatRsp* pRsp = (SHeartBeatRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->connId = htonl(pRsp->connId); + pRsp->queryId = htonl(pRsp->queryId); + pRsp->streamId = htonl(pRsp->streamId); + pRsp->totalDnodes = htonl(pRsp->totalDnodes); + pRsp->onlineDnodes = htonl(pRsp->onlineDnodes); + pRsp->epSet.port[0] = htons(pRsp->epSet.port[0]); + + EXPECT_EQ(pRsp->connId, connId); + EXPECT_EQ(pRsp->queryId, 1234); + EXPECT_EQ(pRsp->streamId, 0); + EXPECT_EQ(pRsp->totalDnodes, 1); + EXPECT_EQ(pRsp->onlineDnodes, 1); + EXPECT_EQ(pRsp->killConnection, 0); + + EXPECT_EQ(pRsp->epSet.inUse, 0); + EXPECT_EQ(pRsp->epSet.numOfEps, 1); + EXPECT_EQ(pRsp->epSet.port[0], 9522); + EXPECT_STREQ(pRsp->epSet.fqdn[0], "localhost"); + } +} + +TEST_F(DndTestProfile, SKillQueryMsg_02) { + ASSERT_NE(pClient, nullptr); + + SKillQueryMsg* pReq = (SKillQueryMsg*)rpcMallocCont(sizeof(SKillQueryMsg)); + pReq->connId = htonl(2345); + pReq->queryId = htonl(1234); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SKillQueryMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_KILL_QUERY; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_INVALID_CONN_ID); +} + +TEST_F(DndTestProfile, SKillQueryMsg_03) { + ASSERT_NE(pClient, nullptr); + int32_t showId = 0; + + { + SShowMsg* pReq = (SShowMsg*)rpcMallocCont(sizeof(SShowMsg)); + pReq->type = TSDB_MGMT_TABLE_QUERIES; + strcpy(pReq->db, ""); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SShowMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SShowRsp* pRsp = (SShowRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->showId = htonl(pRsp->showId); + STableMetaMsg* pMeta = &pRsp->tableMeta; + pMeta->contLen = htonl(pMeta->contLen); + pMeta->numOfColumns = htons(pMeta->numOfColumns); + pMeta->sversion = htons(pMeta->sversion); + pMeta->tversion = htons(pMeta->tversion); + pMeta->tid = htonl(pMeta->tid); + pMeta->uid = htobe64(pMeta->uid); + pMeta->suid = htobe64(pMeta->suid); + + showId = pRsp->showId; + + EXPECT_NE(pRsp->showId, 0); + EXPECT_EQ(pMeta->contLen, 0); + EXPECT_STREQ(pMeta->tableFname, ""); + EXPECT_EQ(pMeta->numOfTags, 0); + EXPECT_EQ(pMeta->precision, 0); + EXPECT_EQ(pMeta->tableType, 0); + EXPECT_EQ(pMeta->numOfColumns, 14); + EXPECT_EQ(pMeta->sversion, 0); + EXPECT_EQ(pMeta->tversion, 0); + EXPECT_EQ(pMeta->tid, 0); + EXPECT_EQ(pMeta->uid, 0); + EXPECT_STREQ(pMeta->sTableName, ""); + EXPECT_EQ(pMeta->suid, 0); + + SSchema* pSchema = NULL; + pSchema = &pMeta->schema[0]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_INT); + EXPECT_EQ(pSchema->bytes, 4); + EXPECT_STREQ(pSchema->name, "queryId"); + + pSchema = &pMeta->schema[1]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_INT); + EXPECT_EQ(pSchema->bytes, 4); + EXPECT_STREQ(pSchema->name, "connId"); + + pSchema = &pMeta->schema[2]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_BINARY); + EXPECT_EQ(pSchema->bytes, TSDB_USER_LEN + VARSTR_HEADER_SIZE); + EXPECT_STREQ(pSchema->name, "user"); + + pSchema = &pMeta->schema[3]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_BINARY); + EXPECT_EQ(pSchema->bytes, TSDB_IPv4ADDR_LEN + 6 + VARSTR_HEADER_SIZE); + EXPECT_STREQ(pSchema->name, "ip:port"); + } + + { + SRetrieveTableMsg* pReq = (SRetrieveTableMsg*)rpcMallocCont(sizeof(SRetrieveTableMsg)); + pReq->showId = htonl(showId); + pReq->free = 0; + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SRetrieveTableMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW_RETRIEVE; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, 0); + + SRetrieveTableRsp* pRsp = (SRetrieveTableRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->numOfRows = htonl(pRsp->numOfRows); + pRsp->offset = htobe64(pRsp->offset); + pRsp->useconds = htobe64(pRsp->useconds); + pRsp->compLen = htonl(pRsp->compLen); + + EXPECT_EQ(pRsp->numOfRows, 0); + EXPECT_EQ(pRsp->offset, 0); + EXPECT_EQ(pRsp->useconds, 0); + EXPECT_EQ(pRsp->completed, 1); + EXPECT_EQ(pRsp->precision, TSDB_TIME_PRECISION_MILLI); + EXPECT_EQ(pRsp->compressed, 0); + EXPECT_EQ(pRsp->reserved, 0); + EXPECT_EQ(pRsp->compLen, 0); + } +} + +TEST_F(DndTestProfile, SKillStreamMsg_01) { + ASSERT_NE(pClient, nullptr); + + { + SKillStreamMsg* pReq = (SKillStreamMsg*)rpcMallocCont(sizeof(SKillStreamMsg)); + pReq->connId = htonl(connId); + pReq->streamId = htonl(3579); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SKillStreamMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_KILL_STREAM; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, 0); + ASSERT_EQ(pMsg->contLen, 0); + } + + { + SHeartBeatMsg* pReq = (SHeartBeatMsg*)rpcMallocCont(sizeof(SHeartBeatMsg)); + pReq->connId = htonl(connId); + pReq->pid = htonl(1234); + pReq->numOfQueries = htonl(0); + pReq->numOfStreams = htonl(0); + strcpy(pReq->app, "dndTestProfile"); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SHeartBeatMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_HEARTBEAT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SHeartBeatRsp* pRsp = (SHeartBeatRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->connId = htonl(pRsp->connId); + pRsp->queryId = htonl(pRsp->queryId); + pRsp->streamId = htonl(pRsp->streamId); + pRsp->totalDnodes = htonl(pRsp->totalDnodes); + pRsp->onlineDnodes = htonl(pRsp->onlineDnodes); + pRsp->epSet.port[0] = htons(pRsp->epSet.port[0]); + + EXPECT_EQ(pRsp->connId, connId); + EXPECT_EQ(pRsp->queryId, 0); + EXPECT_EQ(pRsp->streamId, 3579); + EXPECT_EQ(pRsp->totalDnodes, 1); + EXPECT_EQ(pRsp->onlineDnodes, 1); + EXPECT_EQ(pRsp->killConnection, 0); + + EXPECT_EQ(pRsp->epSet.inUse, 0); + EXPECT_EQ(pRsp->epSet.numOfEps, 1); + EXPECT_EQ(pRsp->epSet.port[0], 9522); + EXPECT_STREQ(pRsp->epSet.fqdn[0], "localhost"); + } +} + +TEST_F(DndTestProfile, SKillStreamMsg_02) { + ASSERT_NE(pClient, nullptr); + + SKillStreamMsg* pReq = (SKillStreamMsg*)rpcMallocCont(sizeof(SKillStreamMsg)); + pReq->connId = htonl(2345); + pReq->streamId = htonl(1234); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SKillStreamMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_KILL_QUERY; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_INVALID_CONN_ID); +} + +TEST_F(DndTestProfile, SKillStreamMsg_03) { + ASSERT_NE(pClient, nullptr); + int32_t showId = 0; + + { + SShowMsg* pReq = (SShowMsg*)rpcMallocCont(sizeof(SShowMsg)); + pReq->type = TSDB_MGMT_TABLE_STREAMS; + strcpy(pReq->db, ""); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SShowMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SShowRsp* pRsp = (SShowRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->showId = htonl(pRsp->showId); + STableMetaMsg* pMeta = &pRsp->tableMeta; + pMeta->contLen = htonl(pMeta->contLen); + pMeta->numOfColumns = htons(pMeta->numOfColumns); + pMeta->sversion = htons(pMeta->sversion); + pMeta->tversion = htons(pMeta->tversion); + pMeta->tid = htonl(pMeta->tid); + pMeta->uid = htobe64(pMeta->uid); + pMeta->suid = htobe64(pMeta->suid); + + showId = pRsp->showId; + + EXPECT_NE(pRsp->showId, 0); + EXPECT_EQ(pMeta->contLen, 0); + EXPECT_STREQ(pMeta->tableFname, ""); + EXPECT_EQ(pMeta->numOfTags, 0); + EXPECT_EQ(pMeta->precision, 0); + EXPECT_EQ(pMeta->tableType, 0); + EXPECT_EQ(pMeta->numOfColumns, 10); + EXPECT_EQ(pMeta->sversion, 0); + EXPECT_EQ(pMeta->tversion, 0); + EXPECT_EQ(pMeta->tid, 0); + EXPECT_EQ(pMeta->uid, 0); + EXPECT_STREQ(pMeta->sTableName, ""); + EXPECT_EQ(pMeta->suid, 0); + + SSchema* pSchema = NULL; + pSchema = &pMeta->schema[0]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_INT); + EXPECT_EQ(pSchema->bytes, 4); + EXPECT_STREQ(pSchema->name, "streamId"); + + pSchema = &pMeta->schema[1]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_INT); + EXPECT_EQ(pSchema->bytes, 4); + EXPECT_STREQ(pSchema->name, "connId"); + + pSchema = &pMeta->schema[2]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_BINARY); + EXPECT_EQ(pSchema->bytes, TSDB_USER_LEN + VARSTR_HEADER_SIZE); + EXPECT_STREQ(pSchema->name, "user"); + } + + { + SRetrieveTableMsg* pReq = (SRetrieveTableMsg*)rpcMallocCont(sizeof(SRetrieveTableMsg)); + pReq->showId = htonl(showId); + pReq->free = 0; + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SRetrieveTableMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW_RETRIEVE; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, 0); + + SRetrieveTableRsp* pRsp = (SRetrieveTableRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->numOfRows = htonl(pRsp->numOfRows); + pRsp->offset = htobe64(pRsp->offset); + pRsp->useconds = htobe64(pRsp->useconds); + pRsp->compLen = htonl(pRsp->compLen); + + EXPECT_EQ(pRsp->numOfRows, 0); + EXPECT_EQ(pRsp->offset, 0); + EXPECT_EQ(pRsp->useconds, 0); + EXPECT_EQ(pRsp->completed, 1); + EXPECT_EQ(pRsp->precision, TSDB_TIME_PRECISION_MILLI); + EXPECT_EQ(pRsp->compressed, 0); + EXPECT_EQ(pRsp->reserved, 0); + EXPECT_EQ(pRsp->compLen, 0); + } +} diff --git a/source/dnode/mgmt/impl/test/show/CMakeLists.txt b/source/dnode/mgmt/impl/test/show/CMakeLists.txt new file mode 100644 index 0000000000..5f1596ce95 --- /dev/null +++ b/source/dnode/mgmt/impl/test/show/CMakeLists.txt @@ -0,0 +1,29 @@ +add_executable(dndTestShow "") + +target_sources(dndTestShow + PRIVATE + "show.cpp" + "../sut/deploy.cpp" +) + +target_link_libraries( + dndTestShow + PUBLIC dnode + PUBLIC util + PUBLIC os + PUBLIC gtest_main +) + +target_include_directories(dndTestShow + PUBLIC + "${CMAKE_SOURCE_DIR}/include/server/dnode/mgmt" + "${CMAKE_CURRENT_SOURCE_DIR}/../../inc" + "${CMAKE_CURRENT_SOURCE_DIR}/../sut" +) + +enable_testing() + +add_test( + NAME dndTestShow + COMMAND dndTestShow +) diff --git a/source/dnode/mgmt/impl/test/show/show.cpp b/source/dnode/mgmt/impl/test/show/show.cpp new file mode 100644 index 0000000000..e8c8fa261c --- /dev/null +++ b/source/dnode/mgmt/impl/test/show/show.cpp @@ -0,0 +1,238 @@ +/* + * 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 "deploy.h" + +class DndTestShow : public ::testing::Test { + protected: + void SetUp() override {} + void TearDown() override {} + + static void SetUpTestSuite() { + const char* user = "root"; + const char* pass = "taosdata"; + const char* path = "/tmp/dndTestShow"; + const char* fqdn = "localhost"; + uint16_t port = 9523; + + pServer = createServer(path, fqdn, port); + ASSERT(pServer); + pClient = createClient(user, pass, fqdn, port); + } + + static void TearDownTestSuite() { + dropServer(pServer); + dropClient(pClient); + } + + static SServer* pServer; + static SClient* pClient; + static int32_t connId; +}; + +SServer* DndTestShow::pServer; +SClient* DndTestShow::pClient; +int32_t DndTestShow::connId; + +TEST_F(DndTestShow, SShowMsg_01) { + ASSERT_NE(pClient, nullptr); + + SConnectMsg* pReq = (SConnectMsg*)rpcMallocCont(sizeof(SConnectMsg)); + pReq->pid = htonl(1234); + strcpy(pReq->app, "dndTestShow"); + strcpy(pReq->db, ""); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SConnectMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_CONNECT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SConnectRsp* pRsp = (SConnectRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->connId = htonl(pRsp->connId); + + EXPECT_EQ(pRsp->connId, 1); + connId = pRsp->connId; +} + +TEST_F(DndTestShow, SShowMsg_02) { + ASSERT_NE(pClient, nullptr); + + SShowMsg* pReq = (SShowMsg*)rpcMallocCont(sizeof(SShowMsg)); + pReq->type = TSDB_MGMT_TABLE_MAX; + strcpy(pReq->db, ""); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SShowMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_INVALID_MSG_TYPE); +} + +TEST_F(DndTestShow, SShowMsg_03) { + ASSERT_NE(pClient, nullptr); + + SShowMsg* pReq = (SShowMsg*)rpcMallocCont(sizeof(SShowMsg)); + pReq->type = TSDB_MGMT_TABLE_START; + strcpy(pReq->db, ""); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SShowMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_INVALID_MSG_TYPE); +} + +TEST_F(DndTestShow, SShowMsg_04) { + ASSERT_NE(pClient, nullptr); + int32_t showId = 0; + + { + SShowMsg* pReq = (SShowMsg*)rpcMallocCont(sizeof(SShowMsg)); + pReq->type = TSDB_MGMT_TABLE_CONNS; + strcpy(pReq->db, ""); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SShowMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SShowRsp* pRsp = (SShowRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->showId = htonl(pRsp->showId); + STableMetaMsg* pMeta = &pRsp->tableMeta; + pMeta->contLen = htonl(pMeta->contLen); + pMeta->numOfColumns = htons(pMeta->numOfColumns); + pMeta->sversion = htons(pMeta->sversion); + pMeta->tversion = htons(pMeta->tversion); + pMeta->tid = htonl(pMeta->tid); + pMeta->uid = htobe64(pMeta->uid); + pMeta->suid = htobe64(pMeta->suid); + + showId = pRsp->showId; + + EXPECT_NE(pRsp->showId, 0); + EXPECT_EQ(pMeta->contLen, 0); + EXPECT_STREQ(pMeta->tableFname, ""); + EXPECT_EQ(pMeta->numOfTags, 0); + EXPECT_EQ(pMeta->precision, 0); + EXPECT_EQ(pMeta->tableType, 0); + EXPECT_EQ(pMeta->numOfColumns, 7); + EXPECT_EQ(pMeta->sversion, 0); + EXPECT_EQ(pMeta->tversion, 0); + EXPECT_EQ(pMeta->tid, 0); + EXPECT_EQ(pMeta->uid, 0); + EXPECT_STREQ(pMeta->sTableName, ""); + EXPECT_EQ(pMeta->suid, 0); + + SSchema* pSchema = NULL; + pSchema = &pMeta->schema[0]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_INT); + EXPECT_EQ(pSchema->bytes, 4); + EXPECT_STREQ(pSchema->name, "connId"); + + pSchema = &pMeta->schema[1]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_BINARY); + EXPECT_EQ(pSchema->bytes, TSDB_USER_LEN + VARSTR_HEADER_SIZE); + EXPECT_STREQ(pSchema->name, "user"); + + pSchema = &pMeta->schema[2]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_BINARY); + EXPECT_EQ(pSchema->bytes, TSDB_USER_LEN + VARSTR_HEADER_SIZE); + EXPECT_STREQ(pSchema->name, "program"); + + pSchema = &pMeta->schema[3]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_INT); + EXPECT_EQ(pSchema->bytes, 4); + EXPECT_STREQ(pSchema->name, "pid"); + + pSchema = &pMeta->schema[4]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_BINARY); + EXPECT_EQ(pSchema->bytes, TSDB_IPv4ADDR_LEN + 6 + VARSTR_HEADER_SIZE); + EXPECT_STREQ(pSchema->name, "ip:port"); + + pSchema = &pMeta->schema[5]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_TIMESTAMP); + EXPECT_EQ(pSchema->bytes, 8); + EXPECT_STREQ(pSchema->name, "login_time"); + + pSchema = &pMeta->schema[6]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_TIMESTAMP); + EXPECT_EQ(pSchema->bytes, 8); + EXPECT_STREQ(pSchema->name, "last_access"); + } + + { + SRetrieveTableMsg* pReq = (SRetrieveTableMsg*)rpcMallocCont(sizeof(SRetrieveTableMsg)); + pReq->showId = htonl(showId); + pReq->free = 0; + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SRetrieveTableMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW_RETRIEVE; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, 0); + + SRetrieveTableRsp* pRsp = (SRetrieveTableRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->numOfRows = htonl(pRsp->numOfRows); + pRsp->offset = htobe64(pRsp->offset); + pRsp->useconds = htobe64(pRsp->useconds); + pRsp->compLen = htonl(pRsp->compLen); + + EXPECT_EQ(pRsp->numOfRows, 1); + EXPECT_EQ(pRsp->offset, 0); + EXPECT_EQ(pRsp->useconds, 0); + EXPECT_EQ(pRsp->completed, 1); + EXPECT_EQ(pRsp->precision, TSDB_TIME_PRECISION_MILLI); + EXPECT_EQ(pRsp->compressed, 0); + EXPECT_EQ(pRsp->reserved, 0); + EXPECT_EQ(pRsp->compLen, 0); + } +} diff --git a/source/dnode/mgmt/impl/test/sut/deploy.cpp b/source/dnode/mgmt/impl/test/sut/deploy.cpp index 132ce54ec6..ad1667eac5 100644 --- a/source/dnode/mgmt/impl/test/sut/deploy.cpp +++ b/source/dnode/mgmt/impl/test/sut/deploy.cpp @@ -15,8 +15,27 @@ #include "deploy.h" -void initLog(char *path) { +void initLog(const char* path) { + dDebugFlag = 0; + vDebugFlag = 0; mDebugFlag = 207; + cDebugFlag = 0; + jniDebugFlag = 0; + tmrDebugFlag = 0; + sdbDebugFlag = 0; + httpDebugFlag = 0; + mqttDebugFlag = 0; + monDebugFlag = 0; + uDebugFlag = 0; + rpcDebugFlag = 0; + odbcDebugFlag = 0; + qDebugFlag = 0; + wDebugFlag = 0; + sDebugFlag = 0; + tsdbDebugFlag = 0; + cqDebugFlag = 0; + debugFlag = 0; + char temp[PATH_MAX]; snprintf(temp, PATH_MAX, "%s/taosdlog", path); if (taosInitLog(temp, tsNumOfLogLines, 1) != 0) { @@ -32,7 +51,7 @@ void* runServer(void* param) { } } -void initOption(SDnodeOpt* pOption, char *path) { +void initOption(SDnodeOpt* pOption, const char* path, const char* fqdn, uint16_t port) { pOption->sver = 1; pOption->numOfCores = 1; pOption->numOfSupportMnodes = 1; @@ -44,19 +63,20 @@ void initOption(SDnodeOpt* pOption, char *path) { pOption->ratioOfQueryCores = 1; pOption->maxShellConns = 1000; pOption->shellActivityTimer = 30; - pOption->serverPort = 9527; + pOption->serverPort = port; strcpy(pOption->dataDir, path); - strcpy(pOption->localEp, "localhost:9527"); - strcpy(pOption->localFqdn, "localhost"); - strcpy(pOption->firstEp, "localhost:9527"); - - taosRemoveDir(path); - taosMkDir(path); + snprintf(pOption->localEp, TSDB_EP_LEN, "%s:%u", fqdn, port); + snprintf(pOption->localFqdn, TSDB_FQDN_LEN, "%s", fqdn); + snprintf(pOption->firstEp, TSDB_EP_LEN, "%s:%u", fqdn, port); } -SServer* createServer(char *path) { +SServer* createServer(const char* path, const char* fqdn, uint16_t port) { + taosRemoveDir(path); + taosMkDir(path); + initLog(path); + SDnodeOpt option = {0}; - initOption(&option, path); + initOption(&option, path, fqdn, port); SDnode* pDnode = dndInit(&option); ASSERT(pDnode); @@ -80,11 +100,11 @@ void dropServer(SServer* pServer) { void processClientRsp(void* parent, SRpcMsg* pMsg, SEpSet* pEpSet) { SClient* pClient = (SClient*)parent; pClient->pRsp = pMsg; - //taosMsleep(1000000); + // taosMsleep(1000000); tsem_post(&pClient->sem); } -SClient* createClient(char *user, char *pass) { +SClient* createClient(const char* user, const char* pass, const char* fqdn, uint16_t port) { SClient* pClient = (SClient*)calloc(1, sizeof(SClient)); ASSERT(pClient); @@ -93,14 +113,14 @@ SClient* createClient(char *user, char *pass) { SRpcInit rpcInit; memset(&rpcInit, 0, sizeof(rpcInit)); - rpcInit.label = "DND-C"; + rpcInit.label = (char*)"DND-C"; rpcInit.numOfThreads = 1; rpcInit.cfp = processClientRsp; rpcInit.sessions = 1024; rpcInit.connType = TAOS_CONN_CLIENT; rpcInit.idleTime = 30 * 1000; - rpcInit.user = user; - rpcInit.ckey = "key"; + rpcInit.user = (char*)user; + rpcInit.ckey = (char*)"key"; rpcInit.parent = pClient; rpcInit.secret = (char*)secretEncrypt; rpcInit.parent = pClient; @@ -110,6 +130,8 @@ SClient* createClient(char *user, char *pass) { ASSERT(pClient->clientRpc); tsem_init(&pClient->sem, 0, 0); + strcpy(pClient->fqdn, fqdn); + pClient->port = port; return pClient; } @@ -123,8 +145,8 @@ void sendMsg(SClient* pClient, SRpcMsg* pMsg) { SEpSet epSet = {0}; epSet.inUse = 0; epSet.numOfEps = 1; - epSet.port[0] = 9527; - strcpy(epSet.fqdn[0], "localhost"); + epSet.port[0] = pClient->port; + strcpy(epSet.fqdn[0], pClient->fqdn); rpcSendRequest(pClient->clientRpc, &epSet, pMsg, NULL); tsem_wait(&pClient->sem); diff --git a/source/dnode/mgmt/impl/test/sut/deploy.h b/source/dnode/mgmt/impl/test/sut/deploy.h index 6c47b03fe7..93188458ec 100644 --- a/source/dnode/mgmt/impl/test/sut/deploy.h +++ b/source/dnode/mgmt/impl/test/sut/deploy.h @@ -24,6 +24,7 @@ #include "trpc.h" #include "tthread.h" #include "ulog.h" +#include "tdataformat.h" typedef struct { SDnode* pDnode; @@ -31,13 +32,15 @@ typedef struct { } SServer; typedef struct { + char fqdn[TSDB_FQDN_LEN]; + uint16_t port; void* clientRpc; SRpcMsg* pRsp; tsem_t sem; } SClient; -SServer* createServer(char* path); +SServer* createServer(const char* path, const char* fqdn, uint16_t port); void dropServer(SServer* pServer); -SClient* createClient(char *user, char *pass); +SClient* createClient(const char* user, const char* pass, const char* fqdn, uint16_t port); void dropClient(SClient* pClient); void sendMsg(SClient* pClient, SRpcMsg* pMsg); diff --git a/source/dnode/mgmt/impl/test/test01/test01.cpp b/source/dnode/mgmt/impl/test/test01/test01.cpp deleted file mode 100644 index 6c440074dc..0000000000 --- a/source/dnode/mgmt/impl/test/test01/test01.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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 "deploy.h" - -class DndTest01 : public ::testing::Test { - protected: - void SetUp() override { - pServer = createServer("/tmp/dndTest01"); - pClient = createClient("root", "taosdata"); - } - void TearDown() override { - dropServer(pServer); - dropClient(pClient); - } - - SServer* pServer; - SClient* pClient; -}; - -TEST_F(DndTest01, connectMsg) { - SConnectMsg* pReq = (SConnectMsg*)rpcMallocCont(sizeof(SConnectMsg)); - pReq->pid = htonl(1234); - strcpy(pReq->app, "test01"); - strcpy(pReq->db, ""); - - SRpcMsg rpcMsg = {0}; - rpcMsg.pCont = pReq; - rpcMsg.contLen = sizeof(SConnectMsg); - rpcMsg.msgType = TSDB_MSG_TYPE_CONNECT; - - sendMsg(pClient, &rpcMsg); - - SConnectRsp* pRsp = (SConnectRsp*)pClient->pRsp->pCont; - ASSERT_NE(pRsp, nullptr); - pRsp->acctId = htonl(pRsp->acctId); - pRsp->clusterId = htonl(pRsp->clusterId); - pRsp->connId = htonl(pRsp->connId); - pRsp->epSet.port[0] = htons(pRsp->epSet.port[0]); - - EXPECT_EQ(pRsp->acctId, 1); - EXPECT_GT(pRsp->clusterId, 0); - EXPECT_EQ(pRsp->connId, 1); - EXPECT_EQ(pRsp->superAuth, 1); - EXPECT_EQ(pRsp->readAuth, 1); - EXPECT_EQ(pRsp->writeAuth, 1); - - EXPECT_EQ(pRsp->epSet.inUse, 0); - EXPECT_EQ(pRsp->epSet.numOfEps, 1); - EXPECT_EQ(pRsp->epSet.port[0], 9527); - EXPECT_STREQ(pRsp->epSet.fqdn[0], "localhost"); -} - -// TEST_F(DndTest01, heartbeatMsg) { -// SHeartBeatMsg* pReq = (SHeartBeatMsg*)rpcMallocCont(sizeof(SHeartBeatMsg)); -// pReq->connId = htonl(1); -// pReq->pid = htonl(1234); -// pReq->numOfQueries = htonl(0); -// pReq->numOfStreams = htonl(0); -// strcpy(pReq->app, "test01"); - -// SRpcMsg rpcMsg = {0}; -// rpcMsg.pCont = pReq; -// rpcMsg.contLen = sizeof(SHeartBeatMsg); -// rpcMsg.msgType = TSDB_MSG_TYPE_HEARTBEAT; - -// sendMsg(pClient, &rpcMsg); - -// SHeartBeatRsp* pRsp = (SHeartBeatRsp*)pClient->pRsp; -// ASSERT(pRsp); - // pRsp->epSet.port[0] = htonl(pRsp->epSet.port[0]); - -// EXPECT_EQ(htonl(pRsp->connId), 1); -// EXPECT_GT(htonl(pRsp->queryId), 0); -// EXPECT_GT(htonl(pRsp->streamId), 1); -// EXPECT_EQ(htonl(pRsp->totalDnodes), 1); -// EXPECT_EQ(htonl(pRsp->onlineDnodes), 1); -// EXPECT_EQ(pRsp->killConnection, 0); - // EXPECT_EQ(pRsp->epSet.inUse, 0); - // EXPECT_EQ(pRsp->epSet.numOfEps, 1); - // EXPECT_EQ(pRsp->epSet.port[0], 9527); - // EXPECT_STREQ(pRsp->epSet.fqdn[0], "localhost"); -// } diff --git a/source/dnode/mnode/impl/inc/mndCluster.h b/source/dnode/mnode/impl/inc/mndCluster.h index efc1ada67d..0206695b88 100644 --- a/source/dnode/mnode/impl/inc/mndCluster.h +++ b/source/dnode/mnode/impl/inc/mndCluster.h @@ -24,6 +24,7 @@ extern "C" { int32_t mndInitCluster(SMnode *pMnode); void mndCleanupCluster(SMnode *pMnode); +int32_t mndGetClusterName(SMnode *pMnode, char *clusterName, int32_t len); #ifdef __cplusplus } diff --git a/source/dnode/mnode/impl/inc/mndDef.h b/source/dnode/mnode/impl/inc/mndDef.h index aaf86c15b6..9e4f922540 100644 --- a/source/dnode/mnode/impl/inc/mndDef.h +++ b/source/dnode/mnode/impl/inc/mndDef.h @@ -116,7 +116,7 @@ typedef struct STrans { typedef struct SClusterObj { int32_t id; - char uid[TSDB_CLUSTER_ID_LEN]; + char name[TSDB_CLUSTER_ID_LEN]; int64_t createdTime; int64_t updateTime; } SClusterObj; @@ -296,7 +296,6 @@ typedef struct SShowObj { void *pIter; void *pVgIter; SMnode *pMnode; - SShowObj **ppShow; char db[TSDB_FULL_DB_NAME_LEN]; int16_t offset[TSDB_MAX_COLUMNS]; int32_t bytes[TSDB_MAX_COLUMNS]; diff --git a/source/dnode/mnode/impl/inc/mndInt.h b/source/dnode/mnode/impl/inc/mndInt.h index dbca6ad057..8d20356e39 100644 --- a/source/dnode/mnode/impl/inc/mndInt.h +++ b/source/dnode/mnode/impl/inc/mndInt.h @@ -51,6 +51,15 @@ typedef struct { SCacheObj *cache; } SProfileMgmt; +typedef struct { + int8_t enable; + pthread_mutex_t lock; + pthread_cond_t cond; + volatile int32_t exit; + pthread_t thread; + char email[TSDB_FQDN_LEN]; +} STelemMgmt; + typedef struct SMnode { int32_t dnodeId; int32_t clusterId; @@ -59,23 +68,18 @@ typedef struct SMnode { SReplica replicas[TSDB_MAX_REPLICA]; tmr_h timer; char *path; + SMnodeCfg cfg; SSdb *pSdb; SDnode *pDnode; SArray *pSteps; SShowMgmt showMgmt; SProfileMgmt profileMgmt; + STelemMgmt telemMgmt; MndMsgFp msgFp[TSDB_MSG_TYPE_MAX]; SendMsgToDnodeFp sendMsgToDnodeFp; SendMsgToMnodeFp sendMsgToMnodeFp; SendRedirectMsgFp sendRedirectMsgFp; PutMsgToMnodeQFp putMsgToApplyMsgFp; - int32_t sver; - int32_t statusInterval; - int32_t mnodeEqualVnodeNum; - int32_t shellActivityTimer; - char *timezone; - char *locale; - char *charset; } SMnode; void mndSendMsgToDnode(SMnode *pMnode, SEpSet *pEpSet, SRpcMsg *rpcMsg); diff --git a/source/dnode/mnode/impl/src/mndCluster.c b/source/dnode/mnode/impl/src/mndCluster.c index 6013ac0c31..9fa7a06630 100644 --- a/source/dnode/mnode/impl/src/mndCluster.c +++ b/source/dnode/mnode/impl/src/mndCluster.c @@ -15,11 +15,52 @@ #define _DEFAULT_SOURCE #include "mndCluster.h" -#include "mndTrans.h" #include "mndShow.h" +#include "mndTrans.h" #define SDB_CLUSTER_VER 1 +static SSdbRaw *mndClusterActionEncode(SClusterObj *pCluster); +static SSdbRow *mndClusterActionDecode(SSdbRaw *pRaw); +static int32_t mndClusterActionInsert(SSdb *pSdb, SClusterObj *pCluster); +static int32_t mndClusterActionDelete(SSdb *pSdb, SClusterObj *pCluster); +static int32_t mndClusterActionUpdate(SSdb *pSdb, SClusterObj *pSrcCluster, SClusterObj *pDstCluster); +static int32_t mndCreateDefaultCluster(SMnode *pMnode); +static int32_t mndGetClusterMeta(SMnodeMsg *pMsg, SShowObj *pShow, STableMetaMsg *pMeta); +static int32_t mndRetrieveClusters(SMnodeMsg *pMsg, SShowObj *pShow, char *data, int32_t rows); +static void mndCancelGetNextCluster(SMnode *pMnode, void *pIter); + +int32_t mndInitCluster(SMnode *pMnode) { + SSdbTable table = {.sdbType = SDB_CLUSTER, + .keyType = SDB_KEY_INT32, + .deployFp = (SdbDeployFp)mndCreateDefaultCluster, + .encodeFp = (SdbEncodeFp)mndClusterActionEncode, + .decodeFp = (SdbDecodeFp)mndClusterActionDecode, + .insertFp = (SdbInsertFp)mndClusterActionInsert, + .updateFp = (SdbUpdateFp)mndClusterActionUpdate, + .deleteFp = (SdbDeleteFp)mndClusterActionDelete}; + + mndAddShowMetaHandle(pMnode, TSDB_MGMT_TABLE_CLUSTER, mndGetClusterMeta); + mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_CLUSTER, mndRetrieveClusters); + mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_CLUSTER, mndCancelGetNextCluster); + return sdbSetTable(pMnode->pSdb, table); +} + +void mndCleanupCluster(SMnode *pMnode) {} + +int32_t mndGetClusterName(SMnode *pMnode, char *clusterName, int32_t len) { + SSdb *pSdb = pMnode->pSdb; + + SClusterObj *pCluster = sdbAcquire(pSdb, SDB_CLUSTER, &pMnode->clusterId); + if (pCluster = NULL) { + return -1; + } + + tstrncpy(clusterName, pCluster->name, len); + sdbRelease(pSdb, pCluster); + return 0; +} + static SSdbRaw *mndClusterActionEncode(SClusterObj *pCluster) { SSdbRaw *pRaw = sdbAllocRaw(SDB_CLUSTER, SDB_CLUSTER_VER, sizeof(SClusterObj)); if (pRaw == NULL) return NULL; @@ -28,7 +69,7 @@ static SSdbRaw *mndClusterActionEncode(SClusterObj *pCluster) { SDB_SET_INT32(pRaw, dataPos, pCluster->id); SDB_SET_INT64(pRaw, dataPos, pCluster->createdTime) SDB_SET_INT64(pRaw, dataPos, pCluster->updateTime) - SDB_SET_BINARY(pRaw, dataPos, pCluster->uid, TSDB_CLUSTER_ID_LEN) + SDB_SET_BINARY(pRaw, dataPos, pCluster->name, TSDB_CLUSTER_ID_LEN) return pRaw; } @@ -51,7 +92,7 @@ static SSdbRow *mndClusterActionDecode(SSdbRaw *pRaw) { SDB_GET_INT32(pRaw, pRow, dataPos, &pCluster->id) SDB_GET_INT64(pRaw, pRow, dataPos, &pCluster->createdTime) SDB_GET_INT64(pRaw, pRow, dataPos, &pCluster->updateTime) - SDB_GET_BINARY(pRaw, pRow, dataPos, pCluster->uid, TSDB_CLUSTER_ID_LEN) + SDB_GET_BINARY(pRaw, pRow, dataPos, pCluster->name, TSDB_CLUSTER_ID_LEN) return pRow; } @@ -76,14 +117,14 @@ static int32_t mndCreateDefaultCluster(SMnode *pMnode) { clusterObj.createdTime = taosGetTimestampMs(); clusterObj.updateTime = clusterObj.createdTime; - int32_t code = taosGetSystemUid(clusterObj.uid, TSDB_CLUSTER_ID_LEN); + int32_t code = taosGetSystemUid(clusterObj.name, TSDB_CLUSTER_ID_LEN); if (code != 0) { - strcpy(clusterObj.uid, "tdengine2.0"); - mError("failed to get uid from system, set to default val %s", clusterObj.uid); + strcpy(clusterObj.name, "tdengine2.0"); + mError("failed to get name from system, set to default val %s", clusterObj.name); } else { - mDebug("cluster:%d, uid is %s", clusterObj.id, clusterObj.uid); + mDebug("cluster:%d, name is %s", clusterObj.id, clusterObj.name); } - clusterObj.id = MurmurHash3_32(clusterObj.uid, TSDB_CLUSTER_ID_LEN); + clusterObj.id = MurmurHash3_32(clusterObj.name, TSDB_CLUSTER_ID_LEN); clusterObj.id = abs(clusterObj.id); pMnode->clusterId = clusterObj.id; @@ -95,85 +136,79 @@ static int32_t mndCreateDefaultCluster(SMnode *pMnode) { return sdbWrite(pMnode->pSdb, pRaw); } +static int32_t mndGetClusterMeta(SMnodeMsg *pMsg, SShowObj *pShow, STableMetaMsg *pMeta) { + int32_t cols = 0; + SSchema *pSchema = pMeta->schema; -// static int32_t mnodeGetClusterMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pConn) { -// int32_t cols = 0; -// SSchema *pSchema = pMeta->schema; + pShow->bytes[cols] = 4; + pSchema[cols].type = TSDB_DATA_TYPE_INT; + strcpy(pSchema[cols].name, "id"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; -// pShow->bytes[cols] = TSDB_CLUSTER_ID_LEN + VARSTR_HEADER_SIZE; -// pSchema[cols].type = TSDB_DATA_TYPE_BINARY; -// strcpy(pSchema[cols].name, "clusterId"); -// pSchema[cols].bytes = htons(pShow->bytes[cols]); -// cols++; + pShow->bytes[cols] = TSDB_CLUSTER_ID_LEN + VARSTR_HEADER_SIZE; + pSchema[cols].type = TSDB_DATA_TYPE_BINARY; + strcpy(pSchema[cols].name, "name"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; -// pShow->bytes[cols] = 8; -// pSchema[cols].type = TSDB_DATA_TYPE_TIMESTAMP; -// strcpy(pSchema[cols].name, "create_time"); -// pSchema[cols].bytes = htons(pShow->bytes[cols]); -// cols++; + pShow->bytes[cols] = 8; + pSchema[cols].type = TSDB_DATA_TYPE_TIMESTAMP; + strcpy(pSchema[cols].name, "create_time"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; -// pMeta->numOfColumns = htons(cols); -// strcpy(pMeta->tableFname, "show cluster"); -// pShow->numOfColumns = cols; + pMeta->numOfColumns = htons(cols); + strcpy(pMeta->tableFname, "show cluster"); + pShow->numOfColumns = cols; -// pShow->offset[0] = 0; -// for (int32_t i = 1; i < cols; ++i) { -// pShow->offset[i] = pShow->offset[i - 1] + pShow->bytes[i - 1]; -// } + pShow->offset[0] = 0; + for (int32_t i = 1; i < cols; ++i) { + pShow->offset[i] = pShow->offset[i - 1] + pShow->bytes[i - 1]; + } -// pShow->numOfRows = 1; -// pShow->rowSize = pShow->offset[cols - 1] + pShow->bytes[cols - 1]; + pShow->numOfRows = 1; + pShow->rowSize = pShow->offset[cols - 1] + pShow->bytes[cols - 1]; -// return 0; -// } - -// static int32_t mnodeRetrieveClusters(SShowObj *pShow, char *data, int32_t rows, void *pConn) { -// int32_t numOfRows = 0; -// int32_t cols = 0; -// char * pWrite; -// SClusterObj *pCluster = NULL; - -// while (numOfRows < rows) { -// pShow->pIter = mnodeGetNextCluster(pShow->pIter, &pCluster); -// if (pCluster == NULL) break; - -// cols = 0; - -// pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; -// STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pCluster->uid, TSDB_CLUSTER_ID_LEN); -// cols++; - -// pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; -// *(int64_t *) pWrite = pCluster->createdTime; -// cols++; - -// mnodeDecClusterRef(pCluster); -// numOfRows++; -// } - -// mnodeVacuumResult(data, pShow->numOfColumns, numOfRows, rows, pShow); -// pShow->numOfReads += numOfRows; -// return numOfRows; -// } - -// static void mnodeCancelGetNextCluster(void *pIter) { -// sdbFreeIter(tsClusterSdb, pIter); -// } - -int32_t mndInitCluster(SMnode *pMnode) { - SSdbTable table = {.sdbType = SDB_CLUSTER, - .keyType = SDB_KEY_INT32, - .deployFp = (SdbDeployFp)mndCreateDefaultCluster, - .encodeFp = (SdbEncodeFp)mndClusterActionEncode, - .decodeFp = (SdbDecodeFp)mndClusterActionDecode, - .insertFp = (SdbInsertFp)mndClusterActionInsert, - .updateFp = (SdbUpdateFp)mndClusterActionUpdate, - .deleteFp = (SdbDeleteFp)mndClusterActionDelete}; - - // mndAddShowMetaHandle(TSDB_MGMT_TABLE_CLUSTER, mnodeGetClusterMeta); - // mndAddShowRetrieveHandle(TSDB_MGMT_TABLE_CLUSTER, mnodeRetrieveClusters); - // mndAddShowFreeIterHandle(TSDB_MGMT_TABLE_CLUSTER, mnodeCancelGetNextCluster); - return sdbSetTable(pMnode->pSdb, table); + return 0; } -void mndCleanupCluster(SMnode *pMnode) {} +static int32_t mndRetrieveClusters(SMnodeMsg *pMsg, SShowObj *pShow, char *data, int32_t rows) { + SMnode *pMnode = pMsg->pMnode; + SSdb *pSdb = pMnode->pSdb; + int32_t numOfRows = 0; + int32_t cols = 0; + char *pWrite; + SClusterObj *pCluster = NULL; + + while (numOfRows < rows) { + pShow->pIter = sdbFetch(pSdb, SDB_CLUSTER, pShow->pIter, (void **)&pCluster); + if (pShow->pIter == NULL) break; + + cols = 0; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + *(int32_t *)pWrite = pCluster->id; + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pCluster->name, TSDB_CLUSTER_ID_LEN); + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + *(int64_t *)pWrite = pCluster->createdTime; + cols++; + + sdbRelease(pSdb, pCluster); + numOfRows++; + } + + mnodeVacuumResult(data, pShow->numOfColumns, numOfRows, rows, pShow); + pShow->numOfReads += numOfRows; + return numOfRows; +} + +static void mndCancelGetNextCluster(SMnode *pMnode, void *pIter) { + SSdb *pSdb = pMnode->pSdb; + sdbCancelFetch(pSdb, pIter); +} diff --git a/source/dnode/mnode/impl/src/mndDnode.c b/source/dnode/mnode/impl/src/mndDnode.c index 24e6113161..241b006293 100644 --- a/source/dnode/mnode/impl/src/mndDnode.c +++ b/source/dnode/mnode/impl/src/mndDnode.c @@ -179,32 +179,33 @@ static void mndGetDnodeData(SMnode *pMnode, SDnodeEps *pEps, int32_t numOfEps) { } static int32_t mndCheckClusterCfgPara(SMnode *pMnode, const SClusterCfg *pCfg) { - if (pCfg->mnodeEqualVnodeNum != pMnode->mnodeEqualVnodeNum) { - mError("\"mnodeEqualVnodeNum\"[%d - %d] cfg inconsistent", pCfg->mnodeEqualVnodeNum, pMnode->mnodeEqualVnodeNum); + if (pCfg->mnodeEqualVnodeNum != pMnode->cfg.mnodeEqualVnodeNum) { + mError("\"mnodeEqualVnodeNum\"[%d - %d] cfg inconsistent", pCfg->mnodeEqualVnodeNum, + pMnode->cfg.mnodeEqualVnodeNum); return DND_REASON_MN_EQUAL_VN_NOT_MATCH; } - if (pCfg->statusInterval != pMnode->statusInterval) { - mError("\"statusInterval\"[%d - %d] cfg inconsistent", pCfg->statusInterval, pMnode->statusInterval); + if (pCfg->statusInterval != pMnode->cfg.statusInterval) { + mError("\"statusInterval\"[%d - %d] cfg inconsistent", pCfg->statusInterval, pMnode->cfg.statusInterval); return DND_REASON_STATUS_INTERVAL_NOT_MATCH; } int64_t checkTime = 0; char timestr[32] = "1970-01-01 00:00:00.00"; (void)taosParseTime(timestr, &checkTime, (int32_t)strlen(timestr), TSDB_TIME_PRECISION_MILLI, 0); - if ((0 != strcasecmp(pCfg->timezone, pMnode->timezone)) && (checkTime != pCfg->checkTime)) { - mError("\"timezone\"[%s - %s] [%" PRId64 " - %" PRId64 "] cfg inconsistent", pCfg->timezone, tsTimezone, + if ((0 != strcasecmp(pCfg->timezone, pMnode->cfg.timezone)) && (checkTime != pCfg->checkTime)) { + mError("\"timezone\"[%s - %s] [%" PRId64 " - %" PRId64 "] cfg inconsistent", pCfg->timezone, pMnode->cfg.timezone, pCfg->checkTime, checkTime); return DND_REASON_TIME_ZONE_NOT_MATCH; } - if (0 != strcasecmp(pCfg->locale, pMnode->locale)) { - mError("\"locale\"[%s - %s] cfg parameters inconsistent", pCfg->locale, pMnode->locale); + if (0 != strcasecmp(pCfg->locale, pMnode->cfg.locale)) { + mError("\"locale\"[%s - %s] cfg parameters inconsistent", pCfg->locale, pMnode->cfg.locale); return DND_REASON_LOCALE_NOT_MATCH; } - if (0 != strcasecmp(pCfg->charset, pMnode->charset)) { - mError("\"charset\"[%s - %s] cfg parameters inconsistent.", pCfg->charset, pMnode->charset); + if (0 != strcasecmp(pCfg->charset, pMnode->cfg.charset)) { + mError("\"charset\"[%s - %s] cfg parameters inconsistent.", pCfg->charset, pMnode->cfg.charset); return DND_REASON_CHARSET_NOT_MATCH; } @@ -251,12 +252,12 @@ static int32_t mndProcessStatusMsg(SMnodeMsg *pMsg) { } } - if (pStatus->sver != pMnode->sver) { + if (pStatus->sver != pMnode->cfg.sver) { if (pDnode != NULL && pDnode->status != DND_STATUS_READY) { pDnode->offlineReason = DND_REASON_VERSION_NOT_MATCH; } mndReleaseDnode(pMnode, pDnode); - mError("dnode:%d, status msg version:%d not match cluster:%d", pStatus->dnodeId, pStatus->sver, pMnode->sver); + mError("dnode:%d, status msg version:%d not match cluster:%d", pStatus->dnodeId, pStatus->sver, pMnode->cfg.sver); return TSDB_CODE_MND_INVALID_MSG_VERSION; } diff --git a/source/dnode/mnode/impl/src/mndProfile.c b/source/dnode/mnode/impl/src/mndProfile.c index bdd0ab500a..ad7a6322bb 100644 --- a/source/dnode/mnode/impl/src/mndProfile.c +++ b/source/dnode/mnode/impl/src/mndProfile.c @@ -29,7 +29,7 @@ typedef struct { char user[TSDB_USER_LEN]; char app[TSDB_APP_NAME_LEN]; // app name that invokes taosc int32_t pid; // pid of app that invokes taosc - int32_t connId; + int32_t id; int8_t killed; int8_t align; uint16_t port; @@ -46,7 +46,7 @@ typedef struct { static SConnObj *mndCreateConn(SMnode *pMnode, char *user, uint32_t ip, uint16_t port, int32_t pid, const char *app); static void mndFreeConn(SConnObj *pConn); -static SConnObj *mndAcquireConn(SMnode *pMnode, int32_t connId, char *user, uint32_t ip, uint16_t port); +static SConnObj *mndAcquireConn(SMnode *pMnode, int32_t connId); static void mndReleaseConn(SMnode *pMnode, SConnObj *pConn); static void *mndGetNextConn(SMnode *pMnode, void *pIter, SConnObj **pConn); static void mndCancelGetNextConn(SMnode *pMnode, void *pIter); @@ -57,17 +57,17 @@ static int32_t mndProcessKillStreamMsg(SMnodeMsg *pMsg); static int32_t mndProcessKillConnectionMsg(SMnodeMsg *pMsg); static int32_t mndGetConnsMeta(SMnodeMsg *pMsg, SShowObj *pShow, STableMetaMsg *pMeta); static int32_t mndRetrieveConns(SMnodeMsg *pMsg, SShowObj *pShow, char *data, int32_t rows); -static int32_t mndGetQueryMeta(SMnodeMsg *pMsg, STableMetaMsg *pMeta, SShowObj *pShow); +static int32_t mndGetQueryMeta(SMnodeMsg *pMsg, SShowObj *pShow, STableMetaMsg *pMeta); static int32_t mndRetrieveQueries(SMnodeMsg *pMsg, SShowObj *pShow, char *data, int32_t rows); static void mndCancelGetNextQuery(SMnode *pMnode, void *pIter); -static int32_t mndGetStreamMeta(SMnodeMsg *pMsg, STableMetaMsg *pMeta, SShowObj *pShow); -static int32_t mndRetrieveStreams(SShowObj *pShow, char *data, int32_t rows, SMnodeMsg *pMsg); +static int32_t mndGetStreamMeta(SMnodeMsg *pMsg, SShowObj *pShow, STableMetaMsg *pMeta); +static int32_t mndRetrieveStreams(SMnodeMsg *pMsg, SShowObj *pShow, char *data, int32_t rows); static void mndCancelGetNextStream(SMnode *pMnode, void *pIter); int32_t mndInitProfile(SMnode *pMnode) { SProfileMgmt *pMgmt = &pMnode->profileMgmt; - int32_t connCheckTime = pMnode->shellActivityTimer * 2; + int32_t connCheckTime = pMnode->cfg.shellActivityTimer * 2; pMgmt->cache = taosCacheInit(TSDB_DATA_TYPE_INT, connCheckTime, true, (__cache_free_fn_t)mndFreeConn, "conn"); if (pMgmt->cache == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; @@ -84,6 +84,12 @@ int32_t mndInitProfile(SMnode *pMnode) { mndAddShowMetaHandle(pMnode, TSDB_MGMT_TABLE_CONNS, mndGetConnsMeta); mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_CONNS, mndRetrieveConns); mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_CONNS, mndCancelGetNextConn); + mndAddShowMetaHandle(pMnode, TSDB_MGMT_TABLE_QUERIES, mndGetQueryMeta); + mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_QUERIES, mndRetrieveQueries); + mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_QUERIES, mndCancelGetNextQuery); + mndAddShowMetaHandle(pMnode, TSDB_MGMT_TABLE_STREAMS, mndGetStreamMeta); + mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_STREAMS, mndRetrieveStreams); + mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_STREAMS, mndCancelGetNextStream); return 0; } @@ -103,7 +109,7 @@ static SConnObj *mndCreateConn(SMnode *pMnode, char *user, uint32_t ip, uint16_t if (connId == 0) atomic_add_fetch_32(&pMgmt->connId, 1); SConnObj connObj = {.pid = pid, - .connId = connId, + .id = connId, .killed = 0, .port = port, .ip = ip, @@ -120,51 +126,45 @@ static SConnObj *mndCreateConn(SMnode *pMnode, char *user, uint32_t ip, uint16_t tstrncpy(connObj.user, user, TSDB_USER_LEN); tstrncpy(connObj.app, app, TSDB_APP_NAME_LEN); - int32_t keepTime = pMnode->shellActivityTimer * 3; + int32_t keepTime = pMnode->cfg.shellActivityTimer * 3; SConnObj *pConn = taosCachePut(pMgmt->cache, &connId, sizeof(int32_t), &connObj, sizeof(connObj), keepTime * 1000); - - mDebug("conn:%d, is created, user:%s", connId, user); - return pConn; + if (pConn == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + mError("conn:%d, data:%p failed to put into cache since %s, user:%s", connId, pConn, user, terrstr()); + return NULL; + } else { + mTrace("conn:%d, data:%p created, user:%s", pConn->id, pConn, user); + return pConn; + } } static void mndFreeConn(SConnObj *pConn) { tfree(pConn->pQueries); tfree(pConn->pStreams); - tfree(pConn); - mDebug("conn:%d, is destroyed", pConn->connId); + mTrace("conn:%d, data:%p destroyed", pConn->id, pConn); } -static SConnObj *mndAcquireConn(SMnode *pMnode, int32_t connId, char *newUser, uint32_t newIp, uint16_t newPort) { +static SConnObj *mndAcquireConn(SMnode *pMnode, int32_t connId) { SProfileMgmt *pMgmt = &pMnode->profileMgmt; SConnObj *pConn = taosCacheAcquireByKey(pMgmt->cache, &connId, sizeof(int32_t)); if (pConn == NULL) { - mDebug("conn:%d, already destroyed, user:%s", connId, newUser); + mDebug("conn:%d, already destroyed", connId); return NULL; } - if (pConn->ip != newIp || pConn->port != newPort /* || strcmp(pConn->user, newUser) != 0 */) { - char oldIpStr[30]; - char newIpStr[30]; - taosIp2String(pConn->ip, oldIpStr); - taosIp2String(newIp, newIpStr); - mDebug("conn:%d, incoming conn user:%s ip:%s:%u, not match exist user:%s ip:%s:%u", connId, newUser, newIpStr, - newPort, pConn->user, oldIpStr, pConn->port); - - if (pMgmt->connId < connId) pMgmt->connId = connId + 1; - taosCacheRelease(pMgmt->cache, (void **)&pConn, false); - return NULL; - } - - int32_t keepTime = pMnode->shellActivityTimer * 3; + int32_t keepTime = pMnode->cfg.shellActivityTimer * 3; pConn->lastAccess = keepTime * 1000 + (uint64_t)taosGetTimestampMs(); + + mTrace("conn:%d, data:%p acquired from cache", pConn->id, pConn); return pConn; } static void mndReleaseConn(SMnode *pMnode, SConnObj *pConn) { - SProfileMgmt *pMgmt = &pMnode->profileMgmt; - if (pConn == NULL) return; + mTrace("conn:%d, data:%p released from cache", pConn->id, pConn); + + SProfileMgmt *pMgmt = &pMnode->profileMgmt; taosCacheRelease(pMgmt->cache, (void **)&pConn, false); } @@ -224,6 +224,7 @@ static int32_t mndProcessConnectMsg(SMnodeMsg *pMsg) { SConnectRsp *pRsp = rpcMallocCont(sizeof(SConnectRsp)); if (pRsp == NULL) { + mndReleaseConn(pMnode, pConn); terrno = TSDB_CODE_OUT_OF_MEMORY; mError("user:%s, failed to login from %s while create rsp since %s", pMsg->user, ip, terrstr()); return -1; @@ -239,12 +240,13 @@ static int32_t mndProcessConnectMsg(SMnodeMsg *pMsg) { } pRsp->clusterId = htonl(pMnode->clusterId); - pRsp->connId = htonl(pConn->connId); + pRsp->connId = htonl(pConn->id); mndGetMnodeEpSet(pMnode, &pRsp->epSet); + mndReleaseConn(pMnode, pConn); pMsg->contLen = sizeof(SConnectRsp); pMsg->pCont = pRsp; - mDebug("user:%s, login from %s, conn:%d", info.user, ip, pConn->connId); + mDebug("user:%s, login from %s, conn:%d", info.user, ip, pConn->id); return 0; } @@ -284,7 +286,9 @@ static int32_t mnodeSaveQueryStreamList(SConnObj *pConn, SHeartBeatMsg *pMsg) { } static int32_t mndProcessHeartBeatMsg(SMnodeMsg *pMsg) { - SMnode *pMnode = pMsg->pMnode; + SMnode *pMnode = pMsg->pMnode; + SProfileMgmt *pMgmt = &pMnode->profileMgmt; + SHeartBeatMsg *pReq = pMsg->rpcMsg.pCont; pReq->connId = htonl(pReq->connId); pReq->pid = htonl(pReq->pid); @@ -295,14 +299,32 @@ static int32_t mndProcessHeartBeatMsg(SMnodeMsg *pMsg) { return -1; } - SConnObj *pConn = mndAcquireConn(pMnode, pReq->connId, info.user, info.clientIp, info.clientPort); + SConnObj *pConn = mndAcquireConn(pMnode, pReq->connId); if (pConn == NULL) { pConn = mndCreateConn(pMnode, info.user, info.clientIp, info.clientPort, pReq->pid, pReq->app); if (pConn == NULL) { mError("user:%s, conn:%d is freed and failed to create new conn since %s", pMsg->user, pReq->connId, terrstr()); return -1; } else { - mDebug("user:%s, conn:%d is freed and create a new conn:%d", pMsg->user, pReq->connId, pConn->connId); + mDebug("user:%s, conn:%d is freed and create a new conn:%d", pMsg->user, pReq->connId, pConn->id); + } + } else if (pConn->killed) { + mError("user:%s, conn:%d is already killed", pMsg->user, pConn->id); + terrno = TSDB_CODE_MND_INVALID_CONNECTION; + return -1; + } else { + if (pConn->ip != info.clientIp || pConn->port != info.clientPort /* || strcmp(pConn->user, info.user) != 0 */) { + char oldIpStr[40]; + char newIpStr[40]; + taosIpPort2String(pConn->ip, pConn->port, oldIpStr); + taosIpPort2String(info.clientIp, info.clientPort, newIpStr); + mError("conn:%d, incoming conn user:%s ip:%s, not match exist user:%s ip:%s", pConn->id, info.user, newIpStr, + pConn->user, oldIpStr); + + if (pMgmt->connId < pConn->id) pMgmt->connId = pConn->id + 1; + taosCacheRelease(pMgmt->cache, (void **)&pConn, false); + terrno = TSDB_CODE_MND_INVALID_CONNECTION; + return -1; } } @@ -329,7 +351,7 @@ static int32_t mndProcessHeartBeatMsg(SMnodeMsg *pMsg) { pConn->queryId = 0; } - pRsp->connId = htonl(pConn->connId); + pRsp->connId = htonl(pConn->id); pRsp->totalDnodes = htonl(1); pRsp->onlineDnodes = htonl(1); mndGetMnodeEpSet(pMnode, &pRsp->epSet); @@ -354,28 +376,17 @@ static int32_t mndProcessKillQueryMsg(SMnodeMsg *pMsg) { mndReleaseUser(pMnode, pUser); SKillQueryMsg *pKill = pMsg->rpcMsg.pCont; - mInfo("kill query msg is received, queryId:%s", pKill->queryId); + int32_t connId = htonl(pKill->connId); + int32_t queryId = htonl(pKill->queryId); + mInfo("kill query msg is received, queryId:%d", pKill->queryId); - const char delim = ':'; - char *connIdStr = strtok(pKill->queryId, &delim); - char *queryIdStr = strtok(NULL, &delim); - - if (queryIdStr == NULL || connIdStr == NULL) { - mError("failed to kill query, queryId:%s", pKill->queryId); - terrno = TSDB_CODE_MND_INVALID_QUERY_ID; - return -1; - } - - int32_t queryId = (int32_t)strtol(queryIdStr, NULL, 10); - - int32_t connId = atoi(connIdStr); SConnObj *pConn = taosCacheAcquireByKey(pMgmt->cache, &connId, sizeof(int32_t)); if (pConn == NULL) { - mError("connId:%s, failed to kill queryId:%d, conn not exist", connIdStr, queryId); + mError("connId:%d, failed to kill queryId:%d, conn not exist", connId, queryId); terrno = TSDB_CODE_MND_INVALID_CONN_ID; return -1; } else { - mInfo("connId:%s, queryId:%d is killed by user:%s", connIdStr, queryId, pMsg->user); + mInfo("connId:%d, queryId:%d is killed by user:%s", connId, queryId, pMsg->user); pConn->queryId = queryId; taosCacheRelease(pMgmt->cache, (void **)&pConn, false); return 0; @@ -395,29 +406,18 @@ static int32_t mndProcessKillStreamMsg(SMnodeMsg *pMsg) { } mndReleaseUser(pMnode, pUser); - SKillQueryMsg *pKill = pMsg->rpcMsg.pCont; - mInfo("kill stream msg is received, streamId:%s", pKill->queryId); - - const char delim = ':'; - char *connIdStr = strtok(pKill->queryId, &delim); - char *streamIdStr = strtok(NULL, &delim); - - if (streamIdStr == NULL || connIdStr == NULL) { - mError("failed to kill stream, streamId:%s", pKill->queryId); - terrno = TSDB_CODE_MND_INVALID_STREAM_ID; - return -1; - } - - int32_t streamId = (int32_t)strtol(streamIdStr, NULL, 10); - int32_t connId = atoi(connIdStr); + SKillStreamMsg *pKill = pMsg->rpcMsg.pCont; + int32_t connId = htonl(pKill->connId); + int32_t streamId = htonl(pKill->streamId); + mDebug("kill stream msg is received, streamId:%d", streamId); SConnObj *pConn = taosCacheAcquireByKey(pMgmt->cache, &connId, sizeof(int32_t)); if (pConn == NULL) { - mError("connId:%s, failed to kill streamId:%d, conn not exist", connIdStr, streamId); + mError("connId:%d, failed to kill streamId:%d, conn not exist", connId, streamId); terrno = TSDB_CODE_MND_INVALID_CONN_ID; return -1; } else { - mInfo("connId:%s, streamId:%d is killed by user:%s", connIdStr, streamId, pMsg->user); + mInfo("connId:%d, streamId:%d is killed by user:%s", connId, streamId, pMsg->user); pConn->streamId = streamId; taosCacheRelease(pMgmt->cache, (void **)&pConn, false); return TSDB_CODE_SUCCESS; @@ -438,14 +438,15 @@ static int32_t mndProcessKillConnectionMsg(SMnodeMsg *pMsg) { mndReleaseUser(pMnode, pUser); SKillConnMsg *pKill = pMsg->rpcMsg.pCont; - int32_t connId = atoi(pKill->queryId); - SConnObj *pConn = taosCacheAcquireByKey(pMgmt->cache, &connId, sizeof(int32_t)); + int32_t connId = htonl(pKill->connId); + + SConnObj *pConn = taosCacheAcquireByKey(pMgmt->cache, &connId, sizeof(int32_t)); if (pConn == NULL) { - mError("connId:%s, failed to kill, conn not exist", pKill->queryId); + mError("connId:%d, failed to kill connection, conn not exist", connId); terrno = TSDB_CODE_MND_INVALID_CONN_ID; return -1; } else { - mInfo("connId:%s, is killed by user:%s", pKill->queryId, pMsg->user); + mInfo("connId:%d, is killed by user:%s", connId, pMsg->user); pConn->killed = 1; taosCacheRelease(pMgmt->cache, (void **)&pConn, false); return TSDB_CODE_SUCCESS; @@ -529,47 +530,47 @@ static int32_t mndGetConnsMeta(SMnodeMsg *pMsg, SShowObj *pShow, STableMetaMsg * static int32_t mndRetrieveConns(SMnodeMsg *pMsg, SShowObj *pShow, char *data, int32_t rows) { SMnode *pMnode = pMsg->pMnode; int32_t numOfRows = 0; - SConnObj *pConnObj = NULL; + SConnObj *pConn = NULL; int32_t cols = 0; char *pWrite; char ipStr[TSDB_IPv4ADDR_LEN + 6]; while (numOfRows < rows) { - pShow->pIter = mndGetNextConn(pMnode, pShow->pIter, &pConnObj); - if (pConnObj == NULL) break; + pShow->pIter = mndGetNextConn(pMnode, pShow->pIter, &pConn); + if (pConn == NULL) break; cols = 0; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - *(int32_t *)pWrite = pConnObj->connId; + *(int32_t *)pWrite = pConn->id; cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConnObj->user, pShow->bytes[cols]); + STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConn->user, pShow->bytes[cols]); cols++; // app name pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConnObj->app, pShow->bytes[cols]); + STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConn->app, pShow->bytes[cols]); cols++; // app pid pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - *(int32_t *)pWrite = pConnObj->pid; + *(int32_t *)pWrite = pConn->pid; cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - taosIpPort2String(pConnObj->ip, pConnObj->port, ipStr); + taosIpPort2String(pConn->ip, pConn->port, ipStr); STR_WITH_MAXSIZE_TO_VARSTR(pWrite, ipStr, pShow->bytes[cols]); cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - *(int64_t *)pWrite = pConnObj->stime; + *(int64_t *)pWrite = pConn->stime; cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - if (pConnObj->lastAccess < pConnObj->stime) pConnObj->lastAccess = pConnObj->stime; - *(int64_t *)pWrite = pConnObj->lastAccess; + if (pConn->lastAccess < pConn->stime) pConn->lastAccess = pConn->stime; + *(int64_t *)pWrite = pConn->lastAccess; cols++; numOfRows++; @@ -580,7 +581,7 @@ static int32_t mndRetrieveConns(SMnodeMsg *pMsg, SShowObj *pShow, char *data, in return numOfRows; } -static int32_t mndGetQueryMeta(SMnodeMsg *pMsg, STableMetaMsg *pMeta, SShowObj *pShow) { +static int32_t mndGetQueryMeta(SMnodeMsg *pMsg, SShowObj *pShow, STableMetaMsg *pMeta) { SMnode *pMnode = pMsg->pMnode; SProfileMgmt *pMgmt = &pMnode->profileMgmt; @@ -596,9 +597,15 @@ static int32_t mndGetQueryMeta(SMnodeMsg *pMsg, STableMetaMsg *pMeta, SShowObj * int32_t cols = 0; SSchema *pSchema = pMeta->schema; - pShow->bytes[cols] = QUERY_ID_SIZE + VARSTR_HEADER_SIZE; - pSchema[cols].type = TSDB_DATA_TYPE_BINARY; - strcpy(pSchema[cols].name, "query_id"); + pShow->bytes[cols] = 4; + pSchema[cols].type = TSDB_DATA_TYPE_INT; + strcpy(pSchema[cols].name, "queryId"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + + pShow->bytes[cols] = 4; + pSchema[cols].type = TSDB_DATA_TYPE_INT; + strcpy(pSchema[cols].name, "connId"); pSchema[cols].bytes = htons(pShow->bytes[cols]); cols++; @@ -691,40 +698,43 @@ static int32_t mndGetQueryMeta(SMnodeMsg *pMsg, STableMetaMsg *pMeta, SShowObj * static int32_t mndRetrieveQueries(SMnodeMsg *pMsg, SShowObj *pShow, char *data, int32_t rows) { SMnode *pMnode = pMsg->pMnode; int32_t numOfRows = 0; - SConnObj *pConnObj = NULL; + SConnObj *pConn = NULL; int32_t cols = 0; char *pWrite; void *pIter; char str[TSDB_IPv4ADDR_LEN + 6] = {0}; while (numOfRows < rows) { - pIter = mndGetNextConn(pMnode, pShow->pIter, &pConnObj); - if (pConnObj == NULL) { + pIter = mndGetNextConn(pMnode, pShow->pIter, &pConn); + if (pConn == NULL) { pShow->pIter = pIter; break; } - if (numOfRows + pConnObj->numOfQueries >= rows) { + if (numOfRows + pConn->numOfQueries >= rows) { mndCancelGetNextConn(pMnode, pIter); break; } pShow->pIter = pIter; - for (int32_t i = 0; i < pConnObj->numOfQueries; ++i) { - SQueryDesc *pDesc = pConnObj->pQueries + i; + for (int32_t i = 0; i < pConn->numOfQueries; ++i) { + SQueryDesc *pDesc = pConn->pQueries + i; cols = 0; - snprintf(str, QUERY_ID_SIZE + 1, "%u:%u", pConnObj->connId, htonl(pDesc->queryId)); pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - STR_WITH_MAXSIZE_TO_VARSTR(pWrite, str, pShow->bytes[cols]); + *(int64_t *)pWrite = htobe64(pDesc->queryId); cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConnObj->user, pShow->bytes[cols]); + *(int64_t *)pWrite = htobe64(pConn->id); cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - snprintf(str, tListLen(str), "%s:%u", taosIpStr(pConnObj->ip), pConnObj->port); + STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConn->user, pShow->bytes[cols]); + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + snprintf(str, tListLen(str), "%s:%u", taosIpStr(pConn->ip), pConn->port); STR_WITH_MAXSIZE_TO_VARSTR(pWrite, str, pShow->bytes[cols]); cols++; @@ -753,7 +763,7 @@ static int32_t mndRetrieveQueries(SMnodeMsg *pMsg, SShowObj *pShow, char *data, cols++; char epBuf[TSDB_EP_LEN + 1] = {0}; - snprintf(epBuf, tListLen(epBuf), "%s:%u", pDesc->fqdn, pConnObj->port); + snprintf(epBuf, tListLen(epBuf), "%s:%u", pDesc->fqdn, pConn->port); pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; STR_WITH_MAXSIZE_TO_VARSTR(pWrite, epBuf, pShow->bytes[cols]); cols++; @@ -787,7 +797,7 @@ static void mndCancelGetNextQuery(SMnode *pMnode, void *pIter) { taosHashCancelIterate(pMgmt->cache->pHashTable, pIter); } -static int32_t mndGetStreamMeta(SMnodeMsg *pMsg, STableMetaMsg *pMeta, SShowObj *pShow) { +static int32_t mndGetStreamMeta(SMnodeMsg *pMsg, SShowObj *pShow, STableMetaMsg *pMeta) { SMnode *pMnode = pMsg->pMnode; SProfileMgmt *pMgmt = &pMnode->profileMgmt; @@ -803,12 +813,18 @@ static int32_t mndGetStreamMeta(SMnodeMsg *pMsg, STableMetaMsg *pMeta, SShowObj int32_t cols = 0; SSchema *pSchema = pMeta->schema; - pShow->bytes[cols] = QUERY_ID_SIZE + VARSTR_HEADER_SIZE; - pSchema[cols].type = TSDB_DATA_TYPE_BINARY; + pShow->bytes[cols] = 4; + pSchema[cols].type = TSDB_DATA_TYPE_INT; strcpy(pSchema[cols].name, "streamId"); pSchema[cols].bytes = htons(pShow->bytes[cols]); cols++; + pShow->bytes[cols] = 4; + pSchema[cols].type = TSDB_DATA_TYPE_INT; + strcpy(pSchema[cols].name, "connId"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + pShow->bytes[cols] = TSDB_USER_LEN + VARSTR_HEADER_SIZE; pSchema[cols].type = TSDB_DATA_TYPE_BINARY; strcpy(pSchema[cols].name, "user"); @@ -871,39 +887,42 @@ static int32_t mndGetStreamMeta(SMnodeMsg *pMsg, STableMetaMsg *pMeta, SShowObj return 0; } -static int32_t mndRetrieveStreams(SShowObj *pShow, char *data, int32_t rows, SMnodeMsg *pMsg) { +static int32_t mndRetrieveStreams(SMnodeMsg *pMsg, SShowObj *pShow, char *data, int32_t rows) { SMnode *pMnode = pMsg->pMnode; int32_t numOfRows = 0; - SConnObj *pConnObj = NULL; + SConnObj *pConn = NULL; int32_t cols = 0; char *pWrite; void *pIter; char ipStr[TSDB_IPv4ADDR_LEN + 6]; while (numOfRows < rows) { - pIter = mndGetNextConn(pMnode, pShow->pIter, &pConnObj); - if (pConnObj == NULL) { + pIter = mndGetNextConn(pMnode, pShow->pIter, &pConn); + if (pConn == NULL) { pShow->pIter = pIter; break; } - if (numOfRows + pConnObj->numOfStreams >= rows) { + if (numOfRows + pConn->numOfStreams >= rows) { mndCancelGetNextConn(pMnode, pIter); break; } pShow->pIter = pIter; - for (int32_t i = 0; i < pConnObj->numOfStreams; ++i) { - SStreamDesc *pDesc = pConnObj->pStreams + i; + for (int32_t i = 0; i < pConn->numOfStreams; ++i) { + SStreamDesc *pDesc = pConn->pStreams + i; cols = 0; - snprintf(ipStr, QUERY_ID_SIZE + 1, "%u:%u", pConnObj->connId, htonl(pDesc->streamId)); pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - STR_WITH_MAXSIZE_TO_VARSTR(pWrite, ipStr, pShow->bytes[cols]); + *(int64_t *)pWrite = htobe64(pDesc->streamId); cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConnObj->user, pShow->bytes[cols]); + *(int64_t *)pWrite = htobe64(pConn->id); + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConn->user, pShow->bytes[cols]); cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; @@ -911,7 +930,7 @@ static int32_t mndRetrieveStreams(SShowObj *pShow, char *data, int32_t rows, SMn cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - snprintf(ipStr, sizeof(ipStr), "%s:%u", taosIpStr(pConnObj->ip), pConnObj->port); + snprintf(ipStr, sizeof(ipStr), "%s:%u", taosIpStr(pConn->ip), pConn->port); STR_WITH_MAXSIZE_TO_VARSTR(pWrite, ipStr, pShow->bytes[cols]); cols++; diff --git a/source/dnode/mnode/impl/src/mndShow.c b/source/dnode/mnode/impl/src/mndShow.c index e652f94957..747ea39237 100644 --- a/source/dnode/mnode/impl/src/mndShow.c +++ b/source/dnode/mnode/impl/src/mndShow.c @@ -16,19 +16,19 @@ #define _DEFAULT_SOURCE #include "mndShow.h" -static int32_t mndProcessShowMsg(SMnodeMsg *pMnodeMsg); -static int32_t mndProcessRetrieveMsg( SMnodeMsg *pMsg); -static bool mndCheckRetrieveFinished(SShowObj *pShow); -static int32_t mndAcquireShowObj(SMnode *pMnode, SShowObj *pShow); -static void mndReleaseShowObj(SShowObj *pShow, bool forceRemove); -static int32_t mndPutShowObj(SMnode *pMnode, SShowObj *pShow); -static void mndFreeShowObj(void *ppShow); -static char *mndShowStr(int32_t showType); +static SShowObj *mndCreateShowObj(SMnode *pMnode, SShowMsg *pMsg); +static void mndFreeShowObj(SShowObj *pShow); +static SShowObj *mndAcquireShowObj(SMnode *pMnode, int32_t showId); +static void mndReleaseShowObj(SShowObj *pShow, bool forceRemove); +static char *mndShowStr(int32_t showType); +static int32_t mndProcessShowMsg(SMnodeMsg *pMnodeMsg); +static int32_t mndProcessRetrieveMsg(SMnodeMsg *pMsg); +static bool mndCheckRetrieveFinished(SShowObj *pShow); int32_t mndInitShow(SMnode *pMnode) { SShowMgmt *pMgmt = &pMnode->showMgmt; - pMgmt->cache = taosCacheInit(TSDB_CACHE_PTR_KEY, 5, true, mndFreeShowObj, "show"); + pMgmt->cache = taosCacheInit(TSDB_DATA_TYPE_INT, 5, true, (__cache_free_fn_t)mndFreeShowObj, "show"); if (pMgmt->cache == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; mError("failed to alloc show cache since %s", terrstr()); @@ -48,47 +48,41 @@ void mndCleanupShow(SMnode *pMnode) { } } -static int32_t mndAcquireShowObj(SMnode *pMnode, SShowObj *pShow) { - TSDB_CACHE_PTR_TYPE handleVal = (TSDB_CACHE_PTR_TYPE)pShow; - +static SShowObj *mndCreateShowObj(SMnode *pMnode, SShowMsg *pMsg) { SShowMgmt *pMgmt = &pMnode->showMgmt; - SShowObj **ppShow = taosCacheAcquireByKey(pMgmt->cache, &handleVal, sizeof(TSDB_CACHE_PTR_TYPE)); - if (ppShow) { - mTrace("show:%d, data:%p acquired from cache", pShow->id, ppShow); - return 0; - } - return -1; -} + int32_t showId = atomic_add_fetch_32(&pMgmt->showId, 1); + if (showId == 0) atomic_add_fetch_32(&pMgmt->showId, 1); -static void mndReleaseShowObj(SShowObj *pShow, bool forceRemove) { - SMnode *pMnode = pShow->pMnode; - SShowMgmt *pMgmt = &pMnode->showMgmt; - SShowObj **ppShow = (SShowObj **)pShow->ppShow; - taosCacheRelease(pMgmt->cache, (void **)(&ppShow), forceRemove); - mDebug("show:%d, data:%p released from cache, force:%d", pShow->id, ppShow, forceRemove); -} - -static int32_t mndPutShowObj(SMnode *pMnode, SShowObj *pShow) { - SShowMgmt *pMgmt = &pMnode->showMgmt; - int32_t lifeSpan = pMnode->shellActivityTimer * 6 * 1000; - - TSDB_CACHE_PTR_TYPE val = (TSDB_CACHE_PTR_TYPE)pShow; - pShow->id = atomic_add_fetch_32(&pMgmt->showId, 1); - SShowObj **ppShow = - taosCachePut(pMgmt->cache, &val, sizeof(TSDB_CACHE_PTR_TYPE), &pShow, sizeof(TSDB_CACHE_PTR_TYPE), lifeSpan); - if (ppShow == NULL) { + int32_t size = sizeof(SShowObj) + pMsg->payloadLen; + SShowObj *pShow = calloc(1, size); + if (pShow != NULL) { + pShow->id = showId; + pShow->pMnode = pMnode; + pShow->type = pMsg->type; + pShow->payloadLen = pMsg->payloadLen; + memcpy(pShow->db, pMsg->db, TSDB_FULL_DB_NAME_LEN); + memcpy(pShow->payload, pMsg->payload, pMsg->payloadLen); + } else { terrno = TSDB_CODE_OUT_OF_MEMORY; - mError("show:%d, failed to put into cache", pShow->id); - return -1; + mError("failed to process show-meta msg:%s since %s", mndShowStr(pMsg->type), terrstr()); + return NULL; } - mTrace("show:%d, data:%p put into cache", pShow->id, ppShow); - return 0; + int32_t keepTime = pMnode->cfg.shellActivityTimer * 6 * 1000; + SShowObj *pShowRet = taosCachePut(pMgmt->cache, &showId, sizeof(int32_t), pShow, size, keepTime); + free(pShow); + if (pShowRet == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + mError("show:%d, failed to put into cache since %s", showId, terrstr()); + return NULL; + } else { + mTrace("show:%d, data:%p created", showId, pShowRet); + return pShowRet; + } } -static void mndFreeShowObj(void *ppShow) { - SShowObj *pShow = *(SShowObj **)ppShow; +static void mndFreeShowObj(SShowObj *pShow) { SMnode *pMnode = pShow->pMnode; SShowMgmt *pMgmt = &pMnode->showMgmt; @@ -103,8 +97,32 @@ static void mndFreeShowObj(void *ppShow) { } } - mDebug("show:%d, data:%p destroyed", pShow->id, ppShow); - tfree(pShow); + mTrace("show:%d, data:%p destroyed", pShow->id, pShow); +} + +static SShowObj *mndAcquireShowObj(SMnode *pMnode, int32_t showId) { + SShowMgmt *pMgmt = &pMnode->showMgmt; + + SShowObj *pShow = taosCacheAcquireByKey(pMgmt->cache, &showId, sizeof(int32_t)); + if (pShow == NULL) { + mError("show:%d, already destroyed", showId); + return NULL; + } + + mTrace("show:%d, data:%p acquired from cache", pShow->id, pShow); + return pShow; +} + +static void mndReleaseShowObj(SShowObj *pShow, bool forceRemove) { + if (pShow == NULL) return; + mTrace("show:%d, data:%p released from cache, force:%d", pShow->id, pShow, forceRemove); + + // A bug in tcache.c + forceRemove = 0; + + SMnode *pMnode = pShow->pMnode; + SShowMgmt *pMgmt = &pMnode->showMgmt; + taosCacheRelease(pMgmt->cache, (void **)(&pShow), forceRemove); } static int32_t mndProcessShowMsg(SMnodeMsg *pMnodeMsg) { @@ -112,7 +130,7 @@ static int32_t mndProcessShowMsg(SMnodeMsg *pMnodeMsg) { SShowMgmt *pMgmt = &pMnode->showMgmt; SShowMsg *pMsg = pMnodeMsg->rpcMsg.pCont; int8_t type = pMsg->type; - uint16_t payloadLen = htonl(pMsg->payloadLen); + int16_t payloadLen = htonl(pMsg->payloadLen); if (type <= TSDB_MGMT_TABLE_START || type >= TSDB_MGMT_TABLE_MAX) { terrno = TSDB_CODE_MND_INVALID_MSG_TYPE; @@ -127,27 +145,13 @@ static int32_t mndProcessShowMsg(SMnodeMsg *pMnodeMsg) { return -1; } - int32_t size = sizeof(SShowObj) + payloadLen; - SShowObj *pShow = calloc(1, size); - if (pShow != NULL) { - pShow->pMnode = pMnode; - pShow->type = type; - pShow->payloadLen = payloadLen; - memcpy(pShow->db, pMsg->db, TSDB_FULL_DB_NAME_LEN); - memcpy(pShow->payload, pMsg->payload, payloadLen); - } else { - terrno = TSDB_CODE_OUT_OF_MEMORY; + SShowObj *pShow = mndCreateShowObj(pMnode, pMsg); + if (pShow == NULL) { mError("failed to process show-meta msg:%s since %s", mndShowStr(type), terrstr()); return -1; } - if (mndPutShowObj(pMnode, pShow) == 0) { - mError("failed to process show-meta msg:%s since %s", mndShowStr(type), terrstr()); - free(pShow); - return -1; - } - - size = sizeof(SShowRsp) + sizeof(SSchema) * TSDB_MAX_COLUMNS + TSDB_EXTRA_PAYLOAD_SIZE; + int32_t size = sizeof(SShowRsp) + sizeof(SSchema) * TSDB_MAX_COLUMNS + TSDB_EXTRA_PAYLOAD_SIZE; SShowRsp *pRsp = rpcMallocCont(size); if (pRsp == NULL) { mndReleaseShowObj(pShow, true); @@ -156,15 +160,14 @@ static int32_t mndProcessShowMsg(SMnodeMsg *pMnodeMsg) { return -1; } - pRsp->qhandle = htobe64((uint64_t)pShow); - - int32_t code = (*metaFp)(pMnodeMsg,pShow, &pRsp->tableMeta); - mDebug("show:%d, type:%s, get meta finished, numOfRows:%d cols:%d result:%s", pShow->id, mndShowStr(type), - pShow->numOfRows, pShow->numOfColumns, tstrerror(code)); + int32_t code = (*metaFp)(pMnodeMsg, pShow, &pRsp->tableMeta); + mDebug("show:%d, data:%p get meta finished, numOfRows:%d cols:%d type:%s result:%s", pShow->id, pShow, + pShow->numOfRows, pShow->numOfColumns, mndShowStr(type), tstrerror(code)); if (code == TSDB_CODE_SUCCESS) { pMnodeMsg->contLen = sizeof(SShowRsp) + sizeof(SSchema) * pShow->numOfColumns; pMnodeMsg->pCont = pRsp; + pRsp->showId = htonl(pShow->id); mndReleaseShowObj(pShow, false); return TSDB_CODE_SUCCESS; } else { @@ -182,14 +185,10 @@ static int32_t mndProcessRetrieveMsg(SMnodeMsg *pMnodeMsg) { int32_t rowsRead = 0; SRetrieveTableMsg *pRetrieve = pMnodeMsg->rpcMsg.pCont; - pRetrieve->qhandle = htobe64(pRetrieve->qhandle); - SShowObj *pShow = (SShowObj *)pRetrieve->qhandle; + int32_t showId = htonl(pRetrieve->showId); - /* - * in case of server restart, apps may hold qhandle created by server before - * restart, which is actually invalid, therefore, signature check is required. - */ - if (mndAcquireShowObj(pMnode, pShow) != 0) { + SShowObj *pShow = mndAcquireShowObj(pMnode, showId); + if (pShow == NULL) { terrno = TSDB_CODE_MND_INVALID_SHOWOBJ; mError("failed to process show-retrieve msg:%p since %s", pShow, terrstr()); return -1; @@ -199,15 +198,16 @@ static int32_t mndProcessRetrieveMsg(SMnodeMsg *pMnodeMsg) { if (retrieveFp == NULL) { mndReleaseShowObj(pShow, false); terrno = TSDB_CODE_MSG_NOT_PROCESSED; - mError("show:%d, failed to retrieve data since %s", pShow->id, terrstr()); + mError("show:%d, data:%p failed to retrieve data since %s", pShow->id, pShow, terrstr()); return -1; } - mDebug("show:%d, type:%s, start retrieve data, numOfReads:%d numOfRows:%d", pShow->id, mndShowStr(pShow->type), - pShow->numOfReads, pShow->numOfRows); + mDebug("show:%d, data:%p start retrieve data, numOfReads:%d numOfRows:%d type:%s", pShow->id, pShow, + pShow->numOfReads, pShow->numOfRows, mndShowStr(pShow->type)); if (mndCheckRetrieveFinished(pShow)) { - mDebug("show:%d, read finished, numOfReads:%d numOfRows:%d", pShow->id, pShow->numOfReads, pShow->numOfRows); + mDebug("show:%d, data:%p read finished, numOfReads:%d numOfRows:%d", pShow->id, pShow, pShow->numOfReads, + pShow->numOfRows); pShow->numOfReads = pShow->numOfRows; } @@ -230,7 +230,7 @@ static int32_t mndProcessRetrieveMsg(SMnodeMsg *pMnodeMsg) { if (pRsp == NULL) { mndReleaseShowObj(pShow, false); terrno = TSDB_CODE_OUT_OF_MEMORY; - mError("show:%d, failed to retrieve data since %s", pShow->id, terrstr()); + mError("show:%d, data:%p failed to retrieve data since %s", pShow->id, pShow, terrstr()); return -1; } @@ -239,20 +239,20 @@ static int32_t mndProcessRetrieveMsg(SMnodeMsg *pMnodeMsg) { rowsRead = (*retrieveFp)(pMnodeMsg, pShow, pRsp->data, rowsToRead); } - mDebug("show:%d, stop retrieve data, rowsRead:%d rowsToRead:%d", pShow->id, rowsRead, rowsToRead); + mDebug("show:%d, data:%p stop retrieve data, rowsRead:%d rowsToRead:%d", pShow->id, pShow, rowsRead, rowsToRead); pRsp->numOfRows = htonl(rowsRead); - pRsp->precision = (int16_t)htonl(TSDB_TIME_PRECISION_MILLI); // millisecond time precision + pRsp->precision = TSDB_TIME_PRECISION_MILLI; // millisecond time precision pMnodeMsg->pCont = pRsp; pMnodeMsg->contLen = size; - if (rowsToRead == 0 || (rowsRead == rowsToRead && pShow->numOfRows == pShow->numOfReads)) { + if (rowsRead == 0 || rowsToRead == 0 || (rowsRead == rowsToRead && pShow->numOfRows == pShow->numOfReads)) { pRsp->completed = 1; - mDebug("%p, retrieve completed", pShow); + mDebug("show:%d, data:%p retrieve completed", pShow->id, pShow); mndReleaseShowObj(pShow, true); } else { - mDebug("%p, retrieve not completed yet", pShow); + mDebug("show:%d, data:%p retrieve not completed yet", pShow->id, pShow); mndReleaseShowObj(pShow, false); } @@ -307,7 +307,7 @@ static char *mndShowStr(int32_t showType) { static bool mndCheckRetrieveFinished(SShowObj *pShow) { if (pShow->pIter == NULL && pShow->numOfReads != 0) { return true; - } + } return false; } diff --git a/source/dnode/mnode/impl/src/mndTelem.c b/source/dnode/mnode/impl/src/mndTelem.c index f9f349aad8..663ae76506 100644 --- a/source/dnode/mnode/impl/src/mndTelem.c +++ b/source/dnode/mnode/impl/src/mndTelem.c @@ -15,27 +15,15 @@ #define _DEFAULT_SOURCE #include "mndTelem.h" -#include "tbuffer.h" -#include "tglobal.h" +#include "mndCluster.h" #include "mndSync.h" +#include "tbuffer.h" +#include "tversion.h" #define TELEMETRY_SERVER "telemetry.taosdata.com" #define TELEMETRY_PORT 80 #define REPORT_INTERVAL 86400 -/* - * sem_timedwait is NOT implemented on MacOSX - * thus we use pthread_mutex_t/pthread_cond_t to simulate - */ -static struct { - bool enable; - pthread_mutex_t lock; - pthread_cond_t cond; - volatile int32_t exit; - pthread_t thread; - char email[TSDB_FQDN_LEN]; -} tsTelem; - static void mndBeginObject(SBufferWriter* bw) { tbufWriteChar(bw, '{'); } static void mndCloseObject(SBufferWriter* bw) { @@ -86,7 +74,7 @@ static void mndAddStringField(SBufferWriter* bw, const char* k, const char* v) { tbufWriteChar(bw, ','); } -static void mndAddCpuInfo(SBufferWriter* bw) { +static void mndAddCpuInfo(SMnode* pMnode, SBufferWriter* bw) { char* line = NULL; size_t size = 0; int32_t done = 0; @@ -116,7 +104,7 @@ static void mndAddCpuInfo(SBufferWriter* bw) { fclose(fp); } -static void mndAddOsInfo(SBufferWriter* bw) { +static void mndAddOsInfo(SMnode* pMnode, SBufferWriter* bw) { char* line = NULL; size_t size = 0; @@ -142,7 +130,7 @@ static void mndAddOsInfo(SBufferWriter* bw) { fclose(fp); } -static void mndAddMemoryInfo(SBufferWriter* bw) { +static void mndAddMemoryInfo(SMnode* pMnode, SBufferWriter* bw) { char* line = NULL; size_t size = 0; @@ -165,16 +153,21 @@ static void mndAddMemoryInfo(SBufferWriter* bw) { fclose(fp); } -static void mndAddVersionInfo(SBufferWriter* bw) { - mndAddStringField(bw, "version", version); - mndAddStringField(bw, "buildInfo", buildinfo); - mndAddStringField(bw, "gitInfo", gitinfo); - mndAddStringField(bw, "email", tsTelem.email); +static void mndAddVersionInfo(SMnode* pMnode, SBufferWriter* bw) { + STelemMgmt* pMgmt = &pMnode->telemMgmt; + + char vstr[32] = {0}; + taosVersionIntToStr(pMnode->cfg.sver, vstr, 32); + + mndAddStringField(bw, "version", vstr); + mndAddStringField(bw, "buildInfo", pMnode->cfg.buildinfo); + mndAddStringField(bw, "gitInfo", pMnode->cfg.gitinfo); + mndAddStringField(bw, "email", pMgmt->email); } -static void mndAddRuntimeInfo(SBufferWriter* bw) { +static void mndAddRuntimeInfo(SMnode* pMnode, SBufferWriter* bw) { SMnodeLoad load = {0}; - if (mndGetLoad(NULL, &load) != 0) { + if (mndGetLoad(pMnode, &load) != 0) { return; } @@ -190,11 +183,13 @@ static void mndAddRuntimeInfo(SBufferWriter* bw) { mndAddIntField(bw, "compStorage", load.compStorage); } -static void mndSendTelemetryReport() { +static void mndSendTelemetryReport(SMnode* pMnode) { + STelemMgmt* pMgmt = &pMnode->telemMgmt; + char buf[128] = {0}; uint32_t ip = taosGetIpv4FromFqdn(TELEMETRY_SERVER); if (ip == 0xffffffff) { - mTrace("failed to get IP address of " TELEMETRY_SERVER ", reason:%s", strerror(errno)); + mTrace("failed to get IP address of " TELEMETRY_SERVER " since :%s", strerror(errno)); return; } SOCKET fd = taosOpenTcpClientSocket(ip, TELEMETRY_PORT, 0); @@ -203,19 +198,18 @@ static void mndSendTelemetryReport() { return; } - int32_t clusterId = 0; - char clusterIdStr[20] = {0}; - snprintf(clusterIdStr, sizeof(clusterIdStr), "%d", clusterId); + char clusterName[64] = {0}; + mndGetClusterName(pMnode, clusterName, sizeof(clusterName)); SBufferWriter bw = tbufInitWriter(NULL, false); mndBeginObject(&bw); - mndAddStringField(&bw, "instanceId", clusterIdStr); + mndAddStringField(&bw, "instanceId", clusterName); mndAddIntField(&bw, "reportVersion", 1); - mndAddOsInfo(&bw); - mndAddCpuInfo(&bw); - mndAddMemoryInfo(&bw); - mndAddVersionInfo(&bw); - mndAddRuntimeInfo(&bw); + mndAddOsInfo(pMnode, &bw); + mndAddCpuInfo(pMnode, &bw); + mndAddMemoryInfo(pMnode, &bw); + mndAddVersionInfo(pMnode, &bw); + mndAddRuntimeInfo(pMnode, &bw); mndCloseObject(&bw); const char* header = @@ -241,23 +235,26 @@ static void mndSendTelemetryReport() { } static void* mndTelemThreadFp(void* param) { + SMnode* pMnode = param; + STelemMgmt* pMgmt = &pMnode->telemMgmt; + struct timespec end = {0}; clock_gettime(CLOCK_REALTIME, &end); end.tv_sec += 300; // wait 5 minutes before send first report setThreadName("mnd-telem"); - while (!tsTelem.exit) { + while (!pMgmt->exit) { int32_t r = 0; struct timespec ts = end; - pthread_mutex_lock(&tsTelem.lock); - r = pthread_cond_timedwait(&tsTelem.cond, &tsTelem.lock, &ts); - pthread_mutex_unlock(&tsTelem.lock); + pthread_mutex_lock(&pMgmt->lock); + r = pthread_cond_timedwait(&pMgmt->cond, &pMgmt->lock, &ts); + pthread_mutex_unlock(&pMgmt->lock); if (r == 0) break; if (r != ETIMEDOUT) continue; - if (mndIsMaster(NULL)) { - mndSendTelemetryReport(); + if (mndIsMaster(pMnode)) { + mndSendTelemetryReport(pMnode); } end.tv_sec += REPORT_INTERVAL; } @@ -265,35 +262,39 @@ static void* mndTelemThreadFp(void* param) { return NULL; } -static void mndGetEmail(char* filepath) { +static void mndGetEmail(SMnode* pMnode, char* filepath) { + STelemMgmt* pMgmt = &pMnode->telemMgmt; + int32_t fd = taosOpenFileRead(filepath); if (fd < 0) { return; } - if (taosReadFile(fd, (void*)tsTelem.email, TSDB_FQDN_LEN) < 0) { + if (taosReadFile(fd, (void*)pMgmt->email, TSDB_FQDN_LEN) < 0) { mError("failed to read %d bytes from file %s since %s", TSDB_FQDN_LEN, filepath, strerror(errno)); } taosCloseFile(fd); } -int32_t mndInitTelem(SMnode *pMnode) { - tsTelem.enable = tsEnableTelemetryReporting; - if (!tsTelem.enable) return 0; +int32_t mndInitTelem(SMnode* pMnode) { + STelemMgmt* pMgmt = &pMnode->telemMgmt; + pMgmt->enable = pMnode->cfg.enableTelem; - tsTelem.exit = 0; - pthread_mutex_init(&tsTelem.lock, NULL); - pthread_cond_init(&tsTelem.cond, NULL); - tsTelem.email[0] = 0; + if (!pMgmt->enable) return 0; - mndGetEmail("/usr/local/taos/email"); + pMgmt->exit = 0; + pthread_mutex_init(&pMgmt->lock, NULL); + pthread_cond_init(&pMgmt->cond, NULL); + pMgmt->email[0] = 0; + + mndGetEmail(pMnode, "/usr/local/taos/email"); pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - int32_t code = pthread_create(&tsTelem.thread, &attr, mndTelemThreadFp, NULL); + int32_t code = pthread_create(&pMgmt->thread, &attr, mndTelemThreadFp, pMnode); pthread_attr_destroy(&attr); if (code != 0) { mTrace("failed to create telemetry thread since :%s", strerror(code)); @@ -303,18 +304,19 @@ int32_t mndInitTelem(SMnode *pMnode) { return 0; } -void mndCleanupTelem(SMnode *pMnode) { - if (!tsTelem.enable) return; +void mndCleanupTelem(SMnode* pMnode) { + STelemMgmt* pMgmt = &pMnode->telemMgmt; + if (!pMgmt->enable) return; - if (taosCheckPthreadValid(tsTelem.thread)) { - pthread_mutex_lock(&tsTelem.lock); - tsTelem.exit = 1; - pthread_cond_signal(&tsTelem.cond); - pthread_mutex_unlock(&tsTelem.lock); + if (taosCheckPthreadValid(pMgmt->thread)) { + pthread_mutex_lock(&pMgmt->lock); + pMgmt->exit = 1; + pthread_cond_signal(&pMgmt->cond); + pthread_mutex_unlock(&pMgmt->lock); - pthread_join(tsTelem.thread, NULL); + pthread_join(pMgmt->thread, NULL); } - pthread_mutex_destroy(&tsTelem.lock); - pthread_cond_destroy(&tsTelem.cond); + pthread_mutex_destroy(&pMgmt->lock); + pthread_cond_destroy(&pMgmt->cond); } diff --git a/source/dnode/mnode/impl/src/mnode.c b/source/dnode/mnode/impl/src/mnode.c index b99de4a019..2fa0838ee8 100644 --- a/source/dnode/mnode/impl/src/mnode.c +++ b/source/dnode/mnode/impl/src/mnode.c @@ -203,22 +203,25 @@ static int32_t mndSetOptions(SMnode *pMnode, const SMnodeOpt *pOption) { pMnode->sendMsgToDnodeFp = pOption->sendMsgToDnodeFp; pMnode->sendMsgToMnodeFp = pOption->sendMsgToMnodeFp; pMnode->sendRedirectMsgFp = pOption->sendRedirectMsgFp; - pMnode->sver = pOption->sver; - pMnode->statusInterval = pOption->statusInterval; - pMnode->mnodeEqualVnodeNum = pOption->mnodeEqualVnodeNum; - pMnode->shellActivityTimer = pOption->shellActivityTimer; - pMnode->timezone = strdup(pOption->timezone); - pMnode->locale = strdup(pOption->locale); - pMnode->charset = strdup(pOption->charset); + pMnode->cfg.sver = pOption->cfg.sver; + pMnode->cfg.enableTelem = pOption->cfg.enableTelem; + pMnode->cfg.statusInterval = pOption->cfg.statusInterval; + pMnode->cfg.mnodeEqualVnodeNum = pOption->cfg.mnodeEqualVnodeNum; + pMnode->cfg.shellActivityTimer = pOption->cfg.shellActivityTimer; + pMnode->cfg.timezone = strdup(pOption->cfg.timezone); + pMnode->cfg.locale = strdup(pOption->cfg.locale); + pMnode->cfg.charset = strdup(pOption->cfg.charset); + pMnode->cfg.gitinfo = strdup(pOption->cfg.gitinfo); + pMnode->cfg.buildinfo = strdup(pOption->cfg.buildinfo); if (pMnode->sendMsgToDnodeFp == NULL || pMnode->sendMsgToMnodeFp == NULL || pMnode->sendRedirectMsgFp == NULL || pMnode->putMsgToApplyMsgFp == NULL || pMnode->dnodeId < 0 || pMnode->clusterId < 0 || - pMnode->statusInterval < 1 || pOption->mnodeEqualVnodeNum < 0) { + pMnode->cfg.statusInterval < 1 || pOption->cfg.mnodeEqualVnodeNum < 0) { terrno = TSDB_CODE_MND_INVALID_OPTIONS; return -1; } - if (pMnode->timezone == NULL || pMnode->locale == NULL || pMnode->charset == NULL) { + if (pMnode->cfg.timezone == NULL || pMnode->cfg.locale == NULL || pMnode->cfg.charset == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; } @@ -289,9 +292,11 @@ void mndClose(SMnode *pMnode) { mDebug("start to close mnode"); mndCleanupSteps(pMnode, -1); tfree(pMnode->path); - tfree(pMnode->charset); - tfree(pMnode->locale); - tfree(pMnode->timezone); + tfree(pMnode->cfg.charset); + tfree(pMnode->cfg.locale); + tfree(pMnode->cfg.timezone); + tfree(pMnode->cfg.gitinfo); + tfree(pMnode->cfg.buildinfo); tfree(pMnode); mDebug("mnode is closed"); } diff --git a/source/util/src/terror.c b/source/util/src/terror.c index 11b40f61f6..3a36ad9b42 100644 --- a/source/util/src/terror.c +++ b/source/util/src/terror.c @@ -86,6 +86,9 @@ TAOS_DEFINE_ERROR(TSDB_CODE_REF_INVALID_ID, "Invalid Ref ID") TAOS_DEFINE_ERROR(TSDB_CODE_REF_ALREADY_EXIST, "Ref is already there") TAOS_DEFINE_ERROR(TSDB_CODE_REF_NOT_EXIST, "Ref is not there") +TAOS_DEFINE_ERROR(TSDB_CODE_INVALID_VERSION_NUMBER, "Invalid version number") +TAOS_DEFINE_ERROR(TSDB_CODE_INVALID_VERSION_STRING, "Invalid version string") +TAOS_DEFINE_ERROR(TSDB_CODE_VERSION_NOT_COMPATIBLE, "Version not compatible") //client TAOS_DEFINE_ERROR(TSDB_CODE_TSC_INVALID_OPERATION, "Invalid operation") diff --git a/source/util/src/tversion.c b/source/util/src/tversion.c new file mode 100644 index 0000000000..3944bd5132 --- /dev/null +++ b/source/util/src/tversion.c @@ -0,0 +1,93 @@ +/* + * 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 . + */ + +#define _DEFAULT_SOURCE +#include "os.h" +#include "taoserror.h" +#include "tdef.h" +#include "ulog.h" + +int32_t taosVersionStrToInt(const char *vstr, int32_t *vint) { + if (vstr == NULL) { + terrno = TSDB_CODE_INVALID_VERSION_STRING; + return -1; + } + + int32_t vnum[4] = {0}; + int32_t len = strlen(vstr); + char tmp[16] = {0}; + + for (int32_t spos = 0, tpos = 0, vpos = 0; spos < len && vpos < 4; ++spos) { + if (vstr[spos] != '.') { + tmp[spos - tpos] = vstr[spos]; + } else { + vnum[vpos] = atoi(tmp); + memset(tmp, 0, sizeof(tmp)); + vpos++; + tpos = spos + 1; + } + } + + if (vnum[0] <= 0) { + terrno = TSDB_CODE_INVALID_VERSION_STRING; + return -1; + } + + *vint = vnum[0] * 1000000 + vnum[1] * 10000 + vnum[2] * 100 + vnum[3]; + return 0; +} + +int32_t taosVersionIntToStr(int32_t vint, char *vstr, int32_t len) { + int32_t s1 = (vint % 100000000) / 1000000; + int32_t s2 = (vint % 1000000) / 10000; + int32_t s3 = (vint % 10000) / 100; + int32_t s4 = vint % 100; + if (s1 <= 0) { + terrno = TSDB_CODE_INVALID_VERSION_NUMBER; + return -1; + } + + snprintf(vstr, len, "%02d.%02d.%02d.%02d", s1, s2, s3, s4); + return 0; +} + +int32_t taosCheckVersionCompatible(int32_t clientVer, int32_t serverVer, int32_t comparedSegments) { + switch (comparedSegments) { + case 4: + break; + case 3: + clientVer %= 100; + serverVer %= 100; + break; + case 2: + clientVer %= 10000; + serverVer %= 10000; + break; + case 1: + clientVer %= 1000000; + serverVer %= 1000000; + break; + default: + terrno = TSDB_CODE_INVALID_VERSION_NUMBER; + return -1; + } + + if (clientVer == serverVer) { + return 0; + } else { + terrno = TSDB_CODE_VERSION_NOT_COMPATIBLE; + return -1; + } +}