1462 lines
47 KiB
C++
1462 lines
47 KiB
C++
/*-------------------------------------------------------------------------
|
|
*
|
|
* commproxy_interface.h
|
|
* api for CommProxy interface
|
|
*
|
|
*
|
|
* Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
* src/include/communication/commproxy_interface.h
|
|
*
|
|
* NOTES
|
|
* Libnet or default tcp socket programming
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#ifndef COMMPROXY_INTERFACE_H
|
|
#define COMMPROXY_INTERFACE_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/socket.h>
|
|
#include <sys/types.h>
|
|
#include <sys/select.h>
|
|
#include <sys/epoll.h>
|
|
#include <poll.h>
|
|
#include <iostream>
|
|
#include <unordered_map>
|
|
#include <mutex>
|
|
#include <condition_variable>
|
|
#include <boost/lockfree/queue.hpp>
|
|
#include <boost/lockfree/stack.hpp>
|
|
#include <string>
|
|
#include <list>
|
|
#include <string.h>
|
|
#include "communication/commproxy_basic.h"
|
|
#include "communication/libnet_extern.h"
|
|
#include "postgres_ext.h"
|
|
#include "postgres.h"
|
|
#include "nodes/pg_list.h"
|
|
#include "port.h"
|
|
#include "pgtime.h"
|
|
#include "utils/memutils.h"
|
|
#include "knl/knl_instance.h"
|
|
#include "knl/knl_thread.h"
|
|
extern knl_instance_context g_instance;
|
|
|
|
|
|
/******************************************************************
|
|
* compile options *
|
|
******************************************************************/
|
|
#define COMM_OPT_ON 1
|
|
#define COMM_OPT_OFF 0
|
|
#define COMM_SEND_QUEUE_WITH_DPDP_MPSC COMM_OPT_OFF
|
|
|
|
/***********************************************************************************
|
|
* Socket function related interface and data structures
|
|
***********************************************************************************
|
|
*/
|
|
/*
|
|
* Notice:
|
|
* 1. only proxy conns have comm_sock_desc struct to save infos
|
|
* 2. kernel proxy and libnet proxy maybe both used, eg. some communicators use libnet, other communicators use kernel
|
|
* 3. if epoll fd is proxy, its listen fd can be noproxy fd but must be same phy_proto_type
|
|
*/
|
|
typedef enum CommConnType {
|
|
CommConnKernel = 0,
|
|
CommConnLibnet,
|
|
/* proxy conn may have different protocol type */
|
|
CommConnProxy,
|
|
CommConnMax
|
|
} CommConnType;
|
|
extern CommConnType CommGetConnType(int sockfd);
|
|
|
|
#define AmIProxyModeType(t) (t == CommConnProxy)
|
|
#define AmISupportProxyMode() (g_comm_controller != NULL)
|
|
/* for some storage socket api, we not support with proxy and libnet mode */
|
|
#define AmINoKernelModeSockfd(fd) (CommGetConnType(fd) != CommConnKernel)
|
|
#define AmIProxyModeSockfd(fd) (CommGetConnType(fd) == CommConnProxy)
|
|
|
|
#define AmIKernelModeSockfd(fd) (CommGetConnType(fd) == CommConnKernel)
|
|
#define AmILibnetNoProxyModeSockfd(fd) (CommGetConnType(fd) == CommConnLibnet)
|
|
|
|
extern void comm_init_api_hook();
|
|
|
|
extern CommSocketOption *CommGetConnOption();
|
|
extern void CommSetConnOption(CommConnSocketRole role, CommConnAttr attr, CommConnNumaMap map, int group_id);
|
|
extern void CommSetEpollOption(CommEpollType type);
|
|
extern void CommSetPollOption(bool no_proxy, bool no_ctx_switch, int threshold);
|
|
extern CommPollOption *CommGetPollOption();
|
|
|
|
extern void CommFilterOptionByIpPort(char *ip, int port, CommSocketOption *option);
|
|
|
|
extern int comm_socket(int domain, int type, int protocol);
|
|
extern int comm_connect(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
|
|
extern int comm_bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
|
|
extern int comm_listen(int sockfd, int backlog);
|
|
extern int comm_accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen);
|
|
extern int comm_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
|
|
|
|
extern int comm_close(int sockfd);
|
|
extern int comm_closesocket(int sockfd);
|
|
extern int comm_shutdown(int sockfd, int how);
|
|
extern int comm_setsockopt(int sockfd, int level, int option_name, const void* option_value, socklen_t option_len);
|
|
extern int comm_getsockopt(int sockfd, int level, int option_name, void* option_value, socklen_t* option_len);
|
|
extern int comm_getpeername(int sockfd, struct sockaddr* addr, socklen_t* addrlen);
|
|
extern int comm_gethostname(char* hostname, size_t size);
|
|
extern int comm_getsockname(int sockfd, struct sockaddr* addr, socklen_t* addrlen);
|
|
extern int comm_ioctl(int fd, int request, ...);
|
|
extern int comm_fcntl(int fd, int request, long arg = 0);
|
|
|
|
/* IO api */
|
|
extern ssize_t comm_read(int sockfd, void* buf, size_t count);
|
|
extern ssize_t comm_write(int sockfd, const void* buf, size_t count);
|
|
extern ssize_t comm_send(int sockfd, const void* buf, size_t len, int flags = 0);
|
|
extern ssize_t comm_recv(int sockfd, void* buf, size_t len, int flags = 0);
|
|
|
|
extern ssize_t comm_sendto(
|
|
int sockfd, const void* buf, size_t len, int flags, const struct sockaddr* dest_addr, socklen_t addrlen);
|
|
extern ssize_t comm_recvfrom(
|
|
int sockfd, void* buf, size_t len, int flags, struct sockaddr* src_addr, socklen_t* addrlen);
|
|
|
|
extern ssize_t comm_sendmsg(int sockfd, const struct msghdr* msg, int flags);
|
|
extern ssize_t comm_recvmsg(int sockfd, struct msghdr* msg, int flags);
|
|
|
|
/* select & poll api */
|
|
extern int comm_poll(struct pollfd* fds, nfds_t nfds, int timeout);
|
|
extern int comm_select(int fds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout);
|
|
|
|
/* epoll api */
|
|
extern int comm_epoll_create(int size);
|
|
extern int comm_epoll_create1(int flag);
|
|
extern int comm_epoll_ctl(int epfd, int op, int fd, struct epoll_event* event);
|
|
extern int comm_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout);
|
|
extern int comm_epoll_pwait(int epfd, struct epoll_event* events, int maxevents, int timeout, const sigset_t *sigmask);
|
|
|
|
|
|
/* gaussdb kernel and gaussdbnetwork */
|
|
typedef pthread_t ThreadId;
|
|
|
|
|
|
/***********************************************************************************
|
|
* Start comm library related interface and data structures
|
|
***********************************************************************************
|
|
*/
|
|
typedef enum ErrorLevel {
|
|
COMM_DEBUG2 = 0,
|
|
COMM_DEBUG1 = 1,
|
|
COMM_DEBUG_DESC = 2,
|
|
COMM_INFO = 3,
|
|
COMM_INFO_DESC = 4,
|
|
COMM_LOG = 5,
|
|
COMM_WARNING = 6,
|
|
COMM_ERROR = 7,
|
|
|
|
ERROR_MAX
|
|
} ErrorLevel;
|
|
|
|
extern ErrorLevel min_debug_level;
|
|
|
|
#define MAX_LTRAN_CLIENT 4
|
|
#define LOCAL_PORT_NUM 2
|
|
#define COMM_DEBUG COMM_DEBUG1
|
|
#define MAX_CONTINUOUS_COUNT 10
|
|
#define INIT_TX_ALLOC_BUFF_NUM 5
|
|
|
|
#ifndef WITH_OPENEULER_OS
|
|
extern int gettimeofday(struct timeval* tp, struct timezone* tzp);
|
|
#endif
|
|
//extern THR_LOCAL knl_thrd_context t_thrd;
|
|
|
|
#define COMM_ELOG(elevel, format, ...) \
|
|
do { \
|
|
if (elevel < min_debug_level) { \
|
|
break; \
|
|
} \
|
|
struct timeval tv; \
|
|
pg_time_t stamp_time; \
|
|
(void)gettimeofday(&tv, NULL); \
|
|
stamp_time = (pg_time_t) tv.tv_sec; \
|
|
const char* tag = NULL; \
|
|
char _out_buff[2048]; \
|
|
switch (elevel) { \
|
|
case COMM_DEBUG2: \
|
|
tag = "DEBUG2"; \
|
|
break; \
|
|
case COMM_DEBUG: \
|
|
tag = "DEBUG"; \
|
|
break; \
|
|
case COMM_INFO: \
|
|
tag = "INFO"; \
|
|
break; \
|
|
case COMM_LOG: \
|
|
tag = "LOG"; \
|
|
break; \
|
|
case COMM_WARNING: \
|
|
tag = "WARNING"; \
|
|
break; \
|
|
case COMM_ERROR: \
|
|
tag = "ERROR"; \
|
|
break; \
|
|
case COMM_DEBUG_DESC: \
|
|
tag = ""; \
|
|
break; \
|
|
case COMM_INFO_DESC: \
|
|
tag = ""; \
|
|
break; \
|
|
default: \
|
|
tag = "UNKNOW"; \
|
|
} \
|
|
if (strlen(tag) == 0) { \
|
|
printf(format, ##__VA_ARGS__); \
|
|
} else { \
|
|
sprintf(_out_buff, "[COMMPROXY] "); \
|
|
sprintf(_out_buff + 12, "%7s: ", tag); \
|
|
sprintf(_out_buff + 21, "%18lu ", t_thrd.proc_cxt.MyProcPid); \
|
|
if (session_timezone != NULL) { \
|
|
(void)pg_strftime(_out_buff + 40, 128, "%Y-%m-%d %H:%M:%S %Z ", pg_localtime(&stamp_time, session_timezone)); \
|
|
sprintf(_out_buff + 40 + 19, ".%03d ", (int)(tv.tv_usec / 1000)); \
|
|
} \
|
|
sprintf(_out_buff + 40 + 24, format, ##__VA_ARGS__);\
|
|
printf("%s", _out_buff); \
|
|
} \
|
|
fflush(stdout); \
|
|
} while (0)
|
|
|
|
#define MAX_LTRAN_CORE_NUM 2
|
|
#define MAX_PROXY_CORE_NUM 8
|
|
#define CPU_NUM_PER_NUMA 2
|
|
|
|
#define MAX_PORT_NUM 4
|
|
#define THREADPOOL_TOTAL_GROUP 8
|
|
#define THREADPOOL_GROUPIRQ_NUMBER 4
|
|
#define THREADPOOL_GROUPCPU_NUMBER 32
|
|
#define THREADPOOL_TOTAL_CPU_NUMBER (THREADPOOL_GROUPCPU_NUMBER * THREADPOOL_TOTAL_GROUP)
|
|
|
|
#define THREADPOOL_TOTAL_WORKER_NUMBER (28 * 4 * 2)
|
|
|
|
#define MAX_SERVING_WORKERS 1024
|
|
#define MAX_LSTACK_CONF 256
|
|
|
|
#define DEFAULT_WORKER_BIND_MODE BIND_CPU_MODE_GROUP
|
|
#define MAX_STAT_PACKET_LENGTH (128 * 1024 * 1024)
|
|
|
|
#define MAX_IP_POR_STR_LEN 50
|
|
#define MAX_FILTER_NUM 10
|
|
#define MAX_FILTER_STR_LEN 30
|
|
typedef struct CommProxyFilter {
|
|
bool s_isvaild;
|
|
char s_noproxy[MAX_FILTER_NUM][MAX_FILTER_STR_LEN];
|
|
int s_noproxy_num;
|
|
} CommProxyFilter;
|
|
|
|
/*
|
|
* cpu core number start with 1, like as htop, we use 0 as invalid
|
|
* but user set config with 0-127, we add 1 when parse config
|
|
*/
|
|
typedef struct CommProxyInstance {
|
|
/* read from config file */
|
|
int s_comm_type;
|
|
int s_comms[THREADPOOL_TOTAL_GROUP][MAX_PROXY_CORE_NUM];
|
|
char s_listen[MAX_FILTER_NUM][MAX_FILTER_STR_LEN];
|
|
char s_connect[MAX_FILTER_NUM][MAX_FILTER_STR_LEN];
|
|
|
|
/* generate by rules */
|
|
int s_comm_nums;
|
|
int s_listen_cnt;
|
|
int s_connect_cnt;
|
|
CommConnNumaMap s_gen_numa_map;
|
|
} CommProxyInstance;
|
|
|
|
typedef struct CommPureInstance {
|
|
int s_comm_type;
|
|
int s_comm_node; /* pure connect is single thread, we bind to node rather than core */
|
|
char s_listen[MAX_FILTER_NUM][MAX_FILTER_STR_LEN];
|
|
char s_connect[MAX_FILTER_NUM][MAX_FILTER_STR_LEN];
|
|
|
|
/* generate by rules */
|
|
int s_listen_cnt;
|
|
int s_connect_cnt;
|
|
CommConnNumaMap s_gen_numa_map;
|
|
} CommPureInstance;
|
|
|
|
typedef struct CommLstackConfig {
|
|
char lstack_conf[MAX_LSTACK_CONF];
|
|
int local_port[LOCAL_PORT_NUM];
|
|
bool start_ltran;
|
|
int ltran_num;
|
|
int ltran_node[MAX_LTRAN_CLIENT];
|
|
int ltran_cores[MAX_LTRAN_CLIENT][2]; /* per ltran needs up/down 2 cores */
|
|
} CommLstackConfig;
|
|
|
|
typedef enum CommSendXlogMode {
|
|
CommSendXlogNormal = 0,
|
|
CommSendXlogWaitIn,
|
|
CommSendXlogProxy
|
|
} CommSendXlogMode;
|
|
typedef struct CommProxyConfig {
|
|
int s_comm_type;
|
|
bool s_enable_libnet;
|
|
int s_debug_level;
|
|
bool s_enable_dfx;
|
|
|
|
CommLstackConfig s_comm_lstack_config;
|
|
int s_comm_proxy_group_cnt;
|
|
int s_numa_num;
|
|
CommProxyInstance s_comm_proxy_groups[MAX_COMM_PROXY_GROUP_CNT];
|
|
|
|
int s_comm_pure_group_cnt;
|
|
CommPureInstance s_comm_pure_groups[MAX_COMM_PURE_GROUP_CNT];
|
|
|
|
char s_repl_direct_conn[MAX_FILTER_STR_LEN];
|
|
|
|
bool s_bypass_standby_flush;
|
|
|
|
/*
|
|
* 0: normal mode
|
|
* 1: send_all_data_mode
|
|
* 2: proxy mode
|
|
*/
|
|
int s_send_xlog_mode;
|
|
} CommProxyConfig;
|
|
|
|
typedef struct CoreBindConfig {
|
|
bool enable_libnet;
|
|
bool start_ltran;
|
|
int numa_node[MAX_LTRAN_CLIENT];
|
|
char lstack_conf[MAX_LSTACK_CONF];
|
|
int ltran[MAX_LTRAN_CORE_NUM];
|
|
int comm[THREADPOOL_TOTAL_GROUP][MAX_PROXY_CORE_NUM];
|
|
char worker[THREADPOOL_TOTAL_GROUP][THREADPOOL_GROUPCPU_NUMBER];
|
|
int worker_per_comm;
|
|
int comm_num[THREADPOOL_TOTAL_GROUP];
|
|
int ltran_num;
|
|
int worker_num[THREADPOOL_TOTAL_GROUP];
|
|
ErrorLevel debug_level;
|
|
int ltran_client_num;
|
|
int local_port[LOCAL_PORT_NUM];
|
|
|
|
/* temp config */
|
|
char repl_direct_conn[MAX_FILTER_STR_LEN];
|
|
} CoreBindConfig;
|
|
|
|
typedef struct ThreadAttr {
|
|
int s_threads_num;
|
|
int s_group_num;
|
|
} ThreadAttr;
|
|
|
|
typedef struct CommProxyInvokeResult {
|
|
int s_ret;
|
|
} CommProxyInvokeResult;
|
|
|
|
extern CoreBindConfig g_core_bind_config;
|
|
extern CommProxyConfig g_comm_proxy_config;
|
|
|
|
extern bool CommProxyNeedSetup();
|
|
extern bool IsCommProxyStartUp();
|
|
extern void CommProxyStartUp();
|
|
|
|
extern void ParseThreadPoolAttr(ThreadAttr *thread_attr);
|
|
extern bool ParseCommProxyAttr(CommProxyConfig* config);
|
|
|
|
extern int CommLibNetPrepareEnv();
|
|
extern int CommCheckLtranProcess();
|
|
|
|
/***********************************************************************************
|
|
* Base data type define and atomic interface related
|
|
***********************************************************************************
|
|
*/
|
|
//extern bool g_start_ltran_ctl
|
|
typedef unsigned int uint32;
|
|
typedef signed int int32;
|
|
extern uint64 comm_atomic_add_fetch_u64(volatile uint64* ptr, uint32 inc);
|
|
extern uint32 comm_atomic_add_fetch_u32(volatile uint32* ptr, uint32 inc);
|
|
extern uint64 comm_atomic_fetch_sub_u64(volatile uint64* ptr, uint32 inc);
|
|
extern uint32 comm_atomic_fetch_sub_u32(volatile uint32* ptr, uint32 inc);
|
|
extern uint64 comm_atomic_read_u64(volatile uint64* ptr);
|
|
extern uint32 comm_atomic_read_u32(volatile uint32* ptr);
|
|
extern void comm_atomic_wirte_u32(volatile uint32* ptr, uint32 val);
|
|
extern bool comm_compare_and_swap_32(volatile int32* dest, int32 oldval, int32 newval);
|
|
|
|
#if defined(__aarch64__)
|
|
#define gaussdb_memory_barrier_dsb(opt) __asm__ __volatile__("DMB " #opt::: "memory")
|
|
#define gaussdb_memory_barrier() gaussdb_memory_barrier_dsb(ish)
|
|
#define gaussdb_read_barrier() gaussdb_memory_barrier_dsb(ishld)
|
|
#define gaussdb_write_barrier() gaussdb_memory_barrier_dsb(ishst)
|
|
|
|
#if defined (__USE_NUMA)
|
|
#define gaussdb_numa_memory_bind(i) \
|
|
do { \
|
|
struct bitmask *nodeMask = numa_allocate_nodemask(); \
|
|
numa_bitmask_setbit(nodeMask, (i)); \
|
|
numa_bind(nodeMask); \
|
|
numa_free_nodemask(nodeMask); \
|
|
} while (0);
|
|
|
|
#define gaussdb_numa_memory_unbind() \
|
|
do { \
|
|
numa_bind(numa_all_nodes_ptr); \
|
|
} while (0);
|
|
#else
|
|
#define gaussdb_numa_memory_bind(i)
|
|
#define gaussdb_numa_memory_unbind()
|
|
#endif
|
|
|
|
#elif defined(__x86_64__)
|
|
#define gaussdb_memory_barrier() \
|
|
__asm__ __volatile__ ("lock; addl $0,0(%%rsp)" : : : "memory")
|
|
|
|
#define gaussdb_read_barrier() gaussdb_memory_barrier()
|
|
#define gaussdb_write_barrier() gaussdb_memory_barrier()
|
|
|
|
#define gaussdb_numa_memory_bind(i)
|
|
#define gaussdb_numa_memory_unbind()
|
|
|
|
#elif defined(__i386__)
|
|
#define gaussdb_memory_barrier() \
|
|
__asm__ __volatile__ ("lock; addl $0,0(%%esp)" : : : "memory")
|
|
|
|
#define gaussdb_numa_memory_bind(i)
|
|
#define gaussdb_numa_memory_unbind()
|
|
|
|
#else
|
|
#define gaussdb_memory_barrier()
|
|
|
|
#define gaussdb_numa_memory_bind(i)
|
|
#define gaussdb_numa_memory_unbind()
|
|
|
|
#endif
|
|
|
|
|
|
#define WaitCondPositive(cond, interval) \
|
|
{ \
|
|
while (!(cond)) { \
|
|
pg_usleep(interval); \
|
|
} \
|
|
}
|
|
|
|
#define WaitCondPositiveWithTimeout(cond, interval, timeout) \
|
|
{ \
|
|
int timegap = 0; \
|
|
while (!(cond)) { \
|
|
pg_usleep(interval); \
|
|
timegap += interval; \
|
|
if (timegap >= timeout) { \
|
|
break; \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
|
|
#define MAX_PROXY_THREAD_NUMS 64
|
|
#define PROXY_RET_OK 0
|
|
#define PROXY_RET_FAIL 1
|
|
#define PROXY_RET_NOTIMPL 2
|
|
|
|
#define comm_static_set(x, v) \
|
|
do { \
|
|
(x) = (v); \
|
|
} while (0);
|
|
|
|
#define comm_static_inc(x) \
|
|
do { \
|
|
(x)++; \
|
|
} while (0);
|
|
|
|
#define comm_static_dec(x) \
|
|
do { \
|
|
(x)--; \
|
|
} while (0);
|
|
|
|
#define comm_static_add(x, v) \
|
|
do { \
|
|
(x) = (x) + (v); \
|
|
} while (0);
|
|
|
|
#define comm_static_sub(x, v) \
|
|
do { \
|
|
(x) = (x) - (v); \
|
|
} while (0);
|
|
|
|
#define comm_static_atomic_inc(x) \
|
|
do { \
|
|
comm_atomic_add_fetch_u32((x), 1); \
|
|
} while (0)
|
|
|
|
#define comm_static_atomic_dec(x) \
|
|
do { \
|
|
comm_atomic_fetch_sub_u32((x), 1); \
|
|
} while (0)
|
|
|
|
#define comm_static_atomic_get(x) \
|
|
comm_atomic_read_u32((x))
|
|
|
|
#define init_req_static(req) \
|
|
do { \
|
|
(req)->s_prepare_num = 0; \
|
|
(req)->s_ready_num = 0; \
|
|
(req)->s_endnum = 0; \
|
|
(req)->s_skipped_num = 0; \
|
|
} while (0);
|
|
|
|
#define COMM_DEBUG_EXEC(x) x;
|
|
|
|
|
|
typedef struct {
|
|
int (*socket_fn)(int domain, int type, int protocol);
|
|
int (*accept_fn)(int s, struct sockaddr*, socklen_t*);
|
|
int (*accept4_fn)(int s, struct sockaddr*, socklen_t*, int flags);
|
|
int (*bind_fn)(int s, const struct sockaddr*, socklen_t);
|
|
int (*listen_fn)(int s, int backlog);
|
|
int (*connect_fn)(int s, const struct sockaddr* name, socklen_t namelen);
|
|
int (*getpeername_fn)(int s, struct sockaddr* name, socklen_t* namelen);
|
|
int (*getsockname_fn)(int s, struct sockaddr* name, socklen_t* namelen);
|
|
int (*setsockopt_fn)(int s, int level, int optname, const void* optval, socklen_t optlen);
|
|
int (*getsockopt_fn)(int s, int level, int optname, void* optval, socklen_t* optlen);
|
|
int (*close_fn)(int fd);
|
|
int (*shutdown_fn)(int fd, int how);
|
|
pid_t (*fork_fn)(void);
|
|
ssize_t (*read_fn)(int fd, void* mem, size_t len);
|
|
ssize_t (*write_fn)(int fd, const void* data, size_t len);
|
|
int (*fcntl_fn)(int fd, int cmd, ...);
|
|
int (*epoll_create_fn)(int size);
|
|
int (*epoll_create1_fn)(int flags);
|
|
int (*epoll_ctl_fn)(int epfd, int op, int fd, struct epoll_event* event);
|
|
int (*epoll_wait_fn)(int epfd, struct epoll_event* events, int maxevents, int timeout);
|
|
int (*epoll_pwait_fn)(int epfd, struct epoll_event* events, int maxevents, int timeout, const sigset_t *sigmask);
|
|
int (*sigaction_fn)(int signum, const struct sigaction* act, struct sigaction* oldact);
|
|
int (*poll_fn)(struct pollfd* fds, nfds_t nfds, int timeout);
|
|
ssize_t (*send_fn)(int sockfd, const void* buf, size_t len, int flags);
|
|
ssize_t (*recv_fn)(int sockfd, void* buf, size_t len, int flags);
|
|
ssize_t (*addr_recv_fn)(int sockfd, void* buf, size_t len, int flags);
|
|
} gs_api_t;
|
|
|
|
extern const gs_api_t g_comm_socket_api[CommConnMax];
|
|
|
|
typedef enum IPAddrType {
|
|
IpAddrTypeAny = 0,
|
|
IpAddrTypeLoopBack = 1,
|
|
IpAddrTypeBroadCast = 2,
|
|
IpAddrTypeLocal = 3,
|
|
IpAddrTypeOther = 4
|
|
} IPAddrType;
|
|
|
|
typedef enum CommFdTypeOpt {
|
|
CommFdTypeSetHostOrLibnet = 0,
|
|
CommFdTypeSetHost = 1,
|
|
CommFdTypeSetLibNet = 2,
|
|
CommFdTypeAddInprogress = 3,
|
|
CommFdTypeDelHost = 4,
|
|
} CommFdType;
|
|
|
|
typedef enum CommQueueChannel {
|
|
ChannelTX = 0,
|
|
ChannelRX,
|
|
|
|
/* Indicate the max number */
|
|
TotalChannel
|
|
} CommQueueChannel;
|
|
|
|
typedef enum CommExecStep {
|
|
comm_exec_step_uninit = 0,
|
|
comm_exec_step_start,
|
|
comm_exec_step_prepare,
|
|
comm_exec_step_process,
|
|
comm_exec_step_ready,
|
|
comm_exec_step_done,
|
|
} CommExecStep;
|
|
|
|
typedef enum CommWaitNextStatus {
|
|
CommWaitNextContinue = 0,
|
|
CommWaitNextBreak
|
|
} CommWaitNextStatus;
|
|
|
|
typedef enum SocketRequestType {
|
|
sockreq_socket = 1,
|
|
sockreq_close,
|
|
|
|
sockreq_accept,
|
|
sockreq_accept4,
|
|
sockreq_poll,
|
|
sockreq_select,
|
|
sockreq_bind,
|
|
sockreq_listen,
|
|
sockreq_setsockopt,
|
|
sockreq_getsockopt,
|
|
sockreq_getsockname,
|
|
sockreq_getpeername,
|
|
sockreq_fcntl,
|
|
sockreq_epoll_create,
|
|
sockreq_epollctl,
|
|
sockreq_epollwait,
|
|
sockreq_recv,
|
|
sockreq_send,
|
|
sockreq_connect,
|
|
sockreq_shutdown,
|
|
sockreq_max
|
|
} SocketRequestType;
|
|
|
|
typedef enum SocketHookType {
|
|
socket_hook_before,
|
|
socket_hook_after,
|
|
socket_hook_max
|
|
} SocketHookType;
|
|
|
|
typedef enum CommProxyerStatus {
|
|
CommProxyerUninit = 0,
|
|
CommProxyerStart,
|
|
CommProxyerReady,
|
|
CommProxyerError,
|
|
CommProxyerClosing,
|
|
CommProxyerDie
|
|
} CommProxyerStatus;
|
|
|
|
/*
|
|
* Communicator data structures forward declaration
|
|
*/
|
|
class CommSockDesc;
|
|
class ThreadPoolCommunicator;
|
|
struct Packet;
|
|
struct SocketRequest;
|
|
|
|
/*
|
|
* Communicator Event definition
|
|
*/
|
|
typedef enum EventType {
|
|
EventUknown = -1,
|
|
EventRecv,
|
|
EventListen,
|
|
EventOut,
|
|
EventThreadPoolListen,
|
|
} EventType;
|
|
|
|
typedef struct EventDataHeader {
|
|
volatile int s_event_type;
|
|
|
|
/* for datafd to listener/recv */
|
|
CommSockDesc* s_sock;
|
|
CommSockDesc* s_listener;
|
|
epoll_data_t s_origin_event_data_ptr;
|
|
uint32 s_origin_events;
|
|
bool s_epoll_oneshot_active;
|
|
} EventDataHeader;
|
|
|
|
#define CommConnTypeShift 2
|
|
typedef enum EpollInputStatus {
|
|
/* if epoll fd is kernel mode, we only support listen kernel fd */
|
|
epoll_kernel_fd_kernel = CommConnKernel << CommConnTypeShift | CommConnKernel,
|
|
|
|
/* if epoll fd is kernel proxy fd, we can listen kernel fd or kernel proxy fd */
|
|
epoll_proxy_fd_kernel = CommConnProxy << CommConnTypeShift | CommConnKernel,
|
|
epoll_proxy_fd_kernel_proxy = CommConnProxy << CommConnTypeShift | CommConnProxy,
|
|
|
|
/* if epoll fd is libnet fd, we only support listen libnet fd */
|
|
epoll_libnet_fd_libnet = CommConnLibnet << CommConnTypeShift | CommConnLibnet,
|
|
} EpollInputStatus;
|
|
|
|
/***********************************************************************************
|
|
* CommAdapter related data structures
|
|
***********************************************************************************
|
|
*/
|
|
typedef void (*CommProcessSendFuncPtr)(ThreadPoolCommunicator *comm);
|
|
|
|
typedef int (*CommWorkerSendFuncPtr)(CommSockDesc* comm_sock, const char* buffer, int length);
|
|
typedef void (*CommProxySendFuncPtr)(ThreadPoolCommunicator *comm);
|
|
typedef int (*CommWorkerRecvFuncPtr)(CommSockDesc* sock_desc, char *buffer, int exp_length);
|
|
typedef void (*CommProxyRecvFuncPtr)(CommSockDesc* sock_desc);
|
|
|
|
typedef struct CommTransporter {
|
|
CommWorkerSendFuncPtr comm_worker_send;
|
|
CommProxySendFuncPtr comm_proxy_send;
|
|
CommWorkerRecvFuncPtr comm_worker_recv;
|
|
CommProxyRecvFuncPtr comm_proxy_recv;
|
|
} CommTransporter;
|
|
|
|
typedef enum CommTransportMode {
|
|
CommModeDefault = 0,
|
|
CommModeDoubleQueue,
|
|
CommModeRingBuffer,
|
|
} CommTransportMode;
|
|
|
|
typedef enum CommEpollMode {
|
|
CommEpollModeWakeup = 0,
|
|
CommEpollModeSockList,
|
|
} CommEpollMode;
|
|
|
|
typedef enum CommProxyNotifyMode {
|
|
CommProxyNotifyModeSem = 0,
|
|
CommProxyNotifyModeSpinLoop,
|
|
CommProxyNotifyModePolling,
|
|
} CommProxyNotifyMode;
|
|
|
|
typedef enum CommProxySendMode {
|
|
CommProxySendModeReadyQueue = 0,
|
|
CommProxySendModePolling,
|
|
} CommProxySendMode;
|
|
|
|
typedef enum SendStatus {
|
|
SendStatusReady = 0,
|
|
SendStatusPart,
|
|
SendStatusError,
|
|
SendStatusSuccess
|
|
} SockSendStatus;
|
|
typedef enum SockRecvStatus {
|
|
RecvStatusReady = 0,
|
|
RecvStatusClose,
|
|
RecvStatusRetry,
|
|
RecvStatusError,
|
|
RecvStatusSuccess
|
|
} SockRecvStatus;
|
|
|
|
typedef struct CommSockDelay {
|
|
int trigger_nums;
|
|
int cur_delay_time;
|
|
int max_trigger_nums;
|
|
int min_trigger_nums;
|
|
} CommSockDelay;
|
|
|
|
/***********************************************************************************
|
|
* CommSocket related data structures
|
|
***********************************************************************************
|
|
*/
|
|
#define InvalidCommFd -1;
|
|
#define MaxPacketLength 1024
|
|
/* socket buffer 256*1024 */
|
|
#define DefaultSocketRingBufferSize (16 * 1024 * 1024)
|
|
/* ring buffer set max to 128MB, */
|
|
#define MaxSocketRingBufferSize (128 * 1024 * 1024)
|
|
#define MaxPbufNum (65536) //must be 2^n
|
|
|
|
class CommTransPort : public BaseObject
|
|
{
|
|
public:
|
|
int m_fd;
|
|
CommQueueChannel m_type;
|
|
ErrorLevel m_debug_level;
|
|
|
|
public:
|
|
virtual bool CheckBufferEmpty() = 0;
|
|
virtual bool CheckBufferFull() = 0;
|
|
virtual size_t GetBufferDataSize() = 0;
|
|
virtual int GetDataFromBuffer(char* s, size_t length) = 0;
|
|
virtual int PutDataToBuffer(const char *s, size_t length) = 0;
|
|
virtual SendStatus SendDataFromBuffer(int fd, ThreadPoolCommunicator *comm) = 0;
|
|
virtual SockRecvStatus RecvDataToBuffer(int fd, ThreadPoolCommunicator *comm) = 0;
|
|
virtual void PrintBufferDetail(const char *info) = 0;
|
|
virtual bool NeedWait(bool block) = 0;
|
|
virtual void WaitBufferEmpty() = 0;
|
|
virtual void Init(int fd, CommQueueChannel type) = 0;
|
|
virtual void DeInit() = 0;
|
|
|
|
CommTransPort() {};
|
|
virtual ~CommTransPort() {};
|
|
};
|
|
|
|
typedef enum TransportStatus {
|
|
TransportNormal = 0,
|
|
TransportBusy,
|
|
TransportChange,
|
|
TransportChangeDone
|
|
} TransportStatus;
|
|
|
|
typedef struct RingBufferGroup {
|
|
char *m_comm_buffer;
|
|
volatile uint32_t m_comm_buffer_size;
|
|
volatile uint32_t m_read_pointer;
|
|
volatile uint32_t m_write_pointer;
|
|
} RingBufferGroup;
|
|
|
|
class CommRingBuffer: public CommTransPort
|
|
{
|
|
public:
|
|
RingBufferGroup *m_buffer;
|
|
RingBufferGroup *m_enlarge_buffer;
|
|
|
|
pthread_mutex_t m_mutex;
|
|
pthread_cond_t m_cv;
|
|
bool m_isempty;
|
|
volatile TransportStatus m_status;
|
|
CommSockDelay m_delay;
|
|
/* proxyer notify worker to recv/send data */
|
|
CommProxyNotifyMode m_notify_mode;
|
|
|
|
public:
|
|
CommRingBuffer();
|
|
~CommRingBuffer();
|
|
void Init(int fd, CommQueueChannel type);
|
|
void DeInit();
|
|
bool CheckBufferEmpty();
|
|
bool CheckBufferFull();
|
|
size_t GetBufferFreeBytes(int r, int w, int size);
|
|
size_t GetBufferDataSize();
|
|
int CopyDataFromBuffer(char* s, size_t length, size_t offset);
|
|
int GetDataFromBuffer(char* s, size_t length);
|
|
int PutDataToBuffer(const char *s, size_t length);
|
|
SendStatus SendDataFromBuffer(int fd, ThreadPoolCommunicator *comm);
|
|
SockRecvStatus RecvDataToBuffer(int fd, ThreadPoolCommunicator *comm);
|
|
void PrintBufferDetail(const char *info);
|
|
bool NeedWait(bool block);
|
|
void NotifyWorker(SockRecvStatus rtn_status);
|
|
void WaitBufferEmpty();
|
|
void SetNotifyMode(CommProxyNotifyMode mode);
|
|
bool EnlargeBufferSize(uint32 length);
|
|
|
|
inline void ResetDelay()
|
|
{
|
|
m_delay.cur_delay_time = 0;
|
|
};
|
|
};
|
|
|
|
#ifdef USE_LIBNET
|
|
class CommRingBufferLibnet: public CommRingBuffer
|
|
{
|
|
public:
|
|
uint32_t m_buffaddr_pointer;
|
|
uint32_t m_curre_buff_num;
|
|
uint32_t m_minus_buff_num_counter;
|
|
uint32_t m_local_read_pointer;
|
|
volatile uint32_t m_curr_data_len;
|
|
struct pkt_buff_info *m_comm_buffer;
|
|
|
|
public:
|
|
CommRingBufferLibnet();
|
|
~CommRingBufferLibnet();
|
|
void Init(int fd, CommQueueChannel type);
|
|
void DeInit();
|
|
size_t GetBufferDataSize();
|
|
void CommReleaseUsedBuff(void *mem);
|
|
int CopyDataFromBuffer(char* s, size_t length, size_t offset);
|
|
int GetDataFromBuffer(char* s, size_t length);
|
|
int PutDataToBuffer(const char *s, size_t length);
|
|
SendStatus SendDataFromBuffer(int fd, ThreadPoolCommunicator *comm);
|
|
SockRecvStatus RecvDataToBuffer(int fd, ThreadPoolCommunicator *comm);
|
|
};
|
|
#endif
|
|
|
|
class CommPacketBuffer: public CommTransPort
|
|
{
|
|
public:
|
|
boost::lockfree::queue<Packet *> *m_data_queue;
|
|
Packet* m_recv_packet;
|
|
sem_t m_data_queue_sem;
|
|
|
|
public:
|
|
CommPacketBuffer();
|
|
~CommPacketBuffer();
|
|
void Init(int fd, CommQueueChannel type);
|
|
void DeInit();
|
|
|
|
public:
|
|
bool CheckBufferEmpty();
|
|
bool CheckBufferFull();
|
|
size_t GetBufferFreeBytes(int r, int w);
|
|
size_t GetBufferDataSize();
|
|
int GetDataFromBuffer(char* s, size_t length);
|
|
int PutDataToBuffer(const char *s, size_t length);
|
|
SendStatus SendDataFromBuffer(int fd, ThreadPoolCommunicator *comm);
|
|
SockRecvStatus RecvDataToBuffer(int fd, ThreadPoolCommunicator *comm);
|
|
void PrintBufferDetail(const char *info);
|
|
bool NeedWait(bool block);
|
|
void WaitBufferEmpty();
|
|
|
|
public:
|
|
inline Packet* GetHeadPacket()
|
|
{
|
|
Packet *pkt_point = NULL;
|
|
m_data_queue->pop(pkt_point);
|
|
if (pkt_point == NULL) {
|
|
return NULL;
|
|
}
|
|
return pkt_point;
|
|
};
|
|
|
|
inline void PopHeadPacket()
|
|
{
|
|
Packet *p = NULL;
|
|
m_data_queue->pop(p);
|
|
};
|
|
|
|
inline Packet* RemoveHeadPacket()
|
|
{
|
|
Packet* p = NULL;
|
|
if (m_data_queue->pop(p)) {
|
|
return p;
|
|
}
|
|
|
|
return NULL;
|
|
};
|
|
|
|
inline void AddTailPacket(Packet* p)
|
|
{
|
|
m_data_queue->push(p);
|
|
};
|
|
|
|
private:
|
|
void BackPktBuff(Packet* pack);
|
|
void ClearQueuePacket();
|
|
};
|
|
|
|
typedef enum CommSockType {
|
|
/* For report error */
|
|
CommSockUnknownType = -1,
|
|
|
|
/* Operates at server side */
|
|
CommSockServerFd, /* returned by comm_socket() */
|
|
CommSockEpollFd, /* returned by comm_epoll_create() */
|
|
CommSockServerDataFd, /* returned by comm_poll()/comm_accept()/comm_connect() */
|
|
|
|
/* communicator library internal type */
|
|
CommSockCommEpollFd,
|
|
CommSockCommServerFd,
|
|
|
|
CommSockClientDataFd,
|
|
|
|
CommSockFakeLibosFd,
|
|
} CommSockType;
|
|
|
|
typedef struct CommFdInfoNode {
|
|
int fd;
|
|
int fdNums;
|
|
struct CommFdInfoNode *next;
|
|
} CommFdInfoNode;
|
|
|
|
#define AmCommDataFd(comm_sock) ((comm_sock)->m_fd_type == CommSockClientDataFd || (comm_sock)->m_fd_type == CommSockServerDataFd || (comm_sock)->m_fd_type == CommSockFakeLibosFd)
|
|
#define AmCommServerFd(comm_sock) ((comm_sock)->m_fd_type == CommSockServerFd)
|
|
|
|
#define IgnoreErrorNo(x) ((x) == 0 || (x) == EAGAIN || (x) == EWOULDBLOCK || (x) == EINTR || (x) == EINPROGRESS)
|
|
typedef enum CommSockStatus {
|
|
CommSockStatusUninit = 0, /* created by socket */
|
|
CommSockStatusReady, /* created by connect/accept/bind */
|
|
CommSockStatusListening, /* called by listen */
|
|
CommSockStatusRegistToEpoll, /* called by comm_epoll_ctl add() */
|
|
CommSockStatusRemovedFromEpoll, /* called by comm_epoll_ctl del() */
|
|
CommSockStatusClosedByPeer, /* called by recv return 0 add del from epoll() */
|
|
CommSockStatusClosedBySelf, /* called by comm_close() */
|
|
CommSockStatusNeedRetry,
|
|
CommSockStatusNormal,
|
|
CommSockStatusProcessedData, /* fd has recv/send data */
|
|
CommSockStatusDie,
|
|
CommSockStatusWorkerGetClose
|
|
} CommSockStatus;
|
|
|
|
typedef enum CommSockPollStatus {
|
|
CommSockPollUnRegist = 0,
|
|
CommSockPollRegisted,
|
|
CommSockPollReady,
|
|
} CommSockPollStatus;
|
|
|
|
typedef enum CommSockListenType {
|
|
CommSockListenNone = 0,
|
|
CommSockListenByPoll,
|
|
CommSockListenByEpoll,
|
|
} CommSockListenType;
|
|
|
|
typedef enum CommSockProcessType {
|
|
CommSockProcessInit = 0,
|
|
CommSockProcessProxyRecving,
|
|
CommSockProcessProxyRecvend,
|
|
CommSockProcessProxySending,
|
|
CommSockProcessProxySendend,
|
|
} CommSockProcessType;
|
|
|
|
typedef enum CommSockConnectStatus {
|
|
CommSockConnectUninit = 0,
|
|
CommSockConnectInprogressBlock,
|
|
CommSockConnectInprogressNonBlock,
|
|
CommSockConnectInprogressNonBlockPollListen,
|
|
CommSockConnectSuccess,
|
|
CommSockConnectFail,
|
|
} CommSockConnectStatus;
|
|
#define ConnectEnd(x) ((x) == CommSockConnectSuccess || (x) == CommSockConnectFail)
|
|
|
|
#define COMM_MIN_DELAY_USEC 10
|
|
#define COMM_MAX_DELAY_USEC 100000
|
|
typedef struct CommSockNode {
|
|
CommSockDesc *s_comm_sock;
|
|
struct CommSockNode *s_next_node;
|
|
struct CommSockNode *s_prev_node;
|
|
} CommSockNode;
|
|
|
|
class CommSockList : public BaseObject {
|
|
public:
|
|
List* m_sock_list;
|
|
CommSockDesc *m_comm_epoll_sock;
|
|
|
|
public:
|
|
CommSockList(CommSockDesc *epoll_sock);
|
|
~CommSockList();
|
|
|
|
void addCommSock(CommSockDesc *comm_sock);
|
|
void delCommSock(CommSockDesc *_comm_sock);
|
|
int getCommEpollEvents(struct epoll_event* events, int events_num);
|
|
bool findCommSock(bool with_lock, int fd);
|
|
|
|
private:
|
|
pthread_mutex_t m_mutex;
|
|
};
|
|
|
|
/*
|
|
* - brief: CommSockDesc is the backend supporting data structure at Comm-Poroxy,
|
|
* it is searched/located by user side fd as key (s_fd_key), normally, we
|
|
* have several case for CommSockDesc serverfd, epoll_fd, datafd
|
|
*/
|
|
class CommSockDesc : public BaseObject {
|
|
public:
|
|
/* "sock fd" of curernt object served */
|
|
int m_fd;
|
|
|
|
/* type socket the current of CommSockDesc */
|
|
CommSockType m_fd_type;
|
|
ThreadPoolCommunicator* m_communicator; /* valid in datafd */
|
|
int m_group_id; /* valid in epollfd & datafd */
|
|
|
|
CommSockListenType m_listen_type;
|
|
|
|
/* some status maybe happen at sametime, TODO:bit and/or */
|
|
CommSockStatus m_status;
|
|
int m_errno;
|
|
bool m_not_need_del_from_epoll;
|
|
|
|
/*
|
|
* for datafd, if accept, parent is serverfd
|
|
* if connect, parent is null
|
|
* for internal serverfd, parent is logical serverfd
|
|
* for logical serverfd and epoll fd, parent is null
|
|
*/
|
|
CommSockDesc *m_parent_comm_sock;
|
|
|
|
/****
|
|
* - brief: CommServerFd maintaince fields
|
|
*/
|
|
int m_server_fd_cnt; /* number of actual fd curernt serverfd contained */
|
|
int* m_server_fd_arrays; /* array of curernt serverfd contained */
|
|
volatile uint32_t m_server_income_ready_num;
|
|
int m_last_index;
|
|
|
|
/****
|
|
* - brief: CommInternalServerFd
|
|
*/
|
|
struct pollfd* m_fds;
|
|
int m_nfds;
|
|
CommSockPollStatus m_poll_status;
|
|
|
|
/****
|
|
* - brief: CommEpollFd maintaince fields
|
|
*/
|
|
boost::lockfree::queue<struct epoll_event*>* m_epoll_queue; /* (n)p(1)c eventg queue */
|
|
volatile uint32 m_events_num;
|
|
sem_t m_epoll_queue_sem; /* PV operation sem */
|
|
/* no-threadpool mode */
|
|
CommSockList *m_epoll_list;
|
|
bool m_need_kernel_call;
|
|
/*
|
|
* epoll get close status by m_status, but m_status we assume it only changed by proxy
|
|
* so we need a flag to avoid catch EPOLLERR event repeat
|
|
* because worker process is async, err will release sock resource, for next process it will core or other exception
|
|
* for EVENTIN/EVENTOUT, if oneshot, we will only catch once
|
|
* if no-oneshot, we catch more than once is normal
|
|
* the reason we set catch flag not remove form m_epoll_list is to be consistent with the kernel call behavior
|
|
*/
|
|
bool m_epoll_catch_error;
|
|
|
|
/*
|
|
* Support a EpollFD at application level registered with proxy-fd and regular fd,
|
|
* We normally see such kind of case in Postmaster's ServerLoop() where unix domain
|
|
* and network-fd(via proxy) is registerred here
|
|
*/
|
|
int m_epoll_real_fd;
|
|
|
|
/****
|
|
* - brief: CommDataFd maintaince fields
|
|
*/
|
|
EventDataHeader m_event_header;
|
|
int m_worker_id;
|
|
bool m_send_idle;
|
|
CommTransPort* m_transport[TotalChannel];
|
|
CommTransportMode m_trans_mode;
|
|
|
|
/* for poll data check */
|
|
unsigned int m_data_threshold[TotalChannel];
|
|
|
|
/* for recv data delay */
|
|
volatile CommSockProcessType m_process;
|
|
bool m_block;
|
|
/* for noblock mode to check connect success */
|
|
std::mutex m_connect_mutex;
|
|
std::condition_variable m_connect_cv;
|
|
CommSockConnectStatus m_connect_status;
|
|
|
|
/*
|
|
* CommProy Dfx support
|
|
* - brief: static per fd s/r packet cnt for each length
|
|
*/
|
|
bool m_enable_packet_static;
|
|
uint64 *m_static_pkt_cnt_by_length[TotalChannel];
|
|
uint64 m_wakeup_cnt;
|
|
|
|
public:
|
|
CommSockDesc();
|
|
virtual ~CommSockDesc();
|
|
void Init(int fd, CommSockType type, ThreadPoolCommunicator* comm, CommSockDesc* parent);
|
|
void DeInit();
|
|
|
|
inline int GetCurrentFd() const
|
|
{
|
|
return m_fd;
|
|
};
|
|
|
|
inline bool CheckActive()
|
|
{
|
|
return (m_worker_id >= 0);
|
|
};
|
|
|
|
inline int GetWorkerId() const
|
|
{
|
|
Assert(m_worker_id >= 0);
|
|
return m_worker_id;
|
|
};
|
|
|
|
inline size_t GetQueueCnt(int channel)
|
|
{
|
|
return m_transport[channel]->GetBufferDataSize();
|
|
};
|
|
|
|
inline void PushEpollEvent(struct epoll_event* listen_event)
|
|
{
|
|
comm_atomic_add_fetch_u32(&m_events_num, 1);
|
|
bool need_post = m_epoll_queue->empty();
|
|
m_epoll_queue->push(listen_event);
|
|
if (need_post) {
|
|
sem_post(&m_epoll_queue_sem);
|
|
}
|
|
};
|
|
|
|
inline struct epoll_event* PopEpollEvent()
|
|
{
|
|
struct epoll_event* ev = NULL;
|
|
bool ret = m_epoll_queue->pop(ev);
|
|
if (ret) {
|
|
Assert(ev != NULL);
|
|
comm_atomic_fetch_sub_u32(&m_events_num, 1);
|
|
}
|
|
|
|
return ev;
|
|
};
|
|
|
|
inline size_t GetEventNums()
|
|
{
|
|
return comm_atomic_read_u32(&m_events_num);
|
|
};
|
|
|
|
/*
|
|
* recv queue we need clear if connection close
|
|
* send queue can not clear, send is async, data should be sent over
|
|
*/
|
|
void ClearSockQueue();
|
|
void WaitQueueEmpty(int channel);
|
|
void BackPktBuff(int channel, Packet* pack);
|
|
|
|
void InitDataStatic();
|
|
void PrintDataStatic();
|
|
void UpdateDataStatic(size_t len, int type);
|
|
|
|
void SetPollThreshold(int channel, int threshold);
|
|
};
|
|
|
|
typedef struct ReqStatic {
|
|
volatile unsigned int s_prepare_num;
|
|
volatile unsigned int s_ready_num;
|
|
volatile unsigned int s_endnum;
|
|
volatile unsigned int s_skipped_num;
|
|
} ReqStatic;
|
|
|
|
/*
|
|
* Users can specify multiple proxy combinations.
|
|
* Each proxy can set different filtering parameters with core config filters
|
|
*/
|
|
class CommController : public BaseObject {
|
|
public:
|
|
ThreadPoolCommunicator** m_communicators[MAX_COMM_PROXY_GROUP_CNT];
|
|
int m_communicator_nums[MAX_COMM_PROXY_GROUP_CNT];
|
|
|
|
ThreadPoolCommunicator** m_special_communicators;
|
|
int m_special_communicator_nums;
|
|
|
|
/* in proxy wait process, controller use poll and epoll wait to be compatible with both realfd and logical fd */
|
|
phy_proto_type_t m_default_proto_type;
|
|
gs_api_t m_default_comm_api;
|
|
|
|
/* Global reference to mapping fd -> CommSockDesc */
|
|
CommSockDesc** m_sockcomm_map_arr;
|
|
|
|
CommTransportMode m_transport_mode;
|
|
|
|
CommEpollMode m_epoll_mode;
|
|
CommProxyNotifyMode m_notify_mode;
|
|
CommProxySendMode m_ready_send_mode;
|
|
|
|
volatile int m_ready_comm_cnt;
|
|
|
|
int m_proxy_recv_loop_cnt;
|
|
int m_proxy_send_loop_cnt;
|
|
|
|
CommProcessSendFuncPtr m_process_send_func;
|
|
|
|
/*
|
|
* CommProxy Dfx Support
|
|
*
|
|
* - brief: statistic information for accept/poll/epoll events
|
|
*/
|
|
ReqStatic m_accept_static;
|
|
ReqStatic m_poll_static;
|
|
ReqStatic m_epoll_recv_static;
|
|
ReqStatic m_epoll_listen_static;
|
|
ReqStatic m_epoll_all_static;
|
|
volatile unsigned int m_active_worker_num;
|
|
|
|
public:
|
|
CommController();
|
|
~CommController();
|
|
|
|
int Init();
|
|
int InitCommProxyGroup(int proxy_id, CommProxyInstance *proxy_instance);
|
|
int GetCommPollEvents( struct pollfd* fdarray, unsigned long nfds, int poll_ready_num);
|
|
void RegistPollEvents( struct pollfd* fdarray, unsigned long nfds);
|
|
void ProxyWaitProcess(SocketRequestType* param);
|
|
|
|
int GetNextDummyFd();
|
|
bool IsServerfd(int fd);
|
|
|
|
int WaitCommReady(int proxy_id);
|
|
void ProxyerStatusReadyCallBack(CommProxyerStatus status);
|
|
|
|
void SetCommSockNotifyMode(int fd, CommProxyNotifyMode mode);
|
|
|
|
void SetCommSockIdle(int sockfd_key);
|
|
void SetCommSockActive(int sockfd_key, int workerid);
|
|
|
|
void BindThreadToGroupExcludeProxy(int fd);
|
|
|
|
ThreadPoolCommunicator* GetCommunicator(int fd);
|
|
ThreadPoolCommunicator* GetCommunicatorByGroup(int proxy_id, int group_id);
|
|
int GetCommSockGroupId(int fd);
|
|
|
|
int CommPollFdMarkSwitch(struct pollfd* fdarray, int nfds);
|
|
|
|
inline CommSockDesc* FdGetCommSockDesc(int sockfd)
|
|
{
|
|
if (sockfd < 0 || !m_sockcomm_map_arr[sockfd] || m_sockcomm_map_arr[sockfd]->m_fd_type == CommSockUnknownType) {
|
|
return NULL;
|
|
}
|
|
|
|
return m_sockcomm_map_arr[sockfd];
|
|
};
|
|
|
|
inline CommSockDesc* const* FdGetCommSockDescPtr(int sockfd)
|
|
{
|
|
if (sockfd < 0 || !m_sockcomm_map_arr[sockfd] || m_sockcomm_map_arr[sockfd]->m_fd_type == CommSockUnknownType) {
|
|
return NULL;
|
|
}
|
|
|
|
return &m_sockcomm_map_arr[sockfd];
|
|
};
|
|
|
|
inline CommSockDesc* FdGetCommSockDescOrigin(int sockfd)
|
|
{
|
|
if (sockfd < 0) {
|
|
return NULL;
|
|
}
|
|
return m_sockcomm_map_arr[sockfd];
|
|
};
|
|
|
|
inline void AddCommSockMap(CommSockDesc* comm)
|
|
{
|
|
int fd = comm->m_fd;
|
|
if (m_sockcomm_map_arr[fd] == NULL) {
|
|
m_sockcomm_map_arr[fd] = comm;
|
|
}
|
|
gaussdb_memory_barrier();
|
|
};
|
|
|
|
inline void DelCommSockMap(CommSockDesc* comm_sock)
|
|
{
|
|
ereport(LOG, (errmodule(MOD_COMM_PROXY), errmsg("delete commsock from map in DelCommSockMap.")));
|
|
int fd = comm_sock->m_fd;
|
|
if (fd < 0 || m_sockcomm_map_arr[fd] == NULL) {
|
|
ereport(ERROR, (errmodule(MOD_COMM_PROXY),
|
|
errcode(ERRCODE_SYSTEM_ERROR),
|
|
errmsg("fd:%d is already deleted or not be created.", fd),
|
|
errdetail("N/A"),
|
|
errcause("System error."),
|
|
erraction("Contact Huawei Engineer.")));
|
|
return;
|
|
}
|
|
m_sockcomm_map_arr[fd] = NULL;
|
|
gaussdb_memory_barrier();
|
|
};
|
|
|
|
private:
|
|
int m_dummy_fd_min;
|
|
int m_dummy_fd_max;
|
|
int m_dummy_fd_next;
|
|
};
|
|
|
|
extern CommController* g_comm_controller;
|
|
|
|
extern int gs_api_init(gs_api_t* gs_api, phy_proto_type_t proto);
|
|
|
|
/* memory api */
|
|
inline void* comm_malloc(size_t size)
|
|
{
|
|
return palloc(size);
|
|
}
|
|
|
|
inline void* comm_malloc0(size_t size)
|
|
{
|
|
return palloc0(size);
|
|
}
|
|
|
|
inline void* comm_repalloc(void* pointer, size_t size)
|
|
{
|
|
return repalloc(pointer, size);
|
|
}
|
|
|
|
#define comm_free(ptr) \
|
|
do { \
|
|
pfree(ptr); \
|
|
} while (0)
|
|
|
|
#define comm_free_ext(ptr) \
|
|
do { \
|
|
pfree(ptr); \
|
|
ptr = NULL; \
|
|
} while (0)
|
|
|
|
extern void CommStartProxyer(ThreadId *thread_id, ThreadPoolCommunicator *comm);
|
|
extern void CommStartProxyStatThread(CommController *controller);
|
|
extern void SetupCommProxySignalHook();
|
|
|
|
extern void init_commsock_recv_delay(CommSockDelay *delay);
|
|
extern void reset_commsock_recv_delay(CommSockDelay *delay);
|
|
extern void perform_commsock_recv_delay(CommSockDelay *delay);
|
|
extern CommWaitNextStatus comm_proxy_process_wait(struct timeval st, int timeout, bool ctx_switch, sem_t* s_queue_sem = NULL);
|
|
extern bool CommLibNetIsLibosFd(phy_proto_type_t proto_type, int fd);
|
|
extern int CommLibNetSetFdType(int fd, CommFdTypeOpt type);
|
|
extern IPAddrType CommLibNetGetIPType(unsigned int ip);
|
|
extern bool CommLibNetIsNoProxyLibosFd(int fd);
|
|
extern bool CommConfigSocketOption(CommConnSocketRole role, struct sockaddr *addr);
|
|
extern bool CommConfigSocketOption(CommConnSocketRole role, const char *ip, int port);
|
|
|
|
|
|
/*------------------------ Comm Proxy inteface definition -----------------------------*/
|
|
extern int comm_proxy_socket(int domain, int type, int protocol);
|
|
extern int comm_proxy_close(int fd);
|
|
extern int comm_proxy_shutdown(int fd, int how);
|
|
extern int comm_proxy_accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen);
|
|
extern int comm_proxy_accept4(int sockfd, struct sockaddr* addr, socklen_t* addrlen, int flags);
|
|
extern int comm_proxy_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
|
|
extern int comm_proxy_bind(int sockfd, const struct sockaddr* ServerAddr, socklen_t addrlen);
|
|
extern int comm_proxy_listen(int sockfd, int backlog);
|
|
extern int comm_proxy_setsockopt(int sockfd, int level, int optname, const void* optval, socklen_t optlen);
|
|
extern int comm_proxy_getsockopt(int sockfd, int level, int optname, void* optval, socklen_t* optlen);
|
|
extern int comm_proxy_getsockname(int sockfd, struct sockaddr* addr, socklen_t* addrlen);
|
|
extern int comm_proxy_getpeername(int sockfd, struct sockaddr* addr, socklen_t* addrlen);
|
|
extern int comm_proxy_fcntl(int sockfd, int cmd, ...);
|
|
extern int comm_proxy_poll(struct pollfd* fdarray, unsigned long nfds, int timeout);
|
|
extern int comm_proxy_epoll_create(int size);
|
|
extern int comm_proxy_epoll_create1(int flag);
|
|
extern int comm_proxy_epoll_ctl(int epfd, int op, int fd, struct epoll_event* event);
|
|
extern int comm_proxy_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout);
|
|
extern int comm_proxy_epoll_pwait(int epfd, struct epoll_event* events, int maxevents, int timeout, const sigset_t *sigmask);
|
|
extern ssize_t comm_proxy_send(int socketfd, const void* buffer, size_t length, int flags);
|
|
extern ssize_t comm_proxy_recv(int socketfd, void* buffer, size_t length, int flags);
|
|
extern void comm_change_event(CommSockDesc* comm_sock, EventType event_type, struct epoll_event* ev);
|
|
extern ssize_t comm_proxy_addr_recv(int sockfd, void *buf, size_t len, int flags);
|
|
extern pid_t comm_proxy_fork(void);
|
|
extern ssize_t comm_proxy_read(int s, void* mem, size_t len);
|
|
extern ssize_t comm_proxy_write(int s, const void* mem, size_t size);
|
|
extern int comm_proxy_sigaction(int signum, const struct sigaction* act, struct sigaction* oldact);
|
|
|
|
typedef struct SockDescCreateAttr {
|
|
CommSockType type;
|
|
ThreadPoolCommunicator* comm;
|
|
CommSockDesc* parent;
|
|
union {
|
|
struct {
|
|
int comm_num;
|
|
} server;
|
|
struct {
|
|
int size;
|
|
int group_id;
|
|
} epoll;
|
|
int other;
|
|
} extra_data;
|
|
} SockDescCreateAttr;
|
|
extern CommSockDesc* CommCreateSockDesc(int fd, SockDescCreateAttr* attr);
|
|
extern void CommReleaseSockDesc(CommSockDesc **comm_sock);
|
|
|
|
/***********************************************************************************
|
|
* CommMonitor related data structures
|
|
***********************************************************************************
|
|
*/
|
|
extern void ProcessCommMonitorMessage(int fd);
|
|
|
|
typedef enum ParseMonitorType {
|
|
ParseMonitorTypeCheck = 0,
|
|
ParseMonitorTypeSet
|
|
} ParseMonitorType;
|
|
|
|
typedef struct ParseMonitorCmd {
|
|
int (*func)(char *recv_buffer, char *send_buffer, ParseMonitorType type); /* parse function */
|
|
const char* name; /* mode name to use from command line as an argument */
|
|
const char* shorts; /* short name */
|
|
const char* note; /* mode description */
|
|
} ParseMonitorCmd;
|
|
|
|
extern ParseMonitorCmd g_parse_monitor_cmd[];
|
|
|
|
#define COMM_API_____________________
|
|
extern bool LibnetAddConnectWaitEntry(int epfd, int sock, int forRead, int forWrite, int opt);
|
|
|
|
#define MAX_SOCKET_FD_NUM (5)
|
|
#define MAX_PKT_TRANS_CNT (5000 * 1000) /* 29k */
|
|
extern unsigned long int g_static_pkt_cnt_by_length[TotalChannel][MAX_PKT_TRANS_CNT];
|
|
extern int g_static_pkt_cnt_idx[TotalChannel];
|
|
extern void comm_update_packet_static(size_t len, int type);
|
|
|
|
#define WalSenderEnter 0
|
|
#define WalSenderWakeup 1
|
|
#define WalSenderCnt 2
|
|
extern unsigned long int g_static_walsender_wakeup[WalSenderCnt][MAX_PKT_TRANS_CNT];
|
|
extern int g_static_walsender_cnt_idx[WalSenderCnt];
|
|
|
|
|
|
extern void comm_update_walsender_static(int type, int len);
|
|
|
|
#define WalRcvWriterWrite 0
|
|
#define WalRcvWriterExpectWrite 1
|
|
#define WalRcvWriterFlush 2
|
|
#define WalRcvWriterStat 3
|
|
#define WalRcvWriterStatMax (5000 * 1000) /* per 3min tpcc has 290k io */
|
|
extern unsigned long int g_static_walrcvwriter_iostat[WalRcvWriterStat][WalRcvWriterStatMax];
|
|
extern int g_static_walrcvwriter_idx[WalRcvWriterStat];
|
|
|
|
extern void comm_update_walrcvwriter_static(int type, int len);
|
|
|
|
extern bool CommGetIpPortFromSockAddr(struct sockaddr *addr, char *ip, int *port);
|
|
|
|
extern unsigned long int g_fd_pkt_length_by_loop[MAX_SOCKET_FD_NUM][TotalChannel][MAX_PKT_TRANS_CNT];
|
|
extern int g_fd_pkt_length_idx[MAX_SOCKET_FD_NUM][TotalChannel];
|
|
extern void comm_reset_packet_length_static();
|
|
extern void comm_update_packet_length_static(int fd, size_t len, int type);
|
|
|
|
extern void comm_print_packet_static();
|
|
extern void comm_print_walsender_static();
|
|
extern void comm_print_walrcvwriter_static();
|
|
extern void comm_print_packet_lenght_static();
|
|
|
|
extern int comm_add_static_fd(int fd);
|
|
|
|
#endif /* COMMPROXY_INTERFACE_H */
|