Merge branch 'rpc' into 3.0
This commit is contained in:
commit
84eeb2ab70
|
@ -1,79 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can use, redistribute, and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License, version 3
|
|
||||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TDENGINE_RPCHEAD_H
|
|
||||||
#define TDENGINE_RPCHEAD_H
|
|
||||||
|
|
||||||
#include <tdef.h>
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define RPC_CONN_TCP 2
|
|
||||||
|
|
||||||
extern int tsRpcOverhead;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
void* msg;
|
|
||||||
int msgLen;
|
|
||||||
uint32_t ip;
|
|
||||||
uint16_t port;
|
|
||||||
int connType;
|
|
||||||
void* shandle;
|
|
||||||
void* thandle;
|
|
||||||
void* chandle;
|
|
||||||
} SRecvInfo;
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char version : 4; // RPC version
|
|
||||||
char comp : 4; // compression algorithm, 0:no compression 1:lz4
|
|
||||||
char resflag : 2; // reserved bits
|
|
||||||
char spi : 3; // security parameter index
|
|
||||||
char encrypt : 3; // encrypt algorithm, 0: no encryption
|
|
||||||
uint16_t tranId; // transcation ID
|
|
||||||
uint32_t linkUid; // for unique connection ID assigned by client
|
|
||||||
uint64_t ahandle; // ahandle assigned by client
|
|
||||||
uint32_t sourceId; // source ID, an index for connection list
|
|
||||||
uint32_t destId; // destination ID, an index for connection list
|
|
||||||
uint32_t destIp; // destination IP address, for NAT scenario
|
|
||||||
char user[TSDB_UNI_LEN]; // user ID
|
|
||||||
uint16_t port; // for UDP only, port may be changed
|
|
||||||
char empty[1]; // reserved
|
|
||||||
uint16_t msgType; // message type
|
|
||||||
int32_t msgLen; // message length including the header iteslf
|
|
||||||
uint32_t msgVer;
|
|
||||||
int32_t code; // code in response message
|
|
||||||
uint8_t content[0]; // message body starts from here
|
|
||||||
} SRpcHead;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t reserved;
|
|
||||||
int32_t contLen;
|
|
||||||
} SRpcComp;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t timeStamp;
|
|
||||||
uint8_t auth[TSDB_AUTH_LEN];
|
|
||||||
} SRpcDigest;
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // TDENGINE_RPCHEAD_H
|
|
|
@ -20,7 +20,6 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can use, redistribute, and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License, version 3
|
|
||||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TDENGINE_RPC_CACHE_H
|
|
||||||
#define TDENGINE_RPC_CACHE_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void *rpcOpenConnCache(int maxSessions, void (*cleanFp)(void *), void *tmrCtrl, int64_t keepTimer);
|
|
||||||
void rpcCloseConnCache(void *handle);
|
|
||||||
void rpcAddConnIntoCache(void *handle, void *data, char *fqdn, uint16_t port, int8_t connType);
|
|
||||||
void *rpcGetConnFromCache(void *handle, char *fqdn, uint16_t port, int8_t connType);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // TDENGINE_RPC_CACHE_H
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can use, redistribute, and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License, version 3
|
|
||||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TDENGINE_RPC_LOG_H
|
|
||||||
#define TDENGINE_RPC_LOG_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "tlog.h"
|
|
||||||
|
|
||||||
#define tFatal(...) \
|
|
||||||
{ \
|
|
||||||
if (rpcDebugFlag & DEBUG_FATAL) { \
|
|
||||||
taosPrintLog("RPC FATAL ", DEBUG_FATAL, rpcDebugFlag, __VA_ARGS__); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
#define tError(...) \
|
|
||||||
{ \
|
|
||||||
if (rpcDebugFlag & DEBUG_ERROR) { \
|
|
||||||
taosPrintLog("RPC ERROR ", DEBUG_ERROR, rpcDebugFlag, __VA_ARGS__); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
#define tWarn(...) \
|
|
||||||
{ \
|
|
||||||
if (rpcDebugFlag & DEBUG_WARN) { \
|
|
||||||
taosPrintLog("RPC WARN ", DEBUG_WARN, rpcDebugFlag, __VA_ARGS__); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
#define tInfo(...) \
|
|
||||||
{ \
|
|
||||||
if (rpcDebugFlag & DEBUG_INFO) { \
|
|
||||||
taosPrintLog("RPC ", DEBUG_INFO, rpcDebugFlag, __VA_ARGS__); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
#define tDebug(...) \
|
|
||||||
{ \
|
|
||||||
if (rpcDebugFlag & DEBUG_DEBUG) { \
|
|
||||||
taosPrintLog("RPC ", DEBUG_DEBUG, rpcDebugFlag, __VA_ARGS__); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
#define tTrace(...) \
|
|
||||||
{ \
|
|
||||||
if (rpcDebugFlag & DEBUG_TRACE) { \
|
|
||||||
taosPrintLog("RPC ", DEBUG_TRACE, rpcDebugFlag, __VA_ARGS__); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
#define tDump(x, y) \
|
|
||||||
{ \
|
|
||||||
if (rpcDebugFlag & DEBUG_DUMP) { \
|
|
||||||
taosDumpData((unsigned char *)x, y); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // TDENGINE_RPC_LOG_H
|
|
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can use, redistribute, and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License, version 3
|
|
||||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _rpc_tcp_header_
|
|
||||||
#define _rpc_tcp_header_
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void *taosInitTcpServer(uint32_t ip, uint16_t port, char *label, int numOfThreads, void *fp, void *shandle);
|
|
||||||
void taosStopTcpServer(void *param);
|
|
||||||
void taosCleanUpTcpServer(void *param);
|
|
||||||
|
|
||||||
void *taosInitTcpClient(uint32_t ip, uint16_t port, char *label, int num, void *fp, void *shandle);
|
|
||||||
void taosStopTcpClient(void *chandle);
|
|
||||||
void taosCleanUpTcpClient(void *chandle);
|
|
||||||
void *taosOpenTcpClientConnection(void *shandle, void *thandle, uint32_t ip, uint16_t port);
|
|
||||||
|
|
||||||
void taosCloseTcpConnection(void *chandle);
|
|
||||||
int taosSendTcpData(uint32_t ip, uint16_t port, void *data, int len, void *chandle);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can use, redistribute, and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License, version 3
|
|
||||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _rpc_udp_header_
|
|
||||||
#define _rpc_udp_header_
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "taosdef.h"
|
|
||||||
|
|
||||||
void *taosInitUdpConnection(uint32_t ip, uint16_t port, char *label, int, void *fp, void *shandle);
|
|
||||||
void taosStopUdpConnection(void *handle);
|
|
||||||
void taosCleanUpUdpConnection(void *handle);
|
|
||||||
int taosSendUdpData(uint32_t ip, uint16_t port, void *data, int dataLen, void *chandle);
|
|
||||||
void *taosOpenUdpConnection(void *shandle, void *thandle, uint32_t ip, uint16_t port);
|
|
||||||
|
|
||||||
void taosFreeMsgHdr(void *hdr);
|
|
||||||
int taosMsgHdrSize(void *hdr);
|
|
||||||
void taosSendMsgHdr(void *hdr, TdFilePtr pFile);
|
|
||||||
void taosInitMsgHdr(void **hdr, void *dest, int maxPkts);
|
|
||||||
void taosSetMsgHdrData(void *hdr, char *data, int dataLen);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -12,7 +12,8 @@
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#ifdef USE_UV
|
#ifndef _TD_TRANSPORT_COMM_H
|
||||||
|
#define _TD_TRANSPORT_COMM_H
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -22,9 +23,6 @@ extern "C" {
|
||||||
#include "lz4.h"
|
#include "lz4.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "osSocket.h"
|
#include "osSocket.h"
|
||||||
#include "rpcCache.h"
|
|
||||||
#include "rpcHead.h"
|
|
||||||
#include "rpcLog.h"
|
|
||||||
#include "taoserror.h"
|
#include "taoserror.h"
|
||||||
#include "tglobal.h"
|
#include "tglobal.h"
|
||||||
#include "thash.h"
|
#include "thash.h"
|
||||||
|
@ -33,6 +31,7 @@ extern "C" {
|
||||||
#include "tmd5.h"
|
#include "tmd5.h"
|
||||||
#include "tmempool.h"
|
#include "tmempool.h"
|
||||||
#include "tmsg.h"
|
#include "tmsg.h"
|
||||||
|
#include "transLog.h"
|
||||||
#include "transportInt.h"
|
#include "transportInt.h"
|
||||||
#include "tref.h"
|
#include "tref.h"
|
||||||
#include "trpc.h"
|
#include "trpc.h"
|
||||||
|
@ -193,11 +192,6 @@ typedef enum { ConnNormal, ConnAcquire, ConnRelease, ConnBroken, ConnInPool } Co
|
||||||
#define container_of(ptr, type, member) ((type*)((char*)(ptr)-offsetof(type, member)))
|
#define container_of(ptr, type, member) ((type*)((char*)(ptr)-offsetof(type, member)))
|
||||||
#define RPC_RESERVE_SIZE (sizeof(STranConnCtx))
|
#define RPC_RESERVE_SIZE (sizeof(STranConnCtx))
|
||||||
|
|
||||||
#define RPC_MSG_OVERHEAD (sizeof(SRpcHead) + sizeof(SRpcDigest))
|
|
||||||
#define rpcHeadFromCont(cont) ((SRpcHead*)((char*)cont - sizeof(SRpcHead)))
|
|
||||||
#define rpcContFromHead(msg) (msg + sizeof(SRpcHead))
|
|
||||||
#define rpcMsgLenFromCont(contLen) (contLen + sizeof(SRpcHead))
|
|
||||||
#define rpcContLenFromMsg(msgLen) (msgLen - sizeof(SRpcHead))
|
|
||||||
#define rpcIsReq(type) (type & 1U)
|
#define rpcIsReq(type) (type & 1U)
|
||||||
|
|
||||||
#define TRANS_RESERVE_SIZE (sizeof(STranConnCtx))
|
#define TRANS_RESERVE_SIZE (sizeof(STranConnCtx))
|
||||||
|
@ -209,15 +203,14 @@ typedef enum { ConnNormal, ConnAcquire, ConnRelease, ConnBroken, ConnInPool } Co
|
||||||
#define transContLenFromMsg(msgLen) (msgLen - sizeof(STransMsgHead));
|
#define transContLenFromMsg(msgLen) (msgLen - sizeof(STransMsgHead));
|
||||||
#define transIsReq(type) (type & 1U)
|
#define transIsReq(type) (type & 1U)
|
||||||
|
|
||||||
int rpcAuthenticateMsg(void* pMsg, int msgLen, void* pAuth, void* pKey);
|
// int rpcAuthenticateMsg(void* pMsg, int msgLen, void* pAuth, void* pKey);
|
||||||
void rpcBuildAuthHead(void* pMsg, int msgLen, void* pAuth, void* pKey);
|
// void rpcBuildAuthHead(void* pMsg, int msgLen, void* pAuth, void* pKey);
|
||||||
int32_t rpcCompressRpcMsg(char* pCont, int32_t contLen);
|
//// int32_t rpcCompressRpcMsg(char* pCont, int32_t contLen);
|
||||||
SRpcHead* rpcDecompressRpcMsg(SRpcHead* pHead);
|
//
|
||||||
|
// int transAuthenticateMsg(void* pMsg, int msgLen, void* pAuth, void* pKey);
|
||||||
int transAuthenticateMsg(void* pMsg, int msgLen, void* pAuth, void* pKey);
|
// void transBuildAuthHead(void* pMsg, int msgLen, void* pAuth, void* pKey);
|
||||||
void transBuildAuthHead(void* pMsg, int msgLen, void* pAuth, void* pKey);
|
// bool transCompressMsg(char* msg, int32_t len, int32_t* flen);
|
||||||
bool transCompressMsg(char* msg, int32_t len, int32_t* flen);
|
// bool transDecompressMsg(char* msg, int32_t len, int32_t* flen);
|
||||||
bool transDecompressMsg(char* msg, int32_t len, int32_t* flen);
|
|
||||||
|
|
||||||
void transFreeMsg(void* msg);
|
void transFreeMsg(void* msg);
|
||||||
|
|
||||||
|
@ -365,4 +358,4 @@ void transThreadOnce();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif // _TD_TRANSPORT_COMM_H
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can use, redistribute, and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3
|
||||||
|
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TD_TRANSPORT_LOG_H
|
||||||
|
#define _TD_TRANSPORT_LOG_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
#include "tlog.h"
|
||||||
|
|
||||||
|
#define tFatal(...) do {if (rpcDebugFlag & DEBUG_FATAL){ taosPrintLog("RPC FATAL ", DEBUG_FATAL, rpcDebugFlag, __VA_ARGS__); }} while (0)
|
||||||
|
#define tError(...)do { if (rpcDebugFlag & DEBUG_ERROR){ taosPrintLog("RPC ERROR ", DEBUG_ERROR, rpcDebugFlag, __VA_ARGS__); } } while(0)
|
||||||
|
#define tWarn(...) do { if (rpcDebugFlag & DEBUG_WARN) { taosPrintLog("RPC WARN ", DEBUG_WARN, rpcDebugFlag, __VA_ARGS__); }} while(0)
|
||||||
|
#define tInfo(...) do { if (rpcDebugFlag & DEBUG_INFO) { taosPrintLog("RPC ", DEBUG_INFO, rpcDebugFlag, __VA_ARGS__); }} while(0)
|
||||||
|
#define tDebug(...) do {if (rpcDebugFlag & DEBUG_DEBUG){ taosPrintLog("RPC ", DEBUG_DEBUG, rpcDebugFlag, __VA_ARGS__); }} while(0)
|
||||||
|
#define tTrace(...) do {if (rpcDebugFlag & DEBUG_TRACE){ taosPrintLog("RPC ", DEBUG_TRACE, rpcDebugFlag, __VA_ARGS__); }} while(0)
|
||||||
|
#define tDump(x, y) do {if (rpcDebugFlag & DEBUG_DUMP) { taosDumpData((unsigned char *)x, y); } } while(0)
|
||||||
|
// clang-format on
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // __TRANS_LOG_H
|
|
@ -21,14 +21,12 @@
|
||||||
#endif
|
#endif
|
||||||
#include "lz4.h"
|
#include "lz4.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "rpcCache.h"
|
|
||||||
#include "rpcHead.h"
|
|
||||||
#include "rpcLog.h"
|
|
||||||
#include "taoserror.h"
|
#include "taoserror.h"
|
||||||
#include "tglobal.h"
|
#include "tglobal.h"
|
||||||
#include "thash.h"
|
#include "thash.h"
|
||||||
#include "tidpool.h"
|
#include "tidpool.h"
|
||||||
#include "tmsg.h"
|
#include "tmsg.h"
|
||||||
|
#include "transLog.h"
|
||||||
#include "tref.h"
|
#include "tref.h"
|
||||||
#include "trpc.h"
|
#include "trpc.h"
|
||||||
#include "ttimer.h"
|
#include "ttimer.h"
|
||||||
|
|
|
@ -1,294 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can use, redistribute, and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License, version 3
|
|
||||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "rpcCache.h"
|
|
||||||
#include "os.h"
|
|
||||||
#include "rpcLog.h"
|
|
||||||
#include "taosdef.h"
|
|
||||||
#include "tglobal.h"
|
|
||||||
#include "tmempool.h"
|
|
||||||
#include "ttimer.h"
|
|
||||||
#include "tutil.h"
|
|
||||||
|
|
||||||
typedef struct SConnHash {
|
|
||||||
char fqdn[TSDB_FQDN_LEN];
|
|
||||||
uint16_t port;
|
|
||||||
char connType;
|
|
||||||
struct SConnHash *prev;
|
|
||||||
struct SConnHash *next;
|
|
||||||
void * data;
|
|
||||||
uint64_t time;
|
|
||||||
} SConnHash;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SConnHash ** connHashList;
|
|
||||||
mpool_h connHashMemPool;
|
|
||||||
int maxSessions;
|
|
||||||
int total;
|
|
||||||
int * count;
|
|
||||||
int64_t keepTimer;
|
|
||||||
TdThreadMutex mutex;
|
|
||||||
void (*cleanFp)(void *);
|
|
||||||
void * tmrCtrl;
|
|
||||||
void * pTimer;
|
|
||||||
int64_t *lockedBy;
|
|
||||||
} SConnCache;
|
|
||||||
|
|
||||||
static int rpcHashConn(void *handle, char *fqdn, uint16_t port, int8_t connType);
|
|
||||||
static void rpcLockCache(int64_t *lockedBy);
|
|
||||||
static void rpcUnlockCache(int64_t *lockedBy);
|
|
||||||
static void rpcCleanConnCache(void *handle, void *tmrId);
|
|
||||||
static void rpcRemoveExpiredNodes(SConnCache *pCache, SConnHash *pNode, int hash, uint64_t time);
|
|
||||||
|
|
||||||
void *rpcOpenConnCache(int maxSessions, void (*cleanFp)(void *), void *tmrCtrl, int64_t keepTimer) {
|
|
||||||
SConnHash **connHashList;
|
|
||||||
mpool_h connHashMemPool;
|
|
||||||
SConnCache *pCache;
|
|
||||||
|
|
||||||
connHashMemPool = taosMemPoolInit(maxSessions, sizeof(SConnHash));
|
|
||||||
if (connHashMemPool == 0) return NULL;
|
|
||||||
|
|
||||||
connHashList = taosMemoryCalloc(sizeof(SConnHash *), maxSessions);
|
|
||||||
if (connHashList == 0) {
|
|
||||||
taosMemPoolCleanUp(connHashMemPool);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pCache = taosMemoryMalloc(sizeof(SConnCache));
|
|
||||||
if (pCache == NULL) {
|
|
||||||
taosMemPoolCleanUp(connHashMemPool);
|
|
||||||
taosMemoryFree(connHashList);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memset(pCache, 0, sizeof(SConnCache));
|
|
||||||
|
|
||||||
pCache->count = taosMemoryCalloc(sizeof(int), maxSessions);
|
|
||||||
pCache->total = 0;
|
|
||||||
pCache->keepTimer = keepTimer;
|
|
||||||
pCache->maxSessions = maxSessions;
|
|
||||||
pCache->connHashMemPool = connHashMemPool;
|
|
||||||
pCache->connHashList = connHashList;
|
|
||||||
pCache->cleanFp = cleanFp;
|
|
||||||
pCache->tmrCtrl = tmrCtrl;
|
|
||||||
pCache->lockedBy = taosMemoryCalloc(sizeof(int64_t), maxSessions);
|
|
||||||
taosTmrReset(rpcCleanConnCache, (int32_t)(pCache->keepTimer * 2), pCache, pCache->tmrCtrl, &pCache->pTimer);
|
|
||||||
|
|
||||||
taosThreadMutexInit(&pCache->mutex, NULL);
|
|
||||||
|
|
||||||
return pCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpcCloseConnCache(void *handle) {
|
|
||||||
SConnCache *pCache;
|
|
||||||
|
|
||||||
pCache = (SConnCache *)handle;
|
|
||||||
if (pCache == NULL || pCache->maxSessions == 0) return;
|
|
||||||
|
|
||||||
taosThreadMutexLock(&pCache->mutex);
|
|
||||||
|
|
||||||
taosTmrStopA(&(pCache->pTimer));
|
|
||||||
|
|
||||||
if (pCache->connHashMemPool) taosMemPoolCleanUp(pCache->connHashMemPool);
|
|
||||||
|
|
||||||
taosMemoryFreeClear(pCache->connHashList);
|
|
||||||
taosMemoryFreeClear(pCache->count);
|
|
||||||
taosMemoryFreeClear(pCache->lockedBy);
|
|
||||||
|
|
||||||
taosThreadMutexUnlock(&pCache->mutex);
|
|
||||||
|
|
||||||
taosThreadMutexDestroy(&pCache->mutex);
|
|
||||||
|
|
||||||
memset(pCache, 0, sizeof(SConnCache));
|
|
||||||
taosMemoryFree(pCache);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpcAddConnIntoCache(void *handle, void *data, char *fqdn, uint16_t port, int8_t connType) {
|
|
||||||
int hash;
|
|
||||||
SConnHash * pNode;
|
|
||||||
SConnCache *pCache;
|
|
||||||
|
|
||||||
uint64_t time = taosGetTimestampMs();
|
|
||||||
|
|
||||||
pCache = (SConnCache *)handle;
|
|
||||||
assert(pCache);
|
|
||||||
assert(data);
|
|
||||||
|
|
||||||
hash = rpcHashConn(pCache, fqdn, port, connType);
|
|
||||||
pNode = (SConnHash *)taosMemPoolMalloc(pCache->connHashMemPool);
|
|
||||||
tstrncpy(pNode->fqdn, fqdn, sizeof(pNode->fqdn));
|
|
||||||
pNode->port = port;
|
|
||||||
pNode->connType = connType;
|
|
||||||
pNode->data = data;
|
|
||||||
pNode->prev = NULL;
|
|
||||||
pNode->time = time;
|
|
||||||
|
|
||||||
rpcLockCache(pCache->lockedBy + hash);
|
|
||||||
|
|
||||||
pNode->next = pCache->connHashList[hash];
|
|
||||||
if (pCache->connHashList[hash] != NULL) (pCache->connHashList[hash])->prev = pNode;
|
|
||||||
pCache->connHashList[hash] = pNode;
|
|
||||||
|
|
||||||
pCache->count[hash]++;
|
|
||||||
rpcRemoveExpiredNodes(pCache, pNode->next, hash, time);
|
|
||||||
|
|
||||||
rpcUnlockCache(pCache->lockedBy + hash);
|
|
||||||
|
|
||||||
pCache->total++;
|
|
||||||
// tTrace("%p %s:%hu:%d:%d:%p added into cache, connections:%d", data, fqdn, port, connType, hash, pNode,
|
|
||||||
// pCache->count[hash]);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *rpcGetConnFromCache(void *handle, char *fqdn, uint16_t port, int8_t connType) {
|
|
||||||
int hash;
|
|
||||||
SConnHash * pNode;
|
|
||||||
SConnCache *pCache;
|
|
||||||
void * pData = NULL;
|
|
||||||
|
|
||||||
pCache = (SConnCache *)handle;
|
|
||||||
assert(pCache);
|
|
||||||
|
|
||||||
uint64_t time = taosGetTimestampMs();
|
|
||||||
|
|
||||||
hash = rpcHashConn(pCache, fqdn, port, connType);
|
|
||||||
rpcLockCache(pCache->lockedBy + hash);
|
|
||||||
|
|
||||||
pNode = pCache->connHashList[hash];
|
|
||||||
while (pNode) {
|
|
||||||
if (time >= pCache->keepTimer + pNode->time) {
|
|
||||||
rpcRemoveExpiredNodes(pCache, pNode, hash, time);
|
|
||||||
pNode = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(pNode->fqdn, fqdn) == 0 && pNode->port == port && pNode->connType == connType) break;
|
|
||||||
|
|
||||||
pNode = pNode->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pNode) {
|
|
||||||
rpcRemoveExpiredNodes(pCache, pNode->next, hash, time);
|
|
||||||
|
|
||||||
if (pNode->prev) {
|
|
||||||
pNode->prev->next = pNode->next;
|
|
||||||
} else {
|
|
||||||
pCache->connHashList[hash] = pNode->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pNode->next) {
|
|
||||||
pNode->next->prev = pNode->prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
pData = pNode->data;
|
|
||||||
taosMemPoolFree(pCache->connHashMemPool, (char *)pNode);
|
|
||||||
pCache->total--;
|
|
||||||
pCache->count[hash]--;
|
|
||||||
}
|
|
||||||
|
|
||||||
rpcUnlockCache(pCache->lockedBy + hash);
|
|
||||||
|
|
||||||
if (pData) {
|
|
||||||
// tTrace("%p %s:%hu:%d:%d:%p retrieved from cache, connections:%d", pData, fqdn, port, connType, hash, pNode,
|
|
||||||
// pCache->count[hash]);
|
|
||||||
} else {
|
|
||||||
// tTrace("%s:%hu:%d:%d failed to retrieve conn from cache, connections:%d", fqdn, port, connType, hash,
|
|
||||||
// pCache->count[hash]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pData;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rpcCleanConnCache(void *handle, void *tmrId) {
|
|
||||||
int hash;
|
|
||||||
SConnHash * pNode;
|
|
||||||
SConnCache *pCache;
|
|
||||||
|
|
||||||
pCache = (SConnCache *)handle;
|
|
||||||
if (pCache == NULL || pCache->maxSessions == 0) return;
|
|
||||||
if (pCache->pTimer != tmrId) return;
|
|
||||||
|
|
||||||
taosThreadMutexLock(&pCache->mutex);
|
|
||||||
uint64_t time = taosGetTimestampMs();
|
|
||||||
|
|
||||||
for (hash = 0; hash < pCache->maxSessions; ++hash) {
|
|
||||||
rpcLockCache(pCache->lockedBy + hash);
|
|
||||||
pNode = pCache->connHashList[hash];
|
|
||||||
rpcRemoveExpiredNodes(pCache, pNode, hash, time);
|
|
||||||
rpcUnlockCache(pCache->lockedBy + hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
// tTrace("timer, total connections in cache:%d", pCache->total);
|
|
||||||
taosTmrReset(rpcCleanConnCache, (int32_t)(pCache->keepTimer * 2), pCache, pCache->tmrCtrl, &pCache->pTimer);
|
|
||||||
taosThreadMutexUnlock(&pCache->mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rpcRemoveExpiredNodes(SConnCache *pCache, SConnHash *pNode, int hash, uint64_t time) {
|
|
||||||
if (pNode == NULL || (time < pCache->keepTimer + pNode->time)) return;
|
|
||||||
|
|
||||||
SConnHash *pPrev = pNode->prev, *pNext;
|
|
||||||
|
|
||||||
while (pNode) {
|
|
||||||
(*pCache->cleanFp)(pNode->data);
|
|
||||||
pNext = pNode->next;
|
|
||||||
pCache->total--;
|
|
||||||
pCache->count[hash]--;
|
|
||||||
// tTrace("%p %s:%hu:%d:%d:%p removed from cache, connections:%d", pNode->data, pNode->fqdn, pNode->port,
|
|
||||||
// pNode->connType, hash, pNode,
|
|
||||||
// pCache->count[hash]);
|
|
||||||
taosMemPoolFree(pCache->connHashMemPool, (char *)pNode);
|
|
||||||
pNode = pNext;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pPrev)
|
|
||||||
pPrev->next = NULL;
|
|
||||||
else
|
|
||||||
pCache->connHashList[hash] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int rpcHashConn(void *handle, char *fqdn, uint16_t port, int8_t connType) {
|
|
||||||
SConnCache *pCache = (SConnCache *)handle;
|
|
||||||
int hash = 0;
|
|
||||||
char * temp = fqdn;
|
|
||||||
|
|
||||||
while (*temp) {
|
|
||||||
hash += *temp;
|
|
||||||
++temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
hash += port;
|
|
||||||
hash += connType;
|
|
||||||
|
|
||||||
hash = hash % pCache->maxSessions;
|
|
||||||
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rpcLockCache(int64_t *lockedBy) {
|
|
||||||
int64_t tid = taosGetSelfPthreadId();
|
|
||||||
int i = 0;
|
|
||||||
while (atomic_val_compare_exchange_64(lockedBy, 0, tid) != 0) {
|
|
||||||
if (++i % 100 == 0) {
|
|
||||||
sched_yield();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rpcUnlockCache(int64_t *lockedBy) {
|
|
||||||
int64_t tid = taosGetSelfPthreadId();
|
|
||||||
if (atomic_val_compare_exchange_64(lockedBy, tid, 0) != tid) {
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,657 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can use, redistribute, and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License, version 3
|
|
||||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "rpcTcp.h"
|
|
||||||
#include "os.h"
|
|
||||||
#include "rpcHead.h"
|
|
||||||
#include "rpcLog.h"
|
|
||||||
#include "taosdef.h"
|
|
||||||
#include "taoserror.h"
|
|
||||||
#include "tutil.h"
|
|
||||||
|
|
||||||
#ifndef USE_UV
|
|
||||||
typedef struct SFdObj {
|
|
||||||
void * signature;
|
|
||||||
TdSocketPtr pSocket; // TCP socket FD
|
|
||||||
void * thandle; // handle from upper layer, like TAOS
|
|
||||||
uint32_t ip;
|
|
||||||
uint16_t port;
|
|
||||||
int16_t closedByApp; // 1: already closed by App
|
|
||||||
struct SThreadObj *pThreadObj;
|
|
||||||
struct SFdObj * prev;
|
|
||||||
struct SFdObj * next;
|
|
||||||
} SFdObj;
|
|
||||||
|
|
||||||
typedef struct SThreadObj {
|
|
||||||
TdThread thread;
|
|
||||||
SFdObj * pHead;
|
|
||||||
TdThreadMutex mutex;
|
|
||||||
uint32_t ip;
|
|
||||||
bool stop;
|
|
||||||
TdEpollPtr pEpoll;
|
|
||||||
int numOfFds;
|
|
||||||
int threadId;
|
|
||||||
char label[TSDB_LABEL_LEN];
|
|
||||||
void * shandle; // handle passed by upper layer during server initialization
|
|
||||||
void *(*processData)(SRecvInfo *pPacket);
|
|
||||||
} SThreadObj;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char label[TSDB_LABEL_LEN];
|
|
||||||
int32_t index;
|
|
||||||
int numOfThreads;
|
|
||||||
SThreadObj **pThreadObj;
|
|
||||||
} SClientObj;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
TdSocketServerPtr pSocketServer;
|
|
||||||
uint32_t ip;
|
|
||||||
uint16_t port;
|
|
||||||
int8_t stop;
|
|
||||||
int8_t reserve;
|
|
||||||
char label[TSDB_LABEL_LEN];
|
|
||||||
int numOfThreads;
|
|
||||||
void * shandle;
|
|
||||||
SThreadObj **pThreadObj;
|
|
||||||
TdThread thread;
|
|
||||||
} SServerObj;
|
|
||||||
|
|
||||||
static void * taosProcessTcpData(void *param);
|
|
||||||
static SFdObj *taosMallocFdObj(SThreadObj *pThreadObj, TdSocketPtr pSocket);
|
|
||||||
static void taosFreeFdObj(SFdObj *pFdObj);
|
|
||||||
static void taosReportBrokenLink(SFdObj *pFdObj);
|
|
||||||
static void * taosAcceptTcpConnection(void *arg);
|
|
||||||
|
|
||||||
void *taosInitTcpServer(uint32_t ip, uint16_t port, char *label, int numOfThreads, void *fp, void *shandle) {
|
|
||||||
SServerObj *pServerObj;
|
|
||||||
SThreadObj *pThreadObj;
|
|
||||||
|
|
||||||
pServerObj = (SServerObj *)taosMemoryCalloc(sizeof(SServerObj), 1);
|
|
||||||
if (pServerObj == NULL) {
|
|
||||||
tError("TCP:%s no enough memory", label);
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pServerObj->pSocketServer = NULL;
|
|
||||||
taosResetPthread(&pServerObj->thread);
|
|
||||||
pServerObj->ip = ip;
|
|
||||||
pServerObj->port = port;
|
|
||||||
tstrncpy(pServerObj->label, label, sizeof(pServerObj->label));
|
|
||||||
pServerObj->numOfThreads = numOfThreads;
|
|
||||||
|
|
||||||
pServerObj->pThreadObj = (SThreadObj **)taosMemoryCalloc(sizeof(SThreadObj *), numOfThreads);
|
|
||||||
if (pServerObj->pThreadObj == NULL) {
|
|
||||||
tError("TCP:%s no enough memory", label);
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
taosMemoryFree(pServerObj);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int code = 0;
|
|
||||||
TdThreadAttr thattr;
|
|
||||||
taosThreadAttrInit(&thattr);
|
|
||||||
taosThreadAttrSetDetachState(&thattr, PTHREAD_CREATE_JOINABLE);
|
|
||||||
|
|
||||||
// initialize parameters in case it may encounter error later
|
|
||||||
for (int i = 0; i < numOfThreads; ++i) {
|
|
||||||
pThreadObj = (SThreadObj *)taosMemoryCalloc(sizeof(SThreadObj), 1);
|
|
||||||
if (pThreadObj == NULL) {
|
|
||||||
tError("TCP:%s no enough memory", label);
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
for (int j = 0; j < i; ++j) taosMemoryFree(pServerObj->pThreadObj[j]);
|
|
||||||
taosMemoryFree(pServerObj->pThreadObj);
|
|
||||||
taosMemoryFree(pServerObj);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pServerObj->pThreadObj[i] = pThreadObj;
|
|
||||||
pThreadObj->pEpoll = NULL;
|
|
||||||
taosResetPthread(&pThreadObj->thread);
|
|
||||||
pThreadObj->processData = fp;
|
|
||||||
tstrncpy(pThreadObj->label, label, sizeof(pThreadObj->label));
|
|
||||||
pThreadObj->shandle = shandle;
|
|
||||||
pThreadObj->stop = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// initialize mutex, thread, fd which may fail
|
|
||||||
for (int i = 0; i < numOfThreads; ++i) {
|
|
||||||
pThreadObj = pServerObj->pThreadObj[i];
|
|
||||||
code = taosThreadMutexInit(&(pThreadObj->mutex), NULL);
|
|
||||||
if (code < 0) {
|
|
||||||
tError("%s failed to init TCP process data mutex(%s)", label, strerror(errno));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pThreadObj->pEpoll = taosCreateEpoll(10); // size does not matter
|
|
||||||
if (pThreadObj->pEpoll == NULL) {
|
|
||||||
tError("%s failed to create TCP epoll", label);
|
|
||||||
code = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
code = taosThreadCreate(&(pThreadObj->thread), &thattr, taosProcessTcpData, (void *)(pThreadObj));
|
|
||||||
if (code != 0) {
|
|
||||||
tError("%s failed to create TCP process data thread(%s)", label, strerror(errno));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pThreadObj->threadId = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
pServerObj->pSocketServer = taosOpenTcpServerSocket(pServerObj->ip, pServerObj->port);
|
|
||||||
if (pServerObj->pSocketServer == NULL) code = -1;
|
|
||||||
|
|
||||||
if (code == 0) {
|
|
||||||
code = taosThreadCreate(&pServerObj->thread, &thattr, taosAcceptTcpConnection, (void *)pServerObj);
|
|
||||||
if (code != 0) {
|
|
||||||
tError("%s failed to create TCP accept thread(%s)", label, strerror(code));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (code != 0) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
taosCleanUpTcpServer(pServerObj);
|
|
||||||
pServerObj = NULL;
|
|
||||||
} else {
|
|
||||||
tDebug("%s TCP server is initialized, ip:0x%x port:%hu numOfThreads:%d", label, ip, port, numOfThreads);
|
|
||||||
}
|
|
||||||
|
|
||||||
taosThreadAttrDestroy(&thattr);
|
|
||||||
return (void *)pServerObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void taosStopTcpThread(SThreadObj *pThreadObj) {
|
|
||||||
if (pThreadObj == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// save thread into local variable and signal thread to stop
|
|
||||||
TdThread thread = pThreadObj->thread;
|
|
||||||
if (!taosCheckPthreadValid(thread)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pThreadObj->stop = true;
|
|
||||||
if (taosComparePthread(thread, taosThreadSelf())) {
|
|
||||||
pthread_detach(taosThreadSelf());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
taosThreadJoin(thread, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void taosStopTcpServer(void *handle) {
|
|
||||||
SServerObj *pServerObj = handle;
|
|
||||||
|
|
||||||
if (pServerObj == NULL) return;
|
|
||||||
pServerObj->stop = 1;
|
|
||||||
|
|
||||||
if (pServerObj->pSocketServer != NULL) {
|
|
||||||
taosShutDownSocketServerRD(pServerObj->pSocketServer);
|
|
||||||
}
|
|
||||||
if (taosCheckPthreadValid(pServerObj->thread)) {
|
|
||||||
if (taosComparePthread(pServerObj->thread, taosThreadSelf())) {
|
|
||||||
pthread_detach(taosThreadSelf());
|
|
||||||
} else {
|
|
||||||
taosThreadJoin(pServerObj->thread, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tDebug("%s TCP server is stopped", pServerObj->label);
|
|
||||||
}
|
|
||||||
|
|
||||||
void taosCleanUpTcpServer(void *handle) {
|
|
||||||
SServerObj *pServerObj = handle;
|
|
||||||
SThreadObj *pThreadObj;
|
|
||||||
if (pServerObj == NULL) return;
|
|
||||||
|
|
||||||
for (int i = 0; i < pServerObj->numOfThreads; ++i) {
|
|
||||||
pThreadObj = pServerObj->pThreadObj[i];
|
|
||||||
taosStopTcpThread(pThreadObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
tDebug("%s TCP server is cleaned up", pServerObj->label);
|
|
||||||
|
|
||||||
taosMemoryFreeClear(pServerObj->pThreadObj);
|
|
||||||
taosMemoryFreeClear(pServerObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *taosAcceptTcpConnection(void *arg) {
|
|
||||||
TdSocketPtr pSocket = NULL;
|
|
||||||
struct sockaddr_in caddr;
|
|
||||||
int threadId = 0;
|
|
||||||
SThreadObj * pThreadObj;
|
|
||||||
SServerObj * pServerObj;
|
|
||||||
|
|
||||||
pServerObj = (SServerObj *)arg;
|
|
||||||
tDebug("%s TCP server is ready, ip:0x%x:%hu", pServerObj->label, pServerObj->ip, pServerObj->port);
|
|
||||||
setThreadName("acceptTcpConn");
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
socklen_t addrlen = sizeof(caddr);
|
|
||||||
pSocket = taosAcceptTcpConnectSocket(pServerObj->pSocketServer, (struct sockaddr *)&caddr, &addrlen);
|
|
||||||
if (pServerObj->stop) {
|
|
||||||
tDebug("%s TCP server stop accepting new connections", pServerObj->label);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pSocket == NULL) {
|
|
||||||
if (errno == EINVAL) {
|
|
||||||
tDebug("%s TCP server stop accepting new connections, exiting", pServerObj->label);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
tError("%s TCP accept failure(%s)", pServerObj->label, strerror(errno));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
taosKeepTcpAlive(pSocket);
|
|
||||||
struct timeval to = {5, 0};
|
|
||||||
int32_t ret = taosSetSockOpt(pSocket, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to));
|
|
||||||
if (ret != 0) {
|
|
||||||
taosCloseSocket(&pSocket);
|
|
||||||
tError("%s failed to set recv timeout fd(%s)for connection from:%s:%hu", pServerObj->label, strerror(errno),
|
|
||||||
taosInetNtoa(caddr.sin_addr), htons(caddr.sin_port));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// pick up the thread to handle this connection
|
|
||||||
pThreadObj = pServerObj->pThreadObj[threadId];
|
|
||||||
|
|
||||||
SFdObj *pFdObj = taosMallocFdObj(pThreadObj, pSocket);
|
|
||||||
if (pFdObj) {
|
|
||||||
pFdObj->ip = caddr.sin_addr.s_addr;
|
|
||||||
pFdObj->port = htons(caddr.sin_port);
|
|
||||||
tDebug("%s new TCP connection from %s:%hu, FD:%p numOfFds:%d", pServerObj->label,
|
|
||||||
taosInetNtoa(caddr.sin_addr), pFdObj->port, pFdObj, pThreadObj->numOfFds);
|
|
||||||
} else {
|
|
||||||
taosCloseSocket(&pSocket);
|
|
||||||
tError("%s failed to malloc FdObj(%s) for connection from:%s:%hu", pServerObj->label, strerror(errno),
|
|
||||||
taosInetNtoa(caddr.sin_addr), htons(caddr.sin_port));
|
|
||||||
}
|
|
||||||
|
|
||||||
// pick up next thread for next connection
|
|
||||||
threadId++;
|
|
||||||
threadId = threadId % pServerObj->numOfThreads;
|
|
||||||
}
|
|
||||||
|
|
||||||
taosCloseSocketServer(&pServerObj->pSocketServer);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *taosInitTcpClient(uint32_t ip, uint16_t port, char *label, int numOfThreads, void *fp, void *shandle) {
|
|
||||||
SClientObj *pClientObj = (SClientObj *)taosMemoryCalloc(1, sizeof(SClientObj));
|
|
||||||
if (pClientObj == NULL) {
|
|
||||||
tError("TCP:%s no enough memory", label);
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tstrncpy(pClientObj->label, label, sizeof(pClientObj->label));
|
|
||||||
pClientObj->numOfThreads = numOfThreads;
|
|
||||||
pClientObj->pThreadObj = (SThreadObj **)taosMemoryCalloc(numOfThreads, sizeof(SThreadObj *));
|
|
||||||
if (pClientObj->pThreadObj == NULL) {
|
|
||||||
tError("TCP:%s no enough memory", label);
|
|
||||||
taosMemoryFreeClear(pClientObj);
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
int code = 0;
|
|
||||||
TdThreadAttr thattr;
|
|
||||||
taosThreadAttrInit(&thattr);
|
|
||||||
taosThreadAttrSetDetachState(&thattr, PTHREAD_CREATE_JOINABLE);
|
|
||||||
|
|
||||||
for (int i = 0; i < numOfThreads; ++i) {
|
|
||||||
SThreadObj *pThreadObj = (SThreadObj *)taosMemoryCalloc(1, sizeof(SThreadObj));
|
|
||||||
if (pThreadObj == NULL) {
|
|
||||||
tError("TCP:%s no enough memory", label);
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
for (int j = 0; j < i; ++j) taosMemoryFree(pClientObj->pThreadObj[j]);
|
|
||||||
taosMemoryFree(pClientObj);
|
|
||||||
taosThreadAttrDestroy(&thattr);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
pClientObj->pThreadObj[i] = pThreadObj;
|
|
||||||
taosResetPthread(&pThreadObj->thread);
|
|
||||||
pThreadObj->ip = ip;
|
|
||||||
pThreadObj->stop = false;
|
|
||||||
tstrncpy(pThreadObj->label, label, sizeof(pThreadObj->label));
|
|
||||||
pThreadObj->shandle = shandle;
|
|
||||||
pThreadObj->processData = fp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// initialize mutex, thread, fd which may fail
|
|
||||||
for (int i = 0; i < numOfThreads; ++i) {
|
|
||||||
SThreadObj *pThreadObj = pClientObj->pThreadObj[i];
|
|
||||||
code = taosThreadMutexInit(&(pThreadObj->mutex), NULL);
|
|
||||||
if (code < 0) {
|
|
||||||
tError("%s failed to init TCP process data mutex(%s)", label, strerror(errno));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pThreadObj->pEpoll = taosCreateEpoll(10); // size does not matter
|
|
||||||
if (pThreadObj->pEpoll == NULL) {
|
|
||||||
tError("%s failed to create TCP epoll", label);
|
|
||||||
code = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
code = taosThreadCreate(&(pThreadObj->thread), &thattr, taosProcessTcpData, (void *)(pThreadObj));
|
|
||||||
if (code != 0) {
|
|
||||||
tError("%s failed to create TCP process data thread(%s)", label, strerror(errno));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pThreadObj->threadId = i;
|
|
||||||
}
|
|
||||||
if (code != 0) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
taosCleanUpTcpClient(pClientObj);
|
|
||||||
pClientObj = NULL;
|
|
||||||
}
|
|
||||||
return pClientObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
void taosStopTcpClient(void *chandle) {
|
|
||||||
SClientObj *pClientObj = chandle;
|
|
||||||
|
|
||||||
if (pClientObj == NULL) return;
|
|
||||||
|
|
||||||
tDebug("%s TCP client is stopped", pClientObj->label);
|
|
||||||
}
|
|
||||||
|
|
||||||
void taosCleanUpTcpClient(void *chandle) {
|
|
||||||
SClientObj *pClientObj = chandle;
|
|
||||||
if (pClientObj == NULL) return;
|
|
||||||
for (int i = 0; i < pClientObj->numOfThreads; ++i) {
|
|
||||||
SThreadObj *pThreadObj = pClientObj->pThreadObj[i];
|
|
||||||
taosStopTcpThread(pThreadObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
tDebug("%s TCP client is cleaned up", pClientObj->label);
|
|
||||||
taosMemoryFreeClear(pClientObj->pThreadObj);
|
|
||||||
taosMemoryFreeClear(pClientObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *taosOpenTcpClientConnection(void *shandle, void *thandle, uint32_t ip, uint16_t port) {
|
|
||||||
SClientObj *pClientObj = shandle;
|
|
||||||
int32_t index = atomic_load_32(&pClientObj->index) % pClientObj->numOfThreads;
|
|
||||||
atomic_store_32(&pClientObj->index, index + 1);
|
|
||||||
SThreadObj *pThreadObj = pClientObj->pThreadObj[index];
|
|
||||||
|
|
||||||
TdSocketPtr pSocket = taosOpenTcpClientSocket(ip, port, pThreadObj->ip);
|
|
||||||
if (pSocket == NULL) return NULL;
|
|
||||||
|
|
||||||
struct sockaddr_in sin;
|
|
||||||
uint16_t localPort = 0;
|
|
||||||
unsigned int addrlen = sizeof(sin);
|
|
||||||
if (taosGetSocketName(pSocket, (struct sockaddr *)&sin, &addrlen) == 0 && sin.sin_family == AF_INET && addrlen == sizeof(sin)) {
|
|
||||||
localPort = (uint16_t)ntohs(sin.sin_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
SFdObj *pFdObj = taosMallocFdObj(pThreadObj, pSocket);
|
|
||||||
|
|
||||||
if (pFdObj) {
|
|
||||||
pFdObj->thandle = thandle;
|
|
||||||
pFdObj->port = port;
|
|
||||||
pFdObj->ip = ip;
|
|
||||||
|
|
||||||
char ipport[40] = {0};
|
|
||||||
taosIpPort2String(ip, port, ipport);
|
|
||||||
tDebug("%s %p TCP connection to %s is created, localPort:%hu FD:%p numOfFds:%d", pThreadObj->label, thandle,
|
|
||||||
ipport, localPort, pFdObj, pThreadObj->numOfFds);
|
|
||||||
} else {
|
|
||||||
tError("%s failed to malloc client FdObj(%s)", pThreadObj->label, strerror(errno));
|
|
||||||
taosCloseSocket(&pSocket);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pFdObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
void taosCloseTcpConnection(void *chandle) {
|
|
||||||
SFdObj *pFdObj = chandle;
|
|
||||||
if (pFdObj == NULL || pFdObj->signature != pFdObj) return;
|
|
||||||
|
|
||||||
SThreadObj *pThreadObj = pFdObj->pThreadObj;
|
|
||||||
tDebug("%s %p TCP connection will be closed, FD:%p", pThreadObj->label, pFdObj->thandle, pFdObj);
|
|
||||||
|
|
||||||
// pFdObj->thandle = NULL;
|
|
||||||
pFdObj->closedByApp = 1;
|
|
||||||
taosShutDownSocketWR(pFdObj->pSocket);
|
|
||||||
}
|
|
||||||
|
|
||||||
int taosSendTcpData(uint32_t ip, uint16_t port, void *data, int len, void *chandle) {
|
|
||||||
SFdObj *pFdObj = chandle;
|
|
||||||
if (pFdObj == NULL || pFdObj->signature != pFdObj) return -1;
|
|
||||||
SThreadObj *pThreadObj = pFdObj->pThreadObj;
|
|
||||||
|
|
||||||
int ret = taosWriteMsg(pFdObj->pSocket, data, len);
|
|
||||||
tTrace("%s %p TCP data is sent, FD:%p bytes:%d", pThreadObj->label, pFdObj->thandle, pFdObj, ret);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void taosReportBrokenLink(SFdObj *pFdObj) {
|
|
||||||
SThreadObj *pThreadObj = pFdObj->pThreadObj;
|
|
||||||
|
|
||||||
// notify the upper layer, so it will clean the associated context
|
|
||||||
if (pFdObj->closedByApp == 0) {
|
|
||||||
taosShutDownSocketWR(pFdObj->pSocket);
|
|
||||||
|
|
||||||
SRecvInfo recvInfo;
|
|
||||||
recvInfo.msg = NULL;
|
|
||||||
recvInfo.msgLen = 0;
|
|
||||||
recvInfo.ip = 0;
|
|
||||||
recvInfo.port = 0;
|
|
||||||
recvInfo.shandle = pThreadObj->shandle;
|
|
||||||
recvInfo.thandle = pFdObj->thandle;
|
|
||||||
recvInfo.chandle = NULL;
|
|
||||||
recvInfo.connType = RPC_CONN_TCP;
|
|
||||||
(*(pThreadObj->processData))(&recvInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
taosFreeFdObj(pFdObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int taosReadTcpData(SFdObj *pFdObj, SRecvInfo *pInfo) {
|
|
||||||
SRpcHead rpcHead;
|
|
||||||
int32_t msgLen, leftLen, retLen, headLen;
|
|
||||||
char * buffer, *msg;
|
|
||||||
|
|
||||||
SThreadObj *pThreadObj = pFdObj->pThreadObj;
|
|
||||||
|
|
||||||
headLen = taosReadMsg(pFdObj->pSocket, &rpcHead, sizeof(SRpcHead));
|
|
||||||
if (headLen != sizeof(SRpcHead)) {
|
|
||||||
tDebug("%s %p read error, FD:%p headLen:%d", pThreadObj->label, pFdObj->thandle, pFdObj, headLen);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
msgLen = (int32_t)htonl((uint32_t)rpcHead.msgLen);
|
|
||||||
int32_t size = msgLen + tsRpcOverhead;
|
|
||||||
buffer = taosMemoryMalloc(size);
|
|
||||||
if (NULL == buffer) {
|
|
||||||
tError("%s %p TCP taosMemoryMalloc(size:%d) fail", pThreadObj->label, pFdObj->thandle, msgLen);
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
tTrace("%s %p read data, FD:%p TCP malloc mem:%p", pThreadObj->label, pFdObj->thandle, pFdObj, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
msg = buffer + tsRpcOverhead;
|
|
||||||
leftLen = msgLen - headLen;
|
|
||||||
retLen = taosReadMsg(pFdObj->pSocket, msg + headLen, leftLen);
|
|
||||||
|
|
||||||
if (leftLen != retLen) {
|
|
||||||
tError("%s %p read error, leftLen:%d retLen:%d FD:%p", pThreadObj->label, pFdObj->thandle, leftLen, retLen, pFdObj);
|
|
||||||
taosMemoryFree(buffer);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(msg, &rpcHead, sizeof(SRpcHead));
|
|
||||||
|
|
||||||
pInfo->msg = msg;
|
|
||||||
pInfo->msgLen = msgLen;
|
|
||||||
pInfo->ip = pFdObj->ip;
|
|
||||||
pInfo->port = pFdObj->port;
|
|
||||||
pInfo->shandle = pThreadObj->shandle;
|
|
||||||
pInfo->thandle = pFdObj->thandle;
|
|
||||||
pInfo->chandle = pFdObj;
|
|
||||||
pInfo->connType = RPC_CONN_TCP;
|
|
||||||
|
|
||||||
if (pFdObj->closedByApp) {
|
|
||||||
taosMemoryFree(buffer);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define maxEvents 10
|
|
||||||
|
|
||||||
static void *taosProcessTcpData(void *param) {
|
|
||||||
SThreadObj * pThreadObj = param;
|
|
||||||
SFdObj * pFdObj;
|
|
||||||
struct epoll_event events[maxEvents];
|
|
||||||
SRecvInfo recvInfo;
|
|
||||||
|
|
||||||
char name[16] = {0};
|
|
||||||
snprintf(name, tListLen(name), "%s-tcp", pThreadObj->label);
|
|
||||||
setThreadName(name);
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
int fdNum = taosWaitEpoll(pThreadObj->pEpoll, events, maxEvents, TAOS_EPOLL_WAIT_TIME);
|
|
||||||
if (pThreadObj->stop) {
|
|
||||||
tDebug("%s TCP thread get stop event, exiting...", pThreadObj->label);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (fdNum < 0) continue;
|
|
||||||
|
|
||||||
for (int i = 0; i < fdNum; ++i) {
|
|
||||||
pFdObj = events[i].data.ptr;
|
|
||||||
|
|
||||||
if (events[i].events & EPOLLERR) {
|
|
||||||
tDebug("%s %p FD:%p epoll errors", pThreadObj->label, pFdObj->thandle, pFdObj);
|
|
||||||
taosReportBrokenLink(pFdObj);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (events[i].events & EPOLLRDHUP) {
|
|
||||||
tDebug("%s %p FD:%p RD hang up", pThreadObj->label, pFdObj->thandle, pFdObj);
|
|
||||||
taosReportBrokenLink(pFdObj);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (events[i].events & EPOLLHUP) {
|
|
||||||
tDebug("%s %p FD:%p hang up", pThreadObj->label, pFdObj->thandle, pFdObj);
|
|
||||||
taosReportBrokenLink(pFdObj);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (taosReadTcpData(pFdObj, &recvInfo) < 0) {
|
|
||||||
taosShutDownSocketWR(pFdObj->pSocket);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
pFdObj->thandle = (*(pThreadObj->processData))(&recvInfo);
|
|
||||||
if (pFdObj->thandle == NULL) taosFreeFdObj(pFdObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pThreadObj->stop) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pThreadObj->pEpoll != NULL) {
|
|
||||||
taosCloseEpoll(&pThreadObj->pEpoll);
|
|
||||||
pThreadObj->pEpoll = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (pThreadObj->pHead) {
|
|
||||||
pFdObj = pThreadObj->pHead;
|
|
||||||
pThreadObj->pHead = pFdObj->next;
|
|
||||||
taosReportBrokenLink(pFdObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
taosThreadMutexDestroy(&(pThreadObj->mutex));
|
|
||||||
tDebug("%s TCP thread exits ...", pThreadObj->label);
|
|
||||||
taosMemoryFreeClear(pThreadObj);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static SFdObj *taosMallocFdObj(SThreadObj *pThreadObj, TdSocketPtr pSocket) {
|
|
||||||
struct epoll_event event;
|
|
||||||
|
|
||||||
SFdObj *pFdObj = (SFdObj *)taosMemoryCalloc(sizeof(SFdObj), 1);
|
|
||||||
if (pFdObj == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pFdObj->closedByApp = 0;
|
|
||||||
pFdObj->pSocket = pSocket;
|
|
||||||
pFdObj->pThreadObj = pThreadObj;
|
|
||||||
pFdObj->signature = pFdObj;
|
|
||||||
|
|
||||||
event.events = EPOLLIN | EPOLLRDHUP;
|
|
||||||
event.data.ptr = pFdObj;
|
|
||||||
if (taosCtlEpoll(pThreadObj->pEpoll, EPOLL_CTL_ADD, pSocket, &event) < 0) {
|
|
||||||
taosMemoryFreeClear(pFdObj);
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// notify the data process, add into the FdObj list
|
|
||||||
taosThreadMutexLock(&(pThreadObj->mutex));
|
|
||||||
pFdObj->next = pThreadObj->pHead;
|
|
||||||
if (pThreadObj->pHead) (pThreadObj->pHead)->prev = pFdObj;
|
|
||||||
pThreadObj->pHead = pFdObj;
|
|
||||||
pThreadObj->numOfFds++;
|
|
||||||
taosThreadMutexUnlock(&(pThreadObj->mutex));
|
|
||||||
|
|
||||||
return pFdObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void taosFreeFdObj(SFdObj *pFdObj) {
|
|
||||||
if (pFdObj == NULL) return;
|
|
||||||
if (pFdObj->signature != pFdObj) return;
|
|
||||||
|
|
||||||
SThreadObj *pThreadObj = pFdObj->pThreadObj;
|
|
||||||
taosThreadMutexLock(&pThreadObj->mutex);
|
|
||||||
|
|
||||||
if (pFdObj->signature == NULL) {
|
|
||||||
taosThreadMutexUnlock(&pThreadObj->mutex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pFdObj->signature = NULL;
|
|
||||||
taosCtlEpoll(pThreadObj->pEpoll, EPOLL_CTL_DEL, pFdObj->pSocket, NULL);
|
|
||||||
taosCloseSocket(&pFdObj->pSocket);
|
|
||||||
|
|
||||||
pThreadObj->numOfFds--;
|
|
||||||
if (pThreadObj->numOfFds < 0)
|
|
||||||
tError("%s %p TCP thread:%d, number of FDs is negative!!!", pThreadObj->label, pFdObj->thandle,
|
|
||||||
pThreadObj->threadId);
|
|
||||||
|
|
||||||
if (pFdObj->prev) {
|
|
||||||
(pFdObj->prev)->next = pFdObj->next;
|
|
||||||
} else {
|
|
||||||
pThreadObj->pHead = pFdObj->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pFdObj->next) {
|
|
||||||
(pFdObj->next)->prev = pFdObj->prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
taosThreadMutexUnlock(&pThreadObj->mutex);
|
|
||||||
|
|
||||||
tDebug("%s %p TCP connection is closed, FD:%p numOfFds:%d", pThreadObj->label, pFdObj->thandle, pFdObj, pThreadObj->numOfFds);
|
|
||||||
|
|
||||||
taosMemoryFreeClear(pFdObj);
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,261 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can use, redistribute, and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License, version 3
|
|
||||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "rpcUdp.h"
|
|
||||||
#include "os.h"
|
|
||||||
#include "rpcHead.h"
|
|
||||||
#include "rpcLog.h"
|
|
||||||
#include "taosdef.h"
|
|
||||||
#include "taoserror.h"
|
|
||||||
#include "ttimer.h"
|
|
||||||
#include "tutil.h"
|
|
||||||
|
|
||||||
#ifndef USE_UV
|
|
||||||
|
|
||||||
#define RPC_MAX_UDP_CONNS 256
|
|
||||||
#define RPC_MAX_UDP_PKTS 1000
|
|
||||||
#define RPC_UDP_BUF_TIME 5 // mseconds
|
|
||||||
#define RPC_MAX_UDP_SIZE 65480
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int index;
|
|
||||||
TdSocketPtr pSocket;
|
|
||||||
uint16_t port; // peer port
|
|
||||||
uint16_t localPort; // local port
|
|
||||||
char label[TSDB_LABEL_LEN]; // copy from udpConnSet;
|
|
||||||
TdThread thread;
|
|
||||||
void *hash;
|
|
||||||
void *shandle; // handle passed by upper layer during server initialization
|
|
||||||
void *pSet;
|
|
||||||
void *(*processData)(SRecvInfo *pRecv);
|
|
||||||
char *buffer; // buffer to receive data
|
|
||||||
} SUdpConn;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int index;
|
|
||||||
int server;
|
|
||||||
uint32_t ip; // local IP
|
|
||||||
uint16_t port; // local Port
|
|
||||||
void * shandle; // handle passed by upper layer during server initialization
|
|
||||||
int threads;
|
|
||||||
char label[TSDB_LABEL_LEN];
|
|
||||||
void *(*fp)(SRecvInfo *pPacket);
|
|
||||||
SUdpConn udpConn[];
|
|
||||||
} SUdpConnSet;
|
|
||||||
|
|
||||||
static void *taosRecvUdpData(void *param);
|
|
||||||
|
|
||||||
void *taosInitUdpConnection(uint32_t ip, uint16_t port, char *label, int threads, void *fp, void *shandle) {
|
|
||||||
SUdpConn * pConn;
|
|
||||||
SUdpConnSet *pSet;
|
|
||||||
|
|
||||||
int size = (int)sizeof(SUdpConnSet) + threads * (int)sizeof(SUdpConn);
|
|
||||||
pSet = (SUdpConnSet *)taosMemoryMalloc((size_t)size);
|
|
||||||
if (pSet == NULL) {
|
|
||||||
tError("%s failed to allocate UdpConn", label);
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(pSet, 0, (size_t)size);
|
|
||||||
pSet->ip = ip;
|
|
||||||
pSet->port = port;
|
|
||||||
pSet->shandle = shandle;
|
|
||||||
pSet->fp = fp;
|
|
||||||
pSet->threads = threads;
|
|
||||||
tstrncpy(pSet->label, label, sizeof(pSet->label));
|
|
||||||
|
|
||||||
TdThreadAttr thAttr;
|
|
||||||
taosThreadAttrInit(&thAttr);
|
|
||||||
taosThreadAttrSetDetachState(&thAttr, PTHREAD_CREATE_JOINABLE);
|
|
||||||
|
|
||||||
int i;
|
|
||||||
uint16_t ownPort;
|
|
||||||
for (i = 0; i < threads; ++i) {
|
|
||||||
pConn = pSet->udpConn + i;
|
|
||||||
ownPort = (port ? port + i : 0);
|
|
||||||
pConn->pSocket = taosOpenUdpSocket(ip, ownPort);
|
|
||||||
if (pConn->pSocket == NULL) {
|
|
||||||
tError("%s failed to open UDP socket %x:%hu", label, ip, port);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pConn->buffer = taosMemoryMalloc(RPC_MAX_UDP_SIZE);
|
|
||||||
if (NULL == pConn->buffer) {
|
|
||||||
tError("%s failed to malloc recv buffer", label);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sockaddr_in sin;
|
|
||||||
unsigned int addrlen = sizeof(sin);
|
|
||||||
if (taosGetSocketName(pConn->pSocket, (struct sockaddr *)&sin, &addrlen) == 0 && sin.sin_family == AF_INET &&
|
|
||||||
addrlen == sizeof(sin)) {
|
|
||||||
pConn->localPort = (uint16_t)ntohs(sin.sin_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
tstrncpy(pConn->label, label, sizeof(pConn->label));
|
|
||||||
pConn->shandle = shandle;
|
|
||||||
pConn->processData = fp;
|
|
||||||
pConn->index = i;
|
|
||||||
pConn->pSet = pSet;
|
|
||||||
|
|
||||||
int code = taosThreadCreate(&pConn->thread, &thAttr, taosRecvUdpData, pConn);
|
|
||||||
if (code != 0) {
|
|
||||||
tError("%s failed to create thread to process UDP data(%s)", label, strerror(errno));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
taosThreadAttrDestroy(&thAttr);
|
|
||||||
|
|
||||||
if (i != threads) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
taosCleanUpUdpConnection(pSet);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tDebug("%s UDP connection is initialized, ip:%x:%hu threads:%d", label, ip, port, threads);
|
|
||||||
return pSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
void taosStopUdpConnection(void *handle) {
|
|
||||||
SUdpConnSet *pSet = (SUdpConnSet *)handle;
|
|
||||||
SUdpConn * pConn;
|
|
||||||
|
|
||||||
if (pSet == NULL) return;
|
|
||||||
|
|
||||||
for (int i = 0; i < pSet->threads; ++i) {
|
|
||||||
pConn = pSet->udpConn + i;
|
|
||||||
if (pConn->pSocket != NULL) taosShutDownSocketRDWR(pConn->pSocket);
|
|
||||||
if (pConn->pSocket != NULL) taosCloseSocket(&pConn->pSocket);
|
|
||||||
pConn->pSocket = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < pSet->threads; ++i) {
|
|
||||||
pConn = pSet->udpConn + i;
|
|
||||||
if (taosCheckPthreadValid(pConn->thread)) {
|
|
||||||
taosThreadJoin(pConn->thread, NULL);
|
|
||||||
}
|
|
||||||
taosMemoryFreeClear(pConn->buffer);
|
|
||||||
// tTrace("%s UDP thread is closed, index:%d", pConn->label, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
tDebug("%s UDP is stopped", pSet->label);
|
|
||||||
}
|
|
||||||
|
|
||||||
void taosCleanUpUdpConnection(void *handle) {
|
|
||||||
SUdpConnSet *pSet = (SUdpConnSet *)handle;
|
|
||||||
SUdpConn * pConn;
|
|
||||||
|
|
||||||
if (pSet == NULL) return;
|
|
||||||
|
|
||||||
for (int i = 0; i < pSet->threads; ++i) {
|
|
||||||
pConn = pSet->udpConn + i;
|
|
||||||
if (pConn->pSocket != NULL) taosCloseSocket(&pConn->pSocket);
|
|
||||||
}
|
|
||||||
|
|
||||||
tDebug("%s UDP is cleaned up", pSet->label);
|
|
||||||
taosMemoryFreeClear(pSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *taosOpenUdpConnection(void *shandle, void *thandle, uint32_t ip, uint16_t port) {
|
|
||||||
SUdpConnSet *pSet = (SUdpConnSet *)shandle;
|
|
||||||
|
|
||||||
pSet->index = (pSet->index + 1) % pSet->threads;
|
|
||||||
|
|
||||||
SUdpConn *pConn = pSet->udpConn + pSet->index;
|
|
||||||
pConn->port = port;
|
|
||||||
|
|
||||||
tDebug("%s UDP connection is setup, ip:%x:%hu localPort:%hu", pConn->label, ip, port, pConn->localPort);
|
|
||||||
|
|
||||||
return pConn;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *taosRecvUdpData(void *param) {
|
|
||||||
SUdpConn * pConn = param;
|
|
||||||
struct sockaddr_in sourceAdd;
|
|
||||||
ssize_t dataLen;
|
|
||||||
unsigned int addLen;
|
|
||||||
uint16_t port;
|
|
||||||
SRecvInfo recvInfo;
|
|
||||||
|
|
||||||
memset(&sourceAdd, 0, sizeof(sourceAdd));
|
|
||||||
addLen = sizeof(sourceAdd);
|
|
||||||
tDebug("%s UDP thread is created, index:%d", pConn->label, pConn->index);
|
|
||||||
char *msg = pConn->buffer;
|
|
||||||
|
|
||||||
setThreadName("recvUdpData");
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
dataLen = taosReadFromSocket(pConn->pSocket, pConn->buffer, RPC_MAX_UDP_SIZE, 0, (struct sockaddr *)&sourceAdd, &addLen);
|
|
||||||
if (dataLen <= 0) {
|
|
||||||
tDebug("%s UDP socket was closed, exiting(%s), dataLen:%d", pConn->label, strerror(errno), (int32_t)dataLen);
|
|
||||||
|
|
||||||
// for windows usage, remote shutdown also returns - 1 in windows client
|
|
||||||
if (pConn->pSocket == NULL) {
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
port = ntohs(sourceAdd.sin_port);
|
|
||||||
|
|
||||||
if (dataLen < sizeof(SRpcHead)) {
|
|
||||||
tError("%s recvfrom failed(%s)", pConn->label, strerror(errno));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t size = dataLen + tsRpcOverhead;
|
|
||||||
char * tmsg = taosMemoryMalloc(size);
|
|
||||||
if (NULL == tmsg) {
|
|
||||||
tError("%s failed to allocate memory, size:%" PRId64, pConn->label, (int64_t)dataLen);
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
tTrace("UDP malloc mem:%p size:%d", tmsg, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
tmsg += tsRpcOverhead; // overhead for SRpcReqContext
|
|
||||||
memcpy(tmsg, msg, dataLen);
|
|
||||||
recvInfo.msg = tmsg;
|
|
||||||
recvInfo.msgLen = dataLen;
|
|
||||||
recvInfo.ip = sourceAdd.sin_addr.s_addr;
|
|
||||||
recvInfo.port = port;
|
|
||||||
recvInfo.shandle = pConn->shandle;
|
|
||||||
recvInfo.thandle = NULL;
|
|
||||||
recvInfo.chandle = pConn;
|
|
||||||
recvInfo.connType = 0;
|
|
||||||
(*(pConn->processData))(&recvInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int taosSendUdpData(uint32_t ip, uint16_t port, void *data, int dataLen, void *chandle) {
|
|
||||||
SUdpConn *pConn = (SUdpConn *)chandle;
|
|
||||||
|
|
||||||
if (pConn == NULL) return -1;
|
|
||||||
|
|
||||||
struct sockaddr_in destAdd;
|
|
||||||
memset(&destAdd, 0, sizeof(destAdd));
|
|
||||||
destAdd.sin_family = AF_INET;
|
|
||||||
destAdd.sin_addr.s_addr = ip;
|
|
||||||
destAdd.sin_port = htons(port);
|
|
||||||
|
|
||||||
int ret = taosSendto(pConn->pSocket, data, (size_t)dataLen, 0, (struct sockaddr *)&destAdd, sizeof(destAdd));
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -15,9 +15,9 @@
|
||||||
|
|
||||||
//#define _DEFAULT_SOURCE
|
//#define _DEFAULT_SOURCE
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "rpcLog.h"
|
|
||||||
#include "tglobal.h"
|
#include "tglobal.h"
|
||||||
#include "tqueue.h"
|
#include "tqueue.h"
|
||||||
|
#include "transLog.h"
|
||||||
#include "trpc.h"
|
#include "trpc.h"
|
||||||
|
|
||||||
int msgSize = 128;
|
int msgSize = 128;
|
||||||
|
|
|
@ -14,9 +14,9 @@
|
||||||
*/
|
*/
|
||||||
#include <tdatablock.h>
|
#include <tdatablock.h>
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "rpcLog.h"
|
|
||||||
#include "taoserror.h"
|
#include "taoserror.h"
|
||||||
#include "tglobal.h"
|
#include "tglobal.h"
|
||||||
|
#include "transLog.h"
|
||||||
#include "trpc.h"
|
#include "trpc.h"
|
||||||
#include "tutil.h"
|
#include "tutil.h"
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
|
|
||||||
//#define _DEFAULT_SOURCE
|
//#define _DEFAULT_SOURCE
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "rpcLog.h"
|
|
||||||
#include "tglobal.h"
|
#include "tglobal.h"
|
||||||
#include "tqueue.h"
|
#include "tqueue.h"
|
||||||
|
#include "transLog.h"
|
||||||
#include "trpc.h"
|
#include "trpc.h"
|
||||||
|
|
||||||
int msgSize = 128;
|
int msgSize = 128;
|
||||||
|
|
|
@ -14,9 +14,9 @@
|
||||||
*/
|
*/
|
||||||
#include <tdatablock.h>
|
#include <tdatablock.h>
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "rpcLog.h"
|
|
||||||
#include "taoserror.h"
|
#include "taoserror.h"
|
||||||
#include "tglobal.h"
|
#include "tglobal.h"
|
||||||
|
#include "transLog.h"
|
||||||
#include "trpc.h"
|
#include "trpc.h"
|
||||||
#include "tutil.h"
|
#include "tutil.h"
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,10 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "rpcLog.h"
|
|
||||||
#include "tdatablock.h"
|
#include "tdatablock.h"
|
||||||
#include "tglobal.h"
|
#include "tglobal.h"
|
||||||
#include "tlog.h"
|
#include "tlog.h"
|
||||||
|
#include "transLog.h"
|
||||||
#include "trpc.h"
|
#include "trpc.h"
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue