Files
openGauss-server/src/include/communication/commproxy_interface.h
2023-01-18 15:00:27 +08:00

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
#if (!defined WITH_OPENEULER_OS) && (!defined OPENEULER_MAJOR)
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 */